This year I've ported all of my code to the newer 3.x / 4.x OpenGL pipeline which as deprecated a number of gl commands ( a full list are here) but the core to most of the initial work is in the follow section from Appendix E or the document
Begin / End primitive specification - Begin, End, and EdgeFlag* (sec- tion 2.6.1); Color*, FogCoord*, Index*, Normal3*, SecondaryColor3*, TexCoord*, Vertex* (section 2.7); and all associated state in tables 6.4 and 6.5. Vertex arrays and array drawing commands must be used to draw primitives.
and
(section 2.8); Frustum, LoadIdentity, LoadMatrix, LoadTransposeMatrix, MatrixMode, Mult- Matrix, MultTransposeMatrix, Ortho, PopMatrix, PushMatrix, Ro- tate, Scale, and Translate
What this basically means is the immediate mode OpenGL is no longer core to OpenGL 3/4 and we must use the GPU as much as possible. Most of this work involves the OpenGL matrix stack and the use of immediate mode, which is slow and inefficient and not available in OpenGL ES (used for mobile devices such as iPhone).
NGL already supports the use of GLSL shaders and with the ngl::Transform and ngl::TransformStack classes we can do all of the glRotate, glTranslate, glScale functions as well as the glPush/PopMatrix commands.
There are also methods built into the Transform / TransformStack to load these matrix values to a shader to use in GLSL.
For example in fixed functionality OpenGL each call to glVertex will pass through the following processes
This is easy to implement as the ngl::Camera class will calculate these values based on our Virtual Camera configuration of Eye, Look and Up (for the View matrix) and Current Transform Stack for the Model element of the ModelView matrix combination.
The projection is also calculated in the camera class and loaded to the shader. The following Vertex shader shows the calculaition of the current Vertex based on these values as well as the fragment normal.
uniform mat4 projectionMatrix; uniform mat4 ViewMatrix; uniform mat4 ModelMatrix; varying vec3 fragmentNormal; varying mat4 transform; void main(void) { fragmentNormal = (ViewMatrix*ModelMatrix*vec4(gl_Normal, 0.0)).xyz; transform=projectionMatrix*ViewMatrix*ModelMatrix; gl_Position = transform*gl_Vertex; }
In the above example the uniform mat4 variables are passed to the shader from our program and represent the current state of the MODELVIEW and PROJECTION matrices at the time of the vertex processing. For example usually we would set the projection of the camera and the view from the camera once a frame (or if fixed at the start of the program), then the modelling transformations of the current set of vertices will be set to position our objects as show in the following configuration code.
ngl::Vector From(0,0,8); ngl::Vector To(0,0,0); ngl::Vector Up(0,1,0); m_cam= new ngl::Camera(From,To,Up,ngl::PERSPECTIVE); // set the shape using FOV 45 Aspect Ratio based on Width and Height // The final two are near and far clipping planes of 0.5 and 10 m_cam->setShape(45,(float)720.0/576.0,0.5,10,ngl::PERSPECTIVE); // now to load the shader and set the values // grab an instance of shader manager ngl::ShaderManager *shader=ngl::ShaderManager::instance(); // load a frag and vert shaders shader->loadShader("Blinn","shaders/Vertex.vs","shaders/Fragment.fs"); // set this as the active shader shader->useShader("Blinn"); // now pass the modelView and projection values to the shader shader->setShaderParamFromMatrix("Blinn","ViewMatrix",m_cam->getModelView()); shader->setShaderParamFromMatrix("Blinn","projectionMatrix",m_cam->getProjection());
This will basically set up a static view similar to the standard gluLookAt function, any modelling transformation such as Push/Pop matrix and glRotate / glTranslate / glScale are loaded to the Model part of the matrix when drawing as show in the following code segment
ngl::Transformation trans; trans.setRotation(m_spinXFace,m_spinYFace,0); // set this in the TX stack m_transformStack.setGlobal(trans); // now set this value in the shader for the current ModelMatrix shader->setShaderParamFromMatrix("Blinn","ModelMatrix",m_transformStack.getCurrAndGlobal().getTransposeMatrix()); // get the VBO instance and draw the built in teapot ngl::VBOPrimitives *prim=ngl::VBOPrimitives::instance(); m_transformStack.pushTransform(); { shader->setShaderParamFromMatrix("Blinn","ModelMatrix",m_transformStack.getCurrAndGlobal().getTransposeMatrix()); prim->draw("teapot"); } // and before a pop m_transformStack.popTransform();
So far so good, we can view, transform and project our models using OpenGL 3/4.x and this system is on the GPU (thanks to the ngl::VBOPrimitives class which wraps our data onto the GPU and mimics a lot of the glut primitives which are all immediate mode gl)
Next we need to look at lighting and material properties and how to shade everything. This is where it get complicated, and will be in the next post.
No comments:
Post a Comment