本文绘制一个带纹理的四边形。
#include<iostream>
#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include"stb_image.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
const char* vertexShaderSource =
"#version 330 core \n"
"layout(location = 0) in vec3 position; \n"
"layout(location = 1) in vec3 aColor; \n"
"layout(location = 2) in vec2 aTexCoord; \n"
"out vec3 ourColor; \n"
"out vec2 TexCoord; \n"
"uniform mat4 u_projectionMatrix; \n"
"uniform mat4 u_modelViewMatrix; \n"
"void main() { \n"
" gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(position.x, position.y, position.z, 1.0);\n"
" ourColor = aColor; \n"
" TexCoord = aTexCoord; \n"
"} \n ";
const char* fragmentShaderSource =
"#version 330 core \n"
"out vec4 color; \n"
"in vec3 ourColor; \n"
"in vec2 TexCoord; \n"
"uniform sampler2D ourTexture; \n"
"uniform sampler2D ourTexture1; \n"
"void main(){ \n"
" color = mix(texture(ourTexture, TexCoord),texture(ourTexture1, TexCoord),0.2); } \n";
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
bool firstMouse = true;
float yaw = -90.0f; // yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right so we initially rotate a bit to the left.
float pitch = 0.0f;
float lastX = 800.0f / 2.0;
float lastY = 600.0 / 2.0;
float fov = 45.0f;
// camera
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
//key表示按下的键,action表示键按下/释放,mode表示是否有Ctrl、Shift、Alt等按钮操作
void key_callback(GLFWwindow * window, int key, int scancode, int action, int mode)
{
//用户按下ESC键,设置窗口WindowShouldClose属性为true,关闭应用程序
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); //主版本号
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); //次版本号
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//核心模式
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Game", NULL, NULL); //创建窗口
if (window == NULL)
{
std::cout << "Open window failed!" << std::endl;
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
//将窗口的上下文设置为当前线程的主上下文
glfwMakeContextCurrent(window);
//GLEW是用来管理OpenGL的函数指针,调用任何OpenGL的函数之前都需要初始化GLEW
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cout << "Init Glew failed!" << std::endl;
glfwTerminate();
return -1;
}
int width, height;
//从GLFW中获取视口大小
glfwGetFramebufferSize(window, &width, &height);
//窗口左下角的位置、宽度、高度
glViewport(0, 0, width, height);
// glEnable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// glPolygonMode(GL_BACK, GL_LINE);
//注册按键回调函数
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
//顶点数组对象
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//顶点缓冲对象
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//将顶点数据复制到缓冲中
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//索引缓冲对象
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 加载并生成纹理
int widtht, heightt, nrChannels;
unsigned char *data = stbi_load("container.jpg", &widtht, &heightt, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, widtht, heightt, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 加载并生成纹理
// int widtht, heightt, nrChannels;
//unsigned char *
data = stbi_load("awesomeface.png", &widtht, &heightt, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, widtht, heightt, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);
//创建顶点着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//创建片段着色器
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//创建着色器程序
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//顶点属性配置,告诉OpenGL该如何解析顶点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation(shaderProgram, "ourTexture"), 0); // 手动设置
glUniform1i(glGetUniformLocation(shaderProgram, "ourTexture1"), 1);
//检查GLFW是否要求退出
while (!glfwWindowShouldClose(window))
{
//检查是否触发事件(鼠标移动、键盘输入等),如果有则调用相应的回调函数
glfwPollEvents();
//渲染操作放入循环中
//清屏
glClearColor(0.2f, 0.3f, 0.3f, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1);
// glBindTexture(GL_TEXTURE_2D, texture);
//启用着色器程序
glUseProgram(shaderProgram);
// pass projection matrix to shader (note that in this case it could change every frame)
glm::mat4 projection = glm::perspective(glm::radians(fov), (float)800 / (float)600, 0.1f, 100.0f);
//ourShader.setMat4("projection", projection);
int location = glGetUniformLocation(shaderProgram, "u_projectionMatrix");
glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)glm::value_ptr(projection));
// camera/view transformation
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
// ourShader.setMat4("view", view);
location = glGetUniformLocation(shaderProgram, "u_modelViewMatrix");
glUniformMatrix4fv(location, 1, GL_FALSE, (GLfloat*)glm::value_ptr(view));
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
//绘制
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glDrawArrays(GL_TRIANGLES, 0, 3);
//交换颜色缓冲
glfwSwapBuffers(window);
}
//结束时释放资源
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
// glfw: whenever the mouse moves, this callback is called
// -------------------------------------------------------
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (firstMouse)
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
lastX = xpos;
lastY = ypos;
float sensitivity = 0.1f; // change this value to your liking
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
// make sure that when pitch is out of bounds, screen doesn't get flipped
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
}
// glfw: whenever the mouse scroll wheel scrolls, this callback is called
// ----------------------------------------------------------------------
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
if (fov <= 1.0f)
fov = 1.0f;
if (fov >= 45.0f)
fov = 45.0f;
}
执行结果:

本文介绍了一个使用OpenGL和GLFW库在窗口中绘制带有纹理的四边形的方法。通过定义顶点着色器和片段着色器,加载纹理,并在着色器中混合两种纹理效果,最终实现了四边形的纹理渲染。
1384

被折叠的 条评论
为什么被折叠?



