• OpenGL原理与实践——核心模式(六):光照贴图、光源分类以及多光源场景主要源码实现


    本章主要以代码为主,理论理解即可。详细分析代码

    目录

    光照贴图

    光源分类

    平行光

    点光源

    shader——点光源

    聚光灯

    聚光灯边缘优化——光强递减

    源码解析

    main

    全局变量、句柄

    main函数主体逻辑

    createModel()

    createTexture(const char* _filename)

    ininShader (const char* _vertexPath, const char* _fragPath)

    render()

    shader

    vsunShader.glsl

    fsunShader.glsl

    sceneShaderv.glsl

    sceneShaderf.glsl

    渲染结果


    光照贴图

    光源分类

    我们之前讨论的都是简单的点光源,并且没有考虑光源随距离的衰减。

    为此,将其光源分为三类

    平行光

    如何区分简单点光源和平行光?

    可以利用齐次向量的最后一个参数,即w。

    • 如果w为1,则标明是一个向量,是平行光;
    • 如果w为0,则标明是一个点,即点光源

    点光源

     

    考虑了光随距离衰减,提出了一种非线性的公式,其中d代表光源与像素点的距离。

    对于公式中三个k系数,有一些经验值:

    shader——点光源

    聚光灯

    聚光灯边缘优化——光强递减

    源码解析

    main

    以往的不变的函数

    1. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
    2. void processInput(GLFWwindow* window);
    3. void mouse_callback(GLFWwindow* window, double xpos, double ypos);

    全局变量、句柄

    1. //场景中有两种东西:物体和光源
    2. uint VAO_cube = 0;
    3. uint VAO_sun = 0;
    4. //设置光源位置
    5. glm::vec3 light_pos(1.0f);
    6. glm::vec3 light_color(1.0f);
    7. //光照贴图
    8. uint _textureBox = 0;
    9. uint _textureSpec = 0;
    10. //类声明
    11. Shader _shader_scene;
    12. Shader _shader_sun;
    13. ffImage* _pImage = nullptr;
    14. Camera _camera;
    15. //初始化投影矩阵、设置宽高
    16. glm::mat4 _projMatrix(1.0f);
    17. int _width = 800;
    18. int _height = 600;

    main函数主体逻辑

    1. int main() {
    2. glfwInit();
    3. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    4. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    5. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
    6. GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Core", NULL, NULL);
    7. if (window == NULL)
    8. {
    9. std::cout << "Failed to create GLFW window" << std::endl;
    10. glfwTerminate();
    11. return -1;
    12. }
    13. glfwMakeContextCurrent(window);
    14. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    15. {
    16. std::cout << "Failed to initialize GLAD" << std::endl;
    17. return -1;
    18. }
    19. glViewport(0, 0, _width, _height);
    20. glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    21. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    22. glfwSetCursorPosCallback(window, mouse_callback);
    23. _camera.lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    24. _camera.setSpeed(0.001f);
    25. VAO_cube = createModel();
    26. VAO_sun = createModel();
    27. light_pos = glm::vec3(2.0f, 0.0f, 0.0f);
    28. light_color = glm::vec3(1.0f, 1.0f, 1.0f);
    29. _textureBox = createTexture("res/box.png");
    30. _textureSpec = createTexture("res/specular.png");
    31. initShader("","");
    32. while (!glfwWindowShouldClose(window))
    33. {
    34. processInput(window);
    35. render();
    36. glfwSwapBuffers(window);
    37. glfwPollEvents();
    38. }
    39. glfwTerminate();
    40. return 0;
    41. }

    值得注意的只有

    1. VAO_cube = createModel();
    2. VAO_sun = createModel();
    3. light_pos = glm::vec3(2.0f, 0.0f, 0.0f);
    4. light_color = glm::vec3(1.0f, 1.0f, 1.0f);
    5. _textureBox = createTexture("res/box.png");
    6. _textureSpec = createTexture("res/specular.png");
    7. initShader("","");

    这些初始化的操作。其中涉及了:

    • 初始化了:刚才提到的全局变量句柄,也就是需要渲染的两种事物cube(物体)和sun(光源),利用了createModel()
    • 初始化了:全局变量light_pos和light_color
    • 初始化了:_textureBos 和 _textureSpec,利用了createTexture
    • 初始化了:InitShader
    • 核心逻辑:render(),完成渲染

    上述四个函数,接下来解析

    createModel()

    1. uint createModel()
    2. {
    3. uint _VAO = 0;
    4. uint _VBO = 0;
    5. float vertices[] = {
    6. //位置 UV 法线
    7. -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
    8. 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
    9. 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
    10. 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f,
    11. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f,
    12. -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
    13. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
    14. 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
    15. 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    16. 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    17. -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    18. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
    19. -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
    20. -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
    21. -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
    22. -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
    23. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
    24. -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
    25. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    26. 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
    27. 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
    28. 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
    29. 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    30. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    31. -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
    32. 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
    33. 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
    34. 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
    35. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f,
    36. -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
    37. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    38. 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    39. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    40. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    41. -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    42. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    43. };
    44. glGenVertexArrays(1, &_VAO);
    45. glBindVertexArray(_VAO);
    46. glGenBuffers(1, &_VBO);
    47. glBindBuffer(GL_ARRAY_BUFFER, _VBO);
    48. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    49. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    50. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));
    51. glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 5));
    52. glEnableVertexAttribArray(0);
    53. glEnableVertexAttribArray(1);
    54. glEnableVertexAttribArray(2);
    55. glBindVertexArray(0);
    56. glBindBuffer(GL_ARRAY_BUFFER, 0);
    57. return _VAO;
    58. }

    是对顶点数据的初始化的VBO绑定操作。

    createTexture(const char* _filename)

    1. uint createTexture(const char* _filename) {
    2. _pImage = ffImage::readFromFile(_filename);
    3. uint _texture = 0;
    4. glGenTextures(1, &_texture);
    5. glBindTexture(GL_TEXTURE_2D, _texture);
    6. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    7. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    8. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    9. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    10. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _pImage->getWidth(), _pImage->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, _pImage->getData());
    11. return _texture;
    12. }

    读取纹理贴图的操作

    ininShader (const char* _vertexPath, const char* _fragPath)

    1. void initShader(const char* _vertexPath, const char* _fragPath)
    2. {
    3. _shader_sun.initShader("shader/vsunShader.glsl", "shader/fsunShader.glsl");
    4. _shader_scene.initShader("shader/sceneShaderv.glsl", "shader/sceneShaderf.glsl");
    5. }

    其实这里并不需要参数,只是一种修改之前代码的写法。用硬编码的方式。

    根据代码得知:我们只需要4个shader:

    • fsunShader:光源的fragmentShader
    • vsunShader:光源的vertexShader
    • sceneShaderf:场景的fragmentShader
    • sceneShaderv:场景的vertexShader

    这里多提一嘴,fragmentShader中的fragment并不是像素,而是插值而来的图元,这两个概念并不相等。

    render()

    在渲染中需要做:

    • 初始化:背景颜色
    • 初始化:需渲染个10个物体的位置
    • 初始化:4个点光源的位置
    • 初始化:相机朝向,以及模型投影矩阵
    • 初始化:激活纹理,已在createTexture中初始化
    • 渲染前:
      • 设置:开始相机位置
      • 设置:物体材质参数,物体的diffuse和specular已通过光照贴图设置完毕
      • 设置:平行光参数×1
      • 设置:点光源参数×4
      • 设置:聚光灯参数×1
    • 渲染:10个物体+4个点光源
    1. void render()
    2. {
    3. //设置视口背景颜色,
    4. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    5. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    6. glEnable(GL_DEPTH_TEST);
    7. //10个物体的位置
    8. glm::vec3 cubePositions[] = {
    9. glm::vec3(0.0f, 0.0f, 0.0f),
    10. glm::vec3(2.0f, 5.0f, -15.0f),
    11. glm::vec3(-1.5f, -2.2f, -2.5f),
    12. glm::vec3(-3.8f, -2.0f, -12.3f),
    13. glm::vec3(2.4f, -0.4f, -3.5f),
    14. glm::vec3(-1.7f, 3.0f, -7.5f),
    15. glm::vec3(1.3f, -2.0f, -2.5f),
    16. glm::vec3(1.5f, 2.0f, -2.5f),
    17. glm::vec3(1.5f, 0.2f, -1.5f),
    18. glm::vec3(-1.3f, 1.0f, -1.5f)
    19. };
    20. //4个光源的位置
    21. glm::vec3 pointLightPositions[] = {
    22. glm::vec3(0.7f, 0.2f, 2.0f),
    23. glm::vec3(2.3f, -3.3f, -4.0f),
    24. glm::vec3(-4.0f, 2.0f, -12.0f),
    25. glm::vec3(0.0f, 0.0f, -3.0f)
    26. };
    27. //调整摄像机朝向位置,调用glm::lootAt
    28. _camera.update();
    29. //初始化投影矩阵
    30. _projMatrix = glm::perspective(glm::radians(45.0f), (float)_width / (float)_height, 0.1f, 100.0f);
    31. //初始化模型矩阵,为单位阵
    32. glm::mat4 _modelMatrix(1.0f);
    33. //对模型进行平移变换
    34. _modelMatrix = glm::translate(_modelMatrix, glm::vec3(0.0f, 0.0f, -3.0f));
    35. //激活纹理,并绑定相应纹理
    36. glActiveTexture(GL_TEXTURE0);
    37. glBindTexture(GL_TEXTURE_2D, _textureBox);
    38. glActiveTexture(GL_TEXTURE1);
    39. glBindTexture(GL_TEXTURE_2D, _textureSpec);
    40. //渲染
    41. _shader_scene.start();
    42. _shader_scene.setVec3("view_pos", _camera.getPosition());
    43. //传入物体材质属性
    44. _shader_scene.setInt("myMaterial.m_specular", 1);
    45. _shader_scene.setFloat("myMaterial.m_shiness", 32);
    46. _shader_scene.setMatrix("_viewMatrix", _camera.getMatrix());
    47. _shader_scene.setMatrix("_projMatrix", _projMatrix);
    48. // directional light 平行光
    49. _shader_scene.setVec3("_dirLight.m_direction", glm::vec3(-0.2f, -1.0f, -0.3f));
    50. _shader_scene.setVec3("_dirLight.m_ambient", glm::vec3(0.05f, 0.05f, 0.05f));
    51. _shader_scene.setVec3("_dirLight.m_diffuse", glm::vec3(0.4f, 0.4f, 0.4f));
    52. _shader_scene.setVec3("_dirLight.m_specular", glm::vec3(0.5f, 0.5f, 0.5f));
    53. // point light 点光源
    54. // point light 1
    55. _shader_scene.setVec3("_pointLight[0].m_pos", pointLightPositions[0]);
    56. _shader_scene.setVec3("_pointLight[0].m_ambient", glm::vec3(0.05f, 0.05f, 0.05f));
    57. _shader_scene.setVec3("_pointLight[0].m_diffuse", glm::vec3(0.8f, 0.8f, 0.8f));
    58. _shader_scene.setVec3("_pointLight[0].m_specular", glm::vec3(1.0f, 1.0f, 1.0f));
    59. _shader_scene.setFloat("_pointLight[0].m_c", 1.0f);
    60. _shader_scene.setFloat("_pointLight[0].m_l", 0.09);
    61. _shader_scene.setFloat("_pointLight[0].m_q", 0.032);
    62. // point light 2
    63. _shader_scene.setVec3("_pointLight[1].m_pos", pointLightPositions[1]);
    64. _shader_scene.setVec3("_pointLight[1].m_ambient", glm::vec3(0.05f, 0.05f, 0.05f));
    65. _shader_scene.setVec3("_pointLight[1].m_diffuse", glm::vec3(0.8f, 0.8f, 0.8f));
    66. _shader_scene.setVec3("_pointLight[1].m_specular", glm::vec3(1.0f, 1.0f, 1.0f));
    67. _shader_scene.setFloat("_pointLight[1].m_c", 1.0f);
    68. _shader_scene.setFloat("_pointLight[1].m_l", 0.09);
    69. _shader_scene.setFloat("_pointLight[1].m_q", 0.032);
    70. // point light 3
    71. _shader_scene.setVec3("_pointLight[2].m_pos", pointLightPositions[2]);
    72. _shader_scene.setVec3("_pointLight[2].m_ambient", glm::vec3(0.05f, 0.05f, 0.05f));
    73. _shader_scene.setVec3("_pointLight[2].m_diffuse", glm::vec3(0.8f, 0.8f, 0.8f));
    74. _shader_scene.setVec3("_pointLight[2].m_specular", glm::vec3(1.0f, 1.0f, 1.0f));
    75. _shader_scene.setFloat("_pointLight[2].m_c", 1.0f);
    76. _shader_scene.setFloat("_pointLight[2].m_l", 0.09);
    77. _shader_scene.setFloat("_pointLight[2].m_q", 0.032);
    78. // point light 4
    79. _shader_scene.setVec3("_pointLight[3].m_pos", pointLightPositions[3]);
    80. _shader_scene.setVec3("_pointLight[3].m_ambient", glm::vec3(0.05f, 0.05f, 0.05f));
    81. _shader_scene.setVec3("_pointLight[3].m_diffuse", glm::vec3(0.8f, 0.8f, 0.8f));
    82. _shader_scene.setVec3("_pointLight[3].m_specular", glm::vec3(1.0f, 1.0f, 1.0f));
    83. _shader_scene.setFloat("_pointLight[3].m_c", 1.0f);
    84. _shader_scene.setFloat("_pointLight[3].m_l", 0.09);
    85. _shader_scene.setFloat("_pointLight[3].m_q", 0.032);
    86. // spotLight
    87. _shader_scene.setVec3("_spotLight.m_pos", _camera.getPosition());//跟随相机
    88. _shader_scene.setVec3("_spotLight.m_direction", _camera.getDirection());//跟随相机
    89. _shader_scene.setVec3("_spotLight.m_ambient", glm::vec3(0.0f, 0.0f, 0.0f));
    90. _shader_scene.setVec3("_spotLight.m_diffuse", glm::vec3(1.0f, 1.0f, 1.0f));
    91. _shader_scene.setVec3("_spotLight.m_specular", glm::vec3(1.0f, 1.0f, 1.0f));
    92. _shader_scene.setFloat("_spotLight.m_c", 1.0f);
    93. _shader_scene.setFloat("_spotLight.m_l", 0.09);
    94. _shader_scene.setFloat("_spotLight.m_q", 0.032);
    95. _shader_scene.setFloat("_spotLight.m_cutOff", glm::cos(glm::radians(12.5f)));
    96. _shader_scene.setFloat("_spotLight.m_outCutOff", glm::cos(glm::radians(15.0f)));
    97. //渲染10个物体
    98. for (int i = 0; i < 10; i++)
    99. {
    100. //初始化单位矩阵(模型),对10个物体求各自的平移旋转变换
    101. _modelMatrix = glm::mat4(1.0f);
    102. _modelMatrix = glm::translate(_modelMatrix, cubePositions[i]);
    103. _modelMatrix = glm::rotate(_modelMatrix, glm::radians(i * 20.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    104. _shader_scene.setMatrix("_modelMatrix", _modelMatrix);
    105. glBindVertexArray(VAO_cube);
    106. glDrawArrays(GL_TRIANGLES, 0, 36);
    107. }
    108. _shader_scene.end();
    109. _shader_sun.start();
    110. _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
    111. _shader_sun.setMatrix("_viewMatrix", _camera.getMatrix());
    112. _shader_sun.setMatrix("_projMatrix", _projMatrix);
    113. //渲染4个点光源
    114. for (int i = 0; i < 4; i++)
    115. {
    116. _modelMatrix = glm::mat4(1.0f);
    117. _modelMatrix = glm::translate(_modelMatrix, pointLightPositions[i]);
    118. _modelMatrix = glm::scale(_modelMatrix, glm::vec3(0.2f, 0.2f, 0.2f));
    119. _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
    120. glBindVertexArray(VAO_sun);
    121. glDrawArrays(GL_TRIANGLES, 0, 36);
    122. }
    123. _shader_sun.end();
    124. }

    shader

    vsunShader.glsl

    1. //vsunShader.glsl
    2. #version 330 core
    3. layout (location = 0) in vec3 aPos;
    4. layout (location = 1) in vec2 aUV;
    5. out vec2 outUV;
    6. uniform mat4 _modelMatrix;
    7. uniform mat4 _viewMatrix;
    8. uniform mat4 _projMatrix;
    9. void main()
    10. {
    11. gl_Position = _projMatrix * _viewMatrix * _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);
    12. outUV = aUV;
    13. };

    从C++代码中设传入数据设置MVP矩阵,

    fsunShader.glsl

    1. #version 330 core
    2. out vec4 FragColor;
    3. in vec2 outUV;
    4. uniform sampler2D ourTexture;
    5. void main()
    6. {
    7. FragColor = vec4(1.0f , 1.0f ,1.0f ,1.0f );
    8. };

    光源的颜色直接设置为白色(1,1,1,1)

    sceneShaderv.glsl

    1. #version 330 core
    2. layout (location = 0) in vec3 aPos;
    3. layout (location = 1) in vec2 aUV;
    4. layout (location = 2) in vec3 aNormal;
    5. out vec2 outUV;
    6. out vec3 outFragPos;
    7. out vec3 outNormal;
    8. uniform mat4 _modelMatrix;
    9. uniform mat4 _viewMatrix;
    10. uniform mat4 _projMatrix;
    11. void main()
    12. {
    13. gl_Position = _projMatrix * _viewMatrix * _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);
    14. outUV = aUV;
    15. outFragPos = vec3( _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0));
    16. outNormal = mat3(transpose(inverse(_modelMatrix))) * aNormal;
    17. };

    从C++代码中设传入数据设置MVP矩阵,设置法向量。

    sceneShaderf.glsl

    1. #version 330 core
    2. out vec4 FragColor;
    3. in vec2 outUV;
    4. in vec3 outFragPos;
    5. in vec3 outNormal;
    6. //物体材质
    7. struct Material
    8. {
    9. sampler2D m_diffuse;//0
    10. sampler2D m_specular;//1
    11. float m_shiness;
    12. };
    13. //平行光
    14. struct DirLight
    15. {
    16. vec3 m_direction;
    17. vec3 m_ambient;
    18. vec3 m_diffuse;
    19. vec3 m_specular;
    20. };
    21. //点光源
    22. struct PointLight
    23. {
    24. vec3 m_pos;
    25. vec3 m_ambient;
    26. vec3 m_diffuse;
    27. vec3 m_specular;
    28. float m_c;
    29. float m_l;
    30. float m_q;
    31. };
    32. //聚光灯
    33. struct SpotLight
    34. {
    35. vec3 m_pos;
    36. vec3 m_direction;
    37. float m_cutOff;
    38. float m_outCutOff;
    39. vec3 m_ambient;
    40. vec3 m_diffuse;
    41. vec3 m_specular;
    42. float m_c;
    43. float m_l;
    44. float m_q;
    45. };
    46. #define MAX_POINT_NUMBER 4
    47. uniform DirLight _dirLight;
    48. uniform PointLight _pointLight[MAX_POINT_NUMBER];
    49. uniform SpotLight _spotLight;
    50. uniform Material myMaterial;
    51. uniform vec3 view_pos;
    52. vec3 calculateDir(DirLight _light, vec3 _normal, vec3 _viewDir){
    53. vec3 _lightDir = normalize(_light.m_direction);
    54. //环境光
    55. vec3 _ambient = _light.m_ambient * vec3(texture(myMaterial.m_diffuse, outUV));
    56. //漫反射
    57. float _diff = max(dot(_normal,-_lightDir),0.0f);
    58. vec3 _diffuse = _light.m_diffuse * _diff * vec3(texture(myMaterial.m_diffuse, outUV));
    59. //镜面反射
    60. vec3 _reflectDir = reflect(_lightDir, _normal);
    61. float _spec = pow(max(dot(_reflectDir, _viewDir),0.0f),myMaterial.m_shiness);
    62. vec3 _specular = _light.m_specular * _spec * vec3(texture(myMaterial.m_specular, outUV));
    63. return (_ambient + _diffuse + _specular);
    64. }
    65. vec3 calculatePoint(PointLight _light , vec3 _normal , vec3 _viewDir , vec3 _fragPos)
    66. {
    67. vec3 _lightDir = normalize( _fragPos - _light.m_pos);
    68. //环境光
    69. vec3 _ambient = _light.m_ambient * vec3(texture(myMaterial.m_diffuse , outUV));
    70. //漫反射
    71. float _diff = max(dot(_normal , -_lightDir) , 0.0f);
    72. vec3 _diffuse = _light.m_diffuse * _diff * vec3(texture(myMaterial.m_diffuse , outUV));
    73. //镜面反射
    74. vec3 _reflectDir = reflect(_lightDir , _normal);
    75. float _spec = pow(max(dot(_reflectDir , _viewDir) , 0.0f) , myMaterial.m_shiness);
    76. vec3 _specular = _light.m_specular * _spec * vec3(texture(myMaterial.m_specular , outUV));
    77. //衰减系数计算
    78. float _dist = length(_light.m_pos - _fragPos);
    79. float _attenuation = 1.0f / (_light.m_c + _light.m_l * _dist + _light.m_q * _dist * _dist);
    80. return (_ambient + _diffuse + _specular) * _attenuation;
    81. }
    82. vec3 calculateSpot(SpotLight _light , vec3 _normal , vec3 _viewDir , vec3 _fragPos)
    83. {
    84. vec3 _lightDir = normalize( _fragPos - _light.m_pos);
    85. vec3 _spotDir= normalize(_light.m_direction);
    86. float _cosTheta = dot(-_lightDir , -_spotDir);
    87. float _epsilon = _light.m_cutOff - _light.m_outCutOff;
    88. float _intensity = clamp((_cosTheta - _light.m_outCutOff) / _epsilon , 0.0f , 1.0f);
    89. //环境光
    90. vec3 _ambient = _light.m_ambient * vec3(texture(myMaterial.m_diffuse , outUV));
    91. //漫反射
    92. float _diff = max(dot(_normal , -_lightDir) , 0.0f);
    93. vec3 _diffuse = _light.m_diffuse * _diff * vec3(texture(myMaterial.m_diffuse , outUV));
    94. //镜面反射
    95. vec3 _reflectDir = reflect(_lightDir , _normal);
    96. float _spec = pow(max(dot(_reflectDir , _viewDir) , 0.0f) , myMaterial.m_shiness);
    97. vec3 _specular = _light.m_specular * _spec * vec3(texture(myMaterial.m_specular , outUV));
    98. //衰减系数计算
    99. float _dist = length(_light.m_pos - _fragPos);
    100. float _attenuation = 1.0f / (_light.m_c + _light.m_l * _dist + _light.m_q * _dist * _dist);
    101. return (_ambient + _diffuse + _specular) * _attenuation * _intensity;
    102. }
    103. void main()
    104. {
    105. vec3 _normal = normalize(outNormal);
    106. vec3 _viewDir = normalize(view_pos - outFragPos);
    107. vec3 _result = calculateDir(_dirLight ,_normal , _viewDir);
    108. for(int i = 0;i < MAX_POINT_NUMBER;i++)
    109. {
    110. _result += calculatePoint(_pointLight[i] , _normal , _viewDir , outFragPos);
    111. }
    112. _result += calculateSpot(_spotLight , _normal , _viewDir , outFragPos);
    113. FragColor = vec4(_result ,1.0f);
    114. //FragColor = vec4(vec3(gl_FragCoord.y / 600.0f) ,1.0f);
    115. };

    总体就是对之前理论的shader代码复现,最后将各个光源的贡献加在一起,作为FragColor输出。

    渲染结果

  • 相关阅读:
    华为云云耀云服务器L实例使用教学:安装jdk和配置环境变量
    刘畊宏男孩女孩看过来!运动数据分析挖掘!⛵
    PowerShell install 一键部署hfish
    【个人博客系统 × Redis】“最后的升级” · 连接Redis · Redis的基本使用
    3、微服务设计为什么要选择DDD
    事务的传播机制
    类加载机制
    [附源码]SSM计算机毕业设计中青年健康管理监测系统JAVA
    2. Layui栅格系统和布局
    MySql(19)视图
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/128043845