漫反射贴图
完整代码:https://github.com/DXT00/LearnOpenGL_study/tree/a9082da982458111eb505a22e92bcb4146bd8ee7
在着色器中使用漫反射贴图的方法和纹理教程中是完全一样的。但这次我们会将纹理储存为Material结构体中的一个sampler2D
。我们将之前定义的vec3
漫反射颜色向量替换为漫反射贴图.
struct Material{
vec3 ambient;
sampler2D diffuse;
vec3 specular;
float shininess;
};
fragment shader:
#type fragment
#version 330 core
struct Material{
vec3 ambient;
sampler2D diffuse;
vec3 specular;
float shininess;
};
out vec4 FragColor;
float ambientStrength = 0.1f;
float specularStrength = 1.0f;
//uniform float u_shininessStrength;//反光度因子,可以是2,4,8,16,..256,一个物体的反光度越高,反射光的能力越强,散射得越少,高光点就会越小
in vec2 v_TexCoord;
in vec3 v_Normal;
in vec3 v_FragPos;
uniform Material u_Material;
uniform sampler2D u_Texture1;
uniform sampler2D u_Texture2;
uniform float u_MixValue;
uniform vec3 u_LightColor;
uniform vec3 u_LightPos;
uniform vec3 u_CameraViewPos;
//ambient
vec3 ambient = u_LightColor * u_Material.ambient* texture(u_Material.diffuse,v_TexCoord).rgb;//u_LightColor * u_Material.ambient
//diffuse
vec3 lightDir = normalize(u_LightPos-v_FragPos);
vec3 norm = normalize(v_Normal);
float diff = max(dot(lightDir,norm),0.0f);
vec3 diffuse = u_LightColor * diff * texture(u_Material.diffuse,v_TexCoord).rgb;// u_Material.diffuse);u_LightColor
//specular
vec3 reflectDir = normalize(reflect(-lightDir,norm));
vec3 viewDir = normalize(u_CameraViewPos-v_FragPos);
float spec = pow(max(dot(reflectDir,viewDir),0.0),u_Material.shininess);
vec3 specular = u_LightColor * spec * u_Material.specular;
void main(){
FragColor = vec4((diffuse + ambient + specular),1.0);// * mix(texture(u_Texture1, v_TexCoord), texture(u_Texture2, vec2(1.0 - v_TexCoord.x, v_TexCoord.y)), u_MixValue);
}
在Application.cpp中添加一个 DiffuseMap的纹理:
m_DiffuseMap.reset(new Texture("assets/texture/container2.png"));
并设置Uniform
由于之前已经有两个纹理了,所以DiffuseMap绑定为2号纹理:
m_Shader->SetUniform1i("u_Material.diffuse", 2);
renderer loop:
//render loop
while (!glfwWindowShouldClose(m_Window->GetNativeWindow())) {
float time = (float)glfwGetTime();
Timestep ts = time - m_LastFrameTime;
m_LastFrameTime = time;
InputCheck(ts);
if (glfwGetKey(m_Window->GetNativeWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(m_Window->GetNativeWindow(), true);
// render
// ------
//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// bind textures on corresponding texture units
glActiveTexture(GL_TEXTURE0);
m_Texture1->Bind();
glActiveTexture(GL_TEXTURE1);
m_Texture2->Bind();
glActiveTexture(GL_TEXTURE2);
m_DiffuseMap->Bind();
Renderer::BeginScene(*m_Camera);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, m_LightSource->GetPosition());
model = glm::scale(model, glm::vec3(0.5f));
Renderer::Submit(m_LightSource->GetVertexArray(), m_LightSource->GetShader(), model);
glDrawArrays(GL_TRIANGLES, 0, 36);
for (unsigned int i = 0; i < 10; i++)
{
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, cubePositions[i]);
model = glm::rotate(model, (float)(glfwGetTime()), glm::vec3(1.0f, (float)i * 20, 0.0f));//(float)(glfwGetTime())
m_Shader->SetUniformMat4f("u_TranInverseModel", glm::transpose(glm::inverse(model)));
m_Shader->SetUniformVec3f("u_CameraViewPos", m_Camera->GetPosition());
//glm::vec3 lightColor;// = m_LightSource->GetLightColor();
//lightColor.x = sin(glfwGetTime() * 2.0f);
//lightColor.y = sin(glfwGetTime() * 0.7f);
//lightColor.z = sin(glfwGetTime() * 1.3f);
m_Shader->SetUniformVec3f("u_LightColor", m_LightSource->GetLightColor());
m_Shader->SetUniformVec3f("u_Material.ambient", glm::vec3(0.25,0.20725,0.20725));
m_Shader->SetUniform1i("u_Material.diffuse", 2);
//m_Shader->SetUniformVec3f("u_Material.diffuse", glm::vec3(1 ,0.829 ,0.829));
m_Shader->SetUniformVec3f("u_Material.specular", glm::vec3(0.5, 0.5,0.5));
m_Shader->SetUniform1f("u_Material.shininess",64.0f);
Renderer::Submit(m_VertexArray, m_Shader, model);
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glfwSwapBuffers(m_Window->GetNativeWindow());
glfwPollEvents();
}
镜面光贴图:
你可能会注意到,镜面高光看起来有些奇怪,因为我们的物体大部分都是木头,我们知道木头不应该有这么强的镜面高光的。我们可以将物体的镜面光材质设置为vec3(0.0)
来解决这个问题,但这也意味着箱子钢制的边框将不再能够显示镜面高光了,我们知道钢铁应该是有一些镜面高光的。所以,我们想要让物体的某些部分以不同的强度显示镜面高光。
镜面光贴图上的每个像素都可以由一个颜色向量来表示,比如说黑色代表颜色向量vec3(0.0)
,灰色代表颜色向量vec3(0.5)
。在片段着色器中,我们接下来会取样对应的颜色值并将它乘以光源的镜面强度。一个像素越「白」,乘积就会越大,物体的镜面光分量就会越亮
由于箱子大部分都由木头所组成,而且木头材质应该没有镜面高光,所以漫反射纹理的整个木头部分全部都转换成了黑色。箱子钢制边框的镜面光强度是有细微变化的,钢铁本身会比较容易受到镜面高光的影响,而裂缝则不会。
把u_Material 的 specular设置为贴图--》Sampler2D
struct Material{
vec3 ambient;
sampler2D diffuse;
sampler2D specular;
float shininess;
};
Application 添加 SpecularMap
m_Shader->SetUniform1i("u_Material.specular", 3);
m_SpecularMap.reset(new Texture("assets/texture/container2_specular.png"));
放射光贴图
对物体的发光部分贴图
完整代码:https://github.com/DXT00/LearnOpenGL_study/tree/e0127d6525036402a0d32319ddbe2144d4226a3a
//ambient
vec3 ambient = u_LightColor * u_Material.ambient* texture(u_Material.diffuse,v_TexCoord).rgb;//u_LightColor * u_Material.ambient
//diffuse
vec3 lightDir = normalize(u_LightPos-v_FragPos);
vec3 norm = normalize(v_Normal);
float diff = max(dot(lightDir,norm),0.0f);
vec3 diffuse = u_LightColor * diff * texture(u_Material.diffuse,v_TexCoord).rgb;// u_Material.diffuse);u_LightColor
//specular
vec3 reflectDir = normalize(reflect(-lightDir,norm));
vec3 viewDir = normalize(u_CameraViewPos-v_FragPos);
float spec = pow(max(dot(reflectDir,viewDir),0.0),u_Material.shininess);
vec3 specular = u_LightColor * spec * texture(u_Material.specular,v_TexCoord).rgb;
//emission
vec3 emission = texture(u_Material.emission,v_TexCoord).rgb;
void main(){
FragColor = vec4((diffuse + ambient + specular + emission),1.0);// * mix(texture(u_Texture1, v_TexCoord), texture(u_Texture2, vec2(1.0 - v_TexCoord.x, v_TexCoord.y)), u_MixValue);
}
m_EmissionMap.reset(new Texture("assets/texture/matrix.jpg"));
m_Shader->SetUniform1i("u_Material.emission", 4);