2015-05-26 7 views
0

Я работаю над программой отсроченного затенения, и теперь мне нужно настроить 50 различных огней в сцене. Чтобы сделать это, я генерироваться случайным образом его атрибуты (положение, диффузный цвет, отраженный цвет) с этим фрагментом кода:Отложенное затенение - Несколько огней (OpenGL/GLSL)

void FBORender::BuildLights() 
{ 
    std::random_device rd; 
    std::mt19937 gen(rd()); 
    std::uniform_real_distribution<> dis(0.0, 0.1); 

    for (int i = 0; i < NUM_LIGHTS; i++) 
    { 
     float dc_r = (float) dis(gen); 
     float dc_g = (float) dis(gen); 
     float dc_b = (float) dis(gen); 

     printf("%f\n", dc_r); 

     float lp_x = (float)(rand() % 40 - 20); 
     float lp_y = (float)(rand() % 100 + 10); 
     float lp_z = (float)(rand() % 40 - 20); 

     DC[i * NUM_LIGHTS] = dc_r; 
     DC[i * NUM_LIGHTS + 1] = dc_g; 
     DC[i * NUM_LIGHTS + 2] = dc_b; 

     LP[i * NUM_LIGHTS] = lp_x; 
     LP[i * NUM_LIGHTS + 1] = lp_y; 
     LP[i * NUM_LIGHTS + 2] = lp_z; 
    } 
} 

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

Адаптирование шейдер, что я должен был выполнить Фонг Ilumination, у меня есть:

#version 410 core 

#define numLights 5 

uniform sampler2D tDiffuse; 
uniform sampler2D tPosition; 
uniform sampler2D tNormals; 

uniform vec4 specularColor; 
uniform vec3 diffuseColor[numLights]; 
uniform vec3 vLightPosition[numLights]; 

in vec2 texCoord; 

out vec4 fragColor; 


void main(void) 
{ 
    vec3 tex = texture(tDiffuse, texCoord.st).xyz; 
    vec3 vPosition = texture(tPosition, texCoord.st).xyz; 
    vec3 vNormal = normalize(texture(tNormals, texCoord.st).xyz * 2 - 1); 

    vec3 vVaryingNormal = vNormal; 

    for (int i = 0; i < numLights; i++) 
    { 
     vec3 vVaryingLightDir = normalize(vLightPosition[i] - vPosition); 

     float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); 
     vec4 partialColor = diff * vec4(diffuseColor[i], 1.0); 
     partialColor = vec4(mix(partialColor.rgb, tex, 0.5), partialColor.a); 
     partialColor += vec4(diffuseColor[i], 1.0); 
     vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal))); 
     float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); 
     if(diff != 0) 
     { 
      float fSpec = pow(spec, 128.0); 
      partialColor.rgb += vec3(fSpec, fSpec, fSpec); 
     } 

     fragColor += partialColor; 
    } 
} 

Однако я получаю уродливые результаты (если не ошибаюсь тоже), так как следующие изображения показывают:

enter image description here enter image description here

И эти результаты используют всего 2 огня. Поскольку я должен использовать 50, я думаю, что все, что я увижу, это белый экран ...

+1

Извините, если это глупый вопрос, но не видя других частей вашего кода, это выглядит странно: 'for (int i = 0; i MaKo

+0

Вы совершенно правы, @MaKo. Я был совершенно глуп. Спасибо за наблюдение. – pceccon

ответ

1

В отложенном рендеринге вы обычно визуализируете каждый свет отдельно и позволяете GPU смешивать результат вместе. Это уменьшает сложность шейдеров.

Давайте подробнее рассмотрим ваши расчеты освещения.

partialColor = vec4(mix(partialColor.rgb, tex, 0.5), partialColor.a); 

Хм ... Что это за линия должна делать? В то время partialColor содержит диффузно заштрихованный цвет (при условии белого материала). Если вы действительно хотите, чтобы вычислить цвет материала путем смешивания (который, кажется, немного странно), вы должны сделать затенение потом:

vec3 materialColor = mix(vec3(1.0, 1.0, 1.0), tex, 0.5); 
vec4 partialColor = vec4(diffuseColor[i] * diff * materialColor, 1.0); 

Следующая строка кода:

partialColor += vec4(diffuseColor[i], 1.0); 

Я понятия не имею, что это должно делать. Оставьте это.

Следующая линии:

vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal))); 
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); 

Вы смешиваете Фонг и Blinn-Фонг. Фонгу требуется точечный продукт вектора отраженного света и вектора глаза. Блинн-Фонг требует точечного произведения нормального и половинного вектора между вектором света и вектора.

Следующая строка:

partialColor.rgb += vec3(fSpec, fSpec, fSpec); 

Это должно быть умножено на зеркальном цветом света. Кроме того, вместо проверки diff != 0.0, вы должны проверить на spec > 0.

Если у вас по-прежнему возникают проблемы, выключите зеркальное освещение и проверьте правильность рассеивающего освещения.

Кроме того, ваши огни кажутся немного яркими. Ожидаемое значение светлого цвета: (0.05, 0.05, 0.05). 50 из них составляют в общей сложности (2.5, 2.5, 2.5), что намного ярче, чем просто белый свет.

0

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

Существуют различные способы расчета света в зависимости расстояния наиболее распространенным является inverse square root, который является в основном:

intensity = 1/sqrt(distance * distance) 

Вы также можете посмотреть на this article на GameDev. Конечно, вы можете получить гораздо лучше, если вы пойдете с PBS (физическое затенение, например: Unreal Engine 4 shading).

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