• OpenGL之光照贴图


     我们需要拓展之前的系统,引入漫反射镜面光贴图(Map)。这允许我们对物体的漫反射分量和镜面光分量有着更精确的控制。

    漫反射贴图

    我们希望通过种方式对物体的每个片段单独设置漫反射颜色。我们仅仅是对同样的原理使用了不同的名字:其实都是使用一张覆盖物体的图像,让我们能够逐片段索引其独立的颜色值。在光照场景中,它通常叫做一个漫反射贴图(Diffuse Map)(3D艺术家通常都这么叫它),它是一个表现了物体所有的漫反射颜色的纹理图像。

    在着色器中使用漫反射贴图的方法和纹理教程中是完全一样的。但这次我们会将纹理储存为Material结构体中的一个sampler2D。我们将之前定义的vec3漫反射颜色向量替换为漫反射贴图。 

    我们也移除了环境光材质颜色向量,因为环境光颜色在几乎所有情况下都等于漫反射颜色,所以我们不需要将它们分开储存:

    1. struct Material {
    2. sampler2D diffuse;
    3. vec3 specular;
    4. float shininess;
    5. };
    6. ...
    7. in vec2 TexCoords;

     注意我们将在片段着色器中再次需要纹理坐标,所以我们声明一个额外的输入变量。接下来我们只需要从纹理中采样片段的漫反射颜色值即可:

    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));

    不要忘记将环境光的材质颜色设置为漫反射材质颜色同样的值。

    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));

    就是使用漫反射贴图的全部步骤了。你可以看到,这并不是什么新的东西,但这能够极大地提高视觉品质。为了让它正常工作,我们还需要使用纹理坐标更新顶点数据,将它们作为顶点属性传递到片段着色器,加载材质并绑定材质到合适的纹理单元。

    更新后的顶点数据可以在这里找到。顶点数据现在包含了顶点位置、法向量和立方体顶点处的纹理坐标。让我们更新顶点着色器来以顶点属性的形式接受纹理坐标,并将它们传递到片段着色器中:

    1. #version 330 core
    2. layout (location = 0) in vec3 aPos;
    3. layout (location = 1) in vec3 aNormal;
    4. layout (location = 2) in vec2 aTexCoords;
    5. ...
    6. out vec2 TexCoords;
    7. void main()
    8. {
    9. ...
    10. TexCoords = aTexCoords;
    11. }

    记得去更新两个VAO的顶点属性指针来匹配新的顶点数据,并加载箱子图像为一个纹理。在绘制箱子之前,我们希望将要用的纹理单元赋值到material.diffuse这个uniform采样器,并绑定箱子的纹理到这个纹理单元:

    1. lightingShader.setInt("material.diffuse", 0);
    2. ...
    3. glActiveTexture(GL_TEXTURE0);
    4. glBindTexture(GL_TEXTURE_2D, diffuseMap);

    使用了漫反射贴图之后,细节再一次得到惊人的提升,这次箱子有了光照开始闪闪发光(字面意思也是)了。箱子看起来可能像这样:

    4.1.lighting_maps.vs

    1. #version 330 core
    2. layout (location = 0) in vec3 aPos;
    3. layout (location = 1) in vec3 aNormal;
    4. layout (location = 2) in vec2 aTexCoords;
    5. out vec3 FragPos;
    6. out vec3 Normal;
    7. out vec2 TexCoords;
    8. uniform mat4 model;
    9. uniform mat4 view;
    10. uniform mat4 projection;
    11. void main()
    12. {
    13. FragPos = vec3(model * vec4(aPos, 1.0));
    14. Normal = mat3(transpose(inverse(model))) * aNormal;
    15. TexCoords = aTexCoords;
    16. gl_Position = projection * view * vec4(FragPos, 1.0);
    17. }

    4.1.lighting_maps.fs

    1. #version 330 core
    2. out vec4 FragColor;
    3. struct Material {
    4. sampler2D diffuse;
    5. vec3 specular;
    6. float shininess;
    7. };
    8. struct Light {
    9. vec3 position;
    10. vec3 ambient;
    11. vec3 diffuse;
    12. vec3 specular;
    13. };
    14. in vec3 FragPos;
    15. in vec3 Normal;
    16. in vec2 TexCoords;
    17. uniform vec3 viewPos;
    18. uniform Material material;
    19. uniform Light light;
    20. void main()
    21. {
    22. // ambient
    23. vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
    24. // diffuse
    25. vec3 norm = normalize(Normal);
    26. vec3 lightDir = normalize(light.position - FragPos);
    27. float diff = max(dot(norm, lightDir), 0.0);
    28. vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
    29. // specular
    30. vec3 viewDir = normalize(viewPos - FragPos);
    31. vec3 reflectDir = reflect(-lightDir, norm);
    32. float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    33. vec3 specular = light.specular * (spec * material.specular);
    34. vec3 result = ambient + diffuse + specular;
    35. FragColor = vec4(result, 1.0);
    36. }

    4.1.light_cube.vs

    1. #version 330 core
    2. layout (location = 0) in vec3 aPos;
    3. uniform mat4 model;
    4. uniform mat4 view;
    5. uniform mat4 projection;
    6. void main()
    7. {
    8. gl_Position = projection * view * model * vec4(aPos, 1.0);
    9. }

    4.1.light_cube.fs 

    1. #version 330 core
    2. out vec4 FragColor;
    3. void main()
    4. {
    5. FragColor = vec4(1.0); // set all 4 vector values to 1.0
    6. }
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    11. void mouse_callback(GLFWwindow* window, double xpos, double ypos);
    12. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
    13. void processInput(GLFWwindow *window);
    14. unsigned int loadTexture(const char *path);
    15. // settings
    16. const unsigned int SCR_WIDTH = 800;
    17. const unsigned int SCR_HEIGHT = 600;
    18. // camera
    19. Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
    20. float lastX = SCR_WIDTH / 2.0f;
    21. float lastY = SCR_HEIGHT / 2.0f;
    22. bool firstMouse = true;
    23. // timing
    24. float deltaTime = 0.0f;
    25. float lastFrame = 0.0f;
    26. // lighting
    27. glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
    28. int main()
    29. {
    30. // glfw: initialize and configure
    31. // ------------------------------
    32. glfwInit();
    33. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    34. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    35. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    36. #ifdef __APPLE__
    37. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    38. #endif
    39. // glfw window creation
    40. // --------------------
    41. GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    42. if (window == NULL)
    43. {
    44. std::cout << "Failed to create GLFW window" << std::endl;
    45. glfwTerminate();
    46. return -1;
    47. }
    48. glfwMakeContextCurrent(window);
    49. glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    50. glfwSetCursorPosCallback(window, mouse_callback);
    51. glfwSetScrollCallback(window, scroll_callback);
    52. // tell GLFW to capture our mouse
    53. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    54. // glad: load all OpenGL function pointers
    55. // ---------------------------------------
    56. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    57. {
    58. std::cout << "Failed to initialize GLAD" << std::endl;
    59. return -1;
    60. }
    61. // configure global opengl state
    62. // -----------------------------
    63. glEnable(GL_DEPTH_TEST);
    64. // build and compile our shader zprogram
    65. // ------------------------------------
    66. Shader lightingShader("4.1.lighting_maps.vs", "4.1.lighting_maps.fs");
    67. Shader lightCubeShader("4.1.light_cube.vs", "4.1.light_cube.fs");
    68. // set up vertex data (and buffer(s)) and configure vertex attributes
    69. // --------------------------------------------------
  • 相关阅读:
    深兰科技轮腿家用AI机器人荣获“2023年度城市更新科创大奖”
    OpenHarmony命令行工具hdc_std使用总结
    Python高级_第2章_计算机网络及TCP网络应用程序开发
    2022年,消费品企业应该选择什么样的会员系统?
    springboot健身房管理系统毕业设计源码031807
    【软考】系统集成项目管理工程师(四)项目管理一般知识
    关于#idea#的问题:IDEA2023版本创建包时显示无效的软件包名称格式设置(语言-java)
    微信小程序 插槽的使用
    MySQL数据库八股文
    Jenkins 构建报错 Could not load
  • 原文地址:https://blog.csdn.net/qq_44632658/article/details/133345342