VBOShader.cpp

Demonstration of a 3D render object that uses vertex buffer objects to cache its result, plus a vertex and fragment shader.

Start e.g.:

../../../bin/vish VBOShader.vis

See also:
Required tutorials: - Simple3DObject.cpp - VertexBufferObject.cpp

Further tutorials: - VectorFieldLines.cpp

00001 
00002 #include <stdio.h>
00003 
00004 #include <ocean/GLvish/VRenderObject.hpp>
00005 #include <ocean/plankton/VCreator.hpp>
00006 #include <ocean/plankton/VTime.hpp>
00007 #include <ocean/GLvish/BoundingBox.hpp>
00008 #include <ocean/GLvish/ArrayTypes.hpp>
00009 
00010 #include <ocean/GLvish/Shader.hpp>
00011 
00012 #include <stdio.h>
00013 
00014 using namespace Wizt;
00015 
00016 
00037 class   MyRenderObject : public VRenderObject
00038 {
00039         struct  MyState : State
00040         {
00041                 double  complexity;
00042 
00043                 MyState()
00044                 : complexity(0.5)
00045                 {}
00046         };
00047 
00048         override RefPtr<State> newState() const
00049         {
00050                 return new MyState();
00051         }
00052 
00053         virtual void render(VRenderContext&Context) const;
00054 
00055 public:
00056         TypedSlot<double>       Complexity,
00057                                 ScaleFactor;
00058 
00059         MyRenderObject(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
00060         : VRenderObject(name, p, VP)
00061         , Complexity(this, "complexity", 0.5)
00062         , ScaleFactor(this, "ScaleFactor", 1.0)
00063         {}
00064 
00065         ~MyRenderObject()
00066         {}
00067 };
00068 
00069 
00070 /*
00071 http://www.opengl.org/sdk/libs/OpenSceneGraph/glsl_quickref.pdf
00072  */
00073 
00074 static const char vertexshader_src[] =
00075 "\n"
00076 ""
00077 "void main(void)\n"
00078 "{\n"
00079 "       gl_Position = ftransform();\n"
00080 ""
00081 "\n"
00082 "}\n";
00083 
00084 
00085 
00086 static const char elevation_vertexshader_src[] =
00087 
00088 #define SHADER_ELEVATION "elevation"
00089 
00090 "attribute float "SHADER_ELEVATION";\n"
00091 "uniform float scaleFactor;\n"
00092 "\n"
00093 ""
00094 "void main(void)\n"
00095 "{\n"
00096 "vec4   Pos     = gl_Vertex;\n"
00097 "       Pos.x += 0.1*scaleFactor*"SHADER_ELEVATION";\n"
00098 "       Pos.y += 0.1*scaleFactor*"SHADER_ELEVATION";\n"
00099 "       Pos.z += 0.1*scaleFactor*"SHADER_ELEVATION";\n"
00100 "vec4   V       = gl_ModelViewMatrix * Pos;\n"
00101 "       gl_Position = gl_ProjectionMatrix * V;"
00102 ""
00103 "\n"
00104 "}\n";
00105 
00106 static const char fragmentshader_src[] =
00107 "\n"
00108 "void main (void)\n"
00109 "{\n"
00110 "       gl_FragColor = gl_Color;\n"
00111 "       gl_FragColor.g = 0.5+0.5*sin(gl_FragCoord.x*3.14/20);" // allows to modify pixel depending on pixel coordinates
00112 "}\n"
00113 ;
00114 
00115 
00116 void MyRenderObject::render(VRenderContext&Context) const
00117 {
00118 static  GLfloat Red[4]   = {0.9, 0.1, 0.1, 1.0 }; 
00119 
00120 int     N = 3000;
00121 double  r = 1.0;
00122 
00123 double  complexity = 0.5;
00124         Complexity << Context >> complexity; 
00125 
00126 double  scalefactor = 1.0; 
00127         ScaleFactor << Context >> scalefactor;
00128 
00129 double  dphi = 3.1415/ 80,
00130         zs   = 0.3 * complexity;
00131 
00132         glEnable( GL_COLOR_MATERIAL );
00133         glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); 
00134         SubObjectBegin(Context);
00135         vglColor4fv(Context, Red, 0.4); 
00136 
00137         glEnable(GL_DEPTH_TEST);
00138 
00139 RefPtr<MyState> state = myState(Context);
00140 
00141 RefPtr<Program> MyProgram;
00142         MyProgram = new Program();
00143 
00144 RefPtr<VertexShader> VS = new VertexShader();
00145         VS->compile( elevation_vertexshader_src);
00146         MyProgram->attach(*VS);
00147 
00148 RefPtr<FragmentShader> FS = new FragmentShader();
00149         FS->compile( fragmentshader_src );
00150         MyProgram->attach(*FS);
00151 
00152         MyProgram->link();
00153 
00154         if (!MyProgram->isValid() )
00155         {
00156                 printf("VertexView: Shader: %s\n", MyProgram->InfoLog().c_str() ); 
00157                 throw "Vertex Shader Compilation Error";
00158         }
00159         else
00160         {
00161                 MyProgram->use();
00162                 MyProgram->setUniformValuef( "scaleFactor", scalefactor);
00163         }
00164 
00165         // 
00166         // Define a parameter space for which VBO's need to be stored. 
00167         // For each value of the parameters in this value set, there will 
00168         // be one VBO, until we run out of memory. 
00169         // In this example, the parameter space is empty.
00170         //
00171 RefPtr<ValueSet> RenderParameterSpace = new ValueSet(); 
00172 
00173         //
00174         // Retrieve a Vertex Buffer Object relative to the Context
00175         // and call it if exists.
00176         // 
00177 RefPtr<VBO> myVBO; 
00178         try
00179         {
00180                 myVBO = Context(*state)(this)( RenderParameterSpace )( VERTEXBUFFER() );
00181         } 
00182         catch(...){}
00183         if (myVBO && !myVBO->empty() && state->complexity == complexity)
00184         {
00185                 if (myVBO->call() )
00186                         return; 
00187         }
00188 
00189         // 
00190         // We don't have a valid VBO, so need to create one. 
00191         //
00192         myVBO = Context[*state][this][ RenderParameterSpace ]( VERTEXBUFFER() ); 
00193         // 
00194         // In case we had one, but need to re-create it, clear the one found. 
00195         //
00196         myVBO->clear(); 
00197 
00198         // 
00199         // Store the complexity value in the state object for further 
00200         // comparision. 
00201         //
00202         state->complexity = complexity; 
00203 
00204         //
00205         // Create a vertex array and a normal array
00206         //
00207         RefPtr<VertexArray> Points = new TypedVertexArray<point>(); 
00208         RefPtr<NormalArray> Normals = new TypedNormalArray<bivector>(); 
00209 
00210 
00211         RefPtr<VertexAttribArray> Attribs = new TypedVertexAttribArray<float>( MyProgram->getAttribID( SHADER_ELEVATION ) );
00212 
00213         //
00214         // Compute the geometry and store them in the vertex and normal arrays. 
00215         //
00216         resetBBox(Context);
00217         {
00218         std::vector<point>      PointData;
00219         std::vector<bivector>   NormalData;
00220         std::vector<float>      AttribData;
00221                 PointData.resize(2*N);
00222                 NormalData.resize(2*N); 
00223                 AttribData.resize(2*N);
00224 
00225                 // 
00226                 // The actual compution. Note that it is completely 
00227                 // independent from OpenGL and could be done elsewhere, 
00228                 // for instance in the object's update() function or 
00229                 // within a thread. However, we need to take care to 
00230                 // employ the caching system right, since this computation 
00231                 // does not need to be performed if a valid VBO object 
00232                 // already exists. The existence of a VBO object however 
00233                 // requires an OpenGL context.
00234                 //
00235                 for (int i=0;i<N;i++) 
00236                 {
00237                 double  phi0 = i*dphi,
00238                         phi1 = (i+5/complexity)*dphi;
00239 
00240                 point   A, B; 
00241                         A = r*cos(phi0), r*sin(phi0), phi0*zs; 
00242                         B = r*cos(phi0), r*sin(phi0), phi1*zs; 
00243 
00244                 bivector N;
00245                         N = cos(phi0), sin(phi0), 0; 
00246 
00247                         embrace( Context, A );
00248                         embrace( Context, B ); 
00249 
00250                         PointData[2*i  ] = A;
00251                         PointData[2*i+1] = B; 
00252 
00253                         NormalData[2*i  ] = N;
00254                         NormalData[2*i+1] = N; 
00255 
00256                         AttribData[2*i  ] =
00257                         AttribData[2*i+1] = sin(10*phi0);
00258                 } 
00259 
00260                 // 
00261                 // Now load the data from RAM to the GPU.
00262                 //
00263                 Points ->load( PointData  );
00264                 Normals->load( NormalData ); 
00265                 Attribs->load( AttribData );
00266 
00267         }
00268         closeBBox(Context); 
00269 
00270         // 
00271         // Tell the VBO ot use these arrays 
00272         //
00273         myVBO->append(Points);
00274         myVBO->append(Normals); 
00275         myVBO->append(Attribs);
00276 
00277         /*
00278           Define a Renderer object, as it will be used in the VBO.
00279           Here, the standard renderer will do, otherwise we could
00280           well derive from the DrawArrays class.
00281          */ 
00282         myVBO->setRenderer( new DrawArrays(GL::QUAD_STRIP, 2*N) ); 
00283         myVBO->call();
00284 }
00285 
00286 static Ref<VCreator<MyRenderObject> > MyCreator("Tutorial/VertexShaderObject", 0);
00287 
00288 /*
00289  This line needs to be contained in ONE source file of each
00290  VISH plugin module. It's not important which one.
00291  */
00292 VISH_DEFAULT_INIT
00293 
00294 

Generated on Thu Apr 2 18:58:49 2009 for VISHTutorial by  doxygen 1.4.7