|
|
| C vs Perl | Perl vs Python | POGL vs SDL | Windows vs Linux |
POGL Benchmarks - C vs Perl
This is a benchmark implemented in C and Perl, using animated FBOs and a fragment shader.
These benchmarks were performed on the same multi-boot system:
3Ghz Intel Pentium D
1G Memory
nVidia GeForce 6800 GT/AGP/SSE2
Matched nVidia drivers (as of March, 15, 2007):
Linux: v97.55
Vista: v100.65
The tests were run using portable, non-OOP C and Perl code on:
Vista
Fedora 6
Ubuntu/Dapper
The C benchmarks require an OpenGL installation and GLUT.
The Perl benchmarks also require Perl, POGL and the Time::HiRes module.
These tests were also run on a similar XP system, with similar results;
however, since it was not possible to install XP after Vista and Linux
were already installed on this benchmark system,
those results were not included in this report.
No statistical difference in overall performance between C and Perl
Perl outperformed C on FBO operations; C beat Perl on Shader ops
On Vista, Perl occasionally/often ran faster than C
Fedora and Ubuntu were comparable in performance
Linux was generally 60% faster than Vista
|
Vista |
Fedora 6 |
Ubuntu/Dapper |
PROFILE |
C | Perl |
C | Perl |
C | Perl |
FBO Texture Rendering FPS |
117.296043 | 137.680194 |
190.628178 | 192.675391 |
193.914733 | 194.749544 |
Teapot Shader FPS |
267.217852 | 284.675682 |
479.408799 | 472.232557 |
472.171695 | 477.404038 |
Frame overhead secs/frame |
0.000032 | 0.000126 |
0.000030 | 0.000071 |
0.000033 | 0.000067 |
OS/GLUT overhead secs/frame |
0.000000 | 0.000050 |
0.000006 | 0.000014 |
0.000114 | 0.000114 |
TOTAL FPS |
81.302792 | 91.315494 |
135.728814 | 135.275647 |
134.742228 | 134.945798 |
There are a number of factors explaining the lack of significant
difference between C and Perl OpenGL performance:
POGL is a compiled C module
Most of the work is performed by the GPU
POGL leverages OpenGL::Array (OGA) objects
OGA stores data in typed C arrays, eliminating the need for conversion/copy/casting
when passing array data to OpenGL APIs.
Perl OpenGL provides a number of other advantages:
Completely portable, with no compiling; faster prototyping
Easy integration into LAMP-based online services
Improved string handling for dynamic shader programming
C Binding
// ogl_bench v1.0 - Copyright 2007 - Graphcomp
// Bob Free bfree@graphcomp.com
// http://graphcomp.com/opengl
// This program is freely distributable without licensing fees
// and is provided without guarantee or warrantee expressed or
// implied. This program is -not- in the public domain.
// Set up standard libs
#include <stdlib.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <stdio.h>
#include <string.h>
// Set up constants
#define PROGRAM "OpenGL Benchmark - C Binding"
#define CYCLES 1000
// Setup OpenGL Extensions
#include <GL/glut.h>
#ifdef _WIN32
#define GL_GLEXT_PROCS
#define loadProc(proc,name) \
if (!proc) \
{ \
proc = (void *)wglGetProcAddress(name); \
if (!proc) error("Unable to load",name); \
}
#define timeb _timeb
#define ftime _ftime
#else
#define GL_GLEXT_PROTOTYPES
#define loadProc(proc,name)
#endif
#include "glext_procs.h"
// Set up types
typedef struct
{
struct timeb start;
float secs;
} Bench;
// Set up globals
Bench appBench;
Bench frameBench;
Bench textureBench;
Bench teapotBench;
struct timeb now;
int frames = 0;
GLuint idWindow = 0;
GLint windowWidth = 512;
GLint windowHeight = 512;
GLint textureWidth = 128;
GLint textureHeight = 128;
GLfloat rotTeapotX = 0;
GLfloat rotTeapotY = 0;
GLuint idTexture = 0;
GLuint idFrameBuffer = 0;
GLuint idRenderBuffer = 0;
GLuint idVertexProg = 0;
GLuint idFragProg = 0;
GLdouble incY = 0.5;
GLdouble rotY = 0.0;
// Start benchmark
void startBench(Bench *pBench)
{
ftime(&pBench->start);
}
// Accumulate benchmark
void endBench(Bench *pBench)
{
ftime(&now);
pBench->secs += (float)(now.time - pBench->start.time) +
(float)((now.millitm - pBench->start.millitm) / 1000.0);
}
// Print benchmark
void printBench()
{
float overhead;
if (!frames || !appBench.secs || !frameBench.secs ||
!textureBench.secs || !teapotBench.secs)
{
printf("No measurable time has elapsed\n");
return;
}
printf("FBO Texture Rendering FPS: %f\n", frames / textureBench.secs);
printf("Teapot Shader FPS: %f\n", frames / teapotBench.secs);
overhead = frameBench.secs - (textureBench.secs + teapotBench.secs);
printf("Frame overhead secs/frame: %f\n", overhead / frames);
overhead = appBench.secs - frameBench.secs;
printf("OS/GLUT overhead secs/frame: %f\n", overhead / frames);
printf("Overall FPS: %f\n", frames / appBench.secs);
printf("\n");
}
// Error handling
void error(char *errTitle, char *errMsg)
{
printf("%s: %s\n", errTitle, errMsg);
exit(0);
}
// Check OpenGL Version
void checkVersion(void)
{
char *version = (char*)glGetString(GL_VERSION);
char *vendor = (char*)glGetString(GL_VENDOR);
char *renderer = (char*)glGetString(GL_RENDERER);
char *exts = (char*)glGetString(GL_EXTENSIONS);
printf("%s\n\n", PROGRAM);
printf("OpenGL: %s\n", version);
printf("Vendor: %s\n", vendor);
printf("Renderer: %s\n", renderer);
printf("\n");
if (!strstr(exts,"EXT_framebuffer_object"))
{
error("Extension not available","EXT_framebuffer_object");
}
}
// Load Extension Procs
void initExtensions(void)
{
loadProc(glIsRenderbufferEXT,"glIsRenderbufferEXT");
loadProc(glBindRenderbufferEXT,"glBindRenderbufferEXT");
loadProc(glDeleteRenderbuffersEXT,"glDeleteRenderbuffersEXT");
loadProc(glGenRenderbuffersEXT,"glGenRenderbuffersEXT");
loadProc(glRenderbufferStorageEXT,"glRenderbufferStorageEXT");
loadProc(glGetRenderbufferParameterivEXT,"glGetRenderbufferParameterivEXT");
loadProc(glIsFramebufferEXT,"glIsFramebufferEXT");
loadProc(glBindFramebufferEXT,"glBindFramebufferEXT");
loadProc(glDeleteFramebuffersEXT,"glDeleteFramebuffersEXT");
loadProc(glGenFramebuffersEXT,"glGenFramebuffersEXT");
loadProc(glCheckFramebufferStatusEXT,"glCheckFramebufferStatusEXT");
loadProc(glFramebufferTexture1DEXT,"glFramebufferTexture1DEXT");
loadProc(glFramebufferTexture2DEXT,"glFramebufferTexture2DEXT");
loadProc(glFramebufferTexture3DEXT,"glFramebufferTexture3DEXT");
loadProc(glFramebufferRenderbufferEXT,"glFramebufferRenderbufferEXT");
loadProc(glGetFramebufferAttachmentParameterivEXT,"glGetFramebufferAttachmentParameterivEXT");
loadProc(glGenerateMipmapEXT,"glGenerateMipmapEXT");
loadProc(glGenProgramsARB,"glGenProgramsARB");
loadProc(glBindProgramARB,"glBindProgramARB");
loadProc(glProgramStringARB,"glProgramStringARB");
loadProc(glDeleteProgramsARB,"glDeleteProgramsARB");
}
// Initialize Vertex/Fragment Programs
void initProgs(void)
{
// NOP Vertex shader
const char *vertexProg =
"!!ARBvp1.0\n"
"TEMP vertexClip;\n"
"DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;\n"
"DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;\n"
"DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;\n"
"DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;\n"
"MOV result.position, vertexClip;\n"
"MOV result.color, vertex.color;\n"
"MOV result.texcoord[0], vertex.texcoord;\n"
"MOV result.texcoord[1], vertex.normal;\n"
"END\n";
// Black Light Fragment shader
const char *fragProg =
"!!ARBfp1.0\n"
"TEMP decal,color;\n"
"TEX decal, fragment.texcoord[0], texture[0], 2D;\n"
"MUL result.color, decal, fragment.texcoord[1];\n"
"END\n";
glGenProgramsARB(1,&idVertexProg);
glGenProgramsARB(1,&idFragProg);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, idVertexProg);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
(GLsizei)strlen(vertexProg), vertexProg);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, idFragProg);
glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
(GLsizei)strlen(fragProg), fragProg);
}
// Terminate Vertex/Fragment Programs
void termProgs(void)
{
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
glDeleteProgramsARB(1,&idVertexProg);
glDeleteProgramsARB(1,&idFragProg);
}
// FBO Status handler
void statusFBO(void)
{
GLenum stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (!stat || stat == GL_FRAMEBUFFER_COMPLETE_EXT) {return;};
printf("FBO status: %04X\n", stat);
exit(0);
}
// Initialize Framebuffers
void initFBO(void)
{
glGenTextures(1,&idTexture);
glGenFramebuffersEXT(1,&idFrameBuffer);
glGenRenderbuffersEXT(1,&idRenderBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, idFrameBuffer);
glBindTexture(GL_TEXTURE_2D, idTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, idTexture, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, idRenderBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,
textureWidth, textureHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, idRenderBuffer);
statusFBO();
}
// FBO texture renderer
void renderFBO(void)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, idFrameBuffer);
glLoadIdentity();
glTranslated(-0.75, -0.85, -2.5);
glRotated(rotTeapotX, 1.0, 0.0, 0.0);
rotTeapotX += .5;
glRotated(rotTeapotY, 0.0, 1.0, 0.0);
rotTeapotY += 1.0;
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1.0, 1.0, 1.0);
glutWireTeapot(0.125);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
// Terminate FBO objects
void termFBO(void)
{
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteRenderbuffersEXT(1,&idRenderBuffer);
glDeleteFramebuffersEXT(1,&idFrameBuffer);
glDeleteTextures(1,&idTexture);
}
// Resize Window
void resizeScene(GLint width, GLint height)
{
if (!height){height = 1;};
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,width/height,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
windowWidth = width;
windowHeight = height;
}
// Initialize OpenGL Environment
void init(void)
{
checkVersion();
initExtensions();
resizeScene(windowWidth, windowHeight);
initFBO();
initProgs();
}
// Terminate OpenGL Environment
void term(void)
{
// Display benchmark
endBench(&appBench);
printBench();
// Disable app
glutHideWindow();
glutKeyboardFunc(0);
glutSpecialFunc(0);
glutIdleFunc(0);
glutReshapeFunc(0);
// Release Framebuffers
termProgs();
termFBO();
// Now we can destroy window
glutDestroyWindow(idWindow);
exit(0);
}
// Frame handler
void display(void)
{
// Run benchmark CYCLES times
if (++frames > CYCLES) {term();};
startBench(&frameBench);
// Render animated texture
startBench(&textureBench);
renderFBO();
endBench(&textureBench);
// Set up ModelView
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-5.0);
glRotated(0.0,1.0,0.0,0.0);
glRotated(rotY,0.0,1.0,0.0);
rotY += incY;
// Set attributes
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
// Clear render buffer and set teapot color
glClearColor((float)0.2, (float)0.2, (float)0.2, (float)1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0.9, 0.45, 0.0);
// Render the teapot using our shader
startBench(&teapotBench);
glEnable(GL_VERTEX_PROGRAM_ARB);
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glutSolidTeapot(1.0);
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glDisable(GL_VERTEX_PROGRAM_ARB);
endBench(&teapotBench);
// Double-buffer and done
glutSwapBuffers();
endBench(&frameBench);
}
// Keyboard handler
void keyPressed(GLubyte key, GLint x, GLint y)
{
term();
}
// Main app
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA);
glutInitWindowSize(windowWidth,windowHeight);
idWindow = glutCreateWindow(PROGRAM);
glutDisplayFunc(display);
glutIdleFunc(display);
//glutReshapeFunc(resizeScene);
glutKeyboardFunc(keyPressed);
init();
startBench(&appBench);
glutMainLoop();
return(0);
}
|
|
Perl Binding
#!/usr/bin/perl -w
# ogl_bench v1.0 - Copyright 2007 - Graphcomp
# Bob Free bfree@graphcomp.com
# http://graphcomp.com/opengl
# This program is freely distributable without licensing fees
# and is provided without guarantee or warrantee expressed or
# implied. This program is -not- in the public domain.
# Set up standard libs
use strict;
use Math::Trig;
eval 'use Time::HiRes qw( gettimeofday )';
my $hasHires = !$@; # Only appBench will be valid if no HiRes
sub ftime{return $hasHires ? gettimeofday() : time()}
# Set up constants
use constant PROGRAM => "OpenGL Benchmark - Perl Binding";
use constant CYCLES => 1000;
# Setup OpenGL Extensions
use OpenGL qw/ :all /;
# Set up globals
my $appBench = {};
my $frameBench = {};
my $textureBench = {};
my $teapotBench={};
my $now;
my $frames = 0;
my $idWindow = 0;
my $windowWidth = 512;
my $windowHeight = 512;
my $textureWidth = 128;
my $textureHeight = 128;
my $rotTeapotX = 0;
my $rotTeapotY = 0;
my $idTexture = 0;
my $idFrameBuffer = 0;
my $idRenderBuffer = 0;
my $idVertexProg = 0;
my $idFragProg = 0;
my $incY = 0.5;
my $rotY = 0.0;
# Start benchmark
sub startBench
{ my($pBench) = @_;
$pBench->{start} = ftime();
}
# Accumulate benchmark
sub endBench
{ my($pBench) = @_;
$now = ftime();
$pBench->{secs} += $now - $pBench->{start};
}
# Print benchmark
sub printBench
{
my $overhead;
if (!$frames || !$appBench->{secs} || !$frameBench->{secs} ||
!$textureBench->{secs} || !$teapotBench->{secs})
{
printf("No measurable time has elapsed\n");
return;
}
printf("FBO Texture Rendering FPS: %f\n", $frames / $textureBench->{secs});
printf("Teapot Shader FPS: %f\n", $frames / $teapotBench->{secs});
$overhead = $frameBench->{secs} - ($textureBench->{secs} + $teapotBench->{secs});
printf("Frame overhead secs/frame: %f\n", $overhead / $frames);
$overhead = $appBench->{secs} - $frameBench->{secs};
printf("OS/GLUT overhead secs/frame: %f\n", $overhead / $frames);
printf("Overall FPS: %f\n", $frames / $appBench->{secs});
printf("\n");
}
# Error handling
sub error
{ my($errTitle,$errMsg) = @_;
printf("%s: %s\n", $errTitle, $errMsg);
exit(0);
}
# Check OpenGL Version
sub checkVersion
{
my $version = glGetString(GL_VERSION);
my $vendor = glGetString(GL_VENDOR);
my $renderer = glGetString(GL_RENDERER);
my $exts = glGetString(GL_EXTENSIONS);
printf("%s\n\n", PROGRAM);
printf("OpenGL: %s\n", $version);
printf("Vendor: %s\n", $vendor);
printf("Renderer: %s\n", $renderer);
printf("\n");
if ($exts !~ m|EXT_framebuffer_object|)
{
error("Extension not available","EXT_framebuffer_object");
}
}
# Initialize Vertex/Fragment Programs
sub initProgs
{
# NOP Vertex shader
my $vertexProg = qq
{!!ARBvp1.0
TEMP vertexClip;
DP4 vertexClip.x, state.matrix.mvp.row[0], vertex.position;
DP4 vertexClip.y, state.matrix.mvp.row[1], vertex.position;
DP4 vertexClip.z, state.matrix.mvp.row[2], vertex.position;
DP4 vertexClip.w, state.matrix.mvp.row[3], vertex.position;
MOV result.position, vertexClip;
MOV result.color, vertex.color;
MOV result.texcoord[0], vertex.texcoord;
MOV result.texcoord[1], vertex.normal;
END
};
# Black Light Fragment shader
my $fragProg = qq
{!!ARBfp1.0
TEMP decal,color;
TEX decal, fragment.texcoord[0], texture[0], 2D;
MUL result.color, decal, fragment.texcoord[1];
END
};
($idVertexProg,$idFragProg) = glGenProgramsARB_p(2);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, $idVertexProg);
glProgramStringARB_p(GL_VERTEX_PROGRAM_ARB, $vertexProg);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, $idFragProg);
glProgramStringARB_p(GL_FRAGMENT_PROGRAM_ARB, $fragProg);
}
# Terminate Vertex/Fragment Programs
sub termProgs
{
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
glDeleteProgramsARB_p($idVertexProg,$idFragProg);
}
# FBO Status handler
sub statusFBO
{
my $stat = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (!$stat || $stat == GL_FRAMEBUFFER_COMPLETE_EXT) {return;};
printf("FBO status: %04X\n", $stat);
exit(0);
}
# Initialize Framebuffers
sub initFBO
{
($idTexture) = glGenTextures_p(1);
($idFrameBuffer) = glGenFramebuffersEXT_p(1);
($idRenderBuffer) = glGenRenderbuffersEXT_p(1);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, $idFrameBuffer);
glBindTexture(GL_TEXTURE_2D, $idTexture);
glTexImage2D_c(GL_TEXTURE_2D, 0, GL_RGBA8, $textureWidth, $textureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, $idTexture, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, $idRenderBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24,
$textureWidth, $textureHeight);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, $idRenderBuffer);
statusFBO();
}
# FBO texture renderer
sub renderFBO
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, $idFrameBuffer);
glLoadIdentity();
glTranslated(-0.75, -0.85, -2.5);
glRotated($rotTeapotX, 1.0, 0.0, 0.0);
$rotTeapotX += .5;
glRotated($rotTeapotY, 0.0, 1.0, 0.0);
$rotTeapotY += 1.0;
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1.0, 1.0, 1.0);
glutWireTeapot(0.125);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
# Terminate FBO objects
sub termFBO
{
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteRenderbuffersEXT_p($idRenderBuffer);
glDeleteFramebuffersEXT_p($idFrameBuffer);
glDeleteTextures_p($idTexture);
}
# Resize Window
sub resizeScene
{ my($width,$height) = @_;
if (!$height){$height = 1;};
glViewport(0, 0, $width, $height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,$width/$height,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
$windowWidth = $width;
$windowHeight = $height;
}
# Initialize OpenGL Environment
sub init
{
checkVersion();
resizeScene($windowWidth, $windowHeight);
initFBO();
initProgs();
}
# Terminate OpenGL Environment
sub term
{
# Display benchmark
endBench($appBench);
printBench();
# Disable app
glutHideWindow();
glutKeyboardFunc(0);
glutSpecialFunc(0);
glutIdleFunc(0);
glutReshapeFunc(0);
# Release Framebuffers
termProgs();
termFBO();
# Now we can destroy window
glutDestroyWindow($idWindow);
exit(0);
}
# Frame handler
sub display
{
# Run benchmark CYCLES times
if (++$frames > CYCLES) {term();};
startBench($frameBench);
# Render animated texture
startBench($textureBench);
renderFBO();
endBench($textureBench);
# Set up ModelView
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-5.0);
glRotated(0.0,1.0,0.0,0.0);
glRotated($rotY,0.0,1.0,0.0);
$rotY += $incY;
# Set attributes
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
# Clear render buffer and set teapot color
glClearColor(0.2, 0.2, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0.9, 0.45, 0.0);
# Render the teapot using our shader
startBench($teapotBench);
glEnable(GL_VERTEX_PROGRAM_ARB);
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glutSolidTeapot(1.0);
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glDisable(GL_VERTEX_PROGRAM_ARB);
endBench($teapotBench);
# Double-buffer and done
glutSwapBuffers();
endBench($frameBench);
}
# Keyboard handler
sub keyPressed
{
term();
}
# Main app
glutInit(@ARGV);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA);
glutInitWindowSize($windowWidth,$windowHeight);
$idWindow = glutCreateWindow(PROGRAM);
glutDisplayFunc(\&display);
glutIdleFunc(\&display);
#glutReshapeFunc(\&resizeScene);
glutKeyboardFunc(\&keyPressed);
init();
startBench($appBench);
glutMainLoop();
exit(0);
|
Note: Perl OpenGL (POGL) has no OS-dependencies; as such, you'll notice a bit of whitespace
in the Perl code compared to C. POGL also provides additional Perl-ish OpenGL APIs
(suffixed with "_p") to simplify string and array handling.
While clearly there are differences between C and Perl, the similarities
make it relatively easy to port code between the two.
If you would like to add Java/Python/Ruby benchmarks to this comparison, please
send the POGL team your port.
Note:
As of this writing, Java OpenGL (JOGL) does not support FBOs, but rather
platform-specific pBuffers, which are known to have poorer
performance than FBOs.
This benchmark source and Win32/Linux binaries are available on this site
Review the README for build instructions.
|
|
|
|
|
|