#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 DrawTexturedPolygon( T p0, T p1, T p2, PlotFunc&& Plot) { using SlopeData = std::array; // All input units except y RasterizeTriangle( &p0, &p1, &p2, // GetXY: Retrieve std::tuple or std::array from a PointType [&](const auto& p) { return std::tuple{ int(std::get<0>(p)), int(std::get<1>(p)) }; }, // Slope generator [&](const T* from, const T* to, int num_steps) { SlopeData result; // Number of steps = number of scanlines // Retrieve X coordinates for begin and end result[0] = Slope( std::get<0>(*from), std::get<0>(*to), num_steps ); // Take the rest of the props [&](std::index_sequence) { // Retrieve begin to end for each prop. The +2 skips x and y. ((result[p+1] = Slope( std::get(*from), std::get(*to), num_steps )), ...); } (std::make_index_sequence{}); return result; }, // Scanline function [&](int y, SlopeData& left, SlopeData& right) { int x = left[0].get(), endx = right[0].get(); // Number of steps = number of pixels on this scanline = endx-x std::array props; for(unsigned p=0; p 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); const int txW = 256, txH = 256; unsigned bitmap[txW*txH]; for(unsigned y=0; y> std::min({x,y,txW-1-x,txH-1-y,31u})); int d = std::min(50,std::max(0,255-50*std::pow(std::hypot(x/float(txW/2)-1.f, y/float(txH/2)-1.f)*4,2.f))); int r = (~x & ~y)&255, g = (x & ~y)&255, b = (~x & y)&255; bitmap[y*txW+x] = std::min(std::max(r-d,l),255)*65536 + std::min(std::max(g-d,l),255)*256 + std::min(std::max(b-d,l),255); } // Create a rectangle comprised of two triangles std::vector< std::array, 3> > triangles { { std::array{ 120.f,40.f, 0.f,0.f }, { 300,40, 0,txH }, { 300,200, txW,txH } }, { std::array{ 120.f,40.f, 0.f,0.f }, { 300,200, txW,txH }, { 120,200, txW,0 } } }; #include "mousemanip-part1.hh" for(bool interrupted=false; !interrupted; ) { // Process events. SDL_Event ev; while(SDL_PollEvent(&ev)) switch(ev.type) { case SDL_QUIT: interrupted = true; break; #include "mousemanip-part2.hh" } // Render graphics Uint32 pixels[W*H]={}; for(auto& t: triangles) { DrawTexturedPolygon( t[0], t[1], t[2], [&](int x,int y, int u,int v) { if(y>=0 && x>=0 && y