added patterned dithering and shading test

Thanks to @HBehrens for valuable input on shading/dithering, hardware limitations and chances, and ideas regarding methods to further improve this proof of concept
master
Alina Marquardt 2016-06-04 03:15:15 +02:00
parent f320b32a6d
commit 9681126ad9
1 changed files with 102 additions and 28 deletions

View File

@ -3,28 +3,39 @@
#include <shading.c> #include <shading.c>
#define ANTIALIASING true #define ANTIALIASING true
#define WHWIDTH 18
static uint8_t shadowtable[] = { /*
192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, static uint8_t bayer4x4[] = {
192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 1, 9, 3,11,
192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 13, 5,15, 7,
192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192, 4,12, 2,10,
192,192,192,193,192,192,192,193,192,192,192,193,196,196,196,197, 16, 8,14, 6,
192,192,192,193,192,192,192,193,192,192,192,193,196,196,196,197, };
192,192,192,193,192,192,192,193,192,192,192,193,196,196,196,197, */
208,208,208,209,208,208,208,209,208,208,208,209,212,212,212,213,
192,192,193,194,192,192,193,194,196,196,197,198,200,200,201,202, static uint8_t bayer8x8[] = {
192,192,193,194,192,192,193,194,196,196,197,198,200,200,201,202, 0,32, 8,40, 2,34,10,42,
208,208,209,210,208,208,209,210,212,212,213,214,216,216,217,218, 48,16,56,24,50,18,58,26,
224,224,225,226,224,224,225,226,228,228,229,230,232,232,233,234, 12,44, 4,36,14,46, 6,38,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 60,28,52,20,62,30,54,22,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 3,35,11,43, 1,33, 9,41,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 51,19,59,27,49,17,57,25,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, 15,47, 7,39,13,45, 5,37,
63,31,55,23,61,29,53,21,
}; };
// alpha should only be 0b??111111 where ?? = 00 (full shade), 01 (much shade), 10 (some shade), 11 (none shade) typedef union GColor32 {
static uint8_t alpha = 0b10111111; uint32_t argb;
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
};
} GColor32;
uint8_t ditherfactor = 85;
typedef struct { typedef struct {
int hours; int hours;
@ -36,7 +47,7 @@ static Layer *s_canvas_layer;
static GPoint s_center; static GPoint s_center;
static Time s_last_time; static Time s_last_time;
static int whwidth = 18;
static bool debug = false; static bool debug = false;
/************************************ UI **************************************/ /************************************ UI **************************************/
@ -107,15 +118,15 @@ static void update_proc(Layer *layer, GContext *ctx) {
graphics_fill_rect(ctx, bounds, 0, GCornerNone); graphics_fill_rect(ctx, bounds, 0, GCornerNone);
graphics_context_set_stroke_color(ctx, GColorWindsorTan); graphics_context_set_stroke_color(ctx, GColorWindsorTan);
graphics_context_set_stroke_width(ctx, whwidth); graphics_context_set_stroke_width(ctx, WHWIDTH);
graphics_draw_line(ctx, s_center, minute_hand_outer); graphics_draw_line(ctx, s_center, minute_hand_outer);
graphics_context_set_stroke_color(ctx, GColorBulgarianRose); graphics_context_set_stroke_color(ctx, GColorBulgarianRose);
graphics_context_set_stroke_width(ctx, whwidth); graphics_context_set_stroke_width(ctx, WHWIDTH);
graphics_draw_line(ctx, s_center, hour_hand_outer); graphics_draw_line(ctx, s_center, hour_hand_outer);
graphics_context_set_fill_color(ctx, GColorWhite); graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_circle(ctx, s_center, whwidth/4); graphics_fill_circle(ctx, s_center, WHWIDTH/4);
// define mapping metadata // define mapping metadata
GSize mapdimensions = GSize(125, 80); GSize mapdimensions = GSize(125, 80);
@ -125,7 +136,6 @@ static void update_proc(Layer *layer, GContext *ctx) {
GRect specularbounds = GRect(master_offset.x+31, master_offset.y+8, 74, 47); GRect specularbounds = GRect(master_offset.x+31, master_offset.y+8, 74, 47);
GColor bgcolor = GColorPurple; GColor bgcolor = GColorPurple;
GColor highlight = GColorIcterine;
// capture frame buffer // capture frame buffer
GBitmap *fb = graphics_capture_frame_buffer(ctx); GBitmap *fb = graphics_capture_frame_buffer(ctx);
@ -142,7 +152,6 @@ static void update_proc(Layer *layer, GContext *ctx) {
if (x >= texturebounds.origin.x && y >= texturebounds.origin.y && x < texturebounds.origin.x+texturebounds.size.w && y < texturebounds.origin.y+texturebounds.size.h) { if (x >= texturebounds.origin.x && y >= texturebounds.origin.y && x < texturebounds.origin.x+texturebounds.size.w && y < texturebounds.origin.y+texturebounds.size.h) {
texture_matrix[y-texturebounds.origin.y][x-texturebounds.origin.x] = info.data[x]; texture_matrix[y-texturebounds.origin.y][x-texturebounds.origin.x] = info.data[x];
} }
memset(&info.data[x], bgcolor.argb, 1);
} }
} }
@ -150,17 +159,72 @@ static void update_proc(Layer *layer, GContext *ctx) {
for(uint8_t y = 0; y < bounds.size.h; y++) { for(uint8_t y = 0; y < bounds.size.h; y++) {
GBitmapDataRowInfo info = gbitmap_get_data_row_info(fb, y); GBitmapDataRowInfo info = gbitmap_get_data_row_info(fb, y);
for(uint8_t x = info.min_x; x <= info.max_x; x++) { for(uint8_t x = info.min_x; x <= info.max_x; x++) {
GColor fbpixel = GColorWhite;
// render texture mapped object by looking up pixels in the lookup table // render texture mapped object by looking up pixels in the lookup table
if (x >= mapbounds.origin.x && y >= mapbounds.origin.y && x < mapbounds.origin.x+mapbounds.size.w && y < mapbounds.origin.y+mapbounds.size.h) { if (x >= mapbounds.origin.x && y >= mapbounds.origin.y && x < mapbounds.origin.x+mapbounds.size.w && y < mapbounds.origin.y+mapbounds.size.h) {
uint16_t surfindex = (x-mapbounds.origin.x)+((y-mapbounds.origin.y)*mapbounds.size.w); uint16_t surfindex = (x-mapbounds.origin.x)+((y-mapbounds.origin.y)*mapbounds.size.w);
//uint8_t xpos = 16+un_heptet_x(surfindex);
uint8_t xpos = 16+un_heptet(surfindex, donutsurfacemapred); uint8_t xpos = 16+un_heptet(surfindex, donutsurfacemapred);
uint8_t ypos = 127-un_heptet(surfindex, donutsurfacemapgreen); uint8_t ypos = 127-un_heptet(surfindex, donutsurfacemapgreen);
if (xpos > 0 && ypos < 127) { if (xpos > 0 && ypos < 127) {
memset(&info.data[x], texture_matrix[ypos][xpos], 1); fbpixel.argb = texture_matrix[ypos][xpos];
} }
} }
// transpose to 24 bit color
GColor32 newpixel;
newpixel.r = fbpixel.r*ditherfactor;
newpixel.g = fbpixel.g*ditherfactor;
newpixel.b = fbpixel.b*ditherfactor;
newpixel.a = 0xff;
// render some test shading from the LUT to test dithering
if (x >= mapbounds.origin.x && y >= mapbounds.origin.y && x < mapbounds.origin.x+mapbounds.size.w && y < mapbounds.origin.y+mapbounds.size.h) {
uint16_t surfindex = (x-mapbounds.origin.x)+((y-mapbounds.origin.y)*mapbounds.size.w);
uint8_t green = 2*(127-un_heptet(surfindex, donutsurfacemapgreen));
if (green < 254) {
if (newpixel.r - green > 0) {
newpixel.r -= green;
} else {
newpixel.r = 0;
}
if (newpixel.g - green > 0) {
newpixel.g -= green;
} else {
newpixel.g = 0;
}
if (newpixel.b - green > 0) {
newpixel.b -= green;
} else {
newpixel.b = 0;
}
}
}
if (x >= mapbounds.origin.x && y >= mapbounds.origin.y && x < mapbounds.origin.x+mapbounds.size.w && y < mapbounds.origin.y+mapbounds.size.h) {
uint16_t surfindex = (x-mapbounds.origin.x)+((y-mapbounds.origin.y)*mapbounds.size.w);
uint8_t red = un_heptet(surfindex, donutsurfacemapred);
if (red > 0) {
if (red + newpixel.r < 255) {
newpixel.r += red;
} else {
newpixel.r = 255;
}
if (red + newpixel.g < 255) {
newpixel.g += red;
} else {
newpixel.g = 255;
}
if (red + newpixel.b < 255) {
newpixel.b += red;
} else {
newpixel.b = 255;
}
}
}
// TODO remove test shading and add better shadows and highlights back in later from resources
// render shadows // render shadows
/*
if (x >= shadowbounds.origin.x && y >= shadowbounds.origin.y && x < shadowbounds.origin.x+shadowbounds.size.w && y < shadowbounds.origin.y+shadowbounds.size.h) { if (x >= shadowbounds.origin.x && y >= shadowbounds.origin.y && x < shadowbounds.origin.x+shadowbounds.size.w && y < shadowbounds.origin.y+shadowbounds.size.h) {
uint16_t shad_index = (x-shadowbounds.origin.x)+((y-shadowbounds.origin.y)*shadowbounds.size.w); uint16_t shad_index = (x-shadowbounds.origin.x)+((y-shadowbounds.origin.y)*shadowbounds.size.w);
uint8_t shad_octet = donutshadow[shad_index/8]; uint8_t shad_octet = donutshadow[shad_index/8];
@ -189,7 +253,16 @@ static void update_proc(Layer *layer, GContext *ctx) {
if (spec_white) { if (spec_white) {
memset(&info.data[x], highlight.argb, 1); memset(&info.data[x], highlight.argb, 1);
} }
} }*/
// here comes the actual dithering
uint8_t bayerpixel = bayer8x8[((x%8)+(y*8))%64];
fbpixel.r = (newpixel.r+bayerpixel)/ditherfactor;
fbpixel.g = (newpixel.g+bayerpixel)/ditherfactor;
fbpixel.b = (newpixel.b+bayerpixel)/ditherfactor;
fbpixel.a = 0b11;
memset(&info.data[x], fbpixel.argb, 1);
} }
} }
@ -258,3 +331,4 @@ int main() {
} }