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

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

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

再比如,如果光源本身就没有红色(RGB中的R分量为0),那么物体自然也不会反射红光,即R值。所以最终颜色的结果的R也是0。
我们需要一个光源和一个物体,那么自然需要构建两组VAO,并进行VBO的绑定;同时设定光源的位置和光源颜色:
- //main.cpp
- VAO_cube = createModel();
- VAO_sun = createModel();
- light_pos = glm::vec3(3.0f, 0.0f, -1.0f);
- light_color = glm::vec3(1.0f, 1.0f, 1.0f);
- uint createModel()
- {
- uint _VAO = 0;
- uint _VBO = 0;
-
- float vertices[] = {
- -0.5f, -0.5f, -0.5f, 0.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, 1.0f, 0.0f, 0.0f, -1.0f,
- 0.5f, 0.5f, -0.5f, 1.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, 0.0f, 0.0f, 0.0f, -1.0f,
-
- -0.5f, -0.5f, 0.5f, 0.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, 1.0f, 0.0f, 0.0f, 1.0f,
- 0.5f, 0.5f, 0.5f, 1.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, 0.0f, 0.0f, 0.0f, 1.0f,
-
- -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
- -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f,
- -0.5f, -0.5f, -0.5f, 0.0f, 1.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, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-
- 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
- 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
- 0.5f, -0.5f, -0.5f, 0.0f, 1.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, 1.0f, 0.0f, 1.0f, 0.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, 1.0f, 1.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, 0.0f,
- -0.5f, -0.5f, 0.5f, 0.0f, 0.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, 1.0f, 0.0f,
- 0.5f, 0.5f, -0.5f, 1.0f, 1.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, 0.0f,
- -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
- -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
- };
-
-
- glGenVertexArrays(1, &_VAO);
- glBindVertexArray(_VAO);
-
- glGenBuffers(1, &_VBO);
- glBindBuffer(GL_ARRAY_BUFFER, _VBO);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
-
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 3));
- glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(sizeof(float) * 5));
-
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
- glEnableVertexAttribArray(2);
-
- glBindVertexArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- return _VAO;
- }


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

一般是一个常数,物体一直显示的颜色。来代表周围环境的光照。
在shader中的实现为:

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


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

也就是说,我们只需要计算法向量与光线向量的cos夹角(单位向量即点乘),并将这个cos赋为系数,乘以光源的颜色,即可得出漫反射的光照。
值得注意的是,Normal 向量的计算是一个齐次坐标阵,并且最后一个元素为0,代表是向量。此外,对于缩放变换,有可能导致法向量Normal进行错误的变换,这里需要做特殊的处理:
![]()

shader中的具体计算方式:

光线方向需要取反,因为实际入射光是从光源射到某个点上的。之前我们定义的是从某点射到光源上的。
材质:物体对于某一种光的反射强度,在Phong模型下,就是不同物体对环境光、漫反射、镜面反射等不同光的反射强度定义。
比如:粘土罐子对于镜面反射几乎没有反应,但是对于漫反射会有很强的反应。
从RGB的角度来讲,可以理解为对RGB的做进一步的“百分比”。



