|

楼主 |
发表于 2009-11-24 20:57:00
|
显示全部楼层
Re: 着色语言(Shader Language),以及HLSL VS GLSL VS CG
好了,这个帖子争了这么久是我想不到的。我和clayman兄争论的重点,我看并不在于学术上,而是在于语言描述上。可惜书不是我写的,不过我很欣赏国内有人写GPU和着色语言的书籍,所以贴上来给大家看看。论坛中确实有高手存在。至少通过这番争论,大家对glsl,hlsl和cg应该有一个比较了。
clayman兄老说这个引用不对,那个引用不对。好吧,我刚才又查了查,找到了一个比较正规的FAQ,国外的,贴出来给大家看看,这个应该比较客观。其实既然cg和HLSL是一样的语言,为什么不用跨平台性更好的呢?。网址是:http://www.fusionindustries.com/default.asp?page=cg-hlsl-faq
Cg and HLSL FAQ [Monday, June 02nd, 2003 - Alex]
Download Cg and HLSL FAQ as Text
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
Workshops
At SIGGRAPH this year, nVidia will be running on workshops on beginning and advanced shader techniques.
I've been to several nVidia sessions at the Game Developers Conference for the last several years and they've been very useful. Not only are the talks in-depth and enlightening, but you get to talk with people on the nVidia dev team.
My background is in graphics research, so being able to discuss the techniques I'm researching and working on with the dev team has helped me learn how to take advantage of the graphics hardware and learn from the demos they've created.
Must-Have Books
|
|