OpenGL学习笔记7——贴图练习
做一下 LearnOpenGL后面的练习
1 让笑脸改方向
题目:修改片段着色器,仅让笑脸图案朝另一个方向看,参考解答
就是只让笑脸的UV的横坐标反转。
#version 330 core
uniform sampler2D texture1;
uniform sampler2D texture2;
in vec3 Color;
in vec2 TexCoord;
out vec4 FragColor;
void main(){
vec2 reverseXTexCoord = TexCoord;
reverseXTexCoord.x *= -1;
FragColor = mix(texture(texture1,TexCoord),texture(texture2,reverseXTexCoord), 0.2);
}
这个还是挺简单的。
2 在箱子的角落放置4个笑脸
题目:尝试用不同的纹理环绕方式,设定一个从0.0f到2.0f范围内的(而不是原来的0.0f到1.0f)纹理坐标。试试看能不能在箱子的角落放置4个笑脸:参考解答,结果。记得一定要试试其它的环绕方式。
这个也挺简单的。首先环绕方式显然是采用重复的方式,可以想下面这样设置。不过它默认的环绕方式就是重复,其实也可以不用设置。
// 水平和垂直两个方向可以采用不同的环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // 设置水平方向的环绕方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 设置垂直方向的环绕方式
看了文档发现,除了GL_TEXTURE_WRAP_S和GL_TEXTURE_WRAP_T之外,还有一个GL_TEXTURE_WRAP_R。应该是第三个方向,也许是三维纹理的范畴,这里我就不太清楚了。
然后就是把uv改成0.0到2.0,但是如果直接改了顶点的数据,箱子的uv也会改。所以我打算还是到Shader里面单独改箱子贴图的uv。
#version 330 core
uniform sampler2D texture1;
uniform sampler2D texture2;
in vec3 Color;
in vec2 TexCoord;
out vec4 FragColor;
void main(){
vec2 reverseXTexCoord = TexCoord;
reverseXTexCoord *= 2;
FragColor = mix(texture(texture1,TexCoord),texture(texture2,reverseXTexCoord), 0.2);
}
然后再看下题目给的结果,发现我和题目想的不一样,不过算了,也差不多。
3 尝试使用GL_NEAREST
题目:尝试在矩形上只显示纹理图像的中间一部分,修改纹理坐标,达到能看见单个的像素的效果。尝试使用GL_NEAREST的纹理过滤方式让像素显示得更清晰:参考解答
更简单啦,先把uv改得很小(0.1),实现放大的效果。
// 三角形的顶点数据
float vertices[] = {
// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.1f, 0.1f, // 右上
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.1f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.1f // 左上
};
然后设置环绕模式为邻近的。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // 其实现在是放大,设置这一个就行了
GL_NEAREST:
GL_LINEAR:
4 动态改变混合度
使用一个uniform变量作为mix函数的第三个参数来改变两个纹理可见度,使用上和下键来改变箱子或笑脸的可见度:参考解答。
需要用上些交互了。也不难,首先修改fragmentShader。添加unifrom。
#version 330 core
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform float mixValue;
uniform float uvScale; // 顺便加一个uv缩放
in vec3 Color;
in vec2 TexCoord;
out vec4 FragColor;
void main(){
FragColor = mix(texture(texture1,TexCoord),texture(texture2,TexCoord * uvScale), mixValue);
}
在main.cpp中添加两个全局变量。
float mixValue = 0;
float uvScale = 1;
在渲染循环中
myShader.setFloat("mixValue", mixValue);
myShader.setFloat("uvScale", uvScale);
然后处理输入实现用键盘改变mixValue和uvScale的值。顺带限制一下mixValue在0-1中间。
// 处理输入
void processInput(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)// 判断是否按下Esc
glfwSetWindowShouldClose(window, true);// 将窗口设置为需要关闭
if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) {
mixValue += 0.002;
if (mixValue > 1)
mixValue = 1;
}
if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) {
mixValue -= 0.002;
if (mixValue < 0)
mixValue = 0;
}
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
uvScale -= 0.01;
}
if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) {
uvScale += 0.01;
}
}
然后就好了。