// Soft Particle Shader
// Created by: Joshua Boggs
// Alpha's out fragments based on the depth of the scene
// =============================================================
//---------------------------------------------------------------------------
// Constants
//---------------------------------------------------------------------------
sampler2D baseMap : register(s0);
sampler2D depthMap : register(s1);
static const float g_farPlane = 50000.0f;
float4x4 World;
float4x4 View;
float4x4 Proj;
static const float g_fDepthThreshold = 100.0f;
static const float2 g_fPixelStep = { 1.0f / 1024.0f, 1.0f / 768.0f };
//---------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Colour : COLOR;
float2 TexCoord : TEXCOORD0;
float Depth : TEXCOORD1;
float3 ProjPos : TEXCOORD2;
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Vertex Shader
//---------------------------------------------------------------------------
VS_OUTPUT VSMain(float4 inPos : POSITION, float4 inColour : COLOR0, float2 inTex0 : TEXCOORD0)
{
VS_OUTPUT Out;
// Concatenate our world and view matrix into one
float4x4 matWorldView = mul(World, View);
// Transform our position into view space
Out.Pos = mul(inPos, matWorldView);
// Set our depth into into a single float, as COLOR.a has low precision
Out.Depth = Out.Pos.z;
// Now project our position into screen space
Out.Pos = mul(Out.Pos, Proj);
Out.TexCoord = inTex0;
Out.Colour = inColour;
Out.ProjPos.xyz = Out.Pos.xyw;// / Out.Pos.w);
return Out;
}
//---------------------------------------------------------------------------
// Pixel Shader
//---------------------------------------------------------------------------
float4 PSMain(VS_OUTPUT In) : SV_TARGET
{
float4 outColour = tex2D(baseMap, In.TexCoord) * In.Colour;
// Project position into tex co-ords
float2 projTexCoords = In.ProjPos.xy / In.ProjPos.z;
projTexCoords = (projTexCoords * 0.5f) + 0.5f;
projTexCoords.y = 1.0f - projTexCoords.y;
projTexCoords += (0.5f * g_fPixelStep);
// Scale our depth relative to the max distance so that it is between 0 and 1
float particleDepth = In.Depth / g_farPlane;
float sceneDepth = tex2D(depthMap, projTexCoords).a;
// find the absolute difference between the particle and scene depth
outColour.a = saturate((sceneDepth - particleDepth) * g_fDepthThreshold) * outColour.a;
return outColour;
}
// =============================================================
// The oil painting shader.
// Created by: Joshua Boggs
// ------------------------------------------------------------
// Symmetric Nearest Neighbour - An Edge Preserving Smoothing Filter:
// Samples a range of symmetric pixels around the current pixel to
// blur pixels whilst preserving edges. Giving it an oil painting look.
// =============================================================
//----------------------------------------------------
// Global Constants
//----------------------------------------------------
static const uint g_uiSampleRange = 4;
// offset by 4 to provide a bit more variance in our samples.
// this is simply what I found to work best for a large brush look.
static const float2 g_vSampleKernel[8] =
{
-(1.0f / 1024.0f) * 4.0f, (1.0f / 768.0f) * 4.0f,
(1.0f / 1024.0f) * 4.0f, -(1.0f / 768.0f) * 4.0f,
0.0f, (1.0f / 768.0f) * 4.0f,
0.0f, -(1.0f / 768.0f) * 4.0f,
(1.0f / 1024.0f) * 4.0f, (1.0f / 768.0f) * 4.0f,
-(1.0f / 1024.0f) * 4.0f, -(1.0f / 768.0f) * 4.0f,
-(1.0f / 1024.0f) * 4.0f, 0.0f,
(1.0f / 1024.0f) * 4.0f, 0.0f
};
//----------------------------------------------------
// Texture Samplers
//----------------------------------------------------
sampler2D ScreenTexture : register(s0); // register for screen quad
//----------------------------------------------------
// Main Pixel Shader Program
//----------------------------------------------------
float4 PSMain(float2 inTex0 : TEXCOORD0 ) : SV_TARGET
{
inTex0 = float2( (1.0f / 1024.0f) * 0.5f,(1.0f / 768.0f) * 0.5f ) + inTex0;
// Apply awesomeness.. NOW!
float3 vAccumColour = 0.0f;
float4 vFinalColour = 0.0f;
float fVariance[2];
float3 vSymmertricColours[2];
// Calculate our Squared Variance
vFinalColour = tex2D(ScreenTexture, inTex0);
float fOriginalGray = dot(vFinalColour, 0.333f);
for(int index = 0; index < g_uiSampleRange*2; index+=2)
{
// Grab our Symmetric Samples
vSymmertricColours[0] = tex2D( ScreenTexture, inTex0 + g_vSampleKernel[index] );
vSymmertricColours[1] = tex2D( ScreenTexture, inTex0 + g_vSampleKernel[index+1]);
// Variance^2 = SUM[n]( (sample[n].r - mean.r)^2 + (sample[n].g - mean.g)^2 + (sample[n].b - mean.b)^2 ) * 1 / N
fVariance[0] = dot(vSymmertricColours[0]-vFinalColour, vSymmertricColours[0]-vFinalColour);
fVariance[1] = dot(vSymmertricColours[1]-vFinalColour, vSymmertricColours[1]-vFinalColour);
if( fVariance[0] < fVariance[1] )
{
vAccumColour += vSymmertricColours[0];
}
else
{
vAccumColour += vSymmertricColours[1];
}
}
vAccumColour /= g_uiSampleRange;
// Pack our mean into RGB
vFinalColour.rgb = saturate(vAccumColour);
vFinalColour.a = 1.0f;
return vFinalColour;
}
;----------------------------------------------------------------------------
; Hardware Skinning Shader
; Created By: Joshua Boggs
;----------------------------------------------------------------------------
vs_1_1
;----------------------------------------------------------------------------
;
; Constants specified by the app
; c0-3 = ViewProj
; c4-7 = InvProj
; c8 = constants - 1.0f, 0.0f, 1.0f / farClipPlane, 1020.01f
; c10+ = bone matrices (with bone-to-skin-to-world transform)
;
; Vertex components (as specified in the vertex DECL)
; v0 = pVertex[i].position
; v1 = pVertex[i].blendweights
; v2 = pVertex[i].blendindices
; v3 = pVertex[i].normal
;
;----------------------------------------------------------------------------
dcl_position v0
dcl_blendweight v1
dcl_blendindices v2
dcl_normal v3
;----------------------------------------------------------------------------
; Determine the last blending weight
;----------------------------------------------------------------------------
mov r0.xyz, v1.xyz ; r0.xyz = w0, w1, w2
dp3 r0.w, v1.xyz, c8.xxxx ; r0.w = w0 + w1 + w2
add r0.w, -r0.w, c8.x ; r0.w = 1 - (w0 + w1 + w2) = w3
;----------------------------------------------------------------------------
; Decode the index - it is swizzled due to the usage of D3DCOLOR for
; packing the indices...
;----------------------------------------------------------------------------
mul r1, v2.zyxw, c8.wwww ; r1 = indices w/ offset
;----------------------------------------------------------------------------
; Transform the position and normal for each bone
; v0 = position
; v3 = normal
;----------------------------------------------------------------------------
; Get the index of the bone matrix [0]
mov a0.x, r1.x
; Transform position and normal
m4x3 r5, v0, c[a0.x + 10]
m3x3 r6, v3, c[a0.x + 10]
; Blend them
mul r5.xyz, r5.xyz, r0.xxx
mul r6.xyz, r6.xyz, r0.xxx
; Get the index of the bone matrix [1]
mov a0.x, r1.y
; Transform position and normal
m4x3 r2, v0, c[a0.x + 10]
m3x3 r3, v3, c[a0.x + 10]
; Blend them
mad r5.xyz, r2.xyz, r0.yyy, r5.xyz
mad r6.xyz, r3.xyz, r0.yyy, r6.xyz
; Get the index of the bone matrix [2]
mov a0.x, r1.z
; Transform position and normal
m4x3 r2, v0, c[a0.x + 10]
m3x3 r3, v3, c[a0.x + 10]
; Blend them
mad r5.xyz, r2.xyz, r0.zzz, r5.xyz
mad r6.xyz, r3.xyz, r0.zzz, r6.xyz
; Get the index of the bone matrix [3]
mov a0.x, r1.w
; Transform position and normal
m4x3 r2, v0, c[a0.x + 10]
m3x3 r3, v3, c[a0.x + 10]
; Blend them
mad r5.xyz, r2, r0.wwww, r5
mad r6.xyz, r3, r0.wwww, r6
;----------------------------------------------------------------------------
; Transform the resulting position into world space
;----------------------------------------------------------------------------
mov r5.w, c8.x ; r5 = world space position
m4x4 r10, r5, c0 ; r10 = clip-space position
;----------------------------------------------------------------------------
; Transform back into world-view space, and calculate depth
;----------------------------------------------------------------------------
mov oPos, r10 ; outputPos = clip-space position
m4x4 r9, r10, c4 ; r9 = world-view position
mul r10, r9, c8.z ; r10 = depth
;----------------------------------------------------------------------------
; Normalize the normal
;----------------------------------------------------------------------------
dp3 r11.x, r6.xyz, r6.xyz ; r11.x = length of normal
rsq r11.xyz, r11.x ; r11.xyz = 1/sqrt(length of normal)
mul r6.xyz, r6.xyz, r11.xyz ; r6 = normalized normal
;----------------------------------------------------------------------------
; Output Normals and Depth as Colour
;----------------------------------------------------------------------------
mov oD0.xyz, r6.xyz ; Normals
mov oD0.w, r10.z ; Depth