Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1350488
  • 博文数量: 281
  • 博客积分: 8800
  • 博客等级: 中将
  • 技术积分: 3346
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-17 22:31
文章分类

全部博文(281)

文章存档

2013年(1)

2012年(18)

2011年(16)

2010年(44)

2009年(86)

2008年(41)

2007年(10)

2006年(65)

我的朋友

分类: LINUX

2012-02-02 10:13:03

Introduction

       Nvidia opened  the geometry shader at November 13, 2006 , A geometry shader begins with a single primitive (point, line, triangle). It can read the attributes of any of the vertices in the primitive and use them to generate new primitives. A geometry shader has a fixed output primitive type (point, line strip, or triangle strip) and emits vertices to define a new primitive. A geometry shader can emit multiple disconnected primitives. The primitives emitted by the geometry shader are clipped and then processed like an equivalent OpenGL primitive specified by the application.

 Thanks for Nvidia's developer great work!

Geometry shader fit into Opengl pipeline

kkk

     First, vertex attributes are specified via immediate-mode commands or through vertex arrays. They can be conventional attributes (e.g., glVertex, glColor, glTexCoord) or generic (numbered) attributes. Vertices are then transformed, either using a vertex shader or fixed-function vertex processing. Fixed-function vertex processing includes position transformation (modelview and projection matrices), lighting, texture coordinate generation, and other calculations. The results of either method are a "transformed vertex", which has a position (in clip coordinates), front and back colors, texture coordinates, generic attributes (vertex shader only), and so on. Note that on many current GL implementations, vertex processing is performed by executing a "fixed function vertex shader" generated by the driver. After vertex transformation, vertices are assembled into primitives, according to the topology (e.g., TRIANGLES, QUAD_STRIP) provided by the call to glBegin(). Primitives are points, lines, triangles, quads, or polygons, but instead decompose them into triangles as permitted by the spec.

       After initial primitive assembly, a geometry shader is executed on eachindividual point, line, or triangle primitive, if one is active. It can read the attributes of each transformed vertex, perform arbitrary computations, and emit new transformed vertices. These emitted vertices are themselves assembled into primitives according to the output primitive type of the geometry shader. 

     Then, the colors of the vertices of each primitive are clamped to [0,1](if color clamping is enabled), and flat shading may be performed by taking the color from the provoking vertex of the primitive. Each primitive is clipped to the view volume, and to any enabled user-defined clip planes. Color, texture coordinate, and other attribute values are computed for each new vertex introduced by clipping. After clipping, the position of each vertex (in clip coordinates) is converted to normalized device coordinates in the perspective division (divide by w) step, and to window coordinates in the viewport transformation step. At the same time, color values may be converted to normalized fixed-point values according to the "Final Color Processing" portion of the specification. After the vertices of the primitive are transformed to window coordinate, the GL determines if the primitive is front- or back-facing. That information is used for two-sided color selection, where a single set of colors is selected from either the front or back colors associated with each transformed vertex. When all this is done, the final transformed position, colors (primary and secondary), and other attributes are used for rasterization (Chapter 3 in the OpenGL 2.0 Specification). When the raster position is specified (via glRasterPos), it goes through the entire vertex processing pipeline as though it were a point. However, geometry shaders are never run on the raster position.

 

Geometry shader setup for GLSL

     Nvidia's NVemulate allows you to emulate the functionality of various GPUs (very slowly) in software.  In addition, you can use it to control GLSL Support. New in this version of NVemulate:

  • Support for GeForce 8 Series
  • Include support enable for EXT_gpu_shader4, EXT_geometry_shader4, and EXT_bindable_uniform

     GLSL support is enabled by default in Nvidia's Release 95 drivers, but you can enable/disable the enhanced GLSL support as well as manipulate software emulation of GPU feature sets and control the dumping of GLSL source and assembly text for debugging, The NVemulate control panel looks like this:

nevemulate.png


     To enable the enhanced GLSL functionality, select the “G80(GeForce 8800 GTS, Quadro FX)” option from the GLSL compiler device support drop box and press the “Apply” button.  No changes to NVemulate settings take effect until the “Apply” button is pressed.  Pressing the “Restore” button reverts the display settings to the driver’s current applied state. With the G80 functionality enabled, the driver will export an additional set of extension strings exposing the enhanced capabilities. The extensions string will now include GL_EXT_gpu_shader4, GL_EXT_geometry_shader4, and GL_EXT_bindable_uniform. Additionally, the GLSL parts of the GL_NV_transform_feedback extension are now also enabled. Furthermore, all GLSL shaders not using these capabilities will now be compiled to the more capable G80 target. This enables better dynamic flow control and array indexing, among other benefits.  As noted earlier, some graphics cards are not capable of GLSL or enhanced GLSL in hardware, so this may require enabling a higher hardware emulation level. (A minimum of NV30 for GLSL and a minimum of G80 for the enhancements)

