Integrated Sebastian Lague's Planet Generator Created Tour function in SectorRenderer which makes the camera follow each terrestrial planet in turn
100 lines
No EOL
4.1 KiB
HLSL
100 lines
No EOL
4.1 KiB
HLSL
float4 triplanar(float3 vertPos, float3 normal, float scale, sampler2D tex) {
|
|
|
|
// Calculate triplanar coordinates
|
|
float2 uvX = vertPos.zy * scale;
|
|
float2 uvY = vertPos.xz * scale;
|
|
float2 uvZ = vertPos.xy * scale;
|
|
|
|
float4 colX = tex2D (tex, uvX);
|
|
float4 colY = tex2D (tex, uvY);
|
|
float4 colZ = tex2D (tex, uvZ);
|
|
// Square normal to make all values positive + increase blend sharpness
|
|
float3 blendWeight = normal * normal;
|
|
// Divide blend weight by the sum of its components. This will make x + y + z = 1
|
|
blendWeight /= dot(blendWeight, 1);
|
|
return colX * blendWeight.x + colY * blendWeight.y + colZ * blendWeight.z;
|
|
}
|
|
|
|
float4 triplanarOffset(float3 vertPos, float3 normal, float3 scale, sampler2D tex, float2 offset) {
|
|
float3 scaledPos = vertPos / scale;
|
|
float4 colX = tex2D (tex, scaledPos.zy + offset);
|
|
float4 colY = tex2D(tex, scaledPos.xz + offset);
|
|
float4 colZ = tex2D (tex,scaledPos.xy + offset);
|
|
|
|
// Square normal to make all values positive + increase blend sharpness
|
|
float3 blendWeight = normal * normal;
|
|
// Divide blend weight by the sum of its components. This will make x + y + z = 1
|
|
blendWeight /= dot(blendWeight, 1);
|
|
return colX * blendWeight.x + colY * blendWeight.y + colZ * blendWeight.z;
|
|
}
|
|
|
|
float3 ObjectToTangentVector(float4 tangent, float3 normal, float3 objectSpaceVector) {
|
|
float3 normalizedTangent = normalize(tangent.xyz);
|
|
float3 binormal = cross(normal, normalizedTangent) * tangent.w;
|
|
float3x3 rot = float3x3 (normalizedTangent, binormal, normal);
|
|
return mul(rot, objectSpaceVector);
|
|
}
|
|
|
|
// Reoriented Normal Mapping
|
|
// http://blog.selfshadow.com/publications/blending-in-detail/
|
|
// Altered to take normals (-1 to 1 ranges) rather than unsigned normal maps (0 to 1 ranges)
|
|
float3 blend_rnm(float3 n1, float3 n2)
|
|
{
|
|
n1.z += 1;
|
|
n2.xy = -n2.xy;
|
|
|
|
return n1 * dot(n1, n2) / n1.z - n2;
|
|
}
|
|
|
|
// Sample normal map with triplanar coordinates
|
|
// Returned normal will be in obj/world space (depending whether pos/normal are given in obj or world space)
|
|
// Based on: medium.com/@bgolus/normal-mapping-for-a-triplanar-shader-10bf39dca05a
|
|
float3 triplanarNormal(float3 vertPos, float3 normal, float3 scale, float2 offset, sampler2D normalMap) {
|
|
float3 absNormal = abs(normal);
|
|
|
|
// Calculate triplanar blend
|
|
float3 blendWeight = saturate(pow(normal, 4));
|
|
// Divide blend weight by the sum of its components. This will make x + y + z = 1
|
|
blendWeight /= dot(blendWeight, 1);
|
|
|
|
// Calculate triplanar coordinates
|
|
float2 uvX = vertPos.zy * scale + offset;
|
|
float2 uvY = vertPos.xz * scale + offset;
|
|
float2 uvZ = vertPos.xy * scale + offset;
|
|
|
|
// Sample tangent space normal maps
|
|
// UnpackNormal puts values in range [-1, 1] (and accounts for DXT5nm compression)
|
|
float3 tangentNormalX = UnpackNormal(tex2D(normalMap, uvX));
|
|
float3 tangentNormalY = UnpackNormal(tex2D(normalMap, uvY));
|
|
float3 tangentNormalZ = UnpackNormal(tex2D(normalMap, uvZ));
|
|
|
|
// Swizzle normals to match tangent space and apply reoriented normal mapping blend
|
|
tangentNormalX = blend_rnm(half3(normal.zy, absNormal.x), tangentNormalX);
|
|
tangentNormalY = blend_rnm(half3(normal.xz, absNormal.y), tangentNormalY);
|
|
tangentNormalZ = blend_rnm(half3(normal.xy, absNormal.z), tangentNormalZ);
|
|
|
|
// Apply input normal sign to tangent space Z
|
|
float3 axisSign = sign(normal);
|
|
tangentNormalX.z *= axisSign.x;
|
|
tangentNormalY.z *= axisSign.y;
|
|
tangentNormalZ.z *= axisSign.z;
|
|
|
|
// Swizzle tangent normals to match input normal and blend together
|
|
float3 outputNormal = normalize(
|
|
tangentNormalX.zyx * blendWeight.x +
|
|
tangentNormalY.xzy * blendWeight.y +
|
|
tangentNormalZ.xyz * blendWeight.z
|
|
);
|
|
|
|
return outputNormal;
|
|
}
|
|
|
|
float3 triplanarNormalTangentSpace(float3 vertPos, float3 normal, float3 scale, float4 tangent, sampler2D normalMap) {
|
|
float3 textureNormal = triplanarNormal(vertPos, normal, scale, 0, normalMap);
|
|
return ObjectToTangentVector(tangent, normal, textureNormal);
|
|
}
|
|
|
|
float3 triplanarNormalTangentSpace(float3 vertPos, float3 normal, float3 scale, float2 offset, float4 tangent, sampler2D normalMap) {
|
|
float3 textureNormal = triplanarNormal(vertPos, normal, scale, offset, normalMap);
|
|
return ObjectToTangentVector(tangent, normal, textureNormal);
|
|
} |