Added terrain and basic terrain textures

This commit is contained in:
2026-06-12 20:57:07 +01:00
parent 65e0008b90
commit b86da7a45a
197 changed files with 20733 additions and 0 deletions

View File

@ -0,0 +1,164 @@
#ifndef SERVICE_PARALLAX_INCLUDED
#define SERVICE_PARALLAX_INCLUDED
// Please define a PerPixelHeightDisplacementParam parameter
// and ComputePerPixelHeightDisplacement function to sample the heightmap.
float2 ParallaxRaymarching(float2 viewDir, PerPixelHeightDisplacementParam ppdParam,
float strength, out float outHeight)
{
const float raymarch_steps = 10;
float2 uvOffset = 0;
const float stepSize = 1.0 / raymarch_steps;
float2 uvDelta = viewDir * (stepSize * strength);
float stepHeight = 1;
float surfaceHeight = ComputePerPixelHeightDisplacement(0, 0, ppdParam);
float2 prevUVOffset = uvOffset;
float prevStepHeight = stepHeight;
float prevSurfaceHeight = surfaceHeight;
for (int i = 1; i < raymarch_steps && stepHeight > surfaceHeight; i++)
{
prevUVOffset = uvOffset;
prevStepHeight = stepHeight;
prevSurfaceHeight = surfaceHeight;
uvOffset -= uvDelta;
stepHeight -= stepSize;
surfaceHeight = ComputePerPixelHeightDisplacement(uvOffset, 0, ppdParam);
}
float prevDifference = prevStepHeight - prevSurfaceHeight;
float difference = surfaceHeight - stepHeight;
float t = prevDifference / (prevDifference + difference);
uvOffset = prevUVOffset -uvDelta * t;
outHeight = surfaceHeight;
return uvOffset;
}
float2 ParallaxRaymarchingDynamic(float3 viewDir, PerPixelHeightDisplacementParam ppdParam,
float strength, float lod)
{
const float minLayers = 8.0;
const float maxLayers = 48.0;
// lod should be dot(normalWS, viewDirWS)
float numLayers = lerp(maxLayers, minLayers, clamp(lod, 0, 1));
if (viewDir.z < 0.001) return 0;
float heightScale = _Parallax; // 0.05
float layerDepth = 1.0 / numLayers;
float currLayerDepth = 0.0;
float2 deltaUV = viewDir.xy * heightScale / (viewDir.z * numLayers);
float2 uvOffset = 0;
float height = 1.0 - ComputePerPixelHeightDisplacement(0, 0, ppdParam);
for (int i = 0; i < numLayers; i++) {
currLayerDepth += layerDepth;
uvOffset -= deltaUV;
height = 1.0 - ComputePerPixelHeightDisplacement(uvOffset, 0, ppdParam);
if (height < currLayerDepth) {
break;
}
}
float2 prevOffset = uvOffset + deltaUV;
float nextDepth = height - currLayerDepth;
float prevDepth = 1.0 - ComputePerPixelHeightDisplacement(prevOffset, 0, ppdParam) -
currLayerDepth + layerDepth;
float2 parallaxUVs = lerp(uvOffset, prevOffset, nextDepth / (nextDepth - prevDepth));
return parallaxUVs;
}
float2 ParallaxRaymarchingDynamicOffset(float3 viewDir, PerPixelHeightDisplacementParam ppdParam,
float strength, float lod)
{
const float minLayers = 8.0;
const float maxLayers = 48.0;
float numLayers = lerp(maxLayers, minLayers, clamp(lod, 0, 1));
if (viewDir.z < 0.001) return 0;
float heightScale = _Parallax;
float refPlane = 0.5;
float layerDepth = 1.0 / numLayers;
float currLayerDepth = 0.0;
float2 totalDelta = viewDir.xy * heightScale / viewDir.z;
float2 deltaUV = totalDelta / numLayers;
// Shift the starting UVs forward so that the ray starts above the surface
float2 uvOffset = totalDelta * refPlane;
float height = 1.0 - ComputePerPixelHeightDisplacement(uvOffset, 0, ppdParam);
for (int i = 0; i < numLayers; i++) {
if (height < currLayerDepth) break;
currLayerDepth += layerDepth;
uvOffset -= deltaUV;
height = 1.0 - ComputePerPixelHeightDisplacement(uvOffset, 0, ppdParam);
}
float2 prevOffset = uvOffset + deltaUV;
float nextDepth = height - currLayerDepth;
float prevDepth = (1.0 - ComputePerPixelHeightDisplacement(prevOffset, 0, ppdParam)) -
(currLayerDepth - layerDepth);
float weight = nextDepth / (nextDepth - prevDepth);
float2 parallaxUVs = lerp(uvOffset, prevOffset, weight);
return parallaxUVs;
}
float GetParallaxSelfShadow(float3 lightDir, float2 uv, PerPixelHeightDisplacementParam ppdParam, float noise)
{
// lightDir.z is the cosine of the angle between the light and the tangent surface.
// If it's 0, we are at the horizon.
if (lightDir.z <= 0.0) return 0.0;
const int numSamples = 16;
float initialHeight = ComputePerPixelHeightDisplacement(0, 0, ppdParam);
// Scale the penumbra by the surface depth.
float shadowHardness = 1.0 / (_BumpShadowHardness);
float heightToTravel = 1.0 - initialHeight;
float2 uvStep = (lightDir.xy * _Parallax) / (lightDir.z * numSamples);
float stepHeight = heightToTravel / numSamples;
float2 currentOffset = uvStep * noise;
float currentRayHeight = initialHeight + (stepHeight * noise);
float shadowFactor = 1.0;
[unroll(numSamples)]
for(int i = 0; i < numSamples; i++)
{
float mipLOD = (float(i) / float(numSamples)) * 7.0;
float sampledHeight = ComputePerPixelHeightDisplacement(currentOffset, mipLOD, ppdParam);
if (sampledHeight > currentRayHeight)
{
float distanceAlongRay = (float)i / (float)numSamples;
float penetration = (sampledHeight - currentRayHeight) * (1.0 - distanceAlongRay);
shadowFactor = min(shadowFactor, saturate(1.0 - penetration * shadowHardness * numSamples));
}
if (shadowFactor <= 0.0) break;
currentOffset += uvStep;
currentRayHeight += stepHeight;
}
return shadowFactor;
}
#endif // SERVICE_PARALLAX_INCLUDED