Implemented FOG support in GLES2.

This commit is contained in:
Juan Linietsky 2018-10-02 18:52:40 -03:00
parent 723e2e9654
commit 11f088279d
3 changed files with 160 additions and 8 deletions

View file

@ -742,20 +742,38 @@ void RasterizerSceneGLES2::environment_set_adjustment(RID p_env, bool p_enable,
}
void RasterizerSceneGLES2::environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->fog_enabled = p_enable;
env->fog_color = p_color;
env->fog_sun_color = p_sun_color;
env->fog_sun_amount = p_sun_amount;
}
void RasterizerSceneGLES2::environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_curve, bool p_transmit, float p_transmit_curve) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
env->fog_depth_enabled = p_enable;
env->fog_depth_begin = p_depth_begin;
env->fog_depth_curve = p_depth_curve;
env->fog_transmit_enabled = p_transmit;
env->fog_transmit_curve = p_transmit_curve;
}
void RasterizerSceneGLES2::environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
}
env->fog_height_enabled = p_enable;
env->fog_height_min = p_min_height;
env->fog_height_max = p_max_height;
env->fog_height_curve = p_height_curve;
}
bool RasterizerSceneGLES2::is_environment(RID p_env) {
return environment_owner.owns(p_env);
}
@ -2031,6 +2049,15 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
glDisable(GL_BLEND);
}
float fog_max_distance = 0;
bool using_fog = false;
if (p_env && !p_shadow && p_env->fog_enabled && (p_env->fog_depth_enabled || p_env->fog_height_enabled)) {
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, p_env->fog_depth_enabled);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, p_env->fog_height_enabled);
fog_max_distance = p_projection.get_z_far();
using_fog = true;
}
RasterizerStorageGLES2::Texture *prev_lightmap = NULL;
float lightmap_energy = 1.0;
bool prev_use_lightmap_capture = false;
@ -2268,10 +2295,34 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
rebind_light = true;
rebind_reflection = true;
rebind_lightmap = true;
if (using_fog) {
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_COLOR_BASE, p_env->fog_color);
Color sun_color_amount = p_env->fog_sun_color;
sun_color_amount.a = p_env->fog_sun_amount;
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_SUN_COLOR_AMOUNT, sun_color_amount);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_TRANSMIT_ENABLED, p_env->fog_transmit_enabled);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_TRANSMIT_CURVE, p_env->fog_transmit_curve);
if (p_env->fog_depth_enabled) {
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_DEPTH_BEGIN, p_env->fog_depth_begin);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_DEPTH_CURVE, p_env->fog_depth_curve);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_MAX_DISTANCE, fog_max_distance);
}
if (p_env->fog_height_enabled) {
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MIN, p_env->fog_height_min);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MAX, p_env->fog_height_max);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_MAX, p_env->fog_height_max);
state.scene_shader.set_uniform(SceneShaderGLES2::FOG_HEIGHT_CURVE, p_env->fog_height_curve);
}
}
}
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse);
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, view_transform_inverse);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, projection_inverse);
@ -2328,6 +2379,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false);
}
void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) {

View file

@ -353,6 +353,21 @@ public:
int canvas_max_layer;
bool fog_enabled;
Color fog_color;
Color fog_sun_color;
float fog_sun_amount;
bool fog_depth_enabled;
float fog_depth_begin;
float fog_depth_curve;
bool fog_transmit_enabled;
float fog_transmit_curve;
bool fog_height_enabled;
float fog_height_min;
float fog_height_max;
float fog_height_curve;
Environment() {
bg_mode = VS::ENV_BG_CLEAR_COLOR;
sky_custom_fov = 0.0;
@ -361,6 +376,24 @@ public:
ambient_energy = 1.0;
ambient_sky_contribution = 0.0;
canvas_max_layer = 0;
fog_enabled = false;
fog_color = Color(0.5, 0.5, 0.5);
fog_sun_color = Color(0.8, 0.8, 0.0);
fog_sun_amount = 0;
fog_depth_enabled = true;
fog_depth_begin = 10;
fog_depth_curve = 1;
fog_transmit_enabled = true;
fog_transmit_curve = 1;
fog_height_enabled = false;
fog_height_min = 0;
fog_height_max = 100;
fog_height_curve = 1;
}
};

View file

@ -379,7 +379,7 @@ void main() {
#endif
mat4 modelview = camera_matrix * world_matrix;
mat4 modelview = camera_inverse_matrix * world_matrix;
float roughness = 1.0;
#define world_transform world_matrix
@ -406,11 +406,11 @@ VERTEX_SHADER_CODE
#endif
#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
vertex = camera_matrix * vertex;
normal = normalize((camera_matrix * vec4(normal, 0.0)).xyz);
vertex = camera_inverse_matrix * vertex;
normal = normalize((camera_inverse_matrix * vec4(normal, 0.0)).xyz);
#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP)
tangent = normalize((camera_matrix * vec4(tangent, 0.0)).xyz);
binormal = normalize((camera_matrix * vec4(binormal, 0.0)).xyz);
tangent = normalize((camera_inverse_matrix * vec4(tangent, 0.0)).xyz);
binormal = normalize((camera_inverse_matrix * vec4(binormal, 0.0)).xyz);
#endif
#endif
@ -816,6 +816,8 @@ uniform float ambient_energy;
varying highp vec3 diffuse_interp;
varying highp vec3 specular_interp;
uniform vec3 light_direction; //may be used by fog, so leave here
#else
//done in fragment
// general for all lights
@ -1296,6 +1298,30 @@ float sample_shadow(
#endif
#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
uniform mediump vec4 fog_color_base;
#ifdef LIGHT_MODE_DIRECTIONAL
uniform mediump vec4 fog_sun_color_amount;
#endif
uniform bool fog_transmit_enabled;
uniform mediump float fog_transmit_curve;
#ifdef FOG_DEPTH_ENABLED
uniform highp float fog_depth_begin;
uniform mediump float fog_depth_curve;
uniform mediump float fog_max_distance;
#endif
#ifdef FOG_HEIGHT_ENABLED
uniform highp float fog_height_min;
uniform highp float fog_height_max;
uniform mediump float fog_height_curve;
#endif
#endif
void main() {
#ifdef RENDER_DEPTH_DUAL_PARABOLOID
@ -1926,5 +1952,45 @@ FRAGMENT_SHADER_CODE
#endif //unshaded
//apply fog
#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
float fog_amount = 0.0;
#ifdef LIGHT_MODE_DIRECTIONAL
vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(eye_position, light_direction), 0.0), 8.0));
#else
vec3 fog_color = fog_color_base.rgb;
#endif
#ifdef FOG_DEPTH_ENABLED
{
float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex));
fog_amount = pow(fog_z, fog_depth_curve);
if (fog_transmit_enabled) {
vec3 total_light = gl_FragColor.rgb;
float transmit = pow(fog_z, fog_transmit_curve);
fog_color = mix(max(total_light, fog_color), fog_color, transmit);
}
}
#endif
#ifdef FOG_HEIGHT_ENABLED
{
float y = (camera_matrix * vec4(vertex, 1.0)).y;
fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve));
}
#endif
gl_FragColor.rgb = mix(gl_FragColor.rgb,fog_color,fog_amount);
#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED)
#endif // not RENDER_DEPTH
}