here three extensions are required:

GL_ARB_fragment_shader GL_ARB_vertex_shader      GL_EXT_geometry_shader4 A small example of a GLUT program using GLEW to check the extensions could be as shown below:

#include
#include

void main(int argc, char **argv)
{

glutInit(&argc, argv);

...

glewInit();
if (GL_ARB_vertex_shader && GL_ARB_fragment_shader&&GL_EXT_geometry_shader4)
printf("Ready for GLSL/n");
else {
printf("Not totally ready :( /n");
exit(1);
}

setShaders();

glutMainLoop();

}

#include
#include

void main(int argc, char **argv)
{

glutInit(&argc, argv);
...
glewInit();
if (glewIsSupported("GL_VERSION_2_1"))
printf("Ready for OpenGL 2.0/n");
else {
printf("OpenGL 2.1 not supported/n");
exit(1);
}

setShaders();

glutMainLoop();

}

Creating a  Program

    The figure bellow shows the necessary steps (in OpenGL 2.0 syntax) to create the geometry shader, the functions used will be detailed in latter sections.

kkkk

The first step is creating an object which will act as a program container. The function available for this purpose returns a handle for the container.

The syntax for this function, in OpenGL 2.0 syntax is as follows:

GLhandleARB glCreateProgramObjectARB(void);

void glProgramParameteriEXT(GLhandleARB program, enum pname, int value);

Geometry shader Input Primitives

   glProgramParameteriEXT with set to GEOMETRY_INPUT_TYPE_EXT and set to one of POINTS, LINES,
LINES_ADJACENCY_EXT, TRIANGLES or TRIANGLES_ADJACENCY_EXT.

          glProgramParameteriEXT(GLhandleARB program,GL_GEOMETRY_INPUT_TYPE_EXT ,GL_LINES_ADJACENCY_EXT);

Geometry Shader Output Primitives

    The output primitive type is a parameter of the program object, and can be set by calling glProgramParameteriEXT with set to  GL_GEOMETRY_OUTPUT_TYPE_EXT and set to one of  GL_POINTS,  GL_LINE_STRIP or GL_TRIANGLE_STRIP.

          glProgramParameteriEXT(GLhandleARB program,GL_GEOMETRY_OUTPUT_TYPE_EXT ,GL_LINE_STRIP);

