. . ___________ .__ \_ _____/_ __ _____|__| ____ ____ | __)| | \/ ___/ |/ _ \ / \ Tm. | | | | /\___ \| ( <_> ) | \ \___| |____//____ >__|\____/|___| / \/ \/ .___ .___ __ .__ | | ____ __| _/_ __ _______/ |________|__| ____ ______ | |/ \ / __ | | \/ ___/\ __\_ __ \ |/ __ \ / ___/ | | | \/ /_/ | | /\___ \ | | | | \/ \ ___/ \___ \ |___|___| /\____ |____//____ > |__| |__| |__|\___ >____ > \/ \/ \/ \/ \/ www.FusionIndustries.com Proudly Presents A Cg & HLSL Shading Language FAQ v0.003 June 6, 2003 This FAQ was created and is maintained by Alex (alexz@FusionIndustries.com). Any comments, questions, additions and corrections are encouraged and welcomed. The latest version of this FAQ can be found at: www.FusionIndustries.com Japanese translation by Yukio Andoh - andoh AT opengl.com www.gimlay.org/~andoh/cg/faq/cg-hlsl-faq.html This FAQ may be freely distributed or copied. This FAQ is divided up into the following sections and questions: 1. The Cg/HLSL Language 2. Profiles 3. Semantics 4. Shader Entry Point (main()) 5. Vertex Shaders 6. Fragment Shaders 7. Interfacing C/C++ and OpenGL with Cg 8. Miscellaneous 9. References 10. Bibliography 11. Change log ------------------------------------------------- 1. The Cg/HLSL Language ------------------------------------------------- 1.1: What's the difference between nVidia's Cg and Microsoft's HLSL (High Level Shading Language)? A: Cg and HLSL are actually the same language! Cg/HLSL was co-developed by nVidia and Microsoft. They have different names for branding purposes. HLSL is part of Microsoft's DirectX API and only compiles into DirectX code, while Cg can compile to DirectX and OpenGL. In this FAQ, Cg and HLSL can be used interchangably. ------------------------------------------------- 2. Profiles ------------------------------------------------- 2.1: When a shader is called, how does Cg know whether to treat it as a vertex or fragment shader? A: When a shader is loaded, one of the parameters allows the programmer to specify if it is a vertex or fragment shader. Also, the type of shader is specified when it is used. For example (using C/C++): ... CGprogram VProgram = cgCreateProgramFromFile(..."vertex_shader.cg"...); CGprofile profile = CG_PROFILE_VP20; // set globally ... void draw_loop() { cgGLBindProgram(VProgram); // Binds shader to OpenGL calls cgGLEnableProfile(profile); // Tells Cg if it is a vertex // or fragment shader // your drawing code goes here // ie glBegin(...); glVertex3f(...); glEnd(); cgGLDisableProfile(profile); // Unbinds shader } 2.2: Which profile types are supported? A: This depends on what the Cg programming has been compiled for and the hardware the program is running on. The possible profiles are supported by the Cg compiler [1] (as of this writing): * DirectX Vertex Shader 2.x Profiles (vs_2_*) * DirectX Pixel Shader 2.x Profiles (ps_2_*) * OpenGL ARB Vertex Program Profile (arbvp1) * OpenGL ARB Fragment Program Profile (arbfp1) * OpenGL NV_vertex_program 2.0 Profile (vp30) * OpenGL NV_fragment_program Profile (fp30) * DirectX Vertex Shader 1.1 Profile (vs_1_1) * DirectX Pixel Shader 1.x Profiles (ps_1_*) * OpenGL NV_vertex_program 1.0 Profile (vp20) * OpenGL NV_texture_shader and NV_register_combiners Profile (fp20) The profiles in CG are named slightly differently. For example, the vp20 profile is called CG_PROFILE_VP20. 2.3: Which profile is the best one to use? A: It depends on the features you want, the development hardware, and the target hardware. Using the most advanced profile (vs_2_*,vp30,etc) will most likely be the fastest and most powerful, but it will only run on the latest hardware. Using the older profiles (vs_1_*,vp20,etc) will run on older hardware, but may impose certain restrictions due to the limitations of hardware and might not be fully optimized for the latest hardware. The best way would be to have a code path for each type of shader and select which profile to use at run-time, by querying the graphics hardware to see which profiles it can support. ------------------------------------------------- 3. Semantics ------------------------------------------------- 3.1: Why do we attach semantics to parameters and variables? A: Semantics are hints which tell the Cg compiler that the variables have access to read and/or write to the registers that contain the current vertex, color, texture coordinates, etc when the shader is called. Without semantics, shaders couldn't interact with the states and data that the underlying graphics sytem (OpenGL/DirectX) provide. 3.2: When do we use semantics? A: Parameters with attached semantics are only considered by Cg when used with main(), otherwise they are ignored. Also, semantics can be attached to the return value of functions. For example: float4 main() : COLOR { return float4(1.0, 1.0, 0.0, 1.0); } 3.3: What are all the semantics available to be used? A: The semantics available in all profiles are: POSITION, NORMAL, BINORMAL, BLENDINDICES, BLENDWEIGHT, TANGENT, PSIZE, TEXCOORD0- TEXCOORD7 In addition, the following is a partial list of semantics available for some of the profiles: COLOR, COLOR0, DIFFUSE, COLOR1, SPECULAR, DEPTH, FOG For a complete and detailed listing, refer to Appendix B in [1]. 3.4: Anything to watch out for with semantics? A: Input binding semantics and output binding semantics can not be mixed within a single structure. ------------------------------------------------- 4. Shader Entry Point (main()) ------------------------------------------------- 4.1: Is there any special data structure, format, or variable name needed for passing parameters to shaders? A: Some paramenters must have semantics bound to them, but otherwise there are no special ways of using shaders. 4.2: I don't see a function called main() in the shader code! How can it be called? A: By default, calling cgCreateProgramFromFile(...) assumes that the Cg file contains a function called main(). However, the start of the shader program ("entry point") doesn't have to be called main(), as long as cgCreateProgramFromFile() is called with a parameter that tells what the name is of the "main()" function. In the following example, the main() function is called "MyMain()" and we tell Cg that when cgCreate...() is called. For example, MyShader.cg: void MyMain(...) {} MyCode.cpp: ... CGprogram Program = cgCreateProgramFromFile(context, CG_SOURCE, "MyShader.cg", profile, "MyMain", NULL ); ... 4.3: In most of nVidia's examples, I see a struct being passed to the shader's main function. How does Cg handle the struct containing different parameters and what does it do when some parameters aren't given? For example, struct appdata { float4 position : POSITION; float3 normal : NORMAL; float3 color : DIFFUSE; float3 TestColor : SPECULAR; }; struct vfconn { float4 pos : POSITION; float4 col0 : COLOR0; }; void main(appdata IN, ...) { vfconn OUT; ... return OUT; } A: The members of the struct have semantics specified, which connect the variables in the shader code to the underlying graphics system (OpenGL/DirectX). For example, the POSITION semantic means that the value is read from the register that hold the homogenous position of the vertex being passed to the shader. The benefit is that any struct or parameters can be passed to functions. If a struct like struct mydata { float4 position : POSITION; float3 color : DIFFUSE; }; void main(mydata m) {...} is passed to a function, then the function will only be able to access and manipulate the data associate with the registers that contain the POSITION and DIFFUSE values from the underlying graphics system (OpenGL/DirectX). This also means that other registers, for example COLOR and TEXCOORD0, cannot be accessed or modified by that function. 4.4: Why does nVidia use structs to pass and return their data to and from shaders? A: The motivation is the same as using structs in any programming language (like C/C++/Java). It is available to be used if desired, but it is not required. 4.5: Does a struct containing parameters with semantics have to be passed to main()? A: No. They can be passed as parameters too. For example: void main( float4 color : COLOR ) {} 4.6: In most of nVidia's examples, they use variables, such as "appdata IN", "vfconn OUT". Do the variable names have to be named IN and OUT? A: The variable names can be anything, as long as it is not a reserved keyword. Note that "in" and "out" are keywords. Variable names are case-sensitive. 4.7: What's the relation of the previous question (4.6) to the keywords "in", "inout" and "out"? Why are they needed if data can be passed and returned like as in C? A: The keywords are available as a matter of convenience, so all parameters can be in the function prototype. The keyword "in" is a modifier for a parameter which tells Cg that the parameter takes input when the shader is called. Similarly, the modifier "out" tells Cg the parameter contains the output of the shader. Finally, "inout" can contain both the input and output. For example: void main( in float4 inPos : POSITION, out float4 outColor: COLOR ) { float4 newPos = inPos + /* ... */; outColor = /* ... */ } ------------------------------------------------- 5. Vertex Shaders ------------------------------------------------- 5.1: Are there any restrictions on the types of parameters vertex shaders can take? A: The short answer: No. The longer answer: The only limitation is that for a given shader, semantics assigned to variables can only be used once for input variables and once for output variables. 5.2: Are there any restrictions on the return value of vertex shaders? A: Vertex shaders must return a four-component (xyzw) vertex with a POSITION binding semantic, which the rasterizer uses. It can be returned within a struct or by using the "out" keyword in the parameter list. ------------------------------------------------- 6. Fragment Shaders ------------------------------------------------- 6.1: Are there any restrictions on the types of parameters fragment shaders can take? A: The short answer: No. The longer answer: The only limitation is that for a given shader, semantics assigned to variables can only be used once for input variables and once for output variables. 6.2: Are there any restrictions on the return value of fragment shaders? A: Fragment shaders must return a color with four components (rgba) with a COLOR binding semantic and optionally depth components with a DEPTH binding semantic. It can be returned within a struct or by using the out keyword in the parameter list. ------------------------------------------------- 7. Interfacing C/C++ and OpenGL with Cg ------------------------------------------------- 7.1: How are parameters in Cg accessed from C/C++? A: By using cgGetNamedParameter(). Refer to example following the next questions. Additional ways of accessing parameters can be found in [1]. 7.2: How are parameters in Cg set? A: By using cgGLSetParameter{1234}{fdv}(), which uses a naming convention similar to OpenGL. There are additional ways of setting data, which can be found in [1]. For example, the following C code snippet creates a handle to the variable called "Diffuse" in the Cg program and sets its value to (1,0,0) (which is red). ... // assume valid Cg program source file and create a handle to it CGprogram Program = cgCreateProgramFromFile(...); // "glue" DiffuseParam to the parameter named "Diffuse" in the Cg code CGparameter DiffuseParam = cgGetNamedParameter(Program, "Diffuse"); // Use "DiffuseParam" to update the value in the Cg shader code cgGLSetParameter3f(DiffuseParam, 1,0,0); ... 7.3: When should Cg programs be called from C/C++/OpenGL? A: Cg programs should be called in the drawing loop where you want the shader to be applied and disabled at the end of the draw loop (similar to glBegin() and glEnd()). For example: void draw() { cgGLBindProgram( program ); // attach the shader cgGLEnableProfile( profile ); // specifies vertex or fragment shader // your drawing code goes here glBegin(GL_TRIANGLES); glColor3f(...); glVertex3fv(...); glEnd(); cgGLDisableProfile(profile); // stops using shader } ------------------------------------------------- 8. Miscellaneous ------------------------------------------------- 8.1: How can I write comments? A: The C/C++ commenting style is supported, which are single line comments (//) and multi-line comments (/*...*/). For example float4 pos; // This is a comment float4 dif; /* This is another comment */ float4 col; /* This is a multiline comment */ ------------------------------------------------- 9. References ------------------------------------------------- Most of this information in this FAQ can be found in greater detail in [1]. www.nVidia.com/cg www.cgshaders.org ------------------------------------------------- 10. Bibliography ------------------------------------------------- [1] CG Toolkit User's Manual (Cg_Toolkit.pdf) www.nVidia.com ------------------------------------------------- 11. Change Log ------------------------------------------------- v0.003 Jun 06, 2003: Added link to Japanese version by Yukio Andoh andoh AT opengl.com v0 002 Jun 03, 2003: Completed question 7.3, minor fixes. v0.001 May 30, 2003: Created. ------------------------------------------- Contact us at http://www.FusionIndustries.com (C)2003 Fusion Industries