Фонг-зеркальное освещение в glsl (lwjgl) - PullRequest
2 голосов
/ 19 декабря 2011

В настоящее время я пытаюсь сделать зеркальное освещение на сфере, используя glsl и Phong-модель.

Вот так выглядит мой фрагментный шейдер:

#version 120
uniform vec4 color;
uniform vec3 sunPosition;
uniform mat4 normalMatrix;
uniform mat4 modelViewMatrix;
uniform float shininess;
// uniform vec4 lightSpecular;
// uniform vec4 materialSpecular;

varying vec3 viewSpaceNormal;
varying vec3 viewSpacePosition;

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = (modelViewMatrix * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)).xyz;
    vec4 specular = calculateSpecular(sunPosition, normal, viewSpacePosition, vec4(0.3,0.3,0.3,0.3), vec4(0.3,0.3,0.3,0.3));
    gl_FragColor = color+specular;
}

SunPosition - этоне перемещается и имеет значение (2.0f, 3.0f, -1.0f).

Проблема заключается в том, что изображение не выглядит так, как оно обычно, если зеркальные вычисления были правильными.

Вот как это выглядит: http://i.imgur.com/Na2C6.png

Причина, по которой у меня нет никакого ambient- / emissiv- / deffuse- освещения в этом коде, заключается в том, что я хочу, чтобы часть specular light работала первой.

Благодарю за любую помощь!

Редактировать: @Darcy Rayner Эта индеда очень помогла мне стать чем-то непонятным ...

Текущий кодвыглядит так:

Вершинный шейдер:

viewSpacePosition = (modelViewMatrix*gl_Vertex).xyz;
viewSpaceSunPosition = (modelViewMatrix*vec4(sunPosition,1)).xyz;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
viewSpaceNormal = (normalMatrix * vec4(gl_Position.xyz, 0.0)).xyz;

Фрагментный шейдер:

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) {
    vec3 r = -l+2*(n*l)*n;
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess);
}

void main(){
    vec3 normal = normalize(viewSpaceNormal);
    vec3 viewSpacePosition = normalize(viewSpacePosition);
    vec3 viewSpaceSunPosition = normalize(viewSpaceSunPosition);
    vec4 specular = calculateSpecular(viewSpaceSunPosition, normal, viewSpacePosition,     vec4(0.7,0.7,0.7,1.0), vec4(0.6,0.6,0.6,1.0));
    gl_FragColor = color+specular;
}

И сфера выглядит так:

-> Picture-link <- </a>

с положением солнца: sunPosition = new Vector (12.0f, 15.0f, -1.0f);

1 Ответ

0 голосов
/ 19 декабря 2011

Попробуйте не использовать gl_FragCoord, так как он хранится в экранных координатах (и я не думаю, что преобразование его с помощью modelViewMatrix вернет его к просмотру координат). Проще всего установить viewSpacePosition в вашем вершинном шейдере как:

// Change gl_Vertex to whatever attribute you are using.
viewSpacePosition = (modelViewMatrix * gl_Vertex).xyz; 

Это должно дать вам viewSpacePosition в координатах вида (т.е. до применения проекции). Затем вы можете продолжить и нормализовать viewSpacePosition во фрагментном шейдере. Не уверен, что вы сохраняете солнечный вектор в мировых координатах, но вы, вероятно, захотите преобразовать его в пространство обзора, а затем нормализовать его. Попробуйте и посмотрите, что произойдет, эти вещи, как правило, очень подвержены ошибкам.

...