GLSL正确的镜面光

时间:2014-01-11 22:40:43

标签: opengl haskell glsl shader opengl-3

我正在尝试在GLSL着色器中使用镜面高光,但我无法让它正常工作。我正在使用Haskell,但这无关紧要。

我使用OpenGL的矩阵而不是制服。

以下是我“改变”玩家的方式。

glLoadIdentity

glPushAttrib gl_TRANSFORM_BIT

-- Rotate Player
let (xr, yr, zr) = playerRotation player
glRotatef xr (-1) 0 0
glRotatef yr 0 (-1) 0
glRotatef zr 0 0 (-1)

-- Translate Player
let (x, y, z) = playerPosition player
glTranslatef (-x) (-y) (-z)

-- Reset attributes to former state?
glPopAttrib

在该部分代码之后,我渲染所有实际的可渲染对象。所以从GLSL的角度来看,相机处于(0,0,0),其他一切都与玩家的位置成反比。很标准。

因此,下面的着色器不起作用,它们基本上使得它看起来像灯光随处可见:

顶点:

#version 400 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;
layout(location = 3) in vec3 color;
layout(location = 4) in float textureId;

out vec3 fragColor;
out vec3 vertex;
out vec2 textureCoord;
out vec3 norm;
out int texId;

void main()
{
    vertex = position;
    textureCoord = texCoord;
    norm = normal;
    fragColor = color;
    // Excuse this
    texId = int(textureId);

    gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);
}

片段:

#version 400

in vec3 fragColor;
in vec3 vertex;
in vec3 norm;
in vec2 textureCoord;
in int texId;

out vec4 outColor;

// Not used
layout(location = 6) uniform vec3 cameraPosition;
layout(location = 7) uniform sampler2D[7] textures;

vec3 lightPos = vec3(3, 1, 0);

void main()
{
    //Position of vertex in modelview space
    vec3 vertexPosition = (gl_ModelViewMatrix * vec4(vertex, 1.0)).xyz;

    //Surface normal of current vertex
    vec3 surfaceNormal = normalize((gl_NormalMatrix * norm).xyz);

    //Direction light has traveled to get to vertexPosition
    vec3 lightDirection = normalize(lightPos - vertexPosition);

    //Basically how much light is hitting the vertex
    float diffuseLightIntensity = max(0.0, dot(surfaceNormal, lightDirection));

    //"Main color"(diffuse) of vertex
    vec3 diffColor = diffuseLightIntensity * fragColor;

    //Adjust color depending upon distance from light
    diffColor /= max(distance(lightPos, vertexPosition)/10, 1);

    //Lowest light level possible
    vec3 ambColor = vec3(0.01, 0.01, 0.01);

    //"View vector" 
    vec3 viewVec = normalize(-vertexPosition);

    //Direction light is reflected off of surface normal
    vec3 reflectionDirection = normalize(reflect(-lightDirection, surfaceNormal));

    //The intensity of reflection (specular)
    float specular = max(0.0, dot(reflectionDirection, viewVec));

    float shininess = 2.0;

    float totalSpec = pow(specular, shininess);

    totalSpec /= max(distance(gl_LightSource[0].position.xyz, vertexPosition)/4, 1);

    vec3 specColor = vec3(totalSpec, totalSpec, totalSpec);

    // Excuse this
    if(texId != -1)
    {
        vec4 textureColor = texture(textures[texId], textureCoord);
        outColor = vec4(ambColor, 1.0) + textureColor + vec4(specColor, 1.0);
    }
    else
    {
        outColor = vec4(ambColor, 1.0) + vec4(diffColor + specColor, 1.0);
    }
}

我只是使用glUniform将玩家的位置传递给cameraPosition。

如何使镜面高光与我的给定变量一起使用?

1 个答案:

答案 0 :(得分:2)

对我来说,无论相机位置如何,我们的光线方向始终如一。尝试在顶点着色器中定义灯光位置,使用模型视图矩阵对其进行变换,并将其传递给片段着色器。