#!/usr/bin/perl -w
our
$PERL_VERSION
= $^V;
$PERL_VERSION
=~ s|^v||;
:glconstants
glpHasGLUT glpCheckExtension
glGetString glGetError
glGenTextures_p glBindTexture glTexParameteri glTexImage2D_c glTexEnvf
glDeleteTextures_p
glGenerateMipmapEXT
glGenFramebuffersEXT_p glBindFramebufferEXT glFramebufferTexture2DEXT
glCheckFramebufferStatusEXT glDeleteFramebuffersEXT_p
glGenRenderbuffersEXT_p glBindRenderbufferEXT glRenderbufferStorageEXT
glDeleteRenderbuffersEXT_p
glFramebufferRenderbufferEXT
glGenBuffersARB_p glBindBufferARB glBufferDataARB_p glBufferSubDataARB_p
glMapBufferARB_c glUnmapBufferARB glDeleteBuffersARB_p
glVertexPointer_p glNormalPointer_p glColorPointer_p glTexCoordPointer_p
glEnableClientState glDisableClientState
glEnable glDisable glBlendFunc glDepthFunc glShadeModel
glMatrixMode glLoadIdentity glLightfv_p glColorMaterial
glTranslatef glRotatef
glColor3f glColor4f
glPushMatrix glPopMatrix glPushAttrib glPopAttrib
glOrtho
glRasterPos2i glRasterPos2f
glPixelZoom glReadPixels_c glDrawPixels_c
glGetDoublev_c glGetIntegerv_c
glClearColor glClearDepth glClear glViewport glDrawElements_c
/
;
:constants :functions
/
;
gluBuild2DMipmaps_c gluErrorString
gluOrtho2D gluProject_p gluUnProject_p gluPerspective
/
;
eval
'use OpenGL::Image 1.03'
;
my
$hasImage
= !$@;
my
$hasIM_635
=
$hasImage
&& OpenGL::Image::HasEngine(
'Magick'
,
'6.3.5'
);
eval
'use OpenGL::Shader'
;
my
$hasShader
= !$@;
eval
'use Image::Magick'
;
my
$hasIM
= !$@;
eval
'use Time::HiRes qw( gettimeofday )'
;
my
$hasHires
= !$@;
$|++;
if
(!glpHasGLUT())
{
print
<<'EOF';
This test requires GLUT:
If you have X installed, you can try the scripts in ./examples/
Most of them do not use GLUT.
It is recommended that you install FreeGLUT for improved Makefile.PL
configuration, installation and debugging.
EOF
exit
0;
}
use
constant
PROGRAM_TITLE
=>
"OpenGL Test App"
;
my
$gameMode
;
if
(
scalar
(
@ARGV
) and
lc
(
$ARGV
[0]) eq
'gamemode'
)
{
$gameMode
=
$ARGV
[1] ||
''
;
}
my
$key_mods
=
{
eval
(GLUT_ACTIVE_SHIFT) =>
"SHIFT"
,
eval
(GLUT_ACTIVE_CTRL) =>
"CTRL"
,
eval
(GLUT_ACTIVE_ALT) =>
"ALT"
};
my
$hasFBO
= 0;
my
$hasVBO
= 0;
my
$idleTime
=
$hasHires
? gettimeofday() :
time
();
my
$idleSecsMax
= 8;
my
$er
;
my
$Window_ID
;
my
$Window_Width
= 300;
my
$Window_Height
= 300;
my
$Inset_Width
= 90;
my
$Inset_Height
= 90;
my
$Window_State
;
my
$Tex_File
=
'test.tga'
;
my
$Tex_Width
= 128;
my
$Tex_Height
= 128;
my
$Tex_Format
;
my
$Tex_Type
;
my
$Tex_Size
;
my
$Tex_Image
;
my
$Tex_Pixels
;
my
$Light_On
= 0;
my
$Blend_On
= 1;
my
$Texture_On
= 1;
my
$Alpha_Add
= 1;
my
$FBO_On
= 0;
my
$Inset_On
= 1;
my
$Fullscreen_On
= 0;
my
$Curr_TexMode
= 0;
my
@TexModesStr
=
qw/ GL_DECAL GL_MODULATE GL_BLEND GL_REPLACE /
;
my
@TexModes
= ( GL_DECAL, GL_MODULATE, GL_BLEND, GL_REPLACE );
my
(
$TextureID_image
,
$TextureID_FBO
);
my
$FrameBufferID
;
my
$RenderBufferID
;
my
$VertexProgID
;
my
$FragProgID
;
my
$FBO_rendered
= 0;
my
$Shader
;
my
$Teapot_Rot
= 0.0;
my
$X_Rot
= 0.9;
my
$Y_Rot
= 0.0;
my
$X_Speed
= 0.0;
my
$Y_Speed
= 0.5;
my
$Z_Off
=-5.0;
my
@Light_Ambient
= ( 0.1, 0.1, 0.1, 1.0 );
my
@Light_Diffuse
= ( 1.2, 1.2, 1.2, 1.0 );
my
@Light_Position
= ( 2.0, 2.0, 0.0, 1.0 );
my
$mm
= OpenGL::Array->new(16,GL_DOUBLE);
my
$pm
= OpenGL::Array->new(16,GL_DOUBLE);
my
$tm
= OpenGL::Array->new(16,GL_DOUBLE);
my
$cm
= OpenGL::Array->new(16,GL_DOUBLE);
my
$vp
= OpenGL::Array->new(4,GL_INT);
my
(
$VertexObjID
,
$NormalObjID
,
$ColorObjID
,
$TexCoordObjID
,
$IndexObjID
,
$FpsVertObjID
,
$FpsNormObjID
,
$FpsColourObjID
,
$FpsIndObjID
);
my
@indices
= (
0,1,2, 2,3,0,
4,5,6, 6,7,4,
8,9,10, 10,11,8,
12,13,14, 14,15,12,
16,17,18, 18,19,16,
20,21,22, 22,23,20,
);
my
$indices
= OpenGL::Array->new_list(GL_UNSIGNED_INT,
@indices
);
my
@verts
=
(
-1.0, -1.3, -1.0,
1.0, -1.3, -1.0,
1.0, -1.3, 1.0,
-1.0, -1.3, 1.0,
-1.0, 1.3, -1.0,
-1.0, 1.3, 1.0,
1.0, 1.3, 1.0,
1.0, 1.3, -1.0,
-1.0, -1.0, -1.3,
-1.0, 1.0, -1.3,
1.0, 1.0, -1.3,
1.0, -1.0, -1.3,
1.3, -1.0, -1.0,
1.3, 1.0, -1.0,
1.3, 1.0, 1.0,
1.3, -1.0, 1.0,
-1.0, -1.0, 1.3,
1.0, -1.0, 1.3,
1.0, 1.0, 1.3,
-1.0, 1.0, 1.3,
-1.3, -1.0, -1.0,
-1.3, -1.0, 1.0,
-1.3, 1.0, 1.0,
-1.3, 1.0, -1.0,
);
my
$verts
= OpenGL::Array->new_list(GL_FLOAT,
@verts
);
my
@norms
=
(
0.0, -1.0, 0.0,
0.0, -1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0,-1.0,
0.0, 0.0,-1.0,
1.0, 0.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
-1.0, 0.0, 0.0,
-1.0, 0.0, 0.0,
);
my
$norms
= OpenGL::Array->new_list(GL_FLOAT,
@norms
);
my
@colors
=
(
0.9,0.2,0.2,.75,
0.9,0.2,0.2,.75,
0.9,0.2,0.2,.75,
0.9,0.2,0.2,.75,
0.5,0.5,0.5,.5,
0.5,0.5,0.5,.5,
0.5,0.5,0.5,.5,
0.5,0.5,0.5,.5,
0.2,0.9,0.2,.5,
0.2,0.9,0.2,.5,
0.2,0.9,0.2,.5,
0.2,0.9,0.2,.5,
0.2,0.2,0.9,.25,
0.2,0.2,0.9,.25,
0.2,0.2,0.9,.25,
0.2,0.2,0.9,.25,
0.9, 0.2, 0.2, 0.5,
0.2, 0.9, 0.2, 0.5,
0.2, 0.2, 0.9, 0.5,
0.1, 0.1, 0.1, 0.5,
0.9,0.9,0.2,0.0,
0.9,0.9,0.2,0.66,
0.9,0.9,0.2,1.0,
0.9,0.9,0.2,0.33,
);
my
$colors
= OpenGL::Array->new_list(GL_FLOAT,
@colors
);
my
@rainbow
=
(
0.9, 0.2, 0.2, 0.5,
0.2, 0.9, 0.2, 0.5,
0.2, 0.2, 0.9, 0.5,
0.1, 0.1, 0.1, 0.5,
);
my
$rainbow
= OpenGL::Array->new_list(GL_FLOAT,
@rainbow
);
my
$rainbow_offset
= 64;
my
@rainbow_inc
;
my
@texcoords
=
(
0.800, 0.800,
0.200, 0.800,
0.200, 0.200,
0.800, 0.200,
0.005, 1.995,
0.005, 0.005,
1.995, 0.005,
1.995, 1.995,
0.995, 0.005,
2.995, 2.995,
0.005, 0.995,
-1.995, -1.995,
0.995, 0.005,
0.995, 0.995,
0.005, 0.995,
0.005, 0.005,
-0.5, -0.5,
1.5, -0.5,
1.5, 1.5,
-0.5, 1.5,
0.005, 0.005,
0.995, 0.005,
0.995, 0.995,
0.005, 0.995,
);
my
$texcoords
= OpenGL::Array->new_list(GL_FLOAT,
@texcoords
);
my
@xform
=
(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
);
my
$xform
= OpenGL::Array->new_list(GL_FLOAT,
@xform
);
my
@fpsbox_coords
= (
0.0, -2.0, 0.0,
0.0, 12.0, 0.0,
140.0, 12.0, 0.0,
140.0, -2.0, 0.0,
);
my
$fpsbox_coords
= OpenGL::Array->new_list(GL_FLOAT,
@fpsbox_coords
);
my
@fpsbox_norms
= (
(0.0,0.0,1.0) x 2,
);
my
$fpsbox_norms
= OpenGL::Array->new_list(GL_FLOAT,
@fpsbox_norms
);
my
@fpsbox_colours
= (
(0.2,0.2,0.2,0.75) x 2,
);
my
$fpsbox_colours
= OpenGL::Array->new_list(GL_FLOAT,
@fpsbox_colours
);
my
@fpsbox_indices
= (
0,1,2, 2,3,0,
);
my
$fpsbox_indices
= OpenGL::Array->new_list(GL_UNSIGNED_INT,
@fpsbox_indices
);
use
constant
CLOCKS_PER_SEC
=>
$hasHires
? 1000 : 1;
my
$FrameCount
= 0;
my
$FrameRate
= 0;
my
$last
=0;
sub
ourDoFPS
{
if
(++
$FrameCount
>= FRAME_RATE_SAMPLES)
{
my
$now
=
$hasHires
? gettimeofday() :
time
();
my
$delta
= (
$now
-
$last
);
$last
=
$now
;
$FrameRate
= FRAME_RATE_SAMPLES / (
$delta
|| 1);
$FrameCount
= 0;
}
}
sub
ourPrintString
{
my
(
$font
,
$str
) =
@_
;
my
@c
=
split
''
,
$str
;
for
(
@c
)
{
glutBitmapCharacter(
$font
,
ord
$_
);
}
}
sub
ourInitVertexBuffers
{
@rainbow
=
map
[
map
rand
(1.0), 0..3], 0..3;
@rainbow
=
map
@$_
,
@rainbow
;
@rainbow_inc
=
map
[
map
0.01 -
rand
(0.02), 0..3], 0..3;
@rainbow_inc
=
map
@$_
,
@rainbow_inc
;
if
(
$hasVBO
)
{
printf
(
"Using VBOs\n"
);
(
$VertexObjID
,
$NormalObjID
,
$ColorObjID
,
$TexCoordObjID
,
$IndexObjID
,
$FpsVertObjID
,
$FpsNormObjID
,
$FpsColourObjID
,
$FpsIndObjID
) =
glGenBuffersARB_p(9);
$verts
->
bind
(
$VertexObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$verts
, GL_STATIC_DRAW_ARB);
if
(DO_TESTS)
{
print
"\nTests:\n"
;
my
$size
= glGetBufferParameterivARB_p(GL_ARRAY_BUFFER_ARB,
GL_BUFFER_SIZE_ARB);
print
" Vertex Buffer Size (bytes): $size\n"
;
my
$count
=
$verts
->elements();
print
" Vertex Buffer Size (elements): $count\n"
;
my
$test
= glGetBufferSubDataARB_p(GL_ARRAY_BUFFER_ARB,12,3,GL_FLOAT);
my
@test
=
$test
->retrieve(0,3);
my
$ords
=
join
(
'/'
,
@test
);
print
" glGetBufferSubDataARB_p: $ords\n"
;
}
$norms
->
bind
(
$NormalObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$norms
, GL_STATIC_DRAW_ARB);
$colors
->
bind
(
$ColorObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$colors
, GL_DYNAMIC_DRAW_ARB);
$rainbow
->assign(0,
@rainbow
);
glBufferSubDataARB_p(GL_ARRAY_BUFFER_ARB,
$rainbow_offset
,
$rainbow
);
$texcoords
->
bind
(
$TexCoordObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$texcoords
, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
$IndexObjID
);
glBufferDataARB_p(GL_ELEMENT_ARRAY_BUFFER_ARB,
$indices
, GL_STATIC_DRAW_ARB);
$fpsbox_coords
->
bind
(
$FpsVertObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$fpsbox_coords
, GL_STATIC_DRAW_ARB);
$fpsbox_norms
->
bind
(
$FpsNormObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$fpsbox_norms
, GL_STATIC_DRAW_ARB);
$fpsbox_colours
->
bind
(
$FpsColourObjID
);
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB,
$fpsbox_colours
, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
$FpsIndObjID
);
glBufferDataARB_p(GL_ELEMENT_ARRAY_BUFFER_ARB,
$fpsbox_indices
, GL_STATIC_DRAW_ARB);
}
else
{
print
"Using classic Vertex Buffers\n"
;
}
print
"-- done\n"
;
}
sub
ourInit
{
my
(
$Width
,
$Height
) =
@_
;
printf
(
"\nUsing POGL v$OpenGL::VERSION\n"
);
ourBuildTextures();
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
ourInitShaders();
ourInitVertexBuffers();
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glClearColor(0.1, 0.1, 0.1, 0.0);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);
cbResizeScene(
$Width
,
$Height
);
glLightfv_p(GL_LIGHT1, GL_POSITION,
@Light_Position
);
glLightfv_p(GL_LIGHT1, GL_AMBIENT,
@Light_Ambient
);
glLightfv_p(GL_LIGHT1, GL_DIFFUSE,
@Light_Diffuse
);
glEnable(GL_LIGHT1);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
sub
ourBuildTextures
{
my
$gluerr
;
my
$tex
;
(
$TextureID_image
,
$TextureID_FBO
) = glGenTextures_p(2);
if
(
$hasImage
&& -e
$Tex_File
)
{
my
$img
= OpenGL::Image->new(
source
=>
$Tex_File
);
die
$@
if
$@;
my
(
$eng
,
$ver
) =
$img
->Get(
'engine'
,
'version'
);
print
"Using OpenGL::Image - $eng v$ver\n"
;
(
$Tex_Width
,
$Tex_Height
) =
$img
->Get(
'width'
,
'height'
);
my
$alpha
=
$img
->Get(
'alpha'
) ?
'has'
:
'no'
;
print
"Loading texture: $Tex_File, $Tex_Width x $Tex_Height, $alpha alpha\n"
;
(
$Tex_Type
,
$Tex_Format
,
$Tex_Size
) =
$img
->Get(
'gl_internalformat'
,
'gl_format'
,
'gl_type'
);
$Tex_Image
=
$img
;
$Tex_Pixels
=
$img
->GetArray();
print
"Using ImageMagick's gaussian blur on inset\n"
if
(
$hasIM_635
);
}
else
{
my
$hole_size
=
int
((
$Tex_Width
/ 2.2) ** 2);
my
$hole_border
=
int
(
$hole_size
/30);
my
$w_2
=
$Tex_Width
/2;
my
$w_4
=
$Tex_Width
/4;
my
$w_16
=
$Tex_Width
/16;
my
$w_32
=
$Tex_Width
/32;
for
(
my
$y
=0;
$y
<
$Tex_Height
;
$y
++)
{
for
(
my
$x
=0;
$x
<
$Tex_Width
;
$x
++)
{
if
( ( (
$x
+
$w_32
)
%$w_4
<
$w_16
) && ( (
$y
+
$w_32
)
%$w_4
<
$w_16
))
{
$tex
.=
pack
"C3"
, 0,0,120;
}
else
{
$tex
.=
pack
"C3"
, 240, 240, 240;
}
my
$t
= (
$x
-
$w_2
)*(
$x
-
$w_2
) + (
$y
-
$w_2
)*(
$y
-
$w_2
);
if
(
$t
<
$hole_size
)
{
$tex
.=
pack
"C"
, 255;
}
elsif
(
$t
<
$hole_size
+
$hole_border
)
{
$tex
.=
pack
"C"
, 128;
}
else
{
$tex
.=
pack
"C"
, 0;
}
}
}
$Tex_Pixels
= OpenGL::Array->new_scalar(GL_UNSIGNED_BYTE,
$tex
,
length
(
$tex
));
$Tex_Type
= GL_RGBA8;
$Tex_Format
= GL_RGBA;
$Tex_Size
= GL_UNSIGNED_BYTE;
}
glBindTexture(GL_TEXTURE_2D,
$TextureID_image
);
print
"Using Mipmap\n"
;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST_MIPMAP_LINEAR);
if
((
$gluerr
= gluBuild2DMipmaps_c(GL_TEXTURE_2D,
$Tex_Type
,
$Tex_Width
,
$Tex_Height
,
$Tex_Format
,
$Tex_Size
,
$Tex_Pixels
->ptr())))
{
die
sprintf
"GLULib%s\n"
, gluErrorString(
$gluerr
);
}
if
(DO_TESTS &&
$hasIM
)
{
my
$loops
= 1000;
my
$im
= Image::Magick->new();
$im
->Read(
$Tex_File
);
$im
->Set(
magick
=>
'RGBA'
,
depth
=>8);
$im
->Negate(
channel
=>
'alpha'
);
my
$start
= gettimeofday();
for
(
my
$i
=0;
$i
<
$loops
;
$i
++)
{
my
(
$blob
) =
$im
->ImageToBlob();
glTexImage2D_s(GL_TEXTURE_2D, 0, GL_RGBA8,
$Tex_Width
,
$Tex_Height
,
0, GL_RGBA, GL_UNSIGNED_BYTE,
$blob
);
}
my
$now
= gettimeofday();
my
$fps
=
$loops
/ (
$now
-
$start
);
print
"ImageToBlob + glTexImage2D_s: $fps\n"
;
$start
= gettimeofday();
for
(
my
$i
=0;
$i
<
$loops
;
$i
++)
{
my
@pixels
=
$im
->GetPixels(
map
=>
'BGRA'
,
width
=>
$Tex_Width
,
height
=>
$Tex_Height
,
normalize
=>
'false'
);
glTexImage2D_p(GL_TEXTURE_2D, 0,
$Tex_Type
,
$Tex_Width
,
$Tex_Height
,
0,
$Tex_Format
,
$Tex_Size
,
@pixels
);
}
$now
= gettimeofday();
$fps
=
$loops
/ (
$now
-
$start
);
print
"GetPixels + glTexImage2D_p: $fps\n"
;
if
(
$hasIM_635
)
{
my
$start
= gettimeofday();
for
(
my
$i
=0;
$i
<
$loops
;
$i
++)
{
glTexImage2D_c(GL_TEXTURE_2D, 0,
$Tex_Type
,
$Tex_Width
,
$Tex_Height
,
0,
$Tex_Format
,
$Tex_Size
,
$Tex_Pixels
->ptr());
}
my
$now
= gettimeofday();
my
$fps
=
$loops
/ (
$now
-
$start
);
print
"OpenGL::Image + glTexImage2D_c: $fps\n"
;
}
}
if
(
$hasFBO
)
{
printf
(
"Using FBOs\n"
);
(
$FrameBufferID
) = glGenFramebuffersEXT_p(1);
(
$RenderBufferID
) = glGenRenderbuffersEXT_p(1);
glBindTexture(GL_TEXTURE_2D,
$TextureID_FBO
);
glTexImage2D_c(GL_TEXTURE_2D, 0,
$Tex_Type
,
$Tex_Width
,
$Tex_Height
,
0,
$Tex_Format
,
$Tex_Size
, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glGenerateMipmapEXT(GL_TEXTURE_2D);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
$FrameBufferID
);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,
$TextureID_FBO
, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
$RenderBufferID
);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB,
$Tex_Width
,
$Tex_Height
);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT,
$RenderBufferID
);
my
$stat
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
die
"FBO Status error: "
. gluErrorString(glGetError())
if
!
$stat
;
die
sprintf
"FBO Status: %04X"
,
$stat
if
$stat
!= GL_FRAMEBUFFER_COMPLETE_EXT;
}
ourSelectTexture();
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
}
sub
ourSelectTexture
{
glBindTexture(GL_TEXTURE_2D,
$FBO_On
?
$TextureID_FBO
:
$TextureID_image
);
}
my
%ext2shaders
= (
arb
=> [
<<'EOF',
!!ARBfp1.0
PARAM surfacecolor = program.local[5];
TEMP color;
MUL color, fragment.texcoord[0].y, 2.0;
ADD color, 1.0, -color;
ABS color, color;
ADD color, 1.01, -color; # Some cards have a rounding error
MOV color.a, 1.0;
MUL color, color, surfacecolor;
MOV result.color, color;
END
EOF
<<'EOF',
!!ARBvp1.0
PARAM center = program.local[0];
PARAM xform[4] = {program.local[1..4]};
TEMP vertexClip;
# ModelView projection
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;
# Additional transform, via matrix variable
DP4 vertexClip.x, vertexClip, xform[0];
DP4 vertexClip.y, vertexClip, xform[1];
DP4 vertexClip.z, vertexClip, xform[2];
DP4 vertexClip.w, vertexClip, xform[3];
#SUB result.position, vertexClip, center;
MOV result.position, vertexClip;
# Pass through color
MOV result.color, vertex.color;
# Pass through texcoords
SUB result.texcoord[0], vertex.texcoord, center;
END
EOF
],
glsl
=> [
<<'EOF',
uniform vec4 surfacecolor;
void main (void) {
float v = 2.0 * gl_TexCoord[0].y;
v = 1.01 - abs(1.0 - v); // Some cards have a rounding error
gl_FragColor = vec4(v,v,v, 1.0) * surfacecolor;
}
EOF
<<'EOF',
uniform vec4 center;
uniform mat4 xform;
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position *= xform;
// Calc texcoord values
vec4 pos = gl_Vertex;
float d = sqrt(pos.x * pos.x + pos.y * pos.y);
float a = atan(pos.x/pos.y) / 3.1415;
if (a < 0.0) a += 1.0;
a *= 2.0;
a -= float(int(a));
pos -= center;
float h = pos.z;
h = abs(2.0 * atan(h/d) / 3.1415);
gl_TexCoord[0].x = a;
gl_TexCoord[0].y = h;
}
EOF
],
);
sub
ourInitShaders
{
if
(
$hasShader
) {
my
$version
=
$OpenGL::Shader::VERSION
;
printf
(
"Using OpenGL::Shader v$version\n"
);
my
$types
= OpenGL::Shader->GetTypes();
my
@types
=
keys
(
%$types
);
printf
(
"This installation supports the following shader types: %s\n"
,
join
(
','
,
@types
));
$Shader
= OpenGL::Shader->new();
if
(!
$Shader
) {
printf
(
"Unable to instantiate OpenGL::Shader\n"
);
return
;
}
my
$type
=
$Shader
->GetType();
my
$ext
=
lc
(
$type
);
my
$shaders
=
$ext2shaders
{
$ext
};
my
$stat
= !
$shaders
?
"Shader: unknown extension '$ext'"
:
$Shader
->Load(
@$shaders
);
if
(!
$stat
) {
my
$ver
=
$Shader
->GetVersion();
print
"Using OpenGL::Shader('$type') v$ver\n"
;
return
;
}
else
{
print
"$stat\n"
;
}
}
}
sub
cbRenderScene
{
my
$time
=
$hasHires
? gettimeofday() :
time
();
my
$time_to_exit
=
$idleSecsMax
- (
$time
-
$idleTime
);
if
(
$time_to_exit
<= 0 )
{
print
"Idle timeout; completing test\n"
;
ourCleanup();
return
quit(
"render callback"
);
}
my
$buf
;
if
(
$FBO_On
&& (
$FBO_On
== 2 || !
$FBO_rendered
))
{
$FBO_rendered
= 1;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
$FrameBufferID
);
glViewport(0, 0,
$Tex_Width
,
$Tex_Height
);
glPushMatrix();
glTranslatef(0, 0, -1.5);
glRotatef(
$Teapot_Rot
--, 0.0, 1.0, 0.0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_DEPTH_TEST);
if
(
$Shader
) {
$Shader
->Enable();
$Shader
->SetVector(
'center'
,0.0,0.0,2.0,0.0);
$Shader
->SetMatrix(
'xform'
,
$xform
);
$Shader
->SetVector(
'surfacecolor'
,1.0,0.5,0.0,1.0);
}
glColor3f(1.0, 1.0, 1.0);
glutWireTeapot(0.25);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D,
$TextureID_FBO
);
glGenerateMipmapEXT(GL_TEXTURE_2D);
if
(
$Shader
) {
$Shader
->Disable();
}
glPopAttrib();
glPopMatrix();
}
ourSelectTexture();
if
(
$Texture_On
) {
glEnable(GL_TEXTURE_2D);
}
else
{
glDisable(GL_TEXTURE_2D);
}
if
(
$Light_On
) {
glEnable(GL_LIGHTING);
}
else
{
glDisable(GL_LIGHTING);
}
if
(
$Alpha_Add
) {
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
}
else
{
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
if
(
$Blend_On
) {
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
}
else
{
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,
$Z_Off
);
glRotatef(
$X_Rot
,1.0,0.0,0.0);
glRotatef(
$Y_Rot
,0.0,1.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for
(
my
$i
=0;
$i
<
scalar
(
@rainbow
);
$i
++) {
$rainbow
[
$i
] +=
$rainbow_inc
[
$i
];
if
(
$rainbow
[
$i
] < 0) {
$rainbow
[
$i
] = 0.0;
}
elsif
(
$rainbow
[
$i
] > 1) {
$rainbow
[
$i
] = 1.0;
}
else
{
next
;
}
$rainbow_inc
[
$i
] = -
$rainbow_inc
[
$i
];
}
if
(
$hasVBO
) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB,
$ColorObjID
);
glMapBufferARB_c(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
$colors
->assign(
$rainbow_offset
,
@rainbow
);
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
}
else
{
$colors
->assign(
$rainbow_offset
,
@rainbow
);
}
glColorPointer_p(4,
$colors
);
glViewport(0, 0,
$Window_Width
,
$Window_Height
);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer_p(3,
$verts
);
glNormalPointer_p(
$norms
);
glTexCoordPointer_p(2,
$texcoords
);
if
(
$hasVBO
) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
$IndexObjID
);
}
glDrawElements_c(GL_TRIANGLES,
scalar
(
@indices
), GL_UNSIGNED_INT,
$hasVBO
? 0 :
$indices
->ptr);
if
(
$hasVBO
) {
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,
$Window_Width
,0,
$Window_Height
,-1.0,1.0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glColor4f(0.6,1.0,0.6,.75);
$buf
=
sprintf
"TIME TO EXIT: %.1fs"
,
$time_to_exit
;
my
$bufwidth
= 6 *
length
$buf
;
glRasterPos2i(
$Window_Width
-4-
$bufwidth
,2); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Mode: %s"
,
$TexModesStr
[
$Curr_TexMode
];
glRasterPos2i(2,2); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Alpha: %d"
,
$Alpha_Add
;
glRasterPos2i(2,14); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Blend: %d"
,
$Blend_On
;
glRasterPos2i(2,26); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Light: %d"
,
$Light_On
;
glRasterPos2i(2,38); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Tex: %d"
,
$Texture_On
;
glRasterPos2i(2,50); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"FBO: %d"
,
$FBO_On
;
glRasterPos2i(2,62); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
$buf
=
sprintf
"Inset: %d"
,
$Inset_On
;
glRasterPos2i(2,74); ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
glTranslatef(6.0,
$Window_Height
- 14,0.0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer_p(3,
$fpsbox_coords
);
glNormalPointer_p(
$fpsbox_norms
);
glColorPointer_p(4,
$fpsbox_colours
);
if
(
$hasVBO
) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
$FpsIndObjID
);
}
glDrawElements_c(GL_TRIANGLES,
scalar
(
@fpsbox_indices
), GL_UNSIGNED_INT,
$hasVBO
? 0 :
$fpsbox_indices
->ptr);
if
(
$hasVBO
) {
glBindBufferARB(GL_ARRAY_BUFFER, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glColor4f(0.9,0.2,0.2,.75);
$buf
=
sprintf
"FPS: %f F: %2d"
,
$FrameRate
,
$FrameCount
;
glRasterPos2i(6,0);
ourPrintString(GLUT_BITMAP_HELVETICA_12,
$buf
);
glPopMatrix();
Capture(
Inset
=>1)
if
(
$Inset_On
);
glutSwapBuffers();
$X_Rot
+=
$X_Speed
;
$Y_Rot
+=
$Y_Speed
;
ourDoFPS();
}
sub
Capture
{
my
(
%params
) =
@_
;
my
(
$w
) = glutGet( GLUT_WINDOW_WIDTH );
my
(
$h
) = glutGet( GLUT_WINDOW_HEIGHT );
glPushAttrib( GL_ENABLE_BIT | GL_VIEWPORT_BIT |
GL_TRANSFORM_BIT | GL_COLOR_BUFFER_BIT);
glDisable( GL_LIGHTING );
glDisable( GL_FOG );
glDisable( GL_TEXTURE_2D );
glDisable( GL_DEPTH_TEST );
glDisable( GL_CULL_FACE );
glDisable( GL_STENCIL_TEST );
glViewport( 0, 0,
$w
,
$h
);
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
eval
{ gluOrtho2D( 0,
$w
, 0,
$h
); 1 } or
$er
++ or
warn
"Catched: $@"
;
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glPixelZoom( 1, 1 );
if
(
$params
{Save})
{
Save(
$w
,
$h
,
$params
{Save});
}
elsif
(
$params
{Inset})
{
Inset(
$w
,
$h
);
}
glMatrixMode( GL_PROJECTION );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glPopAttrib();
}
sub
Inset
{
my
(
$w
,
$h
) =
@_
;
my
$Capture_X
=
int
((
$w
-
$Inset_Width
) / 2);
my
$Capture_Y
=
int
((
$h
-
$Inset_Height
) / 2);
my
$Inset_X
=
$w
- (
$Inset_Width
+ 2);
my
$Inset_Y
=
$h
- (
$Inset_Height
+ 2);
if
(
$hasIM_635
)
{
my
$frame
= OpenGL::Image->new(
engine
=>
'Magick'
,
width
=>
$Inset_Width
,
height
=>
$Inset_Height
);
die
$@
if
$@;
my
(
$fmt
,
$size
) =
$frame
->Get(
'gl_format'
,
'gl_type'
);
glReadPixels_c(
$Capture_X
,
$Capture_Y
,
$Inset_Width
,
$Inset_Height
,
$fmt
,
$size
,
$frame
->Ptr() );
$frame
->Sync();
$frame
->Native->Blur(
radius
=>2,
sigma
=>2);
$frame
->SyncOGA();
glRasterPos2f(
$Inset_X
,
$Inset_Y
);
glDrawPixels_c(
$Inset_Width
,
$Inset_Height
,
$fmt
,
$size
,
$frame
->Ptr() );
}
else
{
my
$len
=
$Inset_Width
*
$Inset_Height
* 4;
my
$oga
= OpenGL::Array->new(
$len
,GL_UNSIGNED_BYTE);
glReadPixels_c(
$Capture_X
,
$Capture_Y
,
$Inset_Width
,
$Inset_Height
,
GL_RGBA, GL_UNSIGNED_BYTE,
$oga
->ptr() );
glRasterPos2f(
$Inset_X
,
$Inset_Y
);
glDrawPixels_c(
$Inset_Width
,
$Inset_Height
, GL_RGBA, GL_UNSIGNED_BYTE,
$oga
->ptr() );
}
}
sub
Save
{
my
(
$w
,
$h
,
$file
) =
@_
;
if
(
$hasImage
)
{
my
$frame
= OpenGL::Image->new(
width
=>
$w
,
height
=>
$h
);
my
(
$fmt
,
$size
) =
$frame
->Get(
'gl_format'
,
'gl_type'
);
glReadPixels_c( 0, 0,
$w
,
$h
,
$fmt
,
$size
,
$frame
->Ptr() );
$frame
->Save(
$file
);
}
else
{
print
"Need OpenGL::Image and ImageMagick 6.3.5 or newer for file capture!\n"
;
}
}
sub
ourCleanup {
print
"Starting cleanup ...\n"
;
glutHideWindow();
glutKeyboardUpFunc();
glutKeyboardFunc();
glutSpecialUpFunc();
glutSpecialFunc();
glutIdleFunc();
glutReshapeFunc();
glutCloseFunc()
if
OpenGL::_have_freeglut();
ReleaseResources();
if
(
defined
(
$gameMode
)) {
print
"Leaving game mode.\n"
;
glutLeaveGameMode();
}
else
{
print
"Destroying window.\n"
;
glutDestroyWindow(
$Window_ID
);
}
undef
(
$Window_ID
);
print
"Cleanup completed.\n"
;
}
sub
ReleaseResources {
return
if
!
defined
$Window_ID
;
if
(
$hasFBO
) {
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
glDeleteRenderbuffersEXT_p(
$RenderBufferID
)
if
$RenderBufferID
;
glDeleteFramebuffersEXT_p(
$FrameBufferID
)
if
$FrameBufferID
;
}
if
(
$Shader
) {
undef
(
$Shader
);
}
if
(
$hasVBO
) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB_p(
$VertexObjID
)
if
$VertexObjID
;
glDeleteBuffersARB_p(
$NormalObjID
)
if
$NormalObjID
;
glDeleteBuffersARB_p(
$ColorObjID
)
if
$ColorObjID
;
glDeleteBuffersARB_p(
$TexCoordObjID
)
if
$TexCoordObjID
;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glDeleteBuffersARB_p(
$IndexObjID
)
if
$IndexObjID
;
}
glDeleteTextures_p(
$TextureID_image
,
$TextureID_FBO
);
}
sub
cbKeyPressed
{
my
$key
=
shift
;
my
$c
=
uc
chr
$key
;
if
(
$key
== 27 or
$c
eq
'Q'
)
{
ourCleanup();
return
quit(
"key press callback"
);
}
elsif
(
$c
eq
'B'
)
{
$Blend_On
= !
$Blend_On
;
}
elsif
(
$c
eq
'K'
)
{
glutLeaveMainLoop()
if
OpenGL::_have_freeglut();
}
elsif
(
$c
eq
'L'
)
{
$Light_On
= !
$Light_On
;
}
elsif
(
$c
eq
'M'
)
{
if
( ++
$Curr_TexMode
> 3 )
{
$Curr_TexMode
=0;
}
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,
$TexModes
[
$Curr_TexMode
]);
}
elsif
(
$c
eq
'T'
)
{
$Texture_On
= !
$Texture_On
;
}
elsif
(
$c
eq
'A'
)
{
$Alpha_Add
= !
$Alpha_Add
;
}
elsif
(
$c
eq
'F'
&&
$hasFBO
)
{
$FBO_On
= (
$FBO_On
+1) % 3;
ourSelectTexture();
}
elsif
(
$c
eq
'I'
)
{
$Inset_On
= !
$Inset_On
;
}
elsif
(
$c
eq
'S'
or
$key
== 32)
{
$X_Speed
=
$Y_Speed
=0;
}
elsif
(
$c
eq
'R'
)
{
$X_Speed
= -
$X_Speed
;
$Y_Speed
= -
$Y_Speed
;
}
elsif
(
$c
eq
'G'
)
{
$Fullscreen_On
= !
$Fullscreen_On
;
if
(
$Fullscreen_On
)
{
$Window_State
= glpFullScreen();
$Window_Width
=
$Window_State
->{w};
$Window_Height
=
$Window_State
->{h};
}
else
{
glpRestoreScreen(
$Window_State
);
}
}
elsif
(
$c
eq
'C'
&&
$hasImage
)
{
Capture(
Save
=>
'capture.tga'
);
}
elsif
(
$c
eq
'W'
)
{
$Z_Off
+= 0.5;
}
elsif
(
$c
eq
'X'
)
{
$Z_Off
-= 0.5;
}
else
{
printf
"KP: No action for %d.\n"
,
$key
;
}
$idleTime
=
$hasHires
? gettimeofday() :
time
();
}
sub
cbSpecialKeyPressed
{
my
$key
=
shift
;
if
(
$key
== GLUT_KEY_PAGE_UP)
{
$Z_Off
-= 0.05;
}
elsif
(
$key
== GLUT_KEY_PAGE_DOWN)
{
$Z_Off
+= 0.05;
}
elsif
(
$key
== GLUT_KEY_UP)
{
$X_Speed
-= 0.01;
}
elsif
(
$key
== GLUT_KEY_DOWN)
{
$X_Speed
+= 0.01;
}
elsif
(
$key
== GLUT_KEY_LEFT)
{
$Y_Speed
-= 0.01;
}
elsif
(
$key
== GLUT_KEY_RIGHT)
{
$Y_Speed
+= 0.01;
}
else
{
printf
"SKP: No action for %d.\n"
,
$key
;
}
$idleTime
=
$hasHires
? gettimeofday() :
time
();
}
sub
cbKeyUp
{
my
(
$key
) =
@_
;
my
$mod
= GetKeyModifier();
print
"Key up: $key w/ $mod\n"
if
(
$mod
);
}
sub
cbSpecialKeyUp
{
my
(
$key
) =
@_
;
my
$mod
= GetKeyModifier();
print
"Special Key up: $key w/ $mod\n"
if
(
$mod
);
}
sub
cbMouseClick
{
my
(
$button
,
$state
,
$x
,
$y
) =
@_
;
if
(
$button
== GLUT_LEFT_BUTTON)
{
print
"Left"
;
}
elsif
(
$button
== GLUT_MIDDLE_BUTTON)
{
print
"Middle"
;
}
elsif
(
$button
== GLUT_RIGHT_BUTTON)
{
print
"Right"
;
}
else
{
print
"Unknown"
;
}
print
" mouse button, "
;
if
(
$state
== GLUT_DOWN)
{
print
"DOWN"
;
}
elsif
(
$state
== GLUT_UP)
{
print
"UP"
;
}
else
{
print
"State UNKNOWN"
;
}
my
$mod
= GetKeyModifier();
print
" w/ $mod"
if
(
$mod
);
print
": $x, $y\n"
;
if
(
$state
== GLUT_UP)
{
my
(
$model
,
$projection
,
$viewport
) = dumpMatrices();
my
@point
= gluUnProject_p(
$x
,
$y
,0,
@$model
,
@$projection
,
@$viewport
);
print
"Model point: $point[0], $point[1], $point[2]\n"
;
print
"\n"
;
}
$idleTime
=
$hasHires
? gettimeofday() :
time
();
}
sub
dumpMatrices
{
print
"\n"
;
glGetDoublev_c(GL_MODELVIEW_MATRIX,
$mm
->ptr());
my
@model
=
$mm
->retrieve(0,16);
glGetDoublev_c(GL_PROJECTION_MATRIX,
$pm
->ptr());
my
@projection
=
$pm
->retrieve(0,16);
glGetDoublev_c(GL_PROJECTION_MATRIX,
$tm
->ptr());
my
@texture
=
$tm
->retrieve(0,16);
glGetDoublev_c(GL_PROJECTION_MATRIX,
$cm
->ptr());
my
@colours
=
$cm
->retrieve(0,16);
for
([
'Model'
,\
@model
], [
'Projection'
,\
@projection
], [
'Texture'
,\
@texture
], [
'Colour'
,\
@colours
]) {
printf
"%-19s$_->[1][0], $_->[1][1], $_->[1][2], $_->[1][3]\n"
,
"$_->[0] Matrix:"
;
print
" $_->[1][4], $_->[1][5], $_->[1][6], $_->[1][7]\n"
;
print
" $_->[1][8], $_->[1][9], $_->[1][10], $_->[1][11]\n"
;
print
" $_->[1][12], $_->[1][13], $_->[1][14], $_->[1][15]\n"
;
}
glGetIntegerv_c(GL_VIEWPORT,
$vp
->ptr());
my
@viewport
=
$vp
->retrieve(0,4);
print
"Viewport: $viewport[0], $viewport[1], $viewport[2], $viewport[3]\n"
;
print
"\n"
;
(\
@model
, \
@projection
, \
@viewport
);
}
sub
GetKeyModifier
{
return
$key_mods
->{glutGetModifiers()};
}
sub
cbResizeScene
{
my
(
$Width
,
$Height
) =
@_
;
$Height
= 1
if
(
$Height
== 0);
glViewport(0, 0,
$Width
,
$Height
);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0,
$Width
/
$Height
,0.1,100.0);
glMatrixMode(GL_MODELVIEW);
$Window_Width
=
$Width
;
$Window_Height
=
$Height
;
$idleTime
=
$hasHires
? gettimeofday() :
time
();
}
sub
cbWindowStat
{
my
(
$stat
) =
@_
;
print
"Window status: $stat\n"
;
}
sub
cbClose
{
my
(
$wid
) =
@_
;
print
"User has closed window: \#$wid\n"
;
ReleaseResources();
}
sub
quit {
my
(
$context
) =
@_
;
$context
||=
"<unknown context>"
;
print
"Exiting in $context using "
;
if
(OpenGL::_have_freeglut()) {
print
"glutLeaveMainLoop (freeglut)\n"
;
glutLeaveMainLoop();
return
;
}
print
"perl exit(0)\n"
;
exit
(0);
}
glutInit();
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);
if
($^O ne
'MSWin32'
and
$OpenGL::Config
->{DEFINE} !~ /-DHAVE_W32API/) {
if
(not glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
{
warn
"glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA) not possible"
;
warn
"...trying without GLUT_ALPHA"
;
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
if
(not glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
{
warn
"glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) not possible, exiting quietly"
;
exit
0;
}
}
}
if
(
defined
(
$gameMode
) && glutGameModeString(
$gameMode
))
{
print
"Running in Game Mode $gameMode\n"
;
glutGameModeString(
$gameMode
);
$Window_ID
= glutEnterGameMode();
$Window_Width
= glutGameModeGet( GLUT_GAME_MODE_WIDTH );
$Window_Height
= glutGameModeGet( GLUT_GAME_MODE_HEIGHT );
}
else
{
glutInitWindowSize(
$Window_Width
,
$Window_Height
);
$Window_ID
= glutCreateWindow( PROGRAM_TITLE );
}
print
"\n"
;
print
PROGRAM_TITLE;
print
' (using hires timer)'
if
(
$hasHires
);
print
"\n\n"
;
my
$version
= glGetString(GL_VERSION);
my
$vendor
= glGetString(GL_VENDOR);
my
$renderer
= glGetString(GL_RENDERER);
print
"Using POGL v$OpenGL::BUILD_VERSION\n"
;
print
"OpenGL installation: $version\n$vendor\n$renderer\n\n"
;
print
"Installed extensions (* implemented in the module):\n"
;
my
$extensions
= glGetString(GL_EXTENSIONS);
my
@extensions
=
split
(
' '
,
$extensions
);
foreach
my
$ext
(
sort
@extensions
)
{
my
$stat
= glpCheckExtension(
$ext
);
printf
(
"%s $ext\n"
,
$stat
?
' '
:
'*'
);
print
(
" $stat\n"
)
if
(
$stat
&&
$stat
!~ m|^
$ext
|);
}
if
(!OpenGL::glpCheckExtension(
'GL_ARB_vertex_buffer_object'
)) {
$hasVBO
= (
$PERL_VERSION
!~ m|^5\.10\.|);
}
if
(!OpenGL::glpCheckExtension(
'GL_EXT_framebuffer_object'
)) {
$hasFBO
= 1;
$FBO_On
= 1;
if
(!OpenGL::glpCheckExtension(
'GL_ARB_fragment_program'
)) {
$FBO_On
++;
}
}
glutDisplayFunc(\
&cbRenderScene
);
glutIdleFunc(\
&cbRenderScene
);
glutReshapeFunc(\
&cbResizeScene
);
glutKeyboardFunc(\
&cbKeyPressed
);
glutSpecialFunc(\
&cbSpecialKeyPressed
);
glutKeyboardUpFunc(\
&cbKeyUp
);
glutSpecialUpFunc(\
&cbSpecialKeyUp
);
glutMouseFunc(\
&cbMouseClick
);
glutCloseFunc(\
&cbClose
)
if
OpenGL::_have_freeglut();
ourInit(
$Window_Width
,
$Window_Height
);
print
qq
{
Hold down arrow
keys
to rotate,
'r'
to
reverse
,
's'
to stop.
Page up/down will move cube away from/towards camera.
Use first letter of shown display mode settings to alter.
Press
'g'
to toggle fullscreen mode (not supported on all platforms).
Press
'c'
to capture/save a RGBA targa file.
'q'
or [Esc] to quit; OpenGL window must have focus
for
input.
};
if
(OpenGL::_have_freeglut()) {
print
"Setting window close to trigger return from mainloop (freeglut).\n"
;
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS)
}
print
"Entering glutMainLoop\n"
;
glutMainLoop();
print
"Returned from glutMainLoop\n"
;
print
"Exiting in main thread\n"
;
if
($^O ne
'MSWin32'
) {
my
$errors
=
''
;
while
((
my
$err
= glGetError()) != 0) {
$errors
.=
"glError: "
. gluErrorString(
$err
) .
"\n"
;
}
die
$errors
if
$errors
;
}