mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-10-01 03:18:09 +03:00
Merge pull request #352 from kichikuou/lighting
SealEngine: Add lighting support
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#define RE_NR_BACK_CGS 16
|
||||
#define RE_NR_INSTANCE_TARGETS 2
|
||||
#define RE_NR_LIGHT_PARAMS 41 // .lit parameter count
|
||||
|
||||
#include <cglm/types.h>
|
||||
|
||||
@@ -57,6 +58,29 @@ enum RE_fog_type {
|
||||
RE_FOG_LIGHT_SCATTERING = 2,
|
||||
};
|
||||
|
||||
// Indices into light_params. Vector entries name their first component.
|
||||
enum seal_light_param {
|
||||
SEAL_LP_TONEMAP_EXPOSURE_BIAS = 0,
|
||||
SEAL_LP_TONEMAP_WHITE_POINT = 1,
|
||||
SEAL_LP_TONEMAP_A = 2,
|
||||
SEAL_LP_TONEMAP_B = 3,
|
||||
SEAL_LP_TONEMAP_C = 4,
|
||||
SEAL_LP_TONEMAP_D = 5,
|
||||
SEAL_LP_TONEMAP_E = 6,
|
||||
SEAL_LP_TONEMAP_F = 7,
|
||||
SEAL_LP_HEMI_VEC = 8, // x,y,z
|
||||
SEAL_LP_HEMI_SKY_COLOR = 11, // r,g,b
|
||||
SEAL_LP_HEMI_MID_COLOR = 14, // r,g,b
|
||||
SEAL_LP_HEMI_GROUND_COLOR = 17, // r,g,b
|
||||
SEAL_LP_LS_BETA_R = 20,
|
||||
SEAL_LP_LS_BETA_M = 21,
|
||||
SEAL_LP_LS_G = 22,
|
||||
SEAL_LP_LS_DISTANCE = 23,
|
||||
SEAL_LP_LS_LIGHT_VEC = 24, // x,y,z
|
||||
SEAL_LP_LS_LIGHT_COLOR = 27, // r,g,b
|
||||
SEAL_LP_LS_SUN_COLOR = 30, // r,g,b
|
||||
};
|
||||
|
||||
enum RE_draw_type {
|
||||
RE_DRAW_TYPE_NORMAL = 0,
|
||||
RE_DRAW_TYPE_ADDITIVE = 1,
|
||||
@@ -158,6 +182,7 @@ struct RE_plugin {
|
||||
|
||||
// SealEngine
|
||||
int mag_speed;
|
||||
float light_params[RE_NR_LIGHT_PARAMS];
|
||||
};
|
||||
|
||||
struct RE_instance {
|
||||
@@ -197,6 +222,7 @@ struct RE_instance {
|
||||
// Lights
|
||||
vec3 vec;
|
||||
vec3 globe_diffuse;
|
||||
float *light_params;
|
||||
|
||||
// Private
|
||||
bool local_transform_needs_update;
|
||||
@@ -244,6 +270,9 @@ bool RE_instance_optimize_path_line(struct RE_instance *instance);
|
||||
bool RE_instance_calc_path_finder_intersect_eye_vec(struct RE_instance *instance, int mouse_x, int mouse_y, vec3 out);
|
||||
bool RE_plugin_transform_pos_to_view_pos(struct RE_plugin *plugin, float x, float y, float z, int *view_x, int *view_y);
|
||||
bool RE_plugin_get_camera_z_vector(struct RE_plugin *plugin, vec3 out);
|
||||
void RE_plugin_reset_light_param(struct RE_plugin *plugin);
|
||||
bool RE_plugin_set_fog_type(struct RE_plugin *plugin, int type);
|
||||
int RE_plugin_get_fog_type(struct RE_plugin *plugin);
|
||||
|
||||
int RE_motion_get_state(struct motion *motion);
|
||||
bool RE_motion_set_state(struct motion *motion, int state);
|
||||
|
||||
+80
-19
@@ -24,11 +24,15 @@
|
||||
#define ALPHA_MAP_BLEND 2
|
||||
#define ALPHA_MAP_TEST 3
|
||||
|
||||
#define FOG_LINEAR 1
|
||||
#define FOG_LIGHT_SCATTERING 2
|
||||
|
||||
#define ENABLE_SPECULAR (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE)
|
||||
#define ENABLE_LIGHT_SCATTERING (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE)
|
||||
|
||||
#if ENGINE == REIGN_ENGINE
|
||||
|
||||
#define NR_DIR_LIGHTS 3
|
||||
#define FOG_LINEAR 1
|
||||
#define FOG_LIGHT_SCATTERING 2
|
||||
|
||||
struct dir_light {
|
||||
vec3 dir;
|
||||
@@ -36,25 +40,17 @@ struct dir_light {
|
||||
vec3 globe_diffuse;
|
||||
};
|
||||
|
||||
uniform sampler2D specular_texture;
|
||||
uniform dir_light dir_lights[NR_DIR_LIGHTS];
|
||||
uniform float specular_strength;
|
||||
uniform float specular_shininess;
|
||||
uniform bool use_specular_map;
|
||||
uniform float rim_exponent;
|
||||
uniform vec3 rim_color;
|
||||
uniform int fog_type;
|
||||
uniform float fog_near;
|
||||
uniform float fog_far;
|
||||
uniform vec3 fog_color;
|
||||
in vec3 light_dir[NR_DIR_LIGHTS];
|
||||
in vec3 specular_dir;
|
||||
in vec3 ls_ex;
|
||||
in vec3 ls_in;
|
||||
|
||||
uniform vec3 global_ambient;
|
||||
|
||||
vec3 dir_lights_diffuse(vec3 norm)
|
||||
vec3 compute_diffuse(vec3 norm)
|
||||
{
|
||||
vec3 diffuse = vec3(0.0);
|
||||
for (int i = 0; i < NR_DIR_LIGHTS; i++) {
|
||||
@@ -64,17 +60,71 @@ vec3 dir_lights_diffuse(vec3 norm)
|
||||
return diffuse;
|
||||
}
|
||||
|
||||
#else // ENGINE == REIGN_ENGINE
|
||||
#elif ENGINE == SEAL_ENGINE
|
||||
|
||||
const vec3 global_ambient = vec3(0.0);
|
||||
|
||||
vec3 dir_lights_diffuse(vec3 norm)
|
||||
// Hemisphere lighting (sky/middle/ground).
|
||||
uniform vec3 hemi_light_dir;
|
||||
uniform vec3 hemi_sky_color;
|
||||
uniform vec3 hemi_mid_color;
|
||||
uniform vec3 hemi_ground_color;
|
||||
|
||||
vec3 compute_diffuse(vec3 norm)
|
||||
{
|
||||
float t = 0.5 * dot(norm, hemi_light_dir) + 0.5;
|
||||
vec3 low_mid = mix(hemi_ground_color, hemi_mid_color, t);
|
||||
vec3 mid_high = mix(hemi_mid_color, hemi_sky_color, t);
|
||||
return mix(low_mid, mid_high, t);
|
||||
}
|
||||
|
||||
#else // TAPIR_ENGINE
|
||||
|
||||
const vec3 global_ambient = vec3(0.0);
|
||||
|
||||
vec3 compute_diffuse(vec3 norm)
|
||||
{
|
||||
return vec3(1.0);
|
||||
}
|
||||
|
||||
#endif // ENGINE == REIGN_ENGINE
|
||||
|
||||
#if ENABLE_LIGHT_SCATTERING
|
||||
uniform int fog_type;
|
||||
in vec3 ls_ex;
|
||||
in vec3 ls_in;
|
||||
#endif
|
||||
|
||||
#if ENABLE_SPECULAR
|
||||
uniform sampler2D specular_texture;
|
||||
uniform vec3 specular_color;
|
||||
uniform float specular_shininess;
|
||||
uniform bool use_specular_map;
|
||||
in vec3 specular_dir;
|
||||
#endif
|
||||
|
||||
#if ENGINE == SEAL_ENGINE
|
||||
// Uncharted 2 (Hable) filmic tone mapping.
|
||||
uniform vec4 tonemap_param; // (ExposureBias, WhitePoint, A, B)
|
||||
uniform vec4 tonemap_param2; // (C, D, E, F)
|
||||
uniform bool nolighting;
|
||||
|
||||
vec3 hable(vec3 v)
|
||||
{
|
||||
float a = tonemap_param.z, b = tonemap_param.w;
|
||||
float c = tonemap_param2.x, d = tonemap_param2.y;
|
||||
float e = tonemap_param2.z, f = tonemap_param2.w;
|
||||
return ((v * (a * v + c * b) + d * e) / (v * (a * v + b) + d * f)) - e / f;
|
||||
}
|
||||
|
||||
vec3 tone_map(vec3 color)
|
||||
{
|
||||
vec3 curr = hable(color * tonemap_param.x);
|
||||
vec3 white = hable(vec3(tonemap_param.y));
|
||||
return curr / white;
|
||||
}
|
||||
#endif
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D blend_tex;
|
||||
uniform bool use_blend_texture;
|
||||
@@ -128,7 +178,7 @@ void main() {
|
||||
texel = mix(texel, texture(blend_tex, blend_tex_coord), blend_weight);
|
||||
}
|
||||
if (diffuse_type != DIFFUSE_EMISSIVE) {
|
||||
diffuse = dir_lights_diffuse(norm);
|
||||
diffuse = compute_diffuse(norm);
|
||||
if (diffuse_type == DIFFUSE_LIGHT_MAP) {
|
||||
diffuse *= texture(light_texture, light_tex_coord).rgb;
|
||||
}
|
||||
@@ -136,17 +186,19 @@ void main() {
|
||||
}
|
||||
frag_rgb += texel.rgb * diffuse * color_mod.rgb * diffuse_mod;
|
||||
|
||||
#if ENGINE == REIGN_ENGINE
|
||||
#if ENABLE_SPECULAR
|
||||
// Specular lighting
|
||||
if (specular_strength > 0.0) {
|
||||
if (any(greaterThan(specular_color, vec3(0.0)))) {
|
||||
vec3 reflect_dir = reflect(specular_dir, norm);
|
||||
float specular = pow(max(dot(view_dir, reflect_dir), 0.0), specular_shininess) * specular_strength;
|
||||
float specular = pow(max(dot(view_dir, reflect_dir), 0.0), specular_shininess);
|
||||
if (use_specular_map) {
|
||||
specular *= texture(specular_texture, tex_coord).r;
|
||||
}
|
||||
frag_rgb += vec3(specular);
|
||||
frag_rgb += specular_color * specular;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENGINE == REIGN_ENGINE
|
||||
// Rim lighting
|
||||
if (rim_exponent > 0.0) {
|
||||
// Normal map is not used here.
|
||||
@@ -158,7 +210,11 @@ void main() {
|
||||
if (fog_type == FOG_LINEAR) {
|
||||
float fog_factor = clamp((dist - fog_near) / (fog_far - fog_near), 0.0, 1.0);
|
||||
frag_rgb = mix(frag_rgb, fog_color, fog_factor);
|
||||
} else if (fog_type == FOG_LIGHT_SCATTERING) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LIGHT_SCATTERING
|
||||
if (fog_type == FOG_LIGHT_SCATTERING) {
|
||||
frag_rgb = frag_rgb * ls_ex + ls_in;
|
||||
}
|
||||
#endif
|
||||
@@ -180,6 +236,11 @@ void main() {
|
||||
frag_rgb *= brightness;
|
||||
}
|
||||
|
||||
#if ENGINE == SEAL_ENGINE
|
||||
if (!nolighting)
|
||||
frag_rgb = tone_map(frag_rgb);
|
||||
#endif
|
||||
|
||||
// Alpha mapping
|
||||
float alpha = texel.a * color_mod.a * alpha_mod;
|
||||
if (alpha_mode == ALPHA_TEST) {
|
||||
|
||||
+25
-12
@@ -16,10 +16,14 @@
|
||||
|
||||
const float PI = 3.14159265358979323846;
|
||||
|
||||
#define FOG_LIGHT_SCATTERING 2
|
||||
|
||||
#define ENABLE_SPECULAR (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE)
|
||||
#define ENABLE_LIGHT_SCATTERING (ENGINE == REIGN_ENGINE || ENGINE == SEAL_ENGINE)
|
||||
|
||||
#if ENGINE == REIGN_ENGINE
|
||||
|
||||
#define NR_DIR_LIGHTS 3
|
||||
#define FOG_LIGHT_SCATTERING 2
|
||||
|
||||
struct dir_light {
|
||||
vec3 dir;
|
||||
@@ -28,16 +32,7 @@ struct dir_light {
|
||||
};
|
||||
|
||||
uniform dir_light dir_lights[NR_DIR_LIGHTS];
|
||||
uniform vec3 specular_light_dir;
|
||||
uniform int fog_type;
|
||||
uniform vec4 ls_params; // (beta_r, beta_m, g, distance)
|
||||
uniform vec3 ls_light_dir;
|
||||
uniform vec3 ls_light_color;
|
||||
uniform vec3 ls_sun_color;
|
||||
out vec3 light_dir[NR_DIR_LIGHTS];
|
||||
out vec3 specular_dir;
|
||||
out vec3 ls_ex;
|
||||
out vec3 ls_in;
|
||||
|
||||
const vec2 uv_scroll = vec2(0.0);
|
||||
|
||||
@@ -47,6 +42,21 @@ uniform vec2 uv_scroll;
|
||||
|
||||
#endif // ENGINE == REIGN_ENGINE
|
||||
|
||||
#if ENABLE_LIGHT_SCATTERING
|
||||
uniform int fog_type;
|
||||
uniform vec4 ls_params; // (beta_r, beta_m, g, distance)
|
||||
uniform vec3 ls_light_dir;
|
||||
uniform vec3 ls_light_color;
|
||||
uniform vec3 ls_sun_color;
|
||||
out vec3 ls_ex;
|
||||
out vec3 ls_in;
|
||||
#endif
|
||||
|
||||
#if ENABLE_SPECULAR
|
||||
uniform vec3 specular_light_dir;
|
||||
out vec3 specular_dir;
|
||||
#endif
|
||||
|
||||
uniform mat4 local_transform;
|
||||
uniform mat4 view_transform;
|
||||
uniform mat4 proj_transform;
|
||||
@@ -131,12 +141,15 @@ void main() {
|
||||
frag_pos = TBN * vec3(world_pos);
|
||||
eye = TBN * camera_pos;
|
||||
|
||||
#if ENABLE_SPECULAR
|
||||
specular_dir = TBN * specular_light_dir;
|
||||
#endif
|
||||
#if ENGINE == REIGN_ENGINE
|
||||
light_dir[0] = TBN * dir_lights[0].dir;
|
||||
light_dir[1] = TBN * dir_lights[1].dir;
|
||||
light_dir[2] = TBN * dir_lights[2].dir;
|
||||
specular_dir = TBN * specular_light_dir;
|
||||
|
||||
#endif
|
||||
#if ENABLE_LIGHT_SCATTERING
|
||||
if (fog_type == FOG_LIGHT_SCATTERING) {
|
||||
float beta_r = ls_params.x;
|
||||
float beta_m = ls_params.y;
|
||||
|
||||
+17
-1
@@ -63,6 +63,8 @@ struct mesh {
|
||||
vec3 outline_color;
|
||||
float outline_thickness;
|
||||
vec2 uv_scroll;
|
||||
vec3 specular_color;
|
||||
float specular_power;
|
||||
};
|
||||
|
||||
struct material {
|
||||
@@ -163,7 +165,7 @@ struct RE_renderer {
|
||||
GLint ambient;
|
||||
} dir_lights[NR_DIR_LIGHTS];
|
||||
GLint specular_light_dir;
|
||||
GLint specular_strength;
|
||||
GLint specular_color;
|
||||
GLint specular_shininess;
|
||||
GLint use_specular_map;
|
||||
GLint specular_texture;
|
||||
@@ -186,6 +188,13 @@ struct RE_renderer {
|
||||
GLint ls_light_dir;
|
||||
GLint ls_light_color;
|
||||
GLint ls_sun_color;
|
||||
GLint hemi_light_dir;
|
||||
GLint hemi_sky_color;
|
||||
GLint hemi_mid_color;
|
||||
GLint hemi_ground_color;
|
||||
GLint tonemap_param;
|
||||
GLint tonemap_param2;
|
||||
GLint nolighting;
|
||||
GLint alpha_mode;
|
||||
GLint alpha_texture;
|
||||
GLint uv_scroll;
|
||||
@@ -665,6 +674,8 @@ enum mesh_flags {
|
||||
MESH_HAS_LIGHT_UV = 1 << 9,
|
||||
MESH_NO_ZWRITE = 1 << 10,
|
||||
MESH_HEIGHT_DETECTION = 1 << 11,
|
||||
MESH_HAS_SPECULAR_COLOR = 1 << 12,
|
||||
MESH_HAS_SPECULAR_POWER = 1 << 13,
|
||||
};
|
||||
|
||||
struct pol_mesh {
|
||||
@@ -691,6 +702,8 @@ struct pol_mesh {
|
||||
Color edge_color;
|
||||
float edge_size;
|
||||
vec2 uv_scroll;
|
||||
vec3 specular_color;
|
||||
float specular_power;
|
||||
};
|
||||
|
||||
struct pol_vertex {
|
||||
@@ -784,6 +797,9 @@ struct amt_material *amt_find_material(struct amt *amt, const char *name);
|
||||
void opr_load(uint8_t *data, size_t size, struct pol *pol);
|
||||
void txa_load(uint8_t *data, size_t size, struct mot *mot);
|
||||
|
||||
void lit_reset(float *out);
|
||||
bool lit_parse(uint8_t *data, size_t size, float *out);
|
||||
|
||||
// mpr.c
|
||||
|
||||
struct mpr_float_key { int frame; float v; };
|
||||
|
||||
@@ -379,6 +379,8 @@ static void add_mesh(struct model *model, struct pol_mesh *m, uint32_t material_
|
||||
mesh->outline_color[2] = m->edge_color.b / 255.f;
|
||||
mesh->outline_thickness = m->edge_size ? m->edge_size : DEFAULT_OUTLINE_THICKNESS;
|
||||
glm_vec2_copy(m->uv_scroll, mesh->uv_scroll);
|
||||
glm_vec3_copy(m->specular_color, mesh->specular_color);
|
||||
mesh->specular_power = m->specular_power;
|
||||
mesh->nr_vertices = nr_vertices;
|
||||
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
|
||||
+75
-1
@@ -574,7 +574,7 @@ void opr_load(uint8_t *data, size_t size, struct pol *pol)
|
||||
|
||||
char s[200];
|
||||
int i1, i2, i3;
|
||||
float f1, f2;
|
||||
float f1, f2, f3;
|
||||
if (sscanf(line, "Mesh = \"%[^\"]\"", s) == 1) {
|
||||
for (int i = 0; i < pol->nr_meshes; i++) {
|
||||
selected[i] = pol->meshes[i] && !strcmp(pol->meshes[i]->name, s);
|
||||
@@ -640,6 +640,20 @@ void opr_load(uint8_t *data, size_t size, struct pol *pol)
|
||||
pol->meshes[i]->uv_scroll[0] = f1;
|
||||
pol->meshes[i]->uv_scroll[1] = f2;
|
||||
}
|
||||
} else if (sscanf(line, "SpecularColor = ( %f , %f , %f )", &f1, &f2, &f3) == 3) {
|
||||
for (int i = 0; i < pol->nr_meshes; i++) {
|
||||
if (!selected[i]) continue;
|
||||
pol->meshes[i]->flags |= MESH_HAS_SPECULAR_COLOR;
|
||||
pol->meshes[i]->specular_color[0] = f1;
|
||||
pol->meshes[i]->specular_color[1] = f2;
|
||||
pol->meshes[i]->specular_color[2] = f3;
|
||||
}
|
||||
} else if (sscanf(line, "SpecularPower = %f", &f1) == 1) {
|
||||
for (int i = 0; i < pol->nr_meshes; i++) {
|
||||
if (!selected[i]) continue;
|
||||
pol->meshes[i]->flags |= MESH_HAS_SPECULAR_POWER;
|
||||
pol->meshes[i]->specular_power = f1;
|
||||
}
|
||||
} else if (strchr(line, '=')) {
|
||||
WARNING("unknown field: %s", line);
|
||||
}
|
||||
@@ -673,3 +687,63 @@ void txa_load(uint8_t *data, size_t size, struct mot *mot)
|
||||
mot->nr_texture_indices = count;
|
||||
mot->texture_indices = indices;
|
||||
}
|
||||
|
||||
void lit_reset(float *out)
|
||||
{
|
||||
static const float lit_param_defaults[RE_NR_LIGHT_PARAMS] = {
|
||||
[SEAL_LP_TONEMAP_EXPOSURE_BIAS] = 1.0f,
|
||||
[SEAL_LP_TONEMAP_WHITE_POINT] = 1.0f,
|
||||
[SEAL_LP_TONEMAP_A] = 0.22f,
|
||||
[SEAL_LP_TONEMAP_B] = 0.30f,
|
||||
[SEAL_LP_TONEMAP_C] = 0.10f,
|
||||
[SEAL_LP_TONEMAP_D] = 0.20f,
|
||||
[SEAL_LP_TONEMAP_E] = 0.01f,
|
||||
[SEAL_LP_TONEMAP_F] = 0.30f,
|
||||
[SEAL_LP_HEMI_VEC + 0] = -1.0f,
|
||||
[SEAL_LP_HEMI_VEC + 1] = -1.0f,
|
||||
[SEAL_LP_HEMI_VEC + 2] = 1.0f,
|
||||
[SEAL_LP_HEMI_SKY_COLOR + 0] = 1.2f,
|
||||
[SEAL_LP_HEMI_SKY_COLOR + 1] = 1.2f,
|
||||
[SEAL_LP_HEMI_SKY_COLOR + 2] = 1.2f,
|
||||
[SEAL_LP_HEMI_MID_COLOR + 0] = 0.5f,
|
||||
[SEAL_LP_HEMI_MID_COLOR + 1] = 0.5f,
|
||||
[SEAL_LP_HEMI_MID_COLOR + 2] = 0.5f,
|
||||
[SEAL_LP_HEMI_GROUND_COLOR + 0] = 0.3f,
|
||||
[SEAL_LP_HEMI_GROUND_COLOR + 1] = 0.3f,
|
||||
[SEAL_LP_HEMI_GROUND_COLOR + 2] = 0.3f,
|
||||
[SEAL_LP_LS_BETA_R] = 0.25f,
|
||||
[SEAL_LP_LS_BETA_M] = 1.25f,
|
||||
[SEAL_LP_LS_G] = 0.05f,
|
||||
[SEAL_LP_LS_DISTANCE] = 140.0f,
|
||||
[SEAL_LP_LS_LIGHT_VEC + 0] = -1.0f,
|
||||
[SEAL_LP_LS_LIGHT_VEC + 1] = -1.0f,
|
||||
[SEAL_LP_LS_LIGHT_VEC + 2] = 1.0f,
|
||||
[SEAL_LP_LS_LIGHT_COLOR + 0] = 1.0f,
|
||||
[SEAL_LP_LS_LIGHT_COLOR + 1] = 1.0f,
|
||||
[SEAL_LP_LS_LIGHT_COLOR + 2] = 1.0f,
|
||||
[SEAL_LP_LS_SUN_COLOR + 0] = 0.5f,
|
||||
[SEAL_LP_LS_SUN_COLOR + 1] = 0.5f,
|
||||
[SEAL_LP_LS_SUN_COLOR + 2] = 0.5f,
|
||||
};
|
||||
memcpy(out, lit_param_defaults, sizeof(lit_param_defaults));
|
||||
}
|
||||
|
||||
bool lit_parse(uint8_t *data, size_t size, float *out)
|
||||
{
|
||||
if (size != 8 + RE_NR_LIGHT_PARAMS * 4 || memcmp(data, "LITP", 4) != 0) {
|
||||
WARNING("invalid .lit file");
|
||||
return false;
|
||||
}
|
||||
struct buffer r;
|
||||
buffer_init(&r, data, size);
|
||||
buffer_skip(&r, 4); // "LITP"
|
||||
int32_t version = buffer_read_int32(&r);
|
||||
if (version != 0) {
|
||||
WARNING("unsupported .lit version %d", version);
|
||||
return false;
|
||||
}
|
||||
lit_reset(out);
|
||||
for (int i = 0; i < RE_NR_LIGHT_PARAMS; i++)
|
||||
out[i] = buffer_read_float(&r);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "system4.h"
|
||||
#include "system4/aar.h"
|
||||
#include "system4/archive.h"
|
||||
#include "system4/cg.h"
|
||||
#include "system4/hashtable.h"
|
||||
#include "system4/string.h"
|
||||
@@ -98,6 +99,7 @@ static void unload_instance(struct RE_instance *instance)
|
||||
static void free_instance(struct RE_instance *instance)
|
||||
{
|
||||
unload_instance(instance);
|
||||
free(instance->light_params);
|
||||
xfree_aligned(instance);
|
||||
}
|
||||
|
||||
@@ -249,6 +251,7 @@ struct RE_plugin *RE_plugin_new(enum RE_plugin_version version)
|
||||
plugin->fog_near = 1.0;
|
||||
plugin->fog_far = 10.0;
|
||||
glm_vec3_one(plugin->fog_color);
|
||||
lit_reset(plugin->light_params);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -431,6 +434,10 @@ bool RE_instance_set_type(struct RE_instance *instance, int type)
|
||||
instance->motion->instance = instance;
|
||||
break;
|
||||
case RE_ITYPE_DIRECTIONAL_LIGHT:
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN) {
|
||||
instance->light_params = xmalloc(RE_NR_LIGHT_PARAMS * sizeof(float));
|
||||
lit_reset(instance->light_params);
|
||||
}
|
||||
break;
|
||||
case RE_ITYPE_SPECULAR_LIGHT:
|
||||
break;
|
||||
@@ -526,6 +533,16 @@ bool RE_instance_load(struct RE_instance *instance, const char *name)
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case RE_ITYPE_DIRECTIONAL_LIGHT:
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN) {
|
||||
struct archive_data *dfile = archive_get_by_name(instance->plugin->aar, name);
|
||||
if (!dfile)
|
||||
return false;
|
||||
bool ok = lit_parse(dfile->data, dfile->size, instance->light_params);
|
||||
archive_free_data(dfile);
|
||||
return ok;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
WARNING("Invalid instance type %d", instance->type);
|
||||
return false;
|
||||
@@ -786,6 +803,50 @@ bool RE_plugin_get_camera_z_vector(struct RE_plugin *plugin, vec3 out)
|
||||
return true;
|
||||
}
|
||||
|
||||
void RE_plugin_reset_light_param(struct RE_plugin *plugin)
|
||||
{
|
||||
lit_reset(plugin->light_params);
|
||||
}
|
||||
|
||||
bool RE_plugin_set_fog_type(struct RE_plugin *plugin, int type)
|
||||
{
|
||||
if (re_plugin_version == RE_REIGN_PLUGIN) {
|
||||
switch (type) {
|
||||
case 0: plugin->fog_type = RE_FOG_NONE; return true;
|
||||
case 1: plugin->fog_type = RE_FOG_LINEAR; return true;
|
||||
case 2: plugin->fog_type = RE_FOG_LIGHT_SCATTERING; return true;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case 0: plugin->fog_type = RE_FOG_NONE; return true;
|
||||
case 1: plugin->fog_type = RE_FOG_LIGHT_SCATTERING; return true;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
WARNING("unknown fog type %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
int RE_plugin_get_fog_type(struct RE_plugin *plugin)
|
||||
{
|
||||
if (re_plugin_version == RE_REIGN_PLUGIN) {
|
||||
switch (plugin->fog_type) {
|
||||
case RE_FOG_NONE: return 0;
|
||||
case RE_FOG_LINEAR: return 1;
|
||||
case RE_FOG_LIGHT_SCATTERING: return 2;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
switch (plugin->fog_type) {
|
||||
case RE_FOG_NONE: return 0;
|
||||
case RE_FOG_LIGHT_SCATTERING: return 1;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
ERROR("[BUG] unexpected fog type %d", plugin->fog_type);
|
||||
}
|
||||
|
||||
void RE_instance_update_local_transform(struct RE_instance *inst)
|
||||
{
|
||||
vec3 euler = {
|
||||
|
||||
+77
-12
@@ -236,7 +236,7 @@ struct RE_renderer *RE_renderer_new(void)
|
||||
r->dir_lights[i].globe_diffuse = glGetUniformLocation(r->program, buf);
|
||||
}
|
||||
r->specular_light_dir = glGetUniformLocation(r->program, "specular_light_dir");
|
||||
r->specular_strength = glGetUniformLocation(r->program, "specular_strength");
|
||||
r->specular_color = glGetUniformLocation(r->program, "specular_color");
|
||||
r->specular_shininess = glGetUniformLocation(r->program, "specular_shininess");
|
||||
r->use_specular_map = glGetUniformLocation(r->program, "use_specular_map");
|
||||
r->specular_texture = glGetUniformLocation(r->program, "specular_texture");
|
||||
@@ -259,6 +259,13 @@ struct RE_renderer *RE_renderer_new(void)
|
||||
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->hemi_light_dir = glGetUniformLocation(r->program, "hemi_light_dir");
|
||||
r->hemi_sky_color = glGetUniformLocation(r->program, "hemi_sky_color");
|
||||
r->hemi_mid_color = glGetUniformLocation(r->program, "hemi_mid_color");
|
||||
r->hemi_ground_color = glGetUniformLocation(r->program, "hemi_ground_color");
|
||||
r->tonemap_param = glGetUniformLocation(r->program, "tonemap_param");
|
||||
r->tonemap_param2 = glGetUniformLocation(r->program, "tonemap_param2");
|
||||
r->nolighting = glGetUniformLocation(r->program, "nolighting");
|
||||
r->alpha_mode = glGetUniformLocation(r->program, "alpha_mode");
|
||||
r->alpha_texture = glGetUniformLocation(r->program, "alpha_texture");
|
||||
r->uv_scroll = glGetUniformLocation(r->program, "uv_scroll");
|
||||
@@ -424,13 +431,22 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
glUniform1i(r->fog_type, (inst->plugin->fog_mode && !(mesh->flags & MESH_NOLIGHTING))
|
||||
? inst->plugin->fog_type : 0);
|
||||
int fog_type = inst->plugin->fog_type;
|
||||
if (!inst->plugin->fog_mode || (re_plugin_version == RE_REIGN_PLUGIN && (mesh->flags & MESH_NOLIGHTING))) {
|
||||
fog_type = RE_FOG_NONE;
|
||||
}
|
||||
glUniform1i(r->fog_type, fog_type);
|
||||
glUniform1i(r->nolighting, !!(mesh->flags & MESH_NOLIGHTING));
|
||||
|
||||
GLboolean use_specular_map = GL_FALSE;
|
||||
if (inst->plugin->specular_mode && !(mesh->flags & MESH_NOLIGHTING)) {
|
||||
glUniform1f(r->specular_strength, material->specular_strength);
|
||||
glUniform1f(r->specular_shininess, material->specular_shininess);
|
||||
if (mesh->flags & MESH_HAS_SPECULAR_COLOR) {
|
||||
glUniform3fv(r->specular_color, 1, mesh->specular_color);
|
||||
} else {
|
||||
glUniform3f(r->specular_color, material->specular_strength, material->specular_strength, material->specular_strength);
|
||||
}
|
||||
float shininess = (mesh->flags & MESH_HAS_SPECULAR_POWER) ? mesh->specular_power : material->specular_shininess;
|
||||
glUniform1f(r->specular_shininess, shininess);
|
||||
if (material->specular_map) {
|
||||
glActiveTexture(GL_TEXTURE0 + SPECULAR_TEXTURE_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, material->specular_map);
|
||||
@@ -438,8 +454,8 @@ static void render_model(struct RE_instance *inst, struct RE_renderer *r, enum d
|
||||
use_specular_map = GL_TRUE;
|
||||
}
|
||||
} else {
|
||||
glUniform1f(r->specular_strength, 0.0);
|
||||
glUniform1f(r->specular_shininess, 0.0);
|
||||
glUniform3f(r->specular_color, 0.0f, 0.0f, 0.0f);
|
||||
glUniform1f(r->specular_shininess, 0.0f);
|
||||
}
|
||||
glUniform1i(r->use_specular_map, use_specular_map);
|
||||
|
||||
@@ -556,7 +572,7 @@ static void reset_draw_uniforms(struct RE_renderer *r)
|
||||
glUniform3f(r->diffuse_mod, 1.0f, 1.0f, 1.0f);
|
||||
glUniform2f(r->uv_scroll, 0.0f, 0.0f);
|
||||
glUniform1i(r->has_bones, GL_FALSE);
|
||||
glUniform1f(r->specular_strength, 0.0f);
|
||||
glUniform3f(r->specular_color, 0.0f, 0.0f, 0.0f);
|
||||
glUniform1f(r->specular_shininess, 0.0f);
|
||||
glUniform1i(r->use_specular_map, GL_FALSE);
|
||||
glUniform1f(r->rim_exponent, 0.0f);
|
||||
@@ -1106,6 +1122,53 @@ static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct R
|
||||
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_light_scattering(struct RE_plugin *plugin)
|
||||
{
|
||||
struct RE_renderer *r = plugin->renderer;
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN) {
|
||||
const float *lp = plugin->light_params;
|
||||
glUniform4f(r->ls_params, lp[SEAL_LP_LS_BETA_R], lp[SEAL_LP_LS_BETA_M],
|
||||
lp[SEAL_LP_LS_G], lp[SEAL_LP_LS_DISTANCE]);
|
||||
glUniform3f(r->ls_light_dir, lp[SEAL_LP_LS_LIGHT_VEC],
|
||||
lp[SEAL_LP_LS_LIGHT_VEC + 1], -lp[SEAL_LP_LS_LIGHT_VEC + 2]);
|
||||
glUniform3fv(r->ls_light_color, 1, &lp[SEAL_LP_LS_LIGHT_COLOR]);
|
||||
glUniform3fv(r->ls_sun_color, 1, &lp[SEAL_LP_LS_SUN_COLOR]);
|
||||
} else {
|
||||
glUniform4f(r->ls_params, plugin->ls_beta_r, plugin->ls_beta_m, plugin->ls_g, plugin->ls_distance);
|
||||
glUniform3fv(r->ls_light_dir, 1, plugin->ls_light_dir);
|
||||
glUniform3fv(r->ls_light_color, 1, plugin->ls_light_color);
|
||||
glUniform3fv(r->ls_sun_color, 1, plugin->ls_sun_color);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_hemisphere_light(struct RE_plugin *plugin)
|
||||
{
|
||||
struct RE_renderer *r = plugin->renderer;
|
||||
const float *lp = plugin->light_params;
|
||||
vec3 hemi_dir = {
|
||||
-lp[SEAL_LP_HEMI_VEC], -lp[SEAL_LP_HEMI_VEC + 1], lp[SEAL_LP_HEMI_VEC + 2]
|
||||
};
|
||||
glm_vec3_normalize(hemi_dir);
|
||||
glUniform3fv(r->hemi_light_dir, 1, hemi_dir);
|
||||
glUniform3fv(r->hemi_sky_color, 1, &lp[SEAL_LP_HEMI_SKY_COLOR]);
|
||||
glUniform3fv(r->hemi_mid_color, 1, &lp[SEAL_LP_HEMI_MID_COLOR]);
|
||||
glUniform3fv(r->hemi_ground_color, 1, &lp[SEAL_LP_HEMI_GROUND_COLOR]);
|
||||
// SealEngine's specular uses the hemisphere light vector. hemi_dir points
|
||||
// toward the light, but the shader's specular formula expects the light
|
||||
// propagation direction.
|
||||
vec3 spec_dir;
|
||||
glm_vec3_negate_to(hemi_dir, spec_dir);
|
||||
glUniform3fv(r->specular_light_dir, 1, spec_dir);
|
||||
}
|
||||
|
||||
static void setup_tone_mapping(struct RE_plugin *plugin)
|
||||
{
|
||||
struct RE_renderer *r = plugin->renderer;
|
||||
const float *lp = plugin->light_params;
|
||||
glUniform4fv(r->tonemap_param, 1, &lp[SEAL_LP_TONEMAP_EXPOSURE_BIAS]);
|
||||
glUniform4fv(r->tonemap_param2, 1, &lp[SEAL_LP_TONEMAP_C]);
|
||||
}
|
||||
|
||||
static void setup_lights(struct RE_plugin *plugin)
|
||||
{
|
||||
struct RE_renderer *r = plugin->renderer;
|
||||
@@ -1141,6 +1204,9 @@ static void setup_lights(struct RE_plugin *plugin)
|
||||
glUniform3fv(r->dir_lights[light_index].diffuse, 1, zero);
|
||||
glUniform3fv(r->dir_lights[light_index].globe_diffuse, 1, zero);
|
||||
}
|
||||
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN)
|
||||
setup_hemisphere_light(plugin);
|
||||
}
|
||||
|
||||
static int cmp_instances_by_z(const void *lhs, const void *rhs)
|
||||
@@ -1248,10 +1314,7 @@ void RE_render(struct sact_sprite *sp)
|
||||
glUniform3fv(r->fog_color, 1, plugin->fog_color);
|
||||
break;
|
||||
case RE_FOG_LIGHT_SCATTERING:
|
||||
glUniform4f(r->ls_params, plugin->ls_beta_r, plugin->ls_beta_m, plugin->ls_g, plugin->ls_distance);
|
||||
glUniform3fv(r->ls_light_dir, 1, plugin->ls_light_dir);
|
||||
glUniform3fv(r->ls_light_color, 1, plugin->ls_light_color);
|
||||
glUniform3fv(r->ls_sun_color, 1, plugin->ls_sun_color);
|
||||
setup_light_scattering(plugin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1259,6 +1322,8 @@ void RE_render(struct sact_sprite *sp)
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
setup_lights(plugin);
|
||||
if (re_plugin_version >= RE_SEAL_PLUGIN)
|
||||
setup_tone_mapping(plugin);
|
||||
|
||||
// Sort instances by z-order.
|
||||
struct RE_instance **sorted_instances = sort_instances(plugin, view_transform);
|
||||
|
||||
+50
-17
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <cglm/cglm.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "system4.h"
|
||||
#include "system4/aar.h"
|
||||
@@ -1178,14 +1179,7 @@ static bool ReignEngine_SetShadowMapResolutionLevel(int plugin, int level)
|
||||
static bool ReignEngine_SetFogType(int plugin, int type)
|
||||
{
|
||||
struct RE_plugin *p = get_plugin(plugin);
|
||||
if (!p)
|
||||
return false;
|
||||
if (type != RE_FOG_LINEAR && type != RE_FOG_LIGHT_SCATTERING) {
|
||||
WARNING("unknown fog type %d", type);
|
||||
return false;
|
||||
}
|
||||
p->fog_type = type;
|
||||
return true;
|
||||
return p ? RE_plugin_set_fog_type(p, type) : false;
|
||||
}
|
||||
|
||||
static bool ReignEngine_SetFogNear(int plugin, float near)
|
||||
@@ -1220,7 +1214,7 @@ static bool ReignEngine_SetFogColor(int plugin, float r, float g, float b)
|
||||
static int ReignEngine_GetFogType(int plugin)
|
||||
{
|
||||
struct RE_plugin *p = get_plugin(plugin);
|
||||
return p ? p->fog_type : 0;
|
||||
return p ? RE_plugin_get_fog_type(p) : 0;
|
||||
}
|
||||
|
||||
static float ReignEngine_GetFogNear(int plugin)
|
||||
@@ -2449,8 +2443,25 @@ static bool SealEngine_IsExistInstanceMotion(int plugin, int instance, struct st
|
||||
//bool SealEngine_AddLineList(int PluginNumber, int InstanceNumber, float X0, float Y0, float Z0, int Color0, float X1, float Y1, float Z1, int Color1);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, SealEngine, SetInstanceCircleShadowRadius, int PluginNumber, int InstanceNumber, float CircleShadowRadius);
|
||||
//float SealEngine_GetInstanceCircleShadowRadius(int PluginNumber, int InstanceNumber);
|
||||
//bool SealEngine_LoadInstanceLightParam(int PluginNumber, int InstanceNumber);
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, SealEngine, StoreInstanceLightParam, int PluginNumber, int InstanceNumber);
|
||||
static bool SealEngine_LoadInstanceLightParam(int plugin, int instance)
|
||||
{
|
||||
struct RE_plugin *rp = get_plugin(plugin);
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!rp || !ri || !ri->light_params)
|
||||
return false;
|
||||
memcpy(ri->light_params, rp->light_params, RE_NR_LIGHT_PARAMS * sizeof(float));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SealEngine_StoreInstanceLightParam(int plugin, int instance)
|
||||
{
|
||||
struct RE_plugin *rp = get_plugin(plugin);
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
if (!rp || !ri || !ri->light_params)
|
||||
return false;
|
||||
memcpy(rp->light_params, ri->light_params, RE_NR_LIGHT_PARAMS * sizeof(float));
|
||||
return true;
|
||||
}
|
||||
static bool SealEngine_SetInstanceUseMagSpeed(int plugin, int instance, bool use_mag_speed)
|
||||
{
|
||||
struct RE_instance *ri = get_instance(plugin, instance);
|
||||
@@ -2517,9 +2528,31 @@ static bool SealEngine_TransformPosToViewPos(int PluginNumber, float x, float y,
|
||||
return RE_plugin_transform_pos_to_view_pos(get_plugin(PluginNumber), x, y, -z, view_x, view_y);
|
||||
}
|
||||
|
||||
HLL_WARN_UNIMPLEMENTED(false, bool, SealEngine, ResetLightParam, int PluginNumber);
|
||||
//bool SealEngine_SetLightParam(int PluginNumber, int Type, float Value);
|
||||
//float SealEngine_GetLightParam(int PluginNumber, int Type);
|
||||
static bool SealEngine_ResetLightParam(int plugin)
|
||||
{
|
||||
struct RE_plugin *rp = get_plugin(plugin);
|
||||
if (!rp)
|
||||
return false;
|
||||
RE_plugin_reset_light_param(rp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SealEngine_SetLightParam(int plugin, int type, float value)
|
||||
{
|
||||
struct RE_plugin *rp = get_plugin(plugin);
|
||||
if (!rp || (unsigned)type >= RE_NR_LIGHT_PARAMS)
|
||||
return false;
|
||||
rp->light_params[type] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
static float SealEngine_GetLightParam(int plugin, int type)
|
||||
{
|
||||
struct RE_plugin *rp = get_plugin(plugin);
|
||||
if (!rp || (unsigned)type >= RE_NR_LIGHT_PARAMS)
|
||||
return 0.0f;
|
||||
return rp->light_params[type];
|
||||
}
|
||||
HLL_QUIET_UNIMPLEMENTED(false, bool, SealEngine, IsThreadLoadingMode, int PluginNumber);
|
||||
//bool SealEngine_ClearCache(int PluginNumber);
|
||||
//bool SealEngine_GetHistogram(int PluginNumber, struct page **HistogramList);
|
||||
@@ -2582,7 +2615,7 @@ HLL_QUIET_UNIMPLEMENTED(false, bool, SealEngine, IsThreadLoadingMode, int Plugin
|
||||
HLL_TODO_EXPORT(AddLineList, SealEngine_AddLineList), \
|
||||
HLL_EXPORT(SetInstanceCircleShadowRadius, SealEngine_SetInstanceCircleShadowRadius), \
|
||||
HLL_TODO_EXPORT(GetInstanceCircleShadowRadius, SealEngine_GetInstanceCircleShadowRadius), \
|
||||
HLL_TODO_EXPORT(LoadInstanceLightParam, SealEngine_LoadInstanceLightParam), \
|
||||
HLL_EXPORT(LoadInstanceLightParam, SealEngine_LoadInstanceLightParam), \
|
||||
HLL_EXPORT(StoreInstanceLightParam, SealEngine_StoreInstanceLightParam), \
|
||||
HLL_EXPORT(SetInstanceUseMagSpeed, SealEngine_SetInstanceUseMagSpeed), \
|
||||
HLL_EXPORT(IsInstanceUseMagSpeed, SealEngine_IsInstanceUseMagSpeed), \
|
||||
@@ -2623,8 +2656,8 @@ HLL_QUIET_UNIMPLEMENTED(false, bool, SealEngine, IsThreadLoadingMode, int Plugin
|
||||
HLL_TODO_EXPORT(GetOptimizedPathLine, SealEngine_GetOptimizedPathLine), \
|
||||
HLL_EXPORT(TransformPosToViewPos, SealEngine_TransformPosToViewPos), \
|
||||
HLL_EXPORT(ResetLightParam, SealEngine_ResetLightParam), \
|
||||
HLL_TODO_EXPORT(SetLightParam, SealEngine_SetLightParam), \
|
||||
HLL_TODO_EXPORT(GetLightParam, SealEngine_GetLightParam), \
|
||||
HLL_EXPORT(SetLightParam, SealEngine_SetLightParam), \
|
||||
HLL_EXPORT(GetLightParam, SealEngine_GetLightParam), \
|
||||
HLL_EXPORT(IsThreadLoadingMode, SealEngine_IsThreadLoadingMode), \
|
||||
HLL_TODO_EXPORT(ClearCache, SealEngine_ClearCache), \
|
||||
HLL_TODO_EXPORT(GetHistogram, SealEngine_GetHistogram)
|
||||
|
||||
Reference in New Issue
Block a user