-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
blit.lut.c
95 lines (74 loc) · 2.29 KB
/
blit.lut.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define RGB565_R_MASK 0b1111100000000000
#define RGB565_G_MASK 0b0000011111100000
#define RGB565_B_MASK 0b0000000000011111
const int ScreenWidth = 1024;
const int ScreenHeight = 768;
const int SpriteSize = 64;
typedef struct _RGB {
float r;
float g;
float b;
} floatrgb_t;
floatrgb_t LUT[1<<16];
int min(int x, int y) {
return x < y ? x : y;
}
int max(int x, int y) {
return x > y ? x : y;
}
void bgra8888_to_floatrgba(uint8_t* bgra8888, float* floatrgba) {
floatrgba[0] = bgra8888[2] / 255.f;
floatrgba[1] = bgra8888[1] / 255.f;
floatrgba[2] = bgra8888[0] / 255.f;
floatrgba[3] = bgra8888[3] / 255.f;
}
void rgb565_to_floatrgb(uint16_t* rgb565, float* floatrgb) {
floatrgb[0] = LUT[rgb565[0]].r;
floatrgb[1] = LUT[rgb565[0]].g;
floatrgb[2] = LUT[rgb565[0]].b;
}
float lerp(float from, float to, float time) {
return (1-time)*from + time*to;
}
void floatrgb_to_rgb565(float* floatrgb, uint16_t* rgb565) {
rgb565[0] = (uint16_t)(floatrgb[0]*31) << 11 |
(uint16_t)(floatrgb[1]*63) << 5 |
(uint16_t)(floatrgb[2]*31);
}
void blitSprite(uint16_t* frameBuffer, uint8_t* sprite, int x, int y) {
int start_i = max(-y, 0);
int start_j = max(-x, 0);
int end_i = min(ScreenHeight-y, SpriteSize);
int end_j = min(ScreenWidth-x , SpriteSize);
int spriteRowOffset = 4*(SpriteSize - (end_j-start_j));
int bufferRowOffset = ScreenWidth - (end_j-start_j);
uint8_t* spritePix = sprite + 4*(start_j + start_i*SpriteSize);
uint16_t* bufferPix = frameBuffer + ScreenWidth*(y + start_i) + x + start_j;
for(int i = start_i; i < end_i; ++i) {
for(int j = start_j; j < end_j; ++j) {
float over[4];
float under[3];
bgra8888_to_floatrgba(spritePix, over);
rgb565_to_floatrgb(bufferPix, under);
// Perform alpha blending
under[0] = lerp(under[0], over[0], over[3]);
under[1] = lerp(under[1], over[1], over[3]);
under[2] = lerp(under[2], over[2], over[3]);
floatrgb_to_rgb565(under, bufferPix);
spritePix += 4;
bufferPix += 1;
}
spritePix += spriteRowOffset;
bufferPix += bufferRowOffset;
}
}
void buildLUTs() {
for(unsigned int i = 0; i < (1<<16); ++i) {
LUT[i].r = ((i & RGB565_R_MASK) >> (6+5)) / 31.f;
LUT[i].g = ((i & RGB565_G_MASK) >> 5) / 63.f;
LUT[i].b = (i & RGB565_B_MASK) / 31.f;
}
}