139 lines
4.5 KiB
HLSL
139 lines
4.5 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
//
|
|
// Declare the placement projection struct and api
|
|
//
|
|
#include "SamplerStates.ush"
|
|
#include "TiledFetch_Combined.ush"
|
|
|
|
#ifndef PLACEMENT_PROJECTION_USH
|
|
#define PLACEMENT_PROJECTION_USH
|
|
|
|
|
|
// Convert the mesh map position to world coordinate
|
|
float3 MeshBoxMin;
|
|
float3 MeshBoxSize;
|
|
float3 MeshViewScale;
|
|
|
|
Texture2D MeshmapPos;
|
|
Texture2D MeshmapNor;
|
|
|
|
float2x3 Fetch_MeshSurface(float2 layer_uv)
|
|
{
|
|
float4 mesh_pos = MeshmapPos.SampleLevel(SamplerStates_NoBorder, layer_uv, 0);
|
|
float4 mesh_nor = MeshmapNor.SampleLevel(SamplerStates_NoBorder, layer_uv, 0);
|
|
|
|
// Center the mesh pos on the center of the Mesh bounding box
|
|
// the projection origin is centered on the pos origin
|
|
// Convert from cm to meter
|
|
//mesh_pos.xyz = (mesh_pos.xyz * MeshBoxExtent + MeshBoxOffset) * MeshViewScale;
|
|
mesh_pos.xyz = ((mesh_pos.xyz - 0.5) * MeshBoxSize) * MeshViewScale * 0.01;
|
|
|
|
// Unpack normal
|
|
mesh_nor.xyz = (mesh_nor.xyz * 2.0 - 1.0);
|
|
|
|
return float2x3( mesh_pos.xyz, mesh_nor.xyz );
|
|
}
|
|
|
|
float3 Transform_Pos_RotateAroundZX(float2 Zcs, float2 Xcs, float3 pos)
|
|
{
|
|
float3x3 rot = float3x3(
|
|
float3(Zcs.x, Zcs.y, 0),
|
|
float3(Xcs.x * -Zcs.y, Xcs.x * Zcs.x, Xcs.y),
|
|
float3(-Xcs.y * -Zcs.y, -Xcs.y * Zcs.x, Xcs.x)
|
|
);
|
|
|
|
return mul(pos, rot);
|
|
}
|
|
float3 Transform_Dir_RotateAroundZX(float2 Zcs, float2 Xcs, float3 dir)
|
|
{
|
|
float3x3 rot = float3x3(
|
|
float3(Zcs.x, Zcs.y, 0),
|
|
float3(Xcs.x * -Zcs.y, Xcs.x * Zcs.x, Xcs.y),
|
|
float3(-Xcs.y * -Zcs.y, -Xcs.y * Zcs.x, Xcs.x)
|
|
);
|
|
|
|
return mul(dir, rot);
|
|
}
|
|
|
|
float3x2 EvalTriplanar_uvs(float3 mesh_pos, float3 mesh_nor, float2 uv_scaling)
|
|
{
|
|
//offset for pushing projection planes sideways until centered
|
|
float2 offsetPivot = float2(0.5, 0.5);
|
|
|
|
float3 nsign = sign(mesh_nor.xyz);
|
|
//UNITY version for ref:
|
|
// float2 xuv = uv_scaling * (mesh_pos.zy + offsetPivot) * float2(nsign.x, 1.0);
|
|
//float2 yuv = uv_scaling * (mesh_pos.xz + offsetPivot) * float2(nsign.y, 1.0);
|
|
//float2 zuv = uv_scaling * (mesh_pos.xy + offsetPivot) * float2(-nsign.z, 1.0);
|
|
float2 xuv = (uv_scaling * mesh_pos.yz + offsetPivot) * float2(-nsign.x, 1.0);
|
|
float2 yuv = (uv_scaling * mesh_pos.xz + offsetPivot) * float2(nsign.y, 1.0);
|
|
float2 zuv = (uv_scaling * mesh_pos.xy + offsetPivot) * float2(nsign.z, -1.0);
|
|
|
|
return float3x2(xuv, yuv, zuv);
|
|
}
|
|
|
|
float3x4 Fetch_Source_Triplanar (Texture2DArray source, float3 mesh_pos, float3 mesh_nor, float2 uv_scaling)
|
|
{
|
|
float3x2 triplanar_uvs = EvalTriplanar_uvs(mesh_pos, mesh_nor, uv_scaling);
|
|
|
|
float4 sample_x = SampleLayerRaster(source, triplanar_uvs[0]);
|
|
float4 sample_y = SampleLayerRaster(source, triplanar_uvs[1]);
|
|
float4 sample_z = SampleLayerRaster(source, triplanar_uvs[2]);
|
|
|
|
return float3x4(sample_x, sample_y, sample_z);
|
|
}
|
|
|
|
float3x4 Fetch_Source_Triplanar(Texture2DArray source, float3x2 triplanar_uvs)
|
|
{
|
|
return float3x4(
|
|
SampleLayerRaster(source, triplanar_uvs[0]),
|
|
SampleLayerRaster(source, triplanar_uvs[1]),
|
|
SampleLayerRaster(source, triplanar_uvs[2])
|
|
);
|
|
}
|
|
|
|
// Convert height to mask value
|
|
float3 HeightMask(float3 triplanarHeightSamples, float midpoint, float strength)
|
|
{
|
|
return saturate((triplanarHeightSamples - midpoint) * strength);
|
|
}
|
|
|
|
// Fetch height from displacement map at triplanar coordinate
|
|
float3 HeightMaskFromDisplacement(Texture2DArray displacement, float3x2 triplanar_uvs, float midpoint, float strength)
|
|
{
|
|
if (strength < 0) /// BRANCH! do no go fetch anything if strength is 0
|
|
return float3(0, 0 , 0);
|
|
|
|
float3 triplanar_height;
|
|
triplanar_height.x = SampleLayerRaster(displacement, triplanar_uvs[0]).x;
|
|
triplanar_height.y = SampleLayerRaster(displacement, triplanar_uvs[1]).x;
|
|
triplanar_height.z = SampleLayerRaster(displacement, triplanar_uvs[2]).x;
|
|
|
|
return HeightMask(triplanar_height, midpoint, strength);
|
|
}
|
|
|
|
float EaseIn(float t)
|
|
{
|
|
return t == 0.0 ? t : pow(2.0, 10.0 * (t - 1.0));
|
|
}
|
|
|
|
float3 ProjectionNormals(float3 normals, float sharpenEdges, float3 heightMask)
|
|
{
|
|
//ease sharpen value for a more linear feel when dragging sliders
|
|
float eased = EaseIn(sharpenEdges);
|
|
|
|
//tighten projection borders, using multiple normalized pow to get sharp edges with no black corners on the planes
|
|
float remappedSharpen = 1.0 + eased * 9; //remap to 1-10 range
|
|
float3 maskedAbsNormals = max(0, (abs(normals) + heightMask));
|
|
//float3 maskedAbsNormals = saturate(abs(normals)+heightMask );
|
|
float3 pow1 = normalize(pow(maskedAbsNormals, remappedSharpen));
|
|
float3 pow2 = normalize(pow(pow1, remappedSharpen));
|
|
float3 pow3 = normalize(pow(pow2, remappedSharpen));
|
|
pow3 /= (pow3.x + pow3.y + pow3.z); // + 0.00001;
|
|
|
|
return saturate(pow3);
|
|
}
|
|
|
|
|
|
#endif |