Geometry Shader_0:GLSL

ZDNet软件频道时间2008-07-03作者:星月冢 | PhysDev论坛
本文关键词:GPU Geometry shader
代码:
#ifdef __VERSION__ //可选,如果在VS中使用,那么没有必要再在GS中使用,因为偶没有听说过(至少现在)那个Graphisc Chipest厂家会只提供VS,GS或FS #version 120 #endif #extension EXT_GPU_shader4:enable varying mat4 HTBN;//用一在GS和FS中矢量变化的活动标架矩阵,用以将矢量变换到"曲面"(这样说比较形象)的"相对论空间"(或内嵌), 在这个空间中的矢量是抽象出的自然坐标,一般情况下是3X3矩阵,但偶这里将其作为齐次句阵处理,所以是HTBN(Homogenous-Tangent-Binormal-Normal) void main() { vec3 vNormal=normalize(gl_NormalMatrix*gl_Normal); vec3 vTangent=normalize(vec3(vNormal.y-vNormal.z,vNormal.z-vNormal.x,vNormal.x-vNormal.y)); vec3 vBinormal=cross(vNormal,vTangent); HTBN=mat4(vec4(vTangent,0.0),vec4(vBinormal,0.0),vec4(vBinormal,0.0),vec4(1.0)); gl_Position=HTBN*gl_Vertex; gl_FrontColor=gl_Color; gl_TexCoord[0]=gl_MultiTexCoord0; }
Geometry shader
代码:
#version 120 #extension EXT_GPU_shader4:require #extension EXT_Geometry_shader4:require varying in  mat4  HTBN[];//Note:由于GS是以图元为处理单位的,而每个图元并不一定有一个顶点,GPU每一桢会为每个图元的每个顶点(当然图元处理是依次进行的)运行若干次,因此在对每个图元的处理过程中会根据输入图元的类型确定在该单批次中的顶点数量(也既单个图元的顶点数量),所以从顶点接受来的数据会被按图元类型确定的单批数量确定每个数据数组的数量(语言运用太烂。。)简单点,就是在运行时动态载入的直观一点:比如在顶点程序中处理了9个顶点,输入类型为POINTS,输出类型为TRIANGLES,那么在GS中的每个单批次中会同时处理3个顶点,就好象在处理之前将传进的数据分组:v0--v1--v2 : v3--v4--v5 : v6--v7--v8 uniform vec4 offset; void main() { for(int i=0;i<gl_VerticesIn;i++) { gl_Position=HTBN*(gl_PositionIn[i]+offset); gl_FrontColor=gl_FrontColorIn[i]; EmitVertex(); } EndPrimitive; }
Fragment shader
代码:
#version 120 #extension ARB_draw_buffers:enable//可以不用,因为GL2.0~2.1核心已经支持同时写入多个颜色缓冲区 #extension EXT_GPU_shader4:enable #extension EXT_texture_array:enable noperspective varying mat4 HTBN; uniform sampler2DArray multiTexMap;//EXT_GPU_shader4新增的(基于NV_GPU_program4) uniform float near; uniform float far; uniform mat3 kernel= { , , };//注意,矩阵在GLSL中是按列存取的,但由于这里数据的对称性,所以看不出传统习惯与转置的区别 //偶这里在shader中初始化而不是将来在程序中 void main() { vec4 CoordShape=HTBN*texture2DArray(multiTexMap,gl_TexCoord[0].xyz,0.0); CoordShape.xyz*=kernel; gl_FragData[0]=CoordShape.r*gl_Color; gl_FragData[1]=CoordShape.g*gl_Color; gl_FragData[2]=CoordShape.b*gl_Color; float scale=1/(far-near);//这样只需1次昂贵的(至少在GPU时间中)除法运算 float mNear=near*scale; float mFar=near*far*scale; gl_FragDepth=mNear+mFar/gl_FragCoord.z; }
下面开始载入shader
代码:
#include<stdafx.h> #include<stdlib.h> #include<iostream.h> #include<fstream.h> #include<GL/wglew.h> #include<GL/glew.h> #include<GL/glut.h>
//这里说点白痴的,当变量声明为static是会被自动初始化为0(不知许多人为何仍然喜欢用NULL,但无论如何将NULL替换为0总不会错,但反过来却未必如此,但使用NULL可能会让一些人感觉成熟些(因为它可有些历史了,呵呵,偶有时也是如此
代码:
static GLuint VS; static GLuint GS; static GLuint FS; static GLuint FBO; static GLuint RBO; static GLuint TXO; static GLuint Proc; static GLint  layer; static GLint  MaxLayer; static GLint  sizeHC , sizeV , sizeZ; static GLint  level; const char* scFile[]=;//假定存在这个位置//
首先创建用以读取代码的函数。说实话,在几天前偶对字符和文件处理还一窍不通,所以在NET上大肆搜掠,终于可以写些简单的流处理函数了,不要笑偶
代码:
char* SrcCodeGenor(const char* fileName) {   fstream ChGenor(fileName,ios::in);   ChGenor.seekg(0,ios::end);     int len=CpGenor.tellg();   CpGenor.seekg(0,ios::beg);   char* Cp=new char[len+1];   while(!CpGenor.eof())   {     ChGenor.read(Cp,len);   }   if(ChGenor.rdstate()==ios::goodbit)   {     cout<<"File Reading as Successful!"<<endl;   }   else if(ChGenor.rdstate()==ios::failbit//ChGenor.rdstate()==ios::badbit)   {     cout<<"Reading File as Faliure"<<endl;     exit(1);   }   else if(ChGenor.rdstate()==ios::eofbit)   {     cout<<"File be Read Finish"<<endl;   } return Cp; delete[] Cp; }
代码:
void Loadshader(const char* sname[3]) {   if(!glewIsSupported("GL_EXT_GPU_shader4")   {     cout<<"It`s very bad that your current context not supported this extensions"<<endl;   }   VS=glCreateshader(GL_VERTEX_shader);   GS=glCreateshader(GL_Geometry_shader_EXT);//Note:如果使用汇编shader需要启用GL_NV_Geometry_program4:glEnable(GL_Geometry_PROGRAM_NV)   FS=glCreateshader(GL_FRAGMENT_shader);   glshaderSource(VS,1,SrcCodeGenor(sname[0]),NULL);//姐姐啊,怎么偶又用NULL了   glshaderSource(GS,1,SrcCodeGenor(sname[1]),NULL);   glshaderSource(FS,1,SrcCodeGenor(sname[2]),NULL);   glCompileshader(VS);   GLint vcompiled;//我一直遵循在需要时创建,也许的确不错   glGetshaderiv(VS,GL_COMPILE_STATUS,&vcompiled);   if(vcompiled!=GL_TRUE)   {     cout<<"Error:Vertex shader compile status as faliure"<<endl;     exit(1);   }   glCompileshader(GS);   GLint gcompiled;   glGetshaderiv(GS,GL_COMPILE_STATUS,&gcompiled);   if(gcompiled!=GL_TRUE)   {     cout<<"Error:Geometry shader compile status as faliure"<<endl;     exit(1);   }   glCompileshader(FS);   GLint fcompiled;   glGetshaderiv(FS,GL_COMPILE_STATUS,&fcompiled);   if(fcompiled!=GL_TRUE)   {     cout<<"Error:Fragment shader compile status as faliure"<<endl;     exit(1);   }   Proc=glCreateProgram();     glAttachshader(Proc,VS);   glAttachshader(Proc,GS);   glAttachshader(Proc,FS);   glLinkProgram(Proc);   GLint linked;   glGetProgramiv(Proc,GL_LINK_STATUS,&linked);   if(!linked)   {     cout<<"Error:Linking as Faliure for Program"<<endl;     exit(1);   }   //&&glGetAttribLocation必须在连接成功后的任何时候可以使用,而glBindAttribLocation则必须在连接之前   //如果不使用,则会在连接时由GL自动分配绑定   GLint GSUnif=glGetUniformLocation(Proc,"offset");   glUniform4f(GSUnif,0.1,0.1,0.1,1.0);     GLint FSUnif0=glGetUniformLocation(Proc,"multiTexMap");   GLint FSUnif1=glGetUniformLocation(Proc,"near");   GLint FSUnif2=glGetUniformLocation(Proc,"far");     glUniformi(FSUnif0,   0);   glUniformf(FSUnif1, 5.0);   glUniformf(FSUnif2,-5.0);     glProgramParameteriEXT(Proc,GL_Geometry_VERTICES_OUT_EXT,500);//>gl_VerticesIn:VERTICES_OUT(NV_Geometry_program4)   glProgramParameteriEXT(Proc,GL_Geometry_INTPUT_TYPE_EXT,GL_POINTS);//PRIMITIVE_IN   glProgramParameteriEXT(Proc,GL_Geometry_OUTPUT_TYPE_EXT,GL_TRIANGLES);//PRIMITIVE_OUT   glValidateProgram(Proc);   GLint valided;   glGetProgramiv(Proc,GL_VALIDATE_STATUS,&valided);   if(!valided)   {     cout<<"The Program can not run in current envirenment"<<endl;     exit(1);   }     glUseProgram(Proc); }
//构建纹理相关
代码:
void texExtrude() {   glGenTextures(1,&TXO);   glGenFrameBuffersEXT(1,&FBO);   glGenRenderBuffersEXT(1,&RBO);     glBindTexture(GL_TEXTURE_2D_ARRAY_EXT,TXO);   glBindFrameBufferEXT(GL_FRAMEBUFFER_EXT,FBO);   glBindRenderBufferEXT(GL_RENDERBUFFER_EXT,RBO);     glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_MAG_FILTER,GL_LINEAR);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_WRAP_S,GL_CLAMP);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_WRAP_T,GL_CLAMP);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_WRAP_R,GL_CLAMP);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_BASE_LEVEL,level-1);   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT,GL_TEXTURE_MAX_LEVEL,0);   glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);   glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);   glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_NORMAL_MAP);   glGenerateMipMapEXT(GL_TEXTURE_2D_ARRAY_EXT);   glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT,0,GL_DPETH_COMPONENT_EXT,sizeH,sizeV,sizeZ,0,GL_RGBA,GL_FLOAT,0);//for sampler2DArray   for(int layer=0;layer<MaxLayer;layer++)   {   glFrameBufferTextureLayerEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,TXO,layer/level,layer);//   }   glRenderBufferStoageEXT(GL_RENDERBUFFER_EXT,GL_RGBA32F,sizeH,sizeV);   glFrameBufferRenderBufferEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,RBO);     GLenum aux[]={ GL_AUX0 , GL_AUX1 , GL_AUX2 };   glReadBuffer(GL_FRAMEBUFFER_EXT);//最终像素读取来源   glDrawBuffers( 3,aux );//用于颜色绘制的目标缓冲区,gl_FragData[0..2]生成的颜色数据将分别写入这3个辅助缓冲区     glEnable(GL_TEXTURE_2D_ARRAY_EXT);   glEnable(GL_TEXTURE_GEN_S);   glEnable(GL_TEXTURE_GEN_T);   glEnable(GL_TEXTURE_GEN_R); }
//创建几何相关
代码:
enum mode{ nurbs,bezier }; void GenGeo() {   switch(mode)   {     case nurbs:     case NURBS:     GLfloat cPt[100][100][3];     GLfloat uknot[100];     GLfloat vknot[100];     for(int j=0;j<100;j++)     {       for(int i=0;i<100;i++)       {         cPt[i][j][0]=i*(j+0);         cPt[i][j][1]=i*(j+1);         cPt[i][j][2]=i*(j+2);         ukont[i]=0.03*i;       }      vknot[j]=0.07*j;     }     GLUnurbsObj* nurbs=gluNewNurbsRenderer();     gluBeginSurface(nurbs);       glNurbsSurface(nurbs,100,uknot,100,vknot,0,9,cPt,3,3,GL_MAP2_VERTEX_3);     gluEndSurface(nurbs);     case bezier:     case BEZIER:     glMapGrid2d(100,0.0,10.0,100,0.0,10.0);     glEvalMesh2(GL_FILL,0,99,0,99);   }   glEnable(GL_MAP2_VERTEX_3); glutPostRedisplay(); }
代码:
#define disableGLstate() {   glDeleteRenderBuffersEXT(1,RBO);   glDeleteFrameBuffersEXT(1,FBO);   glDelateTextures(1,TXO);   glDisable(GL_MAP2_VERTEX_3);   glDisable(GL_TEXTURE_GEN_R);   glDisable(GL_TEXTURE_GEN_T);   glDisable(GL_TEXTURE_GEN_S);   glDisable(GL_TEXTURE_2D_ARRAY_EXT); }
代码:
int main(int argc,char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA); glutInitWindowSize(800,800); glutInitWindowPosition(20,20); glutCreateWindow("GLSL shader View:VS:GS:FS"); texExtrude(); loadshader(scFile); glutDisplayFunc(GenGeo); disableGLstate();  glutMainLoop(); return 0; }
至此结束。//大小写切换,英汉切换,偶。。。 shader 是编译通过的,至于程序没有认真检查,但这里主要是叙述使用GS的过程,而且程序应该基本没有问题。至于Cg GS以后会讲
您看到此篇文章时的感受是:
支持
愤怒
无聊
暴汗
养眼
炒作
不解
标题党
搞笑
用户评论
用户名
评论内容
发表时间
- 发表评论 -
匿名
注册用户

百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134