#ifndef RENDERER_H #define RENDERER_H #include "fastmath.hpp" #include "model.hpp" #include "polygon.hpp" #include "rendertarget.hpp" #include #include #define SCREEN_SPACE_SIZE 2.0 class Renderer { public: Rendertarget *target; bool clearTarget = true; vec3 sunDir = vec3(1.0, -1.0, 1.0).normalize(); void toScreenSpace(vec3 *np, mat4 matrix) { vec4 tp = (matrix * vec4(*np, decimal(1.0f))); tp.x() = tp.x() / tp.z() * decimal(SCREEN_SPACE_SIZE) + decimal(SCREEN_SPACE_SIZE); tp.y() = tp.y() / tp.z() * decimal(SCREEN_SPACE_SIZE) + decimal(SCREEN_SPACE_SIZE); *np = vec3(tp.x(), tp.y(), tp.z()); } void render(const model *model, const mat4 matrix) { decimal widthScale = decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->width); decimal heightScale = decimal(SCREEN_SPACE_SIZE * 2) / decimal((float)target->height); decimal invWidthScale = decimal((float)(target->width / SCREEN_SPACE_SIZE / 2)); decimal invHeightScale = decimal((float)(target->height / SCREEN_SPACE_SIZE / 2)); // TODO clear target with memset vec3 verts[model->verts.size()] = {}; std::copy(model->verts.begin(), model->verts.end(), verts); for (int i = 0; i < model->verts.size(); i++) { toScreenSpace(verts + i, matrix); } vec3 normals[model->normals.size()] = {}; mat3 normalMatrix = matrix.cutTo(); for (int i = 0; i < model->normals.size(); i++) { normals[i] = normalMatrix * model->normals[i]; } polygon testP; for (int f = 0; f < model->faces.size(); f += 3) { testP.small = false; for (int p = 0; p < 3; p++) { testP.points[p] = verts[std::get<0>(model->faces[f + p])]; testP.colors[p] = model->colors[std::get<0>(model->faces[f + p])]; testP.normals[p] = normals[std::get<1>(model->faces[f + p])]; } if ((testP.avgNormal() * vec3(0.0, 0.0, 1.0)) > decimal(0.)) continue; testP.calcDelta(); int startX = std::max( (testP.bounding[0] * invWidthScale).i >> SHIFT_AMOUNT, 0); int endX = std::max( std::min((testP.bounding[1] * invWidthScale).i >> SHIFT_AMOUNT, (uint32_t)target->width - 1), 0); int startY = std::max( (testP.bounding[2] * invHeightScale).i >> SHIFT_AMOUNT, 0); int endY = std::min((testP.bounding[3] * invHeightScale).i >> SHIFT_AMOUNT, target->height - 1); std::cout << "Polys:\n" << testP.baryFactor << "\n"; for (int i = 0; i < 3; i++) { std::cout << testP.points[i]; } std::cout << "Boundings:\n"; std::cout << testP.bounding[0] << " " << startX << "\n"; std::cout << testP.bounding[1] << " " << endX << "\n"; std::cout << testP.bounding[2] << " " << startY << "\n"; std::cout << testP.bounding[3] << " " << endY << "\n"; vec3 pos = vec3(testP.bounding[0], testP.bounding[2], 0.0); for (int x = 0; x < target->width; x++) { for (int y = 0; y < target->height; y++) { // for (int x = startX; x < endX; x++) { // for (int y = startY; y < endY; y++) { testP.calcBarycentric(pos); if (testP.contains(pos)) { // testP.calcBarycentric(pos); decimal depth = testP.calcDepth(); if (depth < target->getDepth(x, y)) { // std::cout << factors << std::endl; vec3 normal = testP.calcNormal(); vec3 color = testP.calcColor(); decimal lightFac = std::max(normal * (-sunDir), decimal(0.0)) + decimal(0.5); ; target->setDepth(x, y, depth); // target->set(x, y, // (color * decimal(120.0)) * lightFac); // target->set(x, y, // vec3(lightFac * decimal(200.0), 0, 0)); // target->set(x, y, // (normal + vec3(1.0, 1.0, 1.0)) * // decimal(120.0)); // target->set( // x, y, // (testP.avgNormal() + vec3(1.0, 1.0, 1.0)) * // decimal(120.0)); target->set(x, y, testP.barycentrics * decimal(200.0)); // if (!factors.isSmall()) // target->set(x, y, vec3(0., 255.0, 0.)); } // target->set(x, y, vec3(0.0, 255.0, 0.0)); } pos.y() += heightScale; } pos.y() = decimal(testP.bounding[2]); pos.x() += widthScale; } } } }; #endif