2015-12-06 2 views
2

Недавно я добавил отложенную поддержку затенения в моем двигателе; однако я столкнулся с некоторыми проблемами затухания: enter image description hereОтложенное затенение и затухание

Как вы можете видеть, когда я обрабатываю светлый объем (сферу), он не хорошо сочетается с окружающей частью изображения!

Вот как я объявляю свою точку света:

PointLight pointlight; 
pointlight.SetPosition(glm::vec3(0.0, 6.0, 0.0)); 
pointlight.SetIntensity(glm::vec3(1.0f, 1.0f, 1.0f)); 

Вот как я вычислить света радиуса сферы:

Attenuation attenuation = pointLights[i].GetAttenuation(); 
    float lightMax = std::fmaxf(std::fmax(pointLights[i].GetIntensity().r, pointLights[i].GetIntensity().g), 
     pointLights[i].GetIntensity().b); 

    float pointLightRadius = (-attenuation.linear + 
     std::sqrtf(std::pow(attenuation.linear, 2.0f) - 4.0f * attenuation.exponential * 
      (attenuation.constant - (256.0f/5.0f) * lightMax)))/(2.0f * attenuation.exponential); 

И, наконец, вот мой фрагмент PointLightPass шейдер:

#version 450 core 

struct BaseLight 
{ 
    vec3 intensities;//a.k.a color of light 
    float ambientCoeff; 
}; 

struct Attenuation 
{ 
    float constant; 
    float linear; 
    float exponential; 
}; 

struct PointLight 
{ 
    BaseLight base; 
    Attenuation attenuation; 
    vec3 position; 
}; 

struct Material 
{ 
    float shininess; 
    vec3 specularColor; 
    float ambientCoeff; 
}; 


layout (std140) uniform Viewport 
{ 
    uniform mat4 Projection; 
    uniform mat4 View; 
    uniform mat4 ViewProjection; 
    uniform vec2 scrResolution; 
}; 

layout(binding = 0) uniform sampler2D gPositionMap; 
layout(binding = 1) uniform sampler2D gAlbedoMap; 
layout(binding = 2) uniform sampler2D gNormalMap; 
layout(binding = 3) uniform sampler2D gSpecularMap; 

uniform vec3 cameraPosition; 
uniform PointLight pointLight; 

out vec4 fragmentColor; 

vec2 FetchTexCoord() 
{ 
     return gl_FragCoord.xy/scrResolution; 
} 

void main() 
{ 
     vec2 texCoord = FetchTexCoord(); 
     vec3 gPosition =  texture(gPositionMap, texCoord).xyz; 
     vec3 gSurfaceColor = texture(gAlbedoMap, texCoord).xyz; 
     vec3 gNormal =  texture(gNormalMap, texCoord).xyz; 
    vec3 gSpecColor = texture(gSpecularMap, texCoord).xyz; 
    float gSpecPower = texture(gSpecularMap, texCoord).a; 

    vec3 totalLight = gSurfaceColor * 0.1; //TODO remove hardcoded ambient light 
    vec3 viewDir = normalize(cameraPosition - gPosition); 

    vec3 lightDir = normalize(pointLight.position - gPosition); 
    vec3 diffuse = max(dot(gNormal, lightDir), 0.0f) * gSurfaceColor * 
        pointLight.base.intensities; 

    vec3 halfWayDir = normalize(lightDir + viewDir); 
    float spec = pow(max(dot(gNormal, halfWayDir), 0.0f), 1.0f); 
    vec3 specular = pointLight.base.intensities * spec /** gSpecColor*/; 

    float distance = length(pointLight.position - gPosition); 
    float attenuation = 1.0f/(1.0f + pointLight.attenuation.linear * distance 
        + pointLight.attenuation.exponential * distance * distance + 
        pointLight.attenuation.constant); 



    diffuse *= attenuation; 
    specular *= attenuation; 
    totalLight += diffuse + specular; 

    fragmentColor = vec4(totalLight, 1.0f); 
} 

Так что вы можете предложить решить эту проблему?

EDIT: Вот более подробная информация:

Для отложенного затенения,

  • я заполнить мой GBuffer;
  • я сделать окружающий свет проход, где я сделать полноэкранное четверной с окружающими цветами:

    #Version 420 ядро ​​

    layout (std140) uniform Viewport 
    { 
        uniform mat4 Projection; 
        uniform mat4 View; 
        uniform mat4 ViewProjection; 
        uniform vec2 scrResolution; 
    }; 
    
    layout(binding = 1) uniform sampler2D gAlbedoMap; 
    out vec4 fragmentColor; 
    
    vec2 FetchTexCoord() 
    { 
         return gl_FragCoord.xy/scrResolution; 
    } 
    
    void main() 
    { 
        vec2 texCoord = FetchTexCoord(); 
        vec3 gSurfaceColor = texture(gAlbedoMap, texCoord).xyz; 
    
        vec3 totalLight = gSurfaceColor * 1.2; //TODO remove hardcoded ambient light 
        fragmentColor = vec4(totalLight, 1.0f); 
    } 
    

Тогда я передаю мои точечные огни (см код выше);

ответ

1

Причина, по которой у вас возникает эта проблема, заключается в том, что вы используете «легкий том» (факт, что вы не совсем поняли в этом вопросе, но был поднят в your other question).

Вы используете нормальное уравнение ослабления освещенности. Хорошо, вы заметите, что это уравнение не волшебным образом останавливается при каком-то произвольном радиусе. Он определен для всех расстояний от 0 до бесконечности.

Целью вашего тома света является предотвращение задержек освещения за определенное расстояние. Хорошо, если ваше ослабление света не достигнет нуля на таком расстоянии, тогда вы увидите разрыв на краю света.

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

Продолжайте увеличивать радиус до тех пор, пока вы не сможете сказать, что он есть.

+0

Можете ли вы привести мне пример такого уравнения, который останавливается на 0? – Coder32

+0

Проблема в том, что я не могу просто экспериментировать с радиусом одного света: мне нужен алгоритм, который работает в 100% случаев! (это для игрового движка) – Coder32