2015-04-04 3 views
4

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

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

Deferred renderer banding

код шейдера фрагмент следующим образом:

vec3 position = texture(worldPos, fs_in.TexCoords).rgb;   
vec3 normal = texture(normals, fs_in.TexCoords).rgb; 
normal = normalize(normal * 2.0 - 1.0); 
vec3 color = texture(albedo, fs_in.TexCoords).rgb; 
float depth = texture(worldPos, fs_in.TexCoords).a; 
// Add global ambient value 
fragColor = vec4(vec3(0.1) * color, 0.0); 
for(int i = 0; i < NR_LIGHTS; ++i) 
{ 
    float distance = abs(length(position - lights[i].Position.xyz)); 
    if(distance <= lights[i].Size) 
    { 
     vec3 lighting;     
     // Ambient    
     lighting += lights[i].Ambient * color;    
     // Diffuse 
     vec3 lightDir = normalize(lights[i].Position.xyz - position); 
     float diffuse = max(dot(normal, lightDir), 0.0); 
     lighting += diffuse * lights[i].Diffuse * color; 
     // Specular 
     vec3 viewDir = normalize(viewPos - position); 
     vec3 reflectDir = reflect(-lightDir, normal); 
     float spec = pow(max(dot(viewDir, reflectDir), 0.0), 8); 
     lighting += spec * lights[i].Specular; 

     // Calculate attenuation 
     float attenuation = max(1.0f - lights[i].Linear * distance, 0.0); 
     lighting *= attenuation; 
     fragColor += vec4(lighting, 0.0); 
    } 
} 
fragColor.a = 1.0;  

Функция затухания является линейной функцией расстояния между положением фрагмента и каждый источник света.

В этой конкретной сцене я использую линейную величину ослабления 0.075 из которых я генерации источника света размер/радиус, как:

Size = 1.0/Linear; 

некоторых наблюдений

Когда я удалить проверку расстояния if(distance <= lights[i].Size) я не получите странный вопрос о границе.

Если я представляю ценность освещения единого источника света и визуализировать расстояние, как distance/lights.Size я получаю следующие 2 изображения:

Deferred renderer banding

, который выглядит так, как если радиус световых/Дистанционно- расчеты и свет затухание аналогично по радиусу.

Когда я меняю уравнение проверки расстояния на if(distance <= lights[i].Size * 2.0f) (чтобы резко увеличить радиус света), я получаю значительно меньшую границу, но если я посмотрю достаточно близко, я время от времени вижу их, поэтому даже это не полностью устраните проблему.

Я понятия не имею, что вызывает это, и на данный момент у меня нет вариантов.

+0

Вы уверены, что ваш параметр 'lights [i] .Size' и/или' .Linear' на самом деле правильный? Можете ли вы, как быстрый тест, просто попробовать 'if (distance <= 1.0/lights [i] .Linear)', просто чтобы убедиться, что вы тестируете ту же границу, которая фактически используется для термина ослабления? – derhass

+0

Я попробовал его с 'if (distance <= 1.0/lights [i] .Linear)' и он дает тот же результат. Что странно, так как вы ожидаете, что граница будет абсолютно правильной (так как это и функция затухания являются взаимно противоположными) – ABHAY

ответ

3

В этом разделе:

vec3 lighting;     
    // Ambient    
    lighting += lights[i].Ambient * color; 

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

// Ambient    
    vec3 lighting = lights[i].Ambient * color; 
+0

Вы правы; всегда думал, что GLSL будет правильно инициализировать переменные по умолчанию, но я думаю, что я ошибся.Это фиксировало проблему с диапазоном. У вас (или других) есть представление о том, как это может привести к группировке? Возможно, он инициализирует его значениями ниже '0.0'? – ABHAY

+0

Я, вероятно, начинаю как 0.0, но он никогда не будет очищен, поэтому для каждого итерационного освещения увеличивается. поэтому, если три света перекрываются, последний свет будет включать освещение от первых двух. – bofjas

+0

Да, это имеет смысл. Еще раз спасибо за ответ. – ABHAY