premult alpha for sprites and bitmap fonts, bm font outline support, optional vertex snapping

This commit is contained in:
2019-08-22 08:00:17 +07:00
parent 87e2231f5c
commit bbefa65d98
17 changed files with 866 additions and 553 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f1044cd99d8bd2b0576b06928493cf7cdad421bae5d71c56a436cc33f59c30a
size 217444
oid sha256:cdd1e2d175c5109ec5840ea37093e7f745fbf618b709ee334b7459ef1567960a
size 61729

View File

@@ -3,7 +3,7 @@
"shader" : "font_bm_shader.json",
"state_block" : {
"blending_state" : {
"src_factor" : "src_alpha",
"src_factor" : "one",
"dst_factor" : "one_minus_src_alpha"
},
"capabilities_state" : {

View File

@@ -1,8 +1,26 @@
uniform sampler2D u_texture;
uniform float u_glyph_dilate;
uniform float u_outline_width;
uniform vec4 u_outline_color;
varying vec2 v_st0;
varying vec4 v_color;
varying vec4 v_color0;
void main() {
gl_FragColor = texture2D(u_texture, v_st0) * v_color;
vec4 t = texture2D(u_texture, v_st0);
float glyph_alpha = t.a;
float outline_alpha = t.r;
vec4 glyph_color = vec4(v_color0.rgb * v_color0.a, v_color0.a);
vec4 outline_color = vec4(u_outline_color.rgb * u_outline_color.a, u_outline_color.a);
vec2 layers_mask = vec2(
step(0.0001, v_color0.a),
step(0.0001, u_outline_color.a * u_outline_width));
gl_FragColor =
layers_mask.x * glyph_alpha * glyph_color +
layers_mask.y * outline_alpha * outline_color * (1.0 - glyph_alpha);
}

View File

@@ -1,3 +1,4 @@
uniform vec2 u_screen_s;
uniform mat4 u_matrix_m;
uniform mat4 u_matrix_vp;
@@ -6,10 +7,33 @@ attribute vec2 a_st0;
attribute vec4 a_color0;
varying vec2 v_st0;
varying vec4 v_color;
varying vec4 v_color0;
#define VERTEX_SNAPPING_ON
vec2 round(vec2 v) {
return vec2(
floor(v.x + 0.5),
floor(v.y + 0.5));
}
vec4 pixel_snap(vec4 pos) {
vec2 hpc = u_screen_s * 0.5;
vec2 pixel_pos = round((pos.xy / pos.w) * hpc);
pos.xy = pixel_pos / hpc * pos.w;
return pos;
}
vec4 vertex_to_homo(vec3 pos) {
return vec4(pos, 1.0) * u_matrix_m * u_matrix_vp;
}
void main() {
v_st0 = vec2(a_st0.s, 1.0 - a_st0.t);
v_color = a_color0;
gl_Position = vec4(a_vertex, 1.0) * u_matrix_m * u_matrix_vp;
v_color0 = a_color0;
#ifndef VERTEX_SNAPPING_ON
gl_Position = vertex_to_homo(a_vertex);
#else
gl_Position = pixel_snap(vertex_to_homo(a_vertex));
#endif
}

View File

@@ -1,3 +1,7 @@
#ifdef GL_OES_standard_derivatives
# extension GL_OES_standard_derivatives : require
#endif
uniform sampler2D u_texture;
uniform float u_glyph_dilate;
@@ -5,7 +9,7 @@ uniform float u_outline_width;
uniform vec4 u_outline_color;
varying vec2 v_st0;
varying vec4 v_color;
varying vec4 v_color0;
void main() {
float distance = texture2D(u_texture, v_st0).a;
@@ -17,13 +21,14 @@ void main() {
float glyph_alpha = smoothstep(glyph_center - width, glyph_center + width, distance);
float outline_alpha = smoothstep(outline_center - width, outline_center + width, distance);
vec4 glyph_color = vec4(v_color.rgb * v_color.a, v_color.a);
vec4 glyph_color = vec4(v_color0.rgb * v_color0.a, v_color0.a);
vec4 outline_color = vec4(u_outline_color.rgb * u_outline_color.a, u_outline_color.a);
vec2 layers_mask = vec2(
step(0.01, v_color.a),
step(0.01, u_outline_color.a * u_outline_width));
step(0.0001, v_color0.a),
step(0.0001, u_outline_color.a * u_outline_width));
gl_FragColor = glyph_alpha * glyph_color * layers_mask.x +
outline_alpha * outline_color * layers_mask.y * (1.0 - glyph_alpha);
gl_FragColor =
layers_mask.x * glyph_alpha * glyph_color +
layers_mask.y * outline_alpha * outline_color * (1.0 - glyph_alpha);
}

View File

@@ -1,3 +1,4 @@
uniform vec2 u_screen_s;
uniform mat4 u_matrix_m;
uniform mat4 u_matrix_vp;
@@ -6,10 +7,33 @@ attribute vec2 a_st0;
attribute vec4 a_color0;
varying vec2 v_st0;
varying vec4 v_color;
varying vec4 v_color0;
#define VERTEX_SNAPPING_ON
vec2 round(vec2 v) {
return vec2(
floor(v.x + 0.5),
floor(v.y + 0.5));
}
vec4 pixel_snap(vec4 pos) {
vec2 hpc = u_screen_s * 0.5;
vec2 pixel_pos = round((pos.xy / pos.w) * hpc);
pos.xy = pixel_pos / hpc * pos.w;
return pos;
}
vec4 vertex_to_homo(vec3 pos) {
return vec4(pos, 1.0) * u_matrix_m * u_matrix_vp;
}
void main() {
v_st0 = vec2(a_st0.s, 1.0 - a_st0.t);
v_color = a_color0;
gl_Position = vec4(a_vertex, 1.0) * u_matrix_m * u_matrix_vp;
v_color0 = a_color0;
#ifndef VERTEX_SNAPPING_ON
gl_Position = vertex_to_homo(a_vertex);
#else
gl_Position = pixel_snap(vertex_to_homo(a_vertex));
#endif
}

View File

@@ -3,6 +3,5 @@ uniform sampler2D u_texture;
varying vec2 v_st0;
void main() {
vec2 st = vec2(v_st0.s, 1.0 - v_st0.t);
gl_FragColor = texture2D(u_texture, st);
gl_FragColor = texture2D(u_texture, v_st0);
}

View File

@@ -6,7 +6,11 @@ attribute vec2 a_st0;
varying vec2 v_st0;
void main() {
v_st0 = a_st0;
gl_Position = vec4(a_vertex, 1.0) * u_matrix_m * u_matrix_vp;
vec4 vertex_to_homo(vec3 pos) {
return vec4(pos, 1.0) * u_matrix_m * u_matrix_vp;
}
void main() {
v_st0 = vec2(a_st0.s, 1.0 - a_st0.t);
gl_Position = vertex_to_homo(a_vertex);
}

View File

@@ -22,6 +22,9 @@
}, {
"prototype" : "ship_prefab.json",
"components" : {
"sprite_renderer" : {
"tint" : [255,0,0,255]
},
"actor" : {
"translation" : [50,-50,0]
}
@@ -31,7 +34,9 @@
"components" : {
"label" : {
"text" : "bm font",
"valign" : "center"
"valign" : "center",
"outline_width" : 0.5,
"outline_color" : [0,0,0,255]
},
"actor" : {
"translation" : [0,180,0],
@@ -44,11 +49,11 @@
"label" : {
"text" : "sdf font",
"valign" : "center",
"outline_width" : 0.2,
"outline_width" : 0.5,
"outline_color" : [0,0,0,255]
},
"actor" : {
"translation" : [0,-180,0],
"translation" : [0.5,-180.5,0],
"scale" : 3
}
}

View File

@@ -3,7 +3,7 @@
"shader" : "sprite_shader.json",
"state_block" : {
"blending_state" : {
"src_factor" : "src_alpha",
"src_factor" : "one",
"dst_factor" : "one_minus_src_alpha"
},
"capabilities_state" : {

View File

@@ -1,9 +1,10 @@
uniform sampler2D u_texture;
varying vec4 v_tint;
varying vec2 v_st;
varying vec2 v_st0;
varying vec4 v_color0;
void main() {
vec2 st = vec2(v_st.s, 1.0 - v_st.t);
gl_FragColor = texture2D(u_texture, st) * v_tint;
vec4 c = texture2D(u_texture, v_st0) * v_color0;
c.rgb *= c.a;
gl_FragColor = c;
}

View File

@@ -1,14 +1,36 @@
uniform vec2 u_screen_s;
uniform mat4 u_matrix_vp;
attribute vec3 a_vertex;
attribute vec4 a_tint;
attribute vec2 a_st;
attribute vec2 a_st0;
attribute vec4 a_color0;
varying vec4 v_tint;
varying vec2 v_st;
varying vec2 v_st0;
varying vec4 v_color0;
vec2 round(vec2 v) {
return vec2(
floor(v.x + 0.5),
floor(v.y + 0.5));
}
vec4 pixel_snap(vec4 pos) {
vec2 hpc = u_screen_s * 0.5;
vec2 pixel_pos = round((pos.xy / pos.w) * hpc);
pos.xy = pixel_pos / hpc * pos.w;
return pos;
}
vec4 vertex_to_homo(vec3 pos) {
return vec4(pos, 1.0) * u_matrix_vp;
}
void main() {
v_st = a_st;
v_tint = a_tint;
gl_Position = vec4(a_vertex, 1.0) * u_matrix_vp;
v_st0 = vec2(a_st0.s, 1.0 - a_st0.t);
v_color0 = a_color0;
#ifndef VERTEX_SNAPPING_ON
gl_Position = vertex_to_homo(a_vertex);
#else
gl_Position = pixel_snap(vertex_to_homo(a_vertex));
#endif
}

View File

@@ -99,7 +99,7 @@ namespace e2d
class render_system::internal_state final : private noncopyable {
public:
internal_state()
: drawer_(the<engine>(), the<debug>(), the<render>()) {}
: drawer_(the<engine>(), the<debug>(), the<render>(), the<window>()) {}
~internal_state() noexcept = default;
void process(ecs::registry& owner) {

View File

@@ -40,8 +40,8 @@ namespace e2d::render_system_impl
static vertex_declaration decl() noexcept {
return vertex_declaration()
.add_attribute<v3f>("a_vertex")
.add_attribute<v2f>("a_st")
.add_attribute<color32>("a_tint").normalized();
.add_attribute<v2f>("a_st0")
.add_attribute<color32>("a_color0").normalized();
}
};
}

View File

@@ -14,6 +14,7 @@ namespace
{
using namespace e2d;
const str_hash screen_s_property_hash = "u_screen_s";
const str_hash matrix_v_property_hash = "u_matrix_v";
const str_hash matrix_p_property_hash = "u_matrix_p";
const str_hash matrix_vp_property_hash = "u_matrix_vp";
@@ -32,6 +33,7 @@ namespace e2d::render_system_impl
const const_node_iptr& cam_n,
engine& engine,
render& render,
window& window,
batcher_type& batcher)
: render_(render)
, batcher_(batcher)
@@ -47,6 +49,9 @@ namespace e2d::render_system_impl
const m4f& m_p = cam.projection();
batcher_.flush()
.property(screen_s_property_hash, cam.target()
? cam.target()->size().cast_to<f32>()
: window.framebuffer_size().cast_to<f32>())
.property(matrix_v_property_hash, m_v)
.property(matrix_p_property_hash, m_p)
.property(matrix_vp_property_hash, m_v * m_p)
@@ -219,8 +224,9 @@ namespace e2d::render_system_impl
// drawer
//
drawer::drawer(engine& e, debug& d, render& r)
drawer::drawer(engine& e, debug& d, render& r, window& w)
: engine_(e)
, render_(r)
, window_(w)
, batcher_(d, r) {}
}

View File

@@ -36,6 +36,7 @@ namespace e2d::render_system_impl
const const_node_iptr& cam_n,
engine& engine,
render& render,
window& window,
batcher_type& batcher);
~context() noexcept;
@@ -59,13 +60,14 @@ namespace e2d::render_system_impl
render::property_block property_cache_;
};
public:
drawer(engine& e, debug& d, render& r);
drawer(engine& e, debug& d, render& r, window& w);
template < typename F >
void with(const camera& cam, const const_node_iptr& cam_n, F&& f);
private:
engine& engine_;
render& render_;
window& window_;
batcher_type batcher_;
};
}
@@ -74,7 +76,7 @@ namespace e2d::render_system_impl
{
template < typename F >
void drawer::with(const camera& cam, const const_node_iptr& cam_n, F&& f) {
context ctx{cam, cam_n, engine_, render_, batcher_};
context ctx{cam, cam_n, engine_, render_, window_, batcher_};
std::forward<F>(f)(ctx);
ctx.flush();
}