2009-06-14 3 views
0

Я пытаюсь реализовать точечные огни в OpenGL с помощью GLSL. Я отправляю все необходимые данные в шейдеры. Для простоты я использую здесь только рассеянный свет.Интерполяция 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); 

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

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

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

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

+0

Не нормализуйте lightDir в вершинном шейдере. Так как нормализация не является линейной операцией, вы должны делать это только в своем флеш-шейдере. – Hannesh

+0

Ваши фотографии никуда не уходят (ImageShack - это ужасный хост изображений, между прочим). Попробуйте [Imgur] (http://imgur.com), и я включу их, когда вы конвертируете ссылки. – Qix

ответ

3

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

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

Смежные вопросы