OpenGL,漫反射着色器

Posted

技术标签:

【中文标题】OpenGL,漫反射着色器【英文标题】:OpenGL, diffuse shader 【发布时间】:2013-09-19 18:47:04 【问题描述】:

我正在尝试在 GLSL/openGL 中实现非常简单的漫反射着色器。 这是我得到的: 顶点着色器:

#version 130

in vec3 vertPos3D;
in vec3 vertNormal3D;

uniform mat3 transpMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;

uniform vec3 lightPosition;

varying vec3 vertNormal;
varying vec3 lightVector;

void main() 
 
    vec4 res_pos = projectionMatrix * viewMatrix * vec4(vertPos3D.xyz, 1.0);
    gl_Position = res_pos;
    mat4 pm = projectionMatrix * viewMatrix;
    vertNormal = (viewMatrix * vec4(vertNormal3D, 0)).xyz;
    lightVector = (viewMatrix * vec4(lightPosition, 1.0)).xyz - (viewMatrix * vec4(vertPos3D.xyz, 1.0)).xyz;

片段着色器:

#version 130
out vec4 color; 

varying vec3 lightVector;
varying vec3 vertNormal;
void main()

    float dot_product = max(normalize(dot(lightVector, vertNormal)), 0.0);
    color = dot_product * vec4( 1.0, 1.0, 1.0, 1.0 );

一旦我将最终颜色与 dot_product 相乘,什么都不会显示。我删除了 dot_product,一切正常(除了漫反射闪电)。恐怕我错过了一些明显的东西。

【问题讨论】:

着色器编译/链接日志中的任何内容? 【参考方案1】:

一个问题:

normalize(dot(lightVector, vertNormal))

GLSL 1.3 中的dot 返回浮点数。normalize 接受向量,而不是浮点数。documentation for dotdocumentation for normalize

至少解决这个问题:

在片段着色器中,替换

float dot_product = max(normalize(dot(lightVector, vertNormal)), 0.0);

float dot_product = clamp(dot(lightVector, vertNormal), 0, 1);

您似乎正在使用 max 和 normalize 来避免从 dot 返回的负数。这正是clamp 的用途。这是documentation for clamp

【讨论】:

感谢您的建议,我更改了那行代码,但总体上没有任何改变。 :( 哦,等待您使用 GLSL 1.3,因此请尝试在顶点着色器和片段着色器中将 in 切换为 attribute,并在片段着色器中移除 out vec4 color; 并将 color 替换为 gl_FragColor跨度> 恐怕没有 好的,片段着色器中的varying 应该是attribute,因为它是输入而不是输出。我编辑了上面的代码。现在可以用了吗? 实际上 1.30 已经有了in/out,所以无论如何都要丢弃所有这些已弃用的attribute/varying 垃圾。【参考方案2】:

使用

float dot_product = max(dot(normalize(lightVector), normalize(normalVector)), 0.0);

Dylan Holmes 的回答略有错误:

仍然需要对 lightVector 进行归一化!

并且不需要夹紧。 max 是正确的。如果输入向量被归一化,点积永远不会返回高于 1.0 的值。

【讨论】:

准确地说:“点积永远不会返回高于 1.0 的值”仅当向量被归一化时才为真,并且 vertNormal 仍然需要归一化,因为它是插值,而不是应用程序呈现的正常值。 在您发表评论之前,我将此信息添加到有关点积的答案中。着色器编程对我来说是几年前的事了,所以我不确定是否有必要。 @djmj normalizing 确实让我忘记了,感谢您指出有关钳位/最大值的问题。

以上是关于OpenGL,漫反射着色器的主要内容,如果未能解决你的问题,请参考以下文章

实现每个顶点的漫反射着色器,不起作用

OpenGL片段着色器不照亮场景

OpenGL 3着色器错误[关闭]

此像素着色器中的漫反射和镜面反射

OpenGL/C++:将多个纹理传递给一个着色器的问题

[Unity Shader] 逐顶点光照和逐片元光照