=== added directory 'data'
=== added directory 'data/models'
=== added file 'data/models/cat.3ds'
Binary files data/models/cat.3ds 1970-01-01 00:00:00 +0000 and data/models/cat.3ds 2010-07-07 10:32:18 +0000 differ
=== added file 'data/models/cube.3ds'
Binary files data/models/cube.3ds 1970-01-01 00:00:00 +0000 and data/models/cube.3ds 2010-07-07 10:32:18 +0000 differ
=== added file 'data/models/horse.3ds'
Binary files data/models/horse.3ds 1970-01-01 00:00:00 +0000 and data/models/horse.3ds 2010-07-07 10:32:18 +0000 differ
=== added directory 'data/shaders'
=== added file 'data/shaders/light-advanced.frag'
@@ -0,0 +1,94 @@
+// Make sure you remember to add the varying variables:
+// varying vec3 Normal;
+// varying vec3 Light;
+// varying vec3 HalfVector;
+// To the fragment shader so that we can read them in.
+
+// First off here, we have to make sure that our Normal
+// has been normalized so to make sure, we are just going
+// to normalize it with the line:
+// Normal = normalize(Normal);
+
+// Next off we want to calculate our diffuse portion of
+// the lighting. Now unlike the basic lighting tutorial,
+// I am going to take into account the materials we have
+// attached to the object, and the settings we have applied
+// to our light.
+
+// Now for our diffuse portion of our equation we get the line:
+// float Diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * max(dot(Normal, Light),0.0);
+// Now the variable gl_FrontMaterial.diffuse is the diffuse
+// material we have assigned to the front face of our object,
+// and to get the diffuse portion of our light, we call the
+// variable gl_LightSource[0].diffuse. Then to take into account
+// how intense this should be, we multiply it by:
+// max(dot(Normal, Light),0.0)
+// Which from our previous tutorial, we used to calculate how
+// intense the light should be, using the angle of the surface
+// compared to the position of the light.
+
+// Seeing as though we now have the diffuse part of our lighting
+// we now need the Ambient term. In this term there are no real
+// calculations like the dot product, used in the diffuse term.
+// Here we are just taking values set inside our OpenGL program
+// and applying them to our object. The variables that we need
+// to use are:
+// gl_FrontMaterial.ambient
+// gl_LightSource[0].ambient
+// gl_LightModel.ambient
+// For our Ambient term to work, we need to multiply
+// gl_FrontMaterial.ambient and gl_LightSource[0].ambient
+// and then add the product of gl_LightModel.ambient and
+// gl_FrontMaterial.ambient
+// So our equation looks like:
+// float Ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
+// Ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
+
+// In this tutorial, I am not going to cover the emissive term
+// that OpenGL supports (I will in a later tutorial), so I am
+// going to jump straight to the most complicated term in the
+// lighting equation. Which is the specular term. The reason
+// that this term is the most complicated, is that it needs
+// to find the reflection of the lighting from the surface of
+// the object, to the 'camera'. The first part of the equation
+// is similar to the start of the previous equations and takes
+// the materials specular term, and the lights specular term
+// and multiplies them together to look like:
+// gl_FrontMaterial.specular * gl_LightSource[0].specular
+// and then comes the tricky part, we need to multiply this by
+// pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+// This takes the dot product of our Normal and HalfVector, and as
+// we have seen in the diffuse term, sets a max of 0.0
+// With the number we have just calculated, we need to raise that
+// to the power of our shininess term set inside our OpenGL program.
+
+// Because we are using the halfVector at this stage, we don't need
+// to use the reflect() expression, but we will when we get into
+// normal mapping.
+
+// So in the end our specular expression looks like:
+// float Specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+
+// Now for the combining of all the expressions. We still need to
+// multiply the diffuse term by the objects color. And with that
+// we then need to add the Ambient term and the Specular term.
+// So our final gl_FragColor call looks like:
+// gl_FragColor = Ambient + (Diffuse * vec4(1,0,0,1)) + Specular;
+
+varying vec3 Normal;
+varying vec3 Light;
+varying vec3 HalfVector;
+
+void main(void)
+{
+ Normal = normalize(Normal);
+
+ float Diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse * max(dot(Normal, Light),0.0);
+
+ float Ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
+ Ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
+
+ float Specular = gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(max(dot(Normal,HalfVector),0.0), gl_FrontMaterial.shininess);
+
+ gl_FragColor = Ambient + (Diffuse * vec4(1,0,0,1)) + Specular;
+}
=== added file 'data/shaders/light-advanced.vert'
@@ -0,0 +1,51 @@
+// First off, I am going to explain a little thing
+// with shaders, that will help you to optimize them
+// in the future. Vertex shaders are called for every
+// vertex passed through, and Fragment shaders are
+// called for every pixel on the screen. Because of this
+// it is wise to do as many calculations in the vertex
+// shader as possible, as they are called less, and if
+// the calculation does not need to be called on a per
+// pixel basis, why do it?
+
+// Now as for the tutorial, you will see that I have
+// removed the variable Diffuse from our vertex shader.
+// This is because we are now going to calculate that in
+// the fragment shader so we can get per pixel lighting.
+
+// In our vertex shader, I have added the varying variables:
+// varying vec3 Normal;
+// varying vec3 Light;
+// varying vec3 HalfVector;
+// These hold the surface normal of our vertex, the direction
+// vector of the light source, and the half vector of the
+// light source (you may want to look into the maths behind
+// lighting, I may add something in the maths section at a
+// later date).
+
+// These variables are going to be calculated here, and passed
+// through to our fragment shader. This is because these variables
+// will not change, so there is no need calculating them on a
+// per pixel basis.
+
+// Now that we have these variables, we need to calculate them.
+// Our Normal and Light variables stay exactly the same
+// as in the previous tutorial. The only new one is the HalfVector
+// which is called similar to our Light variable, just replace
+// position with halfVector, and we get the light sources half
+// vector supplied by OpenGL.
+
+varying vec3 Normal;
+varying vec3 Light;
+varying vec3 HalfVector;
+
+void main(void)
+{
+ Normal = normalize(gl_NormalMatrix * gl_Normal);
+
+ Light = normalize(gl_LightSource[0].position.xyz);
+
+ HalfVector = normalize(gl_LightSource[0].halfVector.xyz);
+
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
\ No newline at end of file
=== added file 'data/shaders/light-basic.frag'
@@ -0,0 +1,24 @@
+// Because we are using the varying float Diffuse in
+// our vertex shader, if we wish to read it in here, we
+// need to set the same variable, so I have done this
+// first.
+
+// After that, I am simply changing the line:
+// gl_FragColor = vec4(0,0,1,1)
+// to
+// gl_FragColor = Diffuse * vec4(0,0,1,1);
+// This multiplies the intensity of the light by the
+// color we originally set the cube to.
+
+// This can or cannot eliminate the need for materials,
+// depending on your needs, but just for the record
+// (and future tutorials), materials are worth while
+// and can be read from inside GLSL :)
+
+varying float Diffuse;
+
+void main(void)
+{
+//Multiply the light Diffuse intensity by the color of the cube
+ gl_FragColor = Diffuse * vec4(0,0,1,1);
+}
=== added file 'data/shaders/light-basic.vert'
@@ -0,0 +1,72 @@
+// For this tutorial, I am going show you how to perform per
+// vertex lighting using shaders. Yes, shaders support per pixel
+// but this is just a starting point.
+
+// First I am going to teach you about varying variables. These
+// are variables that can be shared between the vertex and fragment
+// shaders. These variables are set inside the vertex shader, and
+// then read from the fragment shader. In this case we are going
+// to share a float type variable from the Vertex shader to the
+// Fragment shader. This variable is going to be called Diffuse
+// and will hold a number that will tell us how lit our vertex
+// should be.
+
+// Because we are using per vertex lighting, the GLSL shader will
+// automatically interpolate the color between the vertices. Just
+// like OpenGL does.
+
+// Now first off we need to know the surface normal of the current
+// vertex. Because I am using a GLUT cube, these are already
+// calculated and sent off with the glNormal command. Any numbers
+// sent from OpenGL through glNormal(1,2,3); can be read with
+// the variable gl_Normal. In later tutorials, I will be using
+// self calculated normals, using my own normal generation code.
+
+// Now as for our normal, I am storing it in the variable vec3 Normal.
+// But first, I have to multiply the surface normal (gl_Normal) by
+// the gl_NormalMatrix. This places the normal in coordinates that
+// we can use. (Later on I will show you how to use tangent space
+// normals). We also then have to normalize this multiplication so
+// that all of the normal vectors are between (and including) -1 and 1.
+// This makes sure that we have no scaling errors.
+
+// Next on, we are going to work with our light. I am storing this
+// in a variable called vec3 Light. In this, I am calling for the
+// position of glLight0. This is gathered by the call:
+// gl_LightSource[0].position.xyz
+// This gives us the position of glLight0, and to get the position of
+// any other light, we just change the number 0 to the light number we
+// are after. We do not need to multiply this expression by the
+// gl_NormalMatrix, but we do have to normalize it still.
+
+// Now that we have our surface Normal and the position of our Light.
+// We can now calculate the Diffuse value of our lighting at the
+// given vertex. To do this we need to take the dot product of both
+// the Normal and the Light together. If you have any idea on
+// calculating Normals, then you should have a fair idea of what the
+// dot product does. It works as such:
+// dot(a,b) = (x1 * x2) + (y1 * y2) + (z1 * z3)
+// If this happens to be equal to 0, then the vectors a and b are
+// perpendicular (the light meets the surface at a 90 degree angle).
+// Because this point is when the light is at its brightest, we need
+// to set the maximum value for our diffuse value to 0.0.
+// So our Diffuse equation becomes:
+// Diffuse = max(dot(Normal, Light),0.0);
+
+// And from that, we have now calculated the intensity of the light
+// at the given vertex. That started to turn into a bit of a maths
+// lesson, but it even cleared up some stuff for me without even
+// thinking about it. GO MATHS :)
+
+varying float Diffuse;
+
+void main(void)
+{
+ Normal = normalize(gl_NormalMatrix * gl_Normal);
+
+ Light = normalize(gl_LightSource[0].position.xyz);
+
+ Diffuse = max(dot(Normal, Light),0.0);
+
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
\ No newline at end of file
=== added directory 'data/textures'
=== added file 'data/textures/crate-base.bmp'
Binary files data/textures/crate-base.bmp 1970-01-01 00:00:00 +0000 and data/textures/crate-base.bmp 2010-07-07 10:32:18 +0000 differ
=== added file 'main.cpp'
@@ -0,0 +1,106 @@
+#include "oglsdl.h"
+
+#include "screen.h"
+#include "scene.h"
+
+int main(int argc, char *argv[])
+{
+ SDL_Event event;
+ int running = 1;
+ unsigned current_scene = 0;
+ Screen screen;
+
+ SceneBuild scenebuild;
+ SceneTexture scenetexture;
+ SceneShading sceneshading;
+
+ printf("===================================================\n");
+ printf(" GLMark 08\n");
+ printf("===================================================\n");
+
+ printf("Enter screen width: ");
+ scanf("%d", &screen.mWidth);
+ printf("Enter screen height: ");
+ scanf("%d", &screen.mHeight);
+ printf("Enter screen bpp: ");
+ scanf("%d", &screen.mBpp);
+ printf("Enter '1' for fullscreen '0' for windowed: ");
+ scanf("%d", &screen.mFullScreen);
+
+
+ printf("===================================================\n");
+ if(!screen.init())
+ return 0;
+ printf("===================================================\n");
+
+ if(!scenebuild.load() || !scenetexture.load() || !sceneshading.load())
+ return 0;
+
+ while(running)
+ {
+ while(SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_QUIT:
+ running = 0;
+ break;
+ case SDL_KEYDOWN:
+ if(event.key.keysym.sym == SDLK_ESCAPE)
+ running = 0;
+ break;
+ }
+ }
+
+ screen.clear();
+
+ switch(current_scene)
+ {
+ case 0:
+ current_scene++;
+ scenebuild.start();
+// scenebuild.mRunning = false;
+ break;
+ case 1:
+ scenebuild.update();
+ scenebuild.draw();
+ if(!scenebuild.mRunning)
+ {
+ current_scene++;
+ scenetexture.start();
+// scenetexture.mRunning = false;
+ }
+ break;
+ case 2:
+ scenetexture.update();
+ scenetexture.draw();
+ if(!scenetexture.mRunning)
+ {
+ current_scene++;
+ sceneshading.start();
+// sceneshading.mRunning = false;
+ }
+ break;
+ case 3:
+ sceneshading.update();
+ sceneshading.draw();
+ if(!sceneshading.mRunning)
+ running = false;
+ break;
+ }
+
+ screen.update();
+ }
+
+ scenebuild.calculate_score();
+ scenetexture.calculate_score();
+ sceneshading.calculate_score();
+
+ unsigned score = scenebuild.mScore + scenetexture.mScore + sceneshading.mScore;
+
+ printf("===================================================\n");
+ printf("Your GLMark08 Score is %u ^_^\n", score);
+ printf("===================================================\n");
+
+ return 0;
+}
=== added file 'makefile'
@@ -0,0 +1,2 @@
+all:
+ g++ *.cpp -o glmark -Wall -lSDL -lGL -lGLU -lGLEW
=== added file 'mesh.cpp'
@@ -0,0 +1,240 @@
+#include "mesh.h"
+
+Texel::Texel()
+{
+ u = 0; v = 0;
+}
+
+Texel::Texel(GLfloat pU, GLfloat pV)
+{
+ u = pU; v = pV;
+}
+
+Mesh::Mesh()
+{
+ mPolygonQty = 0;
+ mVertexQty = 0;
+ mMode = GL_QUADS;
+ mVertex = 0;
+}
+
+Mesh::~Mesh()
+{
+ delete [] mVertex;
+ glDeleteLists(1, mBuildList);
+ //deleteArray
+}
+
+void Mesh::make_cube()
+{
+ mPolygonQty = 6;
+ mVertexQty = 4 * mPolygonQty;
+ mMode = GL_QUADS;
+ mVertex = new Vertex[mVertexQty];
+
+ mVertex[0].v = Vector3f( 1.0f, 1.0f,-1.0f);
+ mVertex[1].v = Vector3f(-1.0f, 1.0f,-1.0f);
+ mVertex[2].v = Vector3f(-1.0f, 1.0f, 1.0f);
+ mVertex[3].v = Vector3f( 1.0f, 1.0f, 1.0f);
+
+ mVertex[4].v = Vector3f( 1.0f,-1.0f, 1.0f);
+ mVertex[5].v = Vector3f(-1.0f,-1.0f, 1.0f);
+ mVertex[6].v = Vector3f(-1.0f,-1.0f,-1.0f);
+ mVertex[7].v = Vector3f( 1.0f,-1.0f,-1.0f);
+
+ mVertex[8].v = Vector3f( 1.0f, 1.0f, 1.0f);
+ mVertex[9].v = Vector3f(-1.0f, 1.0f, 1.0f);
+ mVertex[10].v = Vector3f(-1.0f,-1.0f, 1.0f);
+ mVertex[11].v = Vector3f( 1.0f,-1.0f, 1.0f);
+
+ mVertex[12].v = Vector3f( 1.0f,-1.0f,-1.0f);
+ mVertex[13].v = Vector3f(-1.0f,-1.0f,-1.0f);
+ mVertex[14].v = Vector3f(-1.0f, 1.0f,-1.0f);
+ mVertex[15].v = Vector3f( 1.0f, 1.0f,-1.0f);
+
+ mVertex[16].v = Vector3f(-1.0f, 1.0f, 1.0f);
+ mVertex[17].v = Vector3f(-1.0f, 1.0f,-1.0f);
+ mVertex[18].v = Vector3f(-1.0f,-1.0f,-1.0f);
+ mVertex[19].v = Vector3f(-1.0f,-1.0f, 1.0f);
+
+ mVertex[20].v = Vector3f(-1.0f, 1.0f, 1.0f);
+ mVertex[21].v = Vector3f(-1.0f, 1.0f,-1.0f);
+ mVertex[22].v = Vector3f(-1.0f,-1.0f,-1.0f);
+ mVertex[23].v = Vector3f(-1.0f,-1.0f, 1.0f);
+
+ for(unsigned i = 0; i < mVertexQty / 4; i += 4)
+ {
+ Vector3f n;
+ n = normal(mVertex[i].v, mVertex[i + 1].v, mVertex[i + 2].v);
+ for(unsigned j = 0; j < 4; j++)
+ mVertex[i + j].n = n;
+ mVertex[i + 0].t = Texel(0.0f, 0.0f);
+ mVertex[i + 1].t = Texel(1.0f, 0.0f);
+ mVertex[i + 2].t = Texel(1.0f, 1.0f);
+ mVertex[i + 3].t = Texel(0.0f, 1.0f);
+ }
+}
+
+void Mesh::make_torus()
+{
+ unsigned wraps_qty = 64;
+ unsigned per_wrap_qty = 64;
+ float major_radius = 0.8;
+ float minor_radius = 0.4;
+ unsigned i, j;
+ unsigned k = 0;
+
+ Vector3f a, b, c, d, n;
+
+ mMode = GL_TRIANGLES;
+ mVertexQty = wraps_qty * per_wrap_qty * 6;
+ mVertex = new Vertex[mVertexQty];
+
+ for(i = 0; i < wraps_qty; i++)
+ for(j = 0; j < per_wrap_qty; j++)
+ {
+ float wrap_frac = j / (float)per_wrap_qty;
+ float phi = 2 * M_PI * wrap_frac;
+ float theta = 2 * M_PI * (i + wrap_frac) / (float)wraps_qty;
+ float r = major_radius + minor_radius * (float)cos(phi);
+ a.x = (float)sin(theta) * r;
+ a.y = minor_radius * (float)sin(phi);
+ a.z = (float)cos(theta) * r;
+
+ theta = 2 * M_PI * (i + wrap_frac + 1) / (float)wraps_qty;
+ b.x = (float)sin(theta) * r;
+ b.y = minor_radius * (float)sin(phi);
+ b.z = (float)cos(theta) * r;
+
+ wrap_frac = (j + 1) / (float)per_wrap_qty;
+ phi = 2 * M_PI * wrap_frac;
+ theta = 2 * M_PI * (i + wrap_frac) / (float)wraps_qty;
+ r = major_radius + minor_radius * (float)cos(phi);
+ c.x = (float)sin(theta) * r;
+ c.y = minor_radius * (float)sin(phi);
+ c.z = (float)cos(theta) * r;
+
+ theta = 2 * M_PI * (i + wrap_frac + 1) / (float)wraps_qty;
+ d.x = (float)sin(theta) * r;
+ d.y = minor_radius * (float)sin(phi);
+ d.z = (float)cos(theta) * r;
+
+ n = normal(a, b, c);
+ mVertex[k].n = n; mVertex[k].v = a; k++;
+ mVertex[k].n = n; mVertex[k].v = b; k++;
+ mVertex[k].n = n; mVertex[k].v = c; k++;
+ n = normal(a, b, c);
+ mVertex[k].n = n; mVertex[k].v = b; k++;
+ mVertex[k].n = n; mVertex[k].v = c; k++;
+ mVertex[k].n = n; mVertex[k].v = d; k++;
+ }
+}
+
+void Mesh::render()
+{
+ glBegin(mMode);
+ glColor3f(1.0f, 0.0f, 0.0f);
+ for(unsigned i = 0; i < mVertexQty; i++)
+ {
+ glNormal3f(mVertex[i].n.x, mVertex[i].n.y, mVertex[i].n.z);
+ glTexCoord2f(mVertex[i].t.u, mVertex[i].t.v);
+ glVertex3f(mVertex[i].v.x, mVertex[i].v.y, mVertex[i].v.z);
+ }
+ glEnd();
+}
+
+void Mesh::render_array()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &mVertex[0].v.x);
+ glNormalPointer(GL_FLOAT, sizeof(Vertex), &mVertex[0].n.x);
+ glDrawArrays(mMode, 0, mVertexQty);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+}
+
+void Mesh::build_list()
+{
+#ifdef _DEBUG
+ printf("Building list for mesh... ");
+#endif
+
+ mBuildList = glGenLists(1);
+ glNewList(mBuildList, GL_COMPILE);
+ render();
+ glEndList();
+
+#ifdef _DEBUG
+ printf("[ Done ]\n");
+#endif
+}
+
+void Mesh::build_vbo()
+{
+#ifdef _DEBUG
+ printf("Building vbo for mesh... ");
+#endif
+
+ Vector3f *vertex;
+ Texel *texel;
+ Vector3f *normal;
+
+ vertex = new Vector3f[mVertexQty];
+ texel = new Texel[mVertexQty];
+ normal = new Vector3f[mVertexQty];
+
+ for(unsigned i = 0; i < mVertexQty; i++)
+ {
+ vertex[i] = mVertex[i].v;
+ texel[i] = mVertex[i].t;
+ normal[i] = mVertex[i].n;
+ }
+
+ // Generate And Bind The Vertex Buffer
+ glGenBuffersARB(1, &mVBOVertices); // Get A Valid Name
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOVertices); // Bind The Buffer
+ // Load The Data
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Vector3f), vertex, GL_STATIC_DRAW_ARB);
+
+ // Generate And Bind The normal Buffer
+ glGenBuffersARB(1, &mVBONormals); // Get A Valid Name
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBONormals); // Bind The Buffer
+ // Load The Data
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Vector3f), normal, GL_STATIC_DRAW_ARB);
+
+ // Generate And Bind The Texture Coordinate Buffer
+ glGenBuffersARB(1, &mVBOTexCoords); // Get A Valid Name
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOTexCoords); // Bind The Buffer
+ // Load The Data
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, mVertexQty * sizeof(Texel), texel, GL_STATIC_DRAW_ARB);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ delete [] vertex;
+ delete [] texel;
+ delete [] normal;
+#ifdef _DEBUG
+ printf("[ Done ]\n");
+#endif
+}
+
+void Mesh::render_vbo()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBONormals);
+ glNormalPointer(GL_FLOAT, 0, 0);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVBOVertices);
+ glVertexPointer(3, GL_FLOAT, 0, 0);
+
+ glDrawArrays(GL_TRIANGLES, 0, mVertexQty);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
=== added file 'mesh.h'
@@ -0,0 +1,55 @@
+#ifndef _MESH_H
+#define _MESH_H
+
+#include "screen.h"
+#include "vector.h"
+
+#include <stdio.h>
+#include <math.h>
+
+class Texel
+{
+public:
+ GLfloat u, v;
+
+ Texel();
+ Texel(GLfloat pU, GLfloat pV);
+};
+
+class Vertex
+{
+public:
+ Vector3f v;
+ Vector3f n;
+ Texel t;
+};
+
+// Data for a mesh to be rendered by vertex arrays' or vbos' has 3 verticies per
+// polygon and no polygonal data
+class Mesh
+{
+public:
+ unsigned mVertexQty; // Quantity of Verticies
+ unsigned mPolygonQty; // Quantity of polygons, not really needed
+ GLenum mMode; // Polygon mode, eg GL_QUADS, GL_TRIANGLES etc...
+ Vertex *mVertex; // Storage for the verticies
+
+ GLuint mBuildList; // Build list name
+
+ GLuint mVBOVertices; // Vertex VBO name
+ GLuint mVBONormals; // Texture coordinate VBO name
+ GLuint mVBOTexCoords; // Texture coordinate VBO name
+
+ Mesh(); // Default Constructor, should set pointers to null
+ ~Mesh();
+
+ void make_cube();
+ void make_torus();
+ void render();
+ void render_array();
+ void build_list();
+ void build_vbo();
+ void render_vbo();
+};
+
+#endif
=== added file 'model.cpp'
@@ -0,0 +1,254 @@
+#include "model.h"
+
+long filelength(int f)
+{
+ struct stat buf;
+ fstat(f, &buf);
+ return(buf.st_size);
+}
+
+Model::Model()
+{
+ mPolygonQty = 0;
+ mVertexQty = 0;
+ mVertex = 0; // Set pointer to null
+ mPolygon = 0; // Set pointer to null
+}
+
+Model::~Model()
+{
+ delete [] mVertex;
+ delete [] mPolygon;
+}
+
+void Model::convert_to_mesh(Mesh *pMesh)
+{
+#ifdef _DEBUG
+ printf("Converting model to mesh... ");
+#endif
+ pMesh->mVertexQty = 3 * mPolygonQty;
+ pMesh->mPolygonQty = mPolygonQty;
+ pMesh->mMode = GL_TRIANGLES;
+
+ pMesh->mVertex = new Vertex[pMesh->mVertexQty];
+
+ for(unsigned i = 0; i < pMesh->mVertexQty; i += 3)
+ {
+ pMesh->mVertex[i + 0].v = mVertex[mPolygon[i / 3].mA].v;
+ pMesh->mVertex[i + 1].v = mVertex[mPolygon[i / 3].mB].v;
+ pMesh->mVertex[i + 2].v = mVertex[mPolygon[i / 3].mC].v;
+
+ pMesh->mVertex[i + 0].n = mVertex[mPolygon[i / 3].mA].n;
+ pMesh->mVertex[i + 1].n = mVertex[mPolygon[i / 3].mB].n;
+ pMesh->mVertex[i + 2].n = mVertex[mPolygon[i / 3].mC].n;
+
+ pMesh->mVertex[i + 0].t = mVertex[mPolygon[i / 3].mA].t;
+ pMesh->mVertex[i + 1].t = mVertex[mPolygon[i / 3].mB].t;
+ pMesh->mVertex[i + 2].t = mVertex[mPolygon[i / 3].mC].t;
+ }
+
+#ifdef _DEBUG
+ printf("[ Done ]\n");
+#endif
+}
+
+void Model::calculate_normals()
+{
+#ifdef _DEBUG
+ printf("Calculating normals for model... ");
+#endif
+ Vector3f n;
+
+ for(unsigned i = 0; i < mPolygonQty; i++)
+ {
+ n = normal(mVertex[mPolygon[i].mA].v, mVertex[mPolygon[i].mB].v, mVertex[mPolygon[i].mC].v);
+ mVertex[mPolygon[i].mA].n += n;
+ mVertex[mPolygon[i].mB].n += n;
+ mVertex[mPolygon[i].mC].n += n;
+ }
+
+ for(unsigned i = 0; i < mVertexQty; i++)
+ mVertex[i].n.normalize();
+
+#ifdef _DEBUG
+ printf("[ Done ]\n");
+#endif
+}
+
+void Model::center()
+{
+ Vector3f center;
+ Vector3f max = mVertex[0].v, min = mVertex[0].v;
+
+ for(unsigned i = 1; i < mVertexQty; i++)
+ {
+ if(mVertex[i].v.x > max.x) max.x = mVertex[i].v.x;
+ if(mVertex[i].v.y > max.y) max.y = mVertex[i].v.y;
+ if(mVertex[i].v.z > max.z) max.z = mVertex[i].v.z;
+
+ if(mVertex[i].v.x < min.x) min.x = mVertex[i].v.x;
+ if(mVertex[i].v.y < min.y) min.y = mVertex[i].v.y;
+ if(mVertex[i].v.z < min.z) min.z = mVertex[i].v.z;
+ }
+
+ center = (max + min) / 2.0f;
+
+ for(unsigned i = 0; i < mVertexQty; i++)
+ mVertex[i].v -= center;
+}
+
+void Model::scale(GLfloat pAmount)
+{
+ for(unsigned i = 1; i < mVertexQty; i++)
+ mVertex[i].v *= pAmount;
+}
+
+int Model::load_3ds(const char *pFileName)
+{
+#ifdef _DEBUG
+ printf("Loading model from 3ds file... ");
+#endif
+ int i; //Index variable
+
+ FILE *l_file; //File pointer
+
+ unsigned short l_chunk_id; //Chunk identifier
+ unsigned int l_chunk_lenght; //Chunk lenght
+
+ unsigned char l_char; //Char variable
+ unsigned short l_qty; //Number of elements in each chunk
+
+ if ((l_file=fopen (pFileName, "rb"))== NULL)
+ {
+#ifdef _DEBUG
+ printf("[ Fail ]\n");
+#else
+ printf("Could not open 3ds file\n");
+#endif
+ return 0;
+ }
+
+ while (ftell (l_file) < filelength (fileno (l_file))) //Loop to scan the whole file
+ //while(!EOF)
+ {
+ //getch(); //Insert this command for debug (to wait for keypress for each chuck reading)
+
+ fread (&l_chunk_id, 2, 1, l_file); //Read the chunk header
+ fread (&l_chunk_lenght, 4, 1, l_file); //Read the lenght of the chunk
+
+ switch (l_chunk_id)
+ {
+ //----------------- MAIN3DS -----------------
+ // Description: Main chunk, contains all the other chunks
+ // Chunk ID: 4d4d
+ // Chunk Lenght: 0 + sub chunks
+ //-------------------------------------------
+ case 0x4d4d:
+ break;
+
+ //----------------- EDIT3DS -----------------
+ // Description: 3D Editor chunk, objects layout info
+ // Chunk ID: 3d3d (hex)
+ // Chunk Lenght: 0 + sub chunks
+ //-------------------------------------------
+ case 0x3d3d:
+ break;
+
+ //--------------- EDIT_OBJECT ---------------
+ // Description: Object block, info for each object
+ // Chunk ID: 4000 (hex)
+ // Chunk Lenght: len(object name) + sub chunks
+ //-------------------------------------------
+ case 0x4000:
+ i=0;
+ do
+ {
+ fread (&l_char, 1, 1, l_file);
+ mName[i] = l_char;
+ i++;
+ } while(l_char != '\0' && i<20);
+ break;
+
+ //--------------- OBJ_TRIMESH ---------------
+ // Description: Triangular mesh, contains chunks for 3d mesh info
+ // Chunk ID: 4100 (hex)
+ // Chunk Lenght: 0 + sub chunks
+ //-------------------------------------------
+ case 0x4100:
+ break;
+
+ //--------------- TRI_VERTEXL ---------------
+ // Description: Vertices list
+ // Chunk ID: 4110 (hex)
+ // Chunk Lenght: 1 x unsigned short (number of vertices)
+ // + 3 x float (vertex coordinates) x (number of vertices)
+ // + sub chunks
+ //-------------------------------------------
+ case 0x4110:
+ fread (&l_qty, sizeof (unsigned short), 1, l_file);
+ mVertexQty = l_qty;
+ mVertex = new Vertex[mVertexQty];
+ for (i=0; i<l_qty; i++)
+ {
+ fread (&mVertex[i].v.x, sizeof(float), 1, l_file);
+ fread (&mVertex[i].v.y, sizeof(float), 1, l_file);
+ fread (&mVertex[i].v.z, sizeof(float), 1, l_file);
+ }
+ break;
+
+ //--------------- TRI_FACEL1 ----------------
+ // Description: Polygons (faces) list
+ // Chunk ID: 4120 (hex)
+ // Chunk Lenght: 1 x unsigned short (number of polygons)
+ // + 3 x unsigned short (polygon points) x (number of polygons)
+ // + sub chunks
+ //-------------------------------------------
+ case 0x4120:
+ fread (&l_qty, sizeof (unsigned short), 1, l_file);
+ mPolygonQty = l_qty;
+ mPolygon = new Polygon[mPolygonQty];
+ for (i=0; i<l_qty; i++)
+ {
+ fread (&mPolygon[i].mA, sizeof (unsigned short), 1, l_file);
+ fread (&mPolygon[i].mB, sizeof (unsigned short), 1, l_file);
+ fread (&mPolygon[i].mC, sizeof (unsigned short), 1, l_file);
+ fread (&mPolygon[i].mFaceFlags, sizeof (unsigned short), 1, l_file);
+ }
+ break;
+
+ //------------- TRI_MAPPINGCOORS ------------
+ // Description: Vertices list
+ // Chunk ID: 4140 (hex)
+ // Chunk Lenght: 1 x unsigned short (number of mapping points)
+ // + 2 x float (mapping coordinates) x (number of mapping points)
+ // + sub chunks
+ //-------------------------------------------
+ case 0x4140:
+ fread (&l_qty, sizeof (unsigned short), 1, l_file);
+ for (i=0; i<l_qty; i++)
+ {
+ fread (&mVertex[i].t.u, sizeof (float), 1, l_file);
+ fread (&mVertex[i].t.v, sizeof (float), 1, l_file);
+ }
+ break;
+
+ //----------- Skip unknow chunks ------------
+ //We need to skip all the chunks that currently we don't use
+ //We use the chunk lenght information to set the file pointer
+ //to the same level next chunk
+ //-------------------------------------------
+ default:
+ fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
+ }
+ }
+ fclose(l_file); // Closes the file stream
+
+#ifdef _DEBUG
+ printf("[ Success ]\n");
+ printf(" Model Information\n");
+ printf(" Name: %s\n", mName);
+ printf(" Vertex count: %d\n", mVertexQty);
+ printf(" Polygon count: %d\n", mPolygonQty);
+#endif
+ return 1;
+}
=== added file 'model.h'
@@ -0,0 +1,37 @@
+#ifndef _MODEL_H
+#define _MODEL_H
+
+#include "mesh.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+class Polygon
+{
+public:
+ unsigned short mA, mB, mC;
+ unsigned short mFaceFlags;
+};
+
+// A model as loaded from a 3ds file
+class Model
+{
+public:
+ unsigned mPolygonQty;
+ unsigned mVertexQty;
+ Vertex *mVertex;
+ Polygon *mPolygon;
+ char mName[20];
+
+ Model();
+ ~Model();
+
+ int load_3ds(const char *pFileName);
+ void calculate_normals();
+ void center();
+ void scale(GLfloat pAmount);
+ void convert_to_mesh(Mesh *pMesh);
+};
+
+#endif
=== added file 'oglsdl.h'
@@ -0,0 +1,7 @@
+#ifndef _OGLSDL_H
+#define _OGLSDL_H
+
+#include <SDL/SDL.h>
+#include <GL/glew.h>
+
+#endif
=== added file 'readme'
@@ -0,0 +1,11 @@
+requires development libarays
+ sdl libsdl1.2-dev
+ gl libgl1-mesa-dev
+ glu libglu1-mesa-dev
+ glew libglew1.5-dev
+
+compile with
+ make
+
+execute with
+ ./glmark
=== added file 'release'
@@ -0,0 +1,51 @@
+GLMark 0.5.2
+========================
+- current tests
+ no precompilation
+ build lists
+ vertex arrays
+ vertex buffer objects
+ nearest texture filtering
+ linear texture filtering
+ mipmapped texture filtering
+ smooth shader model
+ glsl per vertex lighting
+ glsl per pixel lighting
+
+Updates 26-04-2008
+========================
+- Added GLSL shader tests
+- Fixed some memory leaks
+- Cleaned up the code a bit
+
+Updates 25-04-2008
+========================
+- Readded the texture filter test
+- Improved score system
+
+Updates 24-04-2008
+========================
+- Completly rewritten source
+- Now c++
+- 3dsloader
+- vertex buffer objects
+- havent done texture tests yet
+- select any resolution, fullscreen or windowed
+
+Updates 20-04-2008
+========================
+- Selected color depth used instead of desktop depth
+- Simple makefile included
+- Torus model, which actually tests the different methods of precompilation
+
+Updates 19-04-2008
+========================
+- Tests now run for 30 seconds
+- The score is calculated properly, thanks to Shuffle777.
+- It is now possible to select resolution, color depth and fullscreen/windowed.
+
+Updates
+========================
+- Tests now run for 60 seconds
+- A score is calculated at the end of the benchmark, based on my computer
+(I get exactly 5000) :).
=== added file 'scene.cpp'
@@ -0,0 +1,21 @@
+#include "scene.h"
+
+Scene::Scene()
+{
+}
+
+Scene::~Scene()
+{
+ delete [] mPartDuration;
+ delete [] mAverageFPS;
+ delete [] mScoreScale;
+}
+
+void Scene::calculate_score()
+{
+ mScore = 0;
+ for(unsigned i = 0; i < mPartsQty; i++)
+ mScore += mAverageFPS[i] * mScoreScale[i];
+}
+
+
=== added file 'scene.h'
@@ -0,0 +1,84 @@
+#ifndef _SCENE_H
+#define _SCENE_H
+
+#include "oglsdl.h"
+
+#include "mesh.h"
+#include "model.h"
+#include "texture.h"
+#include "shader.h"
+
+#include <math.h>
+
+class Scene
+{
+public:
+ Scene();
+ ~Scene();
+
+ unsigned mPartsQty; // How many parts for the scene
+ unsigned mCurrentPart; // The current part being rendered
+ double *mPartDuration; // Duration per part in seconds
+
+ double mLastTime, mCurrentTime, mDt;
+ unsigned mCurrentFrame;
+ bool mRunning;
+
+ unsigned *mAverageFPS; // Average FPS per part
+ float *mScoreScale;
+ unsigned mScore; // Score
+
+ void calculate_score();
+
+protected:
+ double mStartTime;
+ double mElapsedTime;
+};
+
+class SceneBuild : public Scene
+{
+public:
+ int load();
+ void start();
+ void update();
+ void draw();
+
+ Mesh mMesh;
+ float mRotation;
+ float mRotationSpeed;
+};
+
+class SceneTexture : public Scene
+{
+public:
+ int load();
+ void start();
+ void update();
+ void draw();
+
+ ~SceneTexture();
+
+ Mesh mCubeMesh;
+ GLuint mTexture[3];
+ Vector3f mRotation;
+ Vector3f mRotationSpeed;
+};
+
+class SceneShading : public Scene
+{
+public:
+ int load();
+ void start();
+ void update();
+ void draw();
+
+ ~SceneShading();
+
+ Shader mShader[2];
+
+ Mesh mMesh;
+ float mRotation;
+ float mRotationSpeed;
+};
+
+#endif
=== added file 'scenebuild.cpp'
@@ -0,0 +1,120 @@
+#include "scene.h"
+
+int SceneBuild::load()
+{
+ Model model;
+
+ if(!model.load_3ds("data/models/horse.3ds"))
+ return 0;
+
+ model.calculate_normals();
+ model.convert_to_mesh(&mMesh);
+
+ mMesh.build_list();
+ mMesh.build_vbo();
+
+ mRotationSpeed = 36.0f;
+
+ mRunning = false;
+
+ mPartsQty = 4;
+ mPartDuration = new double[mPartsQty];
+ mAverageFPS = new unsigned[mPartsQty];
+ mScoreScale = new float[mPartsQty];
+
+ mScoreScale[0] = 1.898f;
+ mScoreScale[1] = 0.540f;
+ mScoreScale[2] = 0.488f;
+ mScoreScale[3] = 0.420f;
+
+ mScore = 0;
+
+ mPartDuration[0] = 10.0;
+ mPartDuration[1] = 10.0;
+ mPartDuration[2] = 10.0;
+ mPartDuration[3] = 10.0;
+
+ mCurrentPart = 0;
+
+ return 1;
+}
+
+void SceneBuild::start()
+{
+ GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
+ GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHTING);
+
+ mCurrentFrame = 0;
+ mRunning = true;
+ mStartTime = SDL_GetTicks() / 1000.0;
+ mLastTime = mStartTime;
+}
+
+void SceneBuild::update()
+{
+ mCurrentTime = SDL_GetTicks() / 1000.0;
+ mDt = mCurrentTime - mLastTime;
+ mLastTime = mCurrentTime;
+
+ mElapsedTime = mCurrentTime - mStartTime;
+
+ if(mElapsedTime >= mPartDuration[mCurrentPart])
+ {
+ mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+
+ switch(mCurrentPart)
+ {
+ case 0:
+ printf("Precompilation\n");
+ printf(" No Precompilation FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 1:
+ printf(" Build list FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 2:
+ printf(" Vertex array FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 3:
+ printf(" Vertex buffer object FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ }
+ mScore += mAverageFPS[mCurrentPart];
+ mCurrentPart++;
+ start();
+ if(mCurrentPart >= mPartsQty)
+ mRunning = false;
+ }
+
+ mRotation += mRotationSpeed * mDt;
+
+ mCurrentFrame++;
+}
+
+void SceneBuild::draw()
+{
+ glTranslatef(0.0f, 0.0f,-2.5f);
+ glRotated(mRotation, 0.0f, 1.0, 0.0f);
+
+ glColor3f(0.0f, 1.0f, 1.0f);
+ switch(mCurrentPart)
+ {
+ case 0:
+ mMesh.render();
+ break;
+ case 1:
+ glCallList(mMesh.mBuildList);
+ case 2:
+ mMesh.render_array();
+ break;
+ case 3:
+ mMesh.render_vbo();
+ break;
+ }
+}
=== added file 'sceneshading.cpp'
@@ -0,0 +1,140 @@
+#include "scene.h"
+
+SceneShading::~SceneShading()
+{
+}
+
+int SceneShading::load()
+{
+ Model model;
+
+ if(!model.load_3ds("data/models/cat.3ds"))
+ return 0;
+
+ model.calculate_normals();
+ model.convert_to_mesh(&mMesh);
+
+ mMesh.build_vbo();
+
+ mShader[0].load("data/shaders/light-basic.vert", "data/shaders/light-basic.frag");
+ mShader[1].load("data/shaders/light-advanced.vert", "data/shaders/light-advanced.frag");
+
+ mRotationSpeed = 36.0f;
+ mRotation = 0.0f;
+
+ mRunning = false;
+
+ mPartsQty = 3;
+ mPartDuration = new double[mPartsQty];
+ mAverageFPS = new unsigned[mPartsQty];
+ mScoreScale = new float[mPartsQty];
+
+ mScoreScale[0] = 0.534f;
+ mScoreScale[1] = 0.532f;
+ mScoreScale[2] = 0.556f;
+
+ mScore = 0;
+
+ mPartDuration[0] = 10.0;
+ mPartDuration[1] = 10.0;
+ mPartDuration[2] = 10.0;
+
+ mCurrentPart = 0;
+
+ return 1;
+}
+
+void SceneShading::start()
+{
+ GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
+ GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
+
+ float no_mat[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ float mat_diffuse[] = {0.1f, 0.5f, 0.8f, 1.0f};
+ float mat_specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ float high_shininess = 100.0f;
+
+ glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+ glMaterialf(GL_FRONT, GL_SHININESS, high_shininess);
+ glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
+
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+ glEnable(GL_LIGHT0);
+
+ switch(mCurrentPart)
+ {
+ case 0:
+ glDisable(GL_TEXTURE_2D);
+ glShadeModel(GL_SMOOTH);
+ break;
+ case 1:
+ glDisable(GL_TEXTURE_2D);
+ mShader[0].use();
+ break;
+ case 2:
+ glDisable(GL_TEXTURE_2D);
+ mShader[1].use();
+ break;
+ };
+
+ mCurrentFrame = 0;
+ mRunning = true;
+ mStartTime = SDL_GetTicks() / 1000.0;
+ mLastTime = mStartTime;
+}
+
+void SceneShading::update()
+{
+ mCurrentTime = SDL_GetTicks() / 1000.0;
+ mDt = mCurrentTime - mLastTime;
+ mLastTime = mCurrentTime;
+
+ mElapsedTime = mCurrentTime - mStartTime;
+
+ if(mElapsedTime >= mPartDuration[mCurrentPart])
+ {
+ mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+
+ switch(mCurrentPart)
+ {
+ case 0:
+ printf("Shading\n");
+ printf(" Smooth shader model FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 1:
+ printf(" GLSL per vertex lighting FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 2:
+ printf(" GLSL per pixel lighting FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ }
+ mScore += mAverageFPS[mCurrentPart];
+ mCurrentPart++;
+ start();
+ if(mCurrentPart >= mPartsQty)
+ mRunning = false;
+ }
+
+ mRotation += mRotationSpeed * mDt;
+
+ mCurrentFrame++;
+}
+
+void SceneShading::draw()
+{
+ glTranslatef(0.0f, 0.0f,-5.0f);
+ glRotated(mRotation, 0.0f, 1.0, 0.0f);
+
+ glColor3f(0.0f, 1.0f, 1.0f);
+
+ mMesh.render_vbo();
+}
+
+
+
=== added file 'scenetexture.cpp'
@@ -0,0 +1,127 @@
+#include "scene.h"
+
+SceneTexture::~SceneTexture()
+{
+ for(unsigned i = 0; i < 3; i++)
+ glDeleteTextures(1, &mTexture[i]);
+}
+
+int SceneTexture::load()
+{
+ Model model;
+
+ if(!model.load_3ds("data/models/cube.3ds"))
+ return 0;
+
+ if(!load_texture("data/textures/crate-base.bmp", mTexture))
+ return 0;
+
+ model.calculate_normals();
+ model.convert_to_mesh(&mCubeMesh);
+ mCubeMesh.build_list();
+
+ mRotationSpeed = Vector3f(36.0f, 36.0f, 36.0f);
+
+ mRunning = false;
+
+ mPartsQty = 3;
+ mPartDuration = new double[mPartsQty];
+ mAverageFPS = new unsigned[mPartsQty];
+ mScoreScale = new float[mPartsQty];
+
+ mScoreScale[0] = 0.471f;
+ mScoreScale[1] = 0.533f;
+ mScoreScale[2] = 0.405f;
+
+ mScore = 0;
+
+ mPartDuration[0] = 10.0;
+ mPartDuration[1] = 10.0;
+ mPartDuration[2] = 10.0;
+
+ mCurrentPart = 0;
+
+ return 1;
+}
+
+void SceneTexture::start()
+{
+ GLfloat lightAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
+ GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
+ GLfloat lightPosition[] = {20.0f, 20.0f, 10.0f, 1.0f};
+
+ glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+ glEnable(GL_LIGHT0);
+
+ glEnable(GL_TEXTURE_2D);
+
+ mCurrentFrame = 0;
+ mRunning = true;
+ mStartTime = SDL_GetTicks() / 1000.0;
+ mLastTime = mStartTime;
+}
+
+void SceneTexture::update()
+{
+ mCurrentTime = SDL_GetTicks() / 1000.0;
+ mDt = mCurrentTime - mLastTime;
+ mLastTime = mCurrentTime;
+
+ mElapsedTime = mCurrentTime - mStartTime;
+
+ if(mElapsedTime >= mPartDuration[mCurrentPart])
+ {
+ mAverageFPS[mCurrentPart] = mCurrentFrame / mElapsedTime;
+
+ switch(mCurrentPart)
+ {
+ case 0:
+ printf("Texture filtering\n");
+ printf(" Nearest FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 1:
+ printf(" Linear FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ case 2:
+ printf(" Mipmapped FPS: %u\n", mAverageFPS[mCurrentPart]);
+ break;
+ }
+ mScore += mAverageFPS[mCurrentPart];
+ mCurrentPart++;
+ start();
+ if(mCurrentPart >= mPartsQty)
+ mRunning = false;
+ }
+
+ mRotation += mRotationSpeed * mDt;
+
+ mCurrentFrame++;
+}
+
+void SceneTexture::draw()
+{
+ glLoadIdentity();
+ glColor3f(1.0f, 1.0f, 1.0f);
+ glTranslatef(0.0f, 0.0f, -4.0f);
+
+ glRotatef(mRotation.x, 1.0f, 0.0f, 0.0f);
+ glRotatef(mRotation.y, 0.0f, 1.0f, 0.0f);
+ glRotatef(mRotation.z, 0.0f, 0.0f, 1.0f);
+
+ switch(mCurrentPart)
+ {
+ case 0:
+ glBindTexture(GL_TEXTURE_2D, mTexture[0]);
+ glCallList(mCubeMesh.mBuildList);
+ break;
+ case 1:
+ glBindTexture(GL_TEXTURE_2D, mTexture[1]);
+ glCallList(mCubeMesh.mBuildList);
+ case 2:
+ glBindTexture(GL_TEXTURE_2D, mTexture[2]);
+ glCallList(mCubeMesh.mBuildList);
+ break;
+ }
+}
=== added file 'screen.cpp'
@@ -0,0 +1,116 @@
+#include "screen.h"
+
+Screen::Screen()
+{
+ mWidth = 800;
+ mHeight = 600;
+ mBpp = 24;
+ mFlags = SDL_OPENGL;
+ mFullScreen = false;
+
+ mInfo = SDL_GetVideoInfo();
+}
+
+Screen::~Screen()
+{
+ SDL_Quit();
+}
+
+Screen::Screen(int pWidth, int pHeight, int pBpp, int pFlags)
+{
+ mWidth = pWidth;
+ mHeight = pHeight;
+ mBpp = pBpp;
+ mFlags = SDL_OPENGL | pFlags;
+
+ mInfo = SDL_GetVideoInfo();
+}
+
+int Screen::init()
+{
+#ifdef _DEBUG
+ printf("Initializing Screen... ");
+#endif
+ if(SDL_Init(SDL_INIT_VIDEO) < 0)
+ {
+ fprintf(stderr, "[ Fail ] - Video initialization failed: %s\n", SDL_GetError());
+ return 0;
+ }
+
+ if(mFullScreen)
+ mFlags = SDL_OPENGL | SDL_FULLSCREEN;
+
+ mInfo = SDL_GetVideoInfo();
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ if(SDL_SetVideoMode(mWidth, mHeight, mBpp, mFlags) == 0)
+ {
+ fprintf(stderr, "[ Fail ] - Video mode set failed: %s\n", SDL_GetError());
+ return 0;
+ }
+
+ SDL_WM_SetCaption("GLMark 08", NULL);
+
+ GLenum err = glewInit();
+ if(GLEW_OK != err)
+ {
+ fprintf(stderr, "[ Fail ] - Error: %s\n", glewGetErrorString(err));
+ return 0;
+ }
+
+ if(!GLEW_ARB_vertex_buffer_object)
+ {
+ fprintf(stderr, "[ Fail ] - VBO objects are not supported\n");
+ return 0;
+ }
+
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
+ glClearDepth(1.0f);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glViewport(0, 0, mWidth, mHeight);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(60.0, mWidth / (float)mHeight, 1.0, 1024.0);
+ glMatrixMode(GL_MODELVIEW);
+
+ clear();
+
+#ifdef _DEBUG
+ printf("[ Success ]\n");
+#endif
+ print_info();
+ return 1;
+}
+
+void Screen::clear()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glLoadIdentity();
+}
+
+void Screen::update()
+{
+ SDL_GL_SwapBuffers();
+}
+
+void Screen::print_info()
+{
+ printf(" OpenGL Information\n");
+ printf(" GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ printf(" GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ printf(" GL_VERSION: %s\n", glGetString(GL_VERSION));
+// printf("GL_EXTENSIONS: %s\n", glGetString(GL_EXTENSIONS));
+}
+
=== added file 'screen.h'
@@ -0,0 +1,29 @@
+#ifndef _SCREEN_H
+#define _SCREEN_H
+
+#include "oglsdl.h"
+
+#include <stdio.h>
+
+class Screen
+{
+public:
+ const SDL_VideoInfo *mInfo;
+
+ int mWidth;
+ int mHeight;
+ int mBpp;
+ int mFlags;
+ int mFullScreen;
+// SDL_Surface *mScreen;
+
+ Screen();
+ ~Screen();
+ Screen(int pWidth, int pHeight, int pBpp, int pFlags);
+ int init();
+ void clear();
+ void update();
+ void print_info();
+};
+
+#endif
=== added file 'shader.cpp'
@@ -0,0 +1,74 @@
+#include "shader.h"
+
+char *readShaderFile(const char *FileName)
+{
+ FILE *fp;
+ char *DATA = NULL;
+
+ int flength = 0;
+
+ fp = fopen(FileName,"rt");
+
+ fseek(fp, 0, SEEK_END);
+
+ flength = ftell(fp);
+
+ rewind(fp);
+
+
+ DATA = (char *)malloc(sizeof(char) * (flength+1));
+ flength = fread(DATA, sizeof(char), flength, fp);
+ DATA[flength] = '\0';
+
+ fclose(fp);
+
+ return DATA;
+}
+
+Shader::~Shader()
+{
+ remove();
+}
+
+void Shader::load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName)
+{
+ char *vertex_shader_source, *fragment_shader_source;
+
+ mVertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
+ mFragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
+
+ vertex_shader_source = readShaderFile(pVertexShaderFileName);
+
+ fragment_shader_source = readShaderFile(pFragmentShaderFileName);
+
+ const char *vs = vertex_shader_source;
+ const char *fs = fragment_shader_source;
+
+ glShaderSourceARB(mVertexShader, 1, &vs, NULL);
+ glShaderSourceARB(mFragmentShader, 1, &fs, NULL);
+
+ free(vertex_shader_source);
+ free(fragment_shader_source);
+
+ glCompileShaderARB(mVertexShader);
+ glCompileShaderARB(mFragmentShader);
+
+ mShaderProgram = glCreateProgramObjectARB();
+ glAttachObjectARB(mShaderProgram, mFragmentShader);
+ glAttachObjectARB(mShaderProgram, mVertexShader);
+
+ glLinkProgram(mShaderProgram);
+}
+
+void Shader::use()
+{
+ glUseProgramObjectARB(mShaderProgram);
+}
+
+void Shader::remove()
+{
+ glDetachObjectARB(mShaderProgram, mVertexShader);
+ glDetachObjectARB(mShaderProgram, mFragmentShader);
+
+ glDeleteObjectARB(mShaderProgram);
+}
=== added file 'shader.h'
@@ -0,0 +1,22 @@
+#ifndef _SHADER_H
+#define _SHADER_H
+
+#include "oglsdl.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+class Shader
+{
+public:
+ ~Shader();
+ void load(const char *pVertexShaderFileName, const char *pFragmentShaderFileName);
+ void remove();
+ void use();
+
+ GLuint mVertexShader;
+ GLuint mFragmentShader;
+ int mShaderProgram;
+};
+
+#endif
=== added file 'texture.cpp'
@@ -0,0 +1,94 @@
+#include "texture.h"
+
+int load_texture(const char pFilename[], GLuint *pTexture)
+{
+ SDL_Surface *surface;
+ GLenum texture_format;
+ GLint nOfColors;
+
+ if ((surface = SDL_LoadBMP(pFilename)))
+ {
+ if ((surface->w & (surface->w - 1)) != 0)
+ printf("warning: image.bmp's width is not a power of 2\n");
+
+ if ((surface->h & (surface->h - 1)) != 0)
+ printf("warning: image.bmp's height is not a power of 2\n");
+
+ nOfColors = surface->format->BytesPerPixel;
+ if (nOfColors == 4)
+ {
+ if (surface->format->Rmask == 0x000000ff)
+ texture_format = GL_RGBA;
+ else
+ texture_format = GL_BGRA;
+ }
+ else
+ {
+ if (nOfColors == 3)
+ {
+ if (surface->format->Rmask == 0x000000ff)
+ texture_format = GL_RGB;
+ else
+ texture_format = GL_BGR;
+ }
+ else
+ {
+ printf("warning: the image is not truecolor.. this will probably break\n");
+ }
+ }
+
+ glGenTextures(3, pTexture);
+
+ // Create Nearest Filtered Texture
+ glBindTexture(GL_TEXTURE_2D, pTexture[0]);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+
+ // Create Linear Filtered Texture
+ glBindTexture(GL_TEXTURE_2D, pTexture[1]);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+
+ // Create MipMapped Texture
+ glBindTexture(GL_TEXTURE_2D, pTexture[2]);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
+
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface->w, surface->h, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+
+/*
+ switch (filter)
+ {
+ case 0:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+ break;
+
+ case 1:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, nOfColors, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels);
+ break;
+
+ case 2:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
+ break;
+ }
+*/
+ }
+ else
+ {
+ fprintf(stderr, "SDL could not load image.bmp: %s\n", SDL_GetError());
+ return 0;
+ }
+
+ if (surface)
+ SDL_FreeSurface(surface);
+
+ return 1;
+}
=== added file 'texture.h'
@@ -0,0 +1,10 @@
+#ifndef _TEXTURE_H
+#define _TEXTURE_H
+
+#include "oglsdl.h"
+
+#include <stdio.h>
+
+int load_texture(const char pFilename[], GLuint *pTexture);
+
+#endif
=== added file 'vector.cpp'
@@ -0,0 +1,125 @@
+#include "vector.h"
+
+Vector3f::Vector3f()
+{
+ x = 0.0f; y = 0.0f; z = 0.0f;
+}
+
+Vector3f::Vector3f(GLfloat pX, GLfloat pY, GLfloat pZ)
+{
+ x = pX; y = pY; z = pZ;
+}
+
+void Vector3f::display()
+{
+ printf("(%f, %f, %f)\n", x, y, z);
+}
+
+float Vector3f::length()
+{
+ return sqrt(x * x + y * y + z * z);
+}
+
+void Vector3f::normalize()
+{
+ GLfloat l = length();
+ x /= l; y /= l; z /= l;
+}
+
+Vector3f &Vector3f::operator=(const Vector3f &pV)
+{
+ x = pV.x;
+ y = pV.y;
+ z = pV.z;
+ return *this;
+}
+
+Vector3f &Vector3f::operator+=(const Vector3f &pV)
+{
+ x += pV.x;
+ y += pV.y;
+ z += pV.z;
+ return *this;
+}
+
+Vector3f &Vector3f::operator-=(const Vector3f &pV)
+{
+ x -= pV.x;
+ y -= pV.y;
+ z -= pV.z;
+ return *this;
+}
+
+Vector3f &Vector3f::operator*=(float pF)
+{
+ x *= pF;
+ y *= pF;
+ z *= pF;
+ return *this;
+}
+
+Vector3f &Vector3f::operator*=(double pF)
+{
+ x *= pF;
+ y *= pF;
+ z *= pF;
+ return *this;
+}
+
+Vector3f &Vector3f::operator/=(float pF)
+{
+ x /= pF;
+ y /= pF;
+ z /= pF;
+ return *this;
+}
+
+Vector3f operator+(const Vector3f &pA, const Vector3f &pB)
+{
+ Vector3f v = pA;
+ return v += pB;
+}
+
+Vector3f operator-(const Vector3f &pA, const Vector3f &pB)
+{
+ Vector3f v = pA;
+ return v -= pB;
+}
+
+Vector3f operator*(const Vector3f &pA, const float &pB)
+{
+ Vector3f v = pA;
+ return v *= pB;
+}
+
+Vector3f operator/(const Vector3f &pA, const float &pB)
+{
+ Vector3f v = pA;
+ return v /= pB;
+}
+
+Vector3f operator*(const Vector3f &pA, const double &pB)
+{
+ Vector3f v = pA;
+ return v *= pB;
+}
+
+Vector3f cross(const Vector3f &pA, const Vector3f &pB)
+{
+ return Vector3f(pA.y * pB.z - pA.z * pB.y,
+ pA.z * pB.x - pA.x * pB.z,
+ pA.x * pB.y - pA.y * pB.x);
+}
+
+float dot(const Vector3f &pA, const Vector3f &pB)
+{
+ return pA.x * pB.x + pA.y * pB.y + pA.z * pB.z;
+}
+
+Vector3f normal(const Vector3f &pA, const Vector3f &pB, const Vector3f &pC)
+{
+ Vector3f n = cross(pB - pA, pC - pA);
+ n.normalize();
+ return n;
+}
+
=== added file 'vector.h'
@@ -0,0 +1,45 @@
+#ifndef _VECTOR_H
+#define _VECTOR_H
+
+#include "oglsdl.h"
+
+#include <stdio.h>
+#include <math.h>
+
+class Vector3f
+{
+ union
+ {
+ struct { GLfloat x; GLfloat y; GLfloat z; };
+ GLfloat v[3];
+ };
+
+public:
+
+ Vector3f();
+ Vector3f(GLfloat pX, GLfloat pY, GLfloat pZ);
+
+ void display();
+ float length();
+ void normalize();
+
+ Vector3f &operator=(const Vector3f &pV);
+ Vector3f &operator+=(const Vector3f &pV);
+ Vector3f &operator-=(const Vector3f &pV);
+ Vector3f &operator*=(float pF);
+ Vector3f &operator/=(float pF);
+ Vector3f &operator*=(double pF);
+};
+
+extern Vector3f operator+(const Vector3f &pA, const Vector3f &pB);
+extern Vector3f operator-(const Vector3f &pA, const Vector3f &pB);
+extern Vector3f operator*(const Vector3f &pA, const float &pB);
+extern Vector3f operator/(const Vector3f &pA, const float &pB);
+
+extern Vector3f operator*(const Vector3f &pA, const double &pB);
+
+extern float dot(const Vector3f &pA, const Vector3f &pB);
+extern Vector3f cross(const Vector3f &pA, const Vector3f &pB);
+extern Vector3f normal(const Vector3f &pA, const Vector3f &pB, const Vector3f &pC);
+
+#endif