GLSL着色器产生不必要的结果

时间:2014-03-04 06:04:34

标签: opengl glsl

我无法使用以下着色器。

顶点着色器

#version 430

in vec4 vPosition;
in vec4 vColor;
in vec2 vTexCoord;
in vec3 vNormal;
in vec3 vTangent;
in vec3 vBitangent;

//out vec4 color;
out vec2 texCoord;

uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;

out vec3 LightDirection_cameraspace;
out vec3 Position_worldspace;
uniform vec3 LightPosition;
out vec3 EyeDirection_cameraspace;

out vec3 LightDirection_tangentspace;
out vec3 EyeDirection_tangentspace;

void main()
{
        gl_Position = Projection * View * Model * vPosition;

        Position_worldspace = (Model * vPosition).xyz;

        vec3 vertexPosition_cameraspace = (View * Model * vPosition).xyz;
        EyeDirection_cameraspace = vec3(0, 0, 0) - vertexPosition_cameraspace;

        vec3 LightPosition_cameraspace = (View * vec4(LightPosition, 1)).xyz;
        LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;

        texCoord = vTexCoord;

        mat4 ModelView = View * Model;
        mat3 MV3x3 = mat3(ModelView);
        vec3 vertexTangent_cameraspace = MV3x3 * vTangent;
        vec3 vertexBitangent_cameraspace = MV3x3 * vBitangent;
        vec3 vertexNormal_cameraspace = MV3x3 * vNormal;

        mat3 TBN = transpose(mat3(
                vertexTangent_cameraspace,
                vertexBitangent_cameraspace,
                vertexNormal_cameraspace
        ));

        LightDirection_tangentspace = TBN * LightDirection_cameraspace;
        EyeDirection_tangentspace = TBN * EyeDirection_cameraspace;
}

片段着色器

#version 430

in vec4 vColor;
in vec2 texCoord;

out vec4 fColor;

uniform sampler2D tex;

in vec3 Position_worldspace;
in vec3 EyeDirection_cameraspace;
uniform vec3 LightPosition;

//uniform sampler2D DiffuseTex; pretty much just tex
uniform sampler2D NormalTex;
uniform sampler2D SpecularTex;

in vec3 LightDirection_tangentspace;
in vec3 EyeDirection_tangentspace;

void main()
{
        vec3 LightColor = vec3(1, 1, 1);
        float LightPower = 50.0f;

        //vec3 MaterialDiffuseColor = texture2D(tex, texCoord).rgb; // EDITABLE VALU 3 LINE
        //vec3 MaterialAmbientColor = vec3(0.1, 0.1, 0.1) * MaterialDiffuseColor;
        //vec3 MaterialSpecularColor = texture2D(SpecularTex, texCoord).rgb * 0.3;
        vec3 MaterialDiffuseColor = vec3(0.5, 0.5, 0.5);
        vec3 MaterialAmbientColor = vec3(0.1, 0.1, 0.1);
        vec3 MaterialSpecularColor = vec3(1, 1, 1);

        vec3 TextureNormal_tangentspace = normalize(texture2D(NormalTex, vec2(texCoord.x, texCoord.y)).rgb * 2.0 - 1.0); // EDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDIT this line if upside down

        float distance = length(LightPosition - Position_worldspace);

        vec3 n = TextureNormal_tangentspace;
        vec3 l = normalize(LightDirection_tangentspace);

        float cosTheta = clamp(dot(n, l), 0, 1);

        vec3 E = normalize(EyeDirection_tangentspace);
        vec3 R = reflect(-l, n);

        float cosAlpha = clamp(dot(E, R), 0, 1);

        fColor = vec4(MaterialAmbientColor + MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) + MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance), 1.0);


}

这是一张imgur相册,其中包含漫反射,高光和法线贴图以及该程序生成的图像。 http://imgur.com/a/8MMU1

P.S。着色器DOES编译,它只是不会产生所需的图像。

1 个答案:

答案 0 :(得分:0)

首先,很好的代码!我看到着色器远比那更难阅读。

您可以简化投影/视图/模型转换,因此没有重复...

vec4 worldPosition = Modle * vPosition;
vec4 cameraPosition = View * worldPosition;
vec4 clipPosition = Projection * cameraPosition;
gl_Position = clipPosition;

要变换法线,你需要一个普通的矩阵(逆转置模型视图),否则秤会弄乱。

在着色器外部计算LightPosition_cameraspace非常常见,因为它不会改变。您也不需要Position_worldspace因为distance可以在相机/眼睛空间中计算。 View * Model非常昂贵,可以计算一次并传入。现在不需要View,您只需将ViewModel替换为ModelView fColor = vec4( MaterialAmbientColor + ( MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) ) + ( MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance) ) , 1.0); {1}}矩阵。

可以通过叉积从法线和切线隐式计算副法线。这节省了相当多的存储和内存带宽。如果您的法线/切线不垂直,则可能需要使用两个交叉乘积来确保所有三个都是正交的。

主要问题似乎出在你的最后一行......

LightPower

float attenuation = 1.0/distance*distance; //just for readability fColor = vec4( MaterialAmbientColor + ( MaterialDiffuseColor * LightColor * cosTheta * attenuation ) + ( MaterialSpecularColor * LightColor * pow(cosAlpha, LightPower) * attenuation ) , 1.0); 正在缩放漫反射和镜面反射分量。切换到以下

LightDirection_tangentspace

如果在此之后你还没有看到正确的结果,你将不得不开始对每个变量进行一些调试以缩小麻烦制造者的范围。例如,正如@ user1118321建议检查颜色不只是黑色或其他东西。使用fColor = vec4(l,1)检查fColor = vec4(n,1) - 对于直接面向灯光的部分,您可能会寻找(0,0,1)/蓝色。确保切线/法线/灯光位置不为零,正常纹理绑定等({{1}})。