老子不信我学不会OpenGL系列!005-01 我就说Uniform肯定需要赋值!

上一章,我们没有给 uniform sampler2D texData 在main.cpp中赋值。这里就来解释为啥。

实际上 texData 存储的是一个地址,texture对象的地址,我们一般管这个地址叫做 texture unit。而一些会给sampler类型的变量附一个默认值:0号地址。而每个texture对象的默认 texture unit都是0 。所以我们刚刚没有对texData进行赋值。

然而并不是所有显卡都会这么做,所以上一章的东西,可能出不来结果…………。

我们实际上可以同时绑定很多个texture对象,前提是,只要他们的texture unit不同。也由此,我们可以将多个texture对象传入shader。所以在绑定之前我们可以人为的激活不同的texture unit:

glActiveTexture(GL_TEXTURE0); // activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, texture);

OpenGL保证了,至少有16个texture unit,并且他们的值是连续的(如:GL_TEXTURE8 == GL_TEXTURE3 + 5)

用下面的方法(与一般的 整型uniform 是一样的)为shader里的 sampler2D texData 进行赋值:

	glUniform1i(glGetUniformLocation(myShaderProg.ID, "texData"), 0);

然后就可以用了。

大概步骤如下:

  1. 建立两个texture对象,并赋予不同的贴图
  2. 激活不同的texture unit,并为其绑定对应的texture对象。
  3. 写shader
  4. 激活shaderpProgram,并为uniform sampler类型的变量赋值。
  5. 绘制

有下面几点要注意:

  • 在读取图片的时候,读出来是反的,可以在读取之前对其进行设置:stbi_set_flip_vertically_on_load(true);
  • shader内置了一个函数:mix(vec4 col1,vec4 col2,float k)这个函数返回:col1*(1-k)+col2*k。用这个函数可以快捷的测试两个texture在一个物体上的效果。
  • alpha通道有问题,我也不会解决,所以有alpha通道的图片,看着差不多就行了(能看出样子,有的地方可能是色块,但绝对不是乱码……)

我的代码如下:

main.cpp:

//  1.头文件:
#include <iostream>

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>

#include "Shader.h"

//  5.OpenGL与窗口(main之前):
void CBK_framebuffer_size(GLFWwindow* window, int w, int h)
{
	glViewport(0, 0, w, h);
}

void processInput(GLFWwindow* window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

int main()
{
	//  2.在创建窗口之前……:
	glfwInit();

	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//  3.创建窗口:
	GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);

	//  4.在OpenGL之前……:
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//  5.OpenGL与窗口:
	glViewport(0, 0, 800, 600);
	glfwSetFramebufferSizeCallback(window, CBK_framebuffer_size);

	//  OpenGL的配置:
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设置背景色

	//  绘图需要用的数据:
	float vertices[] = {
		// positions          // colors           // texture coords
		0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // top right
		0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // bottom right
		-0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // bottom left
		-0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // top left 
	};

	GLuint indeces[] = {
		1,2,3,
		3,0,1
	};

	int imageW, imageH, imageCH,imageW2,imageH2,imageCH2;
	stbi_set_flip_vertically_on_load(true);
	unsigned char *imageData = stbi_load("..\\my_OtherFiles\\container.jpg", &imageW, &imageH, &imageCH, 0);
	unsigned char *imageData2 = stbi_load("..\\my_OtherFiles\\a.png", &imageW2, &imageH2, &imageCH2, 0);

	//  Texture 贴图
	GLuint tex[2];
	glGenTextures(2, tex);
	glBindTexture(GL_TEXTURE_2D, tex[0]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageW, imageH, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
	glGenerateMipmap(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, tex[1]);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageW2, imageH2, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData2);
	glGenerateMipmap(GL_TEXTURE_2D);
	stbi_image_free(imageData);
	stbi_image_free(imageData2);

	//  顶点相关的配置
	GLuint VBO;
	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	GLuint EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indeces), indeces, GL_STATIC_DRAW);

	GLuint VAO;
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	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);
	glBindVertexArray(0);

	//  ShaderProgram
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, tex[0]);//VAO不能存储texture对象,我试了
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, tex[1]);

	Shader myShaderProg("vtx.vs", "frag.fs");
	glUseProgram(myShaderProg.ID);
	glUniform1i(glGetUniformLocation(myShaderProg.ID, "texData"), 0);
	glUniform1i(glGetUniformLocation(myShaderProg.ID, "texData2"), 1);
	glUseProgram(0);


	//  6.Render Loop:
	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		glClear(GL_COLOR_BUFFER_BIT);//绘制背景色

		//  这下面就可以写绘图的代码了
		glUseProgram(myShaderProg.ID);
		glBindVertexArray(VAO);
		glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
		//  这上面是绘图的代码

		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	//  7.程序结束之前:
	glfwTerminate();

	return 0;
}

vertex shader(没改):

#version 330 core
layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inCol;
layout (location = 2) in vec2 inTexCoor;

out vec3 col;
out vec2 texCoor;

void main()
{
    gl_Position = vec4(inPos,1);
    col = inCol;
    texCoor = inTexCoor;
}

fragment shader:

#version 330 core

in vec2 texCoor;
in vec3 col;

out vec4 fragCol;

uniform sampler2D texData;
uniform sampler2D texData2;

void main()
{
    fragCol = mix(texture(texData,texCoor),texture(texData2,texCoor),0.5) * vec4(col,1);
}

运行结果:




猜你喜欢

转载自blog.csdn.net/yymhqe123/article/details/80548518