/*********************************************************************NVMH3**** Path: $Id: //sw/devtools/FXComposer2/Alpha4+/SDK/MEDIA/CgFX1.4/simple_interface_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. * Note the compile-time texture flag. ******************************************************************************/ // compile-time flag #define TEXTURED_SURFACE #include "glm_interfaces.cgh" /////////////////////////////////////////////////////////////////////////////////////// // 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 techniques 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 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 = "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 struct represent data streams between the vertex bffer 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. // // // Why World? // These shaders perform their 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. // // // 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; // float4 Tangent : TANGENT0; // if we were normal mapping, we'd want these too // float4 Binormal : BINORMAL0; }; // // 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; }; stdSurf : StandardSurface; // from glm_interfaces.cgh ////////////////////////////////////////////////////////////////////////////// // Utility Functions ///////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // // In this example, the diffuse value is left BLACK - zero. An obvious extension of this // BRDF would be to add some non-zero diffuse layer. // // We use function overloading to support both vertex and fragment shader programs. // // // for fragment shaders - include texturing // SurfaceInfo new_plastic_surf(vertexOutput IN) { SurfaceInfo s = (SurfaceInfo)0; s.Nn = normalize(IN.WorldNormal); s.Vn = normalize(IN.WorldView); s.SpecExpon = SpecExpon; // global param "SpecExpon" s.SpecColor = Ks.xxx; // global param "Ks" s.DiffColor = SurfColor; // global param "SurfColor" #ifdef TEXTURED_SURFACE s.DiffColor *= tex2D(ColorSampler,IN.TexCoord.xy).xyz; // global param "ColorSampler" #endif /* TEXTURED_SURFACE */ return s; } ///////////////////////////////////////////////////////////////////// // 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 all_in_onePS(vertexOutput IN, uniform float3 LightColor) : COLOR { LightResult R = (LightResult)0; // surface info values SurfaceInfo s = new_plastic_surf(IN); // point light values LightInfo l; l.Ln = normalize(IN.LightVec); // from the point source l.Color = LightColor; R = stdSurf.brdf(s,l,R); // If we wanted to add more lights, just assign new values // to LightInfo "l" and call stdSurf.brdf() again.... // Now join spec and diffuse together float3 result = (R.DiffContrib + R.SpecContrib); // finally, we add-in ambience result += (AmbiColor * s.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 all_in_onePS(PointLight0Col); } } //////////////////////////////////// //////////////////////////// eof /// ////////////////////////////////////