2016-02-16 2 views
2

Я пытаюсь реализовать простую систему освещения/затенения, простую систему освещения Фонга без зеркальных огней, чтобы быть точным. Это в основном работает, за исключением того, что у него есть некоторые (на мой взгляд) неприятные артефакты.OpenGL Простая затенение, артефакты

Моя первая мысль заключалась в том, что, возможно, это проблема текстур mipmaps, но их отключение не сработало. Следующее мое предположение было бы проблемой шейдера, но я не могу найти ошибку.

Неужели кто-нибудь когда-либо испытывал подобную проблему или идею о том, как решить эту проблему?

Image of the artifacts

Vertex шейдеров:

#version 330 core 

// Vertex shader 
layout(location = 0) in vec3 vpos; 
layout(location = 1) in vec2 vuv; 
layout(location = 2) in vec3 vnormal; 

out vec2 uv;  // UV coordinates 
out vec3 normal; // Normal in camera space 
out vec3 pos;  // Position in camera space 
out vec3 light[3]; // Vertex -> light vector in camera space 

uniform mat4 mv; // View * model matrix 
uniform mat4 mvp; // Proj * View * Model matrix 
uniform mat3 nm; // Normal matrix for transforming normals into c-space 

void main() { 
    // Pass uv coordinates 
    uv = vuv; 

    // Adjust normals 
    normal = nm * vnormal; 

    // Calculation of vertex in camera space 
    pos = (mv * vec4(vpos, 1.0)).xyz; 

    // Vector vertex -> light in camera space 
    light[0] = (mv * vec4(0.0,0.3,0.0,1.0)).xyz - pos; 
    light[1] = (mv * vec4(-6.0,0.3,0.0,1.0)).xyz - pos; 
    light[2] = (mv * vec4(0.0,0.3,4.8,1.0)).xyz - pos; 

    // Pass position after projection transformation 
    gl_Position = mvp * vec4(vpos, 1.0); 
} 

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

#version 330 core 

// Fragment shader 
layout(location = 0) out vec3 color; 

in vec2 uv;  // UV coordinates 
in vec3 normal;  // Normal in camera space 
in vec3 pos;  // Position in camera space 
in vec3 light[3]; // Vertex -> light vector in camera space 

uniform sampler2D tex; 
uniform float flicker; 

void main() { 
    vec3 n = normalize(normal); 

    // Ambient 
    color = 0.05 * texture(tex, uv).rgb; 

    // Diffuse lights 
    for (int i = 0; i < 3; i++) { 
     l = normalize(light[i]); 
     cos = clamp(dot(n,l), 0.0, 1.0); 
     length = length(light[i]); 
     color += 0.6 * texture(tex, uv).rgb * cos/pow(length, 2); 
    } 
} 
+1

Почти похоже на проблемы с точностью. В каком формате вы загружаете свою текстуру? –

+0

Кажется, независимо от текстуры. Я просто окрасил всю комнату в белый цвет, но проблема сохраняется. – user3413372

ответ

0

Итак, я нашел информацию о моей проблеме, описанной как «градиентная группировка», также обсуждался here. Проблема, по-видимому, в характере моих текстур, так как и то, и другое, только «белая» текстура и реальная текстура в основном серо-белые, и при использовании 8-битного цветного канала на уровне цветного изображения имеется 256 уровней серого.

Решение будет заключаться в реализации пост-обработки сглаживания или для использования более качественных текстур.

+0

Вы видите полосу, но не из-за глубины бита текстуры. Если вы посмотрите на скриншот, который вы опубликовали в фотошопе, вы можете видеть, что каждая группа не отличается от серого значением, как в связанном сообщении, но два или три. Градиентная группировка, как в связанной записи, выглядит совершенно по-другому, обратите внимание, насколько она более тонкая. Если у вас много шума в вашей текстуре (вместо этого вы попробовали только сплошной цвет, как выглядит полоса?), И в этом случае это может быть проблема цветового пространства (линейная или гамма-коррекция), она не выглядят как вероятное объяснение. – dognotdog

+0

Я все еще думаю, что это какой-то вычислительный артефакт, может быть, даже деление «.../pow ...». Вы можете попробовать предварительное вычисление falloff = 1.0/pow ... и затем умножить это вместо деления в конечном вычислении. – dognotdog

+0

Я пробовал полностью отказаться от falloff. Я пробовал его с белым цветом вместо текстуры, он дает мне именно те полосы, которые видны в ссылке. Самый простой шейдер фрагмента, который у меня был, удалил все, кроме точечного произведения света и нормального вектора, и он все еще дал мне полосы. Я обратился к OpenGL Forum, и мне также сказали, что это просто группы. – user3413372

1

Как первый комментарий говорит, это выглядит как цвет вычисления с использованием недостаточной точности. Попробуйте использовать float mediump или highp.

Кроме того, выражение length = length(light[i]); pow(length,2) довольно неэффективно и также может быть источником наблюдаемой полосы; вместо этого вы должны использовать dot(light[i],light[i]).

+0

Благодарим вас за точку (светлый [i], легкий [i]) совет! К сожалению, использование highp float ничего не изменило, проблема все еще сохраняется. – user3413372

+0

Вы также используете highp для векторов? – dognotdog

+0

Да, я пробовал писать highp перед всем, как вершинным, так и фрагментарным шейдером, чтобы быть уверенным. – user3413372