OpenGL着色器实现纹理合并显示
本文介绍了opengl下实现纹理的装载,同时借助顶点着色器和片源着色器实现两个不同外部纹理的合并显示。
目录
- 1 opengl下纹理的装载
- 2 纹理合并效果显示
- 3 完整的代码
- 1 opengl下纹理的装载
// 初始化GLFW
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
// 创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "Multiple Textures Example", NULL, NULL);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化GLEW
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
// 编译顶点着色器
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);
glUseProgram(shaderProgram);
// 加载纹理1
GLuint textureID1 = SOIL_load_OGL_texture("1.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID1);
glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);
// 加载纹理2
GLuint textureID2 = SOIL_load_OGL_texture("2.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID2);
glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
借助glfw实现窗口的创建,借助SOIL库实现纹理的装载,返回加载后的纹理id。
- 2 纹理合并效果显示
// 设置顶点数据和纹理坐标
float vertices[] = {
// 位置 // 纹理坐标
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
- 1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
// 创建顶点缓冲对象和顶点数组对象
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 绑定纹理并绘制
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID2);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteTextures(1, &textureID1);
glDeleteTextures(1, &textureID2);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glfwTerminate();
绘制两个三角形,并绑定两个纹理。添加顶点着色器和片元着色器,其代码如下:
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
out vec2 fragTexCoord;
void main() {
fragTexCoord = texCoord;
gl_Position = vec4(position, 1.0);
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
in vec2 fragTexCoord;
out vec4 fragColor;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main() {
vec4 color1 = texture(texture1, fragTexCoord);
vec4 color2 = texture(texture2, fragTexCoord);
// 将两个纹理的颜色进行混合
fragColor = mix(color1, color2, 0.5);
}
)";
- 3 完整的代码
完整的代码如下所示,需依赖glfw实现窗口显示,依赖SOIL实现纹理装载。需将两个纹理路径换为本地路径,给出的示例代码路径为1.jpg和2.jpg。
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>
#include <iostream>
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
out vec2 fragTexCoord;
void main() {
fragTexCoord = texCoord;
gl_Position = vec4(position, 1.0);
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
in vec2 fragTexCoord;
out vec4 fragColor;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main() {
vec4 color1 = texture(texture1, fragTexCoord);
vec4 color2 = texture(texture2, fragTexCoord);
// 将两个纹理的颜色进行混合
fragColor = mix(color1, color2, 0.5);
}
)";
int main() {
// 初始化GLFW
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
// 创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "Multiple Textures Example", NULL, NULL);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// 初始化GLEW
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
// 编译顶点着色器
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);
glUseProgram(shaderProgram);
// 加载纹理1
GLuint textureID1 = SOIL_load_OGL_texture("1.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID1);
glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);
// 加载纹理2
GLuint textureID2 = SOIL_load_OGL_texture("2.jpg", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID2);
glUniform1i(glGetUniformLocation(shaderProgram, "texture2"), 1);
// 设置顶点数据和纹理坐标
float vertices[] = {
// 位置 // 纹理坐标
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
- 1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
// 创建顶点缓冲对象和顶点数组对象
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 渲染循环
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
// 绑定纹理并绘制
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID2);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteTextures(1, &textureID1);
glDeleteTextures(1, &textureID2);
glDeleteProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glfwTerminate();
return 0;
}