lightmapper update: added explicit light sampling paths (indirect part)

This commit is contained in:
Turanszki Janos
2018-12-06 23:41:42 +00:00
parent c85d947ae8
commit d50255337b
4 changed files with 154 additions and 22 deletions
+17 -14
View File
@@ -201,7 +201,11 @@ inline bool TraceSceneANY(Ray ray, float maxDistance)
return shadow;
}
inline float3 Shade(inout Ray ray, RayHit hit, inout float seed, in float2 pixel)
// This will modify ray to continue the trace
// Also fill the final params of rayHit, such as normal, uv, materialIndex
// seed should be > 0
// pixel should be normalized uv coordinates of the ray start position (used to randomize)
inline float3 Shade(inout Ray ray, inout RayHit hit, inout float seed, in float2 pixel)
{
if (hit.distance < INFINITE_RAYHIT)
{
@@ -211,17 +215,16 @@ inline float3 Shade(inout Ray ray, RayHit hit, inout float seed, in float2 pixel
float v = hit.bary.y;
float w = 1 - u - v;
float3 N = normalize(tri.n0 * w + tri.n1 * u + tri.n2 * v);
float2 UV = tri.t0 * w + tri.t1 * u + tri.t2 * v;
hit.N = normalize(tri.n0 * w + tri.n1 * u + tri.n2 * v);
hit.UV = tri.t0 * w + tri.t1 * u + tri.t2 * v;
hit.materialIndex = tri.materialIndex;
uint materialIndex = tri.materialIndex;
TracedRenderingMaterial mat = materialBuffer[hit.materialIndex];
TracedRenderingMaterial mat = materialBuffer[materialIndex];
UV = frac(UV); // emulate wrap
float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.baseColorAtlasMulAdd.xy + mat.baseColorAtlasMulAdd.zw, 0);
float4 surfaceMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.surfaceMapAtlasMulAdd.xy + mat.surfaceMapAtlasMulAdd.zw, 0);
float4 normalMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV * mat.normalMapAtlasMulAdd.xy + mat.normalMapAtlasMulAdd.zw, 0);
hit.UV = frac(hit.UV); // emulate wrap
float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, hit.UV * mat.baseColorAtlasMulAdd.xy + mat.baseColorAtlasMulAdd.zw, 0);
float4 surfaceMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, hit.UV * mat.surfaceMapAtlasMulAdd.xy + mat.surfaceMapAtlasMulAdd.zw, 0);
float4 normalMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, hit.UV * mat.normalMapAtlasMulAdd.xy + mat.normalMapAtlasMulAdd.zw, 0);
float4 baseColor = DEGAMMA(mat.baseColor * baseColorMap);
float reflectance = mat.reflectance * surfaceMap.r;
@@ -249,18 +252,18 @@ inline float3 Shade(inout Ray ray, RayHit hit, inout float seed, in float2 pixel
// Specular reflection
//float alpha = 150.0f;
float alpha = sqr(1 - roughness) * 1000;
ray.direction = SampleHemisphere(reflect(ray.direction, N), alpha, seed, pixel);
ray.direction = SampleHemisphere(reflect(ray.direction, hit.N), alpha, seed, pixel);
float f = (alpha + 2) / (alpha + 1);
ray.energy *= (1.0f / specChance) * specular * saturate(dot(N, ray.direction) * f);
ray.energy *= (1.0f / specChance) * specular * saturate(dot(hit.N, ray.direction) * f);
}
else
{
// Diffuse reflection
ray.direction = SampleHemisphere(N, 1.0f, seed, pixel);
ray.direction = SampleHemisphere(hit.N, 1.0f, seed, pixel);
ray.energy *= (1.0f / diffChance) * albedo;
}
ray.origin = hit.position + N * EPSILON;
ray.origin = hit.position + ray.direction * EPSILON;
ray.primitiveID = hit.primitiveID;
ray.bary = hit.bary;
+127 -4
View File
@@ -2,6 +2,10 @@
#include "tracedRenderingHF.hlsli"
#include "raySceneIntersectHF.hlsli"
// Enable explicitly sampling lights placed in the scene.
// Otherwise, only scene materials are sampled (eg. emissive objects, sky, etc)
#define LIGHTMAPGEN_ENABLE_EXPLICIT_LIGHTSAMPLING
struct Input
{
float4 pos : SV_POSITION;
@@ -15,16 +19,135 @@ float4 main(Input input) : SV_TARGET
float3 N = normalize(input.normal);
float2 uv = input.uv;
float seed = g_xColor.z;
float3 result = 0;
float3 finalResult = 0;
float3 direction = SampleHemisphere(N, 1.0f, seed, uv);
Ray ray = CreateRay(input.pos3D + N * EPSILON, direction);
Ray ray = CreateRay(input.pos3D + direction * EPSILON, direction);
const uint bounces = 4;
for (uint i = 0; i < bounces && any(ray.energy); ++i)
{
// Sample primary ray (scene materials, sky, etc):
RayHit hit = TraceScene(ray);
result += ray.energy * Shade(ray, hit, seed, uv);
finalResult += ray.energy * Shade(ray, hit, seed, uv);
#ifdef LIGHTMAPGEN_ENABLE_EXPLICIT_LIGHTSAMPLING
// We sample explicit lights for every bounce, but only diffuse part. Specular will not be baked here.
// Also, because we do it after the primary ray was bounced off, we only get the indirect part.
// Dynamic (explicit) lights will contribute to the direct part later (based on render path specific shaders)
[loop]
for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++)
{
ShaderEntityType light = EntityArray[g_xFrame_LightArrayOffset + iterator];
LightingResult result = (LightingResult)0;
float3 L = 0;
float dist = 0;
switch (light.type)
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
dist = INFINITE_RAYHIT;
float3 lightColor = light.GetColor().rgb*light.energy;
L = light.directionWS.xyz;
result.diffuse = lightColor;
}
break;
case ENTITY_TYPE_POINTLIGHT:
{
L = light.positionWS - ray.origin;
const float dist2 = dot(L, L);
dist = sqrt(dist2);
[branch]
if (dist < light.range)
{
L /= dist;
const float3 lightColor = light.GetColor().rgb*light.energy;
result.diffuse = lightColor;
const float range2 = light.range * light.range;
const float att = saturate(1.0 - (dist2 / range2));
const float attenuation = att * att;
result.diffuse *= attenuation;
}
}
break;
case ENTITY_TYPE_SPOTLIGHT:
{
L = light.positionWS - ray.origin;
const float dist2 = dot(L, L);
dist = sqrt(dist2);
[branch]
if (dist < light.range)
{
L /= dist;
const float3 lightColor = light.GetColor().rgb*light.energy;
const float SpotFactor = dot(L, light.directionWS);
const float spotCutOff = light.coneAngleCos;
[branch]
if (SpotFactor > spotCutOff)
{
result.diffuse = lightColor;
const float range2 = light.range * light.range;
const float att = saturate(1.0 - (dist2 / range2));
float attenuation = att * att;
attenuation *= saturate((1.0 - (1.0 - SpotFactor) * 1.0 / (1.0 - spotCutOff)));
result.diffuse *= attenuation;
}
}
}
break;
case ENTITY_TYPE_SPHERELIGHT:
{
}
break;
case ENTITY_TYPE_DISCLIGHT:
{
}
break;
case ENTITY_TYPE_RECTANGLELIGHT:
{
}
break;
case ENTITY_TYPE_TUBELIGHT:
{
}
break;
}
float NdotL = saturate(dot(L, hit.N));
if (NdotL > 0 && dist > 0)
{
result.diffuse = max(0.0f, result.diffuse);
float3 sampling_offset = float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) * 2 - 1;
Ray newRay;
newRay.origin = ray.origin;
newRay.direction = L + sampling_offset * 0.025f;
newRay.direction_inverse = rcp(newRay.direction);
newRay.energy = 0;
bool hit = TraceSceneANY(newRay, dist);
finalResult += ray.energy * (hit ? 0 : NdotL) * (result.diffuse);
}
}
#endif // LIGHTMAPGEN_ENABLE_EXPLICIT_LIGHTSAMPLING
}
return float4(result, g_xColor.w);
return max(0, float4(finalResult, g_xColor.w));
}
+9 -3
View File
@@ -83,6 +83,11 @@ struct RayHit
float3 position;
uint primitiveID;
float2 bary;
// these will only be filled when bestHit is determined to avoid recomputing them for every intersection:
float3 N;
float2 UV;
uint materialIndex;
};
inline RayHit CreateRayHit()
@@ -92,9 +97,10 @@ inline RayHit CreateRayHit()
hit.position = float3(0.0f, 0.0f, 0.0f);
hit.primitiveID = 0xFFFFFFFF;
hit.bary = 0;
//hit.normal = float3(0.0f, 0.0f, 0.0f);
//hit.materialIndex = 0;
//hit.texCoords = 0;
hit.N = 0;
hit.UV = 0;
hit.materialIndex = 0;
return hit;
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 24;
// minor bug fixes, alterations, refactors, updates
const int revision = 4;
const int revision = 5;
long GetVersion()