-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
451 lines (345 loc) · 17.4 KB
/
Copy pathmain.cpp
File metadata and controls
451 lines (345 loc) · 17.4 KB
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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#define STB_IMAGE_IMPLEMENTATION
#include<stdio.h>
#include<string.h>
#include <cmath>
#include<vector>
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "CommonValues.h"
#include "Window.h"
#include "Mesh.h"
#include "Shader.h"
#include "Camera.h"
#include "Texture.h"
#include "DirectionalLight.h"
#include "PointLight.h"
#include "Material.h"
#include "SpotLight.h"
#include "Model.h"
#include "Skybox.h"
const float toRadians = 3.14159265f / 180.0f; //radians = pi/180
GLuint uniformProjection = 0, uniformModel = 0, uniformView = 0, uniformEyePosition = 0,
uniformSpecularIntensity = 0, uniformShininess = 0,
uniformOmniLightPos = 0, uniformFarPlane = 0;
Window mainWindow;
std::vector<Mesh*> meshList;
std::vector<Shader> shaderList;
Shader directionalShadowShader;
Shader omniShadowShader;
Camera camera;
Texture brickTexture;
Texture dirtTexture;
Texture plainTexture;
Material shinyMaterial; //has high shininess and very high specular intensity
Material dullMaterial; //has low shininess and low specular intensity
Model xwing;
Model blackhawk;
Model character;
DirectionalLight mainLight;
PointLight pointLights[MAX_POINT_LIGHTS];
SpotLight spotLights[MAX_SPOT_LIGHTS];
Skybox skybox;
unsigned int pointLightCount = 0;
unsigned int spotLightCount = 0;
GLfloat deltaTime = 0.0f; //change in time from the last time we chaecked
GLfloat lastTime = 0.0f;
GLfloat blackhawkAngle = 0.0f; //for movement of the blackhawk
//Vertex shader
static const char* vShader = "Shaders/shader.vert";
//vec3 refers to a vector with 3 values with x,y,z positions
//glPosition is a value to the shader itself. It's an output value
//out vec4 vCol is used to indicate whatever vCol is set to, it will be passed on to another shader. In this case, the fragment shader will be picked up
//vCol = vec4(clamp(pos, 0.0f, 1.0f), 1.0f); - means that we want to make the color to whatever the position is. The positions are given in GLfloat vertices[] in the createTriangle() method
//clamp is used because we don't want to have any negative values in there because that will be just black
//Fragment shader
static const char* fShader = "Shaders/shader.frag";
//in vec4 vCol is used to catch the value that will be given by out vec4 vCol in the vertex shader
void calcAverageNormals(unsigned int* indices, unsigned int indiceCount, GLfloat* vertices, unsigned int verticeCount,
unsigned int vLength, unsigned int normalOffset)
{
for (size_t i = 0; i < indiceCount; i += 3)
{
unsigned int in0 = indices[i] * vLength;
unsigned int in1 = indices[i + 1] * vLength;
unsigned int in2 = indices[i + 2] * vLength;
glm::vec3 v1(vertices[in1] - vertices[in0], vertices[in1 + 1] - vertices[in0 + 1], vertices[in1 + 2] - vertices[in0 + 2]); //Here the values that we get in case of the triangle will be 1, 2, 0
glm::vec3 v2(vertices[in2] - vertices[in0], vertices[in2 + 1] - vertices[in0 + 1], vertices[in2 + 2] - vertices[in0 + 2]); //Here instead of in1, we are using in2
glm::vec3 normal = glm::cross(v1, v2); //Cross product finds the line which is poking towards us or away from us
normal = glm::normalize(normal); //Returns a unit vector, since the vectors should be of the same length
in0 += normalOffset; in1 += normalOffset; in2 += normalOffset;
vertices[in0] += normal.x; vertices[in0 + 1] += normal.y; vertices[in0 + 2] += normal.z;
vertices[in1] += normal.x; vertices[in1 + 1] += normal.y; vertices[in1 + 2] += normal.z;
vertices[in2] += normal.x; vertices[in2 + 1] += normal.y; vertices[in2 + 2] += normal.z;
}
//go through all the vertices and jump straight to the end of each one and also normalize the values
for (size_t i = 0; i < verticeCount / vLength; i++)
{
unsigned int nOffset = i * vLength + normalOffset; //Every time when we go through the loop, it is effectively counting up each of these 0 1 2 3 and then grabbing the relevant one from the list of vertices and going to the offset section of it
//Go through each of the rows of the vertices array, get the start of the normal offsets grabbing each of those normals that we've just calculated up here by going through this loop few times going through each one.
glm::vec3 vec(vertices[nOffset], vertices[nOffset + 1], vertices[nOffset + 2]);
vec = glm::normalize(vec);
vertices[nOffset] = vec.x; vertices[nOffset + 1] = vec.y; vertices[nOffset + 2] = vec.z;
}
}
void CreateObjects()
{
unsigned int indices[] = {
0, 3, 1, //Draws the 0th point first, 3rd next and then the 1st
1, 3, 2,
2, 3, 0,
0, 1, 2
};
GLfloat vertices[] = {
// x y z u v normals nx ny nz u and v refer to the texture coordinates
-1.0f,-1.0f, -0.6f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, //black , bottom left
0.0f, -1.0f, 1.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, //goes into the background
1.0f, -1.0f, -0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //red, bottom right
0.0f, 1.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f //green, top
};
unsigned int floorIndices[] = {
0, 2, 1, //top-left, bottom-left, top-right
1, 2, 3 //go backwards along that line ==> previous 0, "2, 1" ==> "1,2" , 3 ; 3 specifies bottom right
};
GLfloat floorVertices[] = {
-10.0f, 0.0f, -10.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, //x,y,z = back left corner; u, v = top left of the image. Here the normals 0.0f, -1.0f, 0.0f will be pointing to the top left of the image
10.0f, 0.0f, -10.0f, 10.0f, 0.0f, 0.0f, -1.0f, 0.0f, //x, y, z = back right; u, v = top right of the image
-10.0f, 0.0f, 10.0f, 0.0f, 10.0f, 0.0f, -1.0f, 0.0f, //front left
10.0f, 0.0f, 10.0f, 10.0f, 10.0f, 0.0f, -1.0f, 0.0f //front right
};
calcAverageNormals(indices, 12, vertices, 32, 8, 5); //amount of indices - 12, no. of vertices - 32, size of each vertex - 8, normal offset - 5. Note: When the indices are altered, the vertices will be altered as well
Mesh* obj1 = new Mesh();
obj1->CreateMesh(vertices, indices, 32, 12);
meshList.push_back(obj1); //For vectors for just adding it to the end of the list
Mesh* obj2 = new Mesh();
obj2->CreateMesh(vertices, indices, 32, 12);
meshList.push_back(obj2); //For vectors for just adding it to the end of the list
Mesh* obj3 = new Mesh();
obj3->CreateMesh(floorVertices, floorIndices, 32, 6); //we have four points that we need to define ==> 4*8 = 32. We have 6 indices
meshList.push_back(obj3);
}
void CreateShaders()
{
Shader* shader1 = new Shader();
shader1->CreateFromFiles(vShader, fShader);
shaderList.push_back(*shader1);
directionalShadowShader = Shader();
directionalShadowShader.CreateFromFiles("Shaders/directional_shadow_map.vert", "Shaders/directional_shadow_map.frag");
omniShadowShader.CreateFromFiles("Shaders/omni_shadow_map.vert", "Shaders/omni_shadow_map.geom", "Shaders/omni_shadow_map.frag");
}
void RenderScene()
{
glm::mat4 model(1.0f); //creates a 4x4 identity matrix
model = glm::translate(model, glm::vec3(0.0f, 0.0f, -2.5f)); //Apply translation to the identity matrix. transaltion is used to move a set of points
//model = glm::rotate(model, curAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f)); //glm::vec3(0.0f, 0.0f, 1.0f) is used to spin the model aroud the z-axis, which is the axis pointing forward and backward from us.
//model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f)); //scale in the x axis by 2, y axis by 2 and the z axis by 1
//glUniform1f(uniformXMove, triOffset); Here, since we have attached the shader, we want to set the uniform value to the value of triOffset. uniformXMove is the location in the shader
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model)); //GL_FALSE is used when we don't want to transpose the matrix. value_ptr is used because the model is not directly in a raw format
brickTexture.UseTexture();
shinyMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
meshList[0]->RenderMesh();
model = glm::mat4(1.0f); //Creates a identity matrix
model = glm::translate(model, glm::vec3(0.0f, 4.0f, -2.5f));
//model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
dirtTexture.UseTexture();
dullMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
meshList[1]->RenderMesh();
model = glm::mat4(1.0f); //Creates a identity matrix
model = glm::translate(model, glm::vec3(0.0f, -2.0f, 0.0f));
//model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.0f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
dirtTexture.UseTexture();
shinyMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
meshList[2]->RenderMesh();
model = glm::mat4(1.0f); //Creates a identity matrix
model = glm::translate(model, glm::vec3(4.0f, 0.0f, -11.0f));
model = glm::rotate(model, -180.0f * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.006f, 0.006f, 0.006f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
shinyMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
xwing.RenderModel();
blackhawkAngle += 0.1f;
if (blackhawkAngle > 360.0f)
{
blackhawkAngle = 0.1f;
}
model = glm::mat4(1.0f);
model = glm::rotate(model, -blackhawkAngle * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::translate(model, glm::vec3(-8.0f, 2.0f, 0.0f));
model = glm::rotate(model, -20.0f * toRadians, glm::vec3(0.0f, 0.0f, 1.0f));
model = glm::rotate(model, -90.0f * toRadians, glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 0.4f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
shinyMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
blackhawk.RenderModel();
//character
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(4.0f, 0.0f, -6.0f));
model = glm::rotate(model, -180.0f * toRadians, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 0.4f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
shinyMaterial.UseMaterial(uniformSpecularIntensity, uniformShininess);
character.RenderModel();
}
void DirectionalShadowMapPass(DirectionalLight* light)
{
directionalShadowShader.UseShader();
//set up the viewport as the same dimensions as the frame buffer
glViewport(0, 0, light->GetShadowMap()->GetShadowWidth(), light->GetShadowMap()->GetShadowHeight()); //make sure that the frame buffer that we are drawing to is also the same size of the viewport
light->GetShadowMap()->write(); //write to our shadowmap
glClear(GL_DEPTH_BUFFER_BIT); //Since we have attached our frame buffer, clear all the depth buffer information, if there is some depth buffer information
uniformModel = directionalShadowShader.GetModelLocation();
directionalShadowShader.SetDirectionalLightTransform(&light->CalculateLightTransform());
directionalShadowShader.Validate();
RenderScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void OmniShadowMapPass(PointLight* light)
{
//set up the viewport as the same dimensions as the frame buffer
glViewport(0, 0, light->GetShadowMap()->GetShadowWidth(), light->GetShadowMap()->GetShadowHeight()); //make sure that the frame buffer that we are drawing to is also the same size of the viewport
omniShadowShader.UseShader();
uniformModel = omniShadowShader.GetModelLocation();
uniformOmniLightPos = omniShadowShader.GetOmniLightPosLocation();
uniformFarPlane = omniShadowShader.GetFarPlaneLocation();
light->GetShadowMap()->write(); //write to our shadowmap
glClear(GL_DEPTH_BUFFER_BIT); //Since we have attached our frame buffer, clear all the depth buffer information, if there is some depth buffer information
glUniform3f(uniformOmniLightPos, light->GetPosition().x, light->GetPosition().y, light->GetPosition().z);
glUniform1f(uniformFarPlane, light->GetFarPlane());
omniShadowShader.SetLightMatrices(light->CalculateLightTransform());
omniShadowShader.Validate();
RenderScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void RenderPass(glm::mat4 projectionMatrix, glm::mat4 viewMatrix)
{
glViewport(0, 0, 1366, 768);
// Clear the window
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Clears the entire screen. RGB format
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clears the color buffer bit and the depth buffer bit
skybox.DrawSkybox(viewMatrix, projectionMatrix);
shaderList[0].UseShader();
uniformModel = shaderList[0].GetModelLocation();
uniformProjection = shaderList[0].GetProjectionLocation();
uniformView = shaderList[0].GetViewLocation();
uniformEyePosition = shaderList[0].GetEyePositionLocation(); //Holds the uniform value for the position of our camera
uniformSpecularIntensity = shaderList[0].GetSpecularIntensityLocation();
uniformShininess = shaderList[0].GetShininessLocation();
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniformMatrix4fv(uniformView, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniform3f(uniformEyePosition, camera.getCameraPosition().x, camera.getCameraPosition().y, camera.getCameraPosition().z);
shaderList[0].SetDirectionalLight(&mainLight);
shaderList[0].SetPointLights(pointLights, pointLightCount, 3, 0);
shaderList[0].SetSpotLights(spotLights, spotLightCount, 3 + pointLightCount, pointLightCount);
shaderList[0].SetDirectionalLightTransform(&mainLight.CalculateLightTransform());
mainLight.GetShadowMap()->Read(GL_TEXTURE2);
shaderList[0].SetTexture(1);
shaderList[0].SetDirectionalShadowMap(2);
glm::vec3 lowerLight = camera.getCameraPosition();
lowerLight.y -= 0.3f;
spotLights[0].SetFlash(lowerLight, camera.getCameraDirection());
shaderList[0].Validate();
RenderScene();
}
int main()
{
mainWindow = Window(1366, 768);
mainWindow.Initialise();
CreateObjects();
CreateShaders();
camera = Camera(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), -60.0f, 0.0f, 5.0f, 0.5f); //start at the middle
brickTexture = Texture("Textures/brick.png");
brickTexture.LoadTextureA();
dirtTexture = Texture("Textures/Circuit.png");
dirtTexture.LoadTextureA();
plainTexture = Texture("Textures/plain.png");
plainTexture.LoadTextureA();
shinyMaterial = Material(4.0f, 256); //the value for shine goes in powers of 2 = 2, 4, 8, 16, 32, 64.............
dullMaterial = Material(0.3f, 4);
xwing = Model();
xwing.LoadModel("Models/x-wing.obj");
blackhawk = Model();
blackhawk.LoadModel("Models/uh60.obj");
character = Model();
character.LoadModel("Models/character.obj"); //import and load the character
mainLight = DirectionalLight(2048, 2048,
1.0f, 0.53f, 0.3f,
0.1f, 0.9f,
-10.0f, -12.0f, 18.5f); //change the fourth parameter 0.2f, to increase or decrease the intensity of diffuse light
pointLights[0] = PointLight(1024, 1024,
0.01f, 100.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f,
1.0f, 2.0f, 0.0f,
0.3f, 0.2f, 0.1f);
pointLightCount++;
pointLights[1] = PointLight(1024, 1024,
0.01f, 100.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f,
-4.0f, 3.0f, 0.0f,
0.3f, 0.2f, 0.1f);
pointLightCount++;
spotLights[0] = SpotLight(1024, 1024,
0.01f, 100.0f,
1.0f, 1.0f, 1.0f,
0.0f, 2.0f,
0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
20.0f); //20.0f indicates the angle of our spotlight. In this case, 20 degrees.
spotLightCount++;
spotLights[1] = SpotLight(1024, 1024,
0.01f, 100.0f,
1.0f, 1.0f, 1.0f,
0.0f, 1.0f,
0.0f, -1.5f, 0.0f,
-100.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
20.0f); //20.0f indicates the angle of our spotlight. In this case, 20 degrees.
spotLightCount++;
std::vector<std::string> skyboxFaces;
//order - +x -x +y -y +z -z
//push_back is used to add to the end of the vector
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_rt.tga");
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_lf.tga");
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_up.tga");
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_dn.tga");
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_bk.tga");
skyboxFaces.push_back("Textures/Skybox/cupertin-lake_ft.tga");
skybox = Skybox(skyboxFaces);
glm::mat4 projection = glm::perspective(glm::radians(60.0f), (GLfloat) mainWindow.getBufferWidth()/ mainWindow.getBufferHeight(), 0.1f, 100.0f); //Divide the width by the height to get the aspect ratio
// loop until window closed
while (!mainWindow.getShouldClose())
{
GLfloat now = glfwGetTime(); //If you are using SDL instead of GLFW, you can use SDL GetPerformanceCounter();
deltaTime = now - lastTime; //how long it took the last loop to go around. In SDL ..... (now - lastTime)*1000/SDL_GetPerformanceFrequency()
lastTime = now;
// Get + Handle user input events
glfwPollEvents();
camera.keyControl(mainWindow.getKeys(), deltaTime);
camera.mouseControl(mainWindow.getXChange(), mainWindow.getYChange());
if (mainWindow.getKeys()[GLFW_KEY_L])
{
spotLights[0].Toggle();
mainWindow.getKeys()[GLFW_KEY_L] = false;
}
DirectionalShadowMapPass(&mainLight); //renders the scene to the frame buffer which will then save it to a texture
for (size_t i = 0; i < pointLightCount; i++)
{
OmniShadowMapPass(&pointLights[i]);
}
//go through all the spot lights
for (size_t i = 0; i < spotLightCount; i++)
{
OmniShadowMapPass(&spotLights[i]);
}
RenderPass(projection, camera.calculateViewMatrix());
glUseProgram(0);
mainWindow.swapBuffers();
}
return 0;
}