= 0.8; float4x4 WorldITXf : WorldInverseTranspose < string UIWidget="None"; > = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; float4x4 WvpXf : WorldViewProjection < string UIWidget="None"; >; float4x4 WorldXf : World < string UIWidget="None"; >; float4x4 ViewIXf : ViewInverse < string UIWidget="None"; >; ////////////////////////////////////////////////////////////////////////// // tweakables //////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Point Light 1 //// float3 LightPosP1 : POSITION < string UIName = "Light Pos 1"; string Object = "PointLight"; string Space = "World"; > = {-10.0f, 10.0f, -10.0f}; // float4 EyeVector = {0,0,1,0}; float3 SurfColor : DIFFUSE < string UIName = "Color Name"; string UIWidget = "Color"; > = {0.3f, 0.3f, 0.5f}; float SpecExpon : SpecularPower < string UIName = "Spec Power"; string UIWidget = "slider"; float UIMin = 1.0; float UIMax = 128.0; float UIStep = 1.0; > = 12.0f; #include ////////////////////////////////////////////////////////////////////////// // structs /////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// struct appData { float4 Position : POSITION; float4 Normal : NORMAL; }; struct vertexOutput { float4 HPOS : POSITION; float4 diffCol : COLOR0; float4 specCol : COLOR1; float2 filmDepth : TEXCOORD0; }; ////////////////////////////////////////////////////////////////////////// // VERTEX SHADER ///////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// vertexOutput ThinFilmVS(appData IN,uniform float3 LightPos) { vertexOutput OUT; float3 Nn = mul(IN.Normal,WorldITXf).xyz; float4 Po = float4(IN.Position.xyz,1.0); // object coordinates float3 Pw = mul(Po,WorldXf).xyz; // world coordinates OUT.HPOS = mul(Po,WvpXf); // screen clipspace coords float3 Ln = normalize(LightPos - Pw); float3 Vn = normalize(ViewIXf[3].xyz - Pw); // obj coords float3 Hn = normalize(Ln + Vn); float4 litV = lit(dot(Ln,Nn),dot(Hn,Nn),SpecExpon); OUT.diffCol = (float4)litV.y; OUT.specCol = (float4)pow(dot(Hn,Nn),SpecExpon); // (float4)litV.z; // OUT.specCol = litV.zzzz; // bug in lit() ? // compute the view depth for the thin film // float viewdepth = (1.0 / dot(Nn,Vn)) * FilmDepth.x; float viewdepth = calc_view_depth(dot(Nn,Vn),FilmDepth.x); OUT.filmDepth = viewdepth.xx; return OUT; } ///////// ///////////////////////////////////////////////////////////////// // PIXEL SHADER ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// float4 ThinFilmPS(vertexOutput IN) : COLOR { // lookup fringe value based on view depth float3 fringeCol = (float3)tex2D(FringeMapSampler, IN.filmDepth); // modulate specular lighting by fringe color, combine with regular lighting float3 rgb = fringeCol*IN.specCol + IN.diffCol*SurfColor; return float4(rgb,1); } ////////////////////////////////////////////////////////////////////////// // TECHNIQUE ///////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// technique ThinFilm < string Script = "Pass = P0"; > { pass P0 < string Script = "Draw=geometry;"; > { VertexShader = compile vs_2_0 ThinFilmVS(LightPosP1); ZEnable = true; ZWriteEnable = true; CullMode = None; PixelShader = compile ps_2_0 ThinFilmPS(); } } /////////////////////////////////// eof /// ]]> = 0.05f; //============================================================================ // texture samplers //============================================================================ #define FILM_TEX_SIZE 256 texture fringeMap < string function = "CreateFringeMap"; string UIWidget = "None"; int width = FILM_TEX_SIZE; int height = 1; // 1D lookup >; sampler FringeMapSampler = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = WRAP; AddressV = CLAMP; }; float4 CreateFringeMap(float2 Pos:POSITION, float2 Psize : PSIZE) : COLOR { // these lambdas are in 100's of nm, // they represent the wavelengths of light for each respective // color channel. They are only approximate so that the texture // can repeat. float3 lamRGB = float3(6,5,4); // (600,500,400)nm - should be more like (600,550,440) // these offsets are used to perturb the phase of the interference // if you are using very thick "thin films" you will want to // modify these offests to avoid complete contructive interference // at a particular depth.. Just a tweak able. float3 offsetRGB = (0).xxx; // p is the period of the texture, it is the LCM of the wavelengths, // this is the depth in nm when the pattern will repeat. I was too // lazy to write up a LCM function, so you have to provide it. float p = 60; //lcm(6,5,4) // vd is the depth of the thin film relative to the texture index float vd = p; // now compute the color values using this formula: // 1/2 ( Sin( 2Pi * d/lam* + Pi/2 + O) + 1 ) // where d is the current depth, or "i*vd" and O is some offset* so that // we avoid complete constructive interference in all wavelenths at some depth. float pi = 3.1415926535f; float3 rgb = 0.5*(sin(2*pi*(Pos.x*vd)/lamRGB + pi/2.0 + offsetRGB) + 1); return float4(rgb,0); } ////////////////////////////////////////////////////////////////////////// // Function to Index this texture - use in vertex or pixel shaders /////// ////////////////////////////////////////////////////////////////////////// float calc_view_depth(float NDotV,float Thickness) { // return (1.0 / NDotV) * Thickness; return (Thickness / NDotV); } #endif /* _H_THINFILMTEX */ /////////////////////////////////// eof /// ]]> = 0.8; // version # bool bReset : FXCOMPOSER_RESETPULSE < string UIName="Reset"; string UIWidget = "none"; >; float4 ClearColor < string UIWidget = "color"; string UIName = "background"; > = {0,0,0,0.0}; float ClearDepth = 1.0; #define NOISY_HALO #include /////////////////////////////////////////////////////////// /////////////////////////////////////// Tweakables //////// /////////////////////////////////////////////////////////// float4 GlowCol < string UIName = "Glow Color"; string UIWidget = "Color"; > = {1.0f, 0.6f, 0.0f, 1.0f}; float Glowness < string UIName = "Glow Strength"; string UIWidget = "slider"; float UIMin = 0.0f; float UIMax = 3.0f; float UIStep = 0.02f; > = 2.2f; float Bias < string UIWidget = "slider"; float UIMin = 0.0; float UIMax = 8.0; float UIStep = 0.1; > = 3.0f; float Trailfade < string UIName = "Trail Fade"; string UIWidget = "slider"; float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01; > = 0.6f; /////////////////////////////////////////////////////////// ///////////////////////////// Render-to-Texture Data ////// /////////////////////////////////////////////////////////// DECLARE_QUAD_TEX(ObjectsMap,ObjectsSamp,"A8R8G8B8") DECLARE_QUAD_TEX(HBlurredMap,HBlurredSamp,"A8R8G8B8") DECLARE_QUAD_TEX(GlowMap,GlowSampler,"A8R8G8B8") DECLARE_QUAD_DEPTH_BUFFER(DepthBuffer,"D24S8") ////////////////////////////////////// /// Noise //////////////////////////// ////////////////////////////////////// #ifdef NOISY_HALO float Timer : TIME < string UIWidget = "None"; >; float Speed < string UIName = "Noise Speed"; string UIWidget = "slider"; float UIMin = 0.0; float UIMax = 0.3; float UIStep = 0.01; > = 0.04f; float2 Crawl < string UIName = "Noise Crawl Speed"; > = {0.04f, -0.02f}; float NoiseBright < string UIName = "Anim Variance"; string UIWidget = "slider"; float UIMin = 0.0; float UIMax = 4.0; float UIStep = 0.01; > = 1.5f; float NoiseScale < string UIName = "Anim Size"; string UIWidget = "slider"; float UIMin = 0.0; float UIMax = 3.0; float UIStep = 0.01; > = 0.9f; #include #endif /* NOISY_HALO */ /////////////////////////////////////////////////////////// /////////////////////////////////// data structures /////// /////////////////////////////////////////////////////////// struct VS_OUTPUT_BLUR { float4 Position : POSITION; float4 Diffuse : COLOR0; float4 TexCoord0 : TEXCOORD0; float4 TexCoord1 : TEXCOORD1; float4 TexCoord2 : TEXCOORD2; float4 TexCoord3 : TEXCOORD3; float4 TexCoord4 : TEXCOORD4; float4 TexCoord5 : TEXCOORD5; float4 TexCoord6 : TEXCOORD6; float4 TexCoord7 : TEXCOORD7; float4 TexCoord8 : COLOR1; }; struct VS_OUTPUT { float4 Position : POSITION; float4 Diffuse : COLOR0; float4 TexCoord0 : TEXCOORD0; }; //////////////////////////////////////////////////////////// ////////////////////////////////// vertex shaders ////////// //////////////////////////////////////////////////////////// VS_OUTPUT VS_Quad(float3 Position : POSITION, float3 TexCoord : TEXCOORD0) { VS_OUTPUT OUT = (VS_OUTPUT)0; OUT.Position = float4(Position, 1); OUT.TexCoord0 = float4(TexCoord, Bias); return OUT; } VS_OUTPUT_BLUR VS_Quad_Vertical_9tap(float3 Position : POSITION, float3 TexCoord : TEXCOORD0) { VS_OUTPUT_BLUR OUT = (VS_OUTPUT_BLUR)0; OUT.Position = float4(Position, 1); float TexelIncrement = (1.0+Bias)/QuadScreenSize.y; //float3 Coord = float3(TexCoord.x + TexelIncrement, TexCoord.y + TexelIncrement, Bias); float3 Coord = float3(TexCoord.x, TexCoord.y, Bias); OUT.TexCoord0 = float4(Coord.x, Coord.y + TexelIncrement, TexCoord.z, Bias); OUT.TexCoord1 = float4(Coord.x, Coord.y + TexelIncrement * 2, TexCoord.z, Bias); OUT.TexCoord2 = float4(Coord.x, Coord.y + TexelIncrement * 3, TexCoord.z, Bias); OUT.TexCoord3 = float4(Coord.x, Coord.y + TexelIncrement * 4, TexCoord.z, Bias); OUT.TexCoord4 = float4(Coord.x, Coord.y, TexCoord.z, Bias); OUT.TexCoord5 = float4(Coord.x, Coord.y - TexelIncrement, TexCoord.z, Bias); OUT.TexCoord6 = float4(Coord.x, Coord.y - TexelIncrement * 2, TexCoord.z, Bias); OUT.TexCoord7 = float4(Coord.x, Coord.y - TexelIncrement * 3, TexCoord.z, Bias); OUT.TexCoord8 = float4(Coord.x, Coord.y - TexelIncrement * 4, TexCoord.z, Bias); return OUT; } VS_OUTPUT_BLUR VS_Quad_Horizontal_9tap(float3 Position : POSITION, float3 TexCoord : TEXCOORD0) { VS_OUTPUT_BLUR OUT = (VS_OUTPUT_BLUR)0; OUT.Position = float4(Position, 1); float TexelIncrement = (1.0+Bias)/QuadScreenSize.x; float3 Coord = float3(TexCoord.x, TexCoord.y, Bias); OUT.TexCoord0 = float4(Coord.x + TexelIncrement, Coord.y, TexCoord.z, Bias); OUT.TexCoord1 = float4(Coord.x + TexelIncrement * 2, Coord.y, TexCoord.z, Bias); OUT.TexCoord2 = float4(Coord.x + TexelIncrement * 3, Coord.y, TexCoord.z, Bias); OUT.TexCoord3 = float4(Coord.x + TexelIncrement * 4, Coord.y, TexCoord.z, Bias); OUT.TexCoord4 = float4(Coord.x, Coord.y, TexCoord.z, Bias); OUT.TexCoord5 = float4(Coord.x - TexelIncrement, Coord.y, TexCoord.z, Bias); OUT.TexCoord6 = float4(Coord.x - TexelIncrement * 2, Coord.y, TexCoord.z, Bias); OUT.TexCoord7 = float4(Coord.x - TexelIncrement * 3, Coord.y, TexCoord.z, Bias); OUT.TexCoord8 = float4(Coord.x - TexelIncrement * 4, Coord.y, TexCoord.z, Bias); return OUT; } ////////////////////////////////////////////////////// ////////////////////////////////// pixel shaders ///// ////////////////////////////////////////////////////// // For two-pass blur, we have chosen to do the horizontal blur FIRST. The // vertical pass includes a post-blur scale factor. // Relative filter weights indexed by distance from "home" texel // This set for 9-texel sampling #define WT9_0 1.0 #define WT9_1 0.8 #define WT9_2 0.6 #define WT9_3 0.4 #define WT9_4 0.2 // Alt pattern -- try your own! // #define WT9_0 0.1 // #define WT9_1 0.2 // #define WT9_2 3.0 // #define WT9_3 1.0 // #define WT9_4 0.4 #define WT9_NORMALIZE (WT9_0+2.0*(WT9_1+WT9_2+WT9_3+WT9_4)) float4 PS_Blur_Horizontal_9tap(VS_OUTPUT_BLUR IN) : COLOR { float OutCol = tex2Dbias(ObjectsSamp, IN.TexCoord0).w * (WT9_1/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord1).w * (WT9_2/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord2).w * (WT9_3/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord3).w * (WT9_4/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord4).w * (WT9_0/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord5).w * (WT9_1/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord6).w * (WT9_2/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord7).w * (WT9_3/WT9_NORMALIZE); OutCol += tex2Dbias(ObjectsSamp, IN.TexCoord8).w * (WT9_4/WT9_NORMALIZE); OutCol += Trailfade * tex2D(GlowSampler, IN.TexCoord4.xy).x; #ifdef NOISY_HALO float3 nuv = float3((NoiseScale*IN.TexCoord4.xy+(Timer*Crawl)),(Speed*Timer)); OutCol *= NoiseBright*(NOISE3D(nuv)).x; #endif /* NOISY_HALO */ return OutCol.xxxx; } float4 PS_Blur_Vertical_9tap(VS_OUTPUT_BLUR IN) : COLOR { float OutCol = tex2Dbias(HBlurredSamp, IN.TexCoord0).w * (WT9_1/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord1).w * (WT9_2/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord2).w * (WT9_3/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord3).w * (WT9_4/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord4).w * (WT9_0/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord5).w * (WT9_1/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord6).w * (WT9_2/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord7).w * (WT9_3/WT9_NORMALIZE); OutCol += tex2Dbias(HBlurredSamp, IN.TexCoord8).w * (WT9_4/WT9_NORMALIZE); // OutCol = OutCol.w * GlowCol; // all alpha float4 glo = (Glowness*OutCol)*GlowCol; // float4 OldCol = tex2Dbias(ObjectsSamp, IN.TexCoord0); // return OldCol + glo; return glo; } //////// // just drawn model itself // add glow on top of model float4 PS_GlowPass(VS_OUTPUT IN) : COLOR { float4 tex = tex2D(GlowSampler, float2(IN.TexCoord0.x, IN.TexCoord0.y)); return tex; } float4 PS_OrigPass(VS_OUTPUT IN) : COLOR { float4 tex = tex2D(ObjectsSamp, float2(IN.TexCoord0.x, IN.TexCoord0.y)); return tex; } //////////////////////////////////////////////////////////// /////////////////////////////////////// techniques ///////// //////////////////////////////////////////////////////////// technique Main < string ScriptClass = "scene"; string ScriptOrder = "postprocess"; string ScriptOutput = "color"; string Script = "LoopByCount=bReset;" "RenderColorTarget0=GlowMap;" "RenderDepthStencilTarget=DepthBuffer;" "ClearSetColor=ClearColor;" "ClearSetDepth=ClearDepth;" "Clear=Color0;" "Clear=Depth;" "LoopEnd=;" "RenderColorTarget0=ObjectsMap;" "RenderDepthStencilTarget=DepthBuffer;" "ClearSetColor=ClearColor;" "ClearSetDepth=ClearDepth;" "Clear=Color0;" "Clear=Depth0;" "ScriptExternal=color;" "Pass=HorizBlur;" "Pass=VertBlur;" "Pass=RedrawGlow;" "Pass=RedrawObj;"; > { pass HorizBlur < string Script = "RenderColorTarget0=HBlurredMap;" "Draw=Buffer;"; > { cullmode = none; ZEnable = false; AlphaBlendEnable = false; VertexShader = compile vs_2_0 VS_Quad_Horizontal_9tap(); PixelShader = compile ps_2_0 PS_Blur_Horizontal_9tap(); } pass VertBlur < string Script = "RenderColorTarget0=GlowMap;" "Draw=Buffer;"; > { cullmode = none; ZEnable = false; AlphaBlendEnable = false; VertexShader = compile vs_2_0 VS_Quad_Vertical_9tap(); PixelShader = compile ps_2_0 PS_Blur_Vertical_9tap(); } pass RedrawGlow < string Script = "RenderColorTarget0=;" "Draw=Buffer;"; > { VertexShader = compile vs_2_0 VS_Quad(); AlphaBlendEnable = false; ZEnable = false; PixelShader = compile ps_2_0 PS_GlowPass(); } pass RedrawObj < string Script = "RenderColorTarget0=;" "Draw=Buffer;"; > { VertexShader = compile vs_2_0 VS_Quad(); ZEnable = false; AlphaBlendEnable = true; SrcBlend = One; DestBlend = InvSrcAlpha; PixelShader = compile ps_2_0 PS_OrigPass(); } } ////////////// eof /// ]]>; // samplers sampler NoiseSamp = sampler_state { texture = ; AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; #define NOISE3D(p) tex3D(NoiseSamp,(p)) #define SNOISE3D(p) (NOISE3D(p)-0.5) #endif /* _H_NOISE3D */ ]]>; \ sampler SampName = sampler_state { \ texture = ; \ AddressU = AddrMode; \ AddressV = AddrMode; \ MipFilter = LINEAR; \ MinFilter = LINEAR; \ MagFilter = LINEAR; \ }; // // Simple 2D File Textures // // example usage: FILE_TEXTURE_2D(GlowMap,GlowSampler,"myfile.dds") // #define FILE_TEXTURE_2D(TextureName,SamplerName,Diskfile) FILE_TEXTURE_2D_MODAL(TextureName,SamplerName,(Diskfile),WRAP) // // Use this variation of DECLARE_QUAD_TEX() if you want a *scaled* render target // // example usage: DECLARE_SIZED_QUAD_TEX(GlowMap,GlowSampler,"A8R8G8B8",1.0) #define DECLARE_SIZED_QUAD_TEX(TexName,SampName,PixFmt,Multiple) texture TexName : RENDERCOLORTARGET < \ float2 ViewPortRatio = {Multiple,Multiple}; \ int MipLevels = 1; \ string Format = PixFmt ; \ string UIWidget = "None"; \ >; \ sampler SampName = sampler_state { \ texture = ; \ AddressU = CLAMP; \ AddressV = CLAMP; \ MipFilter = POINT; \ MinFilter = LINEAR; \ MagFilter = LINEAR; \ }; // // Use this macro to easily declare typical color render targets // // example usage: DECLARE_QUAD_TEX(ObjMap,ObjSampler,"A8R8G8B8") #define DECLARE_QUAD_TEX(TextureName,SamplerName,PixelFormat) DECLARE_SIZED_QUAD_TEX(TextureName,SamplerName,(PixelFormat),1.0) // // Use this macro to easily declare variable-sized depth render targets // // example usage: DECLARE_SIZED_QUAD_DEPTH_BUFFER(DepthMap,"D24S8",0.5) #define DECLARE_SIZED_QUAD_DEPTH_BUFFER(TextureName,PixelFormat,Multiple) texture TextureName : RENDERDEPTHSTENCILTARGET < \ float2 ViewPortRatio = {Multiple,Multiple}; \ string Format = (PixelFormat); \ string UIWidget = "None"; \ >; // // Use this macro to easily declare typical depth render targets // // example usage: DECLARE_QUAD_DEPTH_BUFFER(DepthMap,"D24S8") #define DECLARE_QUAD_DEPTH_BUFFER(TexName,PixFmt) DECLARE_SIZED_QUAD_DEPTH_BUFFER(TexName,PixFmt,1.0) // // declare exact-sized arbitrary texture // // example usage: DECLARE_SIZED_TEX(BlahMap,BlahSampler,"R32F",128,1) #define DECLARE_SIZED_TEX(Tex,Samp,Fmt,Wd,Ht) texture Tex : RENDERCOLORTARGET < \ float2 Dimensions = { Wd, Ht }; \ string Format = Fmt ; \ string UIWidget = "None"; \ int miplevels=1;\ >; \ sampler Samp = sampler_state { \ texture = ; \ AddressU = CLAMP; \ AddressV = CLAMP; \ MipFilter = NONE; \ MinFilter = LINEAR; \ MagFilter = LINEAR; \ }; // // declare exact-sized square texture, as for shadow maps // // example usage: DECLARE_SQUARE_QUAD_TEX(ShadMap,ShadObjSampler,"A16R16G16B16F",512) #define DECLARE_SQUARE_QUAD_TEX(TexName,SampName,PixFmt,Size) DECLARE_SIZED_TEX(TexName,SampName,(PixFmt),Size,Size) // // likewise for shadow depth targets // // example usage: DECLARE_SQUARE_QUAD_DEPTH_BUFFER(ShadDepth,"D24S8",512) #define DECLARE_SQUARE_QUAD_DEPTH_BUFFER(TextureName,PixelFormat,Size) texture TextureName : RENDERDEPTHSTENCILTARGET < \ float2 Dimensions = { Size, Size }; \ string Format = (PixelFormat) ; \ string UIWidget = "None"; \ >; //////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// Utility Functions //////// //////////////////////////////////////////////////////////////////////////// // // Scale inputs for use with texture-based lookup tables. A value ranging from zero to one needs // a slight scaling and offset to be sure to point at the centers of the first and last pixels // of that lookup texture. Pass the integer size of the table in TableSize // For now we'll assume that all tables are 1D, square, or cube-shaped -- all axes of equal size // // Cost of this operation for pixel shaders: two const-register // entries and a MAD (one cycle) QUAD_REAL scale_lookup(QUAD_REAL Value,const QUAD_REAL TableSize) { QUAD_REAL scale = ((TableSize - 1.0)/TableSize); QUAD_REAL shift = (0.5 / TableSize); return (scale*Value + shift); } QUAD_REAL2 scale_lookup(QUAD_REAL2 Value,const QUAD_REAL TableSize) { QUAD_REAL scale = ((TableSize - 1.0)/TableSize); QUAD_REAL shift = (0.5 / TableSize); return (scale.xx*Value + shift.xx); } QUAD_REAL3 scale_lookup(QUAD_REAL3 Value,const QUAD_REAL TableSize) { QUAD_REAL scale = ((TableSize - 1.0)/TableSize); QUAD_REAL shift = (0.5 / TableSize); return (scale.xxx*Value + shift.xxx); } // pre-multiply and un-pre-mutliply functions. The precision // of thse operatoions is often limited to 8-bit so don't // always count on them! // The macro value of NV_ALPHA_EPSILON, if defined, is used to // avoid IEEE "NaN" values that may occur when erroneously // dividing by a zero alpha (thanks to Pete Warden @ Apple // Computer for the suggestion in GPU GEMS II) // multiply color by alpha to turn an un-premultipied // pixel value into a premultiplied one QUAD_REAL4 premultiply(QUAD_REAL4 C) { return QUAD_REAL4((C.w*C.xyz),C.w); } #define NV_ALPHA_EPSILON 0.0001 // given a premultiplied pixel color, try to undo the premultiplication. // beware of precision errors QUAD_REAL4 unpremultiply(QUAD_REAL4 C) { #ifdef NV_ALPHA_EPSILON QUAD_REAL a = C.w + NV_ALPHA_EPSILON; return QUAD_REAL4((C.xyz / a),C.w); #else /* ! NV_ALPHA_EPSILON */ return QUAD_REAL4((C.xyz / C.w),C.w); #endif /* ! NV_ALPHA_EPSILON */ } ///////////////////////////////////////////////////////////////////////////////////// // Structure Declaration //////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// struct QuadVertexOutput { QUAD_REAL4 Position : POSITION; QUAD_REAL2 UV : TEXCOORD0; }; ///////////////////////////////////////////////////////////////////////////////////// // Hidden tweakables declared by this .fxh file ///////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// #ifndef NO_TEXEL_OFFSET #ifdef TWEAKABLE_TEXEL_OFFSET QUAD_REAL QuadTexOffset = 0.5; #else /* !TWEAKABLE_TEXEL_OFFSET */ QUAD_REAL QuadTexOffset < string UIWidget="None"; > = 0.5; #endif /* !TWEAKABLE_TEXEL_OFFSET */ QUAD_REAL2 QuadScreenSize : VIEWPORTPIXELSIZE < string UIWidget="None"; >; #endif /* NO_TEXEL_OFFSET */ //////////////////////////////////////////////////////////// ////////////////////////////////// vertex shaders ////////// //////////////////////////////////////////////////////////// QuadVertexOutput ScreenQuadVS( QUAD_REAL3 Position : POSITION, QUAD_REAL3 TexCoord : TEXCOORD0 ) { QuadVertexOutput OUT; OUT.Position = QUAD_REAL4(Position, 1); #ifdef NO_TEXEL_OFFSET OUT.UV = TexCoord.xy; #else /* NO_TEXEL_OFFSET */ QUAD_REAL2 off = QUAD_REAL2(QuadTexOffset/(QuadScreenSize.x),QuadTexOffset/(QuadScreenSize.y)); OUT.UV = QUAD_REAL2(TexCoord.xy+off); #endif /* NO_TEXEL_OFFSET */ return OUT; } ////////////////////////////////////////////////////// ////////////////////////////////// pixel shaders ///// ////////////////////////////////////////////////////// // add glow on top of model QUAD_REAL4 TexQuadPS(QuadVertexOutput IN,uniform sampler2D InputSampler) : COLOR { QUAD_REAL4 texCol = tex2D(InputSampler, IN.UV); return texCol; } QUAD_REAL4 TexQuadBiasPS(QuadVertexOutput IN,uniform sampler2D InputSampler,QUAD_REAL TBias) : COLOR { QUAD_REAL4 texCol = tex2Dbias(InputSampler, QUAD_REAL4(IN.UV,0,TBias)); return texCol; } ////////////////////////////////////////////////////////////////// /// Macros to define passes within Techniques //////////////////// ////////////////////////////////////////////////////////////////// // older HLSL syntax #define TEX_TECH(TechName,SamplerName) technique TechName { \ pass TexturePass { \ VertexShader = compile vs_2_0 ScreenQuadVS(); \ AlphaBlendEnable = false; ZEnable = false; \ PixelShader = compile ps_2_a TexQuadPS(SamplerName); } } #define TEX_BLEND_TECH(TechName,SamplerName) technique TechName { \ pass TexturePass { \ VertexShader = compile vs_2_0 ScreenQuadVS(); \ ZEnable = false; AlphaBlendEnable = true; \ SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; \ PixelShader = compile ps_2_a TexQuadPS(SamplerName); } } // newer HLSL syntax #define TEX_TECH2(TechName,SamplerName,TargName) technique TechName { \ pass TexturePass < \ string ScriptFunction = "RenderColorTarget0=" (TargName) ";" \ "DrawInternal=Buffer;"; \ > { \ VertexShader = compile vs_2_0 ScreenQuadVS(); \ AlphaBlendEnable = false; ZEnable = false; \ PixelShader = compile ps_2_a TexQuadPS(SamplerName); } } #define TEX_BLEND_TECH2(TechName,SamplerName) technique TechName { \ pass TexturePass < \ string ScriptFunction = "RenderColorTarget0=" (TargName) ";" \ "DrawInternal=Buffer;"; \ > { \ VertexShader = compile vs_2_0 ScreenQuadVS(); \ ZEnable = false; AlphaBlendEnable = true; \ SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; \ PixelShader = compile ps_2_a TexQuadPS(SamplerName); } } #endif /* _QUAD_FXH */ ////////////// eof /// ]]>