漫反射贴图
class Basic : public SubTestBed
{
protected:
::BaseCamera* m_Camera;
glm::mat4 m_Model = glm::identity<glm::mat4>();
std::string m_CubeShader = "SandBox/11_LightTexture/Basic.shader";
Material m_Material;
Light m_Light;
bool m_UseBreatheLight = true;
public:
virtual void Setup() override
{
#pragma region vertices
float vertices[] = {
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.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, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.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, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.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, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.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, 1.0f, 0.0f, 0.0f, 1.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, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.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, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.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, 0.0f, -1.0f, 0.0f, 0.0f, 0.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, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.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, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
#pragma endregion
m_VA[0] = new VertexArray();
m_VB[0] = new VertexBuffer(vertices, sizeof(vertices));
VertexBufferLayout layout;
layout.Push<float>(3);
layout.Push<float>(3);
layout.Push<float>(2);
m_VA[0]->AddBuffer(*m_VB[0], layout);
if (!m_TestScene)
{
TestScene::CameraData data;
data.eye = glm::vec3(-1.2f, 3.6f, 2.5f);
data.at = glm::vec3(1.5f, 0.3f, -1.6f);
data.up = glm::vec3(0.0f, 1.0f, 0.0f);
data.fov = 60.0f;
data.nearClip = 0.1f;
data.farClip = 100.0f;
m_TestScene = new TestScene(TestScene::FREE_CAMERA, data, TestScene::TT_DARK);
m_Camera = (::FreeCamera*)m_TestScene->Camera();
}
m_Model = glm::identity<glm::mat4>();
m_TestScene->Setup();
m_Shader[0] = new Shader(m_CubeShader);
m_Shader[0]->Bind();
m_Shader[0]->SetMat4f("u_Model", m_Model);
m_Texture[0] = new Texture("Resources/Textures/woodbox.png");
// 画表示光源的箱子
m_VA[1] = new VertexArray();
m_VB[1] = new VertexBuffer(vertices, sizeof(vertices));
layout.Clear();
layout.Push<float>(3);
layout.Push<float>(3);
layout.Push<float>(2);
m_VA[1]->AddBuffer(*m_VB[1], layout);
m_Shader[1] = new Shader("SandBox/09_Light/Light.shader");
m_VB[0]->UnBind();
m_VA[0]->UnBind();
m_VB[1]->UnBind();
m_VA[1]->UnBind();
m_Material.ambient = glm::vec3(1.0f, 0.5f, 0.31f);
m_Material.diffuse = glm::vec3(1.0f, 0.5f, 0.31f);
m_Material.specular = glm::vec3(0.5f, 0.5f, 0.5f);
m_Material.shininess = 32.0f;
m_Light.position = glm::vec3(1.2f, 1.0f, 2.0f);
m_Light.ambient = glm::vec3(0.2f, 0.2f, 0.2f);
m_Light.diffuse = glm::vec3(0.5f, 0.5f, 0.5f);
m_Light.specular = glm::vec3(1.0f, 1.0f, 1.0f);
m_UseBreatheLight = false;
}
#Shader Vertex
#version 330 core
layout(location = 0) in vec3 a_position;
layout(location = 1) in vec3 a_normal;
layout(location = 2) in vec2 a_texCoord;
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Projection;
out vec3 v3_Normal;
out vec3 v3_WorldPos;
out vec2 v2_TexCoord;
void main()
{
vec3 vertexPosition = a_position + vec3(0.0, 1.0, 0.0);
gl_Position = u_Projection * u_View * u_Model * vec4(vertexPosition, 1.0);
v3_WorldPos = vec3(u_Model * vec4(vertexPosition, 1.0));
v3_Normal = mat3(transpose(inverse(u_Model))) * a_normal;
v2_TexCoord = a_texCoord;
}
#Shader Fragment
#version 330 core
out vec4 fragColor;
in vec3 v3_Normal;
in vec3 v3_WorldPos;
in vec2 v2_TexCoord;
struct Material
{
sampler2D diffuse;
vec3 specular;
float shininess; // 反光度
};
uniform Material material;
struct Light
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
uniform vec3 u_ViewPos;
void main()
{
vec3 texColor = vec3(texture(material.diffuse, v2_TexCoord));
// 计算环境光
vec3 ambient = light.ambient * texColor;
// 计算漫反射 结果色彩 = 光线色彩 * cosθ θ = 顶点法线和光照方向的夹角
vec3 N = normalize(v3_Normal);
vec3 lightDir = normalize(light.position - v3_WorldPos);
float diff = max(dot(N, lightDir), 0.0);
vec3 diffuse = light.diffuse * (diff * texColor);
// 计算镜面反射 结果色彩 = 光线色彩 * (cosθ) ^ g
vec3 viewDir = normalize(u_ViewPos - v3_WorldPos);
vec3 reflectDir = reflect(-lightDir, N);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * (spec * material.specular);
vec3 result = ambient + diffuse + specular;
fragColor = vec4(result, 1.0);
}
高光贴图
class SpecularTexture : public Basic
{
public:
virtual void Setup() override
{
m_CubeShader = "SandBox/11_LightTexture/SpecularTexture.shader";
Basic::Setup();
m_Texture[1] = new Texture("Resources/Textures/woodbox_specular.png");
}
virtual void Render() override
{
m_Texture[0]->Bind(0);
m_Texture[1]->Bind(1);
this->m_Renderer.Draw(m_VA[0], 36, m_Shader[0]);
m_Shader[0]->SetMat4f("u_Projection", m_Camera->GetProjectionMatrix());
m_Shader[0]->SetMat4f("u_View", m_Camera->GetViewMatrix());
m_Shader[0]->SetVec3("u_ViewPos", m_Camera->GetEye());
m_Shader[0]->SetVec3("light.position", m_Light.position);
m_Shader[0]->SetVec3("light.ambient", m_Light.ambient);
m_Shader[0]->SetVec3("light.diffuse", m_Light.diffuse);
m_Shader[0]->SetVec3("light.specular", m_Light.specular);
m_Shader[0]->SetInt("material.diffuse", 0);
m_Shader[0]->SetInt("material.specular", 1);
m_Shader[0]->SetFloat("material.shininess", m_Material.shininess);
this->m_Renderer.Draw(m_VA[1], 36, m_Shader[1]);
m_Shader[1]->SetMat4f("u_Projection", m_Camera->GetProjectionMatrix());
m_Shader[1]->SetMat4f("u_View", m_Camera->GetViewMatrix());
m_Shader[1]->SetVec3("u_LightColor", 1.0f, 1.0f, 1.0f);
m_Model = glm::identity<glm::mat4>();
m_Model = glm::translate(m_Model, m_Light.position);
m_Model = glm::scale(m_Model, glm::vec3(0.2f));
m_Shader[1]->SetMat4f("u_Model", m_Model);
}
};
#Shader Vertex
// 同上
#Shader Fragment
#version 330 core
out vec4 fragColor;
in vec3 v3_Normal;
in vec3 v3_WorldPos;
in vec2 v2_TexCoord;
struct Material
{
sampler2D diffuse;
sampler2D specular;
float shininess; // 反光度
};
uniform Material material;
// ...略
void main()
{
vec3 diffuseColor = vec3(texture(material.diffuse, v2_TexCoord));
vec3 ambient = light.ambient * diffuseColor;
vec3 N = normalize(v3_Normal);
vec3 lightDir = normalize(light.position - v3_WorldPos);
float diff = max(dot(N, lightDir), 0.0);
vec3 diffuse = light.diffuse * (diff * diffuseColor);
vec3 specularColor = vec3(texture(material.specular, v2_TexCoord));
vec3 viewDir = normalize(u_ViewPos - v3_WorldPos);
vec3 reflectDir = reflect(-lightDir, N);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * (spec * specularColor);
vec3 result = ambient + diffuse + specular;
fragColor = vec4(result, 1.0);
}
放射光贴图
放射光贴图主要用来控制局部地区的光照强度,如机器人的眼睛,箱子上的灯带等
class EmissionMap : public Basic
{
public:
virtual void Setup() override
{
m_CubeShader = "SandBox/11_LightTexture/EmissionMap.shader";
Basic::Setup();
m_Texture[1] = new Texture("Resources/Textures/woodbox_specular.png");
m_Texture[2] = new Texture("Resources/Textures/matrix.jpg");
}
virtual void Render() override
{
m_Texture[0]->Bind(0);
m_Texture[1]->Bind(1);
m_Texture[2]->Bind(2);
this->m_Renderer.Draw(m_VA[0], 36, m_Shader[0]);
m_Shader[0]->SetMat4f("u_Projection", m_Camera->GetProjectionMatrix());
m_Shader[0]->SetMat4f("u_View", m_Camera->GetViewMatrix());
m_Shader[0]->SetVec3("u_ViewPos", m_Camera->GetEye());
m_Shader[0]->SetVec3("light.position", m_Light.position);
m_Shader[0]->SetVec3("light.ambient", m_Light.ambient);
m_Shader[0]->SetVec3("light.diffuse", m_Light.diffuse);
m_Shader[0]->SetVec3("light.specular", m_Light.specular);
m_Shader[0]->SetInt("material.diffuse", 0);
m_Shader[0]->SetInt("material.specular", 1);
m_Shader[0]->SetInt("material.emission", 2);
m_Shader[0]->SetFloat("material.shininess", m_Material.shininess);
// 灯光 ...略
}
};
// vertex shader同上
// fragment shader
// ...略
void main()
{
// ambient/diffuse/specular同上
vec3 emission = vec3(texture(material.emission, v2_TexCoord));
vec3 result = ambient + diffuse + specular + emission;
fragColor = vec4(result, 1.0);
}