利用GLSL操作shader着色器实现平移、纹理与顶点颜色的叠加处理:
利用GLSL操作shader着色器实现平移、旋转等操作:
GLfloat vertices2[] = {
// 坐标 // 颜色 // 纹理
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // 右上 黄
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // 右下 品
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, // 左下 青
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f // 左上 黑
};
GLuint indices[] = {
0, 1, 3, // 起始顶点:右上 -> 右下 -> 左上
1, 2, 3 // 第二顶点:右下 -> 左下 -> 左上
};
GLuint texture;
glGenTextures(1, &texture); // 纹理ID
glBindTexture(GL_TEXTURE_2D, texture); // 将纹理ID绑定到目标'GL_TEXTURE_2D'
// 纹理属性
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
// 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 环绕方式x方向 重复
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // y 方向重复
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // 纹理缩小时的过滤方式 线性
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 纹理放大时的过滤方式 线性 or GL_NEAREST 相邻
// 载入纹理
IMG imageA; // 定义 IMG 对象
loadImg(&imageA, "src/textures/ash_uvgrid01.jpg"); // 将纹理数据加载到 IMG 对象指针
if (imageA.data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageA.width, imageA.height, 0, GL_RGB, GL_UNSIGNED_BYTE, imageA.data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
std::cout << "Texture加载失败!" << std::endl;
}
// 释放纹理图像数据(已加载到GL_TEXTURE_2D目标了)
stbi_image_free(imageA.data);
主循环中渲染部分:
// 变换
glm::mat4 transform = glm::mat4(1.0f);
transform = move(transform, moveX, moveY);
transform = scale(transform, scaleX, scaleY);
ourShader.setMat4("transform", transform);
// 设置颜色与纹理贴图的叠加系数
ourShader.setFloat("coefficient", coefficient);
// 渲染容器
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
对应在主循环结束后的释放:
glDeleteBuffers(1, &texture);
片段着色器程序代码:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform float coefficient; // 叠加系数
uniform sampler2D ourTexture;
void main()
{
// FragColor = vec4(ourColor, 1.0f);
// 纹理vec2 * 颜色vec4 * 系数float (纹理与顶点颜色混合) not texture mix texture
FragColor = texture(ourTexture, TexCoord) * vec4(ourColor, 1.0f) * coefficient;
// 如果我们要将两个纹理混合可以:
// FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
// 20% - 80% (0.2 to 0.8)
}
顶点着色器代码:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord; // 顶点缓冲对象中描述纹理的顶点数据的position
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 transform;
void main()
{
gl_Position = transform * vec4(aPos, 1.0f);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
在主循环中,对coefficient
的设置,就是让片段着色器使用这个全局变量,而我们对鼠标滚轮事件回调后,通过滚动滚轮就可以实现着色器对纹理贴图和顶点颜色的属性进行叠加控制。
主循环中的设置:
// 设置颜色与纹理贴图的叠加系数
ourShader.setFloat("coefficient", coefficient);
鼠标滚轮事件回调函数处理滚轮滚动:
// 滚轮回调
void scrollCall(GLFWwindow* window, GLdouble xoffset, GLdouble yoffset)
{
GLfloat inc = 0.1f;
if (yoffset == 1)
{
coefficient += inc;
if (coefficient > 10.0f)
{
coefficient = 10.0f;
}
}
if (yoffset == -1)
{
coefficient -= inc;
if (coefficient < 0.0f)
{
coefficient = 0.0f;
}
}
}
声明/定义:
glm::mat4 rotate(glm::mat4 &t, GLfloat a, GLfloat x, GLfloat y, GLfloat z);
x, y, z 为定义旋转的轴
// 旋转
glm::mat4 rotate(glm::mat4 &t, GLfloat a, GLfloat x, GLfloat y, GLfloat z)
{
return glm::rotate(t, a, glm::vec3(x, y, z));
}
主循环中的旋转矩阵操作,以及shader操作:
// 变换
glm::mat4 transform = glm::mat4(1.0f);
transform = move(transform, moveX, moveY);
// transform = scale(transform, scaleX, scaleY);
transform = rotate(transform, (GLfloat)glfwGetTime(), 0.0f, 0.0f, 0.1f);
ourShader.setMat4("transform", transform);
// 设置颜色与纹理贴图的叠加系数
ourShader.setFloat("coefficient", coefficient);