纹理,又叫贴图。它的概念的我就不再这里赘述了!你可以直接去OpenGl教程官网去看,对了!
分享一个中文教程:https://learnopengl-cn.github.io/01%20Getting%20started/06%20Textures/
纹理的使用首先需要导入一个库文件,链接如下:https://github.com/nothings/stb/blob/master/stb_image.h,
这个stb_image.h就是我们后面加载图像需要用到的库。
下面则是两张需要用到的贴图:
https://learnopengl-cn.github.io/img/01/06/container.jpg
https://learnopengl-cn.github.io/img/01/06/awesomeface.png
下面就是上代码时间,还是接着上面的代码:
先是fragmentSource.txt:
#version 330 core
out vec4 FragColor;
in vec2 TextureCoord;
uniform sampler2D ourTexture;//这就是我们的贴图ID,根据我代码中写的这是0号
uniform sampler2D ourFace;//这是2号
void main()
{
FragColor = mix(texture(ourTexture,TextureCoord),texture(ourFace,TextureCoord),0.5f);//
}
后是vertexSource.txt:
#version 330 core
out vec2 TextureCoord;
layout(location = 3) in vec3 aPos;
layout(location = 4) in vec3 aColor;
layout(location = 5) in vec2 aTextureCoord;
void main(){
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
TextureCoord=aTextureCoord;
}
然后是main.cpp
先是修改在vao中的位置
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);//从vao里面在0号索引位上拿取三个值
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 8* sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//从vao里面在0号索引位上拿取三个值
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));//从vao里面在0号索引位上拿取三个值
glEnableVertexAttribArray(3);//启用属性0,因为默认是禁用的
glEnableVertexAttribArray(4);//启用属性0,因为默认是禁用的
glEnableVertexAttribArray(5);//启用属性0,因为默认是禁用的
然后是拿两块texture缓冲区。
unsigned int texbufferA;//贴图缓冲区ID
glGenTextures(1, &texbufferA);//创建
glActiveTexture(GL_TEXTURE0);//申请textbuffer中的缓冲区号,这里申请的是零号
glBindTexture(GL_TEXTURE_2D, texbufferA);//绑定
int width, height, nrChannels;
unsigned char* data = stbi_load("container.jpg",&width,&height,&nrChannels,0);//载入图像,宽度、高度和颜色通道的个数
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);//生成贴图
glGenerateMipmap(GL_TEXTURE_2D);//生成多级纹理
}
else
{
printf("stbi load fail!");
}
stbi_image_free(data);//释放空间
unsigned int texbufferB;//贴图缓冲区ID
glGenTextures(1, &texbufferB);
glActiveTexture(GL_TEXTURE2);//申请textbuffer中的缓冲区号,这里申请的是2号
glBindTexture(GL_TEXTURE_2D, texbufferB);//绑定
stbi_set_flip_vertically_on_load(true);//翻转图像,默认是颠倒的
unsigned char* data2 = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);//载入图像,宽度、高度和颜色通道的个数
if (data2)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);//生成贴图
glGenerateMipmap(GL_TEXTURE_2D);//生成多级纹理
}
else
{
printf("stbi load fail!");
}
stbi_image_free(data2);//释放空间
while (!glfwWindowShouldClose(window))
{ // 检查事件,调用相应的回调函数,如下文的glfwInput函数
glfwInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//渲染颜色到后台缓冲
glClear(GL_COLOR_BUFFER_BIT);//清除前台缓冲
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texbufferA);//绑定
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texbufferB);//绑定
glBindVertexArray(VAO);//每次循环都调用,绑定函数绑定VAO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
myShader->Use();
glUniform1i(glGetUniformLocation(myShader->ID, "ourTexture"),0);
glUniform1i(glGetUniformLocation(myShader->ID, "ourFace"),2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//绘制三角形,根据索引数组绘制6个顶点,索引数组类型为GL_UNSIGNED_INT,偏移值为0
//glDrawArrays(GL_TRIANGLES, 0, 3);//开始绘制三角形从0起始,画三组数值
//glBindVertexArray(0);//解绑
// Swap the screen buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
最终的输出如下:
需要注意的是:
texbufferB一定写在texbufferA生成贴图完成之后,否则texbufferA会是一片纯黑色。
也就是这两句话后面。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);//生成贴图
glGenerateMipmap(GL_TEXTURE_2D);//生成多级纹理