• OpenGL原理与实践——核心模式(五):颜色、基础光照、Phong模型、材质与光


    目录

    颜色相关理论

    什么是颜色

    如何计算颜色?

    简单实现

    Phong光照模型——局部光照模型

    环境光

    ​编辑

    漫反射

    镜面反射

    材质与光

    材质与纹理的关系

    材质在shader的体现

    材质属性与光属性

    光在shader的体现

    整体源码实现及渲染结果

    关键代码

    shader——vertexShader.glsl(读取物体数据)

    shader——vsunShader.glsl(读取光源数据)

    shader——fragmentShader.glsl(定义材质、光结构体数据结构,读取数据并计算像素颜色)

    shader——fsunShader.glsl( 定义光源颜色)

    render——传入shader数据并渲染

    渲染结果


    颜色相关理论

    什么是颜色

    说白了就是光反射进人眼的那部分。

    如何计算颜色?

    以这个图为例,设自然光照为RGB分量为(1,1,1),一个物体的颜色RGB为(1,0.5,0.31),由之前所说的颜色理论,物体的颜色即为反射光照所占光源RGB百分比,所以直接相乘即可得到最终颜色。

    再比如,如果光源本身就没有红色(RGB中的R分量为0),那么物体自然也不会反射红光,即R值。所以最终颜色的结果的R也是0。

    简单实现

    我们需要一个光源和一个物体,那么自然需要构建两组VAO,并进行VBO的绑定;同时设定光源的位置和光源颜色:

    1. //main.cpp
    2. VAO_cube = createModel();
    3. VAO_sun = createModel();
    4. light_pos = glm::vec3(3.0f, 0.0f, -1.0f);
    5. light_color = glm::vec3(1.0f, 1.0f, 1.0f);
    1. uint createModel()
    2. {
    3. uint _VAO = 0;
    4. uint _VBO = 0;
    5. float vertices[] = {
    6. -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f,
    7. 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f,
    8. 0.5f, 0.5f, -0.5f, 1.0f, 1.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, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f,
    11. -0.5f, -0.5f, -0.5f, 0.0f, 0.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, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
    14. 0.5f, 0.5f, 0.5f, 1.0f, 1.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, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
    17. -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
    18. -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
    19. -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
    20. -0.5f, -0.5f, -0.5f, 0.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, 0.0f, -1.0f, 0.0f, 0.0f,
    23. -0.5f, 0.5f, 0.5f, 1.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, 1.0f, 1.0f, 0.0f, 0.0f,
    26. 0.5f, -0.5f, -0.5f, 0.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, 0.0f, 1.0f, 0.0f, 0.0f,
    29. 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    30. -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f,
    31. 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f,
    32. 0.5f, -0.5f, 0.5f, 1.0f, 0.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, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f,
    35. -0.5f, -0.5f, -0.5f, 0.0f, 1.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, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    38. 0.5f, 0.5f, 0.5f, 1.0f, 0.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, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
    41. -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    42. };
    43. glGenVertexArrays(1, &_VAO);
    44. glBindVertexArray(_VAO);
    45. glGenBuffers(1, &_VBO);
    46. glBindBuffer(GL_ARRAY_BUFFER, _VBO);
    47. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    48. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    49. glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));
    50. glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 5));
    51. glEnableVertexAttribArray(0);
    52. glEnableVertexAttribArray(1);
    53. glEnableVertexAttribArray(2);
    54. glBindVertexArray(0);
    55. glBindBuffer(GL_ARRAY_BUFFER, 0);
    56. return _VAO;
    57. }

    Phong光照模型——局部光照模型

     

    Phong光照模型是环境光、漫反射和镜面反射的结合。

    环境光

    一般是一个常数,物体一直显示的颜色。来代表周围环境的光照。

    shader中的实现为:

    可以看到这里直接设置为了一个常数系数,然后直接乘以光源光、乘以物体颜色即可完成运算。

    漫反射

    入射的光线可以分为两个向量,只有垂直于平面的分量对光照亮度有贡献。说白了就是物体实际反射出来的光。

    shader:

     

    也就是说,我们只需要计算法向量与光线向量的cos夹角(单位向量即点乘),并将这个cos赋为系数,乘以光源的颜色,即可得出漫反射的光照。

    值得注意的是,Normal 向量的计算是一个齐次坐标阵,并且最后一个元素为0,代表是向量。此外,对于缩放变换,有可能导致法向量Normal进行错误的变换,这里需要做特殊的处理:

    镜面反射

    • 考虑入射光和反射光位置的反射方式
    • 光强考虑观察者位置,视线与反射光夹角决定了光强

    shader中的具体计算方式:

    光线方向需要取反,因为实际入射光是从光源射到某个点上的。之前我们定义的是从某点射到光源上的。

    材质与光

    材质:物体对于某一种光的反射强度,在Phong模型下,就是不同物体对环境光、漫反射、镜面反射等不同光的反射强度定义。

    比如:粘土罐子对于镜面反射几乎没有反应,但是对于漫反射会有很强的反应。

    从RGB的角度来讲,可以理解为对RGB的做进一步的“百分比”。

    材质与纹理的关系

    • 纹理:可理解为普通的贴图,即物体本身最基础的颜色
    • 材质:给物体表面做的进一步的光源反射属性。比如,具有金属质感(材质)木头(纹理)、具有木头质感(材质)金属(纹理)

    材质在shader的体现

    材质属性与光属性

    • 材质属性:我们可以根据自己的喜好来决定如何反射光
    • 光属性:我们可以根据自己的喜好来决定如何发射光

    光在shader的体现

    整体源码实现及渲染结果

    上面说了这么多,需要落实到代码中去

    关键代码

    shader——vertexShader.glsl(读取物体数据)

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

    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. };

    shader——fragmentShader.glsl(定义材质、光结构体数据结构,读取数据并计算像素颜色)

    1. #version 330 core
    2. out vec4 FragColor;
    3. in vec2 outUV;
    4. in vec3 outFragPos;
    5. in vec3 outNormal;
    6. struct Material
    7. {
    8. vec3 m_ambient;
    9. vec3 m_diffuse;
    10. vec3 m_specular;
    11. float m_shiness;
    12. };
    13. uniform Material myMaterial;
    14. struct Light
    15. {
    16. vec3 m_pos;
    17. vec3 m_ambient;
    18. vec3 m_diffuse;
    19. vec3 m_specular;
    20. };
    21. uniform Light myLight;
    22. uniform sampler2D ourTexture;
    23. uniform vec3 view_pos;
    24. void main()
    25. {
    26. //环境光
    27. vec3 _ambient = myLight.m_ambient * myMaterial.m_ambient;
    28. //漫反射
    29. vec3 _normal = normalize(outNormal);
    30. vec3 _lightDir = normalize(myLight.m_pos - outFragPos);
    31. float _diff = max(dot(_normal , _lightDir) , 0.0f);
    32. vec3 _diffuse = myLight.m_diffuse * _diff * myMaterial.m_diffuse;
    33. //镜面反射
    34. float _specular_strength = 0.5;
    35. vec3 _viewDir = normalize(view_pos - outFragPos);
    36. vec3 _reflectDir = reflect(-_lightDir , outNormal);
    37. float _spec = pow(max(dot(_viewDir , _reflectDir) , 0.0f) , myMaterial.m_shiness);
    38. vec3 _sepcular = myLight.m_specular * _spec * myMaterial.m_specular;
    39. vec3 result = _ambient + _diffuse + _sepcular;
    40. FragColor = texture(ourTexture , outUV) * vec4(result ,1.0f);
    41. };

    shader——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. };

     render——传入shader数据并渲染

    1. void render()
    2. {
    3. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    4. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    5. glEnable(GL_DEPTH_TEST);
    6. _camera.update();
    7. _projMatrix = glm::perspective(glm::radians(45.0f), (float)_width / (float)_height, 0.1f, 100.0f);
    8. glm::mat4 _modelMatrix(1.0f);
    9. _modelMatrix = glm::translate(_modelMatrix, glm::vec3(0.0f, 0.0f, -3.0f));
    10. glBindTexture(GL_TEXTURE_2D, _texture);
    11. //物体shader
    12. _shader_cube.start();
    13. _shader_cube.setVec3("view_pos", _camera.getPosition());
    14. //传入光照属性
    15. light_color = glm::vec3((float)glfwGetTime() * 0.4f, (float)glfwGetTime() * 0.5f, (float)glfwGetTime() * 0.7f);
    16. _shader_cube.setVec3("myLight.m_ambient", light_color * glm::vec3(0.1f));
    17. _shader_cube.setVec3("myLight.m_diffuse", light_color * glm::vec3(0.7f));
    18. _shader_cube.setVec3("myLight.m_specular", light_color * glm::vec3(0.5f));
    19. _shader_cube.setVec3("myLight.m_pos", light_pos);
    20. //传入物体材质属性
    21. _shader_cube.setVec3("myMaterial.m_ambient", glm::vec3(0.1f));
    22. _shader_cube.setVec3("myMaterial.m_diffuse", glm::vec3(0.7f));
    23. _shader_cube.setVec3("myMaterial.m_specular", glm::vec3(0.8f));
    24. _shader_cube.setFloat("myMaterial.m_shiness", 32);
    25. _shader_cube.setMatrix("_modelMatrix", _modelMatrix);
    26. _shader_cube.setMatrix("_viewMatrix", _camera.getMatrix());
    27. _shader_cube.setMatrix("_projMatrix", _projMatrix);
    28. glBindVertexArray(VAO_cube);
    29. glDrawArrays(GL_TRIANGLES, 0, 36);
    30. _shader_cube.end();
    31. //光源shader
    32. _shader_sun.start();
    33. _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
    34. _shader_sun.setMatrix("_viewMatrix", _camera.getMatrix());
    35. _shader_sun.setMatrix("_projMatrix", _projMatrix);
    36. _modelMatrix = glm::mat4(1.0f);
    37. _modelMatrix = glm::translate(_modelMatrix, light_pos);
    38. _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
    39. glBindVertexArray(VAO_sun);
    40. glDrawArrays(GL_TRIANGLES, 0, 36);
    41. _shader_cube.end();
    42. }

    渲染结果

  • 相关阅读:
    【博客439】Kubernetes CRI
    Abnova酸性磷酸酶(小麦胚芽)说明书
    五种实现数据加密存储的方式,你选择哪一种
    C++内存管理及模板入门详解
    centos7中卸载Java、jdk命令
    神经网络迭代次数的一个近似关系
    以太坊:“攀登巅峰超越比特币!引领加密货币世界的新时代“
    MySQL-2-函数和约束
    计算机毕业设计(附源码)python-新型冠状病毒防控咨询网站
    二十三种设计模式全面解析-当你的对象需要知道其他对象的状态变化时,观察者模式是你的救星!
  • 原文地址:https://blog.csdn.net/Jason6620/article/details/128042315