OpenGL-不现实的每片段点光源
在这里,您可以看到由点光源照亮的平面组成的场景。在自然界中,每个“碎片”的亮度在很大程度上取决于它与光源的距离,我希望在这里看到从一面墙到另一面墙的平滑过渡 唯一的可变因素是顶点法线,毫无疑问,它们导致了颜色的急剧变化。怎样才能更真实地照亮房间 顶点着色器OpenGL-不现实的每片段点光源,opengl,glsl,Opengl,Glsl,在这里,您可以看到由点光源照亮的平面组成的场景。在自然界中,每个“碎片”的亮度在很大程度上取决于它与光源的距离,我希望在这里看到从一面墙到另一面墙的平滑过渡 唯一的可变因素是顶点法线,毫无疑问,它们导致了颜色的急剧变化。怎样才能更真实地照亮房间 顶点着色器 #version 330 precision highp float; uniform mat4 projection_matrix; uniform mat4 model_matrix; uniform mat4 view_matri
#version 330
precision highp float;
uniform mat4 projection_matrix;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
in vec3 vert_position;
in vec2 vert_texcoord;
in vec3 vert_normal;
out vec3 frag_normal;
out vec2 frag_texcoord;
uniform vec3 LightPosition;
out vec3 toLightVector;
void main(void)
{
vec4 world_position = model_matrix * vec4(vert_position, 1);
frag_texcoord = vert_texcoord;
frag_normal = (model_matrix * vec4(vert_normal, 0)).xyz;
toLightVector = LightPosition - world_position.xyz;
gl_Position = projection_matrix * view_matrix * world_position;
}
片段着色器
#version 330
precision highp float;
in vec3 frag_normal;
in vec2 frag_texcoord;
in vec3 toLightVector;
uniform sampler2D MyTexture0;
uniform vec3 LightColour;
uniform vec3 LightAttenuation;
out vec4 finalColor;
void main(void)
{
float distance = length(toLightVector);
float attFactor = LightAttenuation.x + (LightAttenuation.y * distance) + (LightAttenuation.z * distance * distance);
vec3 unitNormal = normalize(frag_normal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0);
vec3 diffuse = (brightness * LightColour) / attFactor;
finalColor = vec4(diffuse, 1.0) * texture(MyTexture0, frag_texcoord);
}
只需将更多的权重放在距离上,而将更少的权重放在法线上。使光衰减看起来更像(0,0,1)。您的问题在于您对照明模型的期望 照明模型的行为与预期完全一致。但这只是现实的一个模型,一个近似值 真实照明远比简单的点积和衰减复杂得多。这是一个高度复杂的相互作用之间的许多和许多小光源等。这就解释了为什么在现实生活中你(通常)看不到照明的这种不连续性
解决此问题的正确方法不是更改衰减或法线。这是为了研究更精确的照明模型。你不会喜欢这个Nicol Bolas,但会简化计算,使其完全取决于距离,提供的正是我想要的效果 在设计和美学上轻描淡写会毁掉任何一件艺术品,但我要说的是,我不是在写《末日4》,我是在写一个无赖 片段着色器
#version 330
precision highp float;
in vec2 frag_texcoord;
in vec3 toLightVector;
uniform sampler2D MyTexture0;
uniform vec3 LightColour;
uniform vec3 LightAttenuation;
out vec4 finalColor;
void main(void)
{
float distance = length(toLightVector);
float attFactor = LightAttenuation.x + (LightAttenuation.y * distance) + (LightAttenuation.z * distance * distance);
vec3 diffuse = (LightColour) / attFactor;
finalColor = vec4(diffuse, 1.0) * texture(MyTexture0, frag_texcoord);
}
可能与此无关,但值得一提:你用模型矩阵的值变换法线吗?不,我没有,我只是为每个顶点传递一个标准化的方向向量。我有一个向量3数组,每个平面有4个相同的法线,我如何用逆模型矩阵来转换它?”每个碎片的亮度由它与源的距离决定“不,不是。这可能是决定的一部分,但法线和光线方向的点积也非常重要。如果你的正常是不连续的,没有理由期望灯光也会这样。我的问题是修辞,我真正的意思是:这是另一件需要考虑的事情。我不知道你的代码出了什么问题,但正如尼科尔指出的那样,当心被现实生活中的光学所欺骗,你没有光能传递或环境遮挡,光线非常强烈。我明白了,正是法线的急剧变化造成了颜色的急剧变化。将每个顶点朝向其父平面的中心45°是否会创建平滑过渡?我很感激你的建议,但我正在寻找一个永久的解决方案。你能推荐一个更精确的模型吗?最终目标是在预处理过程中将每面墙的照明信息写入光照贴图,如果这样做会产生影响的话。@livin_amuk:如果这是你的目标,那么OpenGL可能是错误的工具。你想要的是某种基于光能传递的照明系统。在CPU上生成结果需要很长时间,但这是一个离线过程。我不是使用着色器生成光照贴图,而是在CPU上使用与着色器相同的算法生成光照贴图。这样,静态环境将具有与动态照明对象相同的亮度。因此。。。你的问题是你的照明模型看起来不真实。因此,答案是去掉照明模型的实际照明模型部分,将其转换为一个值乘以一个距离?怎么会有人认为让事情变得不那么现实是一个有效的答案呢?你知道,战争并不总是必须的。我的问题清楚地表明了哪些方面困扰着我。无论如何,感谢你的投入,你是明智的,是这个社区的宝贵资源。