Skip to content

Commit

Permalink
Fixed premultiplied alpha. Added circle example.
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeysinyavsky committed May 5, 2020
1 parent cdbaf80 commit c991a44
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 46 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ First of all you need to create a table with a buffer information that contain n
`width` - buffer width, same as your texture width<br />
`height` - buffer height, same as your texture height<br />
`channels` - 3 for rgb, 4 for rgba<br />
`premultiply_alpha` - alpha value will be premultiplied into the RGB color values. Optional parameter. Default is false.<br />

For example:
```lua
Expand All @@ -35,7 +36,8 @@ local buffer_info = {
}}),
width = 1024,
height = 2048,
channels = 4
channels = 4,
premultiply_alpha = true
}
```
Then when you have a buffer info, you can use next methods:
Expand Down
79 changes: 42 additions & 37 deletions drawpixels/src/drawpixels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct BufferInfo
int width;
int height;
int channels;
bool premultiply_alpha;
uint8_t *bytes;
uint32_t src_size;
};
Expand Down Expand Up @@ -131,19 +132,13 @@ static void record_mix_pixel(int i, float r, float g, float b, float a)
recordtobuffer(i + 3, oa);
}

// static void record_empty_mix_pixel(int i, float r, float g, float b, float a)
// {
// float ba = 0;
// a = a / 255.0;
// float oa = a + ba * (1 - a);
// r = getmixrgb(1, ba, r / 255.0, a, oa);
// g = getmixrgb(1, ba, g / 255.0, a, oa);
// b = getmixrgb(1, ba, b / 255.0, a, oa);
// recordtobuffer(i, r);
// recordtobuffer(i + 1, g);
// recordtobuffer(i + 2, b);
// recordtobuffer(i + 3, oa);
// }
static void record_premul_alpha_pixel(int i, unsigned short r, unsigned short g, unsigned short b, unsigned short a)
{
buffer_info.bytes[i] = r * a >> 8;
buffer_info.bytes[i + 1] = g * a >> 8;
buffer_info.bytes[i + 2] = b * a >> 8;
buffer_info.bytes[i + 3] = a;
}

static void add_point(int x, int y)
{
Expand Down Expand Up @@ -181,7 +176,7 @@ static void mixpixel(int x, int y, float r, float g, float b, float a)
}

int i = xytoi(x, y);
if (buffer_info.channels == 3 || buffer_info.bytes[i + 3] == 0 || a == 255)
if (buffer_info.channels == 3 || a == 255 || (!buffer_info.premultiply_alpha && buffer_info.bytes[i + 3] == 0))
{
record_pixel(i, r, g, b, a);
return;
Expand All @@ -190,10 +185,10 @@ static void mixpixel(int x, int y, float r, float g, float b, float a)
{
return;
}
// if (buffer_info.bytes[i + 3] == 0)
// {
// record_empty_mix_pixel(i, r, g, b, a);
// }
if (buffer_info.premultiply_alpha && buffer_info.bytes[i + 3] == 0)
{
record_premul_alpha_pixel(i, r, g, b, a);
}

record_mix_pixel(i, r, g, b, a);
}
Expand Down Expand Up @@ -559,7 +554,8 @@ static void read_and_validate_buffer_info(lua_State *L, int index)
lua_getfield(L, index, "width");
lua_getfield(L, index, "height");
lua_getfield(L, index, "channels");
dmScript::LuaHBuffer *lua_buffer = dmScript::CheckBuffer(L, -4);
lua_getfield(L, index, "premultiply_alpha");
dmScript::LuaHBuffer *lua_buffer = dmScript::CheckBuffer(L, -5);
buffer_info.buffer = lua_buffer->m_Buffer;

if (!dmBuffer::IsBufferValid(buffer_info.buffer))
Expand All @@ -573,23 +569,32 @@ static void read_and_validate_buffer_info(lua_State *L, int index)
luaL_error(L, "Buffer is invalid");
}

buffer_info.width = lua_tointeger(L, -3);
buffer_info.width = lua_tointeger(L, -4);
if (buffer_info.width == 0)
{
luaL_error(L, "'width' of the buffer should be an integer and > 0");
}

