Шейдер не отображается должным образом

Я играл с шейдерами с игрушкой под названием ShaderToy и пытался создать эффект воды с видом сверху вниз для 2D-игра на основе кода (для шейдера) от Йонаса Вагнера. Вы можете легко скопировать/вставить этот код в ShaderToy и увидеть результат.

Шейдер выглядит круто в ShaderToy, но когда я пытаюсь воспроизвести его в своем коде, что-то идет не так, см. изображение ниже:

http://ivan.org.es/temp/shader_problems.png

Мой вершинный шейдер (не знаю, какой используется в ShaderToy):

uniform mat4 Projection;
attribute vec2 Position;

void main(){
    gl_Position = Projection*vec4(Position, 0.0, 1.0);
}

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

precision lowp float;

vec3 sunDirection = normalize(vec3(0.0, -1.0, 0.0));
vec3 sunColor = vec3(1.0, 0.8, 0.7);
vec3 eye = vec3(0.0, 1.0, 0.0);

vec4 getNoise(vec2 uv){
    vec2 uv0 = (uv/103.0)+vec2(iGlobalTime/17.0, iGlobalTime/29.0);
    vec2 uv1 = uv/107.0-vec2(iGlobalTime/-19.0, iGlobalTime/31.0);
    vec2 uv2 = uv/vec2(897.0, 983.0)+vec2(iGlobalTime/101.0, iGlobalTime/97.0);
    vec2 uv3 = uv/vec2(991.0, 877.0)-vec2(iGlobalTime/109.0, iGlobalTime/-113.0);
    vec4 noise = (texture2D(iChannel0, uv0)) +
                 (texture2D(iChannel0, uv1)) +
                 (texture2D(iChannel0, uv2)) +
                 (texture2D(iChannel0, uv3));
    return noise*0.5-1.0;
}

void sunLight(const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor){
    vec3 reflection = normalize(reflect(-sunDirection, surfaceNormal));
    float direction = max(0.0, dot(eyeDirection, reflection));
    specularColor += pow(direction, shiny)*sunColor*spec;
    diffuseColor += max(dot(sunDirection, surfaceNormal),0.0)*sunColor*diffuse;
}

void main(){
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    uv *= 100.0;

    vec4 noise = getNoise(uv);
    vec3 surfaceNormal = normalize(noise.xzy*vec3(2.0, 1.0, 2.0));

    vec3 diffuse = vec3(0.3);
    vec3 specular = vec3(0.0);

    vec3 worldToEye = vec3(0.0, 1.0, 0.0);//eye-worldPosition;
    vec3 eyeDirection = normalize(worldToEye);
    sunLight(surfaceNormal, eyeDirection, 100.0, 1.5, 0.5, diffuse, specular);

    gl_FragColor = vec4((diffuse+specular+vec3(0.1))*vec3(0.3, 0.5, 0.9), 1.0);
}

Обратите внимание, что код фрагментного шейдера в ShaderToy и в моем движке точно такой же, мне кажется, что uv-координаты из gl_FragCoord какие-то неправильные или проблема с точностью, потому что через некоторое время эффект становится все хуже и хуже. Я использую орфографическую проекцию, но это не должно иметь большого значения, так как я получаю координаты uv прямо с экрана.

Некоторые идеи о том, что происходит?


person Ivan    schedule 06.08.2013    source источник
comment
Попробуйте увеличить точность, как описано здесь stackoverflow.com/a/6336285/187752.   -  person Kimi    schedule 06.08.2013
comment
Ааа... Я загружал свои текстуры с помощью GL_CLAMP_TO_EDGE, а функция шума предполагала GL_REPEAT. Теперь это работает.   -  person Ivan    schedule 06.08.2013
comment
Пожалуйста, ответьте на свой вопрос. Но в любом случае вы должны указать точность в шейдерах фрагментов - это соответствует спецификациям OpenGL ES 2.0. Пожалуйста, прочитайте ссылку, предоставленную @Kimi для получения дополнительной информации.   -  person keaukraine    schedule 07.08.2013
comment
Сделанный. Я также обновил код, теперь указав точность.   -  person Ivan    schedule 07.08.2013


Ответы (1)


Оказывается, я загружал свои текстуры с помощью

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Вместо этого функция шума шейдера ожидала GL_REPEAT.

person Ivan    schedule 07.08.2013