计算机图形学 || 基础光照之冯氏光照模型

8 篇文章 0 订阅
8 篇文章 1 订阅

Basic:

1. Phong光照模型:

组成分量:

  • 环境光照(Ambient Lighting)
    • 即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
// ambient
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;

hw63

  • 漫反射光照(Diffuse Lighting)
    • 模拟光源对物体的方向性影响(Directional Impact)。它是冯氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

hw64

  • 镜面光照(Specular Lighting)
    • 模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。
// specular
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
// 高光的反光度32
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;

hw65

2. Gouraud Shading:

Gouraud 光照模型和 Phong 光照模型的区别在于: Gouraud 是在顶点着色器中实现的,而 Phong 是在片段着色器中实现。 相比较之下 Gouraud 光照模型做光照因为顶点数少于片段数,所以会更高效,开销更低。但顶点着色器中的最终颜色值仅仅是该顶点的颜色值,片段的颜色值是由插值光照颜色得来的,因此光照效果会显得不够真实。

  • gouraud.vs
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 LightingColor; // resulting color from lighting calculations
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform float ambientStrength;
uniform float diffuseStrength;
uniform float specularStrength;
uniform int reflectance;
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0); 
    // gouraud shading
    // ------------------------
    vec3 Position = vec3(model * vec4(aPos, 1.0));
    vec3 Normal = mat3(transpose(inverse(model))) * aNormal;
    // ambient
    vec3 ambient = ambientStrength * lightColor;
    // diffuse
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - Position);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diffuseStrength * diff * lightColor;
    // specular
    vec3 viewDir = normalize(viewPos - Position);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), reflectance);
    vec3 specular = specularStrength * spec * lightColor;
    
    LightingColor = ambient + diffuse + specular;
}
  • gouraud.fs
#version 330 core
out vec4 FragColor;
in vec3 LightingColor;
uniform vec3 objectColor;
void main()
{
    FragColor = vec4(LightingColor * objectColor, 1.0);
}

hw66

hw67

通过两张图比较可以明显看出区别,其中在 Gouraud 光照模型中可以看到“条纹”。可以看到立方体正面的右上角被高光照亮。由于右下角三角形的右上顶点是亮的,而三角形的其他两个顶点不是亮的,所以亮值内插到其他两个顶点。左上角的三角形也是如此。由于中间碎片的颜色不是直接来自光源,而是插值的结果,中间碎片的光照是不正确的,左上角和右下角的三角形在亮度上发生碰撞,导致两个三角形之间出现可见的条纹。

3. 使用GUI,使参数可调节,效果实时更改
a. GUI里可以切换两种shading。
ImGui::NewFrame();
{
    ImGui::Begin("HW6_WPY", &tool_active, ImGuiWindowFlags_MenuBar);
    if (ImGui::BeginMenuBar())
    {
        if (ImGui::BeginMenu("Menu"))
        {
            if (ImGui::MenuItem("Phong Shading")) {
                phong = true;
                gouraud = false;
            }
            if (ImGui::MenuItem("Gouraud Shading")) {
                gouraud = true;
                phong = false;
            }
            if (ImGui::MenuItem("Close")) {
                tool_active = false;
                glfwSetWindowShouldClose(window, true);//关闭窗口
            }
            ImGui::EndMenu();
        }
        ImGui::EndMenuBar();
    }

hw68

hw69

b. 使用如进度条这样的控件,使ambient因子、diffuse因子、specular因子、反光度等参数可调节,光照效果实时更改。
if (phong)
{
    ImGui::Text("1.Phong Shading");
    ImGui::Text("change the ambient strength");
    ImGui::SliderFloat("ambient strength", &ambient, 0.0f, 1.0f);
    ImGui::Text("change the diffuse strength");
    ImGui::SliderFloat("diffuse strength", &diffuse, 0.0f, 5.0f);
    ImGui::Text("change the specular strength");
    ImGui::SliderFloat("specular strength", &specular, 0.0f, 10.0f);
    ImGui::Text("change the reflectance");
    ImGui::SliderInt("reflectance", &reflectance, 2, 256);
}
phongObject.setFloat("ambientStrength", ambient);
phongObject.setFloat("diffuseStrength", diffuse);
phongObject.setFloat("specularStrength", specular);
phongObject.setInt("reflectance", reflectance);
uniform float ambientStrength;
uniform float diffuseStrength;
uniform float specularStrength;
uniform int reflectance;

ambient因子:

can11

can12

diffuse因子:

can21

can22

specular因子:

can31

can32

反光度:

can41

can42

Bonus:

当前光源为静止状态,尝试使光源在场景中来回移动,光照效果实时更改。
float radius = 1.0f;
float X = sin(glfwGetTime()) * radius;
float Z = cos(glfwGetTime()) * radius;
lightPos = glm::vec3(X, 0.0f, Z);

hw62.gif
github地址:https://github.com/WangPerryWPY/Computer_Graphics/tree/master/HW6

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
games101作业3 是一项关于计算机图形图像技术的作业。 这个作业要求学生实现一个简单的三维渲染器,它能够将三维模型渲染成二维图像。 要完成这个作业,首先需要了解三维渲染的基本原理。三维渲染主要涉及光照、材质、几何变换和纹理等方面的知识。学生需要掌握顶点着色器和片段着色器的工作原理,理解如何使用着色器计算光照和阴影效果。 在实现渲染器之前,学生需要加载一个三维模型并解析它的几何信息和材质信息。模型可能是从文件中读取的,常见的格式有Obj和FBX等。学生需要编写代码将模型中的顶点、法线和纹理坐标等信息读入内存中,并构建顶点缓冲区。 接下来,学生需要编写顶点着色器和片段着色器。顶点着色器负责对顶点进行变换,并计算逐顶点的光照。片段着色器则负责在屏幕空间进行插值,并计算逐像素的光照和纹理颜色。 实现渲染器的核心部分是三维几何变换和光照计算。学生需要掌握如何进行坐标变换、投影变换和视口变换,以及如何实现光照模型,如冯氏光照模型、阴影算法等。 最后,学生需要将渲染结果输出到屏幕上。这可以通过将纹理贴图到屏幕上或直接绘制颜色缓冲区来实现。 总的来说,games101作业3 是一个涉及三维渲染技术的作业。通过实现一个简单的三维渲染器,学生可以掌握三维图形渲染的基本原理和技术。这对于理解计算机图形图像技术和深入学习三维图形学非常有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值