// File generated by Flax Materials Editor // Version: @0 #define MATERIAL 1 #define USE_PER_VIEW_CONSTANTS 1 @3 #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" #include "./Flax/GBufferCommon.hlsl" @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) float4x4 InverseViewProjectionMatrix; float4x3 WorldMatrix; float4x3 WorldMatrixInverseTransposed; float3 GridSize; float PerInstanceRandom; float Dummy0; float VolumetricFogMaxDistance; int ParticleStride; int ParticleIndex; @1META_CB_END // Particles attributes buffer ByteAddressBuffer ParticlesData : register(t0); // Shader resources @2 // Material properties generation input struct MaterialInput { float3 WorldPosition; float TwoSidedSign; float2 TexCoord; uint ParticleIndex; #if USE_VERTEX_COLOR half4 VertexColor; #endif float3x3 TBN; float4 SvPosition; float3 PreSkinnedPosition; float3 PreSkinnedNormal; float3 InstanceOrigin; float InstanceParams; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT]; #endif }; #define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix); // Removes the scale vector from the local to world transformation matrix (supports instancing) float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld) { // Extract per axis scales from localToWorld transform float scaleX = length(localToWorld[0]); float scaleY = length(localToWorld[1]); float scaleZ = length(localToWorld[2]); float3 invScale = float3( scaleX > 0.00001f ? 1.0f / scaleX : 0.0f, scaleY > 0.00001f ? 1.0f / scaleY : 0.0f, scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f); localToWorld[0] *= invScale.x; localToWorld[1] *= invScale.y; localToWorld[2] *= invScale.z; return localToWorld; } // Transforms a vector from tangent space to world space float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector) { return mul(tangentVector, input.TBN); } // Transforms a vector from world space to tangent space float3 TransformWorldVectorToTangent(MaterialInput input, float3 worldVector) { return mul(input.TBN, worldVector); } // Transforms a vector from world space to view space float3 TransformWorldVectorToView(MaterialInput input, float3 worldVector) { return mul(worldVector, (float3x3)ViewMatrix); } // Transforms a vector from view space to world space float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector) { return mul((float3x3)ViewMatrix, viewVector); } // Transforms a vector from local space to world space float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector) { float3x3 localToWorld = (float3x3)GetInstanceTransform(input); //localToWorld = RemoveScaleFromLocalToWorld(localToWorld); return mul(localVector, localToWorld); } // Transforms a vector from local space to world space float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector) { float3x3 localToWorld = (float3x3)GetInstanceTransform(input); //localToWorld = RemoveScaleFromLocalToWorld(localToWorld); return mul(localToWorld, worldVector); } // Gets the current object position (supports instancing) float3 GetObjectPosition(MaterialInput input) { return input.InstanceOrigin.xyz; } // Gets the current object size float3 GetObjectSize(MaterialInput input) { return float3(1, 1, 1); } // Get the current object random value (supports instancing) float GetPerInstanceRandom(MaterialInput input) { return input.InstanceParams; } // Get the current object LOD transition dither factor (supports instancing) float GetLODDitherFactor(MaterialInput input) { return 0; } // Gets the interpolated vertex color (in linear space) float4 GetVertexColor(MaterialInput input) { return 1; } uint GetParticleUint(uint particleIndex, int offset) { return ParticlesData.Load(particleIndex * ParticleStride + offset); } int GetParticleInt(uint particleIndex, int offset) { return asint(ParticlesData.Load(particleIndex * ParticleStride + offset)); } float GetParticleFloat(uint particleIndex, int offset) { return asfloat(ParticlesData.Load(particleIndex * ParticleStride + offset)); } float2 GetParticleVec2(uint particleIndex, int offset) { return asfloat(ParticlesData.Load2(particleIndex * ParticleStride + offset)); } float3 GetParticleVec3(uint particleIndex, int offset) { return asfloat(ParticlesData.Load3(particleIndex * ParticleStride + offset)); } float4 GetParticleVec4(uint particleIndex, int offset) { return asfloat(ParticlesData.Load4(particleIndex * ParticleStride + offset)); } float3 TransformParticlePosition(float3 input) { return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz; } float3 TransformParticleVector(float3 input) { return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz; } @8 // Get material properties function (for vertex shader) Material GetMaterialVS(MaterialInput input) { @5 } // Get material properties function (for domain shader) Material GetMaterialDS(MaterialInput input) { @6 } // Get material properties function (for pixel shader) Material GetMaterialPS(MaterialInput input) { @4 } // Pixel Shader function for Volumetric Fog material injection (local fog) META_PS(true, FEATURE_LEVEL_SM5) void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out float4 VBufferB : SV_Target1) { uint3 gridCoordinate = uint3(input.Vertex.Position.xy, input.LayerIndex); float3 cellOffset = 0.5f; float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy; float zSlice = gridCoordinate.z + cellOffset.z; float sceneDepth = (zSlice / GridSize.z) * VolumetricFogMaxDistance / ViewFar; float deviceDepth = (ViewInfo.w / sceneDepth) + ViewInfo.z; float4 clipPos = float4(volumeUV * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0); float4 wsPos = mul(clipPos, InverseViewProjectionMatrix); float3 positionWS = wsPos.xyz / wsPos.w; // Get material parameters MaterialInput materialInput = (MaterialInput)0; materialInput.WorldPosition = positionWS; materialInput.TexCoord = input.Vertex.TexCoord; materialInput.ParticleIndex = ParticleIndex; materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1)); materialInput.TwoSidedSign = 1.0f; materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz; materialInput.InstanceParams = PerInstanceRandom; materialInput.SvPosition = clipPos; Material material = GetMaterialPS(materialInput); // Compute fog properties float3 albedo = material.Color; float extinction = material.Opacity * material.Mask * 0.001f; float3 emission = material.Emissive; float3 scattering = albedo * extinction; float absorption = max(0.0f, extinction - Luminance(scattering)); // Write fog properties VBufferA = float4(scattering, absorption); VBufferB = float4(emission, 0); } @9