下面是一个简单的OpenGL开发案例,我们将创建一个程序来渲染一个带有纹理的矩形。我们将编写顶点着色器、片段着色器,并加载一个纹理。
着色器代码
顶点着色器 (vertex_shader.glsl)
glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
TexCoord = aTexCoord;
}
片段着色器 (fragment_shader.glsl)
glsl
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
加载纹理
我们将使用SOIL库来加载纹理,这个库提供了简单的接口来加载图像文件。
cpp
#include <SOIL.h>
GLuint loadTexture(const char *path) {
GLuint textureID;
glGenTextures(1, &textureID);
int width, height;
unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
if (image == nullptr) {
std::cout << "Texture failed to load at path: " << path << std::endl;
return 0;
}
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
return textureID;
}
主程序
我们将把上面的代码片段组合在一起,并在主程序中调用它们。
cpp
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include
#include <SOIL.h>
// 省略了之前的初始化代码…
// 顶点数据和索引数据
GLfloat vertices[] = {
// 位置 // 纹理坐标
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下角
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下角
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // 右上角
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // 左上角
};
GLuint indices[] = {
0, 1, 2, // 第一个三角形
2, 3, 0 // 第二个三角形
};
// 省略了之前的缓冲区配置代码…
// 创建和编译着色器程序
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// 删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 加载纹理
GLuint texture1 = loadTexture(“path_to_texture.jpg”);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
// 输入处理
// …
// 渲染指令
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 绑定纹理
glBindTexture(GL_TEXTURE_2D, texture1);
// 绘制矩形
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// 交换缓冲区和轮询IO事件
glfwSwapBuffers(window);
glfwPollEvents();
}
// 退出清理
// …
在上面的代码中,我们省略了初始化GLFW、GLEW、创建窗口、设置视口、配置OpenGL状态等步骤,因为这些步骤已经在之前的例子中展示过了。确保