Geometry Shader outputs
     A geometry shader is limited in the number of vertices it may emit per invocation. The maximum number of vertices a geometry shader can possibly emit needs to be set as a parameter of the program object that contains the geometry shader. call ProgramParameteriEXT with set to GEOMETRY_VERTICES_OUT_EXT and set to the maximum number of vertices the geometry shader will emit in one invocation. This setting will not be guaranteed to be in effect until the next time LinkProgram has been called successfully. If a geometry shader, in one invocation, emits more vertices than the value GEOMETRY_VERTICES_OUT_EXT, these emits may have no effect.

 glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT,&temp);

 glProgramParameteriEXT(GLhandleARB program,GL_GEOMETRY_VERTICES_OUT_EXT,

To attach a shader to a program use the OpenGL 2.0 function:

void glAttachObjectARB(GLhandleARB program, GLhandleARB shader);

Parameters:

program - the handler to the program. shader - the handler to the shader you want to attach.

The syntax for the link function, in OpenGL 2.0, is as follows:

void glLinkProgramARB(GLhandleARB program);

Parameters:

program - the handler to the program.

After the link operation the shader's source can be modified, and the shaders recompiled without affecting the program.

As shown in the figure above, after linking the program, there is a function to actually load and use the program, (ARB extension) glUseProgramObjectARB, or (OpenGL 2.0) glUseProgram. Each program is assigned an handler, and you can have as many programs linked and ready to use as you want (and your hardware allows).

The syntax for this function is as follows (OpenGL 2.0 notation):

void glUseProgramObjectARB(GLhandleARB prog);

Parameters:

prog - the handler to the program you want to use, or zero to return to fixed functionality

Creating a shader

     The first step is creating an object which will act as a shader container. The function available for this purpose returns a handle for the container.

The OpenGL 2.0 syntax for this function is as follows:

GLhandleARB glCreateShaderObjectARB(GLenum shaderType);

Parameter:

shaderType - GL_GEOMETRY_SHADER_EXT.

You can create as many shaders as you want to add to a program, but remember that there can only be a main function for the set of vertex shaders and one main function for the set of fragment shaders in each single program.

The following step is to add some source code. The source code for a shader is a string array.

void glShaderSourceARB(GLhandleARB shader, int numOfStrings, const char **strings, int *lenOfStrings);

Parameters:

shader - the handler to the shader. numOfStrings - the number of strings in the array. strings - the array of strings. lenOfStrings - an array with the length of each string, or NULL, meaning that the strings are NULL terminated.

Finally, the shader must be compiled. The function to achieve this using OpenGL 2.0 is:

void glCompileShaderARB(GLhandleARB shader);

Parameters:

shader - the handler to the shader.

 

Creating a geometry shader

#version 120

where number must be a version of the language, following the same convention as __VERSION__ above. The directive “#version 120” is required in any shader that uses version 1.20 of the language.  

#extension GL_EXT_geometry_shader4 : enable

where extension_name is the name of an extension. Extension names are not documented in this specification.

Geometry language built-in outputs:
varying out vec4 gl_FrontColor;
varying out vec4 gl_BackColor;
varying out vec4 gl_FrontSecondaryColor;
varying out vec4 gl_BackSecondaryColor;
varying out vec4 gl_TexCoord[]; // at most gl_MaxTextureCoords
varying out float gl_FogFragCoord;


Geometry language input varying variables:
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
varying in vec4 gl_BackColorIn[gl_VerticesIn];
varying in vec4 gl_FrontSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_BackSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_TexCoordIn[gl_VerticesIn][]; // at most will be// gl_MaxTextureCoords
varying in float gl_FogFragCoordIn[gl_VerticesIn];
varying in vec4 gl_PositionIn[gl_VerticesIn];
varying in float gl_PointSizeIn[gl_VerticesIn];
varying in vec4 gl_ClipVertexIn[gl_VerticesIn];
 
Geometry Shader Function
This section contains functions that are geometry language specific.Syntax:
void EmitVertex();
void EndPrimitive();

Description:
    The function EmitVertex() specifies that a vertex is completed. A vertex is added to the current output primitive using the current values of the varying output variables and the current values of the special built-in output variables gl_PointSize, gl_ClipVertex, gl_Layer, gl_Position and gl_PrimitiveID. The values of any unwritten output variables are undefined. The values of all varying output variables and the special built-in output variables are undefined after a call to EmitVertex(). If a geometry shader, in one invocation, emits more vertices than the valueGEOMETRY_VERTICES_OUT_EXT, these emits may have no effect.

    The function EndPrimitive() specifies that the current output primitive is completed and a new output primitive (of the same type) should be started. This function does not emit a vertex. The effect of EndPrimitive() is roughly equivalent to calling End followed by a new Begin, where the primitive mode is taken from the program object parameter GEOMETRY_OUTPUT_TYPE_EXT. If the output primitive type is POINTS, calling EndPrimitive() is optional.

#version 120
#extension GL_EXT_geometry_shader4 : enable

void main(void)
{
      mat4x4 bezierBasis=mat4x4( 1, -3, 3, -1, 0, 3, -6, 3 , 0, 0, 3, -3 , 0, 0, 0, 1);
      for(int i=0; i<64; i++)
      {
            float t = i / (64.0-1.0);
            vec4 tvec= vec4(1, t, t*t, t*t*t);
            vec4 b =tvec*bezierBasis;
            vec4 p = gl_PositionIn[0]*b.x+ gl_PositionIn[1]*b.y+ gl_PositionIn[2]*b.z+ gl_PositionIn[3]*b.w;
            gl_Position =p;
            EmitVertex();
      }
      EndPrimitive();

}

Demo&source code.

Demo :

kk

Download Demo: Demo.zip for windows XP.

source code: EMAIL to ymxie@cse.cuhk.edu.hk

References

http://developer.nvidia.com/object/nvemulate.html

http://developer.nvidia.com/object/nvidia_opengl_specs.html

阅读(1632) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~