瀏覽代碼

Implemented FOG support in GLES2.

Juan Linietsky 7 年之前
父節點
當前提交
11f088279d
共有 3 個文件被更改,包括 160 次插入8 次删除
  1. 56 3
      drivers/gles2/rasterizer_scene_gles2.cpp
  2. 33 0
      drivers/gles2/rasterizer_scene_gles2.h
  3. 71 5
      drivers/gles2/shaders/scene.glsl

+ 56 - 3
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -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) {
 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);
 	Environment *env = environment_owner.getornull(p_env);
 	ERR_FAIL_COND(!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) {
 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);
 	Environment *env = environment_owner.getornull(p_env);
 	ERR_FAIL_COND(!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) {
 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);
 	Environment *env = environment_owner.getornull(p_env);
 	ERR_FAIL_COND(!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) {
 bool RasterizerSceneGLES2::is_environment(RID p_env) {
 	return environment_owner.owns(p_env);
 	return environment_owner.owns(p_env);
 }
 }
@@ -2031,6 +2049,15 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 		glDisable(GL_BLEND);
 		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;
 	RasterizerStorageGLES2::Texture *prev_lightmap = NULL;
 	float lightmap_energy = 1.0;
 	float lightmap_energy = 1.0;
 	bool prev_use_lightmap_capture = false;
 	bool prev_use_lightmap_capture = false;
@@ -2268,10 +2295,34 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 				rebind_light = true;
 				rebind_light = true;
 				rebind_reflection = true;
 				rebind_reflection = true;
 				rebind_lightmap = 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_MATRIX, p_projection);
 			state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, projection_inverse);
 			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_REFLECTION_PROBE2, false);
 	state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, 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::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) {
 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) {

+ 33 - 0
drivers/gles2/rasterizer_scene_gles2.h

@@ -353,6 +353,21 @@ public:
 
 
 		int canvas_max_layer;
 		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() {
 		Environment() {
 			bg_mode = VS::ENV_BG_CLEAR_COLOR;
 			bg_mode = VS::ENV_BG_CLEAR_COLOR;
 			sky_custom_fov = 0.0;
 			sky_custom_fov = 0.0;
@@ -361,6 +376,24 @@ public:
 			ambient_energy = 1.0;
 			ambient_energy = 1.0;
 			ambient_sky_contribution = 0.0;
 			ambient_sky_contribution = 0.0;
 			canvas_max_layer = 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;
 		}
 		}
 	};
 	};
 
 

+ 71 - 5
drivers/gles2/shaders/scene.glsl

@@ -379,7 +379,7 @@ void main() {
 
 
 #endif
 #endif
 
 
-	mat4 modelview = camera_matrix * world_matrix;
+	mat4 modelview = camera_inverse_matrix * world_matrix;
 	float roughness = 1.0;
 	float roughness = 1.0;
 
 
 #define world_transform world_matrix
 #define world_transform world_matrix
@@ -406,11 +406,11 @@ VERTEX_SHADER_CODE
 #endif
 #endif
 
 
 #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED)
 #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)
 #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
 #endif
 #endif
 
 
@@ -816,6 +816,8 @@ uniform float ambient_energy;
 varying highp vec3 diffuse_interp;
 varying highp vec3 diffuse_interp;
 varying highp vec3 specular_interp;
 varying highp vec3 specular_interp;
 
 
+uniform vec3 light_direction; //may be used by fog, so leave here
+
 #else
 #else
 //done in fragment
 //done in fragment
 // general for all lights
 // general for all lights
@@ -1296,6 +1298,30 @@ float sample_shadow(
 
 
 #endif
 #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() {
 void main() {
 
 
 #ifdef RENDER_DEPTH_DUAL_PARABOLOID
 #ifdef RENDER_DEPTH_DUAL_PARABOLOID
@@ -1926,5 +1952,45 @@ FRAGMENT_SHADER_CODE
 
 
 #endif //unshaded
 #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
 #endif // not RENDER_DEPTH
 }
 }