float Script : STANDARDSGLOBAL < string UIWidget = "none"; string ScriptClass = "scene"; string ScriptOrder = "standard"; string ScriptOutput = "color"; string Script = "Technique=ps11;"; > = 0.8; /************* UNTWEAKABLES **************/ float4x4 WorldITXf : WorldInverseTranspose < string UIWidget="None"; >; float4x4 WvpXf : WorldViewProjection < string UIWidget="None"; >; float4x4 WorldXf : World < string UIWidget="None"; >; float4x4 ViewInvXf : ViewInverse < string UIWidget="None"; >; bool bReset : FXCOMPOSER_RESETPULSE < string UIName="Reset Painting"; >; float ClearDepth = 1.0; float4 MouseL : LEFTMOUSEDOWN < string UIWidget="None"; >; float3 MousePos : MOUSEPOSITION < string UIWidget="None"; >; float Timer : TIME < string UIWidget = "None"; >; bool Painting < string UIName="Painting On/Off"; > = true; static float PaintFlag = (Painting?1.0:0.0); bool HASelect < string UIName="Paint HalfAngle Map?"; > = true; bool NmIso < string UIName="Isotropic Normal Painting?"; // string Desc="Overrides Symmetry setting"; > = true; bool NmSym < string UIName="Symmetric Normal Painting?"; > = true; bool HfSym < string UIName="Symmetric HalfAngle Painting?"; > = false; /////////////////////// TWEAKABLES ////////////////// ////////////// Brush Variables ///////////////////////// float Opacity < string UIWidget = "slider"; string UIName = "Brush Opacity"; float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01; > = 0.05f; float BrushSizeStart < string UIName = "Brush Start Size"; string UIWidget = "slider"; float UIMin = 0.001; float UIMax = 0.25; float UIStep = 0.001; > = 0.07f; float BrushSizeEnd < string UIName = "Brush End Size"; string UIWidget = "slider"; float UIMin = 0.001; float UIMax = 0.25; float UIStep = 0.001; > = 0.01f; float FadeTime < string UIName = "Brush Fade Time"; string UIWidget = "slider"; float UIMin = 0.1; float UIMax = 10.0; float UIStep = 0.1; > = 2.00f; float3 PaintColor < string UIName = "PaintBrush"; string UIWidget = "Color"; > = {0.4f, 0.3f, 1.0f}; float4 ClearColor < string UIWidget = "color"; string UIName = "Background"; > = {0,0,0,0}; ////////////// Light/Surface Variables ///////////////////////// float3 LightDir : Direction // we'll assume that this one is normalized < string Object = "DirectionalLight"; string Space = "World"; > = {1.0f, 0.0f, 0.0f}; float3 LightColor < string UIName = "Lamp"; string UIWidget = "Color"; > = {1.0f, 1.0f, 1.0f}; float3 AmbiColor : Ambient < string UIName = "Added Ambient"; string UIWidget = "Color"; > = {0.0f, 0.0f, 0.0f}; float3 SurfColor : Diffuse < string UIName = "Added Diffuse"; string UIWidget = "Color"; > = {0.0f, 0.0f, 0.0f}; ////////////////////////////////////// /// Textures ///////////////////////// ////////////////////////////////////// texture halfAngleMapOrig < string ResourceName = "ctHalf.dds"; string ResourceType = "2D"; string UIName = "Map with dot-half-angle factors"; >; sampler2D hmapOrigSampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; AddressU = Clamp; AddressV = Clamp; }; /////////// texture normalAngleMapOrig < string ResourceName = "ctNorm.dds"; string ResourceType = "2D"; string UIName = "Map with dot-normal factors"; >; sampler2D nmapOrigSampler = sampler_state { Texture = ; MinFilter = Linear; MagFilter = Linear; MipFilter = None; AddressU = Clamp; AddressV = Clamp; }; // targets for painting DECLARE_QUAD_TEX(halfAngleMap,hmapSampler,"A16B16G16R16") DECLARE_QUAD_TEX(normalAngleMap,nmapSampler,"A16B16G16R16") //////////// Brush texture /////////// #ifdef CURVE_FROM_FILE texture BrushTex < string name="some_user_curve_map.dds"; string ResourceType = "2D"; >; #else /* ! CURVE_FROM_FILE */ // // This code just builds a sample curve for testing // // // assume "t" ranges from 0 to 1 safely // brute-force this, it's running on the CPU QUAD_REAL3 c_bezier(QUAD_REAL3 c0, QUAD_REAL3 c1, QUAD_REAL3 c2, QUAD_REAL3 c3, QUAD_REAL t) { QUAD_REAL t2 = t*t; QUAD_REAL t3 = t2*t; QUAD_REAL nt = 1.0 - t; QUAD_REAL nt2 = nt*nt; QUAD_REAL nt3 = nt2 * nt; QUAD_REAL3 b = nt3*c0 + (3.0*t*nt2)*c1 + (3.0*t2*nt)*c2 + t3*c3; return b; } // function used to fill the volume noise texture QUAD_REAL4 color_curve(QUAD_REAL2 Pos : POSITION) : COLOR { QUAD_REAL3 kolor0 = QUAD_REAL3(0.0,0.0,0.0); QUAD_REAL3 kolor1 = QUAD_REAL3(0.0,1.0,-1.0); QUAD_REAL3 kolor2 = QUAD_REAL3(1.0,0.0,2.0); QUAD_REAL3 kolor3 = QUAD_REAL3(1.0,1.0,1.0); QUAD_REAL3 sp = c_bezier(kolor0,kolor1,kolor2,kolor3,Pos.x); return QUAD_REAL4(sp,Pos.x); } texture BrushTex < string ResourceType = "2D"; string function = "color_curve"; string UIWidget = "None"; float2 Dimensions = { 256.0f, 4.0f}; // could be height=1, but I want it to be visible in the Texture View... >; #endif /* ! CURVE_FROM_FILE */ sampler BrushSampler = sampler_state { texture = ; AddressU = CLAMP; AddressV = CLAMP; MIPFILTER = LINEAR; MINFILTER = LINEAR; MAGFILTER = LINEAR; }; ////// VM functions and static variables (executed by CPU) //////////// static float Fadeout = (1 - min(1,max(0,(Timer - MouseL.w))/FadeTime)); static float BrushSize = (lerp(BrushSizeEnd,BrushSizeStart,Fadeout)); /************* DATA STRUCTS **************/ /* data from application vertex buffer */ struct appdata { float3 Position : POSITION; float4 UV : TEXCOORD0; float4 Normal : NORMAL; }; /* data passed from vertex shader to pixel shader */ struct vertexOutput { float4 HPosition : POSITION; float2 HalfAngleIndex : TEXCOORD0; // dot prods against half-angle float2 NormalIndex : TEXCOORD1; // dot-prods against normal float2 UV : TEXCOORD2; // plain-ol' UV float4 Diffuse : COLOR0; }; /*********** vertex shader ******/ vertexOutput cookTorrMultVS(appdata IN) { vertexOutput OUT = (vertexOutput)0; float4 Po = float4(IN.Position.xyz,1.0); //compute worldspace position float3 Pw = mul(Po, WorldXf).xyz; float3 Nw = mul(IN.Normal, WorldITXf).xyz; Nw = normalize(Nw); float ldn = dot((-LightDir),Nw); float diffComp = max(0,ldn); float3 diffContrib = SurfColor * ( diffComp * LightColor + AmbiColor); OUT.Diffuse = float4(diffContrib,1.0); OUT.UV = IN.UV.xy; // not currently used float3 EyePos = ViewInvXf[3].xyz; float3 vertToEye = normalize(EyePos - Pw); float3 halfAngle = normalize(vertToEye - LightDir); float2 halfIndices = float2(0.5-dot(LightDir,halfAngle)/2.0, 1.0 - (0.5+dot(Nw,halfAngle)/2.0)); float2 normIndices = float2(0.5-dot(LightDir,Nw)/2.0, 1.0 - (0.5+dot(Nw,vertToEye)/2.0)); OUT.HalfAngleIndex = halfIndices; OUT.NormalIndex = normIndices; OUT.HPosition = mul(Po, WvpXf); return OUT; } /********* pixel shader ********/ float4 cookTorrMultPS(vertexOutput IN) : COLOR { float3 nspec = tex2D(hmapSampler, IN.HalfAngleIndex).xyz * tex2D(nmapSampler, IN.NormalIndex).xyz * LightColor; float4 result = IN.Diffuse + float4(nspec.xyz,1); return result; } /***************************************************/ /*** The dead-simple paintbrush shader *************/ /***************************************************/ static float PaintNorm = (PaintFlag * (HASelect?0.0:1.0) * MouseL.z); static float PaintHalf = (PaintFlag * (HASelect?1.0:0.0) * MouseL.z); float4 stroke_value(float2 pixel,float2 BrushPos,uniform float PaintNow) { float2 delta = pixel-BrushPos; float dd = PaintNow*(1.0 - length(delta)/BrushSize); dd = tex2D(BrushSampler,float2(dd,0)).x; dd *= Opacity * Fadeout; return float4(PaintColor.xyz,dd); } float4 iso_stroke_value(float2 pixel, float2 BrushPos, uniform float PaintNow) { float cb = BrushPos.y-BrushPos.x; float cp = pixel.y-pixel.x; float delta = abs(cp-cb)/1.414; float db = (delta/BrushSize); float dd = 1 - db; float dt = PaintNow * tex2D(BrushSampler,float2(dd,0)).x; dd = dt * Opacity * Fadeout; return float4(PaintColor.xyz,dd); } float4 strokeNormPS(QuadVertexOutput IN) : COLOR { float4 brush1 = stroke_value(IN.UV.xy,MousePos.xy,PaintNorm); float4 brush2 = stroke_value(IN.UV.xy,float2(1.0-MousePos.y,1.0-MousePos.x),PaintNorm); float4 sym = max(brush1,brush2); float4 iso = iso_stroke_value(IN.UV.xy,MousePos.xy,PaintNorm); sym = (NmSym ? sym : brush1); return (NmIso ? iso : sym); } float4 strokeHalfPS(QuadVertexOutput IN) : COLOR { float4 brush1 = stroke_value(IN.UV.xy,MousePos.xy,PaintHalf); float4 brush2 = stroke_value(IN.UV.xy,float2(IN.UV.x,MousePos.y),PaintHalf); return (HfSym ? brush2 : brush1); } QUAD_REAL4 bgLayerPS(QuadVertexOutput IN) : COLOR { QUAD_REAL4 h = float4(tex2D(hmapSampler, IN.UV).xyz,1); QUAD_REAL4 n = float4(tex2D(nmapSampler, IN.UV).xyz,1); if (HASelect) { n = h; } return n; } /*************/ technique ps11 < string Script = "RenderColorTarget0=;" "RenderDepthStencilTarget=;" "LoopByCount=bReset;" "Pass=revertHalfAng;" "Pass=revertNorms;" "LoopEnd=;" "Pass=paintHalfAng;" "Pass=paintNormals;" "RenderColorTarget0=;" "RenderDepthStencilTarget=;" "ClearSetColor=ClearColor;" "ClearSetDepth=ClearDepth;" "Clear=Color;" "Clear=Depth;" "LoopByCount=Painting;" "Pass=bgLayer;" "LoopEnd=;" "Pass=draw3d;"; > { pass revertHalfAng < string Script = "RenderColorTarget0=halfAngleMap;" "RenderDepthStencilTarget=;" "Draw=Buffer;"; > { VertexShader = compile vs_1_1 ScreenQuadVS(); AlphaBlendEnable = false; ZEnable = false; PixelShader = compile ps_2_a TexQuadPS(hmapOrigSampler); } pass revertNorms < string Script = "RenderColorTarget0=normalAngleMap;" "RenderDepthStencilTarget=;" "Draw=Buffer;"; > { VertexShader = compile vs_1_1 ScreenQuadVS(); AlphaBlendEnable = false; ZEnable = false; PixelShader = compile ps_2_a TexQuadPS(nmapOrigSampler); } pass paintHalfAng < string Script = "RenderColorTarget0=halfAngleMap;" "RenderDepthStencilTarget=;" "Draw=Buffer;"; > { VertexShader = compile vs_1_1 ScreenQuadVS(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; ZEnable = false; PixelShader = compile ps_2_a strokeHalfPS(); } pass paintNormals < string Script = "RenderColorTarget0=normalAngleMap;" "RenderDepthStencilTarget=;" "Draw=Buffer;"; > { VertexShader = compile vs_1_1 ScreenQuadVS(); AlphaBlendEnable = true; SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; ZEnable = false; PixelShader = compile ps_2_a strokeNormPS(); } pass bgLayer < string Script = "RenderColorTarget0=;" "RenderDepthStencilTarget=;" "Draw=Buffer;"; > { VertexShader = compile vs_1_1 ScreenQuadVS(); AlphaBlendEnable = false; ZEnable = false; PixelShader = compile ps_2_a bgLayerPS(); } pass draw3d < string Script = "RenderColorTarget0=;" "RenderDepthStencilTarget=;" "Draw=Geometry"; > { VertexShader = compile vs_1_1 cookTorrMultVS(); ZEnable = true; ZWriteEnable = true; CullMode = None; PixelShader = compile ps_1_1 cookTorrMultPS(); } } /***************************** eof ***/ ]]>; \ 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 /// ]]>