Вопрос

Я пытаюсь реализовать точечные светильники в OpenGL с помощью GLSL.Я отправляю все необходимые данные в шейдеры.Для простоты я использую здесь только рассеянный свет.

В моем примере показан огромный треугольник, который я хочу осветить одним источником света.Источник света показан в виде маленького синего треугольника.

Для рассеянного света мне нужно знать угол между источником света и поверхностью.Поэтому я вычисляю нормали и направление света.Затем точечное произведение даст мне число от -1 до 1, тогда как все, что находится между 0 и 1, подсвечивается.

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

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

vec4 pos = modelview_matrix * <input vertex>;
vec4 lightPos = modelview_matrix * <light position>;

vec3 lightDir = normalize(lightPos.xyz - pos.xyz);

шейдер фрагментов:

float NdotL = max(dot(normalize(<correct normal>), normalize(lightDir)), 0.0);
gl_FragColor = vec4(1.0, NdotL, 0.0, 1.0);

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

http://img41.imageshack.us/img41/3566/interpolation.png http://img189.imageshack.us/img189/3566/interpolation.png

Особенно на первом снимке видно, что центральное пятно света находится НЕ прямо под лампой, но слегка сдвинутой к центру треугольника.

Если я передаю "pos" в фрагментный шейдер (то есть он интерполируется), а затем вычисляю "lightDir" в фрагментном шейдере, все работает нормально.

Это было полезно?

Решение

Я думаю, что нормализация вашего lightDir в вершинном шейдере влияет на результат, который вы получаете при интерполяции векторов, потому что она исключает длину из уравнения и, таким образом, влияет на "скорость" интерполяции.

Если вам нужно (визуальное) объяснение, попробуйте нарисовать его в 2D на бумаге.Сначала нарисуйте линию (ваш треугольник) и точку (источник света).Добавьте две линии (lightDir) для обоих концов линии к источнику света, а затем сократите (нормализуйте) эти линии lightDir так, чтобы они имели одинаковую длину и обе пересекались у источника света.Если вы соедините оба конца нормализованных линий lightDir, вы получите непараллельную линию (если источник света находится не точно посередине вашей первой линии).Теперь, если вы проведете линию, которая проходит точно через середину одной из линий, вы увидите, что она не проходит через середину другой линии, а проходит немного левее или правее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top