Skip to content

Commit

Permalink
Merge pull request #45 from pimoroni/blend_modes
Browse files Browse the repository at this point in the history
added new blend modes include multiply, add, subtract, dissolve, etc.…
  • Loading branch information
lowfatcode authored Oct 24, 2021
2 parents e230242 + e47d53d commit 225446c
Show file tree
Hide file tree
Showing 8 changed files with 2,092 additions and 21 deletions.
3 changes: 2 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ add_subdirectory(audio)
add_subdirectory(sprites)
add_subdirectory(colour)
#add_subdirectory(sfx)
add_subdirectory(music)
add_subdirectory(music)
add_subdirectory(blend_modes)
7 changes: 7 additions & 0 deletions examples/blend_modes/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
picosystem_executable(
blend_modes
blend_modes.cpp
)

pixel_double(blend_modes)
disable_startup_logo(blend_modes)
1,896 changes: 1,896 additions & 0 deletions examples/blend_modes/blend_modes.cpp

Large diffs are not rendered by default.

42 changes: 27 additions & 15 deletions examples/sprites/sprites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ float deg_to_rad(float d) {
// draw the world
void draw(uint32_t tick) {
// clear the background
pen(2, 3, 4);
alpha();
pen(1, 1, 1);
clear();

pen(10, 10, 10);
text("Choose your weapon:", 10, 10);
text("Choose your weapon:", 8, 10);

// animate towards the selected weapons angle
static float angle = 0.0f;
Expand Down Expand Up @@ -97,34 +98,45 @@ void draw(uint32_t tick) {
// size to draw weapon (closer = larger)
int32_t scale = ((cos(deg_to_rad(item_angle)) + 1.0f) * 8.0f) + 8.0f;

int32_t a = scale / 1.5;
a = a > 15 ? 15 : a;

// draw the shadow
alpha(a / 8);
pen(1, 1, 1);
int32_t sw = scale + (bounce / 3);
int32_t sh = sw / 3;
fellipse(60 + x, 55 + y + (scale / 1.2), sw / 2, sh / 2);
blend(PEN);
int32_t sw = scale + (bounce / 2);
int32_t sh = sw / 4;
pen(0, 0, 0);
sprite(
weapons[i].id, // sprite id
60 + x - (sw / 2), 50 + y + (scale / 1.2), // position
1, 1,
sw, sh // size
);

blend(ALPHA);

// draw the weapon sprite
int32_t a = ((cos(deg_to_rad(item_angle)) + 1.0f) * 6.0f) + 4.0f;
a = a > 15 ? 15 : a;
alpha(a);
sprite(
weapons[i].id, // sprite id
60 + x - (scale / 2), 55 + y - (scale / 2) + bounce, // position
1, 1,
scale, scale // size
);
alpha(15);

//pen(15, 15, 15);
//text(str(a), 60 + x - (scale / 2), 55 + y - (scale / 2) + bounce);
}

alpha(15);


// centre name of weapon at bottom of screen
int label_width = 40;//text_width(weapons[selected].name);
pen(8, 11, 11);
frect(60 - label_width / 2 - 3, 104 - 3, label_width + 6, 13);
int32_t lw, lh;
measure(weapons[selected].name, lw, lh);
pen(12, 12, 12);
frect(60 - lw / 2 - 3, 104 - 3, lw + 6, 13);
pen(0, 0, 0);
text(weapons[selected].name, 60 - (label_width / 2), 104);
text(weapons[selected].name, 60 - (lw / 2), 104);
}


6 changes: 3 additions & 3 deletions libraries/assets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ namespace picosystem {
{5, 0xf8, 0x18, 0x30, 0x30, 0x60, 0x60, 0x60, 0x00},
{5, 0x70, 0xd8, 0xd8, 0x70, 0xd8, 0xd8, 0x70, 0x00},
{5, 0x70, 0xd8, 0xd8, 0x78, 0x18, 0x98, 0x70, 0x00},
{2, 0x00, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0x00, 0x00},
{2, 0x00, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0x00},
{2, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0x00},
{2, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0xc0, 0xc0, 0xc0},
{4, 0x00, 0x00, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x00},
{5, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00},
{4, 0x00, 0x00, 0xc0, 0x60, 0x30, 0x60, 0xc0, 0x00},
Expand Down Expand Up @@ -130,7 +130,7 @@ namespace picosystem {
{3, 0xc0, 0xc0, 0xe0, 0xc0, 0xc0, 0xc0, 0x60, 0x00},
{5, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0xd8, 0x68, 0x00},
{5, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0x70, 0x20, 0x00},
{6, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xec, 0x5c, 0x00},
{7, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0x6c, 0x00},
{6, 0x00, 0x00, 0xcc, 0x78, 0x30, 0x78, 0xcc, 0x00},
{5, 0x00, 0x00, 0xd8, 0xd8, 0xd8, 0x78, 0x18, 0x70},
{5, 0x00, 0x00, 0xf8, 0x30, 0x60, 0xc0, 0xf8, 0x00},
Expand Down
143 changes: 143 additions & 0 deletions libraries/blend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,150 @@ namespace picosystem {
// step destination and source
pd++; so += ss;
}
}

// compares source and destination RGB channels and picks the darker of the
// two. if there is global alpha the result is then blended with the
// destination.
void DARKEN(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));
color_t d = *pd;

uint16_t sr = (s & 0x000f), sg = (s & 0xf000), sb = (s & 0x0f00);
uint16_t dr = (d & 0x000f), dg = (d & 0xf000), db = (d & 0x0f00);
uint16_t sa = (s & 0x00f0);

s = (sr < dr ? sr : dr) | (sg < dg ? sg : dg) | (sb < db ? sb : db) | sa;
ALPHA(&s, 0, 0, pd, 1);

// step destination and source
pd++; so += ss;
}
}

