118 lines
3.6 KiB
C
118 lines
3.6 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
|
|
// 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. We also expand the range so we can use
|
|
// integers. By using 256, we are essentially adding 8 bits of "decimal
|
|
// point". If you need more bits (or less), just change this to some other
|
|
// power of 2.
|
|
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++) {
|
|
// And then with the shift, it is log2(256), or whatever you shifted
|
|
// by up there. So 512 would be 9, because 2^9 = 512
|
|
i32 texi = 3 * ((texx >> 8) + tex.width * (texy >> 8));
|
|
i32 bufi = 3 * (x + y * buffer.width);
|
|
memcpy(buffer.data + bufi, tex.data + texi, 3);
|
|
texx += stepx;
|
|
bufi += 3;
|
|
}
|
|
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, 8, 12 };
|
|
struct rect bufrect = { 10, 10, 509, 499 };
|
|
|
|
clock_t start = clock();
|
|
for(int i = 0; i < 50; 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");
|
|
}
|