Merge pull request #68 from kichikuou/fog

ReignEngine: Implement Fog
This commit is contained in:
Nunuhara Cabbage
2022-08-05 18:51:38 -07:00
committed by GitHub
8 changed files with 342 additions and 43 deletions
+18 -3
View File
@@ -40,6 +40,11 @@ enum RE_motion_state {
RE_MOTION_STATE_LOOP = 2,
};
enum RE_fog_type {
RE_FOG_LINEAR = 1,
RE_FOG_LIGHT_SCATTERING = 2,
};
struct RE_options {
int anti_aliasing;
int wait_vsync;
@@ -74,16 +79,26 @@ struct RE_plugin {
struct RE_back_cg back_cg[RE_NR_BACK_CGS];
vec3 shadow_map_light_dir;
float shadow_bias;
// Settings.
int render_mode;
int shadow_mode;
vec3 shadow_map_light_dir;
float shadow_bias;
int bump_mode;
int bloom_mode;
int glare_mode;
int fog_mode;
enum RE_fog_type fog_type;
float fog_near;
float fog_far;
vec3 fog_color;
float ls_beta_r;
float ls_beta_m;
float ls_g;
float ls_distance;
vec3 ls_light_dir;
vec3 ls_light_color;
vec3 ls_sun_color;
int specular_mode;
int light_map_mode;
int soft_fog_edge_mode;
+17
View File
@@ -15,6 +15,8 @@
*/
#define NR_DIR_LIGHTS 3
#define FOG_LINEAR 1
#define FOG_LIGHT_SCATTERING 2
struct dir_light {
vec3 dir;
@@ -41,15 +43,22 @@ uniform vec3 rim_color;
uniform bool use_light_map;
uniform bool use_shadow_map;
uniform float shadow_bias;
uniform int fog_type;
uniform float fog_near;
uniform float fog_far;
uniform vec3 fog_color;
in vec2 tex_coord;
in vec2 light_tex_coord;
in vec3 frag_pos;
in vec4 shadow_frag_pos;
in float dist;
in vec3 eye;
in vec3 normal;
in vec3 light_dir[NR_DIR_LIGHTS];
in vec3 specular_dir;
in vec3 ls_ex;
in vec3 ls_in;
out vec4 frag_color;
void main() {
@@ -92,6 +101,14 @@ void main() {
frag_rgb += pow(1.0 - max(dot(normalize(normal), view_dir), 0.0), rim_exponent) * rim_color;
}
// Fog
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) {
frag_rgb = frag_rgb * ls_ex + ls_in;
}
// Shadow mapping
if (use_shadow_map) {
vec3 shadow_coords = shadow_frag_pos.xyz / shadow_frag_pos.w * 0.5 + 0.5;
+35 -4
View File
@@ -15,6 +15,9 @@
*/
#define NR_DIR_LIGHTS 3
#define FOG_LIGHT_SCATTERING 2
const float PI = 3.14159265358979323846;
struct dir_light {
vec3 dir;
@@ -34,10 +37,15 @@ uniform mat4 bone_matrices[MAX_BONES];
uniform bool use_normal_map;
uniform vec3 view_pos;
uniform vec3 camera_pos;
uniform dir_light dir_lights[NR_DIR_LIGHTS];
uniform vec3 specular_light_dir;
uniform mat4 shadow_transform;
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;
in vec3 vertex_pos;
in vec3 vertex_normal;
@@ -51,10 +59,13 @@ out vec2 tex_coord;
out vec2 light_tex_coord;
out vec3 frag_pos;
out vec4 shadow_frag_pos;
out float dist;
out vec3 eye;
out vec3 normal;
out vec3 light_dir[NR_DIR_LIGHTS];
out vec3 specular_dir;
out vec3 ls_ex;
out vec3 ls_in;
void main() {
mat4 local_bone_transform = local_transform;
@@ -83,19 +94,39 @@ void main() {
}
vec4 world_pos = local_bone_transform * vec4(vertex_pos, 1.0);
gl_Position = proj_transform * view_transform * world_pos;
vec4 view_pos = view_transform * world_pos;
gl_Position = proj_transform * view_pos;
tex_coord = vertex_uv;
light_tex_coord = vertex_light_uv;
dist = -view_pos.z;
shadow_frag_pos = shadow_transform * world_pos;
// These are in tangent-space if use_normal_map is true, in world-space
// otherwise.
frag_pos = TBN * vec3(world_pos);
eye = TBN * view_pos;
eye = TBN * camera_pos;
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;
if (fog_type == FOG_LIGHT_SCATTERING) {
float beta_r = ls_params.x;
float beta_m = ls_params.y;
float g = ls_params.z;
float distance = dist / ls_params.w;
vec3 view_dir = normalize(camera_pos - vec3(world_pos));
float cos_theta = dot(view_dir, normalize(ls_light_dir));
// Note: `* PI` in the two assignments below should be `/ PI` (see the
// definitions of Rayleigh / Mie phase functions in [1]), but this is
// how TT3's shader works.
// [1] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/ATI-LightScattering.pdf
float phase_r = 3.0 / 16.0 * PI * (1.0 + cos_theta * cos_theta);
float phase_m = 1.0 / 4.0 * PI * (1.0 - g) * (1.0 - g) / pow(1.0 + g * g - 2.0 * g * cos_theta, 1.5);
float f_ex = exp((beta_r + beta_m) * -distance);
ls_in = (phase_r * beta_r + phase_m * beta_m) / (beta_r + beta_m) * (1.0 - f_ex) * ls_sun_color;
ls_ex = ls_light_color * f_ex;
}
}
+9 -1
View File
@@ -121,7 +121,7 @@ struct RE_renderer {
GLint specular_texture;
GLint rim_exponent;
GLint rim_color;
GLint view_pos;
GLint camera_pos;
GLint use_light_map;
GLint light_texture;
GLint use_normal_map;
@@ -130,6 +130,14 @@ struct RE_renderer {
GLint shadow_transform;
GLint shadow_texture;
GLint shadow_bias;
GLint fog_type;
GLint fog_near;
GLint fog_far;
GLint fog_color;
GLint ls_params;
GLint ls_light_dir;
GLint ls_light_color;
GLint ls_sun_color;
// Attribute variable locations
GLint vertex_normal;
+27
View File
@@ -47,6 +47,15 @@ static const char *motion_state_name(enum RE_motion_state state)
return "UNKNOWN";
}
static const char *fog_type_name(enum RE_fog_type type)
{
switch (type) {
case RE_FOG_LINEAR: return "LINEAR";
case RE_FOG_LIGHT_SCATTERING: return "LIGHT_SCATTERING";
}
return "UNKNOWN";
}
static void print_motion(const char *name, struct motion *m, int indent)
{
if (m->instance->type == RE_ITYPE_BILLBOARD) {
@@ -119,6 +128,24 @@ void RE_debug_print(struct sact_sprite *sp, int indent)
indent_printf(indent, "name = \"%s\",\n", p->plugin.name);
indent_printf(indent, "camera = {x=%f, y=%f, z=%f, pitch=%f, roll=%f, yaw=%f},\n",
SPREAD_VEC3(p->camera.pos), p->camera.pitch, p->camera.roll, p->camera.yaw);
indent_printf(indent, "shadow_map_light_dir = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(p->shadow_map_light_dir));
indent_printf(indent, "shadow_bias = %f,\n", p->shadow_bias);
indent_printf(indent, "fog_type = %s,\n", fog_type_name(p->fog_type));
switch (p->fog_type) {
case RE_FOG_LINEAR:
indent_printf(indent, "fog_near = %f, fog_far = %f,\n", p->fog_near, p->fog_far);
indent_printf(indent, "fog_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->fog_color));
break;
case RE_FOG_LIGHT_SCATTERING:
indent_printf(indent, "ls_beta_r = %f, ls_beta_m = %f,\n", p->ls_beta_r, p->ls_beta_m);
indent_printf(indent, "ls_g = %f,\n", p->ls_g);
indent_printf(indent, "ls_distance = %f,\n", p->ls_distance);
indent_printf(indent, "ls_light_dir = {x=%f, y=%f, z=%f},\n", SPREAD_VEC3(p->ls_light_dir));
indent_printf(indent, "ls_light_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->ls_light_color));
indent_printf(indent, "ls_sun_color = {r=%f, g=%f, b=%f},\n", SPREAD_VEC3(p->ls_sun_color));
break;
}
for (int i = 0; i < p->nr_instances; i++)
print_instance(p->instances[i], i, indent);
+1
View File
@@ -182,6 +182,7 @@ struct RE_plugin *RE_plugin_new(void)
plugin->aar = aar;
for (int i = 0; i < RE_NR_BACK_CGS; i++)
RE_back_cg_init(&plugin->back_cg[i]);
plugin->fog_type = RE_FOG_LINEAR;
return plugin;
}
+28 -2
View File
@@ -172,7 +172,7 @@ struct RE_renderer *RE_renderer_new(struct texture *texture)
r->specular_texture = glGetUniformLocation(r->program, "specular_texture");
r->rim_exponent = glGetUniformLocation(r->program, "rim_exponent");
r->rim_color = glGetUniformLocation(r->program, "rim_color");
r->view_pos = glGetUniformLocation(r->program, "view_pos");
r->camera_pos = glGetUniformLocation(r->program, "camera_pos");
r->use_light_map = glGetUniformLocation(r->program, "use_light_map");
r->light_texture = glGetUniformLocation(r->program, "light_texture");
r->use_normal_map = glGetUniformLocation(r->program, "use_normal_map");
@@ -181,6 +181,14 @@ struct RE_renderer *RE_renderer_new(struct texture *texture)
r->shadow_transform = glGetUniformLocation(r->program, "shadow_transform");
r->shadow_texture = glGetUniformLocation(r->program, "shadow_texture");
r->shadow_bias = glGetUniformLocation(r->program, "shadow_bias");
r->fog_type = glGetUniformLocation(r->program, "fog_type");
r->fog_near = glGetUniformLocation(r->program, "fog_near");
r->fog_far = glGetUniformLocation(r->program, "fog_far");
r->fog_color = glGetUniformLocation(r->program, "fog_color");
r->ls_params = glGetUniformLocation(r->program, "ls_params");
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->vertex_normal = glGetAttribLocation(r->program, "vertex_normal");
r->vertex_uv = glGetAttribLocation(r->program, "vertex_uv");
r->vertex_light_uv = glGetAttribLocation(r->program, "vertex_light_uv");
@@ -507,7 +515,7 @@ static void render_back_cg(struct texture *dst, struct RE_back_cg *bcg, struct R
static void setup_lights(struct RE_plugin *plugin)
{
struct RE_renderer *r = plugin->renderer;
glUniform3fv(r->view_pos, 1, plugin->camera.pos);
glUniform3fv(r->camera_pos, 1, plugin->camera.pos);
int light_index = 0;
for (int i = 0; i < plugin->nr_instances; i++) {
struct RE_instance *inst = plugin->instances[i];
@@ -587,6 +595,24 @@ void RE_render(struct sact_sprite *sp)
glUniformMatrix4fv(r->proj_transform, 1, GL_FALSE, plugin->proj_transform[0]);
glUniformMatrix4fv(r->shadow_transform, 1, GL_FALSE, shadow_transform[0]);
glUniform1f(r->shadow_bias, plugin->shadow_bias);
if (plugin->fog_mode) {
glUniform1i(r->fog_type, plugin->fog_type);
switch (plugin->fog_type) {
case RE_FOG_LINEAR:
glUniform1f(r->fog_near, plugin->fog_near);
glUniform1f(r->fog_far, plugin->fog_far);
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);
break;
}
} else {
glUniform1i(r->fog_type, 0);
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+207 -33
View File
@@ -773,29 +773,203 @@ static bool ReignEngine_SetShadowMapResolutionLevel(int plugin, int level)
}
//bool ReignEngine_SetShadowSplitDepth(int plugin, int num, float fDepth);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetFogType, int plugin, int type);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetFogNear, int plugin, float near);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetFogFar, int plugin, float far);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetFogColor, int plugin, float r, float g, float b);
//int ReignEngine_GetFogType(int plugin);
//float ReignEngine_GetFogNear(int plugin);
//float ReignEngine_GetFogFar(int plugin);
//void ReignEngine_GetFogColor(int plugin, float *r, float *g, float *b);
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;
}
static bool ReignEngine_SetFogNear(int plugin, float near)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->fog_near = near;
return true;
}
static bool ReignEngine_SetFogFar(int plugin, float far)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->fog_far = far;
return true;
}
static bool ReignEngine_SetFogColor(int plugin, float r, float g, float b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->fog_color[0] = r;
p->fog_color[1] = g;
p->fog_color[2] = b;
return true;
}
static int ReignEngine_GetFogType(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->fog_type : 0;
}
static float ReignEngine_GetFogNear(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->fog_near : 0.0;
}
static float ReignEngine_GetFogFar(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->fog_far : 0.0;
}
static void ReignEngine_GetFogColor(int plugin, float *r, float *g, float *b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return;
*r = p->fog_color[0];
*g = p->fog_color[1];
*b = p->fog_color[2];
}
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, LoadLightScatteringSetting, int plugin, struct string *filename /* e.g. "Data\PolyData\BG\bg001\bg001.ls2" */);
//float ReignEngine_GetLSBetaR(int plugin);
//float ReignEngine_GetLSBetaM(int plugin);
//float ReignEngine_GetLSG(int plugin);
//float ReignEngine_GetLSDistance(int plugin);
//void ReignEngine_GetLSLightDir(int plugin, float *pfX, float *pfY, float *pfZ);
//void ReignEngine_GetLSLightColor(int plugin, float *r, float *g, float *b);
//void ReignEngine_GetLSSunColor(int plugin, float *r, float *g, float *b);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSBetaR, int plugin, float beta_r);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSBetaM, int plugin, float beta_m);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSG, int plugin, float g);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSDistance, int plugin, float distance);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSLightDir, int plugin, float x, float y, float z);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSLightColor, int plugin, float r, float g, float b);
HLL_WARN_UNIMPLEMENTED(false, bool, ReignEngine, SetLSSunColor, int plugin, float r, float g, float b);
static float ReignEngine_GetLSBetaR(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->ls_beta_r : 0.0;
}
static float ReignEngine_GetLSBetaM(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->ls_beta_m : 0.0;
}
static float ReignEngine_GetLSG(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->ls_g : 0.0;
}
static float ReignEngine_GetLSDistance(int plugin)
{
struct RE_plugin *p = get_plugin(plugin);
return p ? p->ls_distance : 0.0;
}
static void ReignEngine_GetLSLightDir(int plugin, float *x, float *y, float *z)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return;
*x = p->ls_light_dir[0];
*y = p->ls_light_dir[1];
*z = -p->ls_light_dir[2];
}
static void ReignEngine_GetLSLightColor(int plugin, float *r, float *g, float *b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return;
*r = p->ls_light_color[0];
*g = p->ls_light_color[1];
*b = p->ls_light_color[2];
}
static void ReignEngine_GetLSSunColor(int plugin, float *r, float *g, float *b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return;
*r = p->ls_sun_color[0];
*g = p->ls_sun_color[1];
*b = p->ls_sun_color[2];
}
static bool ReignEngine_SetLSBetaR(int plugin, float beta_r)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_beta_r = beta_r;
return true;
}
static bool ReignEngine_SetLSBetaM(int plugin, float beta_m)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_beta_m = beta_m;
return true;
}
static bool ReignEngine_SetLSG(int plugin, float g)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_g = g;
return true;
}
static bool ReignEngine_SetLSDistance(int plugin, float distance)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_distance = distance;
return true;
}
static bool ReignEngine_SetLSLightDir(int plugin, float x, float y, float z)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_light_dir[0] = x;
p->ls_light_dir[1] = y;
p->ls_light_dir[2] = -z;
glm_vec3_normalize(p->ls_light_dir);
return true;
}
static bool ReignEngine_SetLSLightColor(int plugin, float r, float g, float b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_light_color[0] = r;
p->ls_light_color[1] = g;
p->ls_light_color[2] = b;
return true;
}
static bool ReignEngine_SetLSSunColor(int plugin, float r, float g, float b)
{
struct RE_plugin *p = get_plugin(plugin);
if (!p)
return false;
p->ls_sun_color[0] = r;
p->ls_sun_color[1] = g;
p->ls_sun_color[2] = b;
return true;
}
//bool ReignEngine_SetDrawTextureFog(int plugin, bool bDraw);
//bool ReignEngine_GetDrawTextureFog(int plugin);
@@ -1494,18 +1668,18 @@ HLL_LIBRARY(ReignEngine,
HLL_EXPORT(SetFogNear, ReignEngine_SetFogNear),
HLL_EXPORT(SetFogFar, ReignEngine_SetFogFar),
HLL_EXPORT(SetFogColor, ReignEngine_SetFogColor),
HLL_TODO_EXPORT(GetFogType, ReignEngine_GetFogType),
HLL_TODO_EXPORT(GetFogNear, ReignEngine_GetFogNear),
HLL_TODO_EXPORT(GetFogFar, ReignEngine_GetFogFar),
HLL_TODO_EXPORT(GetFogColor, ReignEngine_GetFogColor),
HLL_EXPORT(GetFogType, ReignEngine_GetFogType),
HLL_EXPORT(GetFogNear, ReignEngine_GetFogNear),
HLL_EXPORT(GetFogFar, ReignEngine_GetFogFar),
HLL_EXPORT(GetFogColor, ReignEngine_GetFogColor),
HLL_EXPORT(LoadLightScatteringSetting, ReignEngine_LoadLightScatteringSetting),
HLL_TODO_EXPORT(GetLSBetaR, ReignEngine_GetLSBetaR),
HLL_TODO_EXPORT(GetLSBetaM, ReignEngine_GetLSBetaM),
HLL_TODO_EXPORT(GetLSG, ReignEngine_GetLSG),
HLL_TODO_EXPORT(GetLSDistance, ReignEngine_GetLSDistance),
HLL_TODO_EXPORT(GetLSLightDir, ReignEngine_GetLSLightDir),
HLL_TODO_EXPORT(GetLSLightColor, ReignEngine_GetLSLightColor),
HLL_TODO_EXPORT(GetLSSunColor, ReignEngine_GetLSSunColor),
HLL_EXPORT(GetLSBetaR, ReignEngine_GetLSBetaR),
HLL_EXPORT(GetLSBetaM, ReignEngine_GetLSBetaM),
HLL_EXPORT(GetLSG, ReignEngine_GetLSG),
HLL_EXPORT(GetLSDistance, ReignEngine_GetLSDistance),
HLL_EXPORT(GetLSLightDir, ReignEngine_GetLSLightDir),
HLL_EXPORT(GetLSLightColor, ReignEngine_GetLSLightColor),
HLL_EXPORT(GetLSSunColor, ReignEngine_GetLSSunColor),
HLL_EXPORT(SetLSBetaR, ReignEngine_SetLSBetaR),
HLL_EXPORT(SetLSBetaM, ReignEngine_SetLSBetaM),
HLL_EXPORT(SetLSG, ReignEngine_SetLSG),