From fe02c8f4019d00c095a65cbad316f02dc199a428 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 10 Jul 2022 13:20:50 +0900 Subject: [PATCH 1/2] ReignEngine: Implement rim lighting Lighting parameters are per-material and are stored in the .amt file. --- shaders/reign.f.glsl | 9 ++++++++- src/3d/3d_internal.h | 9 +++++++++ src/3d/model.c | 6 ++++++ src/3d/renderer.c | 5 +++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index bafb563..c6275a6 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -30,6 +30,8 @@ uniform dir_light dir_lights[NR_DIR_LIGHTS]; uniform vec3 specular_light_dir; uniform float specular_strength; uniform float specular_shininess; +uniform float rim_exponent; +uniform vec3 rim_color; uniform vec3 view_pos; in vec2 tex_coord; @@ -39,6 +41,7 @@ out vec4 frag_color; void main() { vec3 norm = normalize(normal); + vec3 view_dir = normalize(view_pos - frag_pos); vec3 frag_rgb = ambient; // Diffuse lighting @@ -52,11 +55,15 @@ void main() { // Specular lighting if (specular_strength > 0.0) { - vec3 view_dir = normalize(view_pos - frag_pos); vec3 reflect_dir = reflect(specular_light_dir, norm); float specular = pow(max(dot(view_dir, reflect_dir), 0.0), specular_shininess) * specular_strength; frag_rgb += vec3(specular); } + // Rim lighting + if (rim_exponent > 0) { + frag_rgb += pow(1.0 - max(dot(norm, view_dir), 0.0), rim_exponent) * rim_color; + } + frag_color = vec4(frag_rgb, texel.a * alpha_mod); } diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index 5292d31..db1b22a 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -50,6 +50,8 @@ struct material { bool opaque; float specular_strength; float specular_shininess; + float rim_exponent; + vec3 rim_color; }; struct bone { @@ -90,6 +92,8 @@ struct RE_renderer { GLint specular_light_dir; GLint specular_strength; GLint specular_shininess; + GLint rim_exponent; + GLint rim_color; GLint view_pos; // Attribute variable locations @@ -220,6 +224,11 @@ struct amt_material { enum amt_field_index { AMT_SPECULAR_STRENGTH = 0, AMT_SPECULAR_SHININESS = 2, + // amt v5+ + AMT_RIM_EXPONENT = 7, + AMT_RIM_R = 8, + AMT_RIM_G = 9, + AMT_RIM_B = 10, }; struct pol *pol_parse(uint8_t *data, size_t size); diff --git a/src/3d/model.c b/src/3d/model.c index f8df832..c03ed4d 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -80,6 +80,12 @@ static bool init_material(struct material *material, const struct pol_material * if (amt_m) { material->specular_strength = amt_m->fields[AMT_SPECULAR_STRENGTH]; material->specular_shininess = amt_m->fields[AMT_SPECULAR_SHININESS]; + if (amt->version >= 5) { + material->rim_exponent = amt_m->fields[AMT_RIM_EXPONENT]; + material->rim_color[0] = amt_m->fields[AMT_RIM_R]; + material->rim_color[1] = amt_m->fields[AMT_RIM_G]; + material->rim_color[2] = amt_m->fields[AMT_RIM_B]; + } } return true; diff --git a/src/3d/renderer.c b/src/3d/renderer.c index e8e3d21..d577edd 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -82,6 +82,8 @@ struct RE_renderer *RE_renderer_new(struct texture *texture) r->specular_light_dir = glGetUniformLocation(r->shader.program, "specular_light_dir"); r->specular_strength = glGetUniformLocation(r->shader.program, "specular_strength"); r->specular_shininess = glGetUniformLocation(r->shader.program, "specular_shininess"); + 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->vertex_normal = glGetAttribLocation(r->shader.program, "vertex_normal"); r->vertex_uv = glGetAttribLocation(r->shader.program, "vertex_uv"); @@ -273,6 +275,8 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r) glUniform1f(r->specular_strength, 0.0); glUniform1f(r->specular_shininess, 0.0); } + glUniform1f(r->rim_exponent, material->rim_exponent); + glUniform3fv(r->rim_color, 1, material->rim_color); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, material->color_map); @@ -336,6 +340,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma glUniform1f(r->alpha_mod, inst->alpha); glUniform1f(r->specular_strength, 0.0); glUniform1f(r->specular_shininess, 0.0); + glUniform1f(r->rim_exponent, 0.0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, bt->texture); From 80c6b6207425db60a8f8eb699c0a278ae4cbea11 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Sun, 10 Jul 2022 13:33:50 +0900 Subject: [PATCH 2/2] ReignEngine: Implement specular map --- shaders/reign.f.glsl | 5 +++++ src/3d/3d_internal.h | 5 ++++- src/3d/model.c | 38 ++++++++++++++++++++++++++------------ src/3d/renderer.c | 21 +++++++++++++++++++-- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/shaders/reign.f.glsl b/shaders/reign.f.glsl index c6275a6..791f79b 100644 --- a/shaders/reign.f.glsl +++ b/shaders/reign.f.glsl @@ -23,6 +23,7 @@ struct dir_light { }; uniform sampler2D tex; +uniform sampler2D specular_texture; uniform float alpha_mod; uniform vec3 ambient; @@ -30,6 +31,7 @@ uniform dir_light dir_lights[NR_DIR_LIGHTS]; uniform vec3 specular_light_dir; uniform float specular_strength; uniform float specular_shininess; +uniform bool use_specular_map; uniform float rim_exponent; uniform vec3 rim_color; uniform vec3 view_pos; @@ -57,6 +59,9 @@ void main() { if (specular_strength > 0.0) { vec3 reflect_dir = reflect(specular_light_dir, norm); float specular = pow(max(dot(view_dir, reflect_dir), 0.0), specular_shininess) * specular_strength; + if (use_specular_map) { + specular *= texture(specular_texture, tex_coord).r; + } frag_rgb += vec3(specular); } diff --git a/src/3d/3d_internal.h b/src/3d/3d_internal.h index db1b22a..9877710 100644 --- a/src/3d/3d_internal.h +++ b/src/3d/3d_internal.h @@ -47,7 +47,7 @@ struct mesh { struct material { GLuint color_map; - bool opaque; + GLuint specular_map; float specular_strength; float specular_shininess; float rim_exponent; @@ -92,6 +92,8 @@ struct RE_renderer { GLint specular_light_dir; GLint specular_strength; GLint specular_shininess; + GLint use_specular_map; + GLint specular_texture; GLint rim_exponent; GLint rim_color; GLint view_pos; @@ -141,6 +143,7 @@ struct pol { enum pol_texture_type { COLOR_MAP = 1, + SPECULAR_MAP = 4, MAX_TEXTURE_TYPE }; diff --git a/src/3d/model.c b/src/3d/model.c index c03ed4d..8e9099f 100644 --- a/src/3d/model.c +++ b/src/3d/model.c @@ -45,27 +45,24 @@ static struct archive_data *get_aar_entry(struct archive *aar, const char *dir, return dfile; } -static bool init_material(struct material *material, const struct pol_material *m, struct amt *amt, struct archive *aar, const char *path) +static GLuint load_texture(struct archive *aar, const char *path, const char *name) { - if (!m->textures[COLOR_MAP]) { - WARNING("No color texture"); - return false; - } - struct archive_data *dfile = get_aar_entry(aar, path, m->textures[COLOR_MAP], ""); + struct archive_data *dfile = get_aar_entry(aar, path, name, ""); if (!dfile) { - WARNING("cannot load texture %s\\%s", path, m->textures[COLOR_MAP]); - return false; + WARNING("cannot load texture %s\\%s", path, name); + return 0; } struct cg *cg = cg_load_data(dfile); if (!cg) { WARNING("cg_load_data failed: %s", dfile->name); archive_free_data(dfile); - return false; + return 0; } archive_free_data(dfile); - glGenTextures(1, &material->color_map); - glBindTexture(GL_TEXTURE_2D, material->color_map); + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cg->metrics.w, cg->metrics.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, cg->pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); @@ -73,8 +70,23 @@ static bool init_material(struct material *material, const struct pol_material * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); - material->opaque = !cg->metrics.has_alpha; cg_free(cg); + return texture; +} + +static bool init_material(struct material *material, const struct pol_material *m, struct amt *amt, struct archive *aar, const char *path) +{ + if (!m->textures[COLOR_MAP]) { + WARNING("No color texture"); + return false; + } + material->color_map = load_texture(aar, path, m->textures[COLOR_MAP]); + if (!material->color_map) + return false; + + if (m->textures[SPECULAR_MAP]) { + material->specular_map = load_texture(aar, path, m->textures[SPECULAR_MAP]); + } struct amt_material *amt_m = amt ? amt_find_material(amt, m->name) : NULL; if (amt_m) { @@ -95,6 +107,8 @@ static void destroy_material(struct material *material) { if (material->color_map) glDeleteTextures(1, &material->color_map); + if (material->specular_map) + glDeleteTextures(1, &material->specular_map); } static int cmp_by_bone_weight(const void *lhs, const void *rhs) diff --git a/src/3d/renderer.c b/src/3d/renderer.c index d577edd..653a45b 100644 --- a/src/3d/renderer.c +++ b/src/3d/renderer.c @@ -27,6 +27,11 @@ #include "sact.h" #include "vm.h" +enum { + COLOR_TEXTURE_UNIT, + SPECULAR_TEXTURE_UNIT, +}; + static void init_billboard_mesh(struct RE_renderer *r) { static const GLfloat vertices[] = { @@ -82,6 +87,8 @@ struct RE_renderer *RE_renderer_new(struct texture *texture) r->specular_light_dir = glGetUniformLocation(r->shader.program, "specular_light_dir"); r->specular_strength = glGetUniformLocation(r->shader.program, "specular_strength"); r->specular_shininess = glGetUniformLocation(r->shader.program, "specular_shininess"); + r->use_specular_map = glGetUniformLocation(r->shader.program, "use_specular_map"); + r->specular_texture = glGetUniformLocation(r->shader.program, "specular_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"); @@ -268,19 +275,28 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r) struct mesh *mesh = &model->meshes[i]; struct material *material = &model->materials[mesh->material]; + GLboolean use_specular_map = GL_FALSE; if (inst->plugin->specular_mode) { glUniform1f(r->specular_strength, material->specular_strength); glUniform1f(r->specular_shininess, material->specular_shininess); + if (material->specular_map) { + glActiveTexture(GL_TEXTURE0 + SPECULAR_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, material->specular_map); + glUniform1i(r->specular_texture, SPECULAR_TEXTURE_UNIT); + use_specular_map = GL_TRUE; + } } else { glUniform1f(r->specular_strength, 0.0); glUniform1f(r->specular_shininess, 0.0); } + glUniform1i(r->use_specular_map, use_specular_map); + glUniform1f(r->rim_exponent, material->rim_exponent); glUniform3fv(r->rim_color, 1, material->rim_color); - glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE0 + COLOR_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, material->color_map); - glUniform1i(r->shader.texture, 0); + glUniform1i(r->shader.texture, COLOR_TEXTURE_UNIT); glBindVertexArray(mesh->vao); glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices); @@ -340,6 +356,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma glUniform1f(r->alpha_mod, inst->alpha); glUniform1f(r->specular_strength, 0.0); glUniform1f(r->specular_shininess, 0.0); + glUniform1i(r->use_specular_map, GL_FALSE); glUniform1f(r->rim_exponent, 0.0); glActiveTexture(GL_TEXTURE0);