上面说了这么多,需要落实到代码中去
- //vertexShader.glsl
- #version 330 core
- layout (location = 0) in vec3 aPos;
- layout (location = 1) in vec2 aUV;
- layout (location = 2) in vec3 aNormal;
-
- out vec2 outUV;
- out vec3 outFragPos;
- out vec3 outNormal;
-
-
- uniform mat4 _modelMatrix;
- uniform mat4 _viewMatrix;
- uniform mat4 _projMatrix;
-
- void main()
- {
- gl_Position = _projMatrix * _viewMatrix * _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);
- outUV = aUV;
- outFragPos = vec3( _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0));
- outNormal = mat3(transpose(inverse(_modelMatrix))) * aNormal;
- };
- //vsunShader.glsl
- #version 330 core
- layout (location = 0) in vec3 aPos;
- layout (location = 1) in vec2 aUV;
-
- out vec2 outUV;
-
- uniform mat4 _modelMatrix;
- uniform mat4 _viewMatrix;
- uniform mat4 _projMatrix;
-
-
- void main()
- {
- gl_Position = _projMatrix * _viewMatrix * _modelMatrix * vec4(aPos.x, aPos.y, aPos.z, 1.0);
- outUV = aUV;
- };
- #version 330 core
- out vec4 FragColor;
-
- in vec2 outUV;
- in vec3 outFragPos;
- in vec3 outNormal;
-
- struct Material
- {
- vec3 m_ambient;
- vec3 m_diffuse;
- vec3 m_specular;
-
- float m_shiness;
- };
-
- uniform Material myMaterial;
-
- struct Light
- {
- vec3 m_pos;
- vec3 m_ambient;
- vec3 m_diffuse;
- vec3 m_specular;
- };
-
- uniform Light myLight;
-
-
- uniform sampler2D ourTexture;
- uniform vec3 view_pos;
-
- void main()
- {
- //环境光
- vec3 _ambient = myLight.m_ambient * myMaterial.m_ambient;
-
- //漫反射
- vec3 _normal = normalize(outNormal);
- vec3 _lightDir = normalize(myLight.m_pos - outFragPos);
- float _diff = max(dot(_normal , _lightDir) , 0.0f);
- vec3 _diffuse = myLight.m_diffuse * _diff * myMaterial.m_diffuse;
-
- //镜面反射
- float _specular_strength = 0.5;
- vec3 _viewDir = normalize(view_pos - outFragPos);
- vec3 _reflectDir = reflect(-_lightDir , outNormal);
-
- float _spec = pow(max(dot(_viewDir , _reflectDir) , 0.0f) , myMaterial.m_shiness);
-
- vec3 _sepcular = myLight.m_specular * _spec * myMaterial.m_specular;
-
-
- vec3 result = _ambient + _diffuse + _sepcular;
- FragColor = texture(ourTexture , outUV) * vec4(result ,1.0f);
- };
- #version 330 core
- out vec4 FragColor;
-
- in vec2 outUV;
-
- uniform sampler2D ourTexture;
-
- void main()
- {
- FragColor = vec4(1.0f , 1.0f ,1.0f ,1.0f );
- };
- void render()
- {
- glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
-
-
- _camera.update();
- _projMatrix = glm::perspective(glm::radians(45.0f), (float)_width / (float)_height, 0.1f, 100.0f);
- glm::mat4 _modelMatrix(1.0f);
- _modelMatrix = glm::translate(_modelMatrix, glm::vec3(0.0f, 0.0f, -3.0f));
- glBindTexture(GL_TEXTURE_2D, _texture);
-
- //物体shader
- _shader_cube.start();
- _shader_cube.setVec3("view_pos", _camera.getPosition());
-
- //传入光照属性
- light_color = glm::vec3((float)glfwGetTime() * 0.4f, (float)glfwGetTime() * 0.5f, (float)glfwGetTime() * 0.7f);
- _shader_cube.setVec3("myLight.m_ambient", light_color * glm::vec3(0.1f));
- _shader_cube.setVec3("myLight.m_diffuse", light_color * glm::vec3(0.7f));
- _shader_cube.setVec3("myLight.m_specular", light_color * glm::vec3(0.5f));
- _shader_cube.setVec3("myLight.m_pos", light_pos);
-
- //传入物体材质属性
- _shader_cube.setVec3("myMaterial.m_ambient", glm::vec3(0.1f));
- _shader_cube.setVec3("myMaterial.m_diffuse", glm::vec3(0.7f));
- _shader_cube.setVec3("myMaterial.m_specular", glm::vec3(0.8f));
- _shader_cube.setFloat("myMaterial.m_shiness", 32);
-
- _shader_cube.setMatrix("_modelMatrix", _modelMatrix);
- _shader_cube.setMatrix("_viewMatrix", _camera.getMatrix());
- _shader_cube.setMatrix("_projMatrix", _projMatrix);
- glBindVertexArray(VAO_cube);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- _shader_cube.end();
-
- //光源shader
- _shader_sun.start();
- _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
- _shader_sun.setMatrix("_viewMatrix", _camera.getMatrix());
- _shader_sun.setMatrix("_projMatrix", _projMatrix);
-
- _modelMatrix = glm::mat4(1.0f);
- _modelMatrix = glm::translate(_modelMatrix, light_pos);
- _shader_sun.setMatrix("_modelMatrix", _modelMatrix);
- glBindVertexArray(VAO_sun);
- glDrawArrays(GL_TRIANGLES, 0, 36);
- _shader_cube.end();
- }
