259 lines
7.1 KiB
HLSL
259 lines
7.1 KiB
HLSL
// Copyright (c) Wojciech Figat. All rights reserved.
|
|
|
|
#ifndef __COMMON__
|
|
#define __COMMON__
|
|
|
|
// Platform macros
|
|
#ifndef DIRECTX
|
|
#define DIRECTX 0
|
|
#endif
|
|
#ifndef OPENGL
|
|
#define OPENGL 0
|
|
#endif
|
|
#ifndef VULKAN
|
|
#define VULKAN 0
|
|
#endif
|
|
#ifdef PLATFORM_PS4
|
|
#include "./FlaxPlatforms/PS4/Shaders/PS4Common.hlsl"
|
|
#endif
|
|
#ifdef PLATFORM_PS5
|
|
#include "./FlaxPlatforms/PS5/Shaders/PS5Common.hlsl"
|
|
#endif
|
|
|
|
// Reversed Z support
|
|
#ifndef REVERSE_Z
|
|
#define REVERSE_Z 0
|
|
#endif
|
|
#if REVERSE_Z
|
|
#define DEPTH_RANGE_MIN 1
|
|
#define DEPTH_RANGE_MAX 0
|
|
#define DEPTH_CMP(l, r) (l > r)
|
|
#define DEPTH_DIFF(l, r) (r - l)
|
|
#define DEPTH_01(d) (1 - d)
|
|
#else
|
|
#define DEPTH_RANGE_MIN 0
|
|
#define DEPTH_RANGE_MAX 1
|
|
#define DEPTH_CMP(l, r) (l < r)
|
|
#define DEPTH_DIFF(l, r) (l - r)
|
|
#define DEPTH_01(d) (d)
|
|
#endif
|
|
|
|
// Feature levels
|
|
#define FEATURE_LEVEL_ES2 0
|
|
#define FEATURE_LEVEL_ES3 1
|
|
#define FEATURE_LEVEL_ES3_1 2
|
|
#define FEATURE_LEVEL_SM4 3
|
|
#define FEATURE_LEVEL_SM5 4
|
|
#define FEATURE_LEVEL_SM6 5
|
|
#if !defined(FEATURE_LEVEL)
|
|
#error "Invalid platform defines"
|
|
#endif
|
|
|
|
// Meta macros used by shaders parser
|
|
#define META_VS(isVisible, minFeatures)
|
|
#define META_VS_IN_ELEMENT(type, index, format, slot, offset, slotClass, stepRate, isVisible) // [Deprecated in v1.10]
|
|
#define META_HS(isVisible, minFeatures)
|
|
#define META_HS_PATCH(inControlPoints)
|
|
#define META_DS(isVisible, minFeatures)
|
|
#define META_GS(isVisible, minFeatures)
|
|
#define META_PS(isVisible, minFeatures)
|
|
#define META_CS(isVisible, minFeatures)
|
|
#define META_FLAG(flag)
|
|
#define META_PERMUTATION_1(param0)
|
|
#define META_PERMUTATION_2(param0, param1)
|
|
#define META_PERMUTATION_3(param0, param1, param2)
|
|
#define META_PERMUTATION_4(param0, param1, param2, param3)
|
|
#define META_CB_BEGIN(index, name) cbuffer name : register(b##index) {
|
|
#define META_CB_END };
|
|
|
|
#define SHADING_MODEL_UNLIT 0
|
|
#define SHADING_MODEL_LIT 1
|
|
#define SHADING_MODEL_SUBSURFACE 2
|
|
#define SHADING_MODEL_FOLIAGE 3
|
|
|
|
// Detect feature level support
|
|
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5 || defined(WGSL)
|
|
#define CAN_USE_GATHER 1
|
|
#else
|
|
#define CAN_USE_GATHER 0
|
|
#endif
|
|
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5 || defined(WGSL)
|
|
#define CAN_USE_COMPUTE_SHADER 1
|
|
#else
|
|
#define CAN_USE_COMPUTE_SHADER 0
|
|
#endif
|
|
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM4
|
|
#define CAN_USE_GEOMETRY_SHADER 1
|
|
#else
|
|
#define CAN_USE_GEOMETRY_SHADER 0
|
|
#endif
|
|
#if FEATURE_LEVEL >= FEATURE_LEVEL_SM5
|
|
#define CAN_USE_TESSELLATION 1
|
|
#else
|
|
#define CAN_USE_TESSELLATION 0
|
|
#endif
|
|
|
|
#if defined(WGSL)
|
|
// Alias read-only Buffer binded as shader resource into StructuredBuffer to be used as storage on WebGPU (not supported)
|
|
#define CAN_USE_TYPED_BUFFER_LOADS 0
|
|
#define Buffer StructuredBuffer
|
|
#define RWBuffer RWStructuredBuffer
|
|
|
|
// Hack matrix multiplication order for WebGPU (row-major vs column-major bug?)
|
|
#define PROJECT_POINT(p, m) mul(m, p)
|
|
|
|
// Stenil8 is in Red channel on WebGPU
|
|
#define STENCIL_BUFFER_SWIZZLE .r
|
|
#else
|
|
#define CAN_USE_TYPED_BUFFER_LOADS 1
|
|
#define PROJECT_POINT(p, m) mul(p, m)
|
|
#endif
|
|
|
|
// Compiler attributes
|
|
|
|
#if DIRECTX || VULKAN
|
|
|
|
// Avoids flow control constructs.
|
|
#define UNROLL [unroll]
|
|
|
|
// Gives preference to flow control constructs.
|
|
#define LOOP [loop]
|
|
|
|
// Performs branching by using control flow instructions like jmp and label.
|
|
#define BRANCH [branch]
|
|
|
|
// Performs branching by using the cnd instructions.
|
|
#define FLATTEN [flatten]
|
|
|
|
#endif
|
|
|
|
// Compiler support for HLSL 2021 that is stricter (need to use or/and/select for vector-based logical operators)
|
|
#if !defined(__DXC_VERSION_MAJOR) || (__DXC_VERSION_MAJOR <= 1 && __DXC_VERSION_MINOR < 7)
|
|
|
|
#define and(a, b) (a) && (b)
|
|
#define or(a, b) (a) || (b)
|
|
#define select(c, a, b) (c) ? (a) : (b)
|
|
|
|
#endif
|
|
|
|
// Compiler attribute fallback
|
|
#ifndef UNROLL
|
|
#define UNROLL
|
|
#endif
|
|
#ifndef LOOP
|
|
#define LOOP
|
|
#endif
|
|
#ifndef BRANCH
|
|
#define BRANCH
|
|
#endif
|
|
#ifndef FLATTEN
|
|
#define FLATTEN
|
|
#endif
|
|
|
|
#ifndef SamplerLinearClamp
|
|
// Static samplers
|
|
sampler SamplerLinearClamp : register(s0);
|
|
sampler SamplerPointClamp : register(s1);
|
|
sampler SamplerLinearWrap : register(s2);
|
|
sampler SamplerPointWrap : register(s3);
|
|
SamplerComparisonState ShadowSampler : register(s4);
|
|
SamplerComparisonState ShadowSamplerLinear : register(s5);
|
|
#endif
|
|
|
|
// General purpose macros
|
|
#define SAMPLE_RT(rt, texCoord) rt.SampleLevel(SamplerPointClamp, texCoord, 0)
|
|
#define SAMPLE_RT_LINEAR(rt, texCoord) rt.SampleLevel(SamplerLinearClamp, texCoord, 0)
|
|
#if defined(WGSL)
|
|
// WebGPU doesn't allow to sample depth texture with regular sampler, need to use Load instead of Sample and get texture size for UV to pixel coordinate conversion
|
|
float4 LoadTextureWGSL(Texture2D tex, float2 uv)
|
|
{
|
|
uint2 size;
|
|
tex.GetDimensions(size.x, size.y);
|
|
return tex.Load(uint3(size * uv, 0));
|
|
}
|
|
#define SAMPLE_RT_DEPTH(rt, texCoord) LoadTextureWGSL(rt, texCoord).r
|
|
#else
|
|
#define SAMPLE_RT_DEPTH(rt, texCoord) SAMPLE_RT(rt, texCoord).r
|
|
#endif
|
|
|
|
// General purpose constants
|
|
#define HDR_CLAMP_MAX 65472.0
|
|
#define PI 3.1415926535897932
|
|
#define UNITS_TO_METERS_SCALE 0.01f
|
|
|
|
struct Quad_VS2PS
|
|
{
|
|
float4 Position : SV_Position;
|
|
noperspective float2 TexCoord : TEXCOORD0;
|
|
};
|
|
|
|
struct Quad_VS2GS
|
|
{
|
|
Quad_VS2PS Vertex;
|
|
uint LayerIndex : TEXCOORD1;
|
|
};
|
|
|
|
struct Quad_GS2PS
|
|
{
|
|
Quad_VS2PS Vertex;
|
|
uint LayerIndex : SV_RenderTargetArrayIndex;
|
|
};
|
|
|
|
float Luminance(float3 color)
|
|
{
|
|
return dot(color, float3(0.299f, 0.587f, 0.114f));
|
|
}
|
|
|
|
// Quaternion multiplication (http://mathworld.wolfram.com/Quaternion.html)
|
|
float4 QuatMultiply(float4 q1, float4 q2)
|
|
{
|
|
return float4(q2.xyz * q1.w + q1.xyz * q2.w + cross(q1.xyz, q2.xyz), q1.w * q2.w - dot(q1.xyz, q2.xyz));
|
|
}
|
|
|
|
// Vector rotation with a quaternion (http://mathworld.wolfram.com/Quaternion.html)
|
|
float3 QuatRotateVector(float4 q, float3 v)
|
|
{
|
|
float4 nq = q * float4(-1, -1, -1, 1);
|
|
return QuatMultiply(q, QuatMultiply(float4(v, 0), nq)).xyz;
|
|
}
|
|
|
|
// Samples the unwrapped 3D texture (eg. volume texture of size 16x16x16 would be unwrapped to 256x16)
|
|
float4 SampleUnwrappedTexture3D(Texture2D tex, SamplerState s, float3 uvw, float size)
|
|
{
|
|
float intW = floor(uvw.z * size - 0.5);
|
|
half fracW = uvw.z * size - 0.5 - intW;
|
|
float u = (uvw.x + intW) / size;
|
|
float v = uvw.y;
|
|
float4 rg0 = tex.Sample(s, float2(u, v));
|
|
float4 rg1 = tex.Sample(s, float2(u + 1.0f / size, v));
|
|
return lerp(rg0, rg1, fracW);
|
|
}
|
|
|
|
// Converts compact 4x3 object transformation matrix into a full 4x4 matrix.
|
|
float4x4 ToMatrix4x4(float4x3 m)
|
|
{
|
|
return float4x4(float4(m[0].xyz, 0.0f), float4(m[1].xyz, 0.0f), float4(m[2].xyz, 0.0f), float4(m._m30, m._m31, m._m32, 1.0f));
|
|
}
|
|
|
|
// Maps clip-space position into screen-UV space. 1:-1 to 0:1
|
|
float2 ProjectClipToUV(float2 clipPos)
|
|
{
|
|
return clipPos * float2(0.5, -0.5) + float2(0.5, 0.5);
|
|
}
|
|
|
|
// Projects world-space position into clip-space space. (-1:1 from bottom/left to up/right)
|
|
float3 ProjectWorldToClip(float3 wsPos, float4x4 viewProjectionMatrix)
|
|
{
|
|
float4 clipPos = PROJECT_POINT(float4(wsPos, 1), viewProjectionMatrix);
|
|
return clipPos.xyz / clipPos.w;
|
|
}
|
|
|
|
// Projects world-space position into screen-UV space. (0:1 from top/left to bottom/right)
|
|
float3 ProjectWorldToUV(float3 wsPos, float4x4 viewProjectionMatrix)
|
|
{
|
|
float3 clipPos = ProjectWorldToClip(wsPos, viewProjectionMatrix);
|
|
return float3(ProjectClipToUV(clipPos.xy), clipPos.z);
|
|
}
|
|
|
|
#endif
|