10
10
void mouse_callback (GLFWwindow* window, double xpos, double ypos);
11
11
void scroll_callback (GLFWwindow* window, double xoffset, double yoffset);
12
12
13
- // Define colors using glm::vec3
13
+ // Array of colors
14
14
glm::vec3 colors[] =
15
15
{
16
16
glm::vec3 (1 .0f , 1 .0f , 1 .0f ), // White
@@ -29,14 +29,14 @@ glm::vec3 colors[] =
29
29
30
30
// Window dimensions
31
31
GLfloat WIDTH = 800 .0f , HEIGHT = 600 .0f ;
32
- std::string TITLE = " Main Window" ;
32
+ const std::string TITLE = " Main Window" ;
33
33
// Working directory
34
34
std::string PWD = std::filesystem::current_path().string();
35
35
// Shader sources
36
- std::string COLOR_V_SHADER_PATH = PWD + " /../shaders/color.vs" ;
37
- std::string COLOR_F_SHADER_PATH = PWD + " /../shaders/color.fs" ;
38
- std::string LIGHT_V_SHADER_PATH = PWD + " /../shaders/light.vs" ;
39
- std::string LIGHT_F_SHADER_PATH = PWD + " /../shaders/light.fs" ;
36
+ const std::string COLOR_V_SHADER_PATH = PWD + " /../shaders/color.vs" ;
37
+ const std::string COLOR_F_SHADER_PATH = PWD + " /../shaders/color.fs" ;
38
+ const std::string LIGHT_V_SHADER_PATH = PWD + " /../shaders/light.vs" ;
39
+ const std::string LIGHT_F_SHADER_PATH = PWD + " /../shaders/light.fs" ;
40
40
41
41
// Model transformation matrix
42
42
glm::mat4 model;
@@ -50,6 +50,7 @@ glm::vec3 translationVec(0.0f);
50
50
float deltaTime = 0 .0f ;
51
51
float lastFrame = 0 .0f ;
52
52
53
+ // Create Camera object with starting location
53
54
Camera camera (glm::vec3(0 .0f , 0 .0f , 3 .0f ));
54
55
55
56
bool firstMouse = true ;
@@ -106,6 +107,10 @@ float vertices[] = {
106
107
-0 .5f , 0 .5f , -0 .5f ,
107
108
};
108
109
110
+ // Float array to represent cube normals.
111
+ // A Cube has 6 vertices on each face (Every square is made by triangle, so 2 triangles means 6 vertices)
112
+ // so each 6 rows represent a face on the cube.
113
+ // Each face has a different direction with it's normal vector.
109
114
float normals[] =
110
115
{
111
116
// Negetive Z axis
@@ -157,6 +162,9 @@ float normals[] =
157
162
0 .0f , 1 .0f , 0 .0f ,
158
163
};
159
164
165
+ // Float array for texture coordinates.
166
+ // Texture coordinates are in 2D and that's why we have only two components (X,Y) for each vertex.
167
+ // Texture coordinates start from bottom-left (0,0) of image.
160
168
float texture[] =
161
169
{
162
170
0 .0f , 0 .0f ,
@@ -203,6 +211,7 @@ unsigned int indices[] =
203
211
0 , 2 , 3 , // Second triangle (bottom left + top right + top left)
204
212
};
205
213
214
+ // Vector 3 (X,Y,Z) array for cube positions in space
206
215
glm::vec3 cubePositions[] = {
207
216
glm::vec3 ( 0 .0f , 0 .0f , 7 .0f ),
208
217
glm::vec3 ( 2 .0f , 5 .0f , -15 .0f ),
@@ -216,6 +225,7 @@ glm::vec3 cubePositions[] = {
216
225
glm::vec3 (-1 .3f , 1 .0f , -1 .5f )
217
226
};
218
227
228
+ // Function to handle user input from keyboard
219
229
void processInput (GLFWwindow* window)
220
230
{
221
231
float currentFrame = glfwGetTime ();
@@ -267,6 +277,18 @@ void processInput(GLFWwindow* window)
267
277
// if(specularStrength <= 0.0f)
268
278
// specularStrength = 0.0f;
269
279
}
280
+ if (glfwGetKey (window, GLFW_KEY_E) == GLFW_PRESS)
281
+ {
282
+ specularIntensity *= 2 ;
283
+ if (specularIntensity >= 256 )
284
+ specularIntensity = 256 ;
285
+ }
286
+ if (glfwGetKey (window, GLFW_KEY_Q) == GLFW_PRESS)
287
+ {
288
+ specularIntensity /= 2 ;
289
+ if (specularIntensity <= 1 )
290
+ specularIntensity = 1 ;
291
+ }
270
292
// If user presses LEFT_SHIFT key button - increase camera movement
271
293
if (glfwGetKey (window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
272
294
camera.setMovementSpeed (SPEED * 5 .0f );
@@ -296,8 +318,7 @@ int main()
296
318
Shader colorShader (COLOR_V_SHADER_PATH.c_str (), COLOR_F_SHADER_PATH.c_str ());
297
319
Shader lightShader (LIGHT_V_SHADER_PATH.c_str (), LIGHT_F_SHADER_PATH.c_str ());
298
320
299
- // Create new Mesh object
300
- // Mesh mesh(0, vertices, sizeof(vertices), nullptr, 0, texture, sizeof(texture), indices, sizeof(indices), GL_FLOAT, false, 0);
321
+ // Create new Mesh object for cubes
301
322
Mesh mesh (0 , vertices, sizeof (vertices), GL_FLOAT, false , 0 );
302
323
mesh.setNormals (normals);
303
324
mesh.setIndices (indices, sizeof (indices));
@@ -306,22 +327,37 @@ int main()
306
327
mesh.initialise (GL_FLOAT, GL_FALSE);
307
328
// Add indices (elements) attribute to mesh
308
329
mesh.addAttribute (0 , GL_ELEMENT_ARRAY_BUFFER, 3 , 0 , 0 , indices, sizeof (indices), &mesh.elementBuffer );
309
- // Add texture attribute to mesh
330
+ // Add normals attribute to mesh
310
331
mesh.addAttribute (1 , GL_ARRAY_BUFFER, 3 , GL_FLOAT, false , normals, sizeof (normals), &mesh.normalsBuffer );
332
+ // Add texture attribute to mesh
333
+ mesh.addAttribute (2 , GL_ARRAY_BUFFER, 2 , GL_FLOAT, false , texture, sizeof (texture), &mesh.textureBuffer );
311
334
// Unbind mesh from global state
312
335
mesh.unbind ();
313
336
337
+ GLuint texture;
338
+ colorShader.use ();
339
+ // Load texture to "texture" variable
340
+ colorShader.loadTexture (PWD + " /../../assets/container2.png" , &texture, GL_TEXTURE_2D, GL_REPEAT, GL_LINEAR, 0 , GL_RGBA, 0 , GL_RGB, GL_UNSIGNED_BYTE);
341
+ // Set texture unit 0 active (unnecessary if we have only one texture, texture unit 0 is the default)
342
+ glActiveTexture (GL_TEXTURE0);
343
+ // Bind "texture" to texture unit 0
344
+ glBindTexture (GL_TEXTURE0, texture);
345
+ // Make material's sampler2D to point to our texture at texture unit 0
346
+ colorShader.setInt (" material.diffuse" , 0 );
347
+ colorShader.unbind ();
348
+
349
+ // Create new Mesh object for light cube
314
350
Mesh light (0 , nullptr , 0 , GL_FLOAT, false , 0 );
315
351
light.initialise (GL_FLOAT, GL_FALSE);
316
352
317
353
// Use colorShader program before setting uniforms
318
354
colorShader.use ();
319
- // colorShader.setVec3("lightColor", glm::value_ptr(colors[0]));
320
- // Tell OpenGL to enable depth buffer
355
+ // Tell OpenGL to enable depth buffer, so we be able to perceive depth
321
356
Shader::enableDepth ();
322
357
323
358
// Use lightShader program before setting uniforms
324
359
lightShader.use ();
360
+ // Set light cube's color to white
325
361
lightShader.setVec3 (" color" , glm::value_ptr (colors[0 ]));
326
362
327
363
// Main loop
@@ -359,29 +395,36 @@ int main()
359
395
// Set view matrix
360
396
view = camera.calculateLookAtMatrix (camera.getPosition (), camera.getPosition () + camera.getFront (), camera.getUp ());
361
397
lightShader.setMatrix4fv (" view" , 1 , GL_FALSE, glm::value_ptr (view));
398
+ // Simple use of sin to make the light cube move around a bit
362
399
lightPosition = glm::vec3 (1 .0f + sin (glfwGetTime ()) * 2 .0f , sin (glfwGetTime () / 2 .0f ), 0 .0f );
400
+ // Translate (move) light cube to updated position
363
401
model = glm::translate (model, lightPosition);
402
+ // Make light cube a fith (1/5) of it's normal size
403
+ model = glm::scale (model, glm::vec3 (0 .2f , 0 .2f , 0 .2f ));
404
+ // Set all changes made to model
364
405
lightShader.setMatrix4fv (" model" , 1 , GL_FALSE, glm::value_ptr (model));
365
406
// Set light object's light strength
366
- // lightShader.setVec3("color", glm::value_ptr(colors[lightCubeIndex]));
367
407
lightShader.setFloat (" strength" , lightStrength);
368
408
}
369
409
else
370
410
{
411
+ // Simple use of GLFW time function with modulo to have different angles to apply on the cubes
371
412
angle = glfwGetTime () * 15 .0f * (((i + 1 ) % moduloVal) + 1 );
413
+ // How much the rotation affects each axis, 1 is full effect and 0 is none
372
414
rotationVec = glm::vec3 (1 .0f , 0 .5f , 0 .2f );
373
415
// Update uniform matrix in colorShader program
374
416
colorShader.use ();
375
- colorShader. setVec3 ( " objectColor " , glm::value_ptr (colors[i]));
417
+ // Set light properties
376
418
colorShader.setVec3 (" viewPosition" , glm::value_ptr (camera.getPosition ()));
377
419
colorShader.setVec3 (" light.position" , glm::value_ptr (lightPosition));
378
420
colorShader.setVec3 (" light.ambient" , glm::value_ptr (glm::vec3 (1 .0f ) * lightStrength));
379
421
colorShader.setVec3 (" light.diffuse" , glm::value_ptr (glm::vec3 (1 .0f ) * lightStrength));
380
422
colorShader.setVec3 (" light.specular" , glm::value_ptr (glm::vec3 (1 .0f ) * lightStrength));
381
423
382
- colorShader.setVec3 (" material.ambient" , glm::value_ptr (glm::vec3 (0.5 ) * colors[i] * lightStrength));
383
- colorShader.setVec3 (" material.diffuse" , glm::value_ptr (glm::vec3 (0.8 ) * colors[i] * lightStrength));
384
- colorShader.setVec3 (" material.specular" , glm::value_ptr (glm::vec3 (1.0 ) * colors[i] * lightStrength));
424
+ // Set material properties
425
+ colorShader.setVec3 (" material.ambient" , glm::value_ptr (glm::vec3 (0.5 ) * lightStrength));
426
+ colorShader.setVec3 (" material.diffuse" , glm::value_ptr (glm::vec3 (0.8 ) * lightStrength));
427
+ colorShader.setVec3 (" material.specular" , glm::value_ptr (glm::vec3 (1.0 ) * lightStrength));
385
428
colorShader.setFloat (" material.shininess" , specularIntensity);
386
429
// Calculate and set object normal vector so we can calculate in shader how much the light hits the object
387
430
colorShader.setMatrix3fv (" normalMatrix" , 1 , GL_TRUE, glm::value_ptr (glm::mat3 (glm::inverse (model))));
@@ -391,7 +434,9 @@ int main()
391
434
// Set view matrix
392
435
view = camera.calculateLookAtMatrix (camera.getPosition (), camera.getPosition () + camera.getFront (), camera.getUp ());
393
436
colorShader.setMatrix4fv (" view" , 1 , GL_FALSE, glm::value_ptr (view));
437
+ // Rotate cube
394
438
model = glm::rotate (model, glm::radians (angle), rotationVec);
439
+ // Set changes made to model
395
440
colorShader.setMatrix4fv (" model" , 1 , GL_FALSE, glm::value_ptr (model));
396
441
}
397
442
// Render model
0 commit comments