[OpenGL]光照贴图

漫反射贴图
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);
}

放射光贴图

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像