1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
#!/usr/bin/perl
# Purpose: Simple demo of per-pixel lighting with GLSL and OpenGL::Shader
# Copyright (c) 2007, Geoff Broadwell; this script is released
# as open source and may be distributed and modified under the terms
# of either the Artistic License or the GNU General Public License,
# in the same manner as Perl itself. These licenses should have been
# distributed to you as part of your Perl distribution, and can be
# read using `perldoc perlartistic` and `perldoc perlgpl` respectively.
use strict;
use warnings;
use OpenGL ':all';
use OpenGL::Shader;
use Time::HiRes 'time';
our $VERSION = '0.1.0';
my $width = 1000;
my $height = 1000;
my ($frames, $start);
my ($window, $teapot);
my ($shader, $shader_enabled);
go();
sub go {
# Simple usage
print "Press 'Q' or 'Esc' to exit, or any other key to toggle shader.\n";
# GLUT setup
glutInit;
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize($width, $height);
$window = glutCreateWindow('Shader Test');
glutIdleFunc (\&cb_draw);
glutDisplayFunc (\&cb_draw);
glutKeyboardFunc(\&cb_keyboard);
# Shader program
$shader = new OpenGL::Shader('GLSL');
die "This program requires support for GLSL shaders.\n" unless $shader;
my $fragment = fragment_shader();
my $vertex = vertex_shader();
my $info = $shader->Load($fragment, $vertex);
print $info if $info;
toggle_shader();
# Display list for teapot
$teapot = glGenLists(1);
glNewList($teapot, GL_COMPILE);
glutSolidTeapot(1);
glEndList;
# Unchanging GL config
glViewport(0, 0, $width, $height);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(90, $width/$height, 1, 10);
glMatrixMode(GL_MODELVIEW);
glShadeModel(GL_SMOOTH);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv_p(GL_LIGHT0, GL_POSITION, 4, 4, 4, 1);
glMaterialfv_p(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 1, .7, .7, 1);
glMaterialfv_p(GL_FRONT_AND_BACK, GL_SPECULAR, 1, 1, 1, 1);
glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 50 );
# Actually start the test
$start = time;
glutMainLoop;
}
sub cb_draw {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glTranslatef(0, 0, -3);
my $slow_time = time / 5;
my $frac_time = $slow_time - int $slow_time;
my $angle = $frac_time * 360;
glRotatef($angle, 0, 1, 0);
glRotatef(30, 1, 0, 0);
glCallList($teapot);
glutSwapBuffers;
$frames++;
}
sub cb_keyboard {
my $key = shift;
my $chr = lc chr $key;
if ($key == 27 or $chr eq 'q') {
my $time = time - $start;
my $fps = $frames / $time;
printf "%.3f FPS\n", $fps;
glutDestroyWindow($window);
exit(0);
}
else {
toggle_shader();
}
}
sub toggle_shader {
$shader_enabled = !$shader_enabled;
$shader_enabled ? $shader->Enable : $shader->Disable;
}
sub vertex_shader {
return <<'VERTEX';
varying vec3 Normal;
varying vec3 Position;
void main(void) {
gl_Position = ftransform();
Position = vec3(gl_ModelViewMatrix * gl_Vertex);
Normal = gl_NormalMatrix * gl_Normal;
}
VERTEX
}
sub fragment_shader {
return <<'FRAGMENT';
varying vec3 Position;
varying vec3 Normal;
void main(void) {
vec3 normal = normalize(Normal);
vec3 reflected = normalize(reflect(Position, normal));
vec3 light_dir = normalize(vec3(gl_LightSource[0].position) - Position);
float diffuse = max (dot(light_dir, normal ), 0.0);
float spec = clamp(dot(light_dir, reflected), 0.0, 1.0);
spec = pow (spec, gl_FrontMaterial.shininess);
gl_FragColor = gl_FrontLightModelProduct.sceneColor
+ gl_FrontLightProduct[0].ambient
+ diffuse * gl_FrontLightProduct[0].diffuse
+ spec * gl_FrontLightProduct[0].specular;
}
FRAGMENT
}
|