Недавно я добавил отложенную поддержку затенения в моем двигателе; однако я столкнулся с некоторыми проблемами затухания: Отложенное затенение и затухание
Как вы можете видеть, когда я обрабатываю светлый объем (сферу), он не хорошо сочетается с окружающей частью изображения!
Вот как я объявляю свою точку света:
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); }
Тогда я передаю мои точечные огни (см код выше);
Можете ли вы привести мне пример такого уравнения, который останавливается на 0? – Coder32
Проблема в том, что я не могу просто экспериментировать с радиусом одного света: мне нужен алгоритм, который работает в 100% случаев! (это для игрового движка) – Coder32