我有一个在延迟渲染器中执行光照传递的着色器。它需要各种可选功能的制服,其中一个是阴影。
我想使用相同的着色器来执行带有阴影的光照(请参阅我的其他问题here)。这很有效。
然而,当我渲染没有阴影的光时会出现问题,因此不要将任何纹理绑定到阴影采样器,而是保留一些其他纹理。在我的系统上运行NVIDIA 346.59驱动程序时,会产生以下GL错误/警告:
编程未定义的行为警告:采样器对象0绑定到非深度纹理0,但它与使用阴影采样器的程序一起使用。这是未定义的行为。
即使我知道在这种情况下也不会使用采样器。
有没有办法解决这个问题?似乎没有必要绑定一些未使用的占位符纹理只是为了抑制此警告。
编辑:请注意,这确实有效。唯一的问题是司机吐出的警告。
编辑:好的,这是我的着色器。与此问题相关的部分是main()函数。#version 330
#extension GL_ARB_shading_language_420pack : enable
#include "headers/blocks/camera"
#include "headers/blocks/spotlight"
#include "headers/uniform_disks"
#include "headers/shadow/sample_spot"
in vec2 texcrd;
layout(std140, binding=0) uniform CAMERABLOCK { CameraBlock CB; };
layout(std140, binding=1) uniform SPOTLIGHTBLOCK { SpotLightBlock LB; };
uniform int mode;
uniform int shadQuality;
uniform int shadFilter;
layout(binding=0) uniform sampler2D texDiff;
layout(binding=1) uniform sampler2D texNorm;
layout(binding=2) uniform sampler2D texSurf;
layout(binding=3) uniform sampler2D texSpec;
layout(binding=4) uniform sampler2D texAmbi;
layout(binding=5) uniform sampler2D texDepth;
layout(binding=6) uniform sampler2DShadow texShad;
out vec3 fragColour;
vec3 get_view_pos(in vec2 _tc) {
float dep = texture(texDepth, _tc).r * 2.f - 1.f;
vec4 p_pos = vec4(_tc * 2.f - 1.f, dep, 1.f);
vec4 v_pos = CB.invProj * p_pos;
return v_pos.xyz / v_pos.w;
}
float get_shadow_value(vec3 _wpos, vec3 _wsurf) {
vec3 normPos = _wpos + _wsurf*0.04f;
vec4 sc = LB.matrix * vec4(normPos, 1.f);
vec3 shadcrd = sc.xyz / sc.w * 0.5f + 0.5f;
float bias = get_bias(_wsurf, normalize(normPos - LB.position));
if (shadFilter < 2) return sample_shadow(shadcrd, bias, texShad);
else {
if (shadQuality == 0) return sample_shadow_x4(shadcrd, bias, texShad);
if (shadQuality == 1) return sample_shadow_x8(shadcrd, bias, texShad);
if (shadQuality == 2) return sample_shadow_x16(shadcrd, bias, texShad);
}
}
vec3 get_diffuse_value(vec3 _lightDir, vec3 _normal) {
vec3 txDiff = texture(texDiff, texcrd).rgb;
float dotProd = max(dot(-_lightDir, _normal), 0.f);
return LB.colour * txDiff * dotProd;
}
vec3 get_specular_value(vec3 _lightDir, vec3 _normal, vec3 _position) {
vec3 txSpec = texture(texSpec, texcrd).rgb;
vec3 reflection = reflect(_lightDir, _normal);
vec3 dirFromCam = normalize(-_position);
float factor = pow(max(dot(dirFromCam, reflection), 0.f), 50.f);
return LB.colour * txSpec * factor;
}
void main() {
vec3 v_pos = get_view_pos(texcrd);
vec3 v_norm = normalize(texture(texNorm, texcrd).rgb * 2.f - 1.f);
vec3 lightDir = normalize(v_pos - vec3(CB.view * vec4(LB.position, 1.f)));
if (dot(-lightDir, v_norm) < -0.25f) discard;
vec4 wp = CB.invView * vec4(v_pos, 1.f);
vec3 w_pos = wp.xyz / wp.w;
vec3 v_surf = normalize(texture(texSurf, texcrd).rgb * 2.f - 1.f);
vec3 w_surf = normalize(vec3(CB.trnView * vec4(v_surf, 0.f)));
vec3 spotDir = normalize(vec3(CB.view * vec4(LB.direction, 0.f)));
float spotDist = distance(LB.position, w_pos);
float angle = acos(dot(lightDir, spotDir));
if (angle > LB.angle || spotDist > LB.intensity) discard;
bool doShad = bool(mode & 1);
bool doDiff = bool(mode & 2);
bool doSpec = bool(mode & 4);
float shad = 1.f;
if (doShad) shad = get_shadow_value(w_pos, w_surf);
if (shad == 0.f) discard;
vec3 diff = vec3(0.f, 0.f, 0.f);
if (doDiff) diff = get_diffuse_value(lightDir, v_norm);
vec3 spec = vec3(0.f, 0.f, 0.f);
if (doSpec) spec = get_specular_value(lightDir, v_norm, v_pos);
float fovRolf = pow((LB.angle - angle) / (1.f - LB.angle), sqrt(LB.softness));
float dstRolf = 1.f - spotDist / LB.intensity;
float rolloff = fovRolf * dstRolf;
fragColour = (diff + spec) * shad * rolloff;
}
答案 0 :(得分:1)
我也读过你的其他问题。
您通常会使用所有必需/使用的采样器编译着色器,而不会暴露任何未使用的采样器。这样做可能会给你错误。
我知道你不喜欢这种方法,但是使用ifdef并创建不同版本的着色器以考虑阴影/阴影灯。您可以自己缓存它们并在CPU中在运行时切换它们。在CPU中进行分支比在GPU中进行分支更好;请记住,对于对象,您只会执行一次此操作,而在GPU中,您将为每个像素执行一次,这非常浪费。
的内容
#if defined(USE_SHADOWS)
sampler2D [...]
#endif
答案 1 :(得分:0)
在遇到这个问题并进行了一些挖掘之后,我发现了另一种不需要你使用宏的方法。因此,我们的想法是简单地解决警告问题。我创建了1x1和GL_DEPTHCOMPONENT16类型的伪纹理,并将过滤模式设置为:
glTexParameteri(mTextureTarget, GL_TEXTURE_MIN_FILTER, supportsMipMaps && getTextureInfo().mMipCount > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(mTextureTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(mTextureTarget, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
如果你想优化它,你可以做的是你的ShaderObject类(或代表GLShader的w / e对象),在你的着色器中反映制服时,看看你是否有shadowSampler2D类型(I我总是硬编码到15号机组,我一直在寻找它。如果您确实拥有该类型并且在渲染调用期间(在绑定着色器之前),您仍然没有绑定单元15,将伪造的纹理与过滤方法绑定在一起。
此外,您需要在清除其他任何程序之前调用glUseProgram(0)仍然会发出警告。