最近在练习几何着色器的绘制,有一些体会和练习作品。
结果:半径和精度都可调。
1.绘制圆形:
(1)此例子绘制的圆形是基于xy平面的,绘制的基本思路是公式:
degree=2*PI/fragments;
P1.x=P0.x+Radius*cos(degree*i);
P1.y=P0.y+Radius*sin(degree*i);
(2)在3D渲染管线中,可以在几何着色器中由一点生成顶点位置,并绘制图形。在本例子中,从外部应用程序(这里的外部应用程序使用的是OSG渲染库)传入一点、半径和精度。半径和精度使用的uniform修饰的变量传递。
(3)代码实现
VertexShader:顶点着色器这里只是执行一个很简单的接收外部应用程序的数据(这里是顶点数据),并传递顶点数据的功能。
"#version 330 \n"
"layout (location = 0) in vec4 Position; \n"
"void main() \n"
"{ \n"
" gl_Position = Position; \n"
"} \n"
GeometryShader:到了几何着色器这里,要做的工作就相对多一点,负责顶点的生成和圆形的绘制。layout里面设置了输入图元是三角形,表示几何着色器一次可以处理3个顶点,则外部应用允许的绘制模式是三角形。几何着色器中的输入图元和外部允许的绘制模式之间,具体的对应关系是:
"#version 330 \n"
"layout(triangles) in; \n"
"layout(triangle_strip) out; \n"
"layout(max_vertices = 100) out; \n"
"uniform int fragments;\n"
"uniform mat4 osg_ModelViewProjectionMatrix; \n"
"uniform float Radius; \n"
"void Draw_TopCircle_Plane()\n"
"{\n"
"vec4 centerP = gl_in[0].gl_Position;\n"
" int i; \n"
"float Pi=3.14;\n"
"gl_Position=osg_ModelViewProjectionMatrix * centerP;\n"
" EmitVertex(); \n"
"float du = 2.0f * Pi / fragments; \n"
" for (i = 0; i < fragments; i++) \n"
" { \n"/*0*/
"vec4 vertex_1 = vec4(centerP.x+Radius*cos(du*i),centerP.y+Radius*sin(du*i),0.0,1.0);\n"
"gl_Position = osg_ModelViewProjectionMatrix * vertex_1;\n"
" EmitVertex(); \n"
"gl_Position=osg_ModelViewProjectionMatrix * centerP;\n"
" EmitVertex(); \n"
" } \n"
"vec4 vertex_2 = vec4(centerP.x+Radius*cos(du*(fragments)),centerP.y*sin(du*(fragments)),0.0,1.0);\n"
"gl_Position = osg_ModelViewProjectionMatrix * vertex_2;\n"
" EmitVertex(); \n"
"vec4 vertex_3 = vec4(centerP.x+Radius,centerP.y,0.0,1.0);\n"
"gl_Position = osg_ModelViewProjectionMatrix * vertex_3;\n"
" EmitVertex(); \n"
" EndPrimitive(); \n"
"}\n"
"void main(void) \n"
"{ \n"
"Draw_TopCircle_Plane();\n"
"} \n"
Fragmentshader:片元着色器这里只是简单的使用一个通道输出颜色而已
"#version 330 \n"
"layout (location = 0) out vec4 fragData; \n"
"void main() \n"
"{ \n"
" fragData = vec4(0.0,1.0,1.0,1.0); \n"
"} \n"
外部设置代码:
A.设置Uniform:
osg::Vec4 color(0.0, 1.0, 0.5, 1.0);
stateSet->addUniform(new osg::Uniform("color", color));
int fragments = 10;
stateSet->addUniform(new osg::Uniform("fragments", fragments));
float Radius = 10;
stateSet->addUniform(new osg::Uniform("Radius", Radius));
B.设置绘制
geom->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 3));
(4)绘制的效果