#define SHADOWMAP_SIZE 512.0f // The size of ShadowMap // Offsets in the ShadowMap #define HALF 0.5f / SHADOWMAP_SIZE #define ONE 1.0f / SHADOWMAP_SIZE #define TWO 2.0f / SHADOWMAP_SIZE #define THREE 3.0f / SHADOWMAP_SIZE #define FIVE 5.0f / SHADOWMAP_SIZE #define TEN 10.0f / SHADOWMAP_SIZE #define AMB float4(0.5,0.5,0.5,1) // Power of the ambient light #define FI 1000 // Summarized power of the light source //---------------------------------------------- // GLOBAL VARIABLES //--------------------------------------------- float3 g_vCameraPos3f; // Camera position float3 g_vLightPos3f; // Light source position int g_iNumberOfIteration; // Number of iteration int g_iObjectID; // ID of the current object int g_iPhotonMapSize; // PhotonMap size float g_fFresnelFactor; // Fresnel factor float g_fPower; // Power of light source float g_fRefractionIndex; // Refraction index float g_fShadowIntensity; // Shadow intensity float g_fCausticsIntensity; // The intensity of a caustics snippet bool g_bShadowON; // Shadow is used? bool g_bShowHelp; // Darken the scene if help is on float4x4 g_mWorldView; // WorldView transformation matrix float4x4 g_mWorldViewProjection; // WorldViewProjection transformation matrix float4x4 g_mWorldCenterObject; // World transformation matrix of CenterObject float4x4 g_mLightViewTexBias; // Light space transformation matrix texture g_txRoomMap; // Contains the original texture of the Room texture g_txRoomCubeMapColorDistanceMap; // Contains the color and distance information in a CubeMap texture g_txRoomCubeMapUVMap; // Contains the UV and ID of the object in a CubeMap texture g_txPhotonUVMap; // Contains the photon hits UV and ID information texture g_txPowerOfSnippetMap; // Contains the Gaussian filter texture g_txRoomModifyMap; // Contains the texture of the Room with shadow and Caustics effect and black edges texture g_txRoomLastMap; // Contains the texture of the Room // Contain the textures of the Columns with shadow and Caustics effect texture g_txColumnModifyTexture0, g_txColumnLastTexture0; texture g_txColumnModifyTexture1, g_txColumnLastTexture1; texture g_txColumnModifyTexture2, g_txColumnLastTexture2; texture g_txColumnModifyTexture3, g_txColumnLastTexture3; texture g_txColumnOriginalTexture; // Contains the original texture of a Column texture g_txShadowMap; // Contains the shadowMap //----------------------------------------------------------------------------- // SAMPLERS // Each texture must have its own sampler //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // macro definition for filtered samplers //----------------------------------------------------------------------------- #define SAMPLER_LINEAR(g_samplerMap, g_txMap); \ sampler2D g_samplerMap = sampler_state { \ Texture = ; \ MinFilter = Linear; \ MagFilter = Linear; \ MipFilter = Linear; \ AddressU = BORDER; \ AddressV = BORDER; \ }; SAMPLER_LINEAR(g_samplerRoomMap, g_txRoomMap); SAMPLER_LINEAR(g_samplerRoomLastMap, g_txRoomLastMap); SAMPLER_LINEAR(g_samplerPhotonUVMap, g_txPhotonUVMap); SAMPLER_LINEAR(g_samplerPowerOfSnippetMap, g_txPowerOfSnippetMap); SAMPLER_LINEAR(g_samplerColumnLast0Map, g_txColumnLastTexture0); SAMPLER_LINEAR(g_samplerColumnLast1Map, g_txColumnLastTexture1); SAMPLER_LINEAR(g_samplerColumnLast2Map, g_txColumnLastTexture2); SAMPLER_LINEAR(g_samplerColumnLast3Map, g_txColumnLastTexture3); SAMPLER_LINEAR(g_samplerColumnOriginalMap, g_txColumnOriginalTexture); //----------------------------------------------------------------------------- // macro definition for non-filtered samplers //----------------------------------------------------------------------------- #define SAMPLER_POINT(g_samplerMap, g_txMap); \ sampler2D g_samplerMap = sampler_state { \ Texture = ; \ MinFilter = Point; \ MagFilter = Point; \ MipFilter = Point; \ AddressU = BORDER; \ AddressV = BORDER; \ }; SAMPLER_POINT(g_samplerRoomModifyMap, g_txRoomModifyMap); // must be point, it will be used for filtering SAMPLER_POINT(g_samplerColumnModify0Map, g_txColumnModifyTexture0); SAMPLER_POINT(g_samplerColumnModify1Map, g_txColumnModifyTexture1); SAMPLER_POINT(g_samplerColumnModify2Map, g_txColumnModifyTexture2); SAMPLER_POINT(g_samplerColumnModify3Map, g_txColumnModifyTexture3); sampler2D g_samplerShadowMap = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = CLAMP; AddressV = CLAMP; }; samplerCUBE g_samplerRoomCubeMapColorDistanceMap = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = BORDER; AddressV = BORDER; }; samplerCUBE g_samplerRoomCubeMapUVMap = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; AddressU = BORDER; AddressV = BORDER; }; samplerCUBE g_samplerRoomCubeMapUVMap_NO_FILTER = sampler_state { Texture = ; MinFilter = Point; MagFilter = Point; MipFilter = Point; AddressU = BORDER; AddressV = BORDER; }; //----------------------------------------------------------------------------- // FUNCTIONS //----------------------------------------------------------------------------- // This function is called several times. float3 Hit( float3 x, float3 R, samplerCUBE mp ) { float rl = texCUBE( mp, R ).a; // |r| float ppp = length( x ) / texCUBE( mp, x ).a; // |p|/|p’| float dun = 0, pun = ppp, dov = 0, pov; float dl = rl * ( 1 - ppp ); // eq. 2 float3 l = x + R * dl; // ray equation // iteration for( int i = 0; i < g_iNumberOfIteration; i++ ) { float llp = length( l ) / texCUBE( mp,l ).a; // |l|/|l’| if ( llp < 0.999f ) // undershooting { dun = dl; pun = llp; // last undershooting dl += ( dov == 0 ) ? rl * ( 1 - llp ) : // eq. 2 ( dl - dov ) * ( 1 - llp ) / ( llp - pov ); // eq. 3 } else if ( llp > 1.001f ) // overshooting { dov = dl; pov = llp; // last overshooting dl += ( dl -dun ) * ( 1 - llp ) / ( llp - pun );// eq. 3 } l = x + R * dl; // ray equation } return l; // computed hit point } //***************************************************************************** // This function enlarges the usefull areas of the atlases. float4 FlowLight( sampler2D mp, float2 Tex ) { // Reads the current pixel float4 preVal = tex2D( mp, Tex ); // If it is an unused pixel (.a=0) if ( preVal.a == 0 ) { float dist = ONE; if( g_iObjectID != -1 ) dist *= 3.0f; // Reads a neighbor float2 modTex = Tex + float2( dist, 0.0 ); float4 candid = tex2D( mp, modTex ); // Calculate its intensity. // If it is more intensive than the previous (original) one, it is stored. if( dot( candid.xyz, candid.xyz ) > dot( preVal.xyz, preVal.xyz ) ) preVal = candid; // Reads another neighbor modTex += float2( -dist, dist ); candid = tex2D( mp, modTex ); // Calculate its intensity. // If it is more intensive than the previous one, it is stored. if( dot( candid.xyz, candid.xyz ) > dot( preVal.xyz, preVal.xyz ) ) preVal = candid; // Reads another neighbor. If it is more intensive than the previous, it is stored. modTex += float2( -dist, -dist ); candid = tex2D( mp, modTex ); if( dot( candid.xyz, candid.xyz ) > dot( preVal.xyz, preVal.xyz ) ) preVal = candid; // Reads another neighbor. If it is more intensive than the previous, it is stored. modTex += float2( dist, -dist ); candid = tex2D( mp, modTex ); if( dot( candid.xyz, candid.xyz ) > dot( preVal.xyz, preVal.xyz ) ) preVal = candid; } return preVal; } //----------------------------------------------------------------------------- // SHADERS // Here are the different shaders. //----------------------------------------------------------------------------- //***************************************************************************** //----------------------------------------------------------------------------- // RenderRoomColorDistance // This shader stores the viewable object's color and its distance from the CenterObject's position. // The result is stored in a CubeMap. //----------------------------------------------------------------------------- void RenderRoomColorDistanceVS( float4 Pos : POSITION, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0, out float4 outPos : TEXCOORD1 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outTex = Tex; // Calculates the world position outPos = mul( Pos, g_mWorldView ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderRoomColorDistancePS( float2 Tex : TEXCOORD0, float4 Pos : TEXCOORD1 ) : COLOR { // The color of the viewable object in the current pixel. // In the scene there are 2 different textured object. (the room, and the Columns) // Every column has the same brdf texture. float3 retColor = float4(0,0,0,0); if ( g_iObjectID == -1 ) retColor = float4( tex2D( g_samplerRoomMap, Tex ).xyz, 1); else retColor = float4( tex2D( g_samplerColumnOriginalMap, Tex ).xyz, 1); // The distance from the Center object float Distance = (float) ( length( Pos.xyz ) ); return float4( retColor, Distance ); // Color(x,y,z) + Distance(w) } //***************************************************************************** //----------------------------------------------------------------------------- // RenderRoomUV // This shader stores the viewable object's UV and unique ObjectID. // The ObjectID identify the object, because the UV pair is not enough. // The result is stored in a CubeMap. //----------------------------------------------------------------------------- void RenderRoomUVVS( float4 Pos : POSITION, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outTex = Tex; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderRoomUVPS( float2 Tex : TEXCOORD0) : COLOR { // The UV value and the ID of the viewable object in the current pixel // Here the "1" value is unnecessary return float4( Tex, g_iObjectID, 1 ); // Tex(x,y) + g_iObjectID(z) + "1"(w) } //***************************************************************************** //----------------------------------------------------------------------------- // RenderUmbra // This shader copies the brdf color from the original texture Atlas of the Object to the // actual texture Atlas of the Object. // It is needed, because the brdf value is modified with shadow. // If the pixel is in shadow, the brdf value is decreased. // The distance from the light source is also a modifying factor. // The result is stored in a 2D map (Atlas). //----------------------------------------------------------------------------- void RenderUmbraVS( float4 Pos : POSITION, float2 Tex : TEXCOORD0, float3 Normal : NORMAL, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0, out float3 outPos : TEXCOORD1, out float outCosT : TEXCOORD2, out float4 outLPos : TEXCOORD3) { // The Room has no offset. // The Columns have offset from the world's center position. float4 PosWorld = Pos; if ( g_iObjectID > -0.1f ) PosWorld = mul( Pos, g_mWorldView ); // Light vector float3 L = normalize( g_vLightPos3f - PosWorld.xyz ); // Transformation between texture and screen space. // HALF is an offset between the two space. outhPos.x = Tex.x * 2.0f - 1.0f - HALF; outhPos.y = 1.0f - Tex.y * 2.0f + HALF; outhPos.z = 0; outhPos.w = 1; outTex = Tex; outPos = PosWorld.xyz; // The direction of the normal of the Room and the Columns are different. if (g_iObjectID < -0.5f) Normal = -Normal; outCosT = dot( Normal, L ); outLPos = mul( PosWorld, g_mLightViewTexBias ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderUmbraPS( float2 Tex : TEXCOORD0, float3 Pos : TEXCOORD1, float CosT : TEXCOORD2, float4 LPos : TEXCOORD3 ) : COLOR { // return Color float4 retColor = float4(0,0,0,0); // ShadowMap distance values float2 texDist, t051, t052, t053, t054, t101, t102, t103, t104, t031, t032, t033, t034; texDist = t051 = t052 = t053 = t054 = t101 = t102 = t103 = t104 = t031 = t032 = t033 = t034 = 0.0f; // Read the brdf from the atlas of the object // The Room and the Columns have 2 different brdf Atlas. if ( g_iObjectID == -1 ) retColor = float4( tex2D( g_samplerRoomMap, Tex ).xyz, 1); else retColor = float4( tex2D( g_samplerColumnOriginalMap, Tex ).xyz, 1); // Use shadow? if (g_bShadowON) { // Read the ShadowMap for the distance values // and store the alpha value to decide wether its depth value is a real or zero from the ShadowMap border. texDist = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( LPos.xyz / LPos.w, 0 ) ).xw; t031 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( THREE, 0, 0 ), 0 ) ).xw; t032 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( -THREE,ONE, 0 ), 0 ) ).xw; t033 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( ONE, THREE, 0 ), 0 ) ).xw; t034 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( 0, -THREE, 0 ), 0 ) ).xw; t051 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( FIVE, ONE, 0 ), 0 ) ).xw; t052 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( -FIVE, 0, 0 ), 0 ) ).xw; t053 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( -ONE, FIVE, 0 ), 0 ) ).xw; t054 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( 0, -FIVE, 0 ), 0 ) ).xw; t101 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( TEN, THREE, 0 ), 0 ) ).xw; t102 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( -TEN, -ONE, 0 ), 0 ) ).xw; t103 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( -ONE, TEN, 0 ), 0 ) ).xw; t104 = float2( LPos.z, 0.0f ) - tex2Dlod( g_samplerShadowMap, float4( ( LPos.xyz / LPos.w ) + float3( FIVE, -TEN, 0 ), 0 ) ).xw; // Decrease the intensity of the brdf in the area of the shadow, // and increase it if the pixel has an illuminated neighbor. // This variable modifies the brdf. float summarize = 1.0f; // Decrease it if it is in shadow and it is a real depth value ( alpha = 1 ) if ( ( texDist.x > 0.05f ) && ( texDist.y < -0.5f ) ) summarize = g_fShadowIntensity; // Increase it if it is in light. // The power of effect of a neighbor pixel depends on the distance from the original pixel. if ( t031.x < 0.05f && t031.y < -0.5f ) summarize += 0.85; if ( t032.x < 0.05f && t032.y < -0.5f ) summarize += 0.85; if ( t033.x < 0.05f && t033.y < -0.5f ) summarize += 0.85; if ( t034.x < 0.05f && t034.y < -0.5f ) summarize += 0.85; if ( t051.x < 0.05f && t051.y < -0.5f ) summarize += 0.42; if ( t052.x < 0.05f && t052.y < -0.5f ) summarize += 0.42; if ( t053.x < 0.05f && t053.y < -0.5f ) summarize += 0.42; if ( t054.x < 0.05f && t054.y < -0.5f ) summarize += 0.42; if ( t101.x < 0.05f && t101.y < -0.5f ) summarize += 0.10; if ( t102.x < 0.05f && t102.y < -0.5f ) summarize += 0.10; if ( t103.x < 0.05f && t103.y < -0.5f ) summarize += 0.10; if ( t104.x < 0.05f && t104.y < -0.5f ) summarize += 0.10; // The brdf can not be increased by the shadow computation. if ( summarize > 1.0f ) summarize = 1.0; if ( ( texDist.x < 0.05f ) && ( texDist.y < -0.5f ) ) summarize = 1.0; retColor *= summarize; if ( texDist.x > 0.05f ) retColor *= g_fShadowIntensity; if ( g_fShadowIntensity > 0.999 ) retColor /= summarize; } // The intensity of the brdf depends on the position of the light source. float3 L = g_vLightPos3f; float pll2 = dot( ( Pos - L ), ( Pos - L ) ); retColor *= AMB + ( FI / pll2 ) * CosT * g_fCausticsIntensity; if (g_bShowHelp) // light's effect is decreased to improve the visibility of help text retColor *= 0.5f; return retColor; } //***************************************************************************** //----------------------------------------------------------------------------- // RenderRoomAndColumnsScreen // This shader render the scene's objects to the screen with their own atlas. //----------------------------------------------------------------------------- void RenderRoomAndColumnsScreenVS( float4 Pos : POSITION, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outTex = Tex; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderRoomAndColumnsScreenPS( float2 Tex : TEXCOORD0) : COLOR { float4 retColor = float4(1,1,1,1); // Five different atlas for the five object. if (g_iObjectID == -1 ) retColor = float4( tex2D( g_samplerRoomLastMap, Tex ).xyz, 1 ); if (g_iObjectID == 0 ) retColor = float4( tex2D( g_samplerColumnLast0Map, Tex ).xyz, 1 ); if (g_iObjectID == 1 ) retColor = float4( tex2D( g_samplerColumnLast1Map, Tex ).xyz, 1 ); if (g_iObjectID == 2 ) retColor = float4( tex2D( g_samplerColumnLast2Map, Tex ).xyz, 1 ); if (g_iObjectID == 3 ) retColor = float4( tex2D( g_samplerColumnLast3Map, Tex ).xyz, 1 ); return retColor; } //***************************************************************************** //----------------------------------------------------------------------------- // RenderPhotonUVMap // This shader creates the PhotonUVTexture with Hit function. // It is a 2D map with the photon hits. It is created from the position of the light source. // Every pixel stores the UV, and ObjectID information. // The result is stored in a 2D map. //----------------------------------------------------------------------------- void RenderPhotonUVMapVS( float4 Pos : POSITION, float3 Normal : NORMAL, float3 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float3 outTex : TEXCOORD0, out float3 outPos : TEXCOORD1, out float3 outN : TEXCOORD2, out float3 outL : TEXCOORD3) { // The offset (+float4...) is needed to move the Center Object into the center of the PhotonMap. outhPos = mul( Pos, g_mWorldViewProjection ) + float4( -4.0f / (float)g_iPhotonMapSize , 4.0f / (float)g_iPhotonMapSize , 0, 0 ); outTex = Tex; outPos = mul( Pos, g_mWorldCenterObject ); outN = Normal; outL = normalize( outPos - g_vLightPos3f ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderPhotonUVMapPS( float3 Tex : TEXCOORD0, float3 Pos : TEXCOORD1, float3 N : TEXCOORD2, float3 L : TEXCOORD3 ) : COLOR { // By default, there is no Hit. float a = -1; float4 hitSurf = float4(0,0,0,0); if ( dot( L, N ) < -0.1 ){ L = normalize( L ); N = normalize( N ); float3 T = normalize( refract( L, N, g_fRefractionIndex ) ); // Look up from the CubeMap // The return value is a vector. The CubeUVMap is read at that position. float3 TT = Hit( Pos, T, g_samplerRoomCubeMapColorDistanceMap ); hitSurf = texCUBE( g_samplerRoomCubeMapUVMap, TT ); // There is a Hit. a = 1; } return float4( hitSurf.xyz, a ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderPhotonUVMapClassic // This shader creates the PhotonUVTexture with classical method. // It is a 2D map with the photon hits. It is created from the position of the light source. // Every pixel stores the UV, and ObjectID information. // The result is stored in a 2D map. //----------------------------------------------------------------------------- void RenderPhotonUVMapClassicVS( float4 Pos : POSITION, float3 Normal : NORMAL, float3 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float3 outTex : TEXCOORD0, out float3 outPos : TEXCOORD1, out float3 outN : TEXCOORD2, out float3 outL : TEXCOORD3) { // The offset (+float4...) is needed to move the Center Object into the center of the PhotonMap. outhPos = mul( Pos, g_mWorldViewProjection ) + float4( -4.0f / (float)g_iPhotonMapSize , 4.0f / (float)g_iPhotonMapSize , 0, 0 ); outTex = Tex; outPos = mul( Pos, g_mWorldCenterObject ); outN = Normal; outL = normalize( outPos - g_vLightPos3f ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderPhotonUVMapClassicPS( float3 Tex : TEXCOORD0, float3 Pos : TEXCOORD1, float3 N : TEXCOORD2, float3 L : TEXCOORD3 ) : COLOR { // By default, there is no Hit. float a = -1; float4 hitSurf = float4(0,0,0,0); if ( dot( L, N ) < -0.1 ){ L = normalize( L ); N = normalize( N ); float3 TT = normalize( refract( L, N, g_fRefractionIndex ) ); hitSurf = texCUBE( g_samplerRoomCubeMapUVMap, TT ); // There is a Hit. a = 1; } return float4( hitSurf.xyz, a ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderPhotonHit // This shader uses the PhotonUVTexture as an input. // It renders as many snippets to the Object's atlas as many pixels the PhotonUVTexture has. // If a pixel in the PhotonUVTexture is not connected to the actual Object (not the same ObjectID), // it will not be rendered. // The result is blended into the Object's Atlas. //----------------------------------------------------------------------------- void RenderPhotonHitVS( float4 Pos : POSITION, float4 Color : COLOR0, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, //out float2 outTex : TEXCOORD0, out float2 outTexFilter : TEXCOORD1, out float outPower : TEXCOORD2, out float4 outPos : TEXCOORD3, out float4 outColor : TEXCOORD4 ) { // Reads back the PhotonHit's UV position and the ObjectID float4 ph = tex2Dlod(g_samplerPhotonUVMap, float4( Tex, 0, 0)); // This enlarges the snippet's size if it is rendered into a Column's atlas. // It is needed because the Column's atlas contains more elements, // and the same distance (in world space) is bigger in the Column's atlas. if ( g_iObjectID > -0.5 ) Pos *= 3.3f; // Adds the snippet's offset to the UV coordinates outPos.x = ph.x + Pos.x / 2.0; outPos.y = ph.y - Pos.y / 2.0; outPos.z = 0; outPos.w = 1; // Transforms the texture coordinates to screen coordinates // and adds the snippet's offset to it outhPos.x = ( ph.x * 2 ) - 1 + Pos.x + HALF; outhPos.y = 1 - ph.y * 2 + Pos.y - HALF; // Is it a real Hit? // and are we render the right Object? if ( ( ph.a > 0 ) && ( ph.b == g_iObjectID ) ) { // If YES outhPos.z = 0; } // If NO else outhPos.z = -100; outhPos.w = 1; //outTex = outhPos; outTexFilter = Tex; outPower = ph.w; outColor = Color; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderPhotonHitPS( //float2 Tex : TEXCOORD0, float2 TexFilter : TEXCOORD1, float Power : TEXCOORD2, float4 Pos : TEXCOORD3, float4 Color : TEXCOORD4 ) : COLOR { float4 retColor; float4 brdf = float4(0,0,0,0); // Room or Column? if ( g_iObjectID == -1 ) brdf = tex2D( g_samplerRoomMap, Pos); else brdf = tex2D( g_samplerColumnOriginalMap, Pos); // The Gausian weight of a snippet. float4 w = tex2D( g_samplerPowerOfSnippetMap, Color.yz ); // The color of the snippet's pixel. retColor = g_fPower * brdf * w * g_fCausticsIntensity; return float4( retColor.xyz, 0 ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderRefractObjectScreen // This shader calculates the color of the CenterObject with Hit function. // It has reflection and refraction effect. // The result is displayed on the screen. //----------------------------------------------------------------------------- void RenderRefractObjectScreenVS( float4 Pos : POSITION, float3 Normal : NORMAL, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float3 outPos : TEXCOORD1, out float3 outN : TEXCOORD2, out float3 outV : TEXCOORD3 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outPos = mul( Pos, g_mWorldCenterObject ); outN = normalize( Normal ); outV = normalize( outPos - g_vCameraPos3f ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderRefractObjectScreenPS( float3 p0 : TEXCOORD1, float3 N : TEXCOORD2, float3 V : TEXCOORD3 ) : COLOR { V = normalize( V ); N = normalize( N ); // Calculates reflection float3 R = reflect( V, N ); float3 RR = Hit(p0, R, g_samplerRoomCubeMapColorDistanceMap); // Calculates refraction float3 T = refract(V, N, g_fRefractionIndex); float3 TT = Hit(p0, T, g_samplerRoomCubeMapColorDistanceMap); // Calculates reflected color float4 hitSurf = texCUBE( g_samplerRoomCubeMapUVMap_NO_FILTER, RR ); // UV position where the Atlas must be read float4 reflectColor = float4( 1,0,0,0 ); if (hitSurf.b == -1) reflectColor = tex2D( g_samplerRoomLastMap, hitSurf.xy ); if (hitSurf.b == 0) reflectColor = tex2D( g_samplerColumnLast0Map, hitSurf.xy ); if (hitSurf.b == 1) reflectColor = tex2D( g_samplerColumnLast1Map, hitSurf.xy ); if (hitSurf.b == 2) reflectColor = tex2D( g_samplerColumnLast2Map, hitSurf.xy ); if (hitSurf.b == 3) reflectColor = tex2D( g_samplerColumnLast3Map, hitSurf.xy ); // Calculates refracted color hitSurf = texCUBE( g_samplerRoomCubeMapUVMap_NO_FILTER, TT ); float4 refractColor = float4( 1,0,0,0 ); if (hitSurf.b == -1) refractColor = tex2D( g_samplerRoomLastMap, hitSurf.xy ); if (hitSurf.b == 0) refractColor = tex2D( g_samplerColumnLast0Map, hitSurf.xy ); if (hitSurf.b == 1) refractColor = tex2D( g_samplerColumnLast1Map, hitSurf.xy ); if (hitSurf.b == 2) refractColor = tex2D( g_samplerColumnLast2Map, hitSurf.xy ); if (hitSurf.b == 3) refractColor = tex2D( g_samplerColumnLast3Map, hitSurf.xy ); // Calculates return color modified by Fresnel function. float F = g_fFresnelFactor + ( 1 - g_fFresnelFactor ) * pow( 1 - dot( N, -V ), 5 ); return float4( F * reflectColor + ( 1 - F ) * refractColor ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderRefractObjectScreenClassic // This shader calculates the color of the CenterObject with classical method. // It has reflection and refraction effect. // The result is displayed on the screen. //----------------------------------------------------------------------------- void RenderRefractObjectScreenClassicVS( float4 Pos : POSITION, float3 Normal : NORMAL, float2 Tex : TEXCOORD0, out float4 outhPos : POSITION, out float3 outPos : TEXCOORD1, out float3 outN : TEXCOORD2, out float3 outV : TEXCOORD3 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outPos = mul( Pos, g_mWorldCenterObject ); outN = normalize( Normal ); outV = normalize( outPos - g_vCameraPos3f ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderRefractObjectScreenClassicPS( float3 p0 : TEXCOORD1, float3 N : TEXCOORD2, float3 V : TEXCOORD3 ) : COLOR { V = normalize( V ); N = normalize( N ); // Calculates reflection float3 RR = reflect( V, N ); // Calculates refraction float3 TT = refract(V, N, g_fRefractionIndex); // Calculates reflected color float4 hitSurf = texCUBE( g_samplerRoomCubeMapUVMap_NO_FILTER, RR ); // UV position where the Atlas must be read float3 reflectColor = float4(0,0,0,0); if (hitSurf.b == -1) reflectColor = tex2D( g_samplerRoomLastMap, hitSurf.xy ); if (hitSurf.b == 0) reflectColor = tex2D( g_samplerColumnLast0Map, hitSurf.xy ); if (hitSurf.b == 1) reflectColor = tex2D( g_samplerColumnLast1Map, hitSurf.xy ); if (hitSurf.b == 2) reflectColor = tex2D( g_samplerColumnLast2Map, hitSurf.xy ); if (hitSurf.b == 3) reflectColor = tex2D( g_samplerColumnLast3Map, hitSurf.xy ); // Calculates refracted color hitSurf = texCUBE( g_samplerRoomCubeMapUVMap_NO_FILTER, TT ); float3 refractColor = float4(0,0,0,0); if (hitSurf.b == -1) refractColor = tex2D( g_samplerRoomLastMap, hitSurf.xy ); if (hitSurf.b == 0) refractColor = tex2D( g_samplerColumnLast0Map, hitSurf.xy ); if (hitSurf.b == 1) refractColor = tex2D( g_samplerColumnLast1Map, hitSurf.xy ); if (hitSurf.b == 2) refractColor = tex2D( g_samplerColumnLast2Map, hitSurf.xy ); if (hitSurf.b == 3) refractColor = tex2D( g_samplerColumnLast3Map, hitSurf.xy ); // Calculates return color modified by Fresnel function. float F = g_fFresnelFactor + ( 1 - g_fFresnelFactor ) * pow( 1 - dot( N, -V ), 5 ); return float4( F * reflectColor + ( 1 - F ) * refractColor, 1 ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderLightScreen // This shader renders the light source's object to the screen with a diffuse color. //----------------------------------------------------------------------------- void RenderLightScreenVS( float4 Pos : POSITION, out float4 outPos : POSITION ) { outPos = mul( Pos, g_mWorldViewProjection ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderLightScreenPS() : COLOR { return float4( 1, 1, 0.7f, 1 ); } //***************************************************************************** //----------------------------------------------------------------------------- // RenderShadow // This shader calculates the ShadowMapTexture's depth values. // The result is stored in g_pShadowMapTexture. //----------------------------------------------------------------------------- void RenderShadowVS( float4 Pos : POSITION, out float4 outhPos : POSITION, out float2 outPos : TEXCOORD1 ) { outhPos = mul( Pos, g_mWorldViewProjection ); outPos = mul( Pos, g_mLightViewTexBias ).zw; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 RenderShadowPS( float2 Pos : TEXCOORD1 ) : COLOR { return float4(Pos.x, 0, 0, 1); } //***************************************************************************** //----------------------------------------------------------------------------- // FullScreenQuad // This shader modifies the atlases of Room and Columns. // It removes the black edges from the atlases. // The result is stored in the Object's atlas. //----------------------------------------------------------------------------- void FullScreenQuadVS( float4 Pos : POSITION, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0 ) { outhPos = float4( Pos.xy, 0, 1 ); outTex.x = Pos.x * 0.5f + 0.5f; outTex.y = -Pos.y * 0.5f + 0.5f; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 FullScreenQuadPS( float2 Tex : TEXCOORD0 ) : COLOR { float4 preVal = float4(1,1,1,1); if( g_iObjectID ==-1 ) preVal = FlowLight( g_samplerRoomModifyMap, Tex ); if( g_iObjectID == 0 ) preVal = FlowLight( g_samplerColumnModify0Map, Tex ); if( g_iObjectID == 1 ) preVal = FlowLight( g_samplerColumnModify1Map, Tex ); if( g_iObjectID == 2 ) preVal = FlowLight( g_samplerColumnModify2Map, Tex ); if( g_iObjectID == 3 ) preVal = FlowLight( g_samplerColumnModify3Map, Tex ); return preVal; } //***************************************************************************** //----------------------------------------------------------------------------- // PhotonMapScreen // This shader renders the PhotonMap texture (g_txPhotonUVMap) into the screen lower left corner. // This texture contains the PhotonHits positions and ObjectIDs. // The result is displayed on the screen. //----------------------------------------------------------------------------- void PhotonMapScreenVS( float4 Pos : POSITION, out float4 outhPos : POSITION, out float2 outTex : TEXCOORD0 ) { outhPos = float4( Pos.xy * 0.2f + float2( -0.7f, -0.7f ), 0, 1 ); outTex.x = Pos.x * 0.5f + 0.5f; outTex.y = -Pos.y * 0.5f + 0.5f; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float4 PhotonMapScreenPS( float2 Tex : TEXCOORD0 ) : COLOR { return tex2D( g_samplerPhotonUVMap, Tex ); } //***************************************************************************** //----------------------------------------------------------------------------- // TECHNIQUES // Here are the different Techniques. //----------------------------------------------------------------------------- // Technique(AnyRenderPass): // VertexShader = compile vs_3_0 AnyRenderPassVS() // PixelShader = compile vs_3_0 AnyRenderPassPS() // if using the name convention above to name vertex/pixel shaders, // you can use the following macro definition to quickly define a technique: // note: ## stands for concatenation #define Technique(name); \ technique name \ { \ pass p0 \ { \ VertexShader = compile vs_3_0 name##VS(); \ PixelShader = compile ps_3_0 name##PS(); \ } \ } Technique( RenderRoomColorDistance ); Technique( RenderRoomUV ); Technique( RenderUmbra ); Technique( RenderRoomAndColumnsScreen ); Technique( RenderLightScreen ); Technique( RenderPhotonUVMap ); Technique( RenderPhotonUVMapClassic ); Technique( RenderPhotonHit ); Technique( RenderRefractObjectScreen ); Technique( RenderRefractObjectScreenClassic ); Technique( RenderShadow ); Technique( FullScreenQuad ); Technique( PhotonMapScreen );