Я пытался реализовать отложенный рендеринг в течение последних 2 недель. Наконец-то я подошел к проходной точке точечного освещения, используя буфер трафарета и линеаризованную глубину. Я держу 3 текстуры кадрового буфера: альбедо, нормальный + глубина (X, Y, Z, EyeViewLinearDepth), текстура освещения. Поэтому я рисую свой свет (сферу) и применяю этот фрагментный шейдер:
void main(void)
{
vec2 texCoord = gl_FragCoord.xy * u_inverseScreenSize.xy;
float linearDepth = texture2D(u_normalDepth, texCoord.st).a;
// vector to far plane
vec3 viewRay = vec3(v_vertex.xy * (-farClip/v_vertex.z), -farClip);
// scale viewRay by linear depth to get view space position
vec3 vertex = viewRay * linearDepth;
vec3 normal = texture2D(u_normalDepth, texCoord.st).xyz*2.0 - 1.0;
vec4 ambient = vec4(0.0, 0.0, 0.0, 1.0);
vec4 diffuse = vec4(0.0, 0.0, 0.0, 1.0);
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
vec3 lightDir = lightpos - vertex ;
vec3 R = normalize(reflect(lightDir, normal));
vec3 V = normalize(vertex);
float lambert = max(dot(normal, normalize(lightDir)), 0.0);
if (lambert > 0.0) {
float distance = length(lightDir);
if (distance <= u_lightRadius) {
//CLASSICAL LIGHTING COMPUTATION PART
}
}vec4 final_color = vec4(ambient + diffuse + specular);
gl_FragColor = vec4(final_color.xyz, 1.0);
}
Переменные, которые вам нужно знать: v_vertex — это положение вершины (сферы) в пространстве глаза, lightpos — это положение / центр света в пространстве глаза, linearDepth генерируется на этапе прохождения геометрии в пространстве глаза.
Проблема в том, что код провалит это, если проверить: if (distance <= u_lightRadius)
, Свет никогда не вычисляется, пока я не уберу проверку расстояния. Я уверен, что я правильно передаю эти значения, радиус 170.0, светлое положение всего в 40-50 единицах от модели. Определенно что-то не так, но я как-то не могу это найти. Я перепробовал много возможностей радиуса и других переменных.
Задача ещё не решена.
Других решений пока нет …