#include #include #include #include #include #include // You need to generate this with textoc.h #include "texture.h" typedef uint8_t u8; typedef int32_t i32; #define CDEPTH 255 #define log(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) #define panic(fmt, ...) { fprintf(stderr, "PANIC: " fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } // A simple designation of a rectangle struct rect { int x1, y1; // Inclusive int x2, y2; // Exclusive }; // Compute the dimensions of a rect void rect_dims(struct rect bounds, int * width, int * height) { *width = abs(bounds.x2 - bounds.x1); *height = abs(bounds.y2 - bounds.y1); } // A simple designation of a texture struct texture { int width, height; u8 * data; }; // fb is framebuffer. Thsi dumps a color version (rgb) of a framebuffer // to stdout, which you can pipe to a file or some shit idk void dump_ppm(struct texture fb) { log("Dumping framebuffer %dx%d", fb.width, fb.height); printf("P3\n%d %d\n%d\n# Image start\n", fb.width, fb.height, CDEPTH); for(int i = 0; i < fb.width * fb.height * 3; i+=3) printf("%d %d %d\n", fb.data[i], fb.data[i+1], fb.data[i+2]); printf("\n"); } // ------------------------------------------------------ // * THIS IS THE FUNCTION YOU WANT <3 * // ------------------------------------------------------ void drawTexInto(struct texture tex, struct texture buffer, struct rect texbounds, struct rect bufbounds) { int texwidth, texheight, outwidth, outheight; rect_dims(texbounds, &texwidth, &texheight); rect_dims(bufbounds, &outwidth, &outheight); // We precalculate the step through the texture to avoid division and // multiplication per pixel i32 stepx = 256 * (float)texwidth / outwidth; i32 stepy = 256 * (float)texheight / outheight; i32 texx = 256 * texbounds.x1; i32 texy = 256 * texbounds.y1; //log("%f,%f step %f,%f", texx, texy, stepx, stepy); // Buffer is R G B for each pixel, then across then down. If you want X, Y, // it's: 3 * (x + y * width) for(int y = bufbounds.y1; y < bufbounds.y2; y++) { texx = texbounds.x1; for(int x = bufbounds.x1; x < bufbounds.x2; x++) { i32 texi = 3 * ((texx >> 8) + tex.width * (texy >> 8)); i32 bufi = 3 * (x + buffer.width * y); // You can get rid of this for loop for more performance, but probably // not a big deal with -O3, it'll be unrolled buffer.data[bufi] = tex.data[texi]; buffer.data[bufi + 1] = tex.data[texi + 1]; buffer.data[bufi + 2] = tex.data[texi + 2]; texx += stepx; } texy += stepy; } } int main() { log("Program start"); const int width = 512; const int height = 512; const int fbsize = width * height * 3; struct texture fb = { width, height, calloc(fbsize, 1) }; if(!fb.data) panic("Can't allocate framebuffer"); // Initialize the texture. It's already defined elsewhere struct texture tex = { mytex_width, mytex_height, mytex }; // We actually stretch a texture here struct rect texrect = { 0, 0, 16, 16 }; struct rect bufrect = { 10, 10, 26, 26 }; clock_t start = clock(); for(int i = 0; i < 50000; i++) { //overdraw factor drawTexInto(tex, fb, texrect, bufrect); } clock_t end = clock(); double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC; log("1000 iterations took: %fs", cpu_time_used); // Dump the image to the ppm dump_ppm(fb); log("Program end"); }