diff --git a/include/reign.h b/include/reign.h index d630f6c..7b91d40 100644 --- a/include/reign.h +++ b/include/reign.h @@ -191,7 +191,7 @@ struct RE_instance { bool local_transform_needs_update; mat4 local_transform; mat3 normal_transform; - mat4 *bone_transforms; // model->nr_bones elements + mat3x4 *bone_transforms; // row-major, model->nr_bones elements GLuint bone_transforms_ubo; vec4 bounding_sphere; struct RE_instance *shadow_volume_instance; diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index 3583aa3..dd570d9 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -91,7 +91,7 @@ uniform int alpha_mode; in vec2 tex_coord; in vec2 light_tex_coord; -in vec3 color_mod; +in vec4 color_mod; in vec3 frag_pos; in vec4 shadow_frag_pos; in float dist; @@ -125,7 +125,7 @@ void main() { if (diffuse_type == DIFFUSE_LIGHT_MAP) { diffuse *= texture(light_texture, light_tex_coord).rgb; } - frag_rgb += texel.rgb * diffuse * color_mod; + frag_rgb += texel.rgb * diffuse * color_mod.rgb; } } @@ -174,7 +174,7 @@ void main() { } // Alpha mapping - float alpha = texel.a * alpha_mod; + float alpha = texel.a * color_mod.a * alpha_mod; if (alpha_mode == ALPHA_TEST) { if (alpha < 0.8) discard; diff --git a/shaders/reign.v.glsl b/shaders/reign.v.glsl index 5da4478..d10dc03 100644 --- a/shaders/reign.v.glsl +++ b/shaders/reign.v.glsl @@ -39,6 +39,12 @@ out vec3 specular_dir; out vec3 ls_ex; out vec3 ls_in; +const vec2 uv_scroll = vec2(0.0); + +#else // ENGINE == REIGN_ENGINE + +uniform vec2 uv_scroll; + #endif // ENGINE == REIGN_ENGINE uniform mat4 local_transform; @@ -49,8 +55,8 @@ uniform mat3 normal_transform; const int MAX_BONES = 308; // see 3d_internal.h const int NR_WEIGHTS = 4; uniform bool has_bones; -layout(std140) uniform BoneTransforms { - mat4 bone_matrices[MAX_BONES]; +layout(std140, row_major) uniform BoneTransforms { + mat4x3 bone_matrices[MAX_BONES]; }; uniform bool use_normal_map; @@ -62,14 +68,14 @@ in vec3 vertex_pos; in vec3 vertex_normal; in vec2 vertex_uv; in vec2 vertex_light_uv; -in vec3 vertex_color; +in vec4 vertex_color; in vec4 vertex_tangent; in ivec4 vertex_bone_index; in vec4 vertex_bone_weight; out vec2 tex_coord; out vec2 light_tex_coord; -out vec3 color_mod; +out vec4 color_mod; out vec3 frag_pos; out vec4 shadow_frag_pos; out float dist; @@ -80,13 +86,17 @@ void main() { mat4 local_bone_transform = local_transform; mat3 normal_bone_transform = normal_transform; if (has_bones) { - mat4 bone_transform = mat4(0.f); + mat4x3 bone_transform = mat4x3(0.0); for (int i = 0; i < NR_WEIGHTS; i++) { if (vertex_bone_index[i] >= 0) { bone_transform += bone_matrices[vertex_bone_index[i]] * vertex_bone_weight[i]; } } - local_bone_transform *= bone_transform; + local_bone_transform *= mat4( + vec4(bone_transform[0], 0.0), + vec4(bone_transform[1], 0.0), + vec4(bone_transform[2], 0.0), + vec4(bone_transform[3], 1.0)); normal_bone_transform *= mat3(bone_transform); } @@ -104,8 +114,8 @@ void main() { vec4 view_pos = view_transform * world_pos; gl_Position = proj_transform * view_pos; - tex_coord = vertex_uv; - light_tex_coord = vertex_light_uv; + tex_coord = vertex_uv + uv_scroll; + light_tex_coord = vertex_light_uv + uv_scroll; color_mod = vertex_color; dist = -view_pos.z; shadow_frag_pos = shadow_transform * world_pos; diff --git a/shaders/reign_outline.v.glsl b/shaders/reign_outline.v.glsl index ee82afd..493d35c 100644 --- a/shaders/reign_outline.v.glsl +++ b/shaders/reign_outline.v.glsl @@ -22,8 +22,8 @@ uniform mat3 normal_transform; const int MAX_BONES = 308; // see 3d_internal.h const int NR_WEIGHTS = 4; uniform bool has_bones; -layout(std140) uniform BoneTransforms { - mat4 bone_matrices[MAX_BONES]; +layout(std140, row_major) uniform BoneTransforms { + mat4x3 bone_matrices[MAX_BONES]; }; uniform float outline_thickness; @@ -36,13 +36,17 @@ void main() { mat4 local_bone_transform = local_transform; mat3 normal_bone_transform = normal_transform; if (has_bones) { - mat4 bone_transform = mat4(0.f); + mat4x3 bone_transform = mat4x3(0.0); for (int i = 0; i < NR_WEIGHTS; i++) { if (vertex_bone_index[i] >= 0) { bone_transform += bone_matrices[vertex_bone_index[i]] * vertex_bone_weight[i]; } } - local_bone_transform *= bone_transform; + local_bone_transform *= mat4( + vec4(bone_transform[0], 0.0), + vec4(bone_transform[1], 0.0), + vec4(bone_transform[2], 0.0), + vec4(bone_transform[3], 1.0)); normal_bone_transform *= mat3(bone_transform); } diff --git a/shaders/reign_shadow.v.glsl b/shaders/reign_shadow.v.glsl index 9a2729d..3551c4c 100644 --- a/shaders/reign_shadow.v.glsl +++ b/shaders/reign_shadow.v.glsl @@ -20,8 +20,8 @@ uniform mat4 view_transform; const int MAX_BONES = 308; // see 3d_internal.h const int NR_WEIGHTS = 4; uniform bool has_bones; -layout(std140) uniform BoneTransforms { - mat4 bone_matrices[MAX_BONES]; +layout(std140, row_major) uniform BoneTransforms { + mat4x3 bone_matrices[MAX_BONES]; }; in vec3 vertex_pos; @@ -31,13 +31,17 @@ in vec4 vertex_bone_weight; void main() { mat4 local_bone_transform = local_transform; if (has_bones) { - mat4 bone_transform = mat4(0.f); + mat4x3 bone_transform = mat4x3(0.0); for (int i = 0; i < NR_WEIGHTS; i++) { if (vertex_bone_index[i] >= 0) { bone_transform += bone_matrices[vertex_bone_index[i]] * vertex_bone_weight[i]; } } - local_bone_transform *= bone_transform; + local_bone_transform *= mat4( + vec4(bone_transform[0], 0.0), + vec4(bone_transform[1], 0.0), + vec4(bone_transform[2], 0.0), + vec4(bone_transform[3], 1.0)); } gl_Position = view_transform * local_bone_transform * vec4(vertex_pos, 1.0); diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index e10ed91..4aeab24 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -177,6 +177,7 @@ struct RE_renderer { GLint ls_sun_color; GLint alpha_mode; GLint alpha_texture; + GLint uv_scroll; GLuint billboard_vao; GLuint billboard_attr_buffer; @@ -446,6 +447,8 @@ struct pol_mesh { vec2 *light_uvs; uint32_t nr_colors; vec3 *colors; + uint32_t nr_alphas; + float *alphas; uint32_t nr_triangles; struct pol_triangle *triangles; // Parameters in .opr file. @@ -470,6 +473,7 @@ struct pol_triangle { uint32_t uv_index[3]; uint32_t light_uv_index[3]; uint32_t color_index[3]; + uint32_t alpha_index[3]; vec3 normals[3]; uint32_t material_group_index; }; diff --git a/src/3d/model.c b/src/3d/model.c index f698811..0767630 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -42,7 +42,7 @@ struct vertex_light_uv { }; struct vertex_color { - GLfloat color[3]; + GLfloat color[4]; }; struct vertex_tangent { @@ -227,7 +227,7 @@ static void *buf_alloc(uint8_t **ptr, int size) static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_group_index, int material) { bool has_light_map = m->light_uvs && model->materials[material].light_map; - bool has_vertex_colors = m->nr_colors > 0; + bool has_vertex_colors = m->nr_colors > 0 || m->nr_alphas > 0; bool has_normal_map = model->materials[material].normal_map != 0; bool has_bones = !!model->bone_map; @@ -264,7 +264,11 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_ } if (has_vertex_colors) { struct vertex_color *v_color = buf_alloc(&ptr, sizeof(struct vertex_color)); - glm_vec3_copy(m->colors[t->color_index[j]], v_color->color); + if (m->nr_colors > 0) + glm_vec3_copy(m->colors[t->color_index[j]], v_color->color); + else + glm_vec3_one(v_color->color); + v_color->color[3] = m->nr_alphas > 0 ? m->alphas[t->alpha_index[j]] : 1.f; } if (has_normal_map) { struct vertex_tangent *v_tangent = buf_alloc(&ptr, sizeof(struct vertex_tangent)); @@ -329,11 +333,11 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_ } if (has_vertex_colors) { glEnableVertexAttribArray(VATTR_COLOR); - glVertexAttribPointer(VATTR_COLOR, 3, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_color, color)); + glVertexAttribPointer(VATTR_COLOR, 4, GL_FLOAT, GL_FALSE, stride, base + offsetof(struct vertex_color, color)); base += sizeof(struct vertex_color); } else { glDisableVertexAttribArray(VATTR_COLOR); - glVertexAttrib3f(VATTR_COLOR, 1.0, 1.0, 1.0); + glVertexAttrib4f(VATTR_COLOR, 1.0, 1.0, 1.0, 1.0); } if (has_normal_map) { glEnableVertexAttribArray(VATTR_TANGENT); diff --git a/src/3d/parser.c b/src/3d/parser.c index 9bc32a6..4d9a687 100644 --- a/src/3d/parser.c +++ b/src/3d/parser.c @@ -134,7 +134,7 @@ static void destroy_vertex(struct pol_vertex *v) free(v->weights); } -static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, int unknowns_length, const struct pol_material_group *mg) +static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, const struct pol_material_group *mg) { struct pol_triangle *t = &mesh->triangles[triangle_index]; t->vert_index[0] = buffer_read_int32(r); @@ -148,11 +148,15 @@ static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle t->light_uv_index[1] = buffer_read_int32(r) - mesh->nr_uvs; t->light_uv_index[2] = buffer_read_int32(r) - mesh->nr_uvs; } + t->color_index[0] = buffer_read_int32(r); t->color_index[1] = buffer_read_int32(r); t->color_index[2] = buffer_read_int32(r); - - buffer_skip(r, unknowns_length); + if (mesh->alphas) { + t->alpha_index[0] = buffer_read_int32(r); + t->alpha_index[1] = buffer_read_int32(r); + t->alpha_index[2] = buffer_read_int32(r); + } read_direction(r, t->normals[0]); read_direction(r, t->normals[1]); @@ -234,19 +238,20 @@ static struct pol_mesh *parse_mesh(struct buffer *r, const struct pol *pol) } } - int triangle_unknowns_length = 0; if (pol->version >= 2) { - int nr_unknown_bytes = buffer_read_int32(r); - if (nr_unknown_bytes) { - buffer_skip(r, nr_unknown_bytes); - triangle_unknowns_length += 12; + mesh->nr_alphas = buffer_read_int32(r); + if (mesh->nr_alphas > 0) { + mesh->alphas = xcalloc(mesh->nr_alphas, sizeof(float)); + for (uint32_t i = 0; i < mesh->nr_alphas; i++) { + mesh->alphas[i] = buffer_read_u8(r) / 255.f; + } } } mesh->nr_triangles = buffer_read_int32(r); mesh->triangles = xcalloc(mesh->nr_triangles, sizeof(struct pol_triangle)); for (uint32_t i = 0; i < mesh->nr_triangles; i++) { - parse_triangle(r, mesh, i, triangle_unknowns_length, &pol->materials[mesh->material]); + parse_triangle(r, mesh, i, &pol->materials[mesh->material]); } if (pol->version == 1) { @@ -270,6 +275,7 @@ static void free_mesh(struct pol_mesh *mesh) free(mesh->uvs); free(mesh->light_uvs); free(mesh->colors); + free(mesh->alphas); free(mesh->triangles); free(mesh); } diff --git a/src/3d/reign.c b/src/3d/reign.c index 0bfd762..c34cbe7 100644 --- a/src/3d/reign.c +++ b/src/3d/reign.c @@ -178,13 +178,15 @@ static void update_bones(struct RE_instance *inst) } glm_mat4_copy(bone_transform, parent_transforms[i]); - glm_mat4_mul(bone_transform, inst->model->bones[i].inverse_bind_matrix, inst->bone_transforms[i]); - glm_vec3_minv(aabb[0], bone_transform[3], aabb[0]); glm_vec3_maxv(aabb[1], bone_transform[3], aabb[1]); + + glm_mat4_mul(bone_transform, inst->model->bones[i].inverse_bind_matrix, bone_transform); + glm_mat4_transpose(bone_transform); // column major -> row major + glm_mat3x4_copy(bone_transform, inst->bone_transforms[i]); } glBindBuffer(GL_UNIFORM_BUFFER, inst->bone_transforms_ubo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, inst->model->nr_bones * sizeof(mat4), inst->bone_transforms); + glBufferSubData(GL_UNIFORM_BUFFER, 0, inst->model->nr_bones * sizeof(mat3x4), inst->bone_transforms); glBindBuffer(GL_UNIFORM_BUFFER, 0); // Update inst->bounding_sphere. @@ -440,10 +442,10 @@ bool RE_instance_load(struct RE_instance *instance, const char *name) ht_put(instance->plugin->model_cache, name, instance->model); } if (instance->model && instance->model->nr_bones > 0) { - instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat4)); + instance->bone_transforms = xcalloc(instance->model->nr_bones, sizeof(mat3x4)); glGenBuffers(1, &instance->bone_transforms_ubo); glBindBuffer(GL_UNIFORM_BUFFER, instance->bone_transforms_ubo); - glBufferData(GL_UNIFORM_BUFFER, MAX_BONES * sizeof(mat4), NULL, GL_DYNAMIC_DRAW); + glBufferData(GL_UNIFORM_BUFFER, MAX_BONES * sizeof(mat3x4), NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } return !!instance->model; @@ -531,7 +533,10 @@ bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instan if (instance->local_transform_needs_update) RE_instance_update_local_transform(instance); - glm_mat4_mulv3(instance->bone_transforms[bone], offset, 1.0, out); + mat4 bone_transform = GLM_MAT4_IDENTITY_INIT; + glm_mat3x4_copy(instance->bone_transforms[bone], bone_transform); + glm_mat4_transpose(bone_transform); // row major -> column major + glm_mat4_mulv3(bone_transform, offset, 1.0, out); glm_mat4_mulv3(instance->local_transform, out, 1.0, out); return true; } diff --git a/src/3d/renderer.c b/src/3d/renderer.c index b1cd79d..1c09af9 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -181,7 +181,7 @@ static void init_billboard_mesh(struct RE_renderer *r) glDisableVertexAttribArray(VATTR_LIGHT_UV); glVertexAttrib2f(VATTR_LIGHT_UV, 0.0, 0.0); glDisableVertexAttribArray(VATTR_COLOR); - glVertexAttrib3f(VATTR_COLOR, 1.0, 1.0, 1.0); + glVertexAttrib4f(VATTR_COLOR, 1.0, 1.0, 1.0, 1.0); glDisableVertexAttribArray(VATTR_NORMAL); glVertexAttrib3f(VATTR_NORMAL, 0.0, 0.0, 1.0); glDisableVertexAttribArray(VATTR_TANGENT); @@ -254,6 +254,7 @@ struct RE_renderer *RE_renderer_new(enum RE_plugin_version version) r->ls_sun_color = glGetUniformLocation(r->program, "ls_sun_color"); r->alpha_mode = glGetUniformLocation(r->program, "alpha_mode"); r->alpha_texture = glGetUniformLocation(r->program, "alpha_texture"); + r->uv_scroll = glGetUniformLocation(r->program, "uv_scroll"); glGenRenderbuffers(1, &r->depth_buffer); @@ -429,13 +430,22 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d glUniform1i(r->alpha_mode, ALPHA_BLEND); } + vec2 uv_scroll; + glm_vec2_scale(mesh->uv_scroll, r->last_frame_timestamp / 1000.f, uv_scroll); + glUniform2fv(r->uv_scroll, 1, uv_scroll); + glBindVertexArray(mesh->vao); + if (mesh->flags & MESH_BOTH) + glDisable(GL_CULL_FACE); + if (mesh->nr_indices) glDrawElements(GL_TRIANGLES, mesh->nr_indices, GL_UNSIGNED_SHORT, NULL); else glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices); + if (mesh->flags & MESH_BOTH) + glEnable(GL_CULL_FACE); glBindVertexArray(0); glBindTexture(GL_TEXTURE_2D, 0); } @@ -1059,7 +1069,7 @@ struct height_detector *RE_renderer_create_height_detector(struct RE_renderer *r GLuint bone_transforms_ubo; glGenBuffers(1, &bone_transforms_ubo); glBindBuffer(GL_UNIFORM_BUFFER, bone_transforms_ubo); - glBufferData(GL_UNIFORM_BUFFER, MAX_BONES * sizeof(mat4), NULL, GL_STATIC_DRAW); + glBufferData(GL_UNIFORM_BUFFER, MAX_BONES * sizeof(mat3x4), NULL, GL_STATIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, BONE_TRANSFORMS_BINDING, bone_transforms_ubo);