add Preetham sky; add point light and spot light;
This commit is contained in:
@ -61,13 +61,33 @@ const float Epsilon = 0.00001;
|
||||
const int LightCount = 1;
|
||||
const vec3 Fdielectric = vec3(0.04);
|
||||
|
||||
struct DirectionalLight
|
||||
{
|
||||
struct DirectionalLight {
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
float Multiplier;
|
||||
float Intensity;
|
||||
bool CastShadows;
|
||||
};
|
||||
|
||||
struct PointLight {
|
||||
vec3 Position;
|
||||
vec3 Radiance;
|
||||
float Intensity;
|
||||
float Range;
|
||||
bool CastShadows;
|
||||
};
|
||||
|
||||
struct SpotLight {
|
||||
vec3 Position;
|
||||
vec3 Direction;
|
||||
vec3 Radiance;
|
||||
float Intensity;
|
||||
float Range;
|
||||
float InnerConeCos;
|
||||
float OuterConeCos;
|
||||
bool CastShadows;
|
||||
};
|
||||
|
||||
|
||||
in VertexOutput
|
||||
{
|
||||
vec3 WorldPosition;
|
||||
@ -84,6 +104,14 @@ layout(location = 0) out vec4 color;
|
||||
layout(location = 1) out vec4 o_BloomColor;
|
||||
|
||||
uniform DirectionalLight u_DirectionalLights;
|
||||
|
||||
uniform int u_PointLightCount;
|
||||
uniform PointLight u_PointLights;
|
||||
|
||||
uniform int u_SpotLightCount;
|
||||
uniform SpotLight u_SpotLights;
|
||||
|
||||
|
||||
uniform vec3 u_CameraPosition;
|
||||
|
||||
// PBR
|
||||
@ -171,13 +199,102 @@ vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||
}
|
||||
|
||||
// ---------- direction light ----------
|
||||
vec3 ComputeDirectionalLight(DirectionalLight light, vec3 F0, PBRParameters params)
|
||||
{
|
||||
vec3 L = normalize(-light.Direction);
|
||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||
|
||||
vec3 Lh = normalize(L + params.View);
|
||||
float cosLi = max(0.0, dot(params.Normal, L));
|
||||
float cosLh = max(0.0, dot(params.Normal, Lh));
|
||||
|
||||
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
|
||||
float D = ndfGGX(cosLh, params.Roughness);
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||
}
|
||||
|
||||
vec3 ComputePointLight(PointLight light, vec3 F0, PBRParameters params, vec3 worldPos)
|
||||
{
|
||||
vec3 lightVec = light.Position - worldPos;
|
||||
float dist = length(lightVec);
|
||||
if (dist > light.Range) return vec3(0.0);
|
||||
|
||||
vec3 L = lightVec / dist;
|
||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||
|
||||
// 距离衰减:通常使用平方衰减,但为避免分母为零,加一个小值
|
||||
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||
|
||||
// 可选:范围平滑衰减
|
||||
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||
rangeFactor = rangeFactor * rangeFactor; // 平滑
|
||||
attenuation *= rangeFactor;
|
||||
|
||||
vec3 Lh = normalize(L + params.View);
|
||||
float cosLi = max(0.0, dot(params.Normal, L));
|
||||
float cosLh = max(0.0, dot(params.Normal, Lh));
|
||||
|
||||
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
|
||||
float D = ndfGGX(cosLh, params.Roughness);
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
}
|
||||
|
||||
vec3 ComputeSpotLight(SpotLight light, vec3 F0, PBRParameters params, vec3 worldPos)
|
||||
{
|
||||
vec3 lightVec = light.Position - worldPos;
|
||||
float dist = length(lightVec);
|
||||
if (dist > light.Range) return vec3(0.0);
|
||||
|
||||
vec3 L = lightVec / dist;
|
||||
vec3 Lradiance = light.Radiance * light.Intensity;
|
||||
|
||||
// 距离衰减
|
||||
float attenuation = 1.0 / (dist * dist + 0.0001);
|
||||
float rangeFactor = clamp(1.0 - (dist / light.Range), 0.0, 1.0);
|
||||
rangeFactor = rangeFactor * rangeFactor;
|
||||
attenuation *= rangeFactor;
|
||||
|
||||
// 角度衰减(聚光锥)
|
||||
float cosAngle = dot(-L, normalize(light.Direction)); // 光方向指向外,所以用 -L
|
||||
if (cosAngle < light.OuterConeCos) return vec3(0.0);
|
||||
float angleFalloff = (cosAngle - light.OuterConeCos) / (light.InnerConeCos - light.OuterConeCos);
|
||||
angleFalloff = clamp(angleFalloff, 0.0, 1.0);
|
||||
attenuation *= angleFalloff;
|
||||
|
||||
vec3 Lh = normalize(L + params.View);
|
||||
float cosLi = max(0.0, dot(params.Normal, L));
|
||||
float cosLh = max(0.0, dot(params.Normal, Lh));
|
||||
|
||||
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, params.View)));
|
||||
float D = ndfGGX(cosLh, params.Roughness);
|
||||
float G = GeometrySmith(params.Normal, params.View, L, params.Roughness);
|
||||
|
||||
vec3 kd = (1.0 - F) * (1.0 - params.Metalness);
|
||||
vec3 diffuseBRDF = kd * params.Albedo;
|
||||
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * params.NdotV);
|
||||
|
||||
return (diffuseBRDF + specularBRDF) * Lradiance * cosLi * attenuation;
|
||||
}
|
||||
|
||||
vec3 Lighting(vec3 F0)
|
||||
{
|
||||
vec3 result = vec3(0.0);
|
||||
for(int i = 0; i < LightCount; i++)
|
||||
{
|
||||
vec3 Li = u_DirectionalLights.Direction;
|
||||
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Multiplier;
|
||||
vec3 Lradiance = u_DirectionalLights.Radiance * u_DirectionalLights.Intensity;
|
||||
vec3 Lh = normalize(Li + m_Params.View);
|
||||
|
||||
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
||||
@ -202,9 +319,9 @@ vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||
{
|
||||
angle = radians(angle);
|
||||
mat3 rotationMatrix = mat3(
|
||||
vec3(cos(angle), 0.0, sin(angle)),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(-sin(angle), 0.0, cos(angle))
|
||||
vec3(cos(angle), 0.0, sin(angle)),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(-sin(angle), 0.0, cos(angle))
|
||||
);
|
||||
return rotationMatrix * vec;
|
||||
}
|
||||
@ -218,9 +335,9 @@ vec3 IBL(vec3 F0, vec3 Lr)
|
||||
|
||||
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||
vec3 specularIrradiance = textureLod(
|
||||
u_EnvRadianceTex,
|
||||
RotateVectorAboutY(u_EnvMapRotation, Lr),
|
||||
m_Params.Roughness * u_EnvRadianceTexLevels
|
||||
u_EnvRadianceTex,
|
||||
RotateVectorAboutY(u_EnvMapRotation, Lr),
|
||||
m_Params.Roughness * u_EnvRadianceTexLevels
|
||||
).rgb;
|
||||
|
||||
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
||||
@ -314,6 +431,7 @@ void main()
|
||||
|
||||
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||
|
||||
// Shadow
|
||||
float shadowFactor = 1.0;
|
||||
if (u_ShadowEnabled > 0.5) {
|
||||
float shadow = calculateShadow(vs_Input.FragPosLightSpace, m_Params.Normal, u_DirectionalLights.Direction);
|
||||
@ -321,7 +439,13 @@ void main()
|
||||
}
|
||||
|
||||
// directional light with with shadow
|
||||
vec3 lightContribution = u_DirectionalLights.Multiplier > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
|
||||
vec3 lightContribution = u_DirectionalLights.Intensity > 0.0 ? Lighting(F0) * shadowFactor : vec3(0.0);
|
||||
|
||||
if(u_PointLightCount > 0)
|
||||
lightContribution += ComputePointLight(u_PointLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
|
||||
if(u_SpotLightCount > 0)
|
||||
lightContribution += ComputeSpotLight(u_SpotLights, F0, m_Params, vs_Input.WorldPosition);
|
||||
|
||||
vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user