#include "shared/point.hlsl" #include "shared/quat-functions.hlsl" static const float3 Corners[] = { float3(0, -1, 0), float3(1, -1, 0), float3(1, 1, 0), float3(1, 1, 0), float3(0, 1, 0), float3(0, -1, 0), }; cbuffer Params : register(b0) { float4 Color; float Size; float ShrinkWithDistance; float OffsetU; float VisibleRange; // float TransitionProgress; }; cbuffer Transforms : register(b1) { float4x4 CameraToClipSpace; float4x4 ClipSpaceToCamera; float4x4 WorldToCamera; float4x4 CameraToWorld; float4x4 WorldToClipSpace; float4x4 ClipSpaceToWorld; float4x4 ObjectToWorld; float4x4 WorldToObject; float4x4 ObjectToCamera; float4x4 ObjectToClipSpace; }; cbuffer FogParams : register(b2) { float4 FogColor; float FogDistance; float FogBias; } struct psInput { float4 position : SV_POSITION; float4 color : COLOR; float2 texCoord : TEXCOORD; float fog : FOG; }; sampler texSampler : register(s0); StructuredBuffer Points : t0; Texture2D texture2 : register(t1); psInput vsMain(uint id : SV_VertexID) { psInput output; float discardFactor = 1; uint SegmentCount, Stride; Points.GetDimensions(SegmentCount, Stride); float4 aspect = float4(CameraToClipSpace[1][1] / CameraToClipSpace[0][0], 1, 1, 1); int quadIndex = id % 6; uint particleId = id / 6; float3 cornerFactors = Corners[quadIndex]; Point pointAA = Points[particleId < 1 ? 0 : particleId - 1]; Point pointA = Points[particleId]; Point pointB = Points[particleId + 1]; Point pointBB = Points[particleId > SegmentCount - 2 ? SegmentCount - 2 : particleId + 2]; float3 posInObject = cornerFactors.x < 0.5 ? pointA.Position : pointB.Position; float4 aaInScreen = mul(float4(pointAA.Position, 1), ObjectToClipSpace) * aspect; aaInScreen /= aaInScreen.w; float4 aInScreen = mul(float4(pointA.Position, 1), ObjectToClipSpace) * aspect; if (aInScreen.z < -0) discardFactor = 0; aInScreen /= aInScreen.w; float4 bInScreen = mul(float4(pointB.Position, 1), ObjectToClipSpace) * aspect; if (bInScreen.z < -0) discardFactor = 0; bInScreen /= bInScreen.w; float4 bbInScreen = mul(float4(pointBB.Position, 1), ObjectToClipSpace) * aspect; bbInScreen /= bbInScreen.w; float3 direction = (aInScreen - bInScreen).xyz; float3 directionA = particleId > 0 ? (aaInScreen - aInScreen).xyz : direction; float3 directionB = particleId < SegmentCount - 1 ? (bInScreen - bbInScreen).xyz : direction; float3 normal = normalize(cross(direction, float3(0, 0, 1))); float3 normalA = normalize(cross(directionA, float3(0, 0, 1))); float3 normalB = normalize(cross(directionB, float3(0, 0, 1))); if (isnan(pointAA.Scale.x) || pointAA.Scale.x < 0.01) { normalA = normal; } if (isnan(pointBB.Scale.x) || pointAA.Scale.x < 0.01) { normalB = normal; } float3 neighboarNormal = lerp(normalA, normalB, cornerFactors.x); float3 meterNormal = (normal + neighboarNormal) / 2; float4 pos = lerp(aInScreen, bInScreen, cornerFactors.x); float4 posInCamSpace = mul(float4(posInObject, 1), ObjectToCamera); posInCamSpace.xyz /= posInCamSpace.w; posInCamSpace.w = 1; float wAtPoint = lerp(pointA.FX1, pointB.FX1, cornerFactors.x); // Buildup transition float widthAtPoint = pointA.Scale.x * pointB.Scale.x; if (!isnan(widthAtPoint)) { output.texCoord = float2(wAtPoint - OffsetU, cornerFactors.y / 2 + 0.5); } float thickness = !isnan(widthAtPoint) ? Size * discardFactor * lerp(1, 1 / (posInCamSpace.z), ShrinkWithDistance) : widthAtPoint; float miter = dot(-meterNormal, normal); pos += cornerFactors.y * 0.1f * thickness * float4(meterNormal, 0) / clamp(miter, -2.0, -0.13); output.position = pos / aspect; float3 n = cornerFactors.x < 0.5 ? cross(pointA.Position - pointAA.Position, pointA.Position - pointB.Position) : cross(pointB.Position - pointA.Position, pointB.Position - pointBB.Position); n = normalize(n); output.fog = pow(saturate(-posInCamSpace.z / FogDistance), FogBias); output.color.rgb = Color.rgb; output.color.a = Color.a; return output; } float4 psMain(psInput input) : SV_TARGET { float u = (input.texCoord.x + VisibleRange); float4 imgColor = texture2.Sample(texSampler, float2(u, input.texCoord.y)) * Color; float f1 = saturate((input.texCoord.x + VisibleRange) * 100); float f2 = 1 - saturate((input.texCoord.x) * 100); float t = f1 * f2; // return float4(lerp(imgColor.rgb, FogColor.rgb, input.fog * FogColor.a), imgColor.a * t); float4 col = input.color * imgColor; col.a *= t; col.rgb = lerp(col.rgb, FogColor.rgb, input.fog); return clamp(col, float4(0, 0, 0, 0), float4(1000, 1000, 1000, 1)); }