You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.6 KiB
Plaintext

#pragma kernel BakeMeshKernel
#pragma kernel RayCastKernel
#pragma multi_compile __ IS_SKINNED_MESH
#include "../NormalHelperInclude.cginc"
#include "Thread.hlsl"
struct MeshProperties
{
float3 sourceVertex;
float3 sourceNormal;
float4 sourceTangent;
};
uniform RWByteAddressBuffer sourceMeshData;
uniform uint vertexBufferStride;
uniform RWStructuredBuffer<MeshProperties> bakedMesh;
#define SIZEOF_FLOAT3 12
uniform float4x4 transformMatrix;
uniform float4x4 rotationMatrix;
uniform uint verticesCount;
float3 loadSourceVertex(uint index)
{
return asfloat(sourceMeshData.Load3(index * vertexBufferStride));
}
float3 loadSourceNormal(uint index)
{
return mul(rotationMatrix, float4(asfloat(sourceMeshData.Load3(index * vertexBufferStride + SIZEOF_FLOAT3)), 1)).xyz;
}
float4 loadSourceTangent(uint index)
{
return mul(rotationMatrix, asfloat(sourceMeshData.Load4(index * vertexBufferStride + SIZEOF_FLOAT3 * 2)));
}
THREAD_SIZE
void BakeMeshKernel(uint3 id : SV_DispatchThreadID)
{
uint index = id.x;
if (index < verticesCount)
{
MeshProperties baked;
float3 vertex = loadSourceVertex(index);
baked.sourceVertex = mul(transformMatrix, float4(vertex, 1)).xyz;
baked.sourceNormal = loadSourceNormal(index);
baked.sourceTangent = loadSourceTangent(index);
bakedMesh[index] = baked;
}
}
float3 origin;
float3 direction;
RWByteAddressBuffer meshIndexBuffer;
AppendStructuredBuffer<MeshProperties> rayCastHits;
bool intersectTriangle(float3 a, float3 b, float3 c, out float3 barycentricCoordinate)
{
barycentricCoordinate = float3(0, 0, 0);
bool returnValue = true;
float3 ro = origin;
float3 rd = direction;
float3 ab = b - a;
float3 ac = c - a;
float3 n = cross(rd, ac);
float det = dot(ab, n);
if (abs(det) < 1e-5)
{
returnValue = false;
}
else
{
float invDet = 1.0 / det;
float3 k = ro - a;
float u = dot(k, n) * invDet;
if (u < 0.0 || u > 1.0)
{
returnValue = false;
}
else
{
float v = dot(rd, cross(k, ab)) * invDet;
if (v < 0.0 || u + v > 1.0)
{
returnValue = false;
}
else
{
float w = 1.0f - u - v;
barycentricCoordinate = float3(u, v, w);
}
}
}
return returnValue;
}
MeshProperties getBarycentricMeshData(MeshProperties mp1, MeshProperties mp2, MeshProperties mp3, float3 barycentricCoord)
{
MeshProperties interpolated;
interpolated.sourceVertex = Interpolate3(mp1.sourceVertex, mp2.sourceVertex, mp3.sourceVertex, barycentricCoord);
interpolated.sourceNormal = Interpolate3(mp1.sourceNormal, mp2.sourceNormal, mp3.sourceNormal, barycentricCoord);
interpolated.sourceTangent = Interpolate4(mp1.sourceTangent, mp2.sourceTangent, mp3.sourceTangent, barycentricCoord);
return interpolated;
}
MeshProperties createWorldPosMeshProperty(float3 worldVertex, MeshProperties mp)
{
MeshProperties meshProperty;
meshProperty.sourceVertex = worldVertex;
meshProperty.sourceNormal = mp.sourceNormal;
meshProperty.sourceTangent = mp.sourceTangent;
return meshProperty;
}
THREAD_SIZE_EDITOR
void RayCastKernel(uint3 id : SV_DispatchThreadID)
{
uint triangle1Index1 = id.x * 3;
uint triangle1Index2 = triangle1Index1 + 1;
uint triangle1Index3 = triangle1Index1 + 2;
triangle1Index1 = meshIndexBuffer.Load(triangle1Index1 * 4);
triangle1Index2 = meshIndexBuffer.Load(triangle1Index2 * 4);
triangle1Index3 = meshIndexBuffer.Load(triangle1Index3 * 4);
MeshProperties mp1 = bakedMesh[triangle1Index1];
MeshProperties mp2 = bakedMesh[triangle1Index2];
MeshProperties mp3 = bakedMesh[triangle1Index3];
float3 worldVertex1 = mul(transformMatrix, float4(mp1.sourceVertex, 1)).xyz;
float3 worldVertex2 = mul(transformMatrix, float4(mp2.sourceVertex, 1)).xyz;
float3 worldVertex3 = mul(transformMatrix, float4(mp3.sourceVertex, 1)).xyz;
float3 baryCentricCoordinate;
if (intersectTriangle(worldVertex3, worldVertex1, worldVertex2, baryCentricCoordinate))
{
MeshProperties meshData = getBarycentricMeshData(
createWorldPosMeshProperty(worldVertex1, mp1),
createWorldPosMeshProperty(worldVertex2, mp2),
createWorldPosMeshProperty(worldVertex3, mp3)
, baryCentricCoordinate
);
meshData.sourceNormal = mul(rotationMatrix, float4(meshData.sourceNormal, 1)).xyz;
meshData.sourceTangent = mul(rotationMatrix, meshData.sourceTangent);
rayCastHits.Append(
meshData
);
}
}