// Stochastic shared code // Compute local triangle barycentric coordinates and vertex IDs void TriangleGrid(float2 uv, float scale, out float w1, out float w2, out float w3, out int2 vertex1, out int2 vertex2, out int2 vertex3) { // Scaling of the input uv *= 3.464 * scale; // 2 * sqrt(3) // Skew input space into simplex triangle grid const float2x2 gridToSkewedGrid = float2x2(1.0, 0.0, -0.57735027, 1.15470054); float2 skewedCoord = mul(gridToSkewedGrid, uv); // Compute local triangle vertex IDs and local barycentric coordinates int2 baseId = int2(floor(skewedCoord)); float3 temp = float3(frac(skewedCoord), 0); temp.z = 1.0 - temp.x - temp.y; if (temp.z > 0.0) { w1 = temp.z; w2 = temp.y; w3 = temp.x; vertex1 = baseId; vertex2 = baseId + int2(0, 1); vertex3 = baseId + int2(1, 0); } else { w1 = -temp.z; w2 = 1.0 - temp.y; w3 = 1.0 - temp.x; vertex1 = baseId + int2(1, 1); vertex2 = baseId + int2(1, 0); vertex3 = baseId + int2(0, 1); } } // Fast random hash function float2 SimpleHash2(float2 p) { return frac(sin(mul(float2x2(127.1, 311.7, 269.5, 183.3), p)) * 4375.85453); } half3 BaryWeightBlend(half3 iWeights, half tex0, half tex1, half tex2, half contrast) { // compute weight with height map const half epsilon = 1.0f / 1024.0f; half3 weights = half3(iWeights.x * (tex0 + epsilon), iWeights.y * (tex1 + epsilon), iWeights.z * (tex2 + epsilon)); // Contrast weights half maxWeight = max(weights.x, max(weights.y, weights.z)); half transition = contrast * maxWeight; half threshold = maxWeight - transition; half scale = 1.0f / transition; weights = saturate((weights - threshold) * scale); // Normalize weights. half weightScale = 1.0f / (weights.x + weights.y + weights.z); weights *= weightScale; return weights; } void PrepareStochasticUVs(float scale, float3 uv, out float3 uv1, out float3 uv2, out float3 uv3, out half3 weights) { // Get triangle info float w1, w2, w3; int2 vertex1, vertex2, vertex3; TriangleGrid(uv.xy, scale, w1, w2, w3, vertex1, vertex2, vertex3); // Assign random offset to each triangle vertex uv1 = uv; uv2 = uv; uv3 = uv; uv1.xy += SimpleHash2(vertex1); uv2.xy += SimpleHash2(vertex2); uv3.xy += SimpleHash2(vertex3); weights = half3(w1, w2, w3); } void PrepareStochasticUVs(float scale, float2 uv, out float2 uv1, out float2 uv2, out float2 uv3, out half3 weights) { // Get triangle info float w1, w2, w3; int2 vertex1, vertex2, vertex3; TriangleGrid(uv, scale, w1, w2, w3, vertex1, vertex2, vertex3); // Assign random offset to each triangle vertex uv1 = uv; uv2 = uv; uv3 = uv; uv1.xy += SimpleHash2(vertex1); uv2.xy += SimpleHash2(vertex2); uv3.xy += SimpleHash2(vertex3); weights = half3(w1, w2, w3); }