Отображение нормалей GLSL (подсвечиваются области с 0.0 Ламберта)

когда я использую нормаль модели, результат в порядке (есть темные области и освещенные области, как и следовало ожидать от простого диффузного шейдера Ламберта)

но когда я использую карту нормалей, темные области загораются!

я хочу использовать карту нормалей и по-прежнему получать правильное рассеянное освещение, как в этих примерах

вот код с отображением нормалей и без них

и вот код, использующий карту нормалей

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

varying vec3 normal,lightDir;
attribute vec3 vertex,normalVec,tangent;
attribute vec2 UV;

void main(){

gl_TexCoord[0] = gl_TextureMatrix[0] * vec4(UV,0.0,0.0);
normal = normalize (gl_NormalMatrix * normalVec);
vec3 t = normalize (gl_NormalMatrix * tangent);
vec3 b = cross (normal, t);
vec3 vertexPosition = normalize(vec3(gl_ModelViewMatrix * vec4(vertex,1.0)));
vec3 v;
v.x = dot (lightDir, t);
v.y = dot (lightDir, b);
v.z = dot (lightDir, normal);
lightDir = normalize (v);
lightDir = normalize(vec3(1.0,0.5,1.0) - vertexPosition);
gl_Position = gl_ModelViewProjectionMatrix*vec4(vertex,1.0);
}

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

vec4 computeDiffuseLight (const in vec3 direction, const in vec4 lightcolor, const in vec3 normal, const in vec4 mydiffuse){

float nDotL = dot(normal, direction);
vec4 lambert = mydiffuse * lightcolor * max (nDotL, 0.0);
return lambert;
}

varying vec3 normal,lightDir;
uniform sampler2D textures[8];

void main(){
vec3 normalVector = normalize( 2 * texture2D(textures[0],gl_TexCoord[0].st).rgb - 1 );
vec4 diffuse = computeDiffuseLight (lightDir, vec4(1,1,1,1) , normalVector, vec4(0.7,0.7,0.7,0));
gl_FragColor = diffuse ;
}

Примечание: фактическое отображение нормалей работает правильно, как видно из зеркальных бликов.

я использовал Assimp для загрузки модели (md5mesh) и вычислил касательные также с помощью Assimp, а затем отправил их в шейдеры в качестве атрибута

вот ссылка на код и скриншоты проблемы

https://dl.dropboxusercontent.com/u/32670019/code%20and%20screenshots.zip

это проблема в коде или у меня неправильное представление?

Обновленный код и скриншоты

https://dl.dropboxusercontent.com/u/32670019/updated%20code%20and%20screenshots.zip

теперь карта нормалей работает с диффузом, но сам по себе диффуз не корректен


person Darko    schedule 14.05.2013    source источник
comment
Где ваши #version директивы?   -  person genpfault    schedule 14.05.2013
comment
о, я забыл их включить, я использую 1.10, я включу их, спасибо :)   -  person Darko    schedule 14.05.2013


Ответы (1)


Ответ см. ниже.

Быстрое (возможно, ошибочное) наблюдение: линия

vec3 normalVector = normalize( 2 * texture2D(textures[0],gl_TexCoord[0].st).rgb - 1 );

в вашем фрагментном шейдере правильно масштабируется ваша нормаль, чтобы учесть отрицательные значения. Если ваша карта нормалей неверна, отрицательные значения могут появиться там, где они вам не нужны (я полагаю, ваша ось Y). Отрицательные значения нормали могут привести к обратному освещению.

Мой вопрос к вам: Ваша карта нормалей правильная?

ОТВЕТ: после небольшого обсуждения мы обнаружили проблему, я отредактировал этот пост, чтобы сохранить ветку в чистоте, решение проблем Дарко находится в комментариях здесь. Дело дошло до неинициализированного варианта под названием lightDir.

Оригинальный комментарий:

lightDir = нормализовать (v); lightDir = normalize(vec3(1.0,0.5,1.0) - vertexPosition); Это странно, вы перезаписываете это мгновенно, это неправильно? вы, кажется, не сохраняете правильно переведенный lightDir... Или я сошел с ума... Также этот lightDir является переменным, но вы его вообще не устанавливаете. Итак, вы вычисляете вектор v из ничего?

