#!/usr/bin/perl
my
@vertices
= ( -0.6, -0.4, 1.0, 0.0, 0.0,
0.6, -0.4, 0.0, 1.0, 0.0,
0.0, 0.6, 0.0, 0.0, 1.0 );
my
@vertex_shader_text
= (
"uniform mat4 MVP;\n"
,
"attribute vec3 vCol;\n"
,
"attribute vec2 vPos;\n"
,
"varying vec3 color;\n"
,
"void main()\n"
,
"{\n"
,
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
,
" color = vCol;\n"
,
"}\n"
);
my
@fragment_shader_text
= (
"varying vec3 color;\n"
,
"void main()\n"
,
"{\n"
,
" gl_FragColor = vec4(color, 1.0);\n"
,
"}\n"
,
);
my
$drop_callback
=
sub
{
my
(
$window
,
@paths
) =
@_
;
print
"Dropped (@paths)\n"
;
};
my
$cursorenter_callback
=
sub
{
my
(
$window
,
$entered
) =
@_
;
printf
STDERR
"CursorEnter callback: "
. (
$entered
?
"entered"
:
"left"
) .
" window\n"
;
};
my
$cursorpos_callback
=
sub
{
my
(
$window
,
$xpos
,
$ypos
) =
@_
;
printf
STDERR
"CursorPos callback: cursor at ($xpos,$ypos)\n"
;
};
my
$char_callback
=
sub
{
my
(
$window
,
$codepoint
) =
@_
;
printf
STDERR
"Char callback: got codepoint=$codepoint\n"
;
};
my
$charmods_callback
=
sub
{
my
(
$window
,
$codepoint
,
$mods
) =
@_
;
printf
STDERR
"CharMods callback: got codepoint=$codepoint, mods=$mods\n"
;
};
my
$error_callback
=
sub
{
my
(
$error
,
$description
) =
@_
;
printf
STDERR
"Error #%d from perl: %s\n"
,
$error
,
$description
;
};
my
$framebuffersize_callback
=
sub
{
my
(
$window
,
$width
,
$height
) =
@_
;
printf
STDERR
"FrameBufferSize callback: (w,h) = ($width,$height)\n"
;
};
my
$key_callback
=
sub
{
my
(
$window
,
$key
,
$scancode
,
$action
,
$mods
) =
@_
;
if
(
$key
== GLFW_KEY_ESCAPE &&
$action
== GLFW_PRESS) {
glfwSetWindowShouldClose(
$window
, GLFW_TRUE);
}
};
my
$mousebutton_callback
=
sub
{
my
(
$window
,
$button
,
$action
,
$mods
) =
@_
;
printf
STDERR
"MouseButton callback: button=$button, action=$action, mods=$mods\n"
;
};
my
$scroll_callback
=
sub
{
my
(
$window
,
$xoffset
,
$yoffset
) =
@_
;
printf
STDERR
"Scroll callback: offset=($xoffset,$yoffset)\n"
;
};
my
$windowclose_callback
=
sub
{
my
(
$window
) =
@_
;
printf
STDERR
"WindowClose callback: closed!\n"
;
};
my
$windowfocus_callback
=
sub
{
my
(
$window
,
$focused
) =
@_
;
printf
STDERR
"WindowFocus callback: "
. (
$focused
?
"is "
:
"is not "
) .
"focused\n"
;
};
my
$windowiconify_callback
=
sub
{
my
(
$window
,
$iconified
) =
@_
;
printf
STDERR
"WindowIconify callback: "
. (
$iconified
?
"is "
:
"is not "
) .
"iconified\n"
;
};
my
$windowpos_callback
=
sub
{
my
(
$window
,
$xpos
,
$ypos
) =
@_
;
printf
STDERR
"WindowPos callback: ($xpos,$ypos)\n"
;
};
my
$windowrefresh_callback
=
sub
{
my
(
$window
) =
@_
;
printf
STDERR
"WindowRefresh callback!\n"
;
};
my
$windowsize_callback
=
sub
{
my
(
$window
,
$width
,
$height
) =
@_
;
printf
STDERR
"WindowSize callback: ($width,$height)\n"
;
};
my
$joystick_callback
=
sub
{
my
(
$joy_id
,
$event
) =
@_
;
printf
STDERR
"Joystick callback: joy_id=$joy_id with event=$event\n"
;
};
my
(
$window
);
my
(
$vertex_buffer
,
$vertex_shader
,
$fragment_shader
,
$program
);
my
(
$mvp_location
,
$vpos_location
,
$vcol_location
);
glfwSetErrorCallback(
$error_callback
);
die
"glfwInit failed, $!\n"
if
!glfwInit();
$window
= glfwCreateWindow(640, 480,
"Simple example"
, NULL, NULL);
unless
(
defined
$window
) {
glfwTerminate();
die
"glfwCreateWindow failed, $!\n"
;
}
glfwSetKeyCallback(
$window
,
$key_callback
);
glfwSetWindowCloseCallback(
$window
,
$windowclose_callback
);
glfwMakeContextCurrent(
$window
);
die
"glewInit failed, $!\n"
if
GLEW_OK != glewInit();
glfwSwapInterval(1);
my
$icon16
= zeros(4,16,16);
$icon16
(0) .= 255;
$icon16
(3) .= 255;
my
$icon32
= zeros(4,32,32);
$icon32
(1) .= 255;
$icon32
(3) .= 255;
my
$icon48
= zeros(4,48,48);
$icon48
(2) .= 255;
$icon48
(3) .= 255;
$img16
= {
width
=>
$icon16
->dim(0),
height
=>
$icon16
->dim(1),
pixels
=>
pack
(
'C*'
,
$icon16
->list) };
$img32
= {
width
=>
$icon32
->dim(0),
height
=>
$icon32
->dim(1),
pixels
=>
pack
(
'C*'
,
$icon32
->list) };
$img48
= {
width
=>
$icon48
->dim(0),
height
=>
$icon48
->dim(1),
pixels
=>
pack
(
'C*'
,
$icon48
->list) };
glfwSetWindowIcon(
$window
,
$img16
,
$img32
,
$img48
);
my
$vertex_buffer
= glGenBuffers_p(1);
glBindBuffer(GL_ARRAY_BUFFER,
$vertex_buffer
);
glBufferData_p(GL_ARRAY_BUFFER, 4
*scalar
(
@vertices
),
@vertices
, GL_STATIC_DRAW);
my
$vertex_shader
= glCreateShader(GL_VERTEX_SHADER);
glShaderSource_p(
$vertex_shader
,
@vertex_shader_text
);
glCompileShader(
$vertex_shader
);
my
$fragment_shader
= glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource_p(
$fragment_shader
,
@fragment_shader_text
);
glCompileShader(
$fragment_shader
);
my
$program
= glCreateProgram();
glAttachShader(
$program
,
$vertex_shader
);
glAttachShader(
$program
,
$fragment_shader
);
glLinkProgram(
$program
);
my
$mvp_location
= glGetUniformLocation_c(
$program
,
"MVP"
);
my
$vpos_location
= glGetAttribLocation_c(
$program
,
"vPos"
);
my
$vcol_location
= glGetAttribLocation_c(
$program
,
"vCol"
);
glEnableVertexAttribArray(
$vpos_location
);
glVertexAttribPointer_c(
$vpos_location
, 2, GL_FLOAT, GL_FALSE, 4 * 5, 0 );
glEnableVertexAttribArray(
$vcol_location
);
glVertexAttribPointer_c(
$vcol_location
, 3, GL_FLOAT, GL_FALSE, 4 * 5, 4 * 2 );
while
(!glfwWindowShouldClose(
$window
))
{
my
(
$width
,
$height
);
my
(
$angle
,
$c
,
$s
,
$cor
,
$sor
);
my
(
$width
,
$height
) = glfwGetFramebufferSize(
$window
);
my
$ratio
=
$width
/
$height
;
glViewport(0, 0,
$width
,
$height
);
glClear(GL_COLOR_BUFFER_BIT);
$angle
= glfwGetTime();
$c
=
cos
(
$angle
);
$cor
=
$c
/
$ratio
;
$s
=
sin
(
$angle
);
$sor
=
$s
/
$ratio
;
my
$mvp
=
pack
'f[16]'
,
$cor
,
$s
, 0, 0, -
$sor
,
$c
, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1;
my
$pointer_to_mvp_data
=
unpack
'Q'
,
pack
'P'
,
$mvp
;
glUseProgram(
$program
);
glUniformMatrix4fv_c(
$mvp_location
, 1, GL_FALSE,
$pointer_to_mvp_data
);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(
$window
);
glfwPollEvents();
}
glfwDestroyWindow(
$window
);
glfwTerminate();