From af7127580cdef95eee885cfd32e1aa998ee56c6d Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sat, 16 Jul 2022 15:22:21 +0900 Subject: [PATCH] ReignEngine: Implement light mapping --- shaders/reign.f.glsl | 6 ++++++ shaders/reign.v.glsl | 3 +++ src/3d/3d_internal.h | 8 ++++++++ src/3d/model.c | 29 +++++++++++++++++++++++++---- src/3d/parser.c | 25 +++++++++++++++++-------- src/3d/renderer.c | 16 ++++++++++++++++ 6 files changed, 75 insertions(+), 12 deletions(-) diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index bb67130..0f67ba9 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -24,6 +24,7 @@ struct dir_light { uniform sampler2D tex; uniform sampler2D specular_texture; +uniform sampler2D light_texture; uniform float alpha_mod; uniform bool use_normal_map; @@ -36,8 +37,10 @@ uniform float specular_shininess; uniform bool use_specular_map; uniform float rim_exponent; uniform vec3 rim_color; +uniform bool use_light_map; in vec2 tex_coord; +in vec2 light_tex_coord; in vec3 frag_pos; in vec3 eye; in vec3 normal; @@ -63,6 +66,9 @@ void main() { float half_lambert = dot(norm, -light_dir[i]) * 0.5 + 0.5; diffuse += mix(dir_lights[i].globe_diffuse, dir_lights[i].diffuse, half_lambert); } + if (use_light_map) { + diffuse *= texture(light_texture, light_tex_coord).rgb; + } vec4 texel = texture(tex, tex_coord); frag_rgb += texel.rgb * diffuse; diff --git a/shaders/reign.v.glsl b/shaders/reign.v.glsl index c402c59..4d16479 100644 --- a/shaders/reign.v.glsl +++ b/shaders/reign.v.glsl @@ -41,11 +41,13 @@ uniform vec3 specular_light_dir; in vec3 vertex_pos; in vec3 vertex_normal; in vec2 vertex_uv; +in vec2 vertex_light_uv; 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 frag_pos; out vec3 eye; out vec3 normal; @@ -82,6 +84,7 @@ void main() { gl_Position = proj_transform * view_transform * world_pos; tex_coord = vertex_uv; + light_tex_coord = vertex_light_uv; // These are in tangent-space if use_normal_map is true, in world-space // otherwise. diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index 16cc869..f06be1f 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -48,6 +48,7 @@ struct mesh { struct material { GLuint color_map; GLuint specular_map; + GLuint light_map; GLuint normal_map; float specular_strength; float specular_shininess; @@ -98,12 +99,15 @@ struct RE_renderer { GLint rim_exponent; GLint rim_color; GLint view_pos; + GLint use_light_map; + GLint light_texture; GLint use_normal_map; GLint normal_texture; // Attribute variable locations GLint vertex_normal; GLint vertex_uv; + GLint vertex_light_uv; GLint vertex_tangent; GLint vertex_bone_index; GLint vertex_bone_weight; @@ -148,6 +152,7 @@ struct pol { enum pol_texture_type { COLOR_MAP = 1, SPECULAR_MAP = 4, + LIGHT_MAP = 7, NORMAL_MAP = 8, MAX_TEXTURE_TYPE }; @@ -170,6 +175,8 @@ struct pol_mesh { struct pol_vertex *vertices; uint32_t nr_uvs; vec2 *uvs; + uint32_t nr_light_uvs; + vec2 *light_uvs; uint32_t nr_triangles; struct pol_triangle *triangles; }; @@ -188,6 +195,7 @@ struct pol_bone_weight { struct pol_triangle { uint32_t vert_index[3]; uint32_t uv_index[3]; + uint32_t light_uv_index[3]; vec3 normals[3]; uint32_t material; // index in the material group }; diff --git a/src/3d/model.c b/src/3d/model.c index f546ae1..4460130 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -35,6 +35,10 @@ struct vertex_common { GLfloat uv[2]; }; +struct vertex_light_uv { + GLfloat uv[2]; +}; + struct vertex_tangent { GLfloat tangent[4]; }; @@ -92,12 +96,12 @@ static bool init_material(struct material *material, const struct pol_material * if (!material->color_map) return false; - if (m->textures[SPECULAR_MAP]) { + if (m->textures[SPECULAR_MAP]) material->specular_map = load_texture(aar, path, m->textures[SPECULAR_MAP]); - } - if (m->textures[NORMAL_MAP]) { + if (m->textures[LIGHT_MAP]) + material->light_map = load_texture(aar, path, m->textures[LIGHT_MAP]); + if (m->textures[NORMAL_MAP]) material->normal_map = load_texture(aar, path, m->textures[NORMAL_MAP]); - } struct amt_material *amt_m = amt ? amt_find_material(amt, m->name) : NULL; if (amt_m) { @@ -120,6 +124,8 @@ static void destroy_material(struct material *material) glDeleteTextures(1, &material->color_map); if (material->specular_map) glDeleteTextures(1, &material->specular_map); + if (material->light_map) + glDeleteTextures(1, &material->light_map); if (material->normal_map) glDeleteTextures(1, &material->normal_map); } @@ -192,10 +198,13 @@ static void *buf_alloc(uint8_t **ptr, int size) static void add_mesh(struct model *model, struct pol_mesh *m, int material_index, int material, struct RE_renderer *r) { + bool has_light_map = m->light_uvs && model->materials[material].light_map; bool has_normal_map = model->materials[material].normal_map != 0; bool has_bones = !!model->bone_map; GLsizei stride = sizeof(struct vertex_common); + if (has_light_map) + stride += sizeof(struct vertex_light_uv); if (has_normal_map) stride += sizeof(struct vertex_tangent); if (has_bones) @@ -218,6 +227,10 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index glm_vec3_copy(vert->pos, v_common->pos); glm_vec3_copy(t->normals[j], v_common->normal); glm_vec2_copy(m->uvs[t->uv_index[j]], v_common->uv); + if (has_light_map) { + struct vertex_light_uv *v_light_uv = buf_alloc(&ptr, sizeof(struct vertex_light_uv)); + glm_vec2_copy(m->light_uvs[t->light_uv_index[j]], v_light_uv->uv); + } if (has_normal_map) { struct vertex_tangent *v_tangent = buf_alloc(&ptr, sizeof(struct vertex_tangent)); glm_vec4_ucopy(tangent[j], v_tangent->tangent); @@ -265,6 +278,14 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index glEnableVertexAttribArray(r->vertex_uv); glVertexAttribPointer(r->vertex_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)); + base += sizeof(struct vertex_light_uv); + } else { + glDisableVertexAttribArray(r->vertex_light_uv); + glVertexAttrib2f(r->vertex_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)); diff --git a/src/3d/parser.c b/src/3d/parser.c index 49e0743..6df07ed 100644 --- a/src/3d/parser.c +++ b/src/3d/parser.c @@ -125,14 +125,20 @@ static void destroy_vertex(struct pol_vertex *v) free(v->weights); } -static void parse_triangle(struct buffer *r, int unknowns_length, struct pol_triangle *t) +static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, int unknowns_length) { + struct pol_triangle *t = &mesh->triangles[triangle_index]; t->vert_index[0] = buffer_read_int32(r); t->vert_index[1] = buffer_read_int32(r); t->vert_index[2] = buffer_read_int32(r); t->uv_index[0] = buffer_read_int32(r); t->uv_index[1] = buffer_read_int32(r); t->uv_index[2] = buffer_read_int32(r); + if (mesh->light_uvs) { + t->light_uv_index[0] = buffer_read_int32(r) - mesh->nr_uvs; + t->light_uv_index[1] = buffer_read_int32(r) - mesh->nr_uvs; + t->light_uv_index[2] = buffer_read_int32(r) - mesh->nr_uvs; + } buffer_skip(r, unknowns_length); @@ -167,14 +173,16 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) mesh->uvs[i][1] = buffer_read_float(r); } - int triangle_unknowns_length = 12; - - int nr_unknown_f64s = buffer_read_int32(r); - if (nr_unknown_f64s) { - buffer_skip(r, nr_unknown_f64s * 8); - triangle_unknowns_length += 12; + mesh->nr_light_uvs = buffer_read_int32(r); + if (mesh->nr_light_uvs > 0) { + mesh->light_uvs = xcalloc(mesh->nr_light_uvs, sizeof(vec2)); + for (uint32_t i = 0; i < mesh->nr_light_uvs; i++) { + mesh->light_uvs[i][0] = buffer_read_float(r); + mesh->light_uvs[i][1] = buffer_read_float(r); + } } + int triangle_unknowns_length = 12; if (pol_version == 1) { int nr_unknown_vecs = buffer_read_int32(r); buffer_skip(r, nr_unknown_vecs * 12); @@ -191,7 +199,7 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version) 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, triangle_unknowns_length, &mesh->triangles[i]); + parse_triangle(r, mesh, i, triangle_unknowns_length); } if (pol_version == 1) { @@ -213,6 +221,7 @@ static void free_mesh(struct pol_mesh *mesh) destroy_vertex(&mesh->vertices[i]); free(mesh->vertices); free(mesh->uvs); + free(mesh->light_uvs); free(mesh->triangles); free(mesh); } diff --git a/src/3d/renderer.c b/src/3d/renderer.c index eafd855..b630197 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -30,6 +30,7 @@ enum { COLOR_TEXTURE_UNIT, SPECULAR_TEXTURE_UNIT, + LIGHT_TEXTURE_UNIT, NORMAL_TEXTURE_UNIT, }; @@ -51,6 +52,8 @@ static void init_billboard_mesh(struct RE_renderer *r) glVertexAttribPointer(r->shader.vertex, 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); @@ -95,10 +98,13 @@ struct RE_renderer *RE_renderer_new(struct texture *texture) r->rim_exponent = glGetUniformLocation(r->shader.program, "rim_exponent"); r->rim_color = glGetUniformLocation(r->shader.program, "rim_color"); r->view_pos = glGetUniformLocation(r->shader.program, "view_pos"); + r->use_light_map = glGetUniformLocation(r->shader.program, "use_light_map"); + r->light_texture = glGetUniformLocation(r->shader.program, "light_texture"); r->use_normal_map = glGetUniformLocation(r->shader.program, "use_normal_map"); r->normal_texture = glGetUniformLocation(r->shader.program, "normal_texture"); r->vertex_normal = glGetAttribLocation(r->shader.program, "vertex_normal"); r->vertex_uv = glGetAttribLocation(r->shader.program, "vertex_uv"); + r->vertex_light_uv = glGetAttribLocation(r->shader.program, "vertex_light_uv"); r->vertex_tangent = glGetAttribLocation(r->shader.program, "vertex_tangent"); r->vertex_bone_index = glGetAttribLocation(r->shader.program, "vertex_bone_index"); r->vertex_bone_weight = glGetAttribLocation(r->shader.program, "vertex_bone_weight"); @@ -304,6 +310,15 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r) glBindTexture(GL_TEXTURE_2D, material->color_map); glUniform1i(r->shader.texture, COLOR_TEXTURE_UNIT); + if (material->light_map && inst->plugin->light_map_mode) { + glUniform1i(r->use_light_map, GL_TRUE); + glActiveTexture(GL_TEXTURE0 + LIGHT_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, material->light_map); + glUniform1i(r->light_texture, LIGHT_TEXTURE_UNIT); + } else { + glUniform1i(r->use_light_map, GL_FALSE); + } + if (material->normal_map && inst->draw_bump && inst->plugin->bump_mode) { glUniform1i(r->use_normal_map, GL_TRUE); glActiveTexture(GL_TEXTURE0 + NORMAL_TEXTURE_UNIT); @@ -373,6 +388,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma glUniform1f(r->specular_shininess, 0.0); glUniform1i(r->use_specular_map, GL_FALSE); glUniform1f(r->rim_exponent, 0.0); + glUniform1i(r->use_light_map, GL_FALSE); glUniform1i(r->use_normal_map, GL_FALSE); glActiveTexture(GL_TEXTURE0);