person Full Frontal Nudity    schedule 14.05.2013
comment
хорошее наблюдение =] , но да, карта нормалей правильная, я уже пробовал много карт нормалей из рабочих примеров, та же самая карта нормалей, которую я использую, такая же, как и исходные скриншоты - person Darko; 14.05.2013
comment
Теперь, когда я могу комментировать :), пожалуйста, загрузите свой код нестандартного шейдера сюда, а также в zip-архиве, он, похоже, отсутствует. - person Full Frontal Nudity; 14.05.2013
comment
Я бы напечатал (вывел) нормаль, касательную и бикасательную как цвета, я считаю, что они неверны и неправильно преобразуются в касательное пространство. Если вы присмотритесь повнимательнее, теневые карты рельефа также неверны. - person Trax; 14.05.2013
comment
= D, я думаю, что да, разве в zip-файле нет 4 исходных файлов и 4 изображений? , он называется безNormalMap - person Darko; 14.05.2013
comment
lightDir = нормализовать (v); lightDir = normalize(vec3(1.0,0.5,1.0) - vertexPosition); Это странно, вы перезаписываете это мгновенно, это неправильно? вы, кажется, не сохраняете правильно переведенный lightDir... Или я сошел с ума... Также этот lightDir является переменным, но вы его вообще не устанавливаете. Итак, вы вычисляете вектор v из ничего? - person Full Frontal Nudity; 14.05.2013
comment
Нет, я видел подобные проблемы из-за неправильного построения касательной базы. Я бы просто сделал три снимка экрана: 1 вывод нормалей на пиксели в виде цвета rgb (gl_FragColor = normal), 2 тангенс, 3 свет. Это помогает определить, в порядке ли базис касательной. - person Trax; 14.05.2013
comment
хм, это ДЕЙСТВИТЕЛЬНО выглядит странно, возможно, это ошибка, я исправлю ее и дам вам знать, дайте мне минуту - person Darko; 14.05.2013
comment
Также этот lightDir является переменным, но вы его вообще не устанавливаете. Итак, вы вычисляете вектор v из ничего? (дублировать из редактирования) Пожалуйста, обновите свой код, когда вы исправите эти проблемы - person Full Frontal Nudity; 14.05.2013
comment
@FullFrontalNudity, это действительно была проблема, но она создала новую проблему, которую я устал объяснять, но не смог, теперь работает сопоставление нормалей, но сам по себе диффузный шейдер не работает! :D проверьте новую ссылку выше с обновленными материалами - person Darko; 14.05.2013
comment
@Trax, я вижу, и каков ожидаемый результат каждого снимка экрана, поэтому я делаю вывод, что касательная основа в порядке или нет? а что вы имеете в виду под светом? направление света в каком именно пространстве? пожалуйста, расскажите мне больше об этой хорошей технике отладки =] - person Darko; 14.05.2013
comment
цвета должны иметь хороший градиент по поверхности, без больших скачков цвета (но, вероятно, меняются на стыках текстур). Если их нет, то что-то не так. Я имею в виду, что вы также можете выводить свет в касательном пространстве. - person Trax; 14.05.2013
comment
Вы все еще преобразуете свой lightdir в касательное пространство в своем диффузном шейдере, я не думаю, что вам следует это делать. Держите его в этом: lightDir = normalize(vec3(1.0,0.5,1.0) - vertexPosition); Глядя на ваши скриншоты, ваши расчеты тангенса, скорее всего, в порядке. - person Full Frontal Nudity; 14.05.2013
comment
если я это сделаю, то какая польза от касательного пространства? , это единственное, для чего я использую преобразование касательного пространства, поэтому, когда я удалю это, это не будет шейдером сопоставления нормалей (я также попробовал это сейчас, карта нормалей больше не будет работать) - person Darko; 14.05.2013
comment
Если вы собираетесь сделать два шейдера, один с картой нормалей, а другой без. И только та что без не работает, то почему бы просто не вернуть как было? Вам не нужны все карты нормалей, если вы все равно ими не пользуетесь. Может я не понимаю, что именно не так? - person Full Frontal Nudity; 14.05.2013
comment
ну, вы правы, я мог бы просто сделать два шейдера, и это сработало бы, я соглашусь с этим решением =] Большое спасибо, не могли бы вы написать свой третий комментарий (тот, который решил исходную проблему) в посте, так что я могу проголосовать, чтобы дать вам очки репутации? :), вы тоже, @Trax, пожалуйста, оставьте свой комментарий о разных скриншотах в ответе, чтобы я мог проголосовать за него :), всем спасибо :) - person Darko; 14.05.2013
comment
Отредактировал основной пост, чтобы он содержал решение, хотя я не уверен, насколько оно будет полезно для будущих посетителей. - person Full Frontal Nudity; 14.05.2013
comment
это, вероятно, не будет иметь большого значения, я просто хотел отдать вам заработанный кредит, хотя я не мог проголосовать = [ - person Darko; 14.05.2013