diff --git a/include/gfx/gfx.h b/include/gfx/gfx.h index e98d78c..188c334 100644 --- a/include/gfx/gfx.h +++ b/include/gfx/gfx.h @@ -144,6 +144,7 @@ void gfx_copy_stretch(struct texture *dst, int dx, int dy, int dw, int dh, struc void gfx_copy_stretch_amap(struct texture *dst, int dx, int dy, int dw, int dh, struct texture *src, int sx, int sy, int sw, int sh); void gfx_copy_stretch_blend(struct texture *dst, int dx, int dy, int dw, int dh, struct texture *src, int sx, int sy, int sw, int sh, int a); void gfx_copy_stretch_blend_amap(struct texture *dst, int dx, int dy, int dw, int dh, struct texture *src, int sx, int sy, int sw, int sh); +void gfx_copy_stretch_blend_amap_alpha(struct texture *dst, int dx, int dy, int dw, int dh, struct texture *src, int sx, int sy, int sw, int sh, int a); void gfx_copy_rot_zoom(Texture *dst, Texture *src, int sx, int sy, int w, int h, float rotate, float mag); void gfx_copy_rot_zoom_amap(Texture *dst, Texture *src, int sx, int sy, int w, int h, float rotate, float mag); void gfx_copy_rot_zoom_use_amap(Texture *dst, Texture *src, int sx, int sy, int w, int h, float rotate, float mag); diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index 20e8ab0..9cfa999 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -74,10 +74,15 @@ struct motion { float loop_frame_begin, loop_frame_end; }; +// Attribute variable locations enum RE_attribute_location { - ATTR_VERTEX_POS = 0, - ATTR_BONE_INDEX, - ATTR_BONE_WEIGHT, + VATTR_POS = 0, + VATTR_NORMAL, + VATTR_UV, + VATTR_BONE_INDEX, + VATTR_BONE_WEIGHT, + VATTR_LIGHT_UV, + VATTR_TANGENT, }; struct shadow_renderer { @@ -139,12 +144,6 @@ struct RE_renderer { GLint ls_light_color; GLint ls_sun_color; - // Attribute variable locations - GLint vertex_normal; - GLint vertex_uv; - GLint vertex_light_uv; - GLint vertex_tangent; - GLuint billboard_vao; GLuint billboard_attr_buffer; struct hash_table *billboard_textures; // cg_no -> struct billboard_texture* @@ -160,7 +159,7 @@ void RE_instance_update_local_transform(struct RE_instance *inst); // model.c -struct model *model_load(struct archive *aar, const char *path, struct RE_renderer *renderer); +struct model *model_load(struct archive *aar, const char *path); void model_free(struct model *model); struct motion *motion_load(const char *name, struct RE_instance *instance, struct archive *aar); diff --git a/src/3d/model.c b/src/3d/model.c index 8bfd78d..9b922b2 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -196,7 +196,7 @@ static void *buf_alloc(uint8_t **ptr, int size) return p; } -static void add_mesh(struct model *model, struct pol_mesh *m, int material_index, int material, struct RE_renderer *r) +static void add_mesh(struct model *model, struct pol_mesh *m, int material_index, int material) { bool has_light_map = m->light_uvs && model->materials[material].light_map; bool has_normal_map = model->materials[material].normal_map != 0; @@ -271,40 +271,40 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index glBindBuffer(GL_ARRAY_BUFFER, mesh->attr_buffer); const uint8_t *base = (const uint8_t *)0; - glEnableVertexAttribArray(ATTR_VERTEX_POS); - glVertexAttribPointer(ATTR_VERTEX_POS, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, pos)); - glEnableVertexAttribArray(r->vertex_normal); - glVertexAttribPointer(r->vertex_normal, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, normal)); - glEnableVertexAttribArray(r->vertex_uv); - glVertexAttribPointer(r->vertex_uv, 2, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, uv)); + glEnableVertexAttribArray(VATTR_POS); + glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, pos)); + glEnableVertexAttribArray(VATTR_NORMAL); + glVertexAttribPointer(VATTR_NORMAL, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, normal)); + glEnableVertexAttribArray(VATTR_UV); + glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_common, uv)); base += sizeof(struct vertex_common); if (has_light_map) { - glEnableVertexAttribArray(r->vertex_light_uv); - glVertexAttribPointer(r->vertex_light_uv, 2, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_light_uv, uv)); + glEnableVertexAttribArray(VATTR_LIGHT_UV); + glVertexAttribPointer(VATTR_LIGHT_UV, 2, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_light_uv, uv)); base += sizeof(struct vertex_light_uv); } else { - glDisableVertexAttribArray(r->vertex_light_uv); - glVertexAttrib2f(r->vertex_light_uv, 0.0, 0.0); + glDisableVertexAttribArray(VATTR_LIGHT_UV); + glVertexAttrib2f(VATTR_LIGHT_UV, 0.0, 0.0); } if (has_normal_map) { - glEnableVertexAttribArray(r->vertex_tangent); - glVertexAttribPointer(r->vertex_tangent, 4, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_tangent, tangent)); + glEnableVertexAttribArray(VATTR_TANGENT); + glVertexAttribPointer(VATTR_TANGENT, 4, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_tangent, tangent)); base += sizeof(struct vertex_tangent); } else { - glDisableVertexAttribArray(r->vertex_tangent); - glVertexAttrib3f(r->vertex_tangent, 1.0, 0.0, 0.0); + glDisableVertexAttribArray(VATTR_TANGENT); + glVertexAttrib3f(VATTR_TANGENT, 1.0, 0.0, 0.0); } if (has_bones) { - glEnableVertexAttribArray(ATTR_BONE_INDEX); - glVertexAttribIPointer(ATTR_BONE_INDEX, NR_WEIGHTS, GL_INT, stride, base + offsetof(struct vertex_bones, bone_id)); - glEnableVertexAttribArray(ATTR_BONE_WEIGHT); - glVertexAttribPointer(ATTR_BONE_WEIGHT, NR_WEIGHTS, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_bones, bone_weight)); + glEnableVertexAttribArray(VATTR_BONE_INDEX); + glVertexAttribIPointer(VATTR_BONE_INDEX, NR_WEIGHTS, GL_INT, stride, base + offsetof(struct vertex_bones, bone_id)); + glEnableVertexAttribArray(VATTR_BONE_WEIGHT); + glVertexAttribPointer(VATTR_BONE_WEIGHT, NR_WEIGHTS, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_bones, bone_weight)); base += sizeof(struct vertex_bones); } else { - glDisableVertexAttribArray(ATTR_BONE_INDEX); - glVertexAttribI4i(ATTR_BONE_INDEX, 0, 0, 0, 0); - glDisableVertexAttribArray(ATTR_BONE_WEIGHT); - glVertexAttrib4f(ATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0); + glDisableVertexAttribArray(VATTR_BONE_INDEX); + glVertexAttribI4i(VATTR_BONE_INDEX, 0, 0, 0, 0); + glDisableVertexAttribArray(VATTR_BONE_WEIGHT); + glVertexAttrib4f(VATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0); } assert((intptr_t)base == stride); @@ -355,7 +355,7 @@ static void destroy_bone(struct bone *bone) free(bone->name); } -struct model *model_load(struct archive *aar, const char *path, struct RE_renderer *r) +struct model *model_load(struct archive *aar, const char *path) { const char *basename = strrchr(path, '\\'); basename = basename ? basename + 1 : path; @@ -429,11 +429,11 @@ struct model *model_load(struct archive *aar, const char *path, struct RE_render struct pol_material_group *mg = &pol->materials[pol->meshes[i]->material]; int m_off = material_offsets[pol->meshes[i]->material]; if (mg->nr_children == 0) { - add_mesh(model, pol->meshes[i], -1, m_off, r); + add_mesh(model, pol->meshes[i], -1, m_off); continue; } for (uint32_t j = 0; j < mg->nr_children; j++) { - add_mesh(model, pol->meshes[i], j, m_off + j, r); + add_mesh(model, pol->meshes[i], j, m_off + j); } } diff --git a/src/3d/reign.c b/src/3d/reign.c index 948bd46..30eae28 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -245,7 +245,15 @@ bool RE_set_projection(struct RE_plugin *plugin, float width, float height, floa { if (!plugin) return false; - glm_perspective(glm_rad(deg), width / height, near, far, plugin->proj_transform); + + float aspect = width / height; + glm_perspective(glm_rad(deg), aspect, near, far, plugin->proj_transform); + + // Adjust the X and Y scaling factor, because ReignEngine calculates the + // projection matrix based on the horizontal FOV while glm_perspective takes + // the vertical FOV. + plugin->proj_transform[0][0] *= aspect; + plugin->proj_transform[1][1] *= aspect; return true; } @@ -315,7 +323,7 @@ bool RE_instance_load(struct RE_instance *instance, const char *name) switch (instance->type) { case RE_ITYPE_STATIC: case RE_ITYPE_SKINNED: - instance->model = model_load(instance->plugin->aar, name, instance->plugin->renderer); + instance->model = model_load(instance->plugin->aar, name); if (instance->model && instance->model->nr_bones > 0) instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat4)); return !!instance->model; @@ -880,6 +888,9 @@ bool RE_back_cg_set(struct RE_back_cg *bcg, int no) bcg->no = no; gfx_delete_texture(&bcg->texture); + if (!no) // unload only. + return true; + struct cg *cg = asset_cg_load(no); if (!cg) { WARNING("cannot load back CG: %d", no); diff --git a/src/3d/renderer.c b/src/3d/renderer.c index 7817f44..2d668a0 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -46,11 +46,15 @@ static GLuint load_shader(const char *vertex_shader_path, const char *fragment_s glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); - // Bind some attributes to fixed locations, so that common VAO can be used + // Bind vertex attributes to fixed locations, so that common VAO can be used // by multiple programs. - glBindAttribLocation(program, ATTR_VERTEX_POS, "vertex_pos"); - glBindAttribLocation(program, ATTR_BONE_INDEX, "vertex_bone_index"); - glBindAttribLocation(program, ATTR_BONE_WEIGHT, "vertex_bone_weight"); + glBindAttribLocation(program, VATTR_POS, "vertex_pos"); + glBindAttribLocation(program, VATTR_NORMAL, "vertex_normal"); + glBindAttribLocation(program, VATTR_UV, "vertex_uv"); + glBindAttribLocation(program, VATTR_BONE_INDEX, "vertex_bone_index"); + glBindAttribLocation(program, VATTR_BONE_WEIGHT, "vertex_bone_weight"); + glBindAttribLocation(program, VATTR_LIGHT_UV, "vertex_light_uv"); + glBindAttribLocation(program, VATTR_TANGENT, "vertex_tangent"); glLinkProgram(program); @@ -114,20 +118,20 @@ static void init_billboard_mesh(struct RE_renderer *r) glGenBuffers(1, &r->billboard_attr_buffer); glBindBuffer(GL_ARRAY_BUFFER, r->billboard_attr_buffer); - glEnableVertexAttribArray(ATTR_VERTEX_POS); - glVertexAttribPointer(ATTR_VERTEX_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0); - glEnableVertexAttribArray(r->vertex_uv); - glVertexAttribPointer(r->vertex_uv, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12); - glDisableVertexAttribArray(r->vertex_light_uv); - glVertexAttrib2f(r->vertex_light_uv, 0.0, 0.0); - glDisableVertexAttribArray(r->vertex_normal); - glVertexAttrib3f(r->vertex_normal, 0.0, 0.0, 1.0); - glDisableVertexAttribArray(r->vertex_tangent); - glVertexAttrib3f(r->vertex_tangent, 1.0, 0.0, 0.0); - glDisableVertexAttribArray(ATTR_BONE_INDEX); - glVertexAttribI4i(ATTR_BONE_INDEX, 0, 0, 0, 0); - glDisableVertexAttribArray(ATTR_BONE_WEIGHT); - glVertexAttrib4f(ATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0); + glEnableVertexAttribArray(VATTR_POS); + glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, 20, (const void *)0); + glEnableVertexAttribArray(VATTR_UV); + glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, 20, (const void *)12); + glDisableVertexAttribArray(VATTR_LIGHT_UV); + glVertexAttrib2f(VATTR_LIGHT_UV, 0.0, 0.0); + glDisableVertexAttribArray(VATTR_NORMAL); + glVertexAttrib3f(VATTR_NORMAL, 0.0, 0.0, 1.0); + glDisableVertexAttribArray(VATTR_TANGENT); + glVertexAttrib3f(VATTR_TANGENT, 1.0, 0.0, 0.0); + glDisableVertexAttribArray(VATTR_BONE_INDEX); + glVertexAttribI4i(VATTR_BONE_INDEX, 0, 0, 0, 0); + glDisableVertexAttribArray(VATTR_BONE_WEIGHT); + glVertexAttrib4f(VATTR_BONE_WEIGHT, 0.0, 0.0, 0.0, 0.0); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); @@ -189,10 +193,6 @@ struct RE_renderer *RE_renderer_new(struct texture *texture) r->ls_light_dir = glGetUniformLocation(r->program, "ls_light_dir"); r->ls_light_color = glGetUniformLocation(r->program, "ls_light_color"); r->ls_sun_color = glGetUniformLocation(r->program, "ls_sun_color"); - r->vertex_normal = glGetAttribLocation(r->program, "vertex_normal"); - r->vertex_uv = glGetAttribLocation(r->program, "vertex_uv"); - r->vertex_light_uv = glGetAttribLocation(r->program, "vertex_light_uv"); - r->vertex_tangent = glGetAttribLocation(r->program, "vertex_tangent"); glGenRenderbuffers(1, &r->depth_buffer); glBindRenderbuffer(GL_RENDERBUFFER, r->depth_buffer); @@ -411,7 +411,7 @@ static bool calc_shadow_light_transform(struct RE_plugin *plugin, mat4 dest) glm_aabb_invalidate(aabb); for (int i = 0; i < plugin->nr_instances; i++) { struct RE_instance *inst = plugin->instances[i]; - if (!inst || !inst->make_shadow || !inst->model) + if (!inst || !inst->draw || !inst->make_shadow || !inst->model) continue; // Start with the model's AABB, inflated with shadow_volume_bone_radius. vec3 inst_aabb[2]; @@ -480,7 +480,7 @@ static void render_shadow_map(struct RE_plugin *plugin, mat4 light_space_transfo // Render the shadow casters. for (int i = 0; i < plugin->nr_instances; i++) { struct RE_instance *inst = plugin->instances[i]; - if (!inst || !inst->make_shadow || !inst->model) + if (!inst || !inst->draw || !inst->make_shadow || !inst->model) continue; struct model *model = inst->model; if (model->nr_bones > 0) { @@ -505,11 +505,11 @@ static void render_shadow_map(struct RE_plugin *plugin, mat4 light_space_transfo static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct RE_renderer *r) { - if (!bcg->texture.handle) + if (!bcg->show || !bcg->texture.handle) return; int sw = bcg->texture.w; int sh = bcg->texture.h; - gfx_copy_stretch_blend(dst, bcg->x, bcg->y, sw * bcg->mag, sh * bcg->mag, &bcg->texture, 0, 0, sw, sh, bcg->blend_rate * 255); + gfx_copy_stretch_blend_amap_alpha(dst, bcg->x, bcg->y, sw * bcg->mag, sh * bcg->mag, &bcg->texture, 0, 0, sw, sh, bcg->blend_rate * 255); } static void setup_lights(struct RE_plugin *plugin) diff --git a/src/draw.c b/src/draw.c index 0afbb18..98ba36a 100644 --- a/src/draw.c +++ b/src/draw.c @@ -712,6 +712,20 @@ void gfx_copy_stretch_blend_amap(struct texture *dst, int dx, int dy, int dw, in restore_blend_mode(); } +void gfx_copy_stretch_blend_amap_alpha(struct texture *dst, int dx, int dy, int dw, int dh, struct texture *src, int sx, int sy, int sw, int sh, int a) +{ + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + struct copy_data data = STRETCH_DATA(dx, dy, dw, dh, sx, sy, sw, sh); + data.r = 1.0; + data.g = 1.0; + data.b = 1.0; + data.a = a / 255.0; + run_copy_shader(&blend_amap_alpha_bright_shader.s, dst, src, &data); + + restore_blend_mode(); +} + // FIXME: this doesn't work correctly when the src rectangle crosses the edge of the CG. static void copy_rot_zoom(Texture *dst, Texture *src, int sx, int sy, int w, int h, float rotate, float mag, Shader *shader) {