Official spec for JGLMark test #1 "Primitives"

Official spec for JGLMark test #1 “Primitives”
An emitter fountain will spew out random objects. As time goes on more and more objects
will be emiited, until the test concludes. The fountain will be placed in a room. As the fountain emitts objects the camera will be translated
around it. As the emitted objects approach the “ground object”, they will be removed from the scene. This test will utililize vertex arrays, to render the modeled objects However if it is detected that the system is capable of using VBO’s the test will switch to using VBO’s instead. This test is basic test to see how well the system is at handling basic OpenGL tasks.

Below are some renderings of the emmission room and meshes that will spew out of the fountain…
The Emission Room & Fountain:

The Emission Meshes:



Visit us at: http://jglmark.dev.java.net

I’ll admit I’m not qualified to “grade” how well this will perform as a JGLMark test, but it looks great to me. :slight_smile:

For a basic test, this seems simple, yet effective. Everything visible is right there in front of you, and it should be fairly easy to gauge how intense the graphical output is becoming.

And as an added plus, the art looks cool, good job. :slight_smile:

wow, screenshots look nice

I appreciate what are you doing here. Looks serious and proffessionall.
One suggestion: If object were emmited on random basis, and they have different number of vertices, that wouldn’t be accurate measurement. On different machines, so, some Bill and Jack will execute JGLMARK and run the test. It will last, sey 2 minutes, but Bill’s graph. card will have to render X polys, while Jack’s maybe 5-10 % more because of that randomness. What do you think?
Maybe you should programm that fountain to spew out ALWAYS same object at a time?

Just use the same random seed. You’ll get reproducible behaviour without having to hard-code everything.

Thanks for the interest and comments, everyone. I think I can address some of these specific concerns. What crash meant to say is that the emission pattern will appear to be random to the end user. It will, in fact, be the same every time. To me, the highest priority with all of these tests is making sure that they run identically on all hardware. This means the same number of vertices being rendered at the same time on all platforms, this also includes things like number of passes, textures used, and vp/fp and GLSL shaders. You guys are right that any sort of randomness will contaminate the uniformity across machines, thus everything will be explicitly scripted.

below is the code for spewing the meshes from the fountain, feel free to comment.

package pf;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Random;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.ARBBufferObject;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.glu.GLU;

