mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
Merge pull request #336 from kichikuou/draw_filter
Parts: support and fix multiply/screen draw_filter
This commit is contained in:
+24
-9
@@ -20,6 +20,7 @@ uniform vec2 bot_left;
|
||||
uniform vec2 top_right;
|
||||
uniform vec3 add_color;
|
||||
uniform vec3 multiply_color;
|
||||
uniform int draw_filter;
|
||||
|
||||
uniform int use_clipper;
|
||||
uniform sampler2D clipper_tex;
|
||||
@@ -28,23 +29,37 @@ in vec2 tex_coord;
|
||||
in vec2 clip_coord;
|
||||
out vec4 frag_color;
|
||||
|
||||
float point_in_rect(vec2 p, vec2 bot_left, vec2 top_right) {
|
||||
vec2 s = step(bot_left, p) - step(top_right, p);
|
||||
return s.x * s.y;
|
||||
const int DRAW_FILTER_MULTIPLY = 2;
|
||||
const int DRAW_FILTER_SCREEN = 3;
|
||||
|
||||
bool inside_rect(vec2 p, vec2 bl, vec2 tr) {
|
||||
return all(greaterThanEqual(p, bl)) && all(lessThan(p, tr));
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 size = vec2(textureSize(tex, 0));
|
||||
vec2 bl = bot_left / size;
|
||||
vec2 tr = top_right / size;
|
||||
vec2 size = vec2(textureSize(tex, 0));
|
||||
if (!inside_rect(tex_coord, bot_left / size, top_right / size))
|
||||
discard;
|
||||
|
||||
vec4 tex_color = texture(tex, tex_coord);
|
||||
vec3 mod_color = (tex_color.rgb + add_color) * multiply_color;
|
||||
|
||||
float alpha = tex_color.a * blend_rate;
|
||||
|
||||
if (use_clipper != 0) {
|
||||
alpha *= texture(clipper_tex, clip_coord).a * point_in_rect(clip_coord, vec2(0.0), vec2(1.0));
|
||||
if (!inside_rect(clip_coord, vec2(0.0), vec2(1.0)))
|
||||
discard;
|
||||
alpha *= texture(clipper_tex, clip_coord).a;
|
||||
}
|
||||
|
||||
frag_color = vec4(mod_color, alpha) * point_in_rect(tex_coord, bl, tr);
|
||||
if (draw_filter == DRAW_FILTER_MULTIPLY) {
|
||||
// result = mix(dst, mod_color*dst, alpha), used with (GL_DST_COLOR, GL_ZERO)
|
||||
frag_color = vec4(mix(vec3(1.0), mod_color, alpha), 1.0);
|
||||
} else if (draw_filter == DRAW_FILTER_SCREEN) {
|
||||
// result = mod_color*alpha + (1 - mod_color*alpha)*dst,
|
||||
// used with (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
|
||||
frag_color = vec4(mod_color * alpha, 1.0);
|
||||
} else {
|
||||
// normal or additive — blend func handles alpha
|
||||
frag_color = vec4(mod_color, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1728,8 +1728,6 @@ void PE_SetAlpha(int parts_no, int alpha)
|
||||
|
||||
void PE_SetPartsDrawFilter(int parts_no, int draw_filter)
|
||||
{
|
||||
if (draw_filter && draw_filter != 1)
|
||||
UNIMPLEMENTED("(%d, %d)", parts_no, draw_filter);
|
||||
parts_get(parts_no)->draw_filter = draw_filter;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,6 +265,13 @@ enum parts_flash_blend_mode {
|
||||
PARTS_FLASH_BLEND_HARDLIGHT = 14,
|
||||
};
|
||||
|
||||
enum parts_draw_filter {
|
||||
PARTS_DRAW_FILTER_NORMAL = 0,
|
||||
PARTS_DRAW_FILTER_ADDITIVE = 1,
|
||||
PARTS_DRAW_FILTER_MULTIPLY = 2,
|
||||
PARTS_DRAW_FILTER_SCREEN = 3,
|
||||
};
|
||||
|
||||
struct parts_flash_object {
|
||||
TAILQ_ENTRY(parts_flash_object) entry;
|
||||
uint16_t depth;
|
||||
|
||||
+28
-26
@@ -46,12 +46,30 @@ static struct {
|
||||
GLint top_right;
|
||||
GLint add_color;
|
||||
GLint multiply_color;
|
||||
GLint draw_filter;
|
||||
GLint use_clipper;
|
||||
GLint clipper_tex;
|
||||
GLint inv_clipper_transform;
|
||||
} parts_shader;
|
||||
|
||||
static void parts_render_texture(struct texture *texture, mat4 mw_transform, Rectangle *rect, float blend_rate, vec3 add_color, vec3 multiply_color, int alpha_clipper)
|
||||
static void set_draw_filter_blend_func(int draw_filter)
|
||||
{
|
||||
switch (draw_filter) {
|
||||
case PARTS_DRAW_FILTER_ADDITIVE:
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
case PARTS_DRAW_FILTER_MULTIPLY:
|
||||
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
case PARTS_DRAW_FILTER_SCREEN:
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void parts_render_texture(struct texture *texture, mat4 mw_transform, Rectangle *rect, float blend_rate, vec3 add_color, vec3 multiply_color, int draw_filter, int alpha_clipper)
|
||||
{
|
||||
mat4 wv_transform = WV_TRANSFORM(config.view_width, config.view_height);
|
||||
|
||||
@@ -70,6 +88,7 @@ static void parts_render_texture(struct texture *texture, mat4 mw_transform, Rec
|
||||
glUniform2f(parts_shader.top_right, rect->x + rect->w, rect->y + rect->h);
|
||||
glUniform3fv(parts_shader.add_color, 1, add_color);
|
||||
glUniform3fv(parts_shader.multiply_color, 1, multiply_color);
|
||||
glUniform1i(parts_shader.draw_filter, draw_filter);
|
||||
|
||||
struct parts *clipper = alpha_clipper ? parts_try_get(alpha_clipper) : NULL;
|
||||
if (clipper) {
|
||||
@@ -121,7 +140,7 @@ static void parts_render_text(struct parts *parts, struct parts_text *t)
|
||||
struct parts_text_char *ch = &line->chars[j];
|
||||
mat4 mw_transform = WORLD_TRANSFORM(ch->t.w, ch->t.h, x, y);
|
||||
Rectangle r = { 0, 0, ch->t.w, ch->t.h };
|
||||
parts_render_texture(&ch->t, mw_transform, &r, blend_rate, add_color, multiply_color, parts->alpha_clipper_parts_no);
|
||||
parts_render_texture(&ch->t, mw_transform, &r, blend_rate, add_color, multiply_color, 0, parts->alpha_clipper_parts_no);
|
||||
x += ch->advance;
|
||||
}
|
||||
x = parts->global.pos.x + t->common.origin_offset.x;
|
||||
@@ -131,13 +150,7 @@ static void parts_render_text(struct parts *parts, struct parts_text *t)
|
||||
|
||||
static void parts_render_cg(struct parts *parts, struct parts_common *common)
|
||||
{
|
||||
switch (parts->draw_filter) {
|
||||
case 1:
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
set_draw_filter_blend_func(parts->draw_filter);
|
||||
|
||||
mat4 mw_transform = GLM_MAT4_IDENTITY_INIT;
|
||||
glm_translate(mw_transform, (vec3) { parts->global.pos.x, parts->global.pos.y, 0 });
|
||||
@@ -164,7 +177,7 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common)
|
||||
parts->global.multiply_color.g / 255.0f,
|
||||
parts->global.multiply_color.b / 255.0f,
|
||||
};
|
||||
parts_render_texture(&common->texture, mw_transform, &r, parts->global.alpha / 255.0, add_color, multiply_color, parts->alpha_clipper_parts_no);
|
||||
parts_render_texture(&common->texture, mw_transform, &r, parts->global.alpha / 255.0, add_color, multiply_color, parts->draw_filter, parts->alpha_clipper_parts_no);
|
||||
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
@@ -206,19 +219,7 @@ static void render_flat_item(struct parts *parts, struct parts_flat *f,
|
||||
return;
|
||||
Texture *tex = &f->textures[lib_idx];
|
||||
|
||||
switch (key->draw_filter) {
|
||||
case 1: // additive
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
case 2: // multiply
|
||||
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
case 3: // screen
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
set_draw_filter_blend_func(key->draw_filter);
|
||||
|
||||
mat4 render_m;
|
||||
glm_mat4_copy(combined, render_m);
|
||||
@@ -234,9 +235,9 @@ static void render_flat_item(struct parts *parts, struct parts_flat *f,
|
||||
vec3 add_color = { key->add_r / 255.0f, key->add_g / 255.0f, key->add_b / 255.0f };
|
||||
vec3 mul_color = { key->mul_r / 255.0f, key->mul_g / 255.0f, key->mul_b / 255.0f };
|
||||
parts_render_texture(tex, render_m, &rect, alpha, add_color, mul_color,
|
||||
parts->alpha_clipper_parts_no);
|
||||
key->draw_filter, parts->alpha_clipper_parts_no);
|
||||
|
||||
if (key->draw_filter != 0)
|
||||
if (key->draw_filter != PARTS_DRAW_FILTER_NORMAL)
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
break;
|
||||
}
|
||||
@@ -329,7 +330,7 @@ static void parts_render_flash_shape(struct parts *parts, struct parts_flash *f,
|
||||
(parts->global.multiply_color.g / 255.0f) * fixed16_to_float(obj->color_transform.mult_terms[1]),
|
||||
(parts->global.multiply_color.b / 255.0f) * fixed16_to_float(obj->color_transform.mult_terms[2])
|
||||
};
|
||||
parts_render_texture(src, mw_transform, &r, blend_rate, add_color, multiply_color, parts->alpha_clipper_parts_no);
|
||||
parts_render_texture(src, mw_transform, &r, blend_rate, add_color, multiply_color, 0, parts->alpha_clipper_parts_no);
|
||||
}
|
||||
|
||||
static void parts_render_flash_sprite(struct parts *parts, struct parts_flash *f, struct parts_flash_object *obj, struct swf_tag_define_sprite *tag)
|
||||
@@ -502,6 +503,7 @@ void parts_render_init(void)
|
||||
parts_shader.top_right = glGetUniformLocation(parts_shader.shader.program, "top_right");
|
||||
parts_shader.add_color = glGetUniformLocation(parts_shader.shader.program, "add_color");
|
||||
parts_shader.multiply_color = glGetUniformLocation(parts_shader.shader.program, "multiply_color");
|
||||
parts_shader.draw_filter = glGetUniformLocation(parts_shader.shader.program, "draw_filter");
|
||||
parts_shader.use_clipper = glGetUniformLocation(parts_shader.shader.program, "use_clipper");
|
||||
parts_shader.clipper_tex = glGetUniformLocation(parts_shader.shader.program, "clipper_tex");
|
||||
parts_shader.inv_clipper_transform = glGetUniformLocation(parts_shader.shader.program, "inv_clipper_transform");
|
||||
|
||||
Reference in New Issue
Block a user