NLDClient-yudde/ProjectNLD/Assets/Code/Shaders/builtin_shaders-2022.3.17f1/CGIncludes/UnityRayTracingMeshUtils.cginc

332 lines
13 KiB
HLSL

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
#ifndef UNITY_RAY_TRACING_MESH_UTILS_INCLUDED
#define UNITY_RAY_TRACING_MESH_UTILS_INCLUDED
// This helper file contains a list of utility functions needed to fetch vertex attributes from within closesthit or anyhit shaders.
// HLSL example:
// struct Vertex
// {
// float3 position;
// float2 texcoord;
// };
// Vertex FetchVertex(uint vertexIndex)
// {
// Vertex v;
// v.position = UnityRayTracingFetchVertexAttribute3(vertexIndex, kVertexAttributePosition);
// v.texcoord = UnityRayTracingFetchVertexAttribute2(vertexIndex, kVertexAttributeTexCoord0);
// return v;
// }
// uint3 triangleIndices = UnityRayTracingFetchTriangleIndices(PrimitiveIndex());
// Vertex v0, v1, v2;
// v0 = FetchVertex(triangleIndices.x);
// v1 = FetchVertex(triangleIndices.y);
// v2 = FetchVertex(triangleIndices.z);
// Interpolate the vertices using the barycentric coordinates available as input to the closesthit or anyhit shaders.
#define kMaxVertexStreams 8
struct MeshInfo
{
uint vertexSize[kMaxVertexStreams]; // The stride between 2 consecutive vertices in the vertex buffer. There is an entry for each vertex stream.
uint baseVertex; // A value added to each index before reading a vertex from the vertex buffer.
uint vertexStart;
uint indexSize; // 0 when an index buffer is not used, 2 for 16-bit indices or 4 for 32-bit indices.
uint indexStart; // The location of the first index to read from the index buffer.
};
struct VertexAttributeInfo
{
uint Stream; // The stream index used to fetch the vertex attribute. There can be up to kMaxVertexStreams streams.
uint Format; // One of the kVertexFormat* values from bellow.
uint ByteOffset; // The attribute offset in bytes into the vertex structure.
uint Dimension; // The dimension (#channels) of the vertex attribute.
};
// Valid values for the attributeType parameter in UnityRayTracingFetchVertexAttribute* functions.
#define kVertexAttributePosition 0
#define kVertexAttributeNormal 1
#define kVertexAttributeTangent 2
#define kVertexAttributeColor 3
#define kVertexAttributeTexCoord0 4
#define kVertexAttributeTexCoord1 5
#define kVertexAttributeTexCoord2 6
#define kVertexAttributeTexCoord3 7
#define kVertexAttributeTexCoord4 8
#define kVertexAttributeTexCoord5 9
#define kVertexAttributeTexCoord6 10
#define kVertexAttributeTexCoord7 11
#define kVertexAttributeCount 12
static float4 unity_DefaultVertexAttributes[kVertexAttributeCount] =
{
float4(0, 0, 0, 0), // kVertexAttributePosition - always present in ray tracing.
float4(0, 0, 1, 0), // kVertexAttributeNormal
float4(1, 0, 0, 1), // kVertexAttributeTangent
float4(1, 1, 1, 1), // kVertexAttributeColor
float4(0, 0, 0, 0), // kVertexAttributeTexCoord0
float4(0, 0, 0, 0), // kVertexAttributeTexCoord1
float4(0, 0, 0, 0), // kVertexAttributeTexCoord2
float4(0, 0, 0, 0), // kVertexAttributeTexCoord3
float4(0, 0, 0, 0), // kVertexAttributeTexCoord4
float4(0, 0, 0, 0), // kVertexAttributeTexCoord5
float4(0, 0, 0, 0), // kVertexAttributeTexCoord6
float4(0, 0, 0, 0), // kVertexAttributeTexCoord7
};
// Supported
#define kVertexFormatFloat 0
#define kVertexFormatFloat16 1
#define kVertexFormatUNorm8 2
#define kVertexFormatUNorm16 4
#define kVertexFormatSNorm16 5
// Not supported
#define kVertexFormatSNorm8 3
#define kVertexFormatUInt8 6
#define kVertexFormatSInt8 7
#define kVertexFormatUInt16 8
#define kVertexFormatSInt16 9
#define kVertexFormatUInt32 10
#define kVertexFormatSInt32 11
StructuredBuffer<MeshInfo> unity_MeshInfo_RT;
StructuredBuffer<VertexAttributeInfo> unity_MeshVertexDeclaration_RT;
#if defined(SHADER_API_PS5)
Buffer<ByteAddressBuffer> unity_MeshVertexBuffers_RT;
#else
ByteAddressBuffer unity_MeshVertexBuffers_RT[kMaxVertexStreams];
#endif
ByteAddressBuffer unity_MeshIndexBuffer_RT;
static float4 unity_VertexChannelMask_RT[5] =
{
float4(0, 0, 0, 0),
float4(1, 0, 0, 0),
float4(1, 1, 0, 0),
float4(1, 1, 1, 0),
float4(1, 1, 1, 1)
};
// A normalized short (16-bit signed integer) is encode into data. Returns a float in the range [-1, 1].
float DecodeSNorm16(uint data)
{
const float invRange = 1.0f / (float)0x7fff;
// Get the two's complement if the sign bit is set (0x8000) meaning the bits will represent a short negative number.
int signedValue = data & 0x8000 ? -1 * ((~data & 0x7fff) + 1) : data;
// Use max otherwise a value of 32768 as input would be decoded to -1.00003052f. https://www.khronos.org/opengl/wiki/Normalized_Integer
return max(signedValue * invRange, -1.0f);
}
uint3 UnityRayTracingFetchTriangleIndices(uint primitiveIndex)
{
uint3 indices;
MeshInfo meshInfo = unity_MeshInfo_RT[0];
if (meshInfo.indexSize == 2)
{
const uint offsetInBytes = (meshInfo.indexStart + primitiveIndex * 3) << 1;
const uint dwordAlignedOffset = offsetInBytes & ~3;
const uint2 fourIndices = unity_MeshIndexBuffer_RT.Load2(dwordAlignedOffset);
if (dwordAlignedOffset == offsetInBytes)
{
indices.x = fourIndices.x & 0xffff;
indices.y = (fourIndices.x >> 16) & 0xffff;
indices.z = fourIndices.y & 0xffff;
}
else
{
indices.x = (fourIndices.x >> 16) & 0xffff;
indices.y = fourIndices.y & 0xffff;
indices.z = (fourIndices.y >> 16) & 0xffff;
}
indices = indices + meshInfo.baseVertex.xxx;
}
else if (meshInfo.indexSize == 4)
{
const uint offsetInBytes = (meshInfo.indexStart + primitiveIndex * 3) << 2;
indices = unity_MeshIndexBuffer_RT.Load3(offsetInBytes) + meshInfo.baseVertex.xxx;
}
else // meshInfo.indexSize == 0
{
const uint firstVertexIndex = primitiveIndex * 3 + meshInfo.vertexStart;
indices = firstVertexIndex.xxx + uint3(0, 1, 2);
}
return indices;
}
// Checks if the vertex attribute attributeType is present in one of the unity_MeshVertexBuffers_RT vertex streams.
bool UnityRayTracingHasVertexAttribute(uint attributeType)
{
VertexAttributeInfo vertexDecl = unity_MeshVertexDeclaration_RT[attributeType];
return vertexDecl.Dimension != 0;
}
// attributeType is one of the kVertexAttribute* defines
float2 UnityRayTracingFetchVertexAttribute2(uint vertexIndex, uint attributeType)
{
VertexAttributeInfo vertexDecl = unity_MeshVertexDeclaration_RT[attributeType];
const uint attributeDimension = vertexDecl.Dimension;
if (!UnityRayTracingHasVertexAttribute(attributeType) || attributeDimension > 4)
return unity_DefaultVertexAttributes[attributeType].xy;
const uint attributeByteOffset = vertexDecl.ByteOffset;
const uint vertexSize = unity_MeshInfo_RT[0].vertexSize[vertexDecl.Stream];
const uint vertexAddress = vertexIndex * vertexSize;
const uint attributeAddress = vertexAddress + attributeByteOffset;
const uint attributeFormat = vertexDecl.Format;
float2 value = float2(0, 0);
ByteAddressBuffer vertexBuffer = unity_MeshVertexBuffers_RT[NonUniformResourceIndex(vertexDecl.Stream)];
if (attributeFormat == kVertexFormatFloat)
{
value = asfloat(vertexBuffer.Load2(attributeAddress));
}
else if (attributeFormat == kVertexFormatFloat16)
{
const uint twoHalfs = vertexBuffer.Load(attributeAddress);
value = float2(f16tof32(twoHalfs), f16tof32(twoHalfs >> 16));
}
else if (attributeFormat == kVertexFormatSNorm16)
{
const uint twoShorts = vertexBuffer.Load(attributeAddress);
const float x = DecodeSNorm16(twoShorts & 0xffff);
const float y = DecodeSNorm16((twoShorts & 0xffff0000) >> 16);
value = float2(x, y);
}
else if (attributeFormat == kVertexFormatUNorm16)
{
const uint twoShorts = vertexBuffer.Load(attributeAddress);
const float x = (twoShorts & 0xffff) / float(0xffff);
const float y = ((twoShorts & 0xffff0000) >> 16) / float(0xffff);
value = float2(x, y);
}
return unity_VertexChannelMask_RT[attributeDimension].xy * value;
}
// attributeType is one of the kVertexAttribute* defines
float3 UnityRayTracingFetchVertexAttribute3(uint vertexIndex, uint attributeType)
{
VertexAttributeInfo vertexDecl = unity_MeshVertexDeclaration_RT[attributeType];
const uint attributeDimension = vertexDecl.Dimension;
if (!UnityRayTracingHasVertexAttribute(attributeType) || attributeDimension > 4)
return unity_DefaultVertexAttributes[attributeType].xyz;
const uint attributeByteOffset = vertexDecl.ByteOffset;
const uint vertexSize = unity_MeshInfo_RT[0].vertexSize[vertexDecl.Stream];
const uint vertexAddress = vertexIndex * vertexSize;
const uint attributeAddress = vertexAddress + attributeByteOffset;
const uint attributeFormat = vertexDecl.Format;
float3 value = float3(0, 0, 0);
ByteAddressBuffer vertexBuffer = unity_MeshVertexBuffers_RT[NonUniformResourceIndex(vertexDecl.Stream)];
if (attributeFormat == kVertexFormatFloat)
{
value = asfloat(vertexBuffer.Load3(attributeAddress));
}
else if (attributeFormat == kVertexFormatFloat16)
{
const uint2 fourHalfs = vertexBuffer.Load2(attributeAddress);
value = float3(f16tof32(fourHalfs.x), f16tof32(fourHalfs.x >> 16), f16tof32(fourHalfs.y));
}
else if (attributeFormat == kVertexFormatSNorm16)
{
const uint2 fourShorts = vertexBuffer.Load2(attributeAddress);
const float x = DecodeSNorm16(fourShorts.x & 0xffff);
const float y = DecodeSNorm16((fourShorts.x & 0xffff0000) >> 16);
const float z = DecodeSNorm16(fourShorts.y & 0xffff);
value = float3(x, y, z);
}
else if (attributeFormat == kVertexFormatUNorm16)
{
const uint2 fourShorts = vertexBuffer.Load2(attributeAddress);
const float x = (fourShorts.x & 0xffff) / float(0xffff);
const float y = ((fourShorts.x & 0xffff0000) >> 16) / float(0xffff);
const float z = (fourShorts.y & 0xffff) / float(0xffff);
value = float3(x, y, z);
}
else if (attributeFormat == kVertexFormatUNorm8)
{
const uint data = vertexBuffer.Load(attributeAddress);
value = float3(data & 0xff, (data & 0xff00) >> 8, (data & 0xff0000) >> 16) / 255.0f;
}
return unity_VertexChannelMask_RT[attributeDimension].xyz * value;
}
// attributeType is one of the kVertexAttribute* defines
float4 UnityRayTracingFetchVertexAttribute4(uint vertexIndex, uint attributeType)
{
VertexAttributeInfo vertexDecl = unity_MeshVertexDeclaration_RT[attributeType];
const uint attributeDimension = vertexDecl.Dimension;
if (!UnityRayTracingHasVertexAttribute(attributeType) || attributeDimension > 4)
return unity_DefaultVertexAttributes[attributeType];
const uint attributeByteOffset = vertexDecl.ByteOffset;
const uint vertexSize = unity_MeshInfo_RT[0].vertexSize[vertexDecl.Stream];
const uint vertexAddress = vertexIndex * vertexSize;
const uint attributeAddress = vertexAddress + attributeByteOffset;
const uint attributeFormat = vertexDecl.Format;
float4 value = float4(0, 0, 0, 0);
ByteAddressBuffer vertexBuffer = unity_MeshVertexBuffers_RT[NonUniformResourceIndex(vertexDecl.Stream)];
if (attributeFormat == kVertexFormatFloat)
{
value = asfloat(vertexBuffer.Load4(attributeAddress));
}
else if (attributeFormat == kVertexFormatFloat16)
{
const uint2 fourHalfs = vertexBuffer.Load2(attributeAddress);
value = float4(f16tof32(fourHalfs.x), f16tof32(fourHalfs.x >> 16), f16tof32(fourHalfs.y), f16tof32(fourHalfs.y >> 16));
}
else if (attributeFormat == kVertexFormatSNorm16)
{
const uint2 fourShorts = vertexBuffer.Load2(attributeAddress);
const float x = DecodeSNorm16(fourShorts.x & 0xffff);
const float y = DecodeSNorm16((fourShorts.x & 0xffff0000) >> 16);
const float z = DecodeSNorm16(fourShorts.y & 0xffff);
const float w = DecodeSNorm16((fourShorts.y & 0xffff0000) >> 16);
value = float4(x, y, z, w);
}
else if (attributeFormat == kVertexFormatUNorm16)
{
const uint2 fourShorts = vertexBuffer.Load2(attributeAddress);
const float x = (fourShorts.x & 0xffff) / float(0xffff);
const float y = ((fourShorts.x & 0xffff0000) >> 16) / float(0xffff);
const float z = (fourShorts.y & 0xffff) / float(0xffff);
const float w = ((fourShorts.y & 0xffff0000) >> 16) / float(0xffff);
value = float4(x, y, z, w);
}
else if (attributeFormat == kVertexFormatUNorm8)
{
const uint data = vertexBuffer.Load(attributeAddress);
value = float4(data & 0xff, (data & 0xff00) >> 8, (data & 0xff0000) >> 16, (data & 0xff000000) >> 24) / 255.0f;
}
return unity_VertexChannelMask_RT[attributeDimension] * value;
}
#endif //#ifndef UNITY_RAY_TRACING_MESH_UTILS_INCLUDED