GLSL使用pow()时的问题

我目前正在执行着色器来做一些定向灯。 我正在关注灯塔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”行放入 - 那么着色器不再“有效”......我用引号说'有效',因为我从Shader Log中没有输出或错误,但是,现在统一的位置我的所有返回-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作为一个统一的位置返回意味着名称是错误的,或者编译器已经优化了它,但是这对于添加单行是没有意义的,其结果之后不会被使用。 当NSight调试器连接或不连接时,它的行为会有所不同

我可能会做错什么?

编辑:

以下是我可以创建的最简单的Vertex / Fragment着色器,它可以复制问题,同时仍然是“真实世界”着色器。

顶点着色器:

// 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;
}

片段着色器:

// 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调试器时“工作”。


在这个着色器中有一些有趣的事情,它们都与这一行有关:

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);
链接地址: http://www.djcxy.com/p/77033.html

上一篇: GLSL Issue when using pow()

下一篇: Downloading files in a SPA