我有一个像这样实现阴影贴图的着色器:
#version 430 core
out vec4 color;
in VS_OUT {
vec3 N;
vec3 L;
vec3 V;
vec4 shadow_coord;
} fs_in;
layout(binding = 0) uniform sampler2DShadow shadow_tex;
uniform vec3 light_ambient_albedo = vec3(1.0);
uniform vec3 light_diffuse_albedo = vec3(1.0);
uniform vec3 light_specular_albedo = vec3(1.0);
uniform vec3 ambient_albedo = vec3(0.1, 0.1, 0.2);
uniform vec3 diffuse_albedo = vec3(0.4, 0.4, 0.8);
uniform vec3 specular_albedo = vec3(0.0, 0.0, 0.0);
uniform float specular_power = 128.0;
void main(void) {
//color = vec4(0.4, 0.4, 0.8, 1.0);
//normalize
vec3 N = normalize(fs_in.N);
vec3 L = normalize(fs_in.L);
vec3 V = normalize(fs_in.V);
//calculate R
vec3 R = reflect(-L, N);
//calcualte ambient
vec3 ambient = ambient_albedo * light_ambient_albedo;
//calculate diffuse
vec3 diffuse = max(dot(N, L), 0.0) * diffuse_albedo * light_diffuse_albedo;
//calcualte spcular
vec3 specular = pow(max(dot(R, V), 0.0), specular_power) * specular_albedo * light_specular_albedo;
//write color
color = textureProj(shadow_tex, fs_in.shadow_coord) * vec4(ambient + diffuse + specular, 0.5);
//if in shadow, then multiply color by 0.5 ^^, except alpha
}
我想要做的是首先检查片段是否确实在阴影中,只有然后更改颜色(将其减半,使其变为全黑和原始颜色的中间)
但是如何检查textureProj(...)
结果是否确实在阴影中,据我所知它会返回一个标准化的float
值。
像textureProj(...) > 0.9999
这样的东西已经足够吗?我知道如果你使用多重采样它可以返回零或一个以外的值,我想要的行为不会只是在某一点上断。
输出顶点着色器:
#version 430 core
layout(location = 0) in vec4 position;
layout(location = 0) uniform mat4 model_matrix;
layout(location = 1) uniform mat4 view_matrix;
layout(location = 2) uniform mat4 proj_matrix;
layout(location = 3) uniform mat4 shadow_matrix;
out VS_OUT {
vec3 N;
vec3 L;
vec3 V;
vec4 shadow_coord;
} vs_out;
uniform vec4 light_pos = vec4(-20.0, 7.5, -20.0, 1.0);
void main(void) {
vec4 local_light_pos = view_matrix * light_pos;
vec4 p = view_matrix * model_matrix * position;
//normal
vs_out.N = vec3(0.0, 1.0, 0.0);
//light vector
vs_out.L = local_light_pos.xyz - p.xyz;
//view vector
vs_out.V = -p.xyz;
//light space coordinates
vs_out.shadow_coord = shadow_matrix * position;
gl_Position = proj_matrix * p;
}
请注意,片段着色器用于地形,顶点着色器用于地板,因此两者之间可能存在轻微的不一致,但它们应该是不相关的。
shadow_matrix
是以bias_matrix * light_projection_matrix * light_view_matrix * light_model_matrix
传入的制服。
答案 0 :(得分:4)
textureProj (...)
不返回标准化的浮点值。如果您在float
上使用它,它会返回一个sampler<1D|2D|2DRect>Shadow
,但此值代表深度测试的结果。 1.0 =通过, 0.0 =失败。
现在,这里要注意的有趣的事情,以及为阴影采样器返回float
的原因是有意义的,这与过滤阴影贴图有关。如果您在阴影贴图上使用GL_LINEAR
滤镜模式以及阴影采样器,GL将实际选择阴影贴图中最近的4个纹素,并执行4次独立的深度测试。
每个深度测试 仍 具有二进制结果,但GL将返回所有4个测试结果的加权平均值(基于距理想样本位置的距离) 。因此,如果您将GL_LINEAR
与阴影采样器结合使用,您将拥有一个位于 0.0 和 1.0 之间的值,表示平均遮挡4个最近的深度样本。
我应该指出,使用textureProj (...)
对我来说可能是错误的。它使用的坐标是一个4D向量,由(s
,t
,r
)[投影坐标]和(q
)[要测试的深度值]组成。我没有在您的代码中看到您为q
指定深度值的任何位置。如果您可以编辑问题以包含输出shadow_coord
的顶点/几何着色器,那将有所帮助。
答案 1 :(得分:1)
尝试以下方法:
获取模型每个顶点到灯光的距离。
将此距离发送到片段着色器。
将距离与阴影贴图采样器中存储的值进行比较(我假设此纹理从相机的角度存储场景的深度值?)
如果距离大于采样器,则该点处于阴影中。否则,它不是。
如果这令人困惑,这里有一对应该有用的教程: http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html http://ogldev.atspace.co.uk/www/tutorial24/tutorial24.html