Реализация рассеяния света в атмосфере
Я пытаюсь реализовать атмосферное рассеяние в openGL. Я использую эту "бумагу" в качестве учебного пособия: http://developer.amd.com/wordpress/media/2012/10/GDC_02_HoffmanPreetham.pdf
Однако у меня есть некоторые трудности, чтобы понять определенные моменты и выяснить некоторые константы.
В основном я должен реализовать эти формулы:
Во-первых, я не знаю, является ли s расстоянием от глаза до купола или расстоянием от глаза до источника света (здесь солнце). То же самое касается угла тета, я не могу понять, является ли это углом от земли к солнцу или к положению купола, на которое смотрит глаз.
Во-вторых, на этом слайде: Он говорит мне, что появится синий цвет неба. Я знаю, что это причина рассеяния рэлея, но есть кое-что, чего я не могу понять. Все вычисления в приведенных выше формулах дают мне скаляр: так, как белый свет солнца, который по сути является vec3(1,1,1), станет синим, когда я умножу его на скаляры, он получится только в оттенках серого потому что я буду иметь для результата, например, vec3(0.8,0.8,0.8). Я имею в виду, если появляется какой-то другой цвет неба, я должен умножить солнечный свет на vec3, чтобы изменить значение RGB по-другому.
Теперь я столкнулся с некоторыми трудностями при реализации моего шейдера. Вот код для небесного шейдера:
#version 330
in vec3 vpoint;
in vec2 vtexcoord;
out vec2 uv;
out vec3 atmos;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
mat4 MVP = P*V*M;
//uniform vec3 lpos;
vec3 lpos = vec3(100,0,0);
uniform vec3 cpos;
vec3 br = vec3(5.5e-6, 13.0e-6, 22.4e-6);
vec3 bm = vec3(21e-6);
float g = -0.75f;
vec3 Esun = vec3(2000,2000,2000);
vec3 Br(float theta){
return 3/(16*3.14) * br * (1+cos(theta)*cos(theta));
}
vec3 Bm(float theta){
return 1/(4*3.14) * bm * ((1 - g)*(1 - g))/(pow(1+g*g-
2*g*cos(theta),3/2));
}
vec3 atmospheric(float theta, float s){
return (Br(theta)*Bm(theta))/(br+bm) * Esun * (1- exp( -(br+bm)*s ));
}
void main() {
gl_Position = MVP * vec4(vpoint, 1.0);
uv = vtexcoord;
vec3 domePos = vec3(M*vec4(vpoint,1.0));
vec3 ldir = lpos - domePos;
float s = length(domePos-cpos);
float theta = acos(dot(normalize(ldir-domePos),normalize(domePos-
cpos)*vec3(1,1,0)));
atmos = atmospheric(theta,s)*1000000*5;
}
Я не понимаю, чего ожидаю, вот что я получаю:
У меня только синий, и нет красноватого заката, но солнце низкое, и, согласно разным урокам, которые я видел, я должен видеть, что красноватый цвет появляется, когда солнце садится низко.
1 ответ
Предупреждение, я не эксперт в этой области, возьмите это с недоверием.
Это в значительной степени говорит обо всем.
s - расстояние между вершиной / пикселем и камерой.
θ - угол между солнцем и линией визирования.
Чтобы вычислить θ, вам нужно знать "желтую линию" и "линию обзора".
Последний - обычная шейдерная математика; первый - просто способ выразить, как высоко на небе солнце. Вы можете смоделировать его как луч от солнца до точки на земле.
Вся формула выше дает вам векторы.
L0 - это вектор.
Есолнце тоже вектор.
Слайды в основном говорят о том, что физические понятия, такие как Radiance и Irradiance (Esun), непрерывны в спектре, и для описания света и цвета следует использовать спектральное распределение мощности.
Однако более быстрый подход состоит в том, чтобы выполнять математику только в трех точках спектра, одной для длин волн R, G и B.
На практике это говорит о том, что Esun - это вектор, описывающий излучение солнца для трех длин волн RGB.
Синий цвет неба исходит от параметра βR, который зависит от θ, который зависит от "прямой видимости", которая зависит от высоты окрашиваемого фрагмента неба.