-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
289 lines (250 loc) · 10.8 KB
/
main.cpp
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
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
// the OpenGL version include also includes all previous versions
// Build note: Due to a minefield of preprocessor build flags, the gl_load.hpp must come after
// the version include.
// Build note: Do NOT mistakenly include _int_gl_4_4.h. That one doesn't define OpenGL stuff
// first.
// Build note: Also need to link opengl32.lib (unknown directory, but VS seems to know where it
// is, so don't put in an "Additional Library Directories" entry for it).
// Build note: Also need to link glload/lib/glloadD.lib.
#include "glload/include/glload/gl_4_4.h"
#include "glload/include/glload/gl_load.hpp"
// Build note: Must be included after OpenGL code (in this case, glload).
// Build note: Also need to link freeglut/lib/freeglutD.lib. However, the linker will try to
// find "freeglut.lib" (note the lack of "D") instead unless the following preprocessor
// directives are set either here or in the source-building command line (VS has a
// "Preprocessor" section under "C/C++" for preprocessor definitions).
// Build note: Also need to link winmm.lib (VS seems to know where it is, so don't put in an
// "Additional Library Directories" entry).
#define FREEGLUT_STATIC
#define _LIB
#define FREEGLUT_LIB_PRAGMAS 0
#include "freeglut/include/GL/freeglut.h"
// this linking approach is very useful for portable, crude, barebones demo code, but it is
// better to link through the project building properties
#pragma comment(lib, "glload/lib/glloadD.lib")
#pragma comment(lib, "opengl32.lib") // needed for glload::LoadFunctions()
#pragma comment(lib, "freeglut/lib/freeglutD.lib")
#ifdef WIN32
#pragma comment(lib, "winmm.lib") // Windows-specific; freeglut needs it
#endif
// for printf(...)
#include <stdio.h>
// for basic OpenGL stuff
#include "OpenGlErrorHandling.h"
#include "GenerateShader.h"
#include "ParticleManager.h"
ParticleManager gParticleManager;
/*-----------------------------------------------------------------------------------------------
Description:
Governs window creation, the initial OpenGL configuration (face culling, depth mask, even
though this is a 2D demo and that stuff won't be of concern), the creation of geometry, and
the creation of a texture.
Parameters:
argc (From main(...)) The number of char * items in argv. For glut's initialization.
argv (From main(...)) A collection of argument strings. For glut's initialization.
Returns:
False if something went wrong during initialization, otherwise true;
Exception: Safe
Creator: John Cox (3-7-2016)
-----------------------------------------------------------------------------------------------*/
void Init()
{
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
GLuint particleProgramId = GenerateVertexShaderProgram();
GLuint computeProgramId = GenerateComputeShaderProgram();
// all values are in windows space (X and Y limited to [-1,+1])
// Note: Toy with the values as you will.
//unsigned int totalParticles = 20000;
unsigned int totalParticles = 600000;
unsigned int maxParticlesEmittedPerFrame = 200;
glm::vec2 center = glm::vec2(+0.3f, +0.3f);
float radius = 1.1f;
float minVelocity = 0.05f;
float maxVelocity = 0.6f;
gParticleManager.Init(particleProgramId,
computeProgramId,
totalParticles,
maxParticlesEmittedPerFrame,
center,
radius,
minVelocity,
maxVelocity);
}
/*-----------------------------------------------------------------------------------------------
Description:
This is the rendering function. It tells OpenGL to clear out some color and depth buffers,
to set up the data to draw, to draw than stuff, and to report any errors that it came across.
This is not a user-called function.
This function is registered with glutDisplayFunc(...) during glut's initialization.
Parameters: None
Returns: None
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
void Display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// in the absence of an actual timer, use a hard-coded delta time
gParticleManager.Update(0.01f);
// this handles its own bindings and cleans up when it is done
gParticleManager.Render();
// tell the GPU to swap out the displayed buffer with the one that was just rendered
glutSwapBuffers();
// tell glut to call this display() function again on the next iteration of the main loop
// Note: https://www.opengl.org/discussion_boards/showthread.php/168717-I-dont-understand-what-glutPostRedisplay()-does
// Also Note: This display() function will also be registered to run if the window is moved
// or if the viewport is resized. If glutPostRedisplay() is not called, then as long as the
// window stays put and doesn't resize, display() won't be called again (tested with
// debugging).
// Also Also Note: It doesn't matter where this is called in this function. It sets a flag
// for glut's main loop and doesn't actually call the registered display function, but I
// got into the habbit of calling it at the end.
glutPostRedisplay();
}
/*-----------------------------------------------------------------------------------------------
Description:
Tell's OpenGL to resize the viewport based on the arguments provided. This is an
opportunity to call glViewport or glScissor to keep up with the change in size.
This is not a user-called function. It is registered with glutReshapeFunc(...) during
glut's initialization.
Parameters:
w The width of the window in pixels.
h The height of the window in pixels.
Returns: None
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
void Reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
/*-----------------------------------------------------------------------------------------------
Description:
Executes when the user presses a key on the keyboard.
This is not a user-called function. It is registered with glutKeyboardFunc(...) during
glut's initialization.
Note: Although the x and y arguments are for the mouse's current position, this function does
not respond to mouse presses.
Parameters:
key The ASCII code of the key that was pressed (ex: ESC key is 27)
x The horizontal viewport coordinates of the mouse's current position.
y The vertical window coordinates of the mouse's current position
Returns: None
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
void Keyboard(unsigned char key, int x, int y)
{
// this statement is mostly to get ride of an "unreferenced parameter" warning
printf("keyboard: x = %d, y = %d\n", x, y);
switch (key)
{
case 27:
{
// ESC key
glutLeaveMainLoop();
return;
}
default:
break;
}
}
/*-----------------------------------------------------------------------------------------------
Description:
I don't know what this does, but I've kept it around since early times, and this was the
comment given with it:
"Called before FreeGLUT is initialized. It should return the FreeGLUT display mode flags
that you want to use. The initial value are the standard ones used by the framework. You can
modify it or just return you own set. This function can also set the width/height of the
window. The initial value of these variables is the default, but you can change it."
Parameters:
displayMode ??
width ??
height ??
Returns:
??what??
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
unsigned int Defaults(unsigned int displayMode, int &width, int &height)
{
// this statement is mostly to get ride of an "unreferenced parameter" warning
printf("Defaults: width = %d, height = %d\n", width, height);
return displayMode;
}
/*-----------------------------------------------------------------------------------------------
Description:
Cleans up GPU memory. This might happen when the processes die, but be a good memory steward
and clean up properly.
Note: A big program would have the textures, program IDs, buffers, and other things
encapsulated somewhere, and each other those would do the cleanup, but in this barebones
demo, I can just clean up everything here.
Parameters: None
Returns: None
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
void CleanupAll()
{
gParticleManager.Cleanup();
}
/*-----------------------------------------------------------------------------------------------
Description:
Program start and end.
Parameters:
argc The number of strings in argv.
argv A pointer to an array of null-terminated, C-style strings.
Returns:
0 if program ended well, which it always does or it crashes outright, so returning 0 is fine
Exception: Safe
Creator: John Cox (2-13-2016)
-----------------------------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
int width = 500;
int height = 500;
unsigned int displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL;
displayMode = Defaults(displayMode, width, height);
glutInitDisplayMode(displayMode);
glutInitContextVersion(4, 4);
glutInitContextProfile(GLUT_CORE_PROFILE);
// enable this for automatic message reporting (see OpenGlErrorHandling.cpp)
#define DEBUG
#ifdef DEBUG
glutInitContextFlags(GLUT_DEBUG);
#endif
glutInitWindowSize(width, height);
glutInitWindowPosition(300, 200);
int window = glutCreateWindow(argv[0]);
glload::LoadTest glLoadGood = glload::LoadFunctions();
// ??check return value??
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
if (!glload::IsVersionGEQ(3, 3))
{
printf("Your OpenGL version is %i, %i. You must have at least OpenGL 3.3 to run this tutorial.\n",
glload::GetMajorVersion(), glload::GetMinorVersion());
glutDestroyWindow(window);
return 0;
}
if (glext_ARB_debug_output)
{
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
glDebugMessageCallbackARB(DebugFunc, (void*)15);
}
Init();
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(Keyboard);
glutMainLoop();
CleanupAll();
return 0;
}