forked from phenom/healer-man
96 lines
3.7 KiB
HLSL
96 lines
3.7 KiB
HLSL
// Globals
|
|
float4x3 g_worldTransform : register(c0);
|
|
float4x3 g_viewTransform : register(c3);
|
|
float4x4 g_projectionTransform : register(c6);
|
|
|
|
float4 g_ambientColor : register(c10);
|
|
float4 g_shCoefficients[9] : register(c11); // Spherical harmonics coefficients
|
|
float4 g_specularDirection : register(c21); // Object space specular position
|
|
float4 g_specularColor : register(c22);
|
|
float4 g_selfIllumination : register(c23); // Self-illumination term
|
|
float4 g_globalSettings : register(c25); // (Fog Constant, Start, End, Extrude Scale)
|
|
float4 g_globalDiffuse : register(c26);
|
|
float4x4 g_billboardTransform : register(c27); // Billboard transform
|
|
float4 g_prtParam : register(c31); // (u increment, v increment, AR, world ROT)
|
|
float4 g_quadScaleOffset : register(c32); // (scaleX, scaleY, offsetX, offsetY)
|
|
float4x4 g_orientationTransform : register(c33); // Particle poly orientation transform
|
|
float4 g_instanceData[210] : register(c37); // Instance data
|
|
|
|
struct VS_INPUT
|
|
{
|
|
float4 position : POSITION;
|
|
float4 diffuse : COLOR0;
|
|
};
|
|
|
|
struct VS_OUTPUT
|
|
{
|
|
float4 position : POSITION;
|
|
float4 diffuse : COLOR0;
|
|
float2 uv_albedo : TEXCOORD0;
|
|
float1 fog : TEXCOORD1;
|
|
};
|
|
|
|
VS_OUTPUT main(const VS_INPUT v)
|
|
{
|
|
VS_OUTPUT output;
|
|
|
|
// Initialize world-view vectors to 1
|
|
float4 worldPos = float4(1, 1, 1, 1);
|
|
|
|
// Calculate instance data indices
|
|
float1 posScaleOffset = (v.diffuse.w * 256.0f) * 3.0f;
|
|
float1 uvRotOffset = posScaleOffset + 1.0f;
|
|
float1 colorOffset = uvRotOffset + 1.0f;
|
|
|
|
// Scale & translate position by quad scale/offset
|
|
float3 scaledPosition = v.position.xyz;
|
|
scaledPosition.y = (scaledPosition.y + g_quadScaleOffset[2]) * g_quadScaleOffset[0];
|
|
scaledPosition.z = (scaledPosition.z + g_quadScaleOffset[3]) * g_quadScaleOffset[1] * g_prtParam.z;
|
|
|
|
// Scale position by particle scale
|
|
scaledPosition = scaledPosition * g_instanceData[(int) posScaleOffset].www;
|
|
|
|
// Rotate position
|
|
float3 rotRow0 = float3(0.0f, g_instanceData[(int) uvRotOffset].w, -g_instanceData[(int) uvRotOffset].z);
|
|
float3 rotRow1 = float3(0.0f, g_instanceData[(int) uvRotOffset].z, g_instanceData[(int) uvRotOffset].w);
|
|
worldPos.x = scaledPosition.x;
|
|
worldPos.y = dot(scaledPosition, rotRow0);
|
|
worldPos.z = dot(scaledPosition, rotRow1);
|
|
|
|
// Orientation transform
|
|
worldPos.xyz = mul(worldPos, (float4x3) g_orientationTransform);
|
|
|
|
// Handle world rotation
|
|
float4 rotatedWorldPos = float4(1, 1, 1, 1);
|
|
rotatedWorldPos.xyz = mul(worldPos, (float3x3) g_worldTransform);
|
|
worldPos = lerp(worldPos, rotatedWorldPos, g_prtParam.w);
|
|
|
|
// Billboard transform
|
|
worldPos.xyz = mul(worldPos, (float3x3) g_billboardTransform);
|
|
|
|
// Transform position to world space
|
|
float4 particleWorldPos = float4(1, 1, 1, 1);
|
|
particleWorldPos.xyz = g_instanceData[(int) posScaleOffset].xyz;
|
|
worldPos.xyz = worldPos.xyz + mul(particleWorldPos, (float4x3) g_worldTransform);
|
|
|
|
// Transform position to view space
|
|
float4 viewPos = float4(1, 1, 1, 1);
|
|
viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);
|
|
|
|
// Transform position to homogeneous space
|
|
output.position = mul(viewPos, (float4x4) g_projectionTransform);
|
|
|
|
// Calculate fog
|
|
float1 rcpFogRange = 1.0f / (g_globalSettings.z - g_globalSettings.y);
|
|
float1 relativeZ = max(viewPos.z - g_globalSettings.y, 0.0f);
|
|
output.fog = clamp(min(1.0f - (relativeZ * rcpFogRange), 1.0f - g_globalSettings.x), 0.0f, 1.0f);
|
|
|
|
// Multiply particle color by global diffuse
|
|
output.diffuse = g_instanceData[(int) colorOffset] * g_globalDiffuse;
|
|
|
|
// Calculate UV based on current frame index and texture uv increment
|
|
output.uv_albedo.xy = (g_instanceData[(int) uvRotOffset].xy * g_prtParam.xy) + v.diffuse.xy * g_prtParam.xy;
|
|
|
|
return output;
|
|
}
|