[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]
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个面, 而不是空间网格。但这些情况仅限于本程序,因为在该程序中我没有考虑顶点的 共享问题。希望以后会出现 |