raytracing: fix backface lighting on non-procedural geometry

This commit is contained in:
Turánszki János
2021-10-09 13:26:04 +02:00
parent 12cd0f6ac1
commit d1cf3d7a11
4 changed files with 55 additions and 41 deletions
+5
View File
@@ -149,6 +149,7 @@ struct Surface
uint layerMask; // the engine-side layer mask
bool receiveshadow;
float3 facenormal; // surface normal without normal map
bool is_frontface;
// These will be computed when calling Update():
float roughnessBRDF; // roughness input for BRDF functions
@@ -440,6 +441,10 @@ struct Surface
N = n0 * w + n1 * u + n2 * v;
N = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), N);
N = normalize(N);
if (is_frontface == false && !is_hairparticle && !is_emittedparticle)
{
N = -N;
}
facenormal = N;
[branch]
+1
View File
@@ -99,6 +99,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
prim.instanceIndex = q.CommittedInstanceID();
prim.subsetIndex = q.CommittedGeometryIndex();
surface.is_frontface = q.CommittedTriangleFrontFace();
surface.load(prim, q.CommittedTriangleBarycentrics());
#else
+48 -40
View File
@@ -112,6 +112,7 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse
prim.subsetIndex = GeometryIndex();
Surface surface;
surface.is_frontface = (HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE);
surface.load(prim, attr.barycentrics);
[branch]
@@ -125,50 +126,57 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse
surface.pixel = DispatchRaysIndex().xy;
surface.screenUV = surface.pixel / (float2)DispatchRaysDimensions().xy;
// Light sampling:
surface.P = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();
surface.V = -WorldRayDirection();
surface.update();
Lighting lighting;
lighting.create(0, 0, GetAmbient(surface.N), 0);
[loop]
for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++)
if (surface.material.IsUnlit())
{
ShaderEntity light = load_entity(g_xFrame.LightArrayOffset + iterator);
if ((light.layerMask & surface.material.layerMask) == 0)
continue;
if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
{
continue; // static lights will be skipped (they are used in lightmap baking)
}
switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
DirectionalLight(light, surface, lighting);
}
break;
case ENTITY_TYPE_POINTLIGHT:
{
PointLight(light, surface, lighting);
}
break;
case ENTITY_TYPE_SPOTLIGHT:
{
SpotLight(light, surface, lighting);
}
break;
}
payload.data.xyz += surface.albedo + surface.emissiveColor;
}
else
{
// Light sampling:
surface.P = WorldRayOrigin() + WorldRayDirection() * RayTCurrent();
surface.V = -WorldRayDirection();
surface.update();
lighting.indirect.specular += max(0, EnvironmentReflection_Global(surface));
Lighting lighting;
lighting.create(0, 0, GetAmbient(surface.N), 0);
LightingPart combined_lighting = CombineLighting(surface, lighting);
payload.data.xyz += surface.albedo * combined_lighting.diffuse + combined_lighting.specular + surface.emissiveColor;
[loop]
for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++)
{
ShaderEntity light = load_entity(g_xFrame.LightArrayOffset + iterator);
if ((light.layerMask & surface.material.layerMask) == 0)
continue;
if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
{
continue; // static lights will be skipped (they are used in lightmap baking)
}
switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
DirectionalLight(light, surface, lighting);
}
break;
case ENTITY_TYPE_POINTLIGHT:
{
PointLight(light, surface, lighting);
}
break;
case ENTITY_TYPE_SPOTLIGHT:
{
SpotLight(light, surface, lighting);
}
break;
}
}
lighting.indirect.specular += max(0, EnvironmentReflection_Global(surface));
LightingPart combined_lighting = CombineLighting(surface, lighting);
payload.data.xyz += surface.albedo * combined_lighting.diffuse + combined_lighting.specular + surface.emissiveColor;
}
payload.data.w = RayTCurrent();
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates, breaking compatibility changes
const int minor = 58;
// minor bug fixes, alterations, refactors, updates
const int revision = 2;
const int revision = 3;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);