1
+ #include < application.h>
2
+ #include < mesh.h>
3
+ #include < camera.h>
4
+ #include < material.h>
5
+ #include < utility.h>
6
+ #include < memory>
7
+
8
+ class ProgressivePathTracer : public dw ::Application
9
+ {
10
+ protected:
11
+
12
+ // -----------------------------------------------------------------------------------------------------------------------------------
13
+
14
+ bool init (int argc, const char * argv[]) override
15
+ {
16
+ if (!load_shaders ())
17
+ return false ;
18
+
19
+ create_camera ();
20
+ create_image ();
21
+ create_quad ();
22
+
23
+ int work_grp_cnt[3 ];
24
+
25
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0 , &work_grp_cnt[0 ]);
26
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1 , &work_grp_cnt[1 ]);
27
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2 , &work_grp_cnt[2 ]);
28
+
29
+ DW_LOG_INFO (" Max Work Group Count, X: " + std::to_string (work_grp_cnt[0 ]) + " , Y:" + std::to_string (work_grp_cnt[1 ]) + " , Z:" + std::to_string (work_grp_cnt[2 ]));
30
+
31
+ int work_grp_size[3 ];
32
+
33
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0 , &work_grp_size[0 ]);
34
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1 , &work_grp_size[1 ]);
35
+ glGetIntegeri_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2 , &work_grp_size[2 ]);
36
+
37
+ DW_LOG_INFO (" Max Work Group Size, X: " + std::to_string (work_grp_size[0 ]) + " , Y:" + std::to_string (work_grp_size[1 ]) + " , Z:" + std::to_string (work_grp_size[2 ]));
38
+
39
+ int work_grp_inv;
40
+
41
+ glGetIntegerv (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &work_grp_inv);
42
+
43
+ DW_LOG_INFO (" Max Work Group Invocations: " + std::to_string (work_grp_inv));
44
+
45
+ return true ;
46
+ }
47
+
48
+ // -----------------------------------------------------------------------------------------------------------------------------------
49
+
50
+ void update (double delta) override
51
+ {
52
+ // Check if camera had moved.
53
+ check_camera_movement ();
54
+
55
+ // Update camera.
56
+ update_camera ();
57
+
58
+ // Perform path tracing
59
+ path_trace ();
60
+
61
+ // Render image to screen
62
+ render_to_backbuffer ();
63
+
64
+ // Set back to false before checking movement next frame.
65
+ m_camera_moved = false ;
66
+ }
67
+
68
+ // -----------------------------------------------------------------------------------------------------------------------------------
69
+
70
+ void shutdown () override
71
+ {
72
+
73
+ }
74
+
75
+ // -----------------------------------------------------------------------------------------------------------------------------------
76
+
77
+ dw::AppSettings intial_app_settings () override
78
+ {
79
+ dw::AppSettings settings;
80
+
81
+ settings.resizable = false ;
82
+ settings.width = 1280 ;
83
+ settings.height = 720 ;
84
+ settings.title = " GPU Path Tracer - Dihara Wijetunga (c) 2018" ;
85
+
86
+ return settings;
87
+ }
88
+
89
+ // -----------------------------------------------------------------------------------------------------------------------------------
90
+
91
+ void window_resized (int width, int height) override
92
+ {
93
+ // Override window resized method to update camera projection.
94
+ m_main_camera->update_projection (60 .0f , 0 .1f , 1000 .0f , float (m_width) / float (m_height));
95
+ m_aspect_ratio = float (m_width) / float (m_height);
96
+ m_resolution = glm::vec2 (m_width, m_height);
97
+ }
98
+
99
+ // -----------------------------------------------------------------------------------------------------------------------------------
100
+
101
+ void key_pressed (int code) override
102
+ {
103
+ // Handle forward movement.
104
+ if (code == GLFW_KEY_W)
105
+ m_heading_speed = m_camera_speed;
106
+ else if (code == GLFW_KEY_S)
107
+ m_heading_speed = -m_camera_speed;
108
+
109
+ // Handle sideways movement.
110
+ if (code == GLFW_KEY_A)
111
+ m_sideways_speed = -m_camera_speed;
112
+ else if (code == GLFW_KEY_D)
113
+ m_sideways_speed = m_camera_speed;
114
+ }
115
+
116
+ // -----------------------------------------------------------------------------------------------------------------------------------
117
+
118
+ void key_released (int code) override
119
+ {
120
+ // Handle forward movement.
121
+ if (code == GLFW_KEY_W || code == GLFW_KEY_S)
122
+ m_heading_speed = 0 .0f ;
123
+
124
+ // Handle sideways movement.
125
+ if (code == GLFW_KEY_A || code == GLFW_KEY_D)
126
+ m_sideways_speed = 0 .0f ;
127
+ }
128
+
129
+ // -----------------------------------------------------------------------------------------------------------------------------------
130
+
131
+ void mouse_pressed (int code) override
132
+ {
133
+ // Enable mouse look.
134
+ if (code == GLFW_MOUSE_BUTTON_LEFT)
135
+ m_mouse_look = true ;
136
+ }
137
+
138
+ // -----------------------------------------------------------------------------------------------------------------------------------
139
+
140
+ void mouse_released (int code) override
141
+ {
142
+ // Disable mouse look.
143
+ if (code == GLFW_MOUSE_BUTTON_LEFT)
144
+ m_mouse_look = false ;
145
+ }
146
+
147
+ // -----------------------------------------------------------------------------------------------------------------------------------
148
+
149
+ private:
150
+
151
+ // -----------------------------------------------------------------------------------------------------------------------------------
152
+
153
+ void check_camera_movement ()
154
+ {
155
+ if (m_mouse_look && (m_mouse_delta_x != 0 || m_mouse_delta_y != 0 ) || m_heading_speed != 0 .0f || m_sideways_speed != 0 .0f )
156
+ m_camera_moved = true ;
157
+ else
158
+ m_camera_moved = false ;
159
+ }
160
+
161
+ // -----------------------------------------------------------------------------------------------------------------------------------
162
+
163
+ void path_trace ()
164
+ {
165
+ m_image->bind_image (0 , 0 , 0 , GL_READ_WRITE, GL_RGBA32F);
166
+
167
+ m_path_tracer_program->use ();
168
+
169
+ if (m_camera_moved)
170
+ m_num_frames = 0 ;
171
+
172
+ m_path_tracer_program->set_uniform (" u_NumFrames" , m_num_frames);
173
+ m_path_tracer_program->set_uniform (" u_Accum" , float (m_num_frames) / float (m_num_frames + 1 ));
174
+ m_path_tracer_program->set_uniform (" u_FOV" , glm::radians (m_main_camera->m_fov ));
175
+ m_path_tracer_program->set_uniform (" u_AspectRatio" , m_aspect_ratio);
176
+ m_path_tracer_program->set_uniform (" u_Resolution" , m_resolution);
177
+ m_path_tracer_program->set_uniform (" u_InvViewMat" , glm::inverse (m_main_camera->m_view ));
178
+ m_path_tracer_program->set_uniform (" u_InvProjectionMat" , glm::inverse (m_main_camera->m_projection ));
179
+
180
+ glDispatchCompute (m_width, m_height, 1 );
181
+
182
+ glMemoryBarrier (GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
183
+
184
+ m_num_frames++;
185
+ }
186
+
187
+ // -----------------------------------------------------------------------------------------------------------------------------------
188
+
189
+ void render_to_backbuffer ()
190
+ {
191
+ glBindFramebuffer (GL_FRAMEBUFFER, 0 );
192
+ glClearColor (0 .0f , 0 .0f , 0 .0f , 1 .0f );
193
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194
+
195
+ m_quad_vao->bind ();
196
+
197
+ m_present_program->use ();
198
+
199
+ if (m_present_program->set_uniform (" s_Image" , 0 ))
200
+ m_image->bind (0 );
201
+
202
+ glDrawArrays (GL_TRIANGLES, 0 , 6 );
203
+ }
204
+
205
+ // -----------------------------------------------------------------------------------------------------------------------------------
206
+
207
+ bool load_shaders ()
208
+ {
209
+ std::string src;
210
+
211
+ if (!dw::utility::read_text (" shader/present_vs.glsl" , src))
212
+ {
213
+ DW_LOG_ERROR (" Failed to read present_vs.glsl" );
214
+ return false ;
215
+ }
216
+
217
+ m_present_vs = std::make_unique<dw::Shader>(GL_VERTEX_SHADER, src);
218
+
219
+ src.clear ();
220
+
221
+ if (!dw::utility::read_text (" shader/present_fs.glsl" , src))
222
+ {
223
+ DW_LOG_ERROR (" Failed to read present_fs.glsl" );
224
+ return false ;
225
+ }
226
+
227
+ m_present_fs = std::make_unique<dw::Shader>(GL_FRAGMENT_SHADER, src);
228
+
229
+ dw::Shader* present_shaders[] = { m_present_vs.get (), m_present_fs.get () };
230
+
231
+ m_present_program = std::make_unique<dw::Program>(2 , present_shaders);
232
+
233
+ src.clear ();
234
+
235
+ if (!dw::utility::read_text (" shader/path_tracer_cs.glsl" , src))
236
+ {
237
+ DW_LOG_ERROR (" Failed to read path_tracer_cs.glsl" );
238
+ return false ;
239
+ }
240
+
241
+ m_path_tracer_cs = std::make_unique<dw::Shader>(GL_COMPUTE_SHADER, src);
242
+
243
+ dw::Shader* path_tracer_shader = m_path_tracer_cs.get ();
244
+ m_path_tracer_program = std::make_unique<dw::Program>(1 , &path_tracer_shader);
245
+
246
+ return true ;
247
+ }
248
+
249
+ // -----------------------------------------------------------------------------------------------------------------------------------
250
+
251
+ void create_camera ()
252
+ {
253
+ m_main_camera = std::make_unique<dw::Camera>(60 .0f , 0 .1f , 1000 .0f , float (m_width) / float (m_height), glm::vec3 (0 .0f , 0 .0f , 30 .0f ), glm::vec3 (0 .0f , 0.0 , -1 .0f ));
254
+ m_aspect_ratio = float (m_width) / float (m_height);
255
+ m_resolution = glm::vec2 (m_width, m_height);
256
+ }
257
+
258
+ // -----------------------------------------------------------------------------------------------------------------------------------
259
+
260
+ void create_image ()
261
+ {
262
+ m_image = std::make_unique<dw::Texture2D>(m_width, m_height, 1 , 1 , 1 , GL_RGBA32F, GL_RGBA, GL_FLOAT);
263
+ m_image->set_min_filter (GL_LINEAR);
264
+ m_image->set_wrapping (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
265
+ }
266
+
267
+ // -----------------------------------------------------------------------------------------------------------------------------------
268
+
269
+ void create_quad ()
270
+ {
271
+ const float vertices[] =
272
+ {
273
+ -1 .0f , 1 .0f , 0 .0f , 0 .0f , 1 .0f ,
274
+ -1 .0f , -1 .0f , 0 .0f , 0 .0f , 0 .0f ,
275
+ 1 .0f , 1 .0f , 0 .0f , 1 .0f , 1 .0f ,
276
+ 1 .0f , 1 .0f , 0 .0f , 1 .0f , 1 .0f ,
277
+ 1 .0f , -1 .0f , 0 .0f , 1 .0f , 0 .0f ,
278
+ -1 .0f , -1 .0f , 0 .0f , 0 .0f , 0 .0f
279
+ };
280
+
281
+ m_quad_vbo = std::make_unique<dw::VertexBuffer>(GL_STATIC_DRAW, sizeof (vertices), (void *)vertices);
282
+
283
+ dw::VertexAttrib quad_attribs[] =
284
+ {
285
+ { 3 , GL_FLOAT, false , 0 , },
286
+ { 2 , GL_FLOAT, false , sizeof (float ) * 3 }
287
+ };
288
+
289
+ m_quad_vao = std::make_unique<dw::VertexArray>(m_quad_vbo.get (), nullptr , sizeof (float ) * 5 , 2 , quad_attribs);
290
+ }
291
+
292
+ // -----------------------------------------------------------------------------------------------------------------------------------
293
+
294
+ void update_camera ()
295
+ {
296
+ dw::Camera* current = m_main_camera.get ();
297
+
298
+ float forward_delta = m_heading_speed * m_delta;
299
+ float right_delta = m_sideways_speed * m_delta;
300
+
301
+ current->set_translation_delta (current->m_forward , forward_delta);
302
+ current->set_translation_delta (current->m_right , right_delta);
303
+
304
+ if (m_mouse_look)
305
+ {
306
+ // Activate Mouse Look
307
+ current->set_rotatation_delta (glm::vec3 ((float )(m_mouse_delta_y * m_camera_sensitivity * m_delta),
308
+ (float )(m_mouse_delta_x * m_camera_sensitivity * m_delta),
309
+ (float )(0 .0f )));
310
+ }
311
+ else
312
+ {
313
+ current->set_rotatation_delta (glm::vec3 ((float )(0 ),
314
+ (float )(0 ),
315
+ (float )(0 )));
316
+ }
317
+
318
+ current->update ();
319
+ }
320
+
321
+ // -----------------------------------------------------------------------------------------------------------------------------------
322
+
323
+ private:
324
+ // GPU Resources.
325
+ std::unique_ptr<dw::Shader> m_present_vs;
326
+ std::unique_ptr<dw::Shader> m_present_fs;
327
+ std::unique_ptr<dw::Program> m_present_program;
328
+ std::unique_ptr<dw::Shader> m_path_tracer_cs;
329
+ std::unique_ptr<dw::Program> m_path_tracer_program;
330
+ std::unique_ptr<dw::Texture> m_image;
331
+ std::unique_ptr<dw::VertexBuffer> m_quad_vbo;
332
+ std::unique_ptr<dw::VertexArray> m_quad_vao;
333
+
334
+ // Uniforms
335
+ float m_aspect_ratio;
336
+ glm::vec2 m_resolution;
337
+ int32_t m_num_frames = 0 ;
338
+
339
+ // Camera controls.
340
+ bool m_mouse_look = false ;
341
+ bool m_camera_moved = false ;
342
+ float m_heading_speed = 0 .0f ;
343
+ float m_sideways_speed = 0 .0f ;
344
+ float m_camera_sensitivity = 0 .005f ;
345
+ float m_camera_speed = 0 .1f ;
346
+
347
+ // Camera.
348
+ std::unique_ptr<dw::Camera> m_main_camera;
349
+ };
350
+
351
+ DW_DECLARE_MAIN (ProgressivePathTracer)
0 commit comments