/*********************************************************************NVMH3**** Path: $Id: //sw/devtools/FXComposer2/Alpha4+/SDK/MEDIA/CgFX1.4/simple_Cg_example.cgfx#1 $ Copyright NVIDIA Corporation 2005 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Comments: * You can use this shader as a handy platform for further experimentation. For example, consider adding reflections, or normal mapping, or additional lamps. Change the BRDF to be metallic, or other more exotic materials. Try quadratic light falloff. Explore! * Note the compile-time texture flag. ******************************************************************************/ // compile-time flag #define TEXTURED_SURFACE /////////////////////////////////////////////////////////////////////////////////////// // UNTWEAKABLES -- global variables that will be automatically tracked by FXComposer // // and other apps. You don't tweak these directly //////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// float4x4 WorldITXf : WorldInverseTranspose ; float4x4 WVPXf : WorldViewProjection ; float4x4 WorldXf : World ; float4x4 ViewIXf : ViewInverse ; /////////////////////////////////////////////////////////////////////////////////////// // TWEAKABLES -- global variables that MAY be automatically tracked, or may be //////// // manipulated by sliders and other forms of user input. ///////////////////////// /////////////////////////////////////////////////////////////////////////////////////// // A point light source, defined by its location & color /////// // These values could be shared globally, but by passing them as uniform shader parameters (see // the technique below), we can handily add more lights without having to modify the // shader programs. float4 PointLight0Pos : Position < string UIName = "Point Lamp 0 Position"; string Object = "PointLight"; string Space = "World"; > = {-54.0f, 50.0f, 100.0f, 1.0f}; float3 PointLight0Col : Diffuse < string UIName = "Point Lamp 0"; string UIWidget = "Color"; string Object = "PointLight"; > = {1.0f, 0.95f, 0.85f}; // Ambient light everywhere in the scene ////////////////////////////////// float3 AmbiColor : Ambient < string UIName = "Ambient Light"; string UIWidget = "Color"; > = {0.07f, 0.07f, 0.07f}; // Surface attributes ////////////////////////// float3 SurfColor : Diffuse < string UIName = "Surface"; string UIWidget = "Color"; > = {1.0f, 1.0f, 1.0f}; float SpecExpon : SpecularPower < string UIName = "Specular Power"; string UIWidget = "Slider"; float UIMin = 1.0; float UIMax = 128.0; float UIStep = 1.0; > = 25.0; float Kd < string UIName = "Diffuse Brightness"; string UIWidget = "Slider"; float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.05; > = 1.0; float Ks < string UIName = "Specular Brightness"; string UIWidget = "Slider"; float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.05; > = 0.6; // Surface texture ////// #ifdef TEXTURED_SURFACE texture ColorTexture : Diffuse < string ResourceName = "..\\CgFX_textures\\default_color.dds"; string ResourceType = "2D"; string UIName = "Surface Texture (if used)"; >; sampler2D ColorSampler = sampler_state { Texture = ; MinFilter = LinearMipMapLinear; MagFilter = Linear; }; #endif /* TEXTURED_SURFACE */ /////////////////////////////////////////////////////////////////////////////////// // "CONNECTOR" STRUCTS -- how vertex buffer, vertex and fragment shaders combine // /////////////////////////////////////////////////////////////////////////////////// // // The following structs represent data streams between the vertex buffer to the vertex program, // and from the vertex program to the fragment program. These are set up in standard ways // but remember, the architecture is generically programmable so we can pass whatever information // we like in whichever registers. // // These values COULD be passed as individual parameters in and aout of the shaders, // but practice has shown using structs to be easier to understand and less error-prone. // // // This is the data fed to the effect's vertex shaders from the vertex buffer. // struct appdata { float3 Position : POSITION; float4 UV : TEXCOORD0; float4 Normal : NORMAL0; }; // // This is the data that the vertex program will deliver to the rasterizer and pixel shader, // for subsequent per-fragment shading. // struct vertexOutput { float4 HPosition : POSITION; float4 TexCoord : TEXCOORD0; float3 LightVec : TEXCOORD1; float3 WorldNormal : TEXCOORD2; // why world space? see "Why World?" above float3 WorldView : TEXCOORD5; }; // // Why World? // This shader performs its lighting math in WORLD coordinates. Some shaders may use // alternative coordinate systems, usually for clightly-greater efficiency or to match // some pre-existing setup in their render engine. We use World space here because it's the // most-easily extensible -- particularly, if you add reflection cubemaps to these shaders, // the world-space normal is exactly the vector you'll need. // ///////////////////////////////////////////////////////////////////// // SHADERS - VERTEX PROGRAMS //////////////////////////////////////// ///////////////////////////////////////////////////////////////////// // // Vertex setup for fragment-shaded point lighting // vertexOutput pointlightVS(appdata IN, uniform float4 LightPos) { vertexOutput OUT = (vertexOutput)0; float4 normal = normalize(IN.Normal); OUT.WorldNormal = mul(WorldITXf, normal).xyz; float4 Po = float4(IN.Position.xyz,1); float3 Pw = mul(WorldXf, Po).xyz; OUT.LightVec = normalize(LightPos.xyz - Pw); OUT.TexCoord = IN.UV; OUT.WorldView = normalize(float3(ViewIXf[0].w, ViewIXf[1].w, ViewIXf[2].w) - Pw); OUT.HPosition = mul(WVPXf, Po); return OUT; } ///////////////////////////////////////////////////////////////////// // SHADERS - FRAGMENT (PIXEL) PROGRAMS ////////////////////////////// ///////////////////////////////////////////////////////////////////// // // unified fragment shading // float4 plasticPS(vertexOutput IN, uniform float3 LightColor) : COLOR { // surface info values float3 diffColor = SurfColor; #ifdef TEXTURED_SURFACE diffColor *= tex2D(ColorSampler,IN.TexCoord.xy).xyz; #endif /* TEXTURED_SURFACE */ float3 Nn = normalize(IN.WorldNormal); float3 Vn = normalize(IN.WorldView); float3 Ln = normalize(IN.LightVec); // from the point source float3 Hn = normalize(Vn + Ln); float4 litV = lit(dot(Ln,Nn),dot(Hn,Nn),SpecExpon); // built-in lighting function float3 diffContrib = (litV.y * Kd) * LightColor * diffColor; float3 specContrib = (Ks * litV.z) * LightColor; // Now join spec and diffuse together float3 result = (diffContrib + specContrib); // finally, we add-in ambient light result += (AmbiColor * diffColor); return float4(result,1); } ///////////////////////////////////////////////////////////////////////////////////// // TECHNIQUES -- Putting the shaders together into a complete effect //////////////// ///////////////////////////////////////////////////////////////////////////////////// // // Fragment shading combined into a single pass // technique main { pass pass0 { VertexProgram = compile arbvp1 pointlightVS(PointLight0Pos); DepthTestEnable = true; DepthMask = true; CullFaceEnable = false; BlendEnable = false; FragmentProgram = compile arbfp1 plasticPS(PointLight0Col); } } //////////////////////////////////// //////////////////////////// eof /// ////////////////////////////////////