Aquacolor

Aquacolor



LearningOpenGL【10】

Gumdrop · 2025-09-04 · 16浏览 · 未分类



正文之前补充两个重要知识点:

GLM库中使用如glm::translate(amat, xxx)的写法时,进行的是连续右乘操作!

lightModel = glm::translate(lightModel, lightPos);
lightModel = glm::scale(lightModel, glm::vec3(0.2f));
//lightModel = glm::translate(glm::mat4(1.0f), lightPos) * glm::scale(glm::mat4(1.0f), glm::vec3(0.2f)) * lightModel;

以上两个写法才是等价的。

shader程序中禁止修改in变量!

尽量通过有效的命名来区别开变量。

基础知识

Phone lighting model(有的也叫shading)

ambient、diffuse、specular,三者计算结果相加得到最终结果。

需要利用到shading point坐标(这里会叫做片段坐标)、lightDir、viewDir。

比较简陋的模型要使用物体颜色和光源颜色。

在比较完备的Phone光照模型中,三种光照会分别具有不同的颜色和强度,都需要传入shader。

物体颜色和光照颜色得到的反射颜色,在制作不同材质时将会是不相同的,但是通常会简单使用乘法进行颜色混合。

代码和解释

/// <summary>
/// 实现render loop。
/// </summary>
CameraState::lastTime = 0.0f;
CameraState::lastX = cwindow.width / 2.0;
CameraState::lastY = cwindow.height / 2.0;
CameraState::yaw = -90.0f;
CameraState::pitch = 0.0f;
CameraState::cameraPos = glm::vec3(0.0f, 0.0f, 10.0f);
CameraState::cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
CameraState::cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetFramebufferSizeCallback(window,
    [](GLFWwindow* window, int width, int height) {glViewport(0, 0, width, height); });
while (!glfwWindowShouldClose(window))
{
    processInput(window);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    glm::vec3 objectColor = glm::vec3(0.5f, 0.5f, 0.0f);
    glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);
    glm::vec3 lightPos = glm::vec3(2.0f, 1.5f, -1.0f);

    glm::mat4 model = glm::mat4(1.0f);
    glm::mat4 lightModel = glm::mat4(1.0f);
    lightModel = glm::translate(lightModel, lightPos);
    lightModel = glm::scale(lightModel, glm::vec3(0.2f));
    //lightModel = glm::translate(glm::mat4(1.0f), lightPos) * glm::scale(glm::mat4(1.0f), glm::vec3(0.2f)) * lightModel;
    glm::mat4 view = glm::mat4(1.0f);
    view = glm::lookAt(CameraState::cameraPos, CameraState::cameraPos + CameraState::cameraFront, CameraState::cameraUp);
    glm::mat4 projection = glm::mat4(1.0f);
    projection = glm::perspective(glm::radians(45.0f), (float)cwindow.width / cwindow.height, 0.1f, 100.0f);

    shader.use();
    glBindVertexArray(boxVAO);
    shader.setVec3("objectColor", glm::value_ptr(objectColor));
    shader.setVec3("lightColor", glm::value_ptr(lightColor));
    shader.setVec3("lightPos", glm::value_ptr(lightPos));
    shader.setVec3("viewPos", glm::value_ptr(CameraState::cameraPos));
    shader.setMat4("model", glm::value_ptr(model));
    shader.setMat4("view", glm::value_ptr(view));
    shader.setMat4("projection", glm::value_ptr(projection));
    glDrawArrays(GL_TRIANGLES, 0, 36);

    lightShader.use();
    glBindVertexArray(lightVAO);
    lightShader.setVec3("lightColor", glm::value_ptr(lightColor));
    lightShader.setMat4("model", glm::value_ptr(lightModel));
    lightShader.setMat4("view", glm::value_ptr(view));
    lightShader.setMat4("projection", glm::value_ptr(projection));
    glDrawArrays(GL_TRIANGLES, 0, 36);

    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    glfwSwapBuffers(window);
    glfwPollEvents();
}

可以发现我们链接了新的程序用来绘制光源物体。各种参数通常是使用uniform变量传入程序的。

//VertexShader.glsl
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 fragPos;
out vec3 normal;

void main()
{
    gl_Position = projection *view *model* vec4(aPos, 1.0);
    fragPos = vec3(model* vec4(aPos, 1.0f));
    normal = aNormal;
}

//FragmentShader.glsl
#version 330 core  

in vec3 fragPos;
in vec3 normal;

out vec4 fragColor;

uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;

void main()
{
    float ambientStrength = 0.1f;
    float diffuseStrength = 0.7f;
    float specularStrength = 0.5f;

    vec3 norm = normalize(normal);
    vec3 lightDir = normalize(lightPos - fragPos);
    vec3 viewDir = normalize(viewPos - fragPos);
    float diffuseCos = max(dot(lightDir, norm), 0.0f);
    float specularCos = max(dot(reflect(-lightDir, norm), viewDir), 0.0f);

    float ambient = ambientStrength;
    float diffuse = diffuseStrength * diffuseCos;
    float specular = specularStrength * pow(specularCos, 32);
    fragColor = vec4((ambient + diffuse + specular) * lightColor * objectColor, 1.0f);
}

(各部分光照的计算表达式不再打一次了,除了数学问题之外没什么问题,但是忘记截图了所以没图)

使用GLSL结构体表示材质

物体颜色和光照颜色得到的反射颜色,在制作不同材质时将会是不相同的。

使用了“材质”的语言概念,将会改变光照模型的计算方式。

在上面的shader中,其实三部分是同色的,只是强度不同。(每个片段的颜色都是lightColor*objectColor乘以系数)

使用了材质的shader,其各部分颜色为partStrength*lightColor*partColor再乘其他因式,不同部分因式不同。

这能够使三部分各自有各自颜色,形成更丰富的光照效果。

#version 330 core

struct Material{
    vec3 ambientCS;
    vec3 diffuseCS;
    vec3 specularCS;
    float shininess;
};

in vec3 FragPos;
in vec3 Normal;

out vec4 FragColor;

uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform Material material;

void main()
{
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    vec3 viewDir = normalize(viewPos - FragPos);
    // Ambient
    vec3 ambient = material.ambientCS;
    // Diffuse
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = material.diffuseCS * diff;
    // Specular
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = material.specularCS * spec;
    // Combine
    FragColor = vec4(ambient + diffuse + specular, 1.0);
}

renderloop如果要对shader中的结构体对象传值,需要把对象名像名字空间一样使用。

shader.setFloat("material.shininess", specularShininess);

2025-09-04T13:13:57.png

用同样的方式使用光源结构

虽然这能使自定义程度进一步提高,但是光源和物体都对lighting结果有影响时,其结果不能简单预测。

使用物体颜色作为材质高光、光源颜色作为光源高光部分,结果用乘法计算。

2025-09-05T10:28:58.png

都用光源颜色计算高光部分。

2025-09-05T10:28:20.png

在乘法混合颜色的模型中,通常以一个颜色作为原本的颜色,而另一个颜色视为对原颜色的滤波。

(下一部分的光照模型中,纹理颜色将作为原颜色被光源颜色滤波(ambient、diffuse),而高光部分仅由光源颜色计算不被滤波)



©

comment 评论区

添加新评论

face表情



  • ©2026 bilibili.com

textsms
内容不能为空
昵称不能为空
email
邮件地址格式错误
web
beach_access
验证码不能为空
keyboard发表评论


star_outline 咱快来抢个沙发吧!




©2026 Aquacolor

Theme Romanticism2.2 by Akashi
Powered by Typecho