文章目录
环境
- 系统:ubuntu20.04
- opengl版本:4.6
- glfw版本:3.3
- glad版本:4.6
- cmake版本:3.16.3
- gcc版本:10.3.0
在<opengl学习日记9-opengl使用纹理示例>的基础上,拓展使用多个纹理。
代码
CMakeLists.txt文件内容不变。
fragmentShaderSource.fs
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
FragColor = mix(texture(texture1,TexCoord),texture(texture2,TexCoord),0.2) ;
}
vertexShaderSource.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
main.cpp
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "stbimage.h"
//#include <glm/glm.hpp>
//#include <glm/gtc/matrix_transform.hpp>
//#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <fstream>
#include <iosfwd>
#include <sstream>
#include <string>
//定义窗口大小
int SCR_WIDTH = 800;
int SCR_HEIGHT = 600;
std::string readFile(const std::string filename)
{
std::string data;
data = readFile(filename.c_str());
return data;
}
std::string readFile(const char* filename)
{
std::string data;
std::ifstream infile;
infile.open(filename);
std::stringstream neirong;
neirong << infile.rdbuf();
infile.close();
data = neirong.str();
return data;
}
int main()
{
std::cout << "Hello World!" << std::endl;
std::cout << "初始化" << std::endl;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "transformtions", NULL, NULL);
if (window == NULL) {
std::cout << "创建窗口失败" << std::endl;
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "初始化glad失败" << std::endl;
return -1;
}
std::cout << "顶点定义,VAO,VBO,EBO" << std::endl;
float vertices[] = {0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 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, 1.0f};
//索引缓冲区
unsigned int indices[] = {0, 1, 3,
1, 2, 3};
unsigned int VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//定位点关系
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *) (6 * sizeof(float)));
glEnableVertexAttribArray(2);
std::cout << "着色器定义" << std::endl;
std::cout << "着色器定义:顶点着色器" << std::endl;
std::string vertexShaderSource = readFile("vertexShaderSource.vs");
const char *vertexShaderSourceCtr = vertexShaderSource.c_str();
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSourceCtr, NULL);
glCompileShader(vertexShader);
int success;
char infolog[512] = {0};
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertexShader, 512, NULL, infolog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infolog << std::endl;
}
std::cout << "着色器定义:片段着色器" << std::endl;
std::string fragmentShaderSource = readFile("fragmentShaderSource.fs");
const char *fragmentShaderSourceCtr = fragmentShaderSource.c_str();
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSourceCtr, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragmentShader, 512, NULL, infolog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infolog << std::endl;
}
std::cout << "着色器定义:启用着色器程序" << std::endl;
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infolog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infolog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
std::cout << "纹理定义" << std::endl;
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_set_flip_vertically_on_load(true);
std::cout << "读取纹理图片" << std::endl;
int width, height, nrChannels;
unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (texturesData) {
//绑定和纹理图片数据结合
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
texturesData);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "读取图片数据错误" << std::endl;
}
stbi_image_free(texturesData);
std::cout << "纹理定义2" << std::endl;
unsigned int texture2;
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
std::cout << "读取纹理图片" << std::endl;
// int width, height, nrChannels;
texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (texturesData) {
//绑定和纹理图片数据结合
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
texturesData);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "读取图片数据错误" << std::endl;
}
stbi_image_free(texturesData);
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture1"),0);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture2"),1);
std::cout << "绘制" << std::endl;
while (!glfwWindowShouldClose(window)) {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (const GLvoid *) 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
std::cout << "内存释放" << std::endl;
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
总结
-
使用多个纹理,则需要定义多个纹理,读取多个图片数据
std::cout << "纹理定义" << std::endl;
unsigned int texture1;
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_set_flip_vertically_on_load(true); std::cout << "读取纹理图片" << std::endl; int width, height, nrChannels; unsigned char* texturesData = stbi_load("container.jpg", &width, &height, &nrChannels, 0); if (texturesData) { //绑定和纹理图片数据结合 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texturesData); glGenerateMipmap(GL_TEXTURE_2D); } else { std::cout << "读取图片数据错误" << std::endl; } stbi_image_free(texturesData); std::cout << "纹理定义2" << std::endl; unsigned int texture2; glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); std::cout << "读取纹理图片" << std::endl; // int width, height, nrChannels; texturesData = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0); if (texturesData) { //绑定和纹理图片数据结合 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturesData); glGenerateMipmap(GL_TEXTURE_2D); } else { std::cout << "读取图片数据错误" << std::endl; } stbi_image_free(texturesData);
-
一张图片纹理叠加在另一张图片纹理上,需要有透明通道,图片格式是png,所以在绑定png纹理图片是需要注意参数变化
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
texturesData);
注意第三个参数和第七个参数,由GL_RGB
变为GL_RGBA
-
在绘制之前需要手动设置一次纹理对应的采样器
glUseProgram(shaderProgram);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture1"),0);
glUniform1i(glGetUniformLocation((GLuint)shaderProgram,"texture2"),1);
这里需要注意,glUniform1i
函数的书写是数字1
,不是字母l
-
在读取纹理之前,设置一下,可保持加载图像不上下颠倒
stbi_set_flip_vertically_on_load(true);