// This file is distributed under a BSD license. See LICENSE.txt for details. asc { cbuffer CubeHordeBasePara : register(c0) : slot vs 0 { float4x4 mvp; float4 lightDir; float4x3 lightMvp; float3 up; float4 shadowCol; float4 positions[8]; float4 normals[6]; }; cbuffer CubeHordePixelPara : register(c0) : slot ps 0 { float4 darkCol; float4 lightCol; float4 clipPlane; }; cbuffer CubeHordeXForm : register(c32) : slot vs 1 { float4 transform[224]; // 112*2 }; cbuffer BlurPara : register(c0) : slot vs 0 { float4x4 mvp; float2 pixelOffset; }; } // TODO: check out how to use functions with ASC so I don't have to copy&paste // the cube stuff every time :) // (variance) shadow map write shader CubeHordeShadowWrite : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; use CubeHordeXForm; void main( in int4 indices : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float out_z : TEXCOORD0, ) { // get input params float4 in_pos = positions[indices.x]; // x axis float3 x_axis = transform[indices.z]; // scale float lenXSq = dot(x_axis,x_axis); float lenXRSq = rsqrt(lenXSq); x_axis *= lenXRSq; float3 scale; scale.x = lenXSq * lenXRSq; scale.y = transform[indices.z].w; scale.z = transform[indices.z+1].w; // get transform for this cube float3 z_axis = normalize(cross(x_axis,up)); float3 y_axis = cross(z_axis,x_axis); float4 xlate = transform[indices.z+1]; // calc worldspace position float4 world_pos; float3 scaled_pos; scaled_pos = in_pos.xyz * scale; world_pos.xyz = scaled_pos.x * x_axis; world_pos.xyz += scaled_pos.y * y_axis; world_pos.xyz += scaled_pos.z * z_axis; world_pos.xyz += xlate.xyz; world_pos.w = 1.0f; // calc output position+z out_pos = mul(world_pos,mvp); out_z = mul(world_pos,lightMvp).z; } } } ps { asc ps_2_0 { void main( in float4 in_col : COLOR, in float in_z : TEXCOORD0, out float4 result : COLOR ) { result = in_z; } } } }; // render with shadow map shader CubeHordeShadowRender : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; use CubeHordeXForm; void main( in int4 indices : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float4 out_col : COLOR, out float3 out_mpos : TEXCOORD0, out float3 out_ldir : TEXCOORD1, out float3 out_lrpos : TEXCOORD2, // light-relative position ) { // get input params float4 in_pos = positions[indices.x]; // x axis float3 x_axis = transform[indices.z]; // scale float lenXSq = dot(x_axis,x_axis); float lenXRSq = rsqrt(lenXSq); x_axis *= lenXRSq; float3 scale; scale.x = lenXSq * lenXRSq; scale.y = transform[indices.z].w; scale.z = transform[indices.z+1].w; // get transform for this cube float3 z_axis = normalize(cross(x_axis,up)); float3 y_axis = cross(z_axis,x_axis); float4 xlate = transform[indices.z+1]; // calc worldspace position float4 world_pos; float3 scaled_pos; scaled_pos = in_pos.xyz * scale; world_pos.xyz = scaled_pos.x * x_axis; world_pos.xyz += scaled_pos.y * y_axis; world_pos.xyz += scaled_pos.z * z_axis; world_pos.xyz += xlate.xyz; world_pos.w = 1.0f; // calc output position/color/light dir out_pos = mul(world_pos,mvp); out_col = in_col; out_mpos = in_pos; out_ldir = lightDir; out_ldir.x = dot(lightDir,x_axis); out_ldir.y = dot(lightDir,y_axis); out_ldir.z = dot(lightDir,z_axis); out_lrpos = mul(world_pos,lightMvp); } } } ps { asc ps_2_0 { use CubeHordePixelPara; samplerCUBE sampNormal : register(s0); sampler2D sampShadow : register(s1); void main( in float4 in_col : COLOR, in float3 in_mpos : TEXCOORD0, in float3 in_ldir : TEXCOORD1, in float3 in_lrpos : TEXCOORD2, out float4 result : COLOR ) { // normal from model position float3 normal = texCUBE(sampNormal,in_mpos); // shade (diffuse, directional) float lightTerm = saturate(dot(normal,in_ldir)); float4 baseCol = in_col * saturate(dot(normal,in_ldir)); // read shadow map, variance shadow map computation float2 moments = tex2D(sampShadow,in_lrpos.xy); float litFactor = in_lrpos.z <= moments.x+0.01; result = lerp(darkCol,lightCol,lightTerm * (litFactor * 0.9 + 0.1)); //result = baseCol * (litFactor * 0.9 + 0.1); /*float variance = moments.y - moments.x*moments.x; float md = moments.x - in_lrpos.z; float pMax = min(variance / (variance + md*md),1.0f); result = baseCol * (max(litFactor,pMax) * 0.9 + 0.1);*/ } } } }; // render with shadow map and plane clip shader CubeHordeShadowRenderClip : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; use CubeHordeXForm; void main( in int4 indices : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float4 out_col : COLOR, out float3 out_mpos : TEXCOORD0, out float3 out_ldir : TEXCOORD1, out float3 out_lrpos : TEXCOORD2, // light-relative position out float3 out_wpos : TEXCOORD3, // world position ) { // get input params float4 in_pos = positions[indices.x]; // x axis float3 x_axis = transform[indices.z]; // scale float lenXSq = dot(x_axis,x_axis); float lenXRSq = rsqrt(lenXSq); x_axis *= lenXRSq; float3 scale; scale.x = lenXSq * lenXRSq; scale.y = transform[indices.z].w; scale.z = transform[indices.z+1].w; // get transform for this cube float3 z_axis = normalize(cross(x_axis,up)); float3 y_axis = cross(z_axis,x_axis); float4 xlate = transform[indices.z+1]; // calc worldspace position float4 world_pos; float3 scaled_pos; scaled_pos = in_pos.xyz * scale; world_pos.xyz = scaled_pos.x * x_axis; world_pos.xyz += scaled_pos.y * y_axis; world_pos.xyz += scaled_pos.z * z_axis; world_pos.xyz += xlate.xyz; world_pos.w = 1.0f; // calc output position/color/light dir out_pos = mul(world_pos,mvp); out_col = in_col; out_mpos = in_pos; out_ldir = lightDir; out_ldir.x = dot(lightDir,x_axis); out_ldir.y = dot(lightDir,y_axis); out_ldir.z = dot(lightDir,z_axis); out_lrpos = mul(world_pos,lightMvp); out_wpos = world_pos; } } } ps { asc ps_2_0 { use CubeHordePixelPara; samplerCUBE sampNormal : register(s0); sampler2D sampShadow : register(s1); void main( in float4 in_col : COLOR, in float3 in_mpos : TEXCOORD0, in float3 in_ldir : TEXCOORD1, in float3 in_lrpos : TEXCOORD2, in float3 in_wpos : TEXCOORD3, out float4 result : COLOR ) { // normal from model position float3 normal = texCUBE(sampNormal,in_mpos); // shade (diffuse, directional) float lightTerm = saturate(dot(normal,in_ldir)); float4 baseCol = in_col * saturate(dot(normal,in_ldir)); // read shadow map, variance shadow map computation float2 moments = tex2D(sampShadow,in_lrpos.xy); float litFactor = in_lrpos.z <= moments.x+0.01; result = lerp(darkCol,lightCol,lightTerm * (litFactor * 0.9 + 0.1)); // clip this! clip(dot(float4(in_wpos,1),clipPlane)); } } } }; // lotsa cubes ahoy! shader CubeHordeShaderClip : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; use CubeHordeXForm; void main( in int4 indices : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float4 out_col : COLOR, out float3 out_mpos : TEXCOORD0, out float3 out_ldir : TEXCOORD1, out float3 out_wpos : TEXCOORD2, ) { // get input params float4 in_pos = positions[indices.x]; // x axis float3 x_axis = transform[indices.z]; // scale float lenXSq = dot(x_axis,x_axis); float lenXRSq = rsqrt(lenXSq); x_axis *= lenXRSq; float3 scale; scale.x = lenXSq * lenXRSq; scale.y = transform[indices.z].w; scale.z = transform[indices.z+1].w; // get transform for this cube float3 z_axis = normalize(cross(x_axis,up)); float3 y_axis = cross(z_axis,x_axis); float4 xlate = transform[indices.z+1]; // calc worldspace position float4 world_pos; float3 scaled_pos; scaled_pos = in_pos.xyz * scale; world_pos.xyz = scaled_pos.x * x_axis; world_pos.xyz += scaled_pos.y * y_axis; world_pos.xyz += scaled_pos.z * z_axis; world_pos.xyz += xlate.xyz; world_pos.w = 1.0f; // calc output position/color/light dir out_pos = mul(world_pos,mvp); out_col = in_col; out_mpos = in_pos; out_ldir = lightDir; out_ldir.x = dot(lightDir,x_axis); out_ldir.y = dot(lightDir,y_axis); out_ldir.z = dot(lightDir,z_axis); out_wpos = world_pos; } } } ps { asc ps_2_0 { use CubeHordePixelPara; samplerCUBE sampNormal : register(s0); void main( in float4 in_col : COLOR, in float3 in_mpos : TEXCOORD0, in float3 in_ldir : TEXCOORD1, in float3 in_wpos : TEXCOORD2, out float4 result : COLOR ) { // normal from model position float3 normal = texCUBE(sampNormal,in_mpos); // shade (diffuse, directional) float lightTerm = saturate(dot(normal,in_ldir)); result = lerp(darkCol,lightCol,lightTerm); // clip this! clip(dot(float4(in_wpos,1),clipPlane)); } } } }; // lotsa cubes ahoy! shader CubeHordeShader : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; use CubeHordeXForm; void main( in int4 indices : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float4 out_col : COLOR, out float3 out_mpos : TEXCOORD0, out float3 out_ldir : TEXCOORD1, ) { // get input params float4 in_pos = positions[indices.x]; // x axis float3 x_axis = transform[indices.z]; // scale float lenXSq = dot(x_axis,x_axis); float lenXRSq = rsqrt(lenXSq); x_axis *= lenXRSq; float3 scale; scale.x = lenXSq * lenXRSq; scale.y = transform[indices.z].w; scale.z = transform[indices.z+1].w; // get transform for this cube float3 z_axis = normalize(cross(x_axis,up)); float3 y_axis = cross(z_axis,x_axis); float4 xlate = transform[indices.z+1]; // calc worldspace position float4 world_pos; float3 scaled_pos; scaled_pos = in_pos.xyz * scale; world_pos.xyz = scaled_pos.x * x_axis; world_pos.xyz += scaled_pos.y * y_axis; world_pos.xyz += scaled_pos.z * z_axis; world_pos.xyz += xlate.xyz; world_pos.w = 1.0f; // calc output position/color/light dir out_pos = mul(world_pos,mvp); out_col = in_col; out_mpos = in_pos; out_ldir = lightDir; out_ldir.x = dot(lightDir,x_axis); out_ldir.y = dot(lightDir,y_axis); out_ldir.z = dot(lightDir,z_axis); } } } ps { asc ps_2_0 { use CubeHordePixelPara; samplerCUBE sampNormal : register(s0); void main( in float4 in_col : COLOR, in float3 in_mpos : TEXCOORD0, in float3 in_ldir : TEXCOORD1, out float4 result : COLOR ) { // normal from model position float3 normal = texCUBE(sampNormal,in_mpos); // shade (diffuse, directional) float lightTerm = saturate(dot(normal,in_ldir)); result = lerp(darkCol,lightCol,lightTerm); } } } }; // for the ground plane; no lighting, no tex, no zwrite variant. // (this is a normal render-triangles-with-VSM shader) shader GroundPlaneShader : sASCMaterial { vs { asc vs_2_0 { use CubeHordeBasePara; void main( in float4 in_pos : POSITION, in float4 in_col : COLOR, out float4 out_pos : POSITION, out float4 out_col : COLOR, out float3 out_lrpos : TEXCOORD0, // light-relative position ) { // this is pretty straightforward. out_pos = mul(in_pos,mvp); out_col = shadowCol; out_lrpos = mul(in_pos,lightMvp); } } } ps { asc ps_2_0 { sampler2D sampShadow : register(s0); void main( in float4 in_col : COLOR, in float3 in_lrpos : TEXCOORD0, out float4 result : COLOR ) { // read shadow map, variance shadow map computation float2 moments = tex2D(sampShadow,in_lrpos.xy); float litFactor = saturate(in_lrpos.z) <= moments.x+0.01; //result = in_col * (litFactor * 0.9 + 0.1); result = lerp(in_col, float4(0,0,0,0), litFactor * 0.9 + 0.1); /*float variance = moments.y - moments.x*moments.x; float md = moments.x - in_lrpos.z; float pMax = min(variance / (variance + md*md),1.0f); result = in_col * (max(litFactor,pMax) * 0.9 + 0.1);*/ } } } }; // simple blur shader shader BlurShader : sASCMaterial { vs { asc vs_2_0 { use BlurPara; void main( in float4 in_pos : POSITION, in float4 in_uv : TEXCOORD0, out float4 out_pos : POSITION, out float2 out_uv0 : TEXCOORD0, out float2 out_uv1 : TEXCOORD1, out float2 out_uv2 : TEXCOORD2, out float2 out_uv3 : TEXCOORD3, out float2 out_uv4 : TEXCOORD4, ) { // this is pretty straightforward. out_pos = mul(in_pos,mvp); out_uv0 = in_uv - 2 * pixelOffset; out_uv1 = in_uv - pixelOffset; out_uv2 = in_uv; out_uv3 = in_uv + pixelOffset; out_uv4 = in_uv + 2 * pixelOffset; } } } ps { asc ps_2_0 { sampler2D samp0 : register(s0); sampler2D samp1 : register(s1); sampler2D samp2 : register(s2); void main( in float2 in_uv0 : TEXCOORD0, in float2 in_uv1 : TEXCOORD1, in float2 in_uv2 : TEXCOORD2, in float2 in_uv3 : TEXCOORD3, in float2 in_uv4 : TEXCOORD4, out float4 result : COLOR ) { // read pixels float4 p0 = tex2D(samp0,in_uv0); float4 p1 = tex2D(samp1,in_uv1); float4 p2 = tex2D(samp2,in_uv2); float4 p3 = tex2D(samp0,in_uv3); float4 p4 = tex2D(samp1,in_uv4); // weighted sum for results: (1 4 6 4 1)/16 result = 1.0/16.0 * (p0 + p4) + 1.0/4.0 * (p1 + p3) + 3.0/8.0 * p2; } } } };