Modern OpenGL---09 纹理(纹理单元可贴多个纹理)

对之前画的矩形基础上贴上纹理。在片段着色器中,声明一个采样器,表示纹理位置,每个纹理位置叫做纹理单元,比如 0、1等,当只有一个纹理事时,纹理单元默认为0,当有一个以上的纹理时,则需要通过uniform从外部设置每个纹理单元的值。

需要注意的是,在一个以上的纹理绑定过程中,需要激活纹理单元的位置,然后进行绑定当前纹理。比如需要绑定第2个纹理时,需要先通过 glActiveTexture(GL_TEXTURE1),来激活位置为 1 的纹理单元,然后再通过 glBindTexture()来绑定纹理对象。(第1个纹理单元可以不用激活,因为会默认第一个激活,其纹理单元为 GL_TEXTURE0)。

代码:

#define STB_IMAGE_IMPLEMENTATION
#include 
#include 
#include "std_image.h"
#include 
#include 

int main()
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	GLFWwindow* window = glfwCreateWindow(1120, 1120, "Rectangle", nullptr, nullptr);
	glfwMakeContextCurrent(window);
	std::cout << glGetString(GL_VERSION) << std::endl;
	glewInit();

	std::vector<float> vertices = {
		-0.8f, -0.8f, 1.0f, 0.0f, 0.0f,	 0.0f,  1.0f, // 0  位置2个,颜色3个,纹理坐标2个
		 0.8f, -0.8f, 0.0f, 1.0f, 0.0f,	 1.0f,  1.0f, // 1
		 0.8f,  0.8f, 0.0f, 0.0f, 1.0f,	 1.0f,  0.0f, // 2
		-0.8f,  0.8f, 1.0f, 1.0f, 0.0f,	 0.0f,  0.0f, // 3
	};

	unsigned int vbo;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), &vertices[0], GL_STATIC_DRAW);

	int width, height, nrChannels;
	unsigned char* texture = stbi_load("./data/wall.jpg", &width, &height, &nrChannels, 0);
	unsigned int tbo;
	glGenTextures(1, &tbo);
	glActiveTexture(GL_TEXTURE0); 
	glBindTexture(GL_TEXTURE_2D, tbo);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
	glGenerateMipmap(GL_TEXTURE_2D);  //经常会忘了这个函数,其功能是产生多级渐进纹理
	stbi_image_free(texture);

	unsigned char* texture1 = stbi_load("./data/container.jpg", &width, &height, &nrChannels, 0);
	unsigned int tbo1;
	glGenTextures(1, &tbo1);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, tbo1);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture1);
	glGenerateMipmap(GL_TEXTURE_2D);
	stbi_image_free(texture1);

	unsigned int vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0);
	
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, (void*)(2 * sizeof(float)));
	
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 7, (void*)(5 * sizeof(float)));

	std::vector<int> indices = {
		0, 1, 2,
		2, 3, 0
	}; 
	unsigned int ibo;
	glGenBuffers(1, &ibo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

	const char* vertexShaderSource = "#version 330 core\n"      
		"layout(location = 0) in vec4 pos;\n"
		"layout(location = 1) in vec4 color;\n"
		"layout(location = 2) in vec2 text_pos;\n"
		"out vec4 our_color;\n"
		"out vec2 our_text_pos;\n"
		"void main()\n"
		"{\n"
		"	gl_Position = pos;\n"
		"	our_color = color;\n"
		"	our_text_pos = text_pos;\n"
		"}\0";
	unsigned int vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, &vertexShaderSource, nullptr);
	glCompileShader(vs);

	const char* fragmentShaderSource = "#version 330 core\n"
		"out vec4 color;\n"
		"in vec4 our_color;\n"
		"in vec2 our_text_pos;\n"
		"uniform float r;\n"
		"uniform sampler2D ourTexture;\n"
		"uniform sampler2D ourTexture1;\n"
		"void main()\n"
		"{\n"
		//"	color = texture(ourTexture, our_text_pos) * vec4(r, our_color.y, our_color.z, our_color.w);\n"
		"	color = mix(texture(ourTexture, our_text_pos), texture(ourTexture1, our_text_pos), 0.5)* vec4(r, our_color.y, our_color.z, our_color.w);\n"
		"}\0";
	unsigned int fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, &fragmentShaderSource, nullptr);
	glCompileShader(fs);
	int result;
	glGetShaderiv(fs, GL_COMPILE_STATUS, &result);
	if (!result)
	{
		char message[512];
		glGetShaderInfoLog(fs, 512, 0, message);
		std::cout << message << std::endl;
	}

	unsigned int program = glCreateProgram();
	glAttachShader(program, vs);
	glAttachShader(program, fs);
	glLinkProgram(program);
	glUseProgram(program);
	int location = glGetUniformLocation(program, "r");
	glUniform1i(glGetUniformLocation(program, "ourTexture"), 0);
	glUniform1i(glGetUniformLocation(program, "ourTexture1"), 1);

	glBindVertexArray(0);
	float increment = 0.05f, r = 0.1f;

	while (!glfwWindowShouldClose(window))
	{
		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		glBindVertexArray(vao);
		glUseProgram(program);
		glUniform1f(location, r);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);   
		glfwSwapBuffers(window);
		glfwPollEvents();

		if (r > 1) increment = -0.05f;
		else if (r < 0) increment = 0.05f;
		r += increment;
	}
	glDeleteProgram(program);
	glfwTerminate();

	return 0;
}

实验结果:
可以看到有两层纹理,一个是木箱,一个是砖墙,两个纹理分别如下:
Modern OpenGL---09 纹理(纹理单元可贴多个纹理)_第1张图片
Modern OpenGL---09 纹理(纹理单元可贴多个纹理)_第2张图片

最终渲染效果:

你可能感兴趣的:(计算机图形学,自动驾驶,c++,windows)