-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.re
261 lines (215 loc) · 7.07 KB
/
index.re
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*
* vim: set ft=reason:
*/
module Constants = ReasonglInterface.Constants;
module Gl: ReasonglInterface.Gl.t = Reasongl.Gl;
/**
* This program is an example of how to draw a square.
* You can vary the number of vertices drawn, allowing you to draw triangles, squares and circles.
*/
type glCamera = {projectionMatrix: Gl.Mat4.t};
type glEnv = {
camera: glCamera,
window: Gl.Window.t,
context: Gl.contextT
};
/**
* Helper function which will initialize the shaders and attach them to the GL context.
* Returns the program.
*/
let getProgram
context::(context: Gl.contextT)
vertexShader::(vertexShaderSource: string)
fragmentShader::(fragmentShaderSource: string)
:option Gl.programT => {
let vertexShader = Gl.createShader context Constants.vertex_shader;
Gl.shaderSource context vertexShader vertexShaderSource;
Gl.compileShader context vertexShader;
let compiledCorrectly =
Gl.getShaderParameter
::context shader::vertexShader paramName::Gl.Compile_status == 1;
if compiledCorrectly {
let fragmentShader = Gl.createShader context Constants.fragment_shader;
Gl.shaderSource context fragmentShader fragmentShaderSource;
Gl.compileShader context fragmentShader;
let compiledCorrectly =
Gl.getShaderParameter
::context shader::fragmentShader paramName::Gl.Compile_status == 1;
if compiledCorrectly {
let program = Gl.createProgram context;
Gl.attachShader ::context ::program shader::vertexShader;
Gl.deleteShader ::context vertexShader;
Gl.attachShader ::context ::program shader::fragmentShader;
Gl.deleteShader ::context fragmentShader;
Gl.linkProgram ::context program;
let linkedCorrectly =
Gl.getProgramParameter ::context ::program paramName::Gl.Link_status == 1;
if linkedCorrectly {
Some program
} else {
print_endline @@
"Linking error: " ^ Gl.getProgramInfoLog ::context program;
None
}
} else {
print_endline @@
"Fragment shader error: " ^ Gl.getShaderInfoLog ::context fragmentShader;
None
}
} else {
print_endline @@
"Vertex shader error: " ^ Gl.getShaderInfoLog ::context vertexShader;
None
}
};
/**
* Dumb vertex shader which take for input a vertex position and a vertex color and maps the point onto
* the screen.
* Fragment shader simply applies the color to the pixel.
*/
let vertexShaderSource = {|
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 uPMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = uPMatrix * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
|};
let fragmentShaderSource = {|
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor;
}
|};
/** This initializes the window **/
let screen = "asd";
let window = Gl.Window.init ::screen argv::Sys.argv;
let windowSize = 600;
Gl.Window.setWindowSize ::window width::windowSize height::windowSize;
/** Initialize the Gl context **/
let context = Gl.Window.getContext window;
Gl.viewport ::context x::0 y::0 width::(Gl.Window.getPixelWidth window) height::(Gl.Window.getPixelHeight window);
/* Gl.clearColor context 1.0 1.0 1.0 1.0; */
Gl.clear
::context mask::(Constants.color_buffer_bit lor Constants.depth_buffer_bit);
/** Camera is a simple record containing one matrix used to project a point in 3D onto the screen. **/
let camera = {projectionMatrix: Gl.Mat4.create ()};
/**
* Those buffers are basically pointers to chunks of memory on the graphics card. They're used to store the
* vertex and color data.
*/
let vertexBuffer = Gl.createBuffer context;
let colorBuffer = Gl.createBuffer context;
/** Compiles the shaders and gets the program with the shaders loaded into **/
let program =
switch (
getProgram
::context
vertexShader::vertexShaderSource
fragmentShader::fragmentShaderSource
) {
| None =>
failwith "Could not create the program and/or the shaders. Aborting."
| Some program => program
};
Gl.useProgram context program;
/** Get the attribs ahead of time to be used inside the render function **/
let aVertexPosition =
Gl.getAttribLocation ::context ::program name::"aVertexPosition";
Gl.enableVertexAttribArray ::context attribute::aVertexPosition;
let aVertexColor =
Gl.getAttribLocation ::context ::program name::"aVertexColor";
Gl.enableVertexAttribArray ::context attribute::aVertexColor;
let pMatrixUniform = Gl.getUniformLocation context program "uPMatrix";
Gl.uniformMatrix4fv
::context location::pMatrixUniform value::camera.projectionMatrix;
/**
* Will mutate the projectionMatrix to be an ortho matrix with the given boundaries.
* See this link for quick explanation of what this is.
* https://shearer12345.github.io/graphics/assets/projectionPerspectiveVSOrthographic.png
*/
Gl.Mat4.ortho
out::camera.projectionMatrix
left::0.
right::(float_of_int (Gl.Window.getWidth window))
bottom::0.
top::(float_of_int (Gl.Window.getHeight window))
near::0.
far::100.;
let frame = ref(0);
/**
* Render simply draws a rectangle.
*/
let render time => {
if (!frame === 0) {
frame := !frame + 1;
} else if (!frame === 1) {
/* Same @Hack as /~https://github.com/Schmavery/reprocessing/commit/36e684a65c9edbefce38184f0c0c664f2d5fc19e. */
Gl.Window.setWindowSize ::window width::windowSize height::windowSize;
frame := !frame + 1;
};
/* 0,0 is the bottom left corner */
let x = 150;
let y = 150;
let width = 300;
let height = 300;
/**
* Setup vertices to be sent to the GPU and bind the data on the "register" called `array_buffer`.
*/
let square_vertices = [|
float_of_int @@ x + width,
float_of_int @@ y + height,
0.0,
float_of_int x,
float_of_int @@ y + height,
0.0,
float_of_int @@ x + width,
float_of_int y,
0.0,
float_of_int x,
float_of_int y,
0.0
|];
Gl.bindBuffer ::context target::Constants.array_buffer buffer::vertexBuffer;
Gl.bufferData
::context
target::Constants.array_buffer
data::(Gl.Bigarray.of_array Gl.Bigarray.Float32 square_vertices)
usage::Constants.static_draw;
Gl.vertexAttribPointer
::context
attribute::aVertexPosition
size::3
type_::Constants.float_
normalize::false
stride::0
offset::0;
/** Setup colors to be sent to the GPU **/
let r = 1.;
let g = 0.;
let b = 0.;
let a = 1.;
let square_colors = [|r, g, b, a, r, g, b, a, r, g, b, a, r, g, b, a|];
Gl.bindBuffer ::context target::Constants.array_buffer buffer::colorBuffer;
Gl.bufferData
::context
target::Constants.array_buffer
data::(Gl.Bigarray.of_array Gl.Bigarray.Float32 square_colors)
usage::Constants.static_draw;
Gl.vertexAttribPointer
::context
attribute::aVertexColor
size::4
type_::Constants.float_
normalize::false
stride::0
offset::0;
Gl.uniformMatrix4fv
::context location::pMatrixUniform value::camera.projectionMatrix;
/** Final call which actually does the "draw" **/
Gl.drawArrays ::context mode::Constants.triangle_strip first::0 count::4
};
/** Start the render loop. **/
Gl.render ::window displayFunc::render ();