buffer_info.height = lua_tointeger(L, -2);
buffer_info.height = lua_tointeger(L, -3);
if (buffer_info.height == 0)
{
luaL_error(L, "'height' of the buffer should be an integer and > 0");
}

buffer_info.channels = lua_tointeger(L, -1);
buffer_info.channels = lua_tointeger(L, -2);
if (buffer_info.channels == 0)
{
luaL_error(L, "'channels' of should be an integer and 3 or 4");
}

if (lua_isboolean(L, -1) == 1)
{
buffer_info.premultiply_alpha = lua_toboolean(L, -1);
}
else
{
buffer_info.premultiply_alpha = false;
}
}

static void draw_line(int x0, int y0, int x1, int y1, int r, int g, int b, int a)
Expand Down Expand Up @@ -1300,7 +1305,7 @@ static int stop_record_points_lua(lua_State *L)

static int fill_area_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;
read_and_validate_buffer_info(L, 1);
int32_t x = luaL_checknumber(L, 2);
int32_t y = luaL_checknumber(L, 3);
Expand All @@ -1326,7 +1331,7 @@ static int fill_area_lua(lua_State *L)

static int draw_triangle_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x0 = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1355,7 +1360,7 @@ static int draw_triangle_lua(lua_State *L)

static int draw_line_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x0 = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1400,7 +1405,7 @@ static int draw_line_lua(lua_State *L)

static int draw_gradient_line_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x0 = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1457,7 +1462,7 @@ static int draw_gradient_line_lua(lua_State *L)

static int draw_arc_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand All @@ -1483,7 +1488,7 @@ static int draw_arc_lua(lua_State *L)

static int draw_filled_arc_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1516,7 +1521,7 @@ static int draw_filled_arc_lua(lua_State *L)

static int draw_gradient_arc_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1565,7 +1570,7 @@ static int draw_gradient_arc_lua(lua_State *L)

static int draw_circle_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1609,7 +1614,7 @@ static int draw_circle_lua(lua_State *L)

static int draw_filled_circle_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1644,7 +1649,7 @@ static int draw_filled_circle_lua(lua_State *L)

static int fill_texture_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
uint8_t r = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1678,7 +1683,7 @@ static int fill_texture_lua(lua_State *L)

static int draw_rect_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1729,7 +1734,7 @@ bool sort_coords(const Point &p1, const Point &p2)

static int draw_filled_rect_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t posx = luaL_checknumber(L, 2);
Expand Down Expand Up @@ -1792,7 +1797,7 @@ static int draw_filled_rect_lua(lua_State *L)

static int draw_pixel_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x = luaL_checknumber(L, 2);
Expand All @@ -1814,7 +1819,7 @@ static int draw_pixel_lua(lua_State *L)

static int read_color_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x = luaL_checknumber(L, 2);
Expand All @@ -1840,7 +1845,7 @@ static int read_color_lua(lua_State *L)

