/
01_triangle.php
176 lines (141 loc) 路 5.32 KB
/
01_triangle.php
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?php
/**
* This is the most basic example of how to use the GLFW library.
* You can think of it as a ""Hello World"" example.
*
* This example does not utilize our helper class to keep it a basic as possible.
*/
// initalize GLFW
if (!glfwInit()) {
throw new Exception('GLFW could not be initialized!');
}
// prints the GLFW version for the examples sake
echo glfwGetVersionString() . PHP_EOL;
// configure the window
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
// make sure to set the GLFW context version to the same
// version the GLFW extension has been compiled with, default 4.1
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// enable forward compatibitly, @see glfw docs for details
// but mostly this fixes an issue many expirence on MacOS
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// glfwCreateWindow will initalizes a new window in which you can render,
// you can have multiple windows of course.
if (!$window = glfwCreateWindow(800, 800, "PHP GLFW Demo")) {
throw new Exception('OS Window could not be initialized!');
}
// calling this method will make the given window object
// the one that is bound to the current GL context. In other words
// all GL commands will be executed in the context of this window
// Special in PHP-GLFW is that this will also initialize glad.
glfwMakeContextCurrent($window);
var_dump(glGetString(GL_VERSION));
// setting the swap interval to "1" basically enabled vsync.
// more correctly it defines how many screen updates to wait for
// after glfwSwapBuffers has been called
glfwSwapInterval(1);
// Shader Setup
// ----------------------------------------------------------------------------
// create, upload and compile the vertex shader
$vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource($vertexShader, <<< 'GLSL'
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
out vec4 pcolor;
void main()
{
pcolor = vec4(color, 1.0f);
gl_Position = vec4(position, 1.0f);
}
GLSL);
glCompileShader($vertexShader);
glGetShaderiv($vertexShader, GL_COMPILE_STATUS, $success);
if (!$success) {
throw new Exception("Vertex shader could not be compiled.");
}
// create, upload and compile the fragment shader
$fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource($fragShader, <<<'GLSL'
#version 330 core
out vec4 fragment_color;
in vec4 pcolor;
void main()
{
fragment_color = pcolor;
}
GLSL);
glCompileShader($fragShader);
glGetShaderiv($fragShader, GL_COMPILE_STATUS, $success);
if (!$success) {
throw new Exception("Fragment shader could not be compiled.");
}
// create a shader programm and link our vertex and framgent shader together
$shaderProgram = glCreateProgram();
glAttachShader($shaderProgram, $vertexShader);
glAttachShader($shaderProgram, $fragShader);
glLinkProgram($shaderProgram);
glGetProgramiv($shaderProgram, GL_LINK_STATUS, $linkSuccess);
if (!$linkSuccess) {
throw new Exception("Shader program could not be linked.");
}
// free the shders
glDeleteShader($vertexShader);
glDeleteShader($fragShader);
// Buffer and data setup
// ----------------------------------------------------------------------------
// create a vertex array (VertextArrayObject -> VAO)
glGenVertexArrays(1, $VAO);
// create a buffer for our vertices (VertextBufferObject -> VBO)
glGenBuffers(1, $VBO);
// bind the buffer to our VAO
glBindVertexArray($VAO);
glBindBuffer(GL_ARRAY_BUFFER, $VBO);
// declare vertices for a single triangle and the colors for each vertex
$buffer = new \GL\Buffer\FloatBuffer([
// positions // colors
0.5, -0.5, 0.0, 1.0, 0.0, 0.0, // bottom right
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0, // bottom let
0.0, 0.5, 0.0, 0.0, 0.0, 1.0 // top
]);
// now we can upload our float buffer to the currently bound VBO
glBufferData(GL_ARRAY_BUFFER, $buffer, GL_STATIC_DRAW);
// in the next step we have to define the vertex attributes, in simpler
// words tell openGL how the data we just uploaded should be split and iterated over.
// positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, GL_SIZEOF_FLOAT * 6, 0);
glEnableVertexAttribArray(0);
// colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, GL_SIZEOF_FLOAT * 6, GL_SIZEOF_FLOAT * 3);
glEnableVertexAttribArray(1);
// unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Main Loop
// ----------------------------------------------------------------------------
// `glfwWindowShouldClose` returns true when the user clicks on the little
// close button on the window, there probably are other triggers. But in short
// we simply loop forever until the window tells us it wants to close.
while (!glfwWindowShouldClose($window))
{
// setting the clear color to black and clearing the color buffer
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
// use the shader, will active the given shader program
// for the coming draw calls.
glUseProgram($shaderProgram);
// bind & draw the vertex array
glBindVertexArray($VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// swap the windows framebuffer and
// poll queued window events.
glfwSwapBuffers($window);
glfwPollEvents();
}
// stop & cleanup
glDeleteVertexArrays(1, $VAO);
glDeleteBuffers(1, $VBO);
glfwDestroyWindow($window);
glfwTerminate();