diff --git a/WickedEngine/shaders/raytraceCS.hlsl b/WickedEngine/shaders/raytraceCS.hlsl index 11ee9e669..5ec51ee07 100644 --- a/WickedEngine/shaders/raytraceCS.hlsl +++ b/WickedEngine/shaders/raytraceCS.hlsl @@ -15,26 +15,22 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) return; } float3 result = 0; + float3 energy = 1; // Compute screen coordinates: - float2 screenUV = float2((pixel + xTracePixelOffset) * xTraceResolution_rcp.xy * 2.0f - 1.0f) * float2(1, -1); + float2 uv = float2((pixel + xTracePixelOffset) * xTraceResolution_rcp.xy * 2 - 1) * float2(1, -1); float seed = xTraceRandomSeed; // Create starting ray: - Ray ray = CreateCameraRay(screenUV); + RayDesc ray = CreateCameraRay(uv); uint bounces = xTraceUserData.x; const uint bouncelimit = 16; - for (uint bounce = 0; ((bounce < min(bounces, bouncelimit)) && any(ray.energy)); ++bounce) + for (uint bounce = 0; ((bounce < min(bounces, bouncelimit)) && any(energy)); ++bounce) { - ray.Update(); + ray.Direction = normalize(ray.Direction); #ifdef RTAPI - RayDesc apiray; - apiray.TMin = 0.001; - apiray.TMax = FLT_MAX; - apiray.Origin = ray.origin; - apiray.Direction = ray.direction; RayQuery< RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES > q; @@ -46,7 +42,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) RAY_FLAG_FORCE_OPAQUE | 0, // uint RayFlags 0xFF, // uint InstanceInclusionMask - apiray // RayDesc Ray + ray // RayDesc Ray ); q.Proceed(); if (q.CommittedStatus() != COMMITTED_TRIANGLE_HIT) @@ -62,16 +58,16 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) if (IsStaticSky()) { // We have envmap information in a texture: - envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.direction, 0).rgb); + envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.Direction, 0).rgb); } else { - envColor = GetDynamicSkyColor(ray.direction); + envColor = GetDynamicSkyColor(ray.Direction); } - result += max(0, ray.energy * envColor); + result += max(0, energy * envColor); // Erase the ray's energy - ray.energy = 0.0f; + energy = 0.0f; break; } @@ -80,7 +76,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) #ifdef RTAPI // ray origin updated for next bounce: - ray.origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); + ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); ShaderMesh mesh = bindless_buffers[q.CommittedInstanceID()].Load(0); ShaderMeshSubset subset = bindless_subsets[mesh.subsetbuffer][q.CommittedGeometryIndex()]; @@ -98,7 +94,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) #else // ray origin updated for next bounce: - ray.origin = hit.position; + ray.Origin = ray.Origin + ray.Direction * hit.distance; EvaluateObjectSurface( hit, @@ -108,24 +104,24 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) #endif // RTAPI - surface.P = ray.origin; + surface.P = ray.Origin; surface.V = normalize(g_xCamera_CamPos - surface.P); surface.update(); - float3 current_energy = ray.energy; + float3 current_energy = energy; result += max(0, current_energy * surface.emissiveColor.rgb * surface.emissiveColor.a); float roulette; const float blendChance = 1 - surface.opacity; - roulette = rand(seed, screenUV); + roulette = rand(seed, uv); if (roulette < blendChance) { // Alpha blending // The ray penetrates the surface, so push DOWN along normal to avoid self-intersection: - ray.origin = trace_bias_position(ray.origin, -surface.N); + ray.Origin = trace_bias_position(ray.Origin, -surface.N); // Add a new bounce iteration, otherwise the transparent effect can disappear: bounces++; @@ -135,54 +131,54 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) else { const float refractChance = surface.transmission; - roulette = rand(seed, screenUV); + roulette = rand(seed, uv); if (roulette < refractChance) { // Refraction - const float3 R = refract(ray.direction, surface.N, 1 - material.refraction); - ray.direction = lerp(R, SampleHemisphere_cos(R, seed, screenUV), surface.roughnessBRDF); - ray.energy *= surface.albedo; + const float3 R = refract(ray.Direction, surface.N, 1 - material.refraction); + ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); + energy *= surface.albedo; // The ray penetrates the surface, so push DOWN along normal to avoid self-intersection: - ray.origin = trace_bias_position(ray.origin, -surface.N); + ray.Origin = trace_bias_position(ray.Origin, -surface.N); // Add a new bounce iteration, otherwise the transparent effect can disappear: bounces++; } else { - const float3 F = F_Schlick(surface.f0, saturate(dot(-ray.direction, surface.N))); + const float3 F = F_Schlick(surface.f0, saturate(dot(-ray.Direction, surface.N))); const float specChance = dot(F, 0.333); - roulette = rand(seed, screenUV); + roulette = rand(seed, uv); if (roulette < specChance) { // Specular reflection - const float3 R = reflect(ray.direction, surface.N); - ray.direction = lerp(R, SampleHemisphere_cos(R, seed, screenUV), surface.roughnessBRDF); - ray.energy *= F / specChance; + const float3 R = reflect(ray.Direction, surface.N); + ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); + energy *= F / specChance; } else { // Diffuse reflection - ray.direction = SampleHemisphere_cos(surface.N, seed, screenUV); - ray.energy *= surface.albedo / (1 - specChance); + ray.Direction = SampleHemisphere_cos(surface.N, seed, uv); + energy *= surface.albedo / (1 - specChance); } - if (dot(ray.direction, surface.facenormal) <= 0) + if (dot(ray.Direction, surface.facenormal) <= 0) { // Don't allow normal map to bend over the face normal more than 90 degrees to avoid light leaks // In this case, we will not allow more bounces, // but the current light sampling is still fine to avoid abrupt cutoff - ray.energy = 0; + energy = 0; } // Ray reflects from surface, so push UP along normal to avoid self-intersection: - ray.origin = trace_bias_position(ray.origin, surface.N); + ray.Origin = trace_bias_position(ray.Origin, surface.N); } } - surface.P = ray.origin; + surface.P = ray.Origin; float3 lightColor = 0; SurfaceToLight surfaceToLight = (SurfaceToLight)0; @@ -291,24 +287,19 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) { float3 shadow = surfaceToLight.NdotL * current_energy; - float3 sampling_offset = float3(rand(seed, screenUV), rand(seed, screenUV), rand(seed, screenUV)) * 2 - 1; // todo: should be specific to light surface + float3 sampling_offset = float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) * 2 - 1; // todo: should be specific to light surface - Ray newRay; - newRay.origin = surface.P; - newRay.direction = L + sampling_offset * 0.025; - newRay.energy = 0; - newRay.Update(); + RayDesc newRay; + newRay.Origin = surface.P; + newRay.Direction = normalize(L + sampling_offset * 0.025); + newRay.TMin = 0.001; + newRay.TMax = dist; #ifdef RTAPI - RayDesc apiray; - apiray.TMin = 0.001; - apiray.TMax = dist; - apiray.Origin = newRay.origin; - apiray.Direction = newRay.direction; q.TraceRayInline( scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure 0, // uint RayFlags 0xFF, // uint InstanceInclusionMask - apiray // RayDesc Ray + newRay // RayDesc Ray ); while (q.Proceed()) { @@ -342,7 +333,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) } shadow = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT ? 0 : shadow; #else - shadow = TraceRay_Any(newRay, dist, groupIndex) ? 0 : shadow; + shadow = TraceRay_Any(newRay, groupIndex) ? 0 : shadow; #endif // RTAPI if (any(shadow)) { diff --git a/WickedEngine/shaders/raytrace_debugbvhPS.hlsl b/WickedEngine/shaders/raytrace_debugbvhPS.hlsl index 36a7cb016..3d985fb7b 100644 --- a/WickedEngine/shaders/raytrace_debugbvhPS.hlsl +++ b/WickedEngine/shaders/raytrace_debugbvhPS.hlsl @@ -3,7 +3,7 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_Target { - Ray ray = CreateCameraRay(clipspace); + RayDesc ray = CreateCameraRay(clipspace); uint hitCount = TraceRay_DebugBVH(ray); @@ -28,4 +28,4 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_Target float4 heatmap = float4(lerp(a, b, l - floor(l)), 0.8f); return heatmap; -} \ No newline at end of file +} diff --git a/WickedEngine/shaders/raytracingHF.hlsli b/WickedEngine/shaders/raytracingHF.hlsli index d33929c97..c653352da 100644 --- a/WickedEngine/shaders/raytracingHF.hlsli +++ b/WickedEngine/shaders/raytracingHF.hlsli @@ -13,38 +13,28 @@ inline float3 trace_bias_position(in float3 P, in float3 N) return P + N * 0.0001; } -struct Ray +#ifdef HLSL5 +struct RayDesc { - float3 origin; - float3 direction; - float3 direction_rcp; - float3 energy; - - inline void Update() - { - direction_rcp = rcp(direction); - } + float3 Origin; + float TMin; + float3 Direction; + float TMax; }; +#endif // HLSL5 -inline Ray CreateRay(float3 origin, float3 direction) -{ - Ray ray; - ray.origin = origin; - ray.direction = normalize(direction); - ray.energy = float3(1, 1, 1); - ray.Update(); - return ray; -} - -inline Ray CreateCameraRay(float2 clipspace) +inline RayDesc CreateCameraRay(float2 clipspace) { float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0, 1)); unprojected.xyz /= unprojected.w; - const float3 origin = g_xCamera_CamPos; - const float3 direction = normalize(unprojected.xyz - origin); + RayDesc ray; + ray.Origin = g_xCamera_CamPos; + ray.Direction = normalize(unprojected.xyz - ray.Origin); + ray.TMin = 0.001; + ray.TMax = FLT_MAX; - return CreateRay(origin, direction); + return ray; } #ifdef RTAPI @@ -211,19 +201,17 @@ STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND5); struct RayHit { - float distance; - float3 position; - uint primitiveID; float2 bary; + float distance; + uint primitiveID; }; inline RayHit CreateRayHit() { RayHit hit; - hit.distance = FLT_MAX; - hit.position = 0; - hit.primitiveID = 0xFFFFFFFF; hit.bary = 0; + hit.distance = FLT_MAX; + hit.primitiveID = ~0u; return hit; } @@ -330,7 +318,7 @@ void EvaluateObjectSurface( } inline void IntersectTriangle( - in Ray ray, + in RayDesc ray, inout RayHit bestHit, in BVHPrimitive prim, uint primitiveID @@ -338,7 +326,7 @@ inline void IntersectTriangle( { float3 v0v1 = prim.v1() - prim.v0(); float3 v0v2 = prim.v2() - prim.v0(); - float3 pvec = cross(ray.direction, v0v2); + float3 pvec = cross(ray.Direction, v0v2); float det = dot(v0v1, pvec); #ifdef RAY_BACKFACE_CULLING // if the determinant is negative the triangle is backfacing @@ -352,60 +340,57 @@ inline void IntersectTriangle( #endif float invDet = 1 / det; - float3 tvec = ray.origin - prim.v0(); + float3 tvec = ray.Origin - prim.v0(); float u = dot(tvec, pvec) * invDet; if (u < 0 || u > 1) return; float3 qvec = cross(tvec, v0v1); - float v = dot(ray.direction, qvec) * invDet; + float v = dot(ray.Direction, qvec) * invDet; if (v < 0 || u + v > 1) return; float t = dot(v0v2, qvec) * invDet; - if (t > 0 && t < bestHit.distance) + if (t >= ray.TMin && t <= bestHit.distance) { bestHit.distance = t; - bestHit.position = ray.origin + t * ray.direction; bestHit.primitiveID = primitiveID; bestHit.bary = float2(u, v); } } inline bool IntersectTriangleANY( - in Ray ray, - in float maxDistance, + in RayDesc ray, in BVHPrimitive prim, uint primitiveID ) { float3 v0v1 = prim.v1() - prim.v0(); float3 v0v2 = prim.v2() - prim.v0(); - float3 pvec = cross(ray.direction, v0v2); + float3 pvec = cross(ray.Direction, v0v2); float det = dot(v0v1, pvec); // ray and triangle are parallel if det is close to 0 if (abs(det) < 0.000001) return false; float invDet = 1 / det; - float3 tvec = ray.origin - prim.v0(); + float3 tvec = ray.Origin - prim.v0(); float u = dot(tvec, pvec) * invDet; if (u < 0 || u > 1) return false; float3 qvec = cross(tvec, v0v1); - float v = dot(ray.direction, qvec) * invDet; + float v = dot(ray.Direction, qvec) * invDet; if (v < 0 || u + v > 1) return false; float t = dot(v0v2, qvec) * invDet; - if (t > 0 && t < maxDistance) + if (t >= ray.TMin && t <= ray.TMax) { RayHit hit; hit.distance = t; - hit.position = ray.origin + t * ray.direction; hit.primitiveID = primitiveID; hit.bary = float2(u, v); @@ -440,14 +425,19 @@ inline bool IntersectTriangleANY( } -inline bool IntersectNode(in Ray ray, in BVHNode box, in float primitive_best_distance) +inline bool IntersectNode( + in RayDesc ray, + in BVHNode box, + in float3 rcpDirection, + in float primitive_best_distance +) { - const float t0 = (box.min.x - ray.origin.x) * ray.direction_rcp.x; - const float t1 = (box.max.x - ray.origin.x) * ray.direction_rcp.x; - const float t2 = (box.min.y - ray.origin.y) * ray.direction_rcp.y; - const float t3 = (box.max.y - ray.origin.y) * ray.direction_rcp.y; - const float t4 = (box.min.z - ray.origin.z) * ray.direction_rcp.z; - const float t5 = (box.max.z - ray.origin.z) * ray.direction_rcp.z; + const float t0 = (box.min.x - ray.Origin.x) * rcpDirection.x; + const float t1 = (box.max.x - ray.Origin.x) * rcpDirection.x; + const float t2 = (box.min.y - ray.Origin.y) * rcpDirection.y; + const float t3 = (box.max.y - ray.Origin.y) * rcpDirection.y; + const float t4 = (box.min.z - ray.Origin.z) * rcpDirection.z; + const float t5 = (box.max.z - ray.Origin.z) * rcpDirection.z; const float tmin = max(max(min(t0, t1), min(t2, t3)), min(t4, t5)); // close intersection point's distance on ray const float tmax = min(min(max(t0, t1), max(t2, t3)), max(t4, t5)); // far intersection point's distance on ray @@ -460,14 +450,18 @@ inline bool IntersectNode(in Ray ray, in BVHNode box, in float primitive_best_di return true; } } -inline bool IntersectNode(in Ray ray, in BVHNode box) +inline bool IntersectNode( + in RayDesc ray, + in BVHNode box, + in float3 rcpDirection +) { - const float t0 = (box.min.x - ray.origin.x) * ray.direction_rcp.x; - const float t1 = (box.max.x - ray.origin.x) * ray.direction_rcp.x; - const float t2 = (box.min.y - ray.origin.y) * ray.direction_rcp.y; - const float t3 = (box.max.y - ray.origin.y) * ray.direction_rcp.y; - const float t4 = (box.min.z - ray.origin.z) * ray.direction_rcp.z; - const float t5 = (box.max.z - ray.origin.z) * ray.direction_rcp.z; + const float t0 = (box.min.x - ray.Origin.x) * rcpDirection.x; + const float t1 = (box.max.x - ray.Origin.x) * rcpDirection.x; + const float t2 = (box.min.y - ray.Origin.y) * rcpDirection.y; + const float t3 = (box.max.y - ray.Origin.y) * rcpDirection.y; + const float t4 = (box.min.z - ray.Origin.z) * rcpDirection.z; + const float t5 = (box.max.z - ray.Origin.z) * rcpDirection.z; const float tmin = max(max(min(t0, t1), min(t2, t3)), min(t4, t5)); // close intersection point's distance on ray const float tmax = min(min(max(t0, t1), max(t2, t3)), max(t4, t5)); // far intersection point's distance on ray @@ -476,8 +470,10 @@ inline bool IntersectNode(in Ray ray, in BVHNode box) // Returns the closest hit primitive if any (useful for generic trace). If nothing was hit, then rayHit.distance will be equal to FLT_MAX -inline RayHit TraceRay_Closest(Ray ray, uint groupIndex = 0) +inline RayHit TraceRay_Closest(RayDesc ray, uint groupIndex = 0) { + const float3 rcpDirection = rcp(ray.Direction); + RayHit bestHit = CreateRayHit(); #ifndef RAYTRACE_STACK_SHARED @@ -498,7 +494,7 @@ inline RayHit TraceRay_Closest(Ray ray, uint groupIndex = 0) BVHNode node = bvhNodeBuffer[nodeIndex]; - if (IntersectNode(ray, node, bestHit.distance)) + if (IntersectNode(ray, node, rcpDirection, bestHit.distance)) { if (nodeIndex >= leafNodeOffset) { @@ -533,8 +529,10 @@ inline RayHit TraceRay_Closest(Ray ray, uint groupIndex = 0) } // Returns true immediately if any primitives were hit, flase if nothing was hit (useful for opaque shadows): -inline bool TraceRay_Any(Ray ray, float maxDistance, uint groupIndex = 0) +inline bool TraceRay_Any(RayDesc ray, uint groupIndex = 0) { + const float3 rcpDirection = rcp(ray.Direction); + bool shadow = false; #ifndef RAYTRACE_STACK_SHARED @@ -555,7 +553,7 @@ inline bool TraceRay_Any(Ray ray, float maxDistance, uint groupIndex = 0) BVHNode node = bvhNodeBuffer[nodeIndex]; - if (IntersectNode(ray, node)) + if (IntersectNode(ray, node, rcpDirection)) { if (nodeIndex >= leafNodeOffset) { @@ -563,7 +561,7 @@ inline bool TraceRay_Any(Ray ray, float maxDistance, uint groupIndex = 0) const uint primitiveID = node.LeftChildIndex; const BVHPrimitive prim = primitiveBuffer[primitiveID]; - if (IntersectTriangleANY(ray, maxDistance, prim, primitiveID)) + if (IntersectTriangleANY(ray, prim, primitiveID)) { shadow = true; break; @@ -595,8 +593,10 @@ inline bool TraceRay_Any(Ray ray, float maxDistance, uint groupIndex = 0) // Returns number of BVH nodes that were hit (useful for debug): // returns 0xFFFFFFFF when there was a stack overflow -inline uint TraceRay_DebugBVH(Ray ray) +inline uint TraceRay_DebugBVH(RayDesc ray) { + const float3 rcpDirection = rcp(ray.Direction); + uint hit_counter = 0; // Emulated stack for tree traversal: @@ -615,7 +615,7 @@ inline uint TraceRay_DebugBVH(Ray ray) BVHNode node = bvhNodeBuffer[nodeIndex]; - if (IntersectNode(ray, node)) + if (IntersectNode(ray, node, rcpDirection)) { hit_counter++; diff --git a/WickedEngine/shaders/renderlightmapPS.hlsl b/WickedEngine/shaders/renderlightmapPS.hlsl index 85e98c006..fc704048a 100644 --- a/WickedEngine/shaders/renderlightmapPS.hlsl +++ b/WickedEngine/shaders/renderlightmapPS.hlsl @@ -19,15 +19,19 @@ float4 main(Input input) : SV_TARGET float2 uv = input.uv; float seed = xTraceRandomSeed; - float3 direction = SampleHemisphere_cos(surface.N, seed, uv); - Ray ray = CreateRay(trace_bias_position(input.pos3D, surface.N), direction); + RayDesc ray; + ray.Origin = trace_bias_position(input.pos3D, surface.N); + ray.Direction = SampleHemisphere_cos(surface.N, seed, uv); + ray.TMin = 0.001; + ray.TMax = FLT_MAX; float3 result = 0; + float3 energy = 1; uint bounces = xTraceUserData.x; const uint bouncelimit = 16; - for (uint bounce = 0; ((bounce < min(bounces, bouncelimit)) && any(ray.energy)); ++bounce) + for (uint bounce = 0; ((bounce < min(bounces, bouncelimit)) && any(energy)); ++bounce) { - surface.P = ray.origin; + surface.P = ray.Origin; [loop] for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++) @@ -141,21 +145,16 @@ float4 main(Input input) : SV_TARGET if (NdotL > 0 && dist > 0) { - float3 shadow = NdotL * ray.energy; + float3 shadow = NdotL * energy; float3 sampling_offset = float3(rand(seed, uv), rand(seed, uv), rand(seed, uv)) * 2 - 1; - Ray newRay; - newRay.origin = trace_bias_position(surface.P, surface.N); - newRay.direction = L + sampling_offset * 0.025f; - newRay.energy = 0; - newRay.Update(); + RayDesc newRay; + newRay.Origin = trace_bias_position(surface.P, surface.N); + newRay.Direction = normalize(L + sampling_offset * 0.025f); + newRay.TMin = 0.001; + newRay.TMax = dist; #ifdef RTAPI - RayDesc apiray; - apiray.TMin = 0.001; - apiray.TMax = dist; - apiray.Origin = newRay.origin; - apiray.Direction = newRay.direction; RayQuery< RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES > q; @@ -163,7 +162,7 @@ float4 main(Input input) : SV_TARGET scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure 0, // uint RayFlags 0xFF, // uint InstanceInclusionMask - apiray // RayDesc Ray + newRay // RayDesc Ray ); while (q.Proceed()) { @@ -197,7 +196,7 @@ float4 main(Input input) : SV_TARGET } shadow = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT ? 0 : shadow; #else - shadow = TraceRay_Any(newRay, dist) ? 0 : shadow; + shadow = TraceRay_Any(newRay) ? 0 : shadow; #endif // RTAPI if (any(shadow)) { @@ -207,20 +206,24 @@ float4 main(Input input) : SV_TARGET } // Sample primary ray (scene materials, sky, etc): + ray.Direction = normalize(ray.Direction); #ifdef RTAPI - RayDesc apiray; - apiray.TMin = 0.001; - apiray.TMax = FLT_MAX; - apiray.Origin = ray.origin; - apiray.Direction = ray.direction; RayQuery< - RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES > q; - q.TraceRayInline(scene_acceleration_structure, 0, 0xFF, apiray); + q.TraceRayInline( + scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure +#ifdef RAY_BACKFACE_CULLING + RAY_FLAG_CULL_BACK_FACING_TRIANGLES | +#endif // RAY_BACKFACE_CULLING + RAY_FLAG_FORCE_OPAQUE | + 0, // uint RayFlags + 0xFF, // uint InstanceInclusionMask + ray // RayDesc Ray + ); q.Proceed(); - if(q.CommittedStatus() != COMMITTED_TRIANGLE_HIT) + if (q.CommittedStatus() != COMMITTED_TRIANGLE_HIT) #else RayHit hit = TraceRay_Closest(ray); @@ -233,25 +236,24 @@ float4 main(Input input) : SV_TARGET if (IsStaticSky()) { // We have envmap information in a texture: - envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.direction, 0).rgb); + envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.Direction, 0).rgb); } else { - envColor = GetDynamicSkyColor(ray.direction, true, true, false, true); + envColor = GetDynamicSkyColor(ray.Direction, true, true, false, true); } - result += max(0, ray.energy * envColor); + result += max(0, energy * envColor); // Erase the ray's energy - ray.energy = 0; + energy = 0; break; } ShaderMaterial material; #ifdef RTAPI - // ray origin updated for next bounce: - ray.origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); + ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); ShaderMesh mesh = bindless_buffers[q.CommittedInstanceID()].Load(0); ShaderMeshSubset subset = bindless_subsets[mesh.subsetbuffer][q.CommittedGeometryIndex()]; @@ -268,9 +270,8 @@ float4 main(Input input) : SV_TARGET ); #else - - // Non-RTAPI path: sampling from texture atlas - ray.origin = hit.position; + // ray origin updated for next bounce: + ray.Origin = ray.Origin + ray.Direction * hit.distance; EvaluateObjectSurface( hit, @@ -282,22 +283,20 @@ float4 main(Input input) : SV_TARGET surface.update(); - result += max(0, ray.energy * surface.emissiveColor.rgb * surface.emissiveColor.a); - // Calculate chances of reflection types: - const float refractChance = material.transmission; + const float refractChance = surface.transmission; // Roulette-select the ray's path float roulette = rand(seed, uv); if (roulette < refractChance) { // Refraction - const float3 R = refract(ray.direction, surface.N, 1 - material.refraction); - ray.direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); - ray.energy *= surface.albedo; + const float3 R = refract(ray.Direction, surface.N, 1 - material.refraction); + ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); + energy *= surface.albedo; // The ray penetrates the surface, so push DOWN along normal to avoid self-intersection: - ray.origin = trace_bias_position(ray.origin, -surface.N); + ray.Origin = trace_bias_position(ray.Origin, -surface.N); // Add a new bounce iteration, otherwise the transparent effect can disappear: bounces++; @@ -305,29 +304,29 @@ float4 main(Input input) : SV_TARGET else { // Calculate chances of reflection types: - const float3 F = F_Schlick(surface.f0, saturate(dot(-ray.direction, surface.N))); + const float3 F = F_Schlick(surface.f0, saturate(dot(-ray.Direction, surface.N))); const float specChance = dot(F, 0.333f); roulette = rand(seed, uv); if (roulette < specChance) { // Specular reflection - const float3 R = reflect(ray.direction, surface.N); - ray.direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); - ray.energy *= F / specChance; + const float3 R = reflect(ray.Direction, surface.N); + ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); + energy *= F / specChance; } else { // Diffuse reflection - ray.direction = SampleHemisphere_cos(surface.N, seed, uv); - ray.energy *= surface.albedo / (1 - specChance); + ray.Direction = SampleHemisphere_cos(surface.N, seed, uv); + energy *= surface.albedo / (1 - specChance); } // Ray reflects from surface, so push UP along normal to avoid self-intersection: - ray.origin = trace_bias_position(ray.origin, surface.N); + ray.Origin = trace_bias_position(ray.Origin, surface.N); } - ray.Update(); + result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a); } return float4(result, xTraceAccumulationFactor); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 8d5a99e6c..71bf7c3f8 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 55; // minor bug fixes, alterations, refactors, updates - const int revision = 10; + const int revision = 11; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);