OpenGL学习笔记——半反射,反射贴图

来源:互联网 发布:有声照片软件 编辑:程序博客网 时间:2024/05/18 01:10

注:原教程:LearnOpenGL CN,我这个只是学习笔记!


学习了天空盒,反射和折射这一章节之后,我打算动手搞一搞里面的练习作业。

首先将6.2节的程序扩展为支持半反射效果。


图1是默认教程给的效果图:



经过分析,如果想实现一个半反射的效果,需要以下步骤

【1】增加纹理贴图

【2】增加一个反射率参数,对颜色按照反射率进行混合计算(注意这里并不需要用到Blending,因为不是要画两遍Cube,而是在一个Cube上做混合。)


【1.1】首先要扩展顶点数据,让他支持纹理坐标

 float cubeVertices[] = {        // positions          // normals   //coord是我新增加的        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,         0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  0.0f, 0.0f,         0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  1.0f, 0.0f,         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  1.0f, 1.0f,         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  1.0f, 1.0f,        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  0.0f, 1.0f,        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,  0.0f, 0.0f,        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f, 1.0f, 0.0f,        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f, 1.0f, 1.0f,        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f, 0.0f, 1.0f,        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f, 0.0f, 1.0f,        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f, 0.0f, 0.0f,        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f, 1.0f, 0.0f,         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f, 1.0f, 0.0f,         0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f, 1.0f, 1.0f,         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f, 0.0f, 1.0f,         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f, 0.0f, 1.0f,         0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f, 0.0f, 0.0f,         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f, 1.0f, 0.0f,        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f, 0.0f, 1.0f,         0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f, 1.0f, 1.0f,         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f, 1.0f, 0.0f,         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f, 1.0f, 0.0f,        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f, 0.0f, 0.0f,        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f, 0.0f, 1.0f,        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,         0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f    };
其次,要修改VAO格式,让shader能够识别出纹理坐标:注意要把6*sizeof(float)改成8*,因为我们扩展了2个float,作为纹理坐标。

    unsigned int cubeVAO, cubeVBO;    glGenVertexArrays(1, &cubeVAO);    glGenBuffers(1, &cubeVBO);    glBindVertexArray(cubeVAO);    glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);    glEnableVertexAttribArray(0);    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);    glEnableVertexAttribArray(1);    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
【2】修改片段和顶点程序

#version 330 corelayout (location = 0) in vec3 aPos;layout (location = 1) in vec3 aNormal;layout (location = 2) in vec2 aTexCoord;out vec3 Normal;out vec3 Position;out vec2 TexCoord;uniform mat4 model;uniform mat4 view;uniform mat4 projection;void main(){    Normal = mat3(transpose(inverse(model))) * aNormal;    Position = vec3(model * vec4(aPos, 1.0));    TexCoord = aTexCoord;    gl_Position = projection * view * model * vec4(aPos, 1.0);}
这里我增加了纹理坐标的相关内容。

#version 330 coreout vec4 FragColor;in vec3 Normal;in vec3 Position;in vec2 TexCoord;uniform vec3 cameraPos;uniform sampler2D texture1;uniform samplerCube skybox;uniform float refectRate;void main(){        vec3 I = normalize(Position - cameraPos);    vec3 R = reflect(I, normalize(Normal));    vec4 color = texture(skybox, R) * refectRate + texture(texture1, TexCoord) * (1-refectRate);    FragColor = vec4(color.rgb , 1.0);}
片段程序。我增加了纹理坐标的输入,纹理的uniform数据,和反射率的uniform数据

【1.2】从新回到CPP文件的修改,这里要绑定贴图和设置参数。

    shader.use();    shader.setInt("skybox", 0);shader.setInt("texture1", 1);shader.setFloat("refectRate", 0.5f);    skyboxShader.use();    skyboxShader.setInt("skybox", 0);
以及

        // cubes        glBindVertexArray(cubeVAO);        glActiveTexture(GL_TEXTURE0);        glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, cubeTexture);        glDrawArrays(GL_TRIANGLES, 0, 36);        glBindVertexArray(0);
然后运行看看效果:



OK,目标达成!!

下面准备完成第二个目标,反射贴图,严格来说,应该用一个灰度图来做反射贴图,这样比较省,我这里偷个懒,直接用photoshop制作rgb图了。



reflect_map.jpg

大体过程都差不多,增加一张反射贴图,然后修改一下片段程序,利用反射贴图的r通道值,作为反射率。

#version 330 coreout vec4 FragColor;in vec3 Normal;in vec3 Position;in vec2 TexCoord;uniform vec3 cameraPos;uniform sampler2D texture1;uniform sampler2D reflectMap;uniform samplerCube skybox;void main(){        vec3 I = normalize(Position - cameraPos);    vec3 R = reflect(I, normalize(Normal));    float reflectRate = texture(reflectMap, TexCoord).r;    vec4 color = texture(skybox, R) * reflectRate + texture(texture1, TexCoord) * (1-reflectRate);    FragColor = vec4(color.rgb , 1.0);}
最终效果: