Geometry Shader简明教程



[code]
int main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitWindowPosition(256,128);
glutInitWindowSize(512,512);
glutCreateWindow("OpenGL geometry shader demo");
GLenum err;
//初始化GLEW以及确定你的GPU是否支持GS功能
if((err=glewInit())!=GLEW_OK){
printf("Error:GLEW initialize failed. ");
return -1;
}
if(!glewIsSupported("GL_NV_gpu_program4")){
printf("Error:nessary extensions not suported. ");
return -1;
}
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glEnable(GL_LINE_SMOOTH);
initASMShader();
glutMainLoop();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_GEOMETRY_PROGRAM_NV);
glDisable(GL_VERTEX_PROGRAM_ARB);
return 0;
}
[/code]
Vertex Shader

代码:

static GLuint vertexProgram;
static GLuint geometryProgram;
static const char* srcVP=ASM_PROC_PATH_VP "quadMesh.vp";
static const char* srcGP=ASM_PROC_PATH_GP "quadMesh.gp";
//ASM_PROC_PATH_VP等定义在UDH/shaderPath.h中,UDH="User Defined Header"^-^
//#define ASM_PROC_PATH_VP "C:GPU Shaders/ASM/VP/"
代码:

void initASMShader()
{
vertexProgram=asmShaderLoador(GL_VERTEX_PROGRAM_ARB,srcVP);
geometryProgram=asmShaderLoador(GL_GEOMETRY_PROGRAM_NV,srcGP);
//asmShaderLoador包含在UDH/asmShader.h文件中,代码如下:
/*GLuint asmShaderLoador(GLenum t,const char* src)
{
assert(t==GL_VERTEX_PROGRAM_ARB||
t==GL_GEOMETRY_PROGRAM_NV||
t==GL_FRAGMENT_PROGRAM_ARB);
FILE* fp;
if((fp=fopen(src,"rb"))==NULL){
switch(t){
case GL_VERTEX_PROGRAM_ARB:
printf("Error:[asm].vp file open failed. ");
break;
case GL_GEOMETRY_PROGRAM_NV:
printf("Error:[asm].gp file open failed. ");
break;
case GL_FRAGMENT_PROGRAM_ARB:
printf("Error:[asm].fp file open failed. ");
break;
}
return 0;
}
fseek(fp,0,SEEK_END);
long len=ftell(fp);
fseek(fp,0,SEEK_SET);
char* cBuffer=NULL;
cBuffer=(char*)malloc(len+1);
while(!feof(fp)){
fread(cBuffer,1,len,fp);
}
GLuint PROC;
glGenProgramsARB(1,&PROC);
glBindProgramARB(t,PROC);
glProgramStringARB(t,GL_PROGRAM_FORMAT_ASCII_ARB,len,cBuffer);
free(cBuffer);
fclose(fp);
GLint errPos=0;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&errPos);
if(errPos!=-1||glGetError()!=GL_NO_ERROR){
switch(t){
case GL_VERTEX_PROGRAM_ARB:
printf("[VP].err.pos:%d ",errPos);
printf("[VP].err.str:%s ",glGetString(GL_PROGRAM_ERROR_STRING_ARB));
break;
case GL_GEOMETRY_PROGRAM_NV:
printf("[GP].err.pos:%d ",errPos);
printf("[GP].err.str:%s ",glGetString(GL_PROGRAM_ERROR_STRING_ARB));
break;
case GL_FRAGMENT_PROGRAM_ARB:
printf("[FP].err.pos:%d ",errPos);
printf("[FP].err.str:%s ",glGetString(GL_PROGRAM_ERROR_STRING_ARB));
break;
default:
assert(0);
}
return 0;
}
glEnable(t);
return PROC;
}*/

}
代码:

void display(void)
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
glTranslatef(-0.5,0.45,0.0);
glEnable(GL_POINT_SMOOTH);
glPointSize(2.0);
glBegin(GL_POINTS);
glVertex2f(0.0,0.0);//仅绘制一个点,即可派生出整个最终的Quad Mesh
glEnd();
glDisable(GL_POINT_SMOOTH);
glPopMatrix();
glFlush();
}
代码:

void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,(double)w,0.0,(double)h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
代码:

#quadMesh.vp
!!ARBvp1.0
DP4 result.position.x,vertex.position,state.matrix.mvp.row[0];
DP4 result.position.y,vertex.position,state.matrix.mvp.row[1];
DP4 result.position.z,vertex.position,state.matrix.mvp.row[2];
DP4 result.position.w,vertex.position,state.matrix.mvp.row[3];
END

顶点程序只是简单的向几何管线传递几何数据,其他什么也不做(这里我们仅仅演示GS的使用,VS相信大家已经是再熟悉不过了)
代码:

#quadMesh.gp
!!NVgp4.0
PRIMITIVE_IN POINTS;
PRIMITIVE_OUT LINE_STRIP;
VERTICES_OUT 125;
#8800GTS(估计整个G8系列都是如此)最大支持的每个图元最大的顶点输出量为256,如果输出的顶点数量大于256,你的显卡也许不会报错,而且你的程序也将继续执行,但多余的顶点将会被忽略
TEMP LoopDep;
MOV.U LoopDep,5;
FLOAT TEMP ePos;//发射顶点的位置变量
FLOAT TEMP xPos;
FLOAT TEMP yPos;
MOV.F xPos,vertex[0].position;
MOV.F yPos,vertex[0].position;
MOV.F ePos,vertex[0].position;
#绘制水平直线栏
#每条线由5个顶点strip而成
#没绘制一条,ePos即被初始化为原始值,
#并且其Y坐标递增一个step,以便下一条线的绘制
REP.S LoopDep.y;
REP.S LoopDep.x;
MOV.F result.position,ePos;
EMIT;
ADD.F ePos.x,ePos.x,{0.25}.x;
ENDREP;
ENDPRIM;
ADD.F xPos.y,xPos.y,{-0.25}.x;
MOV.F ePos,xPos;
ENDREP;
#绘制垂直直线栏
#最终的结果将是与水平栏交叉形成网格
MOV.F ePos,yPos;
REP.S LoopDep.x;
REP.S LoopDep.y;
MOV.F result.position,ePos;
EMIT;
ADD.F ePos.y,ePos.y,{-0.25}.x;
ENDREP;
ENDPRIM;
ADD.F yPos.x,yPos.x,{0.25}.x;
MOV.F ePos,yPos;
ENDREP;
END
Geometry Shader
执行结果:
修改GP
[code]
!!NVgp4.0
PRIMITIVE_IN POINTS;
PRIMITIVE_OUT POINTS;
VERTICES_OUT 200;
INT TEMP LoopDep;
MOV.U LoopDep,10;
FLOAT TEMP ePos;
FLOAT TEMP xPos;
FLOAT TEMP yPos;
MOV.F xPos,vertex[0].position;
MOV.F yPos,vertex[0].position;
MOV.F ePos,vertex[0].position;
REP.U LoopDep.y;
REP.U LoopDep.x;
MOV.F result.position,ePos;
EMIT;
ADD.F ePos.x,ePos.x,{0.125}.x;
ENDREP;
ENDPRIM;
ADD.F xPos.y,xPos.y,{-0.125}.x;
MOV.F ePos,xPos;
ENDREP;
MOV.F ePos,yPos;
REP.U LoopDep.x;
REP.U LoopDep.y;
MOV.F result.position,ePos;
EMIT;
ADD.F ePos.y,ePos.y,{-0.125}.x;
ENDREP;
ENDPRIM;
ADD.F yPos.x,yPos.x,{0.125}.x;
MOV.F ePos,yPos;
ENDREP;
END
[/code]
用同一个程序载入运行,自己试试看吧。
比起这个,画圆或参数曲线要容易多了。
很容易将这个几何着色器修改成3D CUBE Mesh
但是本程序生成的是5x5的网格网格,每个直线有5个顶点共有125个
所以如果绘制CUBE,将会有25x25x25个顶点,所以如果你有兴趣将
他改成3D CUBE GP着色器,建议使用2X2网格,不过那样也仅仅可以绘制6个面,
而不是空间网格。但这些情况仅限于本程序,因为在该程序中我没有考虑顶点的
共享问题。希望以后会出现
转载请注明出处
  

你可能感兴趣的:(shader,primitive,fp,float,网格,path,OpenGL)