3D City v-1.0
Computer Graphics Project
engine.h
Go to the documentation of this file.
1#pragma once
2#include "core.h"
3#include <functional>
4#include <algorithm>
5#include <limits>
6#include <functional>
7
8#include "material.h"
9#include "pointLight.h"
10#include "camera.h"
11#include "thread_pool.hpp"
12
13inline static int roundfloat(const float &in) {
14 return in < 0 ? in - 0.5f : in + 0.5f;
15}
16
17inline static int rounddouble(const double &in) {
18 return in < 0 ? in - 0.5f : in + 0.5f;
19}
20
21class Vertex2;
26 std::vector<std::tuple<Vertex2 *, Mesh *>> fragments;
27 float *z;
29
30 float *clearedz;
32 size_t x_size, y_size;
34 framebuffer(const size_t &x, const size_t &y) : x_size(x), y_size(y) {
35 fragments.reserve(x_size * y_size);
37 z = new float[x_size * y_size];
38
40 clearedz = new float[x_size * y_size];
41 for (uint32_t x = 0; x < x_size * y_size; ++x) {
42 clearedcolorlayer[x] = color(0, 0, 0, 255);
43 clearedz[x] = -std::numeric_limits<float>::max();
44 }
45
46 xmax = x_size / 2;
47 xmin = -xmax;
48 ymax = y_size / 2;
49 ymin = -ymax;
50
51 clear();
52 }
53
55 delete[] colorlayer;
56 delete[] z;
57 }
58
59 void clear() {
60 memcpy(colorlayer, clearedcolorlayer, x_size * y_size * sizeof(color));
61 memcpy(z, clearedz, x_size * y_size * sizeof(float));
62 }
63};
64
65#ifdef PHONG_SHADING
66#define EXTRA_VERTEX_INFO vec3
67#else
68#define EXTRA_VERTEX_INFO vec3_T<vec3>
69#endif
70
74struct Vertex2 {
76 //fragment Position for phong and INTENSITY for gouraud
78 Vertex2(const Vertex &vin, const EXTRA_VERTEX_INFO &pos) : v(vin), extraInfoAboutVertex(pos) {}
80 Vertex2 operator*(const float &f) const {
81 return Vertex2(v * f, extraInfoAboutVertex * f);
82 }
83 Vertex2 operator+(const Vertex2 &f) const {
85 }
86 Vertex2 operator-(const Vertex2 &f) const {
88 }
89};
90
94struct engine {
95
97
98 uint32_t vao, vbo, ibo, tex, shader;
99
100 private:
102
103 const char *vertexShaderSource = R"(#version 330 core
104 layout (location = 0) in vec3 aPos;
105 layout (location = 1) in vec2 texCoord;
106 out vec2 f_texCoord;
107 void main()
108 {
109 gl_Position = vec4(aPos.xyz, 1.0);
110 f_texCoord=texCoord;
111 }
112 )";
113
114 const char *fragmentShaderSource = R"(#version 330 core
115 out vec4 FragColor;
116 in vec2 f_texCoord;
117 uniform sampler2D tex;
118 void main()
119 {
120 FragColor = texture(tex,f_texCoord);
121 //FragColor = vec4(f_texCoord.x,f_texCoord.y,0,0);
122 // if(FragColor.xyz==vec3(0)){
123 // //FragColor =vec4(FragColor.w);
124 // }
125 }
126 )";
127
128 float vertices[20] =
129 {
130 // x y z
131 -1.0f, -1.0f, -0.0f, 0.f, 0.f,
132 1.0f, 1.0f, -0.0f, 1.f, 1.f,
133 -1.0f, 1.0f, -0.0f, 0.f, 1.f,
134 1.0f, -1.0f, -0.0f, 1.f, 0.f};
135
136 uint32_t indices[6] =
137 {
138 // 2---,1
139 // | .' |
140 // 0'---3
141 0, 1, 2,
142 0, 3, 1};
143
144 public:
148 engine(const uint32_t &x, const uint32_t &y) {
149 fboCPU = new framebuffer(x, y);
150
151 glGenVertexArrays(1, &vao);
152 glGenBuffers(1, &vbo);
153 glGenBuffers(1, &ibo);
154
155 glBindVertexArray(vao);
156
157 glBindBuffer(GL_ARRAY_BUFFER, vbo);
158 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
159
160 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
161 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
162
163 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)0);
164 glEnableVertexAttribArray(0);
165 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void *)(3 * sizeof(float)));
166 glEnableVertexAttribArray(1);
167 glBindVertexArray(0);
168
169 glBindBuffer(GL_ARRAY_BUFFER, 0);
170
171 GLcall(glGenTextures(1, &tex));
172 GLcall(glActiveTexture(GL_TEXTURE0));
173 GLcall(glBindTexture(GL_TEXTURE_2D, tex));
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
176 GLcall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fboCPU->x_size, fboCPU->y_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
177 GLcall(glBindTexture(GL_TEXTURE_2D, 0));
178
179 // build and compile our shader program
180 // ------------------------------------
181 // vertex shader
182 unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
183 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
184 glCompileShader(vertexShader);
185 // check for shader compile errors
186 int success;
187 char infoLog[512];
188 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
189 if (!success) {
190 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
191 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"
192 << infoLog << std::endl;
193 }
194 // fragment shader
195 unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
196 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
197 glCompileShader(fragmentShader);
198 // check for shader compile errors
199 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
200 if (!success) {
201 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
202 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"
203 << infoLog << std::endl;
204 }
205 // link shaders
206 shader = glCreateProgram();
207 glAttachShader(shader, vertexShader);
208 glAttachShader(shader, fragmentShader);
209 glLinkProgram(shader);
210 // check for linking errors
211 glGetProgramiv(shader, GL_LINK_STATUS, &success);
212 if (!success) {
213 glGetProgramInfoLog(shader, 512, NULL, infoLog);
214 std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n"
215 << infoLog << std::endl;
216 }
217 glDeleteShader(vertexShader);
218 glDeleteShader(fragmentShader);
219 glUseProgram(shader);
220
221 auto location = glGetUniformLocation(shader, "tex");
222 if (location == -1)
223 std::cout << "Warning: uniform tex does not exist !" << std::endl;
224 glUniform1i(location, 0);
225 glUseProgram(0);
226 }
227
232 delete fboCPU;
233 GLcall(glDeleteBuffers(1, &vbo));
234 GLcall(glDeleteVertexArrays(1, &vao));
235 GLcall(glDeleteTextures(1, &tex));
236 GLcall(glDeleteProgram(shader));
237 }
238
242 void clear() {
243 triangles.clear();
244 glClear(GL_COLOR_BUFFER_BIT);
245 fboCPU->clear();
246 }
247
251 void draw() {
252 if (wireframe) {
253 for (auto &tris : triangles) {
254 draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[0].v.position.x), roundfloat(std::get<0>(tris)[0].v.position.y), roundfloat(std::get<0>(tris)[1].v.position.x), roundfloat(std::get<0>(tris)[1].v.position.y), color(255));
255 draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[1].v.position.x), roundfloat(std::get<0>(tris)[1].v.position.y), roundfloat(std::get<0>(tris)[2].v.position.x), roundfloat(std::get<0>(tris)[2].v.position.y), color(255));
256 draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[2].v.position.x), roundfloat(std::get<0>(tris)[2].v.position.y), roundfloat(std::get<0>(tris)[0].v.position.x), roundfloat(std::get<0>(tris)[0].v.position.y), color(255));
257 }
258 } else {
260 // for (auto &tris : triangles) {
261 // draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[0].v.position.x), roundfloat(std::get<0>(tris)[0].v.position.y), roundfloat(std::get<0>(tris)[1].v.position.x), roundfloat(std::get<0>(tris)[1].v.position.y), color(255));
262 // draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[1].v.position.x), roundfloat(std::get<0>(tris)[1].v.position.y), roundfloat(std::get<0>(tris)[2].v.position.x), roundfloat(std::get<0>(tris)[2].v.position.y), color(255));
263 // draw_bresenham_adjusted(roundfloat(std::get<0>(tris)[2].v.position.x), roundfloat(std::get<0>(tris)[2].v.position.y), roundfloat(std::get<0>(tris)[0].v.position.x), roundfloat(std::get<0>(tris)[0].v.position.y), color(255));
264 // }
265 }
266 uint8_t *imageData = (uint8_t *)&fboCPU->colorlayer[0].col;
267 glUseProgram(shader);
268 GLcall(glBindTexture(GL_TEXTURE_2D, tex));
269 GLcall(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fboCPU->x_size, fboCPU->y_size, GL_RGBA, GL_UNSIGNED_BYTE, imageData));
270 glBindVertexArray(vao);
271 GLcall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));
272 }
273
277 std::vector<std::tuple<std::array<Vertex2, 3>, Mesh *>> triangles;
278
282 float nearPlane = 1.0f;
283
287 bool cullBackface = true;
288
292 Mesh *currentMesh = nullptr;
293
300 std::vector<pointLight> pointLights;
301
305 camera *cam = nullptr;
306
307 bool wireframe = false;
308
310
314 color getcolor(const Vertex2 &v, Mesh *mesh) const {
315 color col;
316
317 //check if texture exists
318 if (mesh->material.diffuse.w) {
319 float intpart;
320 int tx = roundfloat(std::modf(v.v.texCoord.x, &intpart) * (mesh->material.diffuse.w - 1));
321 int ty = roundfloat(std::modf(v.v.texCoord.y, &intpart) * (mesh->material.diffuse.h - 1));
322 auto ret = &mesh->material.diffuse.m_data[(abs(tx) + mesh->material.diffuse.w * abs(ty)) * mesh->material.diffuse.m_bpp];
323 col = color(*ret, *(ret + 1), *(ret + 2));
324 } else
325 col = mesh->material.diffuseColor;
326
327 if (!mesh->doLightCalculations) {
328 return col;
329 }
330 // col = color(vec3(v.v.texCoord.x, v.v.texCoord.y, 1));
331 // return col;
332 color result(0, 0, 0, 255);
333#ifdef PHONG_SHADING
334 const auto viewDir = (cam->eye - v.extraInfoAboutVertex).normalize();
335 for (auto &light : pointLights) {
336 const float test = vec3::dist(cam->eye, light.getpos());
337 // if (test > lightRenderDistance) {
338 // continue;
339 // }
340 float dist = vec3::dist(v.extraInfoAboutVertex, light.getpos());
341 float int_by_at = light.intensity / (light.constant + light.linear * dist + light.quadratic * (dist * dist));
342 if (int_by_at > 0.01) {
343 result += CalcPointLight(light, v.v.normal, v.extraInfoAboutVertex, viewDir, col, int_by_at, &mesh->material);
344 }
345 }
346 result += CalcDirLight(v.v.normal, viewDir, col, &mesh->material);
347#else
348 // result += col * (v.extraInfoAboutVertex.x);
349 result += col * (v.extraInfoAboutVertex.y);
350 result += color(v.extraInfoAboutVertex.z);
351#endif
352 result += col * (ambientLightColor * ambientLightIntensity);
353
354 return result;
355 }
356
357 bool printed = false;
361 void makeRequiredTriangles(const std::vector<Vertex> &vertices, const std::vector<uint32_t> &indices, const mat4f &modelmat) {
362 const auto view = trans::lookAt(cam->eye, cam->eye + cam->getViewDir(), cam->getUp());
363 const auto per = trans::persp(fboCPU->x_size, fboCPU->y_size, cam->FOV);
364 // #ifdef MULTITHREADED
365 // pool.parallelize_loop(0, indices.size() / 3, [&](const unsigned int start, const unsigned int end) {
366 // for (unsigned int i = start; i < end; i++) {
367 // std::array<Vertex, 3> points = {vertices[indices[i * 3]], vertices[indices[i * 3 + 1]], vertices[indices[i * 3 + 2]]};
368 // makeRequiredTrianglesHelper(points, modelmat, view, per);
369 // }
370 // });
371 // #else
372 // #endif
373 for (size_t i = 0; i < indices.size() / 3; i++) {
374 std::array<Vertex, 3> points = {vertices[indices[i * 3]], vertices[indices[i * 3 + 1]], vertices[indices[i * 3 + 2]]};
375 makeRequiredTrianglesHelper(points, modelmat, view, per);
376 }
377
378 // printf("triangle_count: %d\n", triangles.size());
379 // printf("\033[F");
380 }
381
382 void setTime(float time) {
383 assert(time >= 0.f && time < 24.f);
384 dirlight.intensity = 0.7666921f * exp(-pow((time - 12.4125f) / (3.047894f), 2.f) / 2.f);
386 const uint8_t min = floor(time), max = ceil(time);
387 float alpha;
388 if (min == max)
389 alpha = 0;
390 else
391 alpha = (max - time) / (max - min);
392
393 float green = greenTimeMap[min] + alpha * (greenTimeMap[max] - greenTimeMap[min]);
394 float blue = blueTimeMap[min] + alpha * (blueTimeMap[max] - blueTimeMap[min]);
395 ambientLightColor = color(vec3(1, green, blue));
396 const float t = M_PI * sin(M_PI * time / 24);
397 dirlight.direction = vec3(sin(t), -cos(t), 0);
399
400 // printf("time: %f\n", time);
401 // printf("ambientlight color: (%d,%d,%d)\n", ambientLightColor.r(), ambientLightColor.g(), ambientLightColor.b());
402 // printf("dirlight intensity: %f\n", dirlight.intensity);
403 // printVec(dirlight.direction);
404
405 // printf("\033[F");
406 // printf("\033[F");
407 // printf("\033[F");
408 // printf("\033[F");
409 }
410
411 private:
412 std::unordered_map<uint8_t, float>
413 greenTimeMap = {{0, 0}, {1, 0.1}, {2, 0.3}, {3, 0.3}, {4, 0.35}, {5, 0.4}, {6, 0.5}, {7, 0.55}, {8, 0.6}, {9, 1}, {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1}, {16, 1}, {17, 0.8}, {18, 0.5}, {19, 0.4}, {20, 0.3}, {21, 0.25}, {22, 0.1}, {23, 0.06}, {24, 0}},
414 blueTimeMap = {{0, 0}, {1, 0}, {2, 0}, {3, 0.05}, {4, 0.06}, {5, 0.1}, {6, 0.15}, {7, 0.25}, {8, 0.35}, {9, 0.75}, {10, 0.8}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1}, {16, 0.8}, {17, 0.6}, {18, 0.4}, {19, 0.1}, {20, 0.01}, {21, 0}, {22, 0}, {23, 0}, {24, 0}};
415
416 static inline float max(const float &first, const float &second) {
417 return first > second ? first : second;
418 }
419
420 static inline vec3 reflect(const vec3 &I, const vec3 &N) {
421 return I - N * 2.0 * vec3::dot(N, I);
422 }
423
427 color CalcDirLight(const vec3 &normal, const vec3 &viewdir, const color &col, const Material *material) const {
428 auto diff = max(vec3::dot(normal, -dirlight.direction), 0.0f);
429 auto spec = pow(max(vec3::dot(viewdir, reflect(dirlight.direction, normal)), 0.0), material->shininess);
430 color diffuse = col * dirlight.col * dirlight.intensity * material->DiffuseStrength * diff;
431 color specular = dirlight.col * dirlight.intensity * material->SpecularStrength * spec;
432 diffuse += specular;
433 diffuse.a() = 255;
434 return std::move(diffuse);
435 }
436
440 static color CalcPointLight(const pointLight &light, const vec3 &normal, const vec3 &fragPos, const vec3 &viewDir, const color &diffuseColor, float int_by_at, const Material *material) {
441 const vec3 lightDir = vec3::normalize(light.getpos() - fragPos);
442 const float diff = max(vec3::dot(normal, lightDir), 0.0);
443 const vec3 halfwayDir = vec3::normalize(lightDir + viewDir);
444 const float spec = pow(max(vec3::dot(normal, halfwayDir), 0.0), material->shininess);
445 const color ambient = diffuseColor * light.get_ambient_color() * (material->AmbientStrength * int_by_at);
446 const color diffuse = diffuseColor * light.get_diffuse_color() * (material->DiffuseStrength * diff * int_by_at);
447 const color specular = light.get_diffuse_color() * (material->SpecularStrength * spec * int_by_at);
448 // return (ambient + diffuse + specular);
449 return (diffuse + specular);
450 }
451
452 std::mutex fboCPUMutex;
453
454 void makeRequiredTrianglesHelper(std::array<Vertex, 3> &points, const mat4f &modelmat, const mat4f &view, const mat4f &per) {
455 std::array<bool, 3> clip{false, false, false};
456 std::array<Vertex2, 3> t;
457// Vertex temp;
458#ifdef PHONG_SHADING
459 std::array<EXTRA_VERTEX_INFO, 3> extraInfoAboutVertex{modelmat * points[0].position, modelmat * points[1].position, modelmat * points[2].position};
460#else
461 std::array<EXTRA_VERTEX_INFO, 3> extraInfoAboutVertex;
462 extraInfoAboutVertex[0].x = modelmat * points[0].position;
463 extraInfoAboutVertex[1].x = modelmat * points[1].position;
464 extraInfoAboutVertex[2].x = modelmat * points[2].position;
465#endif
466 std::array<vec4, 3> modelviewTransformed{view * (modelmat * points[0].position), view * (modelmat * points[1].position), view * (modelmat * points[2].position)};
467
468 if (modelviewTransformed[0].z > -nearPlane) {
469 clip[0] = true;
470 }
471
472 if (modelviewTransformed[1].z > -nearPlane) {
473 clip[1] = true;
474 }
475
476 if (modelviewTransformed[2].z > -nearPlane) {
477 clip[2] = true;
478 }
479
480 points[0].position = modelviewTransformed[0];
481 points[0].normal = modelmat * points[0].normal;
482 points[1].position = modelviewTransformed[1];
483 points[1].normal = modelmat * points[1].normal;
484 points[2].position = modelviewTransformed[2];
485 points[2].normal = modelmat * points[2].normal;
486
487 vec4 centroid = (points[0].position + points[1].position + points[2].position) / 3;
488
489 if (cullBackface && vec3::dot(view * points[0].normal, (vec3)centroid) > 0) {
490 return;
491 }
492
493#ifndef PHONG_SHADING
494 fillExtraInformationForGoraudShading(points[0], extraInfoAboutVertex[0]);
495 fillExtraInformationForGoraudShading(points[1], extraInfoAboutVertex[1]);
496 fillExtraInformationForGoraudShading(points[2], extraInfoAboutVertex[2]);
497#endif
498
499 if ((clip[0] && clip[1] && clip[2])) {
500 return;
501 } else if (clip[0]) {
502 if (clip[1]) {
503 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 0, 1, 2, t);
504 triangles.emplace_back(std::make_tuple(t, currentMesh));
505 return;
506 } else if (clip[2]) {
507 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 0, 2, 1, t);
508 triangles.emplace_back(std::make_tuple(t, currentMesh));
509 return;
510 } else {
511 clip1helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 0, t, triangles);
512 return;
513 }
514 } else if (clip[1]) {
515 if (clip[2]) {
516 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 1, 2, 0, t);
517 triangles.emplace_back(std::make_tuple(t, currentMesh));
518 return;
519 } else if (clip[0]) {
520 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 1, 0, 2, t);
521 triangles.emplace_back(std::make_tuple(t, currentMesh));
522 return;
523 } else {
524 clip1helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 1, t, triangles);
525 return;
526 }
527 } else if (clip[2]) {
528 if (clip[0]) {
529 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 2, 0, 1, t);
530 triangles.emplace_back(std::make_tuple(t, currentMesh));
531 return;
532 } else if (clip[1]) {
533 clip2helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 2, 1, 0, t);
534 triangles.emplace_back(std::make_tuple(t, currentMesh));
535 return;
536 } else {
537 clip1helper(per, extraInfoAboutVertex, modelviewTransformed, points.data(), 2, t, triangles);
538 return;
539 }
540 }
541
542 t[0] = Vertex2(Vertex::perspectiveMul(points[0], per), extraInfoAboutVertex[0]);
543 t[1] = Vertex2(Vertex::perspectiveMul(points[1], per), extraInfoAboutVertex[1]);
544 t[2] = Vertex2(Vertex::perspectiveMul(points[2], per), extraInfoAboutVertex[2]);
545 t[0].extraInfoAboutVertex *= t[0].v.position.z;
546 t[1].extraInfoAboutVertex *= t[1].v.position.z;
547 t[2].extraInfoAboutVertex *= t[2].v.position.z;
548
549 if ((t[0].v.position.x > fboCPU->xmax || t[0].v.position.x < fboCPU->xmin) && (t[0].v.position.y > fboCPU->ymax || t[0].v.position.y < fboCPU->ymin) &&
550 (t[1].v.position.x > fboCPU->xmax || t[1].v.position.x < fboCPU->xmin) && (t[1].v.position.y > fboCPU->ymax || t[1].v.position.y < fboCPU->ymin) &&
551 (t[2].v.position.x > fboCPU->xmax || t[2].v.position.x < fboCPU->xmin) && (t[2].v.position.y > fboCPU->ymax || t[2].v.position.y < fboCPU->ymin))
552 return;
553
554 triangles.emplace_back(std::make_tuple(t, currentMesh));
555 }
556
560 void
561 putpixel_adjusted(int x, int y, float z, const color &col = color(255)) {
562 assert(x < fboCPU->xmax && x > fboCPU->xmin && y < fboCPU->ymax && y > fboCPU->ymin);
563 const size_t indx = ((size_t)x + fboCPU->xmax) + ((size_t)y + fboCPU->ymax) * fboCPU->x_size;
564
565 fboCPU->colorlayer[indx] = col;
566 fboCPU->z[indx] = z;
567 }
568
572 inline float getpixelZ_adjusted(int x, int y) const {
573 const bool test = ((size_t)x + fboCPU->xmax) < fboCPU->x_size && (x + fboCPU->xmax) >= 0 && ((size_t)y + fboCPU->ymax) < fboCPU->y_size && (y + fboCPU->ymax) >= 0;
574 return test ? fboCPU->z[((size_t)x + fboCPU->xmax) + ((size_t)y + fboCPU->ymax) * fboCPU->x_size] : std::numeric_limits<float>::max();
575 }
576
580 void draw_bresenham_adjusted(int x1, int y1, int x2, int y2, const color &col = color(0)) {
581 int dx = abs(x2 - x1);
582 int dy = abs(y2 - y1);
583
584 int lx = x2 > x1 ? 1 : -1;
585 int ly = y2 > y1 ? 1 : -1;
586
587 int x = x1, y = y1;
588 bool changed = false;
589
590 if (dx <= dy) {
591 changed = true;
592 std::swap(dx, dy);
593 std::swap(lx, ly);
594 std::swap(x, y);
595 }
596 int p = 2 * dy - dx;
597 for (int k = 0; k <= dx; k++) {
598
599 if (!changed) {
600 if (x < fboCPU->xmax && x > fboCPU->xmin && y < fboCPU->ymax && y > fboCPU->ymin)
601 putpixel_adjusted(x, y, 1, col);
602 } else {
603 if (y < fboCPU->xmax && y > fboCPU->xmin && x < fboCPU->ymax && x > fboCPU->ymin)
604 putpixel_adjusted(y, x, 1, col);
605 }
606
607 if (p < 0) {
608 x += lx;
609 p += 2 * dy;
610 } else {
611 x += lx;
612 y += ly;
613 p += 2 * dy - 2 * dx;
614 }
615 }
616 }
617
618 inline void clip1(const std::array<vec4, 3> &tris, unsigned char which, float &u1, float &u2) const {
619 u1 = -(nearPlane + tris[which].z) / (tris[(which + 1) % 3].z - tris[which].z);
620 u2 = -(nearPlane + tris[which].z) / (tris[(which + 2) % 3].z - tris[which].z);
621 }
622
623 inline void clip2(const std::array<vec4, 3> &tris, unsigned char idx1, unsigned char idx2, unsigned char rem, float &u1, float &u2) const {
624 u1 = -(nearPlane + tris[idx1].z) / (tris[rem].z - tris[idx1].z);
625 u2 = -(nearPlane + tris[idx2].z) / (tris[rem].z - tris[idx2].z);
626 }
627
631 inline void clip2helper(const mat4f &per, const std::array<EXTRA_VERTEX_INFO, 3> &extraInfoAboutVertex, const std::array<vec4, 3> &modelviewTransformed, Vertex *points, unsigned char idx1, unsigned char idx2, unsigned char rem, std::array<Vertex2, 3> &t) {
632 float u1, u2;
633 clip2(modelviewTransformed, idx1, idx2, rem, u1, u2);
634
635 t[idx1] = Vertex2(Vertex::perspectiveMul(points[idx1] + (points[rem] - points[idx1]) * u1, per), extraInfoAboutVertex[idx1] + (extraInfoAboutVertex[rem] - extraInfoAboutVertex[idx1]) * u1);
636 t[idx2] = Vertex2(Vertex::perspectiveMul(points[idx2] + (points[rem] - points[idx2]) * u2, per), extraInfoAboutVertex[idx2] + (extraInfoAboutVertex[rem] - extraInfoAboutVertex[idx2]) * u2);
637 t[rem] = Vertex2(Vertex(modelviewTransformed[rem], points[rem].normal, points[rem].texCoord).perspectiveMul(per), extraInfoAboutVertex[rem]);
638
639 t[idx1].extraInfoAboutVertex *= t[idx1].v.position.z;
640 t[idx2].extraInfoAboutVertex *= t[idx2].v.position.z;
641 t[rem].extraInfoAboutVertex *= t[rem].v.position.z;
642 }
643
647 inline void clip1helper(const mat4f &per, const std::array<EXTRA_VERTEX_INFO, 3> &extraInfoAboutVertex, const std::array<vec4, 3> &modelviewTransformed, Vertex *points, unsigned char idx1, std::array<Vertex2, 3> &t, std::vector<std::tuple<std::array<Vertex2, 3>, Mesh *>> &triangles) {
648 float u1, u2;
649 unsigned char idx2 = (idx1 + 1) % 3, idx3 = (idx1 + 2) % 3;
650 clip1(modelviewTransformed, idx1, u1, u2);
651
652 t[idx1] = Vertex2(Vertex::perspectiveMul(points[idx1] + (points[idx2] - points[idx1]) * u1, per), extraInfoAboutVertex[idx1] + (extraInfoAboutVertex[idx2] - extraInfoAboutVertex[idx1]) * u1);
653 t[idx2] = Vertex2(Vertex(modelviewTransformed[idx2], points[idx2].normal, points[idx2].texCoord).perspectiveMul(per), extraInfoAboutVertex[idx2]);
654 t[idx3] = Vertex2(Vertex(modelviewTransformed[idx3], points[idx3].normal, points[idx3].texCoord).perspectiveMul(per), extraInfoAboutVertex[idx3]);
655 t[idx1].extraInfoAboutVertex *= t[idx1].v.position.z;
656 t[idx2].extraInfoAboutVertex *= t[idx2].v.position.z;
657 t[idx3].extraInfoAboutVertex *= t[idx3].v.position.z;
658 const std::lock_guard<std::mutex> lock(fboCPUMutex);
659 triangles.emplace_back(std::make_tuple(t, currentMesh));
660 t[idx2] = t[idx3];
661 t[idx3] = Vertex2(Vertex::perspectiveMul(points[idx1] + (points[idx3] - points[idx1]) * u2, per), extraInfoAboutVertex[idx1] + (extraInfoAboutVertex[idx3] - extraInfoAboutVertex[idx1]) * u2);
662 t[idx3].extraInfoAboutVertex *= t[idx3].v.position.z;
663 triangles.emplace_back(std::make_tuple(t, currentMesh));
664 }
665
669 void fillBottomFlatTriangle(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh) {
670 assert(fabs(v1.v.position.y - v0.v.position.y) < 0.01);
671 assert(v1.v.position.x >= v0.v.position.x);
672 // calulcate slopes in screen space
673 const double m0 = (v2.v.position.x - v0.v.position.x) / (v2.v.position.y - v0.v.position.y);
674 const double m1 = (v2.v.position.x - v1.v.position.x) / (v2.v.position.y - v1.v.position.y);
675
676 // calculate start and end scanlines
677 int yStart = (int)ceil(v0.v.position.y - 0.5f);
678 const int yEnd = (int)ceil(v2.v.position.y - 0.5f); // the scanline AFTER the last line drawn
679
680 const double unit0 = 1.f / (v2.v.position.y - v0.v.position.y);
681 double u0 = 0;
682
683 Vertex2 diff0 = v2 - v0, diff1 = v2 - v1, diff2;
684 Vertex2 vx0, vx1, vx2;
685
686 if (yStart <= fboCPU->ymin) {
687 u0 = unit0 * (fboCPU->ymin - yStart + 1);
688 yStart = fboCPU->ymin + 1;
689 }
690 for (int y = yStart; y < yEnd && y < fboCPU->ymax; ++y, u0 += unit0) {
691 const double px0 = m0 * (double(y) + 0.5f - v0.v.position.y) + v0.v.position.x;
692 const double px1 = m1 * (double(y) + 0.5f - v1.v.position.y) + v1.v.position.x;
693
694 vx0 = v0 + diff0 * u0;
695 vx1 = v1 + diff1 * u0;
696
697 // calculate start and end pixels
698 int xStart = (int)ceil(px0 - 0.5f);
699 const int xEnd = (int)ceil(px1 - 0.5f); // the pixel AFTER the last pixel drawn
700
701 const double unit2 = 1.f / (px1 - px0);
702 double u2 = 0;
703 diff2 = vx1 - vx0;
704
705 if (xStart <= fboCPU->xmin) {
706 u2 = unit2 * (fboCPU->xmin - xStart + 1);
707 xStart = fboCPU->xmin + 1;
708 }
709 for (int x = xStart; x < xEnd && x < fboCPU->xmax; x++, u2 += unit2) {
710 const double z = 1 / (vx0.v.position.z + (diff2.v.position.z) * u2);
711#ifdef MULTITHREADED
712 const std::lock_guard<std::mutex> lock(fboCPUMutex);
713#endif
714 auto gotz = getpixelZ_adjusted(x, y);
715 if (gotz < z) {
716 vx2 = vx0 + diff2 * u2;
717 vx2.v.texCoord /= vx2.v.position.z;
718 vx2.v.normal /= vx2.v.position.z;
719 vx2.extraInfoAboutVertex /= vx2.v.position.z;
720 putpixel_adjusted(x, y, z, getcolor(vx2, mesh));
721 }
722 }
723 }
724 }
725
729 void fillTopFlatTriangle(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh) {
730 assert(fabs(v2.v.position.y - v1.v.position.y) < 0.01);
731 assert(v2.v.position.x >= v1.v.position.x);
732 // calulcate slopes in screen space
733 const double m0 = (v1.v.position.x - v0.v.position.x) / (v1.v.position.y - v0.v.position.y);
734 const double m1 = (v2.v.position.x - v0.v.position.x) / (v2.v.position.y - v0.v.position.y);
735
736 // calculate start and end scanlines
737 const int yStart = (int)ceil(v0.v.position.y - 0.5);
738 const int yEnd = (int)ceil(v2.v.position.y - 0.5); // the scanline AFTER the last line drawn
739
740 const double unit0 = 1.0 / (v1.v.position.y - v0.v.position.y), unit1 = 1.0 / (v2.v.position.y - v0.v.position.y);
741 double u0 = 0, u1 = 0;
742
743 Vertex2 diff0 = v1 - v0, diff1 = v2 - v0, diff2;
744 Vertex2 vx0, vx1, vx2;
745
746 for (int y = yStart; y < yEnd && y < fboCPU->ymax; y++, u0 += unit0, u1 += unit1) {
747 if (y <= fboCPU->ymin) {
748 continue;
749 }
750 const double px0 = m0 * (double(y) + 0.5f - v0.v.position.y) + v0.v.position.x;
751 const double px1 = m1 * (double(y) + 0.5f - v0.v.position.y) + v0.v.position.x;
752
753 vx0 = v0 + diff0 * u0;
754 vx1 = v0 + diff1 * u1;
755
756 // calculate start and end pixels
757 const int xStart = (int)ceil(px0 - 0.5f);
758 const int xEnd = (int)ceil(px1 - 0.5f); // the pixel AFTER the last pixel drawn
759
760 const double unit2 = 1.0 / (px1 - px0);
761 double u2 = 0;
762 diff2 = vx1 - vx0;
763
764 for (int x = xStart; x < xEnd && x < fboCPU->xmax; x++, u2 += unit2) {
765 if (x <= fboCPU->xmin) {
766 continue;
767 }
768 double z = 1 / (vx0.v.position.z + (diff2.v.position.z) * u2);
769#ifdef MULTITHREADED
770 const std::lock_guard<std::mutex> lock(fboCPUMutex);
771#endif
772 const auto gotz = getpixelZ_adjusted(x, y);
773 if (gotz < z) {
774 vx2 = vx0 + diff2 * u2;
775 vx2.v.texCoord /= vx2.v.position.z;
776 vx2.v.normal /= vx2.v.position.z;
777 vx2.extraInfoAboutVertex /= vx2.v.position.z;
778 putpixel_adjusted(x, y, z, getcolor(vx2, mesh));
779 }
780 }
781 }
782 }
783
784 void calculateBarycentricCoordinates(const vec2 &p, const vec4 &v1, const vec4 &v2, const vec4 &v3, std::array<float, 3> &values) {
785 const float area = (v2.y - v3.y) * (v1.x - v3.x) + (v3.x - v2.x) * (v1.y - v3.y);
786 values[0] = fabs(((v2.y - v3.y) * (p.x - v3.x) + (v3.x - v2.x) * (p.y - v3.y)) / area);
787 values[1] = fabs(((v3.y - v1.y) * (p.x - v3.x) + (v1.x - v3.x) * (p.y - v3.y)) / area);
788 values[2] = 1.f - values[0] - values[1];
789
790 // if (fabs(values[0]) > 1 && fabs(values[1]) > 1 && fabs(values[2]) > 1) {
791 // printVec(vec2(v1));
792 // printVec(vec2(v2));
793 // printVec(vec2(v3));
794 // printVec(p);
795 // assert(false);
796 // }
797
798 // float dist[] = {vec2::dist(p, vec2(v1)), vec2::dist(p, vec2(v2)), vec2::dist(p, vec2(v3))};
799 // if (dist[0] > dist[1] && dist[0] > dist[2]) {
800 // if (fabs(values[0]) > fabs(values[1]) && fabs(values[0]) > fabs(values[2])) {
801 // printVec(vec2(v1));
802 // printVec(vec2(v2));
803 // printVec(vec2(v3));
804 // printVec(p);
805 // assert(false);
806 // }
807 // } else if (dist[1] > dist[0] && dist[1] > dist[2]) {
808 // if (fabs(values[1]) > fabs(values[0]) && fabs(values[1]) > fabs(values[2])) {
809 // printVec(vec2(v1));
810 // printVec(vec2(v2));
811 // printVec(vec2(v3));
812 // printVec(p);
813 // assert(false);
814 // }
815 // } else {
816 // if (fabs(values[2]) > fabs(values[1]) && fabs(values[2]) > fabs(values[0])) {
817 // printVec(vec2(v1));
818 // printVec(vec2(v2));
819 // printVec(vec2(v3));
820 // printVec(p);
821 // assert(false);
822 // }
823 // }
824 }
825
830 void fillBottomFlatTriangleBary(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh) {
831 assert(fabs(v1.v.position.y - v0.v.position.y) < 0.01);
832 assert(v1.v.position.x >= v0.v.position.x);
833
834 const double m0 = (double)(v2.v.position.x - v0.v.position.x) / (v2.v.position.y - v0.v.position.y);
835 const double m1 = (double)(v2.v.position.x - v1.v.position.x) / (v2.v.position.y - v1.v.position.y);
836
837 const int yStart = (int)ceil(v0.v.position.y - 0.5f);
838 const int yEnd = (int)ceil(v2.v.position.y - 0.5f); // the scanline AFTER the last line drawn
839
840 const double unit0 = (v2.v.position.y - v0.v.position.y) / (yEnd - yStart);
841 double u0 = 0;
842
843 Vertex2 vx2;
844 std::array<float, 3> coefficients;
845
846 for (int y = yStart; y < yEnd && y < fboCPU->ymax; ++y, u0 += unit0) {
847 if (y <= fboCPU->ymin) {
848 continue;
849 }
850 const double px0 = m0 * (double(y) + 0.5 - v0.v.position.y) + v0.v.position.x;
851 const double px1 = m1 * (double(y) + 0.5 - v1.v.position.y) + v1.v.position.x;
852
853 const int xStart = (int)ceil(px0 - 0.5);
854 const int xEnd = (int)ceil(px1 - 0.5);
855
856 const double unit2 = (px1 - px0) / (xEnd - xStart);
857 double u2 = 0;
858
859 for (int x = xStart; x < xEnd && x < fboCPU->xmax; x++, u2 += unit2) {
860 if (x <= fboCPU->xmin) {
861 continue;
862 }
863 const vec2 pos(px0 + u2, v0.v.position.y + u0);
864 calculateBarycentricCoordinates(pos, v0.v.position, v1.v.position, v2.v.position, coefficients);
865
866 double z = 1 / (coefficients[0] * v0.v.position.z + coefficients[1] * v1.v.position.z + coefficients[2] * v2.v.position.z);
867#ifdef MULTITHREADED
868 const std::lock_guard<std::mutex> lock(fboCPUMutex);
869#endif
870 auto gotz = getpixelZ_adjusted(x, y);
871 if (gotz < z) {
872 vx2 = v0 * coefficients[0] + v1 * coefficients[1] + v2 * coefficients[2];
873 vx2.v.texCoord /= vx2.v.position.z;
874 vx2.v.normal /= vx2.v.position.z;
875 vx2.extraInfoAboutVertex /= vx2.v.position.z;
876 putpixel_adjusted(x, y, z, getcolor(vx2, mesh));
877 }
878 }
879 }
880 }
881
882 void fillTopFlatTriangleBary(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh) {
883 assert(fabs(v2.v.position.y - v1.v.position.y) < 0.01);
884 assert(v2.v.position.x >= v1.v.position.x);
885 // calulcate slopes in screen space
886 const double m0 = (v1.v.position.x - v0.v.position.x) / (v1.v.position.y - v0.v.position.y);
887 const double m1 = (v2.v.position.x - v0.v.position.x) / (v2.v.position.y - v0.v.position.y);
888
889 // calculate start and end scanlines
890 const int yStart = (int)ceil(v0.v.position.y - 0.5);
891 const int yEnd = (int)ceil(v2.v.position.y - 0.5); // the scanline AFTER the last line drawn
892
893 const double unit0 = (v2.v.position.y - v0.v.position.y) / (yEnd - yStart);
894 double u0 = 0;
895
896 Vertex2 vx2;
897 std::array<float, 3> coefficients;
898
899 for (int y = yStart; y < yEnd && y < fboCPU->ymax; ++y, u0 += unit0) {
900 if (y <= fboCPU->ymin) {
901 continue;
902 }
903 const double px0 = m0 * (double(y) + 0.5f - v0.v.position.y) + v0.v.position.x;
904 const double px1 = m1 * (double(y) + 0.5f - v0.v.position.y) + v0.v.position.x;
905
906 const int xStart = (int)ceil(px0 - 0.5);
907 const int xEnd = (int)ceil(px1 - 0.5);
908
909 const double unit2 = (px1 - px0) / (xEnd - xStart);
910 double u2 = 0;
911
912 for (int x = xStart; x < xEnd && x < fboCPU->xmax; x++, u2 += unit2) {
913 if (x <= fboCPU->xmin) {
914 continue;
915 }
916 const vec2 pos(px0 + u2, v0.v.position.y + u0);
917 calculateBarycentricCoordinates(pos, v0.v.position, v1.v.position, v2.v.position, coefficients);
918
919 const double z = 1 / (coefficients[0] * v0.v.position.z + coefficients[1] * v1.v.position.z + coefficients[2] * v2.v.position.z);
920#ifdef MULTITHREADED
921 const std::lock_guard<std::mutex> lock(fboCPUMutex);
922#endif
923 auto gotz = getpixelZ_adjusted(x, y);
924 if (gotz < z) {
925 vx2 = v0 * coefficients[0] + v1 * coefficients[1] + v2 * coefficients[2];
926 vx2.v.texCoord /= vx2.v.position.z;
927 vx2.v.normal /= vx2.v.position.z;
928 vx2.extraInfoAboutVertex /= vx2.v.position.z;
929 putpixel_adjusted(x, y, z, getcolor(vx2, mesh));
930 }
931 }
932 }
933 }
934
935 void rasterizeTrianglesHelper(std::tuple<std::array<Vertex2, 3>, Mesh *> &tris) {
936 auto &v0 = std::get<0>(tris)[0];
937 auto &v1 = std::get<0>(tris)[1];
938 auto &v2 = std::get<0>(tris)[2];
939 const auto &mesh = std::get<1>(tris);
940
941 //sorting vertices by y
942 if (v1.v.position.y < v0.v.position.y) {
943 std::swap(v0, v1);
944 }
945 if (v2.v.position.y < v1.v.position.y) {
946 std::swap(v1, v2);
947 }
948 if (v1.v.position.y < v0.v.position.y) {
949 std::swap(v0, v1);
950 }
951
952 if (v0.v.position.y == v1.v.position.y) // natural flat bottom
953 {
954 if (v1.v.position.x < v0.v.position.x) {
955 std::swap(v0, v1);
956 }
957#ifdef USEBARYCENTRIC
958 fillBottomFlatTriangleBary(v0, v1, v2, mesh);
959#else
960 fillBottomFlatTriangle(v0, v1, v2, mesh);
961#endif
962 } else if (v1.v.position.y == v2.v.position.y) // natural flat top
963 {
964 if (v2.v.position.x < v1.v.position.x) {
965 std::swap(v1, v2);
966 }
967#ifdef USEBARYCENTRIC
968 fillTopFlatTriangleBary(v0, v1, v2, mesh);
969#else
970 fillTopFlatTriangle(v0, v1, v2, mesh);
971#endif
972 } else // general triangle
973 {
974 assert(v2.v.position.y > v1.v.position.y && v1.v.position.y > v0.v.position.y);
975 // find splitting vertex
976 const double alphaSplit = (v1.v.position.y - v0.v.position.y) / (v2.v.position.y - v0.v.position.y);
977 const auto vi = v0 + (v2 - v0) * alphaSplit;
978
979#ifdef USEBARYCENTRIC
980 if (v1.v.position.x < vi.v.position.x) // major left
981 {
982 fillTopFlatTriangleBary(v0, v1, vi, mesh);
983 fillBottomFlatTriangleBary(v1, vi, v2, mesh);
984 } else // major right
985 {
986 fillTopFlatTriangleBary(v0, vi, v1, mesh);
987 fillBottomFlatTriangleBary(vi, v1, v2, mesh);
988 }
989#else
990 if (v1.v.position.x < vi.v.position.x) // major left
991 {
992 fillTopFlatTriangle(v0, v1, vi, mesh);
993 fillBottomFlatTriangle(v1, vi, v2, mesh);
994 } else // major right
995 {
996 fillTopFlatTriangle(v0, vi, v1, mesh);
997 fillBottomFlatTriangle(vi, v1, v2, mesh);
998 }
999#endif
1000 // draw_bresenham_adjusted(roundfloat(vi.v.position.x), roundfloat(vi.v.position.y), roundfloat(v1.v.position.x), roundfloat(v1.v.position.y), color(0, 255, 0));
1001 }
1002 }
1003
1008#ifdef MULTITHREADED
1009 pool.parallelize_loop(0, triangles.size(), [&](const unsigned int start, const unsigned int end) {
1010 for (unsigned int i = start; i < end; i++) {
1011 rasterizeTrianglesHelper(triangles[i]);
1012 }
1013 });
1014
1015#else
1016 for (auto &tris : triangles) {
1018 }
1019#endif
1020 }
1021
1025#ifndef PHONG_SHADING
1026 void fillExtraInformationForGoraudShading(Vertex &v, EXTRA_VERTEX_INFO &vertPos) const {
1027 const auto viewDir = (cam->eye - vertPos.x).normalize();
1028 vertPos = EXTRA_VERTEX_INFO(vec3(0), vec3(0), vec3(0));
1029 for (auto &light : pointLights) {
1030 float dist = vec3::dist(vertPos.x, light.getpos());
1031 float int_by_at = light.intensity / (light.constant + light.linear * dist + light.quadratic * (dist * dist));
1032 const vec3 lightDir = vec3::normalize(light.getpos() - vertPos.x);
1033 if (int_by_at > 0.000001) {
1034 const float diff = max(vec3::dot(v.normal, lightDir), 0.0);
1035 const vec3 halfwayDir = vec3::normalize(lightDir + viewDir);
1036 const float spec = std::pow(max(vec3::dot(v.normal, halfwayDir), 0.0), currentMesh->material.shininess);
1037 vertPos.x += light.get_ambient_color().getcolorVec3() * currentMesh->material.AmbientStrength * light.intensity * int_by_at;
1038 vertPos.y += light.get_diffuse_color().getcolorVec3() * currentMesh->material.DiffuseStrength * light.intensity * diff * int_by_at;
1039 vertPos.z += light.get_diffuse_color().getcolorVec3() * currentMesh->material.SpecularStrength * light.intensity * spec * int_by_at;
1040 }
1041 }
1042 }
1043#endif
1044};
camera class implementing simple camera movement
Definition: camera.h:6
vec3 getViewDir() const
Definition: camera.h:68
vec3 eye
Definition: camera.h:12
float FOV
Definition: camera.h:14
vec3 getUp() const
Definition: camera.h:67
A C++17 thread pool class.
Definition: thread_pool.hpp:36
void parallelize_loop(const T1 &first_index, const T2 &index_after_last, const F &loop, ui32 num_blocks=0)
Parallelize a loop by splitting it into blocks, submitting each block separately to the thread pool,...
#define GLcall(x)
Definition: core.h:43
#define EXTRA_VERTEX_INFO
Definition: engine.h:66
vec3_T< float > vec3
Definition: maths.h:305
class to store information about material read from .mtl file along with obj
Definition: material.h:20
float SpecularStrength
Definition: material.h:24
float DiffuseStrength
Definition: material.h:23
color diffuseColor
Definition: material.h:27
float AmbientStrength
Definition: material.h:22
texture diffuse
Definition: material.h:28
float shininess
Definition: material.h:26
Vertex + extra info required for shading.
Definition: engine.h:74
Vertex2 operator-(const Vertex2 &f) const
Definition: engine.h:86
Vertex v
Definition: engine.h:75
Vertex2(const Vertex &vin, const EXTRA_VERTEX_INFO &pos)
Definition: engine.h:78
Vertex2 operator+(const Vertex2 &f) const
Definition: engine.h:83
Vertex2 operator*(const float &f) const
Definition: engine.h:80
EXTRA_VERTEX_INFO extraInfoAboutVertex
Definition: engine.h:77
Vertex2()
Definition: engine.h:79
Definition: core.h:108
Vertex perspectiveMul(const mat4f &per)
Definition: core.h:137
vec2 texCoord
Definition: core.h:111
vec3 normal
Definition: core.h:110
vec4 position
Definition: core.h:109
class that holds color with 8 bits per channel with 4 channels rgba.
Definition: core.h:165
uint8_t a() const
Definition: core.h:194
uint32_t col
Definition: core.h:166
Definition: core.h:341
color col
Definition: core.h:344
vec3 direction
Definition: core.h:342
float intensity
Definition: core.h:343
this class represents all drawable entities that has a material and vertices
Definition: drawable.h:12
bool doLightCalculations
Definition: drawable.h:17
Material material
Definition: drawable.h:16
backend for all rendering purposes
Definition: engine.h:94
void clip2helper(const mat4f &per, const std::array< EXTRA_VERTEX_INFO, 3 > &extraInfoAboutVertex, const std::array< vec4, 3 > &modelviewTransformed, Vertex *points, unsigned char idx1, unsigned char idx2, unsigned char rem, std::array< Vertex2, 3 > &t)
clips and perspective transforms input triangle vertices if two points are out of clip space
Definition: engine.h:631
float getpixelZ_adjusted(int x, int y) const
get z value of specified pixel from framebuffer
Definition: engine.h:572
std::mutex fboCPUMutex
Definition: engine.h:452
void makeRequiredTriangles(const std::vector< Vertex > &vertices, const std::vector< uint32_t > &indices, const mat4f &modelmat)
fill triangles array by doing required clipping and culling
Definition: engine.h:361
void clip1(const std::array< vec4, 3 > &tris, unsigned char which, float &u1, float &u2) const
Definition: engine.h:618
void fillTopFlatTriangle(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh)
rasterize TopFlatTriangle: v0 is bottom unique and v2.x > v1.x
Definition: engine.h:729
void fillBottomFlatTriangleBary(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh)
rasterize BottomFlatTriangle: v2 is top unique and v1.x > v0.x
Definition: engine.h:830
camera * cam
camera
Definition: engine.h:305
bool wireframe
Definition: engine.h:307
const char * vertexShaderSource
Definition: engine.h:103
void clear()
clear all drawing surface
Definition: engine.h:242
uint32_t ibo
Definition: engine.h:98
static vec3 reflect(const vec3 &I, const vec3 &N)
Definition: engine.h:420
void draw_bresenham_adjusted(int x1, int y1, int x2, int y2, const color &col=color(0))
bresenham line drawing function to draw wireframe of objects
Definition: engine.h:580
void setTime(float time)
Definition: engine.h:382
float lightRenderDistance
Definition: engine.h:309
color ambientLightColor
Definition: engine.h:298
engine(const uint32_t &x, const uint32_t &y)
constructor and opengl draw surface initialization
Definition: engine.h:148
color CalcDirLight(const vec3 &normal, const vec3 &viewdir, const color &col, const Material *material) const
function to calculate effect of directional light in a fragment with color col
Definition: engine.h:427
color getcolor(const Vertex2 &v, Mesh *mesh) const
essentially a fragment shader : inputs fragment position and information and outputs color value for ...
Definition: engine.h:314
void fillTopFlatTriangleBary(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh)
Definition: engine.h:882
static color CalcPointLight(const pointLight &light, const vec3 &normal, const vec3 &fragPos, const vec3 &viewDir, const color &diffuseColor, float int_by_at, const Material *material)
function to calculate effect of a point light in a fragment with color col
Definition: engine.h:440
Mesh * currentMesh
which material to use for further render calls
Definition: engine.h:292
uint32_t shader
Definition: engine.h:98
bool cullBackface
switch for backface culling
Definition: engine.h:287
void putpixel_adjusted(int x, int y, float z, const color &col=color(255))
putpixel assuming middle of screen to be the origin
Definition: engine.h:561
void draw()
send framebuffer from cpu to gpu as texture to be able to render using opengl
Definition: engine.h:251
void calculateBarycentricCoordinates(const vec2 &p, const vec4 &v1, const vec4 &v2, const vec4 &v3, std::array< float, 3 > &values)
Definition: engine.h:784
bool printed
Definition: engine.h:357
void clip1helper(const mat4f &per, const std::array< EXTRA_VERTEX_INFO, 3 > &extraInfoAboutVertex, const std::array< vec4, 3 > &modelviewTransformed, Vertex *points, unsigned char idx1, std::array< Vertex2, 3 > &t, std::vector< std::tuple< std::array< Vertex2, 3 >, Mesh * > > &triangles)
clips and perspective transforms input triangle vertices if one point is out of the clip space
Definition: engine.h:647
const char * fragmentShaderSource
Definition: engine.h:114
framebuffer * fboCPU
Definition: engine.h:96
uint32_t vao
Definition: engine.h:98
~engine()
destructor
Definition: engine.h:231
void makeRequiredTrianglesHelper(std::array< Vertex, 3 > &points, const mat4f &modelmat, const mat4f &view, const mat4f &per)
Definition: engine.h:454
std::vector< std::tuple< std::array< Vertex2, 3 >, Mesh * > > triangles
set of triangles to be drawn to screen
Definition: engine.h:277
uint32_t tex
Definition: engine.h:98
std::vector< pointLight > pointLights
Definition: engine.h:300
float ambientLightIntensity
lights.
Definition: engine.h:297
void clip2(const std::array< vec4, 3 > &tris, unsigned char idx1, unsigned char idx2, unsigned char rem, float &u1, float &u2) const
Definition: engine.h:623
dirLight dirlight
Definition: engine.h:299
uint32_t indices[6]
Definition: engine.h:136
float nearPlane
nearplane of camera for clipping and culling
Definition: engine.h:282
std::unordered_map< uint8_t, float > greenTimeMap
Definition: engine.h:413
static float max(const float &first, const float &second)
Definition: engine.h:416
void fillBottomFlatTriangle(const Vertex2 &v0, const Vertex2 &v1, const Vertex2 &v2, Mesh *mesh)
rasterize BottomFlatTriangle: v2 is top unique and v1.x > v0.x
Definition: engine.h:669
void rasterizeTriangles()
helper function to rasterize triangles in vector of triangles.
Definition: engine.h:1007
uint32_t vbo
Definition: engine.h:98
std::unordered_map< uint8_t, float > blueTimeMap
Definition: engine.h:414
void rasterizeTrianglesHelper(std::tuple< std::array< Vertex2, 3 >, Mesh * > &tris)
Definition: engine.h:935
thread_pool pool
Definition: engine.h:101
float vertices[20]
Definition: engine.h:128
Framebuffer implementation for cpu.
Definition: engine.h:25
int ymin
Definition: engine.h:33
int ymax
Definition: engine.h:33
float * clearedz
Definition: engine.h:30
~framebuffer()
Definition: engine.h:54
int xmax
Definition: engine.h:33
color * colorlayer
Definition: engine.h:28
size_t x_size
Definition: engine.h:32
color * clearedcolorlayer
Definition: engine.h:31
float * z
Definition: engine.h:27
int xmin
Definition: engine.h:33
size_t y_size
Definition: engine.h:32
void clear()
Definition: engine.h:59
std::vector< std::tuple< Vertex2 *, Mesh * > > fragments
Definition: engine.h:26
framebuffer(const size_t &x, const size_t &y)
Definition: engine.h:34
pointlight
Definition: pointLight.h:9
const vec3 & getpos() const
Definition: pointLight.h:64
const color & get_ambient_color() const
Definition: pointLight.h:66
const color & get_diffuse_color() const
Definition: pointLight.h:65
int h
Definition: material.h:13
int m_bpp
Definition: material.h:13
int w
Definition: material.h:13
unsigned char * m_data
Definition: material.h:11
T y
Definition: maths.h:26
T x
Definition: maths.h:26
static float dot(const vec3_T< float > &a, const vec3_T< float > &b)
Definition: maths.h:301
static double dist(const vec3_T< float > &a, const vec3_T< float > &b)
Definition: maths.h:289
T x
Definition: maths.h:162
vec3_T< T > normalize()
Definition: maths.h:278
T z
Definition: maths.h:314
T y
Definition: maths.h:314
T x
Definition: maths.h:314
A C++17 thread pool for high-performance scientific computing.