diff --git a/WickedEngine/shaders/chamfernormals_edgedetectCS.hlsl b/WickedEngine/shaders/chamfernormals_edgedetectCS.hlsl index 0433ff495..86ed1b76e 100644 --- a/WickedEngine/shaders/chamfernormals_edgedetectCS.hlsl +++ b/WickedEngine/shaders/chamfernormals_edgedetectCS.hlsl @@ -1,9 +1,9 @@ #include "globals.hlsli" #include "ShaderInterop_Postprocess.h" -TEXTURE2D(input_normals, float4, TEXSLOT_ONDEMAND0); +TEXTURE2D(input_normals, float4, TEXSLOT_ONDEMAND0); // DXGI_FORMAT_R8G8B8A8_UNORM -RWTEXTURE2D(output_edgeMap, uint4, 0); +RWTEXTURE2D(output_edgeMap, uint4, 0); // DXGI_FORMAT_R32G32B32A32_UINT static const int2 offsets[3] = { int2(1, 0), @@ -11,29 +11,34 @@ static const int2 offsets[3] = { int2(1, 1), }; +static float detect_edge_threshold = 0.1f; // lower: less chance for detecting edges +static float detect_corner_threshold = 0.8f; // higher: less chance for detecting corners +static float reject_depth_threshold = 0.001f; // depth difference above this will be detected as separate surface without edge + [numthreads(8, 8, 1)] void main(uint3 DTid : SV_DispatchThreadID) { float4 normal = input_normals[DTid.xy]; - normal.xyz = normal.xyz * 2 - 1; + normal.xyz = normalize(normal.xyz * 2 - 1); - float lineardepth = texture_lineardepth[DTid.xy]; + const float lineardepth = texture_lineardepth[DTid.xy]; float3 edgeNormal = 0; for (uint i = 0; i < 3; ++i) { - int2 pixel2 = DTid.xy + offsets[i]; + const int2 pixel2 = DTid.xy + offsets[i]; - float ld = texture_lineardepth[pixel2]; - float diff = abs(lineardepth - ld); + const float ld = texture_lineardepth[pixel2]; + const float diff = abs(lineardepth - ld); - if (diff < 0.0001) + if (diff < reject_depth_threshold) { - float3 n = input_normals[pixel2].xyz * 2 - 1; + const float3 n = input_normals[pixel2].xyz * 2 - 1; - if (abs(dot(normal.xyz, n.xyz)) < 0.5) + if (abs(dot(normal.xyz, n.xyz)) < detect_edge_threshold) { edgeNormal = normalize(normal.xyz + n.xyz); + break; } } } @@ -51,19 +56,19 @@ void main(uint3 DTid : SV_DispatchThreadID) float3 N = normal.xyz; float3 NR = input_normals[max(0, min(DTid.xy + int2(1, 0), xPPResolution - 1))].xyz * 2 - 1; float3 ND = input_normals[max(0, min(DTid.xy + int2(0, 1), xPPResolution - 1))].xyz * 2 - 1; - if (abs(dot(N, cross(NR, ND))) > 0.2f) + if (abs(dot(N, cross(NR, ND))) > detect_corner_threshold) { cornerNormal += NR + ND; } NR = input_normals[max(0, min(DTid.xy + int2(-1, 0), xPPResolution - 1))].xyz * 2 - 1; ND = input_normals[max(0, min(DTid.xy + int2(0, 1), xPPResolution - 1))].xyz * 2 - 1; - if (abs(dot(N, cross(NR, ND))) > 0.2f) + if (abs(dot(N, cross(NR, ND))) > detect_corner_threshold) { cornerNormal += NR + ND; } NR = input_normals[max(0, min(DTid.xy + int2(1, 0), xPPResolution - 1))].xyz * 2 - 1; ND = input_normals[max(0, min(DTid.xy + int2(0, -1), xPPResolution - 1))].xyz * 2 - 1; - if (abs(dot(N, cross(NR, ND))) > 0.2f) + if (abs(dot(N, cross(NR, ND))) > detect_corner_threshold) { cornerNormal += NR + ND; } diff --git a/WickedEngine/shaders/chamfernormals_jumpfloodCS.hlsl b/WickedEngine/shaders/chamfernormals_jumpfloodCS.hlsl index 3828158a7..2bce0d820 100644 --- a/WickedEngine/shaders/chamfernormals_jumpfloodCS.hlsl +++ b/WickedEngine/shaders/chamfernormals_jumpfloodCS.hlsl @@ -1,9 +1,9 @@ #include "globals.hlsli" #include "ShaderInterop_Postprocess.h" -TEXTURE2D(input_edgeMap, uint4, TEXSLOT_ONDEMAND0); +TEXTURE2D(input_edgeMap, uint4, TEXSLOT_ONDEMAND0); // DXGI_FORMAT_R32G32B32A32_UINT -RWTEXTURE2D(output_edgeMap, uint4, 0); +RWTEXTURE2D(output_edgeMap, uint4, 0); // DXGI_FORMAT_R32G32B32A32_UINT static const int2 offsets[9] = { int2(-1, -1), int2(-1, 0), int2(-1, 1), @@ -16,7 +16,7 @@ void main(uint3 DTid : SV_DispatchThreadID) { const float2 uv = (DTid.xy + 0.5) * xPPResolution_rcp; - float lineardepth = texture_lineardepth[DTid.xy]; + const float lineardepth = texture_lineardepth[DTid.xy]; const float depth = texture_depth[DTid.xy]; const float3 P = reconstructPosition(uv, depth); @@ -28,18 +28,18 @@ void main(uint3 DTid : SV_DispatchThreadID) for (uint i = 0; i < 9; ++i) { - int2 pixel = (int2)DTid.xy + int2(offsets[i] * xPPParams0.x); - uint4 edgeMap = input_edgeMap[pixel]; + const int2 pixel = (int2)DTid.xy + int2(offsets[i] * xPPParams0.x); + const uint4 edgeMap = input_edgeMap[pixel]; - uint2 edge = edgeMap.xy; + const uint2 edge = edgeMap.xy; if (edge.x) { - uint2 edgePixel = unpack_pixel(edge.y); - float2 edgeUV = (edgePixel.xy + 0.5) * xPPResolution_rcp; + const uint2 edgePixel = unpack_pixel(edge.y); + const float2 edgeUV = (edgePixel.xy + 0.5) * xPPResolution_rcp; const float edgeDepth = texture_depth[edgePixel]; const float3 edgePosition = reconstructPosition(edgeUV, edgeDepth); - float dist = length(edgePosition - P); + const float dist = length(edgePosition - P); if (dist < bestEdgeDistance) { @@ -49,15 +49,15 @@ void main(uint3 DTid : SV_DispatchThreadID) } - uint2 corner = edgeMap.zw; + const uint2 corner = edgeMap.zw; if (corner.x) { - uint2 cornerPixel = unpack_pixel(corner.y); - float2 cornerUV = (cornerPixel.xy + 0.5) * xPPResolution_rcp; + const uint2 cornerPixel = unpack_pixel(corner.y); + const float2 cornerUV = (cornerPixel.xy + 0.5) * xPPResolution_rcp; const float cornerDepth = texture_depth[cornerPixel]; const float3 cornerPosition = reconstructPosition(cornerUV, cornerDepth); - float dist = length(cornerPosition - P); + const float dist = length(cornerPosition - P); if (dist < bestCornerDistance) { diff --git a/WickedEngine/shaders/chamfernormals_outputCS.hlsl b/WickedEngine/shaders/chamfernormals_outputCS.hlsl index b6150fb5e..5a732c1c6 100644 --- a/WickedEngine/shaders/chamfernormals_outputCS.hlsl +++ b/WickedEngine/shaders/chamfernormals_outputCS.hlsl @@ -1,66 +1,71 @@ #include "globals.hlsli" #include "ShaderInterop_Postprocess.h" -TEXTURE2D(input_edgeMap, uint4, TEXSLOT_ONDEMAND0); +TEXTURE2D(input_edgeMap, uint4, TEXSLOT_ONDEMAND0); // DXGI_FORMAT_R32G32B32A32_UINT -RWTEXTURE2D(input_output_normals, unorm float4, 0); +RWTEXTURE2D(input_output_normals, unorm float4, 0); // DXGI_FORMAT_R8G8B8A8_UNORM + +static const float chamfer_edge_radius = 0.05; // radius of the edge chamfering in world space +static const float chamfer_edge_strength = 1; // falloff for edge smoothness (lower: smaller chamfer, higher: stronger chamfer) + +static const float chamfer_corner_radius = 0.1; // radius of the corner chamfering in world space +static const float chamfer_corner_strength = 2; // falloff for corner smoothness (lower: smaller chamfer, higher: stronger chamfer) [numthreads(8, 8, 1)] void main(uint3 DTid : SV_DispatchThreadID) { const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; + const float depth = texture_depth[DTid.xy]; + const float3 P = reconstructPosition(uv, depth); float4 normal = input_output_normals[DTid.xy]; - normal.xyz = normal.xyz * 2 - 1; + normal.xyz = normalize(normal.xyz * 2 - 1); - uint4 edgeMap = input_edgeMap[DTid.xy]; + const uint4 edgeMap = input_edgeMap[DTid.xy]; + // edges: uint2 closestEdge = edgeMap.xy; if (closestEdge.x) { - float3 edgeNormal = unpack_unitvector(closestEdge.x); - uint2 edgePixel = unpack_pixel(closestEdge.y); - float2 edgeUV = (edgePixel.xy + 0.5f) * xPPResolution_rcp; + const float3 edgeNormal = unpack_unitvector(closestEdge.x); + const uint2 edgePixel = unpack_pixel(closestEdge.y); + const float2 edgeUV = (edgePixel.xy + 0.5f) * xPPResolution_rcp; const float edgeDepth = texture_depth[edgePixel]; const float3 edgePosition = reconstructPosition(edgeUV, edgeDepth); - const float depth = texture_depth[DTid.xy]; - const float3 P = reconstructPosition(uv, depth); - - float dist = length(edgePosition - P); + const float dist = length(edgePosition - P); - float l = dist * 10; + float l = dist / chamfer_edge_radius; l = saturate(l); + l = pow(l, chamfer_edge_strength); normal.xyz = lerp(edgeNormal, normal.xyz, l); normal.xyz = normalize(normal.xyz); - //output[DTid.xy] = dist * 10; + //input_output_normals[DTid.xy] = dist * 10; //return; } + // corners: closestEdge = edgeMap.zw; if (closestEdge.x) { - float3 edgeNormal = unpack_unitvector(closestEdge.x); - uint2 edgePixel = unpack_pixel(closestEdge.y); - float2 edgeUV = (edgePixel.xy + 0.5f) * xPPResolution_rcp; + const float3 edgeNormal = unpack_unitvector(closestEdge.x); + const uint2 edgePixel = unpack_pixel(closestEdge.y); + const float2 edgeUV = (edgePixel.xy + 0.5f) * xPPResolution_rcp; const float edgeDepth = texture_depth[edgePixel]; const float3 edgePosition = reconstructPosition(edgeUV, edgeDepth); - const float depth = texture_depth[DTid.xy]; - const float3 P = reconstructPosition(uv, depth); + const float dist = length(edgePosition - P); - float dist = length(edgePosition - P); - - float l = dist * 5; + float l = dist / chamfer_corner_radius; l = saturate(l); - l = pow(l, 2); + l = pow(l, chamfer_corner_strength); normal.xyz = lerp(edgeNormal, normal.xyz, l); normal.xyz = normalize(normal.xyz); - //output[DTid.xy] = dist * 10; + //input_output_normals[DTid.xy] = dist * 10; //return; }