Merge pull request #90 from kichikuou/reign

ReignEngine improvements
This commit is contained in:
Nunuhara Cabbage
2022-12-27 10:11:27 -08:00
committed by GitHub
8 changed files with 233 additions and 78 deletions
+3
View File
@@ -165,6 +165,8 @@ struct RE_instance {
mat4 local_transform;
mat3 normal_transform;
mat4 *bone_transforms; // model->nr_bones elements
vec4 bounding_sphere;
struct RE_instance *shadow_volume_instance;
float z_from_camera;
};
@@ -186,6 +188,7 @@ bool RE_instance_set_vertex_pos(struct RE_instance *instance, int index, float x
int RE_instance_get_bone_index(struct RE_instance *instance, const char *name);
bool RE_instance_trans_local_pos_to_world_pos_by_bone(struct RE_instance *instance, int bone, vec3 offset, vec3 out);
float RE_instance_calc_height(struct RE_instance *instance, float x, float z);
bool RE_instance_set_debug_draw_shadow_volume(struct RE_instance *instance, bool draw);
int RE_motion_get_state(struct motion *motion);
bool RE_motion_set_state(struct motion *motion, int state);
+6 -6
View File
@@ -52,7 +52,7 @@ uniform bool use_specular_map;
uniform float rim_exponent;
uniform vec3 rim_color;
uniform int diffuse_type;
uniform bool use_shadow_map;
uniform float shadow_darkness;
uniform float shadow_bias;
uniform int fog_type;
uniform float fog_near;
@@ -133,26 +133,26 @@ void main() {
}
// Shadow mapping
if (use_shadow_map) {
if (shadow_darkness > 0.0) {
vec3 shadow_coords = shadow_frag_pos.xyz / shadow_frag_pos.w * 0.5 + 0.5;
shadow_coords.z = min(1.0, shadow_coords.z - shadow_bias);
// PCF with 9 samples.
float shadow_factor = 1.0;
float brightness = 1.0;
vec2 texel_size = 1.0 / vec2(textureSize(shadow_texture, 0));
for (int x = -1; x <= 1; ++x) {
for (int y = -1; y <= 1; ++y) {
float depth = texture(shadow_texture, shadow_coords.xy + vec2(x, y) * texel_size).r;
if (depth < shadow_coords.z)
shadow_factor -= 0.05;
brightness -= 0.05 * shadow_darkness;
}
}
frag_rgb *= shadow_factor;
frag_rgb *= brightness;
}
// Alpha mapping
float alpha = texel.a * alpha_mod;
if (alpha_mode == ALPHA_TEST) {
if (alpha < 1.0)
if (alpha < 0.8)
discard;
} else if (alpha_mode == ALPHA_MAP_BLEND) {
alpha *= texture(alpha_texture, tex_coord).r;
+9 -2
View File
@@ -51,7 +51,9 @@ struct mesh {
uint32_t flags;
GLuint vao;
GLuint attr_buffer;
GLuint index_buffer;
int nr_vertices;
int nr_indices;
int material;
};
@@ -65,6 +67,7 @@ struct material {
GLuint normal_map;
float specular_strength;
float specular_shininess;
float shadow_darkness;
float rim_exponent;
vec3 rim_color;
};
@@ -143,7 +146,7 @@ struct RE_renderer {
GLint light_texture;
GLint use_normal_map;
GLint normal_texture;
GLint use_shadow_map;
GLint shadow_darkness;
GLint shadow_transform;
GLint shadow_texture;
GLint shadow_bias;
@@ -176,6 +179,7 @@ void RE_instance_update_local_transform(struct RE_instance *inst);
struct model *model_load(struct archive *aar, const char *path);
void model_free(struct model *model);
struct model *model_create_sphere(int r, int g, int b, int a);
struct motion *motion_load(const char *name, struct RE_instance *instance, struct archive *aar);
void motion_free(struct motion *motion);
@@ -393,6 +397,7 @@ enum mesh_flags {
MESH_NOMAKESHADOW = 1 << 1,
MESH_ENVMAP = 1 << 2,
MESH_BOTH = 1 << 3,
MESH_SPRITE = 1 << 4,
};
struct pol_mesh {
@@ -425,7 +430,7 @@ struct pol_triangle {
uint32_t uv_index[3];
uint32_t light_uv_index[3];
vec3 normals[3];
uint32_t material; // index in the material group
uint32_t material_group_index;
};
struct pol_bone {
@@ -468,6 +473,8 @@ struct amt_material {
enum amt_field_index {
AMT_SPECULAR_STRENGTH = 0,
AMT_SPECULAR_SHININESS = 2,
// amt v4+
AMT_SHADOW_DARKNESS = 6,
// amt v5+
AMT_RIM_EXPONENT = 7,
AMT_RIM_R = 8,
+104 -4
View File
@@ -110,12 +110,15 @@ static bool init_material(struct material *material, const struct pol_material *
if (m->textures[NORMAL_MAP])
material->normal_map = load_texture(aar, path, m->textures[NORMAL_MAP], NULL);
material->is_transparent = has_alpha || material->alpha_map;
material->is_transparent = (has_alpha || material->alpha_map) && !(material->flags & MATERIAL_SPRITE);
material->shadow_darkness = 1.0f;
struct amt_material *amt_m = amt ? amt_find_material(amt, m->name) : NULL;
if (amt_m) {
material->specular_strength = amt_m->fields[AMT_SPECULAR_STRENGTH];
material->specular_shininess = amt_m->fields[AMT_SPECULAR_SHININESS];
if (amt->version >= 4)
material->shadow_darkness = amt_m->fields[AMT_SHADOW_DARKNESS];
if (amt->version >= 5) {
material->rim_exponent = amt_m->fields[AMT_RIM_EXPONENT];
material->rim_color[0] = amt_m->fields[AMT_RIM_R];
@@ -211,7 +214,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)
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_normal_map = model->materials[material].normal_map != 0;
@@ -231,7 +234,7 @@ static void add_mesh(struct model *model, struct pol_mesh *m, int material_index
int nr_vertices = 0;
for (uint32_t i = 0; i < m->nr_triangles; i++) {
struct pol_triangle *t = &m->triangles[i];
if (material_index >= 0 && t->material != (uint32_t)material_index)
if (t->material_group_index != material_group_index)
continue;
vec4 tangent[3];
if (has_normal_map)
@@ -336,6 +339,8 @@ static void destroy_mesh(struct mesh *mesh)
{
glDeleteVertexArrays(1, &mesh->vao);
glDeleteBuffers(1, &mesh->attr_buffer);
if (mesh->index_buffer)
glDeleteBuffers(1, &mesh->index_buffer);
}
static struct bone *add_bone(struct model *model, struct pol *pol, struct pol_bone *pol_bone)
@@ -460,7 +465,7 @@ struct model *model_load(struct archive *aar, const char *path)
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);
add_mesh(model, pol->meshes[i], 0, m_off);
continue;
}
for (uint32_t j = 0; j < mg->nr_children; j++) {
@@ -499,6 +504,101 @@ void model_free(struct model *model)
free(model);
}
static void init_sphere_mesh(struct mesh *mesh)
{
const int w_segments = 16;
const int h_segments = 16;
const int nr_vertices = (w_segments + 1) * (h_segments + 1);
struct vertex_common *vertices = xcalloc(nr_vertices, sizeof(struct vertex_common));
struct vertex_common *v = vertices;
for (int y = 0; y <= h_segments; y++) {
float theta = GLM_PIf * y / h_segments;
for (int x = 0; x <= w_segments; x++, v++) {
float phi = 2.0f * GLM_PIf * x / w_segments;
v->pos[0] = -cosf(phi) * sinf(theta);
v->pos[1] = cosf(theta);
v->pos[2] = sinf(phi) * sinf(theta);
glm_vec3_copy(v->pos, v->normal);
v->uv[0] = v->uv[1] = 0.0f;
}
}
assert(v == vertices + nr_vertices);
const int nr_indices = 3 * 2 * w_segments * (h_segments - 1);
GLushort *indices = xcalloc(nr_indices, sizeof(GLushort));
GLushort *pi = indices;
for (int y = 0; y < h_segments; y++) {
for (int x = 0; x < w_segments; x++) {
GLushort a = y * w_segments + x + 1;
GLushort b = y * w_segments + x;
GLushort c = (y + 1) * w_segments + x;
GLushort d = (y + 1) * w_segments + x + 1;
if (y > 0) {
*pi++ = a;
*pi++ = b;
*pi++ = d;
}
if (y < h_segments - 1) {
*pi++ = b;
*pi++ = c;
*pi++ = d;
}
}
}
assert(pi == indices + nr_indices);
mesh->flags = MESH_NOLIGHTING;
mesh->nr_vertices = nr_vertices;
mesh->nr_indices = nr_indices;
glGenVertexArrays(1, &mesh->vao);
glBindVertexArray(mesh->vao);
glGenBuffers(1, &mesh->attr_buffer);
glBindBuffer(GL_ARRAY_BUFFER, mesh->attr_buffer);
glBufferData(GL_ARRAY_BUFFER, nr_vertices * sizeof(struct vertex_common), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(VATTR_POS);
glVertexAttribPointer(VATTR_POS, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, pos));
glEnableVertexAttribArray(VATTR_NORMAL);
glVertexAttribPointer(VATTR_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, normal));
glEnableVertexAttribArray(VATTR_UV);
glVertexAttribPointer(VATTR_UV, 2, GL_FLOAT, GL_FALSE, sizeof(struct vertex_common), (void*)offsetof(struct vertex_common, uv));
glGenBuffers(1, &mesh->index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, nr_indices * sizeof(GLushort), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
free(vertices);
free(indices);
}
struct model *model_create_sphere(int r, int g, int b, int a)
{
struct model *model = xcalloc(1, sizeof(struct model));
model->nr_meshes = 1;
model->meshes = xcalloc(1, sizeof(struct mesh));
init_sphere_mesh(&model->meshes[0]);
model->aabb[0][0] = -1.0f;
model->aabb[0][1] = -1.0f;
model->aabb[0][2] = -1.0f;
model->aabb[1][0] = 1.0f;
model->aabb[1][1] = 1.0f;
model->aabb[1][2] = 1.0f;
model->nr_materials = 1;
model->materials = xcalloc(1, sizeof(struct material));
struct material *material = &model->materials[0];
material->is_transparent = true;
glGenTextures(1, &material->color_map);
glBindTexture(GL_TEXTURE_2D, material->color_map);
uint8_t pixel[4] = {r, g, b, a};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
glBindTexture(GL_TEXTURE_2D, 0);
model->has_transparent_material = true;
return model;
}
static int cmp_motions_by_bone_id(const void *lhs, const void *rhs)
{
return (*(struct mot_bone **)lhs)->id - (*(struct mot_bone **)rhs)->id;
+16 -8
View File
@@ -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)
static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle_index, int unknowns_length, const struct pol_material_group *mg)
{
struct pol_triangle *t = &mesh->triangles[triangle_index];
t->vert_index[0] = buffer_read_int32(r);
@@ -154,7 +154,9 @@ static void parse_triangle(struct buffer *r, struct pol_mesh *mesh, int triangle
read_direction(r, t->normals[0]);
read_direction(r, t->normals[1]);
read_direction(r, t->normals[2]);
t->material = buffer_read_int32(r);
t->material_group_index = buffer_read_int32(r);
if (t->material_group_index >= mg->nr_children)
t->material_group_index = 0;
}
static uint32_t parse_mesh_attributes(const char *name)
@@ -168,10 +170,12 @@ static uint32_t parse_mesh_attributes(const char *name)
flags |= MESH_ENVMAP;
if (strstr(name, "(both)"))
flags |= MESH_BOTH;
if (strstr(name, "(sprite)"))
flags |= MESH_SPRITE;
return flags;
}
static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version)
static struct pol_mesh *parse_mesh(struct buffer *r, const struct pol *pol)
{
int type = buffer_read_int32(r);
if (type != 0) {
@@ -183,11 +187,15 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version)
mesh->name = read_cstring(r);
mesh->flags = parse_mesh_attributes(mesh->name);
mesh->material = buffer_read_int32(r);
if (mesh->material >= pol->nr_materials) {
WARNING("material index out of range (%d >= %d)", mesh->material, pol->nr_materials);
mesh->material = 0;
}
mesh->nr_vertices = buffer_read_int32(r);
mesh->vertices = xcalloc(mesh->nr_vertices, sizeof(struct pol_vertex));
for (uint32_t i = 0; i < mesh->nr_vertices; i++) {
parse_vertex(r, pol_version, &mesh->vertices[i]);
parse_vertex(r, pol->version, &mesh->vertices[i]);
}
mesh->nr_uvs = buffer_read_int32(r);
@@ -207,7 +215,7 @@ static struct pol_mesh *parse_mesh(struct buffer *r, int pol_version)
}
int triangle_unknowns_length = 12;
if (pol_version == 1) {
if (pol->version == 1) {
int nr_unknown_vecs = buffer_read_int32(r);
buffer_skip(r, nr_unknown_vecs * 12);
} else {
@@ -223,10 +231,10 @@ 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, mesh, i, triangle_unknowns_length);
parse_triangle(r, mesh, i, triangle_unknowns_length, &pol->materials[mesh->material]);
}
if (pol_version == 1) {
if (pol->version == 1) {
if (buffer_read_int32(r) != 1)
WARNING("unexpected mesh footer");
if (buffer_read_int32(r) != 0)
@@ -288,7 +296,7 @@ struct pol *pol_parse(uint8_t *data, size_t size)
pol->nr_meshes = buffer_read_int32(&r);
pol->meshes = xcalloc(pol->nr_meshes, sizeof(struct pol_mesh *));
for (uint32_t i = 0; i < pol->nr_meshes; i++) {
pol->meshes[i] = parse_mesh(&r, pol->version);
pol->meshes[i] = parse_mesh(&r, pol);
}
pol->nr_bones = buffer_read_int32(&r);
+49 -7
View File
@@ -39,19 +39,22 @@ static struct RE_instance *create_instance(struct RE_plugin *plugin)
instance->plugin = plugin;
for (int i = 0; i < RE_NR_INSTANCE_TARGETS; i++)
instance->target[i] = -1;
instance->scale[0] = 1.0;
instance->scale[1] = 1.0;
instance->scale[2] = 1.0;
instance->alpha = 1.0;
instance->scale[0] = 1.0f;
instance->scale[1] = 1.0f;
instance->scale[2] = 1.0f;
instance->alpha = 1.0f;
instance->shadow_volume_bone_radius = 0.1f;
instance->draw_bump = true;
instance->fps = 30.0;
instance->column_height = 1.0;
instance->column_radius = 1.0;
instance->fps = 30.0f;
instance->column_height = 1.0f;
instance->column_radius = 1.0f;
glm_mat4_identity(instance->local_transform);
glm_mat3_identity(instance->normal_transform);
return instance;
}
static void free_instance(struct RE_instance *instance);
static void unload_instance(struct RE_instance *instance)
{
if (instance->motion) {
@@ -78,6 +81,10 @@ static void unload_instance(struct RE_instance *instance)
RE_renderer_free_height_detector(instance->height_detector);
instance->height_detector = NULL;
}
if (instance->shadow_volume_instance) {
free_instance(instance->shadow_volume_instance);
instance->shadow_volume_instance = NULL;
}
}
static void free_instance(struct RE_instance *instance)
@@ -143,6 +150,10 @@ static void update_bones(struct RE_instance *inst)
return;
mat4 parent_transforms[MAX_BONES];
vec3 aabb[2];
glm_aabb_invalidate(aabb);
// Update inst->bone_transforms.
for (int i = 0; i < inst->model->nr_bones; i++) {
struct mot_frame mf;
calc_motion_frame(inst->motion, i, &mf);
@@ -162,6 +173,24 @@ 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]);
}
// Update inst->bounding_sphere.
vec3 center;
glm_aabb_center(aabb, center);
if (inst->local_transform_needs_update)
RE_instance_update_local_transform(inst);
glm_mat4_mulv3(inst->local_transform, center, 1.0f, inst->bounding_sphere);
inst->bounding_sphere[3] = glm_aabb_radius(aabb) * inst->scale[0] + inst->shadow_volume_bone_radius;
struct RE_instance *shvol = inst->shadow_volume_instance;
if (shvol) {
glm_vec3_copy(inst->bounding_sphere, shvol->pos);
glm_vec3_broadcast(inst->bounding_sphere[3], shvol->scale);
RE_instance_update_local_transform(shvol);
}
}
@@ -443,6 +472,19 @@ float RE_instance_calc_height(struct RE_instance *instance, float x, float z)
return y;
}
bool RE_instance_set_debug_draw_shadow_volume(struct RE_instance *inst, bool draw)
{
if (!inst)
return false;
if (draw && !inst->shadow_volume_instance) {
inst->shadow_volume_instance = create_instance(inst->plugin);
inst->shadow_volume_instance->model = model_create_sphere(255, 0, 0, 64);
}
if (inst->shadow_volume_instance)
inst->shadow_volume_instance->draw = draw;
return true;
}
void RE_instance_update_local_transform(struct RE_instance *inst)
{
vec3 euler = {
+33 -47
View File
@@ -27,8 +27,8 @@
#include "sact.h"
// TODO: Respect RE_plugin.shadow_map_resolution_level
#define SHADOW_WIDTH 1024
#define SHADOW_HEIGHT 1024
#define SHADOW_WIDTH 512
#define SHADOW_HEIGHT 512
enum {
COLOR_TEXTURE_UNIT,
@@ -201,7 +201,7 @@ struct RE_renderer *RE_renderer_new(struct texture *texture)
r->light_texture = glGetUniformLocation(r->program, "light_texture");
r->use_normal_map = glGetUniformLocation(r->program, "use_normal_map");
r->normal_texture = glGetUniformLocation(r->program, "normal_texture");
r->use_shadow_map = glGetUniformLocation(r->program, "use_shadow_map");
r->shadow_darkness = glGetUniformLocation(r->program, "shadow_darkness");
r->shadow_transform = glGetUniformLocation(r->program, "shadow_transform");
r->shadow_texture = glGetUniformLocation(r->program, "shadow_texture");
r->shadow_bias = glGetUniformLocation(r->program, "shadow_bias");
@@ -317,7 +317,7 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
for (int i = 0; i < model->nr_meshes; i++) {
struct mesh *mesh = &model->meshes[i];
struct material *material = &model->materials[mesh->material];
bool is_transparent = material->is_transparent || inst->alpha < 1.0f;
bool is_transparent = (material->is_transparent && !(mesh->flags & MESH_SPRITE)) || inst->alpha < 1.0f;
if (phase != (is_transparent ? DRAW_TRANSPARENT : DRAW_OPAQUE))
continue;
@@ -347,7 +347,10 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
glBindTexture(GL_TEXTURE_2D, material->color_map);
glUniform1i(r->texture, COLOR_TEXTURE_UNIT);
glUniform1i(r->use_shadow_map, draw_shadow && !(mesh->flags & MESH_BOTH));
if (draw_shadow && !(mesh->flags & MESH_BOTH))
glUniform1f(r->shadow_darkness, material->shadow_darkness);
else
glUniform1f(r->shadow_darkness, 0.0f);
if (mesh->flags & MESH_ENVMAP) {
glUniform1i(r->diffuse_type, DIFFUSE_ENV_MAP);
@@ -376,14 +379,19 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
glActiveTexture(GL_TEXTURE0 + ALPHA_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, material->alpha_map);
glUniform1i(r->alpha_texture, ALPHA_TEXTURE_UNIT);
} else if (material->flags & MATERIAL_SPRITE) {
} else if (material->flags & MATERIAL_SPRITE || mesh->flags & MESH_SPRITE) {
glUniform1i(r->alpha_mode, ALPHA_TEST);
} else {
glUniform1i(r->alpha_mode, ALPHA_BLEND);
}
glBindVertexArray(mesh->vao);
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
if (mesh->nr_indices)
glDrawElements(GL_TRIANGLES, mesh->nr_indices, GL_UNSIGNED_SHORT, NULL);
else
glDrawArrays(GL_TRIANGLES, 0, mesh->nr_vertices);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -405,13 +413,16 @@ static void render_skinned_model(struct RE_instance *inst, struct RE_renderer *r
if (!model)
return;
if (model->nr_bones > 0) {
if (model->nr_bones > 0 && inst->motion) {
glUniform1i(r->has_bones, GL_TRUE);
glUniformMatrix4fv(r->bone_matrices, model->nr_bones, GL_FALSE, inst->bone_transforms[0][0]);
} else {
glUniform1i(r->has_bones, GL_FALSE);
}
render_model(inst, r, phase);
if (inst->shadow_volume_instance && phase == DRAW_TRANSPARENT)
render_static_model(inst->shadow_volume_instance, r, phase);
}
static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, mat4 view_mat, enum draw_phase phase)
@@ -452,7 +463,7 @@ static void render_billboard(struct RE_instance *inst, struct RE_renderer *r, ma
glUniform1f(r->rim_exponent, 0.0);
glUniform1i(r->diffuse_type, DIFFUSE_NORMAL);
glUniform1i(r->use_normal_map, GL_FALSE);
glUniform1i(r->use_shadow_map, GL_FALSE);
glUniform1f(r->shadow_darkness, 0.0f);
glUniform1i(r->alpha_mode, ALPHA_BLEND);
glUniform1i(r->fog_type, inst->plugin->fog_mode ? inst->plugin->fog_type : 0);
switch (inst->draw_type) {
@@ -572,7 +583,7 @@ static void render_particle_effect(struct RE_instance *inst, struct RE_renderer
glUniform1i(r->use_specular_map, GL_FALSE);
glUniform1f(r->rim_exponent, 0.0);
glUniform1i(r->use_normal_map, GL_FALSE);
glUniform1i(r->use_shadow_map, GL_FALSE);
glUniform1f(r->shadow_darkness, 0.0f);
glUniform1i(r->alpha_mode, ALPHA_BLEND);
glDepthMask(GL_FALSE);
@@ -626,52 +637,27 @@ static void render_instance(struct RE_instance *inst, struct RE_renderer *r, mat
static bool calc_shadow_light_transform(struct RE_plugin *plugin, mat4 dest)
{
// Compute AABB of shadow casters.
vec3 aabb[2];
glm_aabb_invalidate(aabb);
// Compute a bounding sphere of shadow casters.
vec4 bounding_sphere = {};
for (int i = 0; i < plugin->nr_instances; i++) {
struct RE_instance *inst = plugin->instances[i];
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];
glm_vec3_subs(inst->model->aabb[0], inst->shadow_volume_bone_radius, inst_aabb[0]);
glm_vec3_adds(inst->model->aabb[1], inst->shadow_volume_bone_radius, inst_aabb[1]);
// To save CPU cycles, consider only the translation components of bone transforms.
vec3 bone_translation_aabb[2];
glm_aabb_invalidate(bone_translation_aabb);
for (int j = 0; j < inst->model->nr_bones; j++) {
glm_vec3_minv(inst->bone_transforms[j][3], bone_translation_aabb[0], bone_translation_aabb[0]);
glm_vec3_maxv(inst->bone_transforms[j][3], bone_translation_aabb[1], bone_translation_aabb[1]);
}
if (glm_aabb_isvalid(bone_translation_aabb)) {
glm_vec3_add(inst_aabb[0], bone_translation_aabb[0], inst_aabb[0]);
glm_vec3_add(inst_aabb[1], bone_translation_aabb[1], inst_aabb[1]);
}
// Apply local transform.
if (inst->local_transform_needs_update)
RE_instance_update_local_transform(inst);
glm_aabb_transform(inst_aabb, inst->local_transform, inst_aabb);
glm_aabb_merge(inst_aabb, aabb, aabb);
if (bounding_sphere[3] > 0.0f)
glm_sphere_merge(inst->bounding_sphere, bounding_sphere, inst->bounding_sphere);
else
glm_vec4_copy(inst->bounding_sphere, bounding_sphere);
}
if (!glm_aabb_isvalid(aabb))
float radius = bounding_sphere[3] * 1.2f; // Add some padding.
if (radius <= 0.0f)
return false;
// Create a orthographic frustum that contains the AABB.
vec3 center;
glm_aabb_center(aabb, center);
vec3 light_pos;
glm_vec3_scale(plugin->shadow_map_light_dir, -glm_aabb_radius(aabb), light_pos);
glm_vec3_add(light_pos, center, light_pos);
// Create a orthographic frustum that contains the bounding sphere.
mat4 view_matrix;
vec3 up = {0.0, 1.0, 0.0};
glm_lookat(light_pos, center, up, view_matrix);
glm_look(bounding_sphere, plugin->shadow_map_light_dir, GLM_YUP, view_matrix);
mat4 proj_matrix;
glm_aabb_transform(aabb, view_matrix, aabb);
glm_ortho_aabb(aabb, proj_matrix);
glm_ortho(-radius, radius, -radius, radius, -radius, radius, proj_matrix);
glm_mat4_mul(proj_matrix, view_matrix, dest);
return true;
}
+13 -4
View File
@@ -651,8 +651,17 @@ static bool ReignEngine_SetInstanceShadowVolumeBoneRadius(int plugin, int instan
return true;
}
//bool ReignEngine_GetInstanceDebugDrawShadowVolume(int plugin, int instance);
//bool ReignEngine_SetInstanceDebugDrawShadowVolume(int plugin, int instance, bool flag);
static bool ReignEngine_GetInstanceDebugDrawShadowVolume(int plugin, int instance)
{
struct RE_instance *ri = get_instance(plugin, instance);
return ri && ri->shadow_volume_instance && ri->shadow_volume_instance->draw;
}
static bool ReignEngine_SetInstanceDebugDrawShadowVolume(int plugin, int instance, bool flag)
{
return RE_instance_set_debug_draw_shadow_volume(get_instance(plugin, instance), flag);
}
//bool ReignEngine_SaveEffect(int plugin, int instance);
static bool ReignEngine_GetEffectFrameRange(int plugin, int instance, int *begin_frame, int *end_frame)
@@ -1899,8 +1908,8 @@ HLL_LIBRARY(ReignEngine,
HLL_EXPORT(SetInstanceSoftFogEdgeLength, ReignEngine_SetInstanceSoftFogEdgeLength),
HLL_EXPORT(GetInstanceShadowVolumeBoneRadius, ReignEngine_GetInstanceShadowVolumeBoneRadius),
HLL_EXPORT(SetInstanceShadowVolumeBoneRadius, ReignEngine_SetInstanceShadowVolumeBoneRadius),
HLL_TODO_EXPORT(GetInstanceDebugDrawShadowVolume, ReignEngine_GetInstanceDebugDrawShadowVolume),
HLL_TODO_EXPORT(SetInstanceDebugDrawShadowVolume, ReignEngine_SetInstanceDebugDrawShadowVolume),
HLL_EXPORT(GetInstanceDebugDrawShadowVolume, ReignEngine_GetInstanceDebugDrawShadowVolume),
HLL_EXPORT(SetInstanceDebugDrawShadowVolume, ReignEngine_SetInstanceDebugDrawShadowVolume),
HLL_TODO_EXPORT(SaveEffect, ReignEngine_SaveEffect),
HLL_EXPORT(GetEffectFrameRange, ReignEngine_GetEffectFrameRange),
HLL_EXPORT(GetEffectObjectType, ReignEngine_GetEffectObjectType),