opengl纹理

1.说明

opengl纹理_第1张图片

 为了完成纹理映射,需要为图像的每个顶点指定一个纹理坐标([0,1]),来表明从纹理图像的哪个位置采样。其余部分通过插值得到。

使用纹理坐标获取纹理颜色的过程叫采样(Sampling)。

纹理也可以理解成颜色,采样纹理就是获取那个位置的颜色。

2.纹理环绕

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

3.纹理过滤 

不太理解

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

4.多级渐远纹理

5.生成纹理

// texture是纹理的ID,当前绑定到这个ID上,通过ID就可以访问纹理数据,使用纹理
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// 为当前绑定的纹理对象设置环绕、过滤方式
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);
// 加载并生成纹理
int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
if (data)
{
    //生成
    //当调用glTexImage2D时,当前绑定的纹理对象就会被附加上纹理图像。
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    //多级渐远纹理
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);

6.应用纹理

 vertex shader输出纹理坐标TexCoord, fragment shader接受这个变量;

GLSL有一个供纹理对象使用的内建数据类型sampler(采样器),片段着色器通过采样器获取纹理对象

我们在片段着色器中添加一个uniform sampler2D变量,稍后把纹理对象赋值给它。

//fs
#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;

void main()
{
    //第一个参数是纹理采样器,第二个参数是对应的纹理坐标。
    //texture函数会使用之前设置的纹理参数对相应的颜色值进行采样。
    FragColor = texture(ourTexture, TexCoord);
}

glBindTexture()会自动把纹理对象赋值给片段着色器的对应的的采样器

//在调用glDrawElements之前绑定纹理了,它会自动把纹理赋值给片段着色器的采样器
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

7.纹理单元

多个纹理:片段着色器中可以设置多个纹理采样器,每个纹理采样器都有其独自的位置,这个位置被称为纹理单元

通过指定位置访问纹理采样器,每个纹理采样器绑定不同的纹理数据,这样我们就可以使用多个纹理。使用每个纹理采样器之前需要激活。 

 设置纹理采样器的纹理单元,放在渲染循环的前面:

    //设置每个纹理采样器的纹理单元(位置)  uniform变量
    //只有一个纹理时,默认纹理单元是0,是默认激活的,所以不需要设置纹理单元和激活纹理单元
    /*uniform sampler2D texture1;   uniform sampler2D texture2;*/
    ourShader.use(); 
    glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0);         //GL_TEXTURE0
    ourShader.setInt("texture2", 1);                                        //GL_TEXTURE1

 激活纹理单元,放在渲染循环中:

glActiveTexture(GL_TEXTURE0);           //激活纹理单元  GL_TEXTURE0 - GL_TEXTURE16
glBindTexture(GL_TEXTURE_2D, texture1); //绑定纹理,自动把纹理图像赋值给片段着色器的纹理采样器
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);

 opengl纹理_第2张图片

8.示例
两个纹理


纹理采样器 - 纹理单元 - 纹理ID

1.生成纹理

2.设置每个纹理采样器对应的纹理单元,

3.使用纹理前,要先激活纹理单元,然后绑定纹理ID,(并把纹理赋值给纹理采样器),然后绘制;

纹理单元相当于一个桥梁,沟通纹理采样器和纹理(通过纹理ID可使用纹理)

glActiveTexture(GL_TEXTURE0);          
glBindTexture(GL_TEXTURE_2D, texture1);

 


FS:

uniform sampler2D texture1;
uniform sampler2D texture2;

//texture()函数用于采样,参数1是采样器,参数2是纹理坐标

FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);


//加载并生成纹理,通过ID访问每个纹理

  unsigned int texture1,texture2;        /ID
    //texture1
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);                 //将texture1绑定到GL_TEXTURE_2D上
    // set the texture wrapping parameters
    // set texture filtering parameters
   
     //加载并生成纹理
    unsigned char* data = stbi_load("D:/Files-D/Codes/OpenGL/RuMen/RuMen/container.jpg", &width, &height, &nrChannels, 0);

    if (data) {
        //参数:绑定纹理目标,多级渐远纹理的级别,纹理格式,宽,高,总是0,源图格式,源图数据类型,纹理数据
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);

//texture2同样


/设置每个纹理采样器的纹理单元(位置)  uniform变量
    //只有一个纹理时,默认纹理单元是0,是默认激活的,所以不需要设置纹理单元和激活纹理单元
    ourShader.use(); 
    ourShader.setInt("texture1", 0);                                        //GL_TEXTURE0
    ourShader.setInt("texture2", 1);                                        //GL_TEXTURE1


//使用

ourShader.use();

glActiveTexture(GL_TEXTURE0);           //激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture1); //绑定纹理,自动把纹理图像赋值给片段着色器对应的的纹理采样器
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, texture2);

你可能感兴趣的:(图形学基础,开发语言)