我目前正在实施一个着色器来做一些定向灯。我正在遵循Lighthouse 3d(http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/directional-lights-per-pixel/)
的教程我遇到的问题是以下几行:
vec3 h = normalize(l_dir + e);
float intSpec = max(dot(h, n), 0.0);
float specularPower = pow(intSpec, shininess);
如果我将“float specularPower”行留下 - 那么着色器不再“正常”....我在引号中说“工作”,因为我没有从着色器日志中获得输出或错误,但是,现在我的所有返回-1的统一位置,我无法设置我的纹理位置等。
如果我将其删除,则着色器的其余部分按预期工作(但由于缺少镜面反射功率而产生不正确的结果)。
更令人好奇的是,如果我附加了nVidia Nsight调试器,那么我在屏幕上输出它似乎“工作”,但如果我只是在调试模式下使用VS2012,我屏幕上什么都没显示,以下错误消息:
First-chance exception at 0x000000005EB066E6 (nvoglv64.dll) in application.exe: 0xC0000005: Access violation reading location 0x0000000000000008.
First-chance exception at 0x000000005EB066E6 (nvoglv64.dll) in application.exe: 0xC0000005: Access violation reading location 0x0000000000000008.
在运行Windows 8 64位的PC上,GTX 480和GTX 560都出现了这种现象。
我知道-1作为Uniform位置返回意味着名称错误,或者编译器已经对其进行了优化,但是添加一行是没有意义的,其结果根本就没有使用然后。当连接或不连接NSight调试器时,行为是不同的
我可能做错了什么?
编辑:
下面是我可以创建的最简单的顶点/片段着色器,可以复制问题,同时仍然是“真实世界”的着色器。
顶点着色器:
// Default Vertex Shader
#version 430 core
uniform mat4 projMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_TexCoords;
out vec2 pass_TexCoords;
out vec3 v;
out Data {
vec3 normal;
vec4 eye;
} DataOut;
void main(void)
{
DataOut.normal = normalize(in_Normal);
DataOut.eye = (viewMatrix * modelMatrix) * in_Position;
pass_TexCoords = in_TexCoords;
v = vec3(in_Position);
gl_Position = projMatrix * viewMatrix * modelMatrix * in_Position;
}
Fragment Shader:
// Default Fragment Shader
#version 430 core
uniform sampler2D material[3];
in vec2 pass_TexCoords;
in Data {
vec3 normal;
vec4 eye;
} DataIn;
layout (location = 0) out vec4 out_Colour;
void main(void)
{
float shininess = 0.5;
vec3 l_dir = vec3(0.0, 0.0, 1.0);
vec3 n = normalize(DataIn.normal);
vec3 e = normalize(vec3(DataIn.eye));
float intensity = max(dot(n, l_dir), 0.0);
float specularPower;
if(intensity > 0.0) {
vec3 h = normalize(l_dir + e);
float dHN = dot(h, n);
float intSpec = max(dHN, 0.0);
float specularPower = pow(intSpec, shininess);
} else {
specularPower = 1.0;
}
vec4 diffuse_Colour = texture(material[0], pass_TexCoords);
out_Colour = diffuse_Colour * specularPower;
}
我还检查了程序信息日志,但没有返回任何错误。再次,使用这些着色器,在通过VS2012运行时失败(制服返回-1),但在连接nVidia Nsight调试器时“有效”。
答案 0 :(得分:4)
这个着色器中有一些有趣的事情,它们都与这一行的事实有关:
float specularPower = pow(intSpec, shininess);
在最终编译的着色器中绝对没有任何内容。您已在函数范围内隐藏了同名变量。
// Default Fragment Shader
#version 430 core
uniform sampler2D material[3];
in vec2 pass_TexCoords;
in Data {
vec3 normal;
vec4 eye;
} DataIn;
layout (location = 0) out vec4 out_Colour;
void main(void)
{
vec3 l_dir = vec3(0.0, 0.0, 1.0);
vec3 n = normalize(DataIn.normal);
float intensity = max(dot(n, l_dir), 0.0);
float specularPower;
if(intensity > 0.0) {
// This branch did not affect anything outside of this scope, so it is gone...
// specularPower is uninitialized if this branch is triggered
} else {
specularPower = 1.0;
}
vec4 diffuse_Colour = texture(material[0], pass_TexCoords);
out_Colour = diffuse_Colour * specularPower;
}
specularPower = pow(intSpec, shininess);
您的着色器实际上会在if (intensity > 0.0) { ... }
分支中执行某些操作。
shininess
是此程序中的常量,您也可以像这样替换该语句:specularPower = sqrt (intSpec);