mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-29 18:38:04 +03:00
Implement PartsEngine.SetPartsAlphaClipperPartsNumber
This allows a specified part to be used as an alpha map (clipper) during rendering. A dedicated vertex shader (parts.v.glsl) is introduced to calculate clipping coordinates using an inverse transformation matrix. Refactored parts_render_text() to use parts_render_texture() so that alpha clipping is applied to text. This also enables color modifications for text, while rotation and scaling remain unsupported, matching the original PartsEngine behavior. Incremented the parts save version since alpha_clipper_parts_no is now persisted.
This commit is contained in:
@@ -373,6 +373,7 @@ cJSON *parts_to_json(struct parts *parts, bool recursive, bool verbose)
|
||||
cJSON_AddNumberToObject(obj, "linked_from", parts->linked_from);
|
||||
cJSON_AddNumberToObject(obj, "draw_filter", parts->draw_filter);
|
||||
cJSON_AddBoolToObject(obj, "message_window", parts->message_window);
|
||||
cJSON_AddNumberToObject(obj, "alpha_clipper_parts_no", parts->alpha_clipper_parts_no);
|
||||
|
||||
cJSON_AddItemToObjectCS(obj, "motions", motions = cJSON_CreateArray());
|
||||
struct parts_motion *motion;
|
||||
|
||||
+3
-1
@@ -1769,7 +1769,9 @@ float PE_GetPartsRotateZ(int parts_no)
|
||||
|
||||
void PE_SetPartsAlphaClipperPartsNumber(int parts_no, int alpha_clipper_parts_no)
|
||||
{
|
||||
UNIMPLEMENTED("(%d, %d)", parts_no, alpha_clipper_parts_no);
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
parts->alpha_clipper_parts_no = alpha_clipper_parts_no;
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
void PE_SetPartsPixelDecide(int parts_no, bool pixel_decide)
|
||||
|
||||
@@ -334,6 +334,7 @@ struct parts {
|
||||
int linked_from;
|
||||
int draw_filter;
|
||||
bool message_window;
|
||||
int alpha_clipper_parts_no;
|
||||
struct parts_motion_list motion;
|
||||
};
|
||||
|
||||
|
||||
+66
-26
@@ -43,31 +43,12 @@ static struct {
|
||||
GLint top_right;
|
||||
GLint add_color;
|
||||
GLint multiply_color;
|
||||
GLint use_clipper;
|
||||
GLint clipper_tex;
|
||||
GLint inv_clipper_transform;
|
||||
} parts_shader;
|
||||
|
||||
static void parts_render_text(struct parts *parts, struct parts_text *t)
|
||||
{
|
||||
int x = parts->global.pos.x + t->common.origin_offset.x;
|
||||
int y = parts->global.pos.y + t->common.origin_offset.y;
|
||||
for (int i = 0; i < t->nr_lines; i++) {
|
||||
struct parts_text_line *line = &t->lines[i];
|
||||
for (int j = 0; j < line->nr_chars; j++) {
|
||||
struct parts_text_char *ch = &line->chars[j];
|
||||
Rectangle rect = {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.w = ch->t.w,
|
||||
.h = ch->t.h
|
||||
};
|
||||
gfx_render_texture(&ch->t, &rect);
|
||||
x += ch->advance;
|
||||
}
|
||||
x = parts->global.pos.x + t->common.origin_offset.x;
|
||||
y += line->height;
|
||||
}
|
||||
}
|
||||
|
||||
static void parts_render_texture(struct texture *texture, mat4 mw_transform, Rectangle *rect, float blend_rate, vec3 add_color, vec3 multiply_color)
|
||||
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)
|
||||
{
|
||||
mat4 wv_transform = WV_TRANSFORM(config.view_width, config.view_height);
|
||||
|
||||
@@ -86,9 +67,65 @@ 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);
|
||||
|
||||
struct parts *clipper = alpha_clipper ? parts_try_get(alpha_clipper) : NULL;
|
||||
if (clipper) {
|
||||
struct parts_common *c_common = &clipper->states[clipper->state].common;
|
||||
|
||||
// Calculate the inverse of the clipper's world matrix.
|
||||
mat4 clip_mw = GLM_MAT4_IDENTITY_INIT;
|
||||
glm_translate(clip_mw, (vec3) { clipper->global.pos.x, clipper->global.pos.y, 0 });
|
||||
glm_rotate_z(clip_mw, clipper->local.rotation.z * (M_PI/180.0), clip_mw);
|
||||
glm_scale(clip_mw, (vec3){ clipper->global.scale.x, clipper->global.scale.y, 1.0 });
|
||||
glm_translate(clip_mw, (vec3){ c_common->origin_offset.x, c_common->origin_offset.y, 0 });
|
||||
glm_scale(clip_mw, (vec3){ c_common->w, c_common->h, 1.0 });
|
||||
mat4 clip_inv;
|
||||
glm_mat4_inv(clip_mw, clip_inv);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, c_common->texture.handle);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glUniform1i(parts_shader.use_clipper, 1);
|
||||
glUniform1i(parts_shader.clipper_tex, 1);
|
||||
glUniformMatrix4fv(parts_shader.inv_clipper_transform, 1, GL_FALSE, clip_inv[0]);
|
||||
} else {
|
||||
glUniform1i(parts_shader.use_clipper, 0);
|
||||
}
|
||||
|
||||
gfx_run_job(&job);
|
||||
}
|
||||
|
||||
static void parts_render_text(struct parts *parts, struct parts_text *t)
|
||||
{
|
||||
vec3 add_color = {
|
||||
parts->global.add_color.r / 255.0f,
|
||||
parts->global.add_color.g / 255.0f,
|
||||
parts->global.add_color.b / 255.0f
|
||||
};
|
||||
vec3 multiply_color = {
|
||||
parts->global.multiply_color.r / 255.0f,
|
||||
parts->global.multiply_color.g / 255.0f,
|
||||
parts->global.multiply_color.b / 255.0f,
|
||||
};
|
||||
float blend_rate = parts->global.alpha / 255.0;
|
||||
|
||||
int x = parts->global.pos.x + t->common.origin_offset.x;
|
||||
int y = parts->global.pos.y + t->common.origin_offset.y;
|
||||
for (int i = 0; i < t->nr_lines; i++) {
|
||||
struct parts_text_line *line = &t->lines[i];
|
||||
for (int j = 0; j < line->nr_chars; j++) {
|
||||
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);
|
||||
x += ch->advance;
|
||||
}
|
||||
x = parts->global.pos.x + t->common.origin_offset.x;
|
||||
y += line->height;
|
||||
}
|
||||
}
|
||||
|
||||
static void parts_render_cg(struct parts *parts, struct parts_common *common)
|
||||
{
|
||||
switch (parts->draw_filter) {
|
||||
@@ -124,7 +161,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_render_texture(&common->texture, mw_transform, &r, parts->global.alpha / 255.0, add_color, multiply_color, parts->alpha_clipper_parts_no);
|
||||
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
@@ -165,7 +202,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_render_texture(src, mw_transform, &r, blend_rate, add_color, multiply_color, 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)
|
||||
@@ -326,10 +363,13 @@ void parts_dirty(possibly_unused struct parts *parts)
|
||||
|
||||
void parts_render_init(void)
|
||||
{
|
||||
gfx_load_shader(&parts_shader.shader, "shaders/render.v.glsl", "shaders/parts.f.glsl");
|
||||
gfx_load_shader(&parts_shader.shader, "shaders/parts.v.glsl", "shaders/parts.f.glsl");
|
||||
parts_shader.blend_rate = glGetUniformLocation(parts_shader.shader.program, "blend_rate");
|
||||
parts_shader.bot_left = glGetUniformLocation(parts_shader.shader.program, "bot_left");
|
||||
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.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");
|
||||
}
|
||||
|
||||
+4
-1
@@ -22,7 +22,7 @@
|
||||
#include "parts_internal.h"
|
||||
#include "../hll/iarray.h"
|
||||
|
||||
#define CURRENT_SAVE_VERSION 2
|
||||
#define CURRENT_SAVE_VERSION 3
|
||||
|
||||
static void save_parts_params(struct iarray_writer *w, struct parts_params *params)
|
||||
{
|
||||
@@ -503,6 +503,7 @@ static void save_parts(struct iarray_writer *w, struct parts *parts)
|
||||
iarray_write(w, parts->linked_from);
|
||||
iarray_write(w, parts->draw_filter);
|
||||
iarray_write(w, parts->message_window);
|
||||
iarray_write(w, parts->alpha_clipper_parts_no);
|
||||
|
||||
unsigned motion_count_pos = iarray_writer_pos(w);
|
||||
iarray_write(w, 0); // size of motion list
|
||||
@@ -540,6 +541,8 @@ static void load_parts(struct iarray_reader *r, int version)
|
||||
parts->draw_filter = iarray_read(r);
|
||||
if (version > 0)
|
||||
parts->message_window = iarray_read(r);
|
||||
if (version > 2)
|
||||
parts->alpha_clipper_parts_no = iarray_read(r);
|
||||
|
||||
int motion_count = iarray_read(r);
|
||||
for (int i = 0; i < motion_count; i++) {
|
||||
|
||||
Reference in New Issue
Block a user