#include "rasterize.hh" #include #include #include class Slope { float begin, step; public: Slope() {} Slope(float from, float to, int num_steps) { float inv_step = 1.f / num_steps; begin = from; // Begin here step = (to - from) * inv_step; // Stepsize = (end-begin) / num_steps } float get() const { return begin; } void advance() { begin += step; } }; template void DrawSmoothColorPolygon( std::array p0, std::array p1, std::array p2, PlotFunc&& Plot) { using SlopeData = std::array; // x and three props RasterizeTriangle( &p0, &p1, &p2, // GetXY: Retrieve std::tuple or std::array from a PointType [&](const auto& p) { return std::tuple{ p[0], p[1] }; }, // Slope generator [&](const std::array* from, const std::array* to, int num_steps) { SlopeData result; // Retrieve X coordinates for begin and end. result[0] = Slope( (*from)[0], (*to)[0], num_steps ); // Take the rest of the props (RGB color) for(unsigned p=0; p<3; ++p) { // Retrieve begin to end for each prop. The +2 skips x and y. result[p+1] = Slope( (*from)[p+2], (*to)[p+2], num_steps ); } return result; }, // Scanline function [&](int y, SlopeData& left, SlopeData& right) { int x = left[0].get(), endx = right[0].get(); Slope props[3]; for(unsigned p=0; p<3; ++p) { // Number of steps = number of pixels on this scanline int num_steps = endx-x; props[p] = Slope( left[p+1].get(), right[p+1].get(), num_steps ); } for(; x < endx; ++x) // Render each pixel { Plot(x, y, props[0].get(), props[1].get(), props[2].get()); // After each pixel, update the props by their step-sizes for(auto& prop: props) prop.advance(); } // After the scanline is drawn, update the X coordinate and props on both sides for(auto& slope: left) slope.advance(); for(auto& slope: right) slope.advance(); }); } #include "mesh.hh" #include int main() { const int W = 424, H = 240; // Create a screen. SDL_Window* window = SDL_CreateWindow("Chip8", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, W*4,H*4, SDL_WINDOW_RESIZABLE); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0); SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, W,H); // Create a mesh of triangles covering the entire screen std::vector< std::array, 3> > triangles = CreateTriangleMesh(W,H,20); for(bool interrupted=false; !interrupted; ) { // Process events. SDL_Event ev; while(SDL_PollEvent(&ev)) switch(ev.type) { case SDL_QUIT: interrupted = true; break; } // Render graphics Uint32 pixels[W*H]={}; int color = 0x3B0103A5, b=19; for(auto& t: triangles) { color = ((color << b) | (unsigned(color) >> (32-b))); std::array p0 { t[0][0], t[0][1], (color&0xFF),((color>>8)&0xFF),((color>>16)&0xFF) }; color = ((color << b) | (unsigned(color) >> (32-b))); std::array p1 { t[1][0], t[1][1], (color&0xFF),((color>>8)&0xFF),((color>>16)&0xFF) }; color = ((color << b) | (unsigned(color) >> (32-b))); std::array p2 { t[2][0], t[2][1], (color&0xFF),((color>>8)&0xFF),((color>>16)&0xFF) }; DrawSmoothColorPolygon( p0,p1,p2, [&](int x,int y, int b,int g,int r) { pixels[y*W+x] = b+(g<<8)+(r<<16); }); } SDL_UpdateTexture(texture, nullptr, pixels, 4*W); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer); SDL_Delay(1000/60); } }