6.纹理

1.纹理采样:根据纹理坐标获取像素值

2.纹理环绕:当纹理坐标超出默认范围时纹理的重复方式,OpenGL提供了以下几种方式

6.纹理_第1张图片

对纹理环绕方式进行设置:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f }; 

glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

3.纹理过滤:纹理坐标不依赖于分辨率,可以是任意浮点值,纹理像素映射到纹理坐标称为过滤。

    两种纹理过滤方式:

        (1) GL_NEAREST:选取中心点距离纹理坐标最近的像素值作为纹理的颜色

        (2) GL_LINEAR: 它会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色

    设置纹理被放大或缩小时的过滤方式

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

4.多级渐远纹理: 它简单来说就是一系列的纹理图像,后一个纹理图像是前一个的二分之一。多级渐远纹理背后的理念很简单:距观察者的距离超过一定的阈值,OpenGL会使用不同的多级渐远纹理,即最适合物体的距离的那个(仅用于纹理被缩小时)

    多级渐远纹理的过滤方式:

6.纹理_第2张图片

设置多级渐远纹理的过滤方式:

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

5.加载纹理:使用文件图像加载库stb_image.h,在源文件中引入stb_image.h并定义 STB_IMAGE_IMPLEMENTATION即可使用

#define STB_IMAGE_IMPLEMENTATION 
#include "stb_image.h"
main(){
    int width, height, nrChannels;
    unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
    //释放图像内存
    stbi_image_free(data);
}

6.创建纹理对象并配置:

       (1)创建纹理对象,使用ID进行引用
       unsigned int texture;
       glGenTextures(1,&texture);
       (2)绑定纹理到target,之后的任何纹理指令都会配置当前绑定的纹理(使用多个纹理时,需要配置完一个纹理之后,再绑定别的纹理进行配置)
       glBindTexture(GL_TEXTURE_2D,texture);
       (3)设置纹理参数
       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);
       (4)翻转y轴
       stbi_set_flip_vertically_on_load(true);
       (5)使用图像数据生成纹理
       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,  GL_UNSIGNED_BYTE, data);
       (6)自动生成多级渐远纹理
       glGenerateMipmap(GL_TEXTURE_2D);

 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data)

  • 第一个参数指定了纹理目标(Target)。设置为GL_TEXTURE_2D意味着会生成与当前绑定的纹理对象在同一个目标上的纹理(任何绑定到GL_TEXTURE_1D和GL_TEXTURE_3D的纹理不会受到影响)。

  • 第二个参数为纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别。

  • 第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值,因此我们也把纹理储存为RGB值。

  • 第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们,所以我们使用对应的变量。

  • 下个参数应该总是被设为0(历史遗留的问题)。

  • 第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像,并把它们储存为char(byte)数组,我们将会传入对应值。

  • 最后一个参数是真正的图像数据

7.使用纹理

    (1)主程序中:在绘制前将纹理绑定至target

glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(VAO); 
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

(2)shader中:

顶点着色器将纹理坐标传出给片元着色器

layout (location = 2) in vec2 aTexCoord;
out vec2 TexCoord;
void main() { 
    gl_Position = vec4(aPos, 1.0); 
    ourColor = aColor; 
    TexCoord = aTexCoord; 
}

片元着色器中根据纹理target和纹理坐标进行采样

in vec2 TexCoord;
uniform sampler2D ourTexture; 
void main() { 
    FragColor = texture(ourTexture, TexCoord); 
}

8.使用纹理单元:纹理在shader中定义类型为uniform,通过uniform1i我们可以将纹理绑定至不同纹理单元,在绘制前激活不同的纹理单元并绑定至target即可使用,默认激活纹理单元是GL_TEXTURE0

//设置纹理单元
unsigned int tex1Location  = glGetUniformLocation(shaderProgram,"ourTexture1");
glUniform1i(tex1Location,0);
unsigned int tex2Location  = glGetUniformLocation(shaderProgram,"ourTexture2");
glUniform1i(tex2Location,1);

//激活纹理单元
glActiveTexture(GL_TEXTURE0); 
//绑定至target
glBindTexture(GL_TEXTURE_2D,texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,texture2);

9.使用两幅纹理进行混合:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include 
#include 
#include 
extern void framebuffer_size_callback(GLFWwindow* window, int width, int height);
extern void processInput(GLFWwindow *window);
extern unsigned int SCR_WIDTH = 800;
extern unsigned int SCR_HEIGHT = 600;
const char * vertexShaderSource_TextureTest =
       "#version 330 core\n"
       "layout(location = 0)in vec3 aPos;\n"
       "layout(location = 2)in vec2 aTexCoord;\n "
       "layout(location = 1)in vec3 aColor;\n"
       "out vec3 myColor;\n"
       "out vec2 TexCoord;\n"
       "void main(){\n"
       "gl_Position = vec4(aPos,1.0f);\n"
       "TexCoord = vec2(aTexCoord.x,aTexCoord.y);\n"
       "myColor = aColor;\n"
       "}\n";
const char * fragementShaderSource_TextureTest =
       "#version 330 core\n"
       "out vec4 FragColor;\n"
       "in vec2 TexCoord;\n"
       "in vec3 myColor;\n"
       "uniform sampler2D ourTexture1;\n"
       "uniform sampler2D ourTexture2;\n"
       "void main(){\n"
       "FragColor =  mix(texture(ourTexture1,TexCoord),texture(ourTexture2,TexCoord),0.2);\n"
       "}\n";
int DrawATexture(){
       //初始化窗口和OpenGL
       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, "LearnOpenGL",  NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    // glad: load all OpenGL function pointers
    // ---------------------------------------
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
       //顶点着色器
       //创建着色器对象
       unsigned int vertexShader;
       vertexShader = glCreateShader(GL_VERTEX_SHADER);
       //着色器填充源代码
       glShaderSource(vertexShader,1,&vertexShaderSource_TextureTest,NULL);
       //编译着色器
       glCompileShader(vertexShader);
       //检测着色器是否编译成功,并查看错误信息
       int success;
       char infoLog[512];
       glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success);   //检测是否编译成功
       if(!success)
       {
              glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
              std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog <<  std::endl;
       }
       //片元着色器
       unsigned int fragmentShader;
       fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
       glShaderSource(fragmentShader,1,&fragementShaderSource_TextureTest,NULL);
       glCompileShader(fragmentShader);
       //检测着色器是否编译成功,并查看错误信息
       int success_f;
       char infoLog_f[512];
       glGetShaderiv(fragmentShader,GL_COMPILE_STATUS,&success_f);      //检测是否编译成功
       if(!success)
       {
              glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog_f);
              std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog <<  std::endl;
       }
       //创建程序对象
       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::PROGRAM::LINK_FAILED"<

 

你可能感兴趣的:(opengl,opengl,c++,3d)