// compares source and destination RGB channels and picks the lighter of the
// two. if there is global alpha the result is then blended with the
// destination.
void LIGHTEN(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));
color_t d = *pd;

uint16_t sr = (s & 0x000f), sg = (s & 0xf000), sb = (s & 0x0f00);
uint16_t dr = (d & 0x000f), dg = (d & 0xf000), db = (d & 0x0f00);
uint16_t sa = (s & 0x00f0);

s = (sr > dr ? sr : dr) | (sg > dg ? sg : dg) | (sb > db ? sb : db) | sa;
ALPHA(&s, 0, 0, pd, 1);

// step destination and source
pd++; so += ss;
}
}

// compares source and destination RGB channels and picks the lighter of the
// two. if there is global alpha the result is then blended with the
// destination.
void ADD(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));
color_t d = *pd;

int32_t sr = (s & 0x000f), sg = (s & 0xf000), sb = (s & 0x0f00);
int32_t dr = (d & 0x000f), dg = (d & 0xf000), db = (d & 0x0f00);
int32_t sa = (s & 0x00f0);

dr += sr;
dg += sg;
db += sb;

dr = dr > 15 ? 15 : dr;
dg = dg > (15 << 12) ? (15 << 12) : dg;
db = db > (15 << 8) ? (15 << 8) : db;

s = dr | dg | db | sa;

ALPHA(&s, 0, 0, pd, 1);

// step destination and source
pd++; so += ss;
}
}

// compares source and destination RGB channels and picks the lighter of the
// two. if there is global alpha the result is then blended with the
// destination.
void SUBTRACT(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));
color_t d = *pd;

int32_t sr = (s & 0x000f), sg = (s & 0xf000), sb = (s & 0x0f00);
int32_t dr = (d & 0x000f), dg = (d & 0xf000), db = (d & 0x0f00);
int32_t sa = (s & 0x00f0);

dr = dr > sr ? dr - sr : 0;
dg = dg > sg ? dg - sg : 0;
db = db > sb ? db - sb : 0;

s = dr | dg | db | sa;
ALPHA(&s, 0, 0, pd, 1);

// step destination and source
pd++; so += ss;
}
}

// compares source and destination RGB channels and picks the lighter of the
// two. if there is global alpha the result is then blended with the
// destination.
void MULTIPLY(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));
color_t d = *pd;

int32_t sr = (s & 0x000f), sg = (s & 0xf000), sb = (s & 0x0f00);
int32_t dr = (d & 0x000f), dg = (d & 0xf000), db = (d & 0x0f00);
int32_t sa = (s & 0x00f0);

dr = (sr * dr) >> 4;
dg = (sg * dg) >> 18;
db = (sb * db) >> 12;

s = dr | dg | db | sa;
ALPHA(&s, 0, 0, pd, 1);

// step destination and source
pd++; so += ss;
}
}

uint32_t _hash(uint32_t v) {
int n = 4;
do {
v = ((v >> 8) ^ v) * 0xD2 + n;
} while(--n);
return v;
}
// performs a "fizzlefade" style effect by only copying the source pixel if
// the destination pointer address hashes to a value < source alpha
void DISSOLVE(color_t *ps, uint32_t so, int32_t ss, color_t *pd, uint32_t c) {
while(c--) {
color_t s = *(ps + (so >> 16));

int32_t sa = (s & 0x00f0) >> 4;

// create 4-bit hash of destination pointer...
int32_t h = _hash(int32_t(pd) >> 1) & 0x000f;
h = h == 0 ? 0 : h - 1;
if(h < sa) {
COPY(&s, 0, 0, pd, 1);
}

// step destination and source
pd++; so += ss;
}
}

// blends the source and destination
Expand Down
4 changes: 2 additions & 2 deletions libraries/hardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ namespace picosystem {
FRMCTR1 = 0xB1, FRMCTR2 = 0xB2, GMCTRP1 = 0xE0, GMCTRN1 = 0xE1,
INVOFF = 0x20, SLPOUT = 0x11, DISPON = 0x29, GAMSET = 0x26,
DISPOFF = 0x28, RAMWR = 0x2C, INVON = 0x21, CASET = 0x2A,
RASET = 0x2B, STE = 0x44
RASET = 0x2B, STE = 0x44, DGMEN = 0xBA,
};

_screen_command(SWRESET);
Expand All @@ -352,7 +352,7 @@ namespace picosystem {
_screen_command(TEON, 1, "\x00");
_screen_command(FRMCTR2, 5, "\x0C\x0C\x00\x33\x33");
_screen_command(COLMOD, 1, "\x03");
_screen_command(GAMSET, 1, "\x04");
_screen_command(GAMSET, 1, "\x01");

_screen_command(GCTRL, 1, "\x14");
_screen_command(VCOMS, 1, "\x25");
Expand Down
12 changes: 12 additions & 0 deletions libraries/picosystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ namespace picosystem {
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void PEN(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void DARKEN(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void LIGHTEN(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void ADD(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void SUBTRACT(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void MULTIPLY(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);
void DISSOLVE(
color_t* ps, uint32_t so, int32_t ss, color_t* pd, uint32_t c);

// audio
void play(
Expand Down

0 comments on commit 225446c

Please sign in to comment.