public class GLFountain {
public static boolean EXIT_APP = false;
public static String WINDOW_TITLE = “OpenGL Mesh Fountain”;
public static DisplayMode displayMode;
public static int WINDOW_WIDTH = 1024;
public static int WINDOW_HEIGHT = 768;
public static int WINDOW_DEPTH = 32;
public float FOVY = 80.0f;
public float NEAR_VIEW_DISTANCE = 0.1f;
public float FAR_VIEW_DISTANCE = 1000.0f;
public float EYE_X = 0.0f;
public float EYE_Y = 600.0f;
public float EYE_Z = 350.0f;
public float AT_X = 0.0f;
public float AT_Y = 0.0f;
public float AT_Z = 0.0f;
public float UP_X = 0.0f;
public float UP_Y = 1.0f;
public float UP_Z = 0.0f;
public float [] floatplane = {300.0f,0.0f,-300.0f,300.0f,0.0f,300.0f,-300.0f,0.0f,300.0f,-300.0f,0.0f,-300.0f};
public FloatBuffer plane = BufferUtils.createFloatBuffer(floatplane.length);
public float [] floattriangles = {0.0f,1.0f,0.0f,1.0f,-1.0f,0.0f,-1.0f,-1.0f,0.0f};
public FloatBuffer triangles = BufferUtils.createFloatBuffer(floattriangles.length);
public int [] VBO_ID = new int[2];

public final int MaxObjects = 10000;
int ctr=0;
public int Objects = 0;
public float DistanceTime = 0.1f;
public float Gravity = 9.8f;
public byte randX[] = new byte[1000];
public byte randY[] = new byte[1000];
public byte randZ[] = new byte[1000];
public float[] x = new float[MaxObjects];
public float[] y = new float[MaxObjects];
public float[] z = new float[MaxObjects];
public float[] DirectionX = new float[MaxObjects];
public float[] DirectionY = new float[MaxObjects];
public float[] DirectionZ = new float[MaxObjects];
public float [] rand_R = new float[MaxObjects];
public float [] rand_G = new float[MaxObjects];
public float [] rand_B = new float[MaxObjects];
public float startPointX=0.0f;
public float startPointY=0.0f;
public float startPointZ=0.0f;



public static void main(String[] args) {
    GLFountain glfountain = new GLFountain();
    glfountain.run();
}

public void run() {
    long startTime = System.currentTimeMillis() + 5000;
    long fps = 0;
    try {
        init();
        while (!EXIT_APP) {
            MainLoop();
            Display.update();
            if (startTime > System.currentTimeMillis()) {
                fps++;
            } else {
                long timeUsed = 5000 + (startTime - System.currentTimeMillis());
                startTime = System.currentTimeMillis() + 5000;
                String outdata = fps + " frames in " + (float) (timeUsed / 1000f) + " seconds = "+ (fps / (timeUsed / 1000f))+" FPS";
                System.out.println( outdata );
                Display.setTitle(WINDOW_TITLE + " " + outdata);
                fps = 0;
            }
        }
        cleanup();
        System.exit(0);
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(0);
    }
}

public void MainLoop() {
    if(Display.isCloseRequested()) {
        EXIT_APP = true;
    }
    timePassesBy();
    newObject();
    render();
}

public void createWindow() throws Exception {
    DisplayMode modes[] = Display.getAvailableDisplayModes();
    for (int i = 0; i < modes.length; i++) {
        if (modes[i].getWidth() == WINDOW_WIDTH
                && modes[i].getHeight() == WINDOW_HEIGHT
                && modes[i].getBitsPerPixel() == WINDOW_DEPTH) {
            displayMode = modes[i];
            break;
        }
    }
    Display.setDisplayMode(displayMode);
    Display.setTitle(WINDOW_TITLE);
    Display.create();
}

public void init() throws Exception {
    createWindow();
    CheckExtensions();
    initGL();
    CreateVBO();
    initializefountain();
}

public void CheckExtensions() {
    if (!GLContext.getCapabilities().GL_ARB_vertex_buffer_object ) {
        System.out.println("ARB VBO Extension is not supported!");
        System.out.println("Dropping Out!");
        System.exit(1);
    }
}

public void initGL() {
    Display.setVSyncEnabled(false);
    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
    GL11.glShadeModel(GL11.GL_SMOOTH);
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    GL11.glClearDepth(1.0);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthFunc(GL11.GL_LEQUAL);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(FOVY,(float) displayMode.getWidth() / (float) displayMode.getHeight(),NEAR_VIEW_DISTANCE,FAR_VIEW_DISTANCE);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    GLU.gluLookAt(EYE_X, EYE_Y, EYE_Z, AT_X, AT_Y, AT_Z, UP_X, UP_Y, UP_Z);
}

public void CreateVBO() {
    plane.put(floatplane).rewind();
    triangles.put(floattriangles).rewind();
    VBO_ID[0]=CreateVBOID();
    BufferData(VBO_ID[0], plane);
    VBO_ID[1]=CreateVBOID();
    BufferData(VBO_ID[1], triangles);
}

public  int CreateVBOID() {
    IntBuffer buffer = BufferUtils.createIntBuffer(1);
    ARBVertexBufferObject.glGenBuffersARB(buffer);
    return buffer.get(0);
}

public static void BufferData(int id, FloatBuffer buffer) {
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
    ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}

public void initializefountain() {
    Random r = new Random(34567890);
    r.nextBytes(randX);
    r.nextBytes(randY);
    r.nextBytes(randZ);
    for (int i = 0; i < MaxObjects; i++) {
        rand_R[i] =(float)Math.random();
        rand_G[i] =(float)Math.random();
        rand_B[i] =(float)Math.random();
    }
    for (int i = 0; i < 10; i++) {
        newObject();
    }
}

void newObject(){
    if (Objects  < MaxObjects){
        initObject(Objects);
        Objects++;
    }
}

void initObject(int p) {
    x[p] = startPointX;
    y[p] = startPointY;
    z[p] = startPointZ;
    ctr++;
    ctr %= randX.length;
    DirectionX[p] = randX[ctr] / 10.0f;
    DirectionY[p] = randY[ctr] / 10.0f - 80;
    DirectionZ[p] = randZ[ctr] / 10.0f;
}

void timePassesBy(){
    for (int i = 0; i < Objects; i++) {
        DirectionY[i]  += DistanceTime*Gravity;
        x[i] -= DistanceTime*DirectionX[i];
        y[i] -= DistanceTime*DirectionY[i];
        z[i] -= DistanceTime*DirectionZ[i];
        if (y[i] < startPointY) {
            initObject(i);
        }
    }
}

public void render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    GL11.glColor3f(0.6f, 0.6f, 0.6f);
    ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, VBO_ID[0]); 
    GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
    GL11.glDrawArrays(GL11.GL_QUADS, 0, 12);       
    for (int i = 0; i < Objects; i++) {
        GL11.glColor3f(rand_R[i], rand_G[i], rand_B[i]);
        GL11.glPushMatrix();
        GL11.glTranslatef(x[i],y[i],z[i]);
        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, VBO_ID[1]);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 9);
        GL11.glPopMatrix();           
    }
}

public void cleanup() {
    IntBuffer del_vbo_id = BufferUtils.createIntBuffer(1);
    del_vbo_id.put(0, VBO_ID[0]);
    ARBBufferObject.glDeleteBuffersARB(del_vbo_id);
    del_vbo_id.put(0, VBO_ID[1]);
    ARBBufferObject.glDeleteBuffersARB(del_vbo_id);
    Display.destroy();
}

}