= 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 ///
]]>