static int draw_bezier_lua(lua_State *L)
{
int top = lua_gettop(L) + 4;
int top = lua_gettop(L) + 5;

read_and_validate_buffer_info(L, 1);
int32_t x0 = luaL_checknumber(L, 2);
Expand Down
2 changes: 1 addition & 1 deletion examples/arcs/arcs.collection
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ embedded_instances {
" type: \"sprite\"\n"
" data: \"tile_set: \\\"/examples/full.atlas\\\"\\n"
"default_animation: \\\"fullscreen512\\\"\\n"
"material: \\\"/examples/sprite.material\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n"
"\"\n"
" position {\n"
Expand Down
57 changes: 57 additions & 0 deletions examples/circle/circle.collection
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: "default"
scale_along_z: 0
embedded_instances {
id: "canvas"
data: "components {\n"
" id: \"circle\"\n"
" component: \"/examples/circle/circle.script\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
"embedded_components {\n"
" id: \"sprite\"\n"
" type: \"sprite\"\n"
" data: \"tile_set: \\\"/examples/full.atlas\\\"\\n"
"default_animation: \\\"fullscreen512\\\"\\n"
"material: \\\"/examples/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n"
"\"\n"
" position {\n"
" x: 8.572\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
"}\n"
""
position {
x: 248.0
y: 500.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}
24 changes: 24 additions & 0 deletions examples/circle/circle.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
function init(self)
msg.post("@render:", "clear_color", {color = vmath.vector4(1, 0, 0, 1)})
-- size of texture when scaled to nearest power of two
local width = 64
local height = 64
local channels = 4

self.resource_path = go.get("#sprite", "texture0")

self.buffer_info = {
buffer = buffer.create(width * height, {{name = hash("rgba"), type = buffer.VALUE_TYPE_UINT8, count = channels}}),
width = width,
height = height,
channels = channels,
premultiply_alpha = true
}

self.header = {width = width, height = height, type = resource.TEXTURE_TYPE_2D, format = resource.TEXTURE_FORMAT_RGBA, num_mip_maps = 1}
drawpixels.fill(self.buffer_info, 0, 0, 0, 0)

drawpixels.circle(self.buffer_info, width * 0.5, width * 0.5, width * 0.9, 0, 0, 255, 255, true)

resource.set_texture(self.resource_path, self.header, self.buffer_info.buffer)
end
2 changes: 1 addition & 1 deletion examples/fills/fills.collection
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ embedded_instances {
" type: \"sprite\"\n"
" data: \"tile_set: \\\"/examples/full.atlas\\\"\\n"
"default_animation: \\\"fullscreen512\\\"\\n"
"material: \\\"/examples/sprite.material\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n"
"\"\n"
" position {\n"
Expand Down
7 changes: 4 additions & 3 deletions examples/lines_aa/lines.script
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function init(self)
msg.post("@render:", "clear_color", {color = vmath.vector4(1, 1, 1, 1)})
msg.post("@render:", "clear_color", {color = vmath.vector4(1, 1, 0, 1)})
-- size of texture when scaled to nearest power of two
local width = 512
local height = 512
Expand All @@ -11,11 +11,12 @@ function init(self)
buffer = buffer.create(width * height, {{name = hash("rgba"), type = buffer.VALUE_TYPE_UINT8, count = channels}}),
width = width,
height = height,
channels = channels
channels = channels,
premultiply_alpha = true
}

self.header = {width = width, height = height, type = resource.TEXTURE_TYPE_2D, format = resource.TEXTURE_FORMAT_RGBA, num_mip_maps = 1}
drawpixels.fill(self.buffer_info, 255, 255, 0, 255)
drawpixels.fill(self.buffer_info, 0, 0, 0, 0)

drawpixels.gradient_line(self.buffer_info, width * 0.2, width * 0.1, width * 0.9, width * 0.9, 255, 0, 0, 0, 0, 255, 255, true, 12)
drawpixels.line(self.buffer_info, width * 0.2, width * 0.5, width * 0.9, width * 0.9, 0, 0, 255, 255, true, 5)
Expand Down
2 changes: 1 addition & 1 deletion examples/lines_aa/lines_aa.collection
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ embedded_instances {
" type: \"sprite\"\n"
" data: \"tile_set: \\\"/examples/full.atlas\\\"\\n"
"default_animation: \\\"fullscreen512\\\"\\n"
"material: \\\"/examples/sprite.material\\\"\\n"
"material: \\\"/builtins/materials/sprite.material\\\"\\n"
"blend_mode: BLEND_MODE_ALPHA\\n"
"\"\n"
" position {\n"
Expand Down
4 changes: 2 additions & 2 deletions examples/sprite.material
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ samplers {
name: "texture_sampler"
wrap_u: WRAP_MODE_CLAMP_TO_EDGE
wrap_v: WRAP_MODE_CLAMP_TO_EDGE
filter_min: FILTER_MODE_MIN_LINEAR
filter_mag: FILTER_MODE_MAG_LINEAR
filter_min: FILTER_MODE_MIN_NEAREST
filter_mag: FILTER_MODE_MAG_NEAREST
}

0 comments on commit c991a44

Please sign in to comment.