OverviewFilesCommitsIssuesDocsReleasesPeers

nvidia-rtx-godot / servers / rendering / renderer_rd / shaders / fog_inc.glsl

60 lines · glsl ref:
// Shared fog evaluation used by both rasterized (forward_clustered/mobile) and
// ray-traced paths.  Requires scene_data_inc.glsl to be included first so that
// SceneData and the SCENE_DATA_FLAGS_* defines are available.
//
// Caller must define before including this file:
//   vec3 fog_get_directional_color(uint index)
//   vec3 fog_get_directional_direction(uint index)
//
// Optionally define FOG_HAS_RADIANCE and provide:
//   vec3 fog_sample_radiance(vec3 view_dir, float mip_level)

vec4 fog_process(SceneData scene_data, vec3 vertex) {
	vec3 fog_color = scene_data.fog_light_color;
	bool use_depth_fog = (scene_data.flags & SCENE_DATA_FLAGS_USE_DEPTH_FOG) != 0u;

#ifdef FOG_HAS_RADIANCE
	if (scene_data.fog_aerial_perspective > 0.0) {
		float mip_level = mix(
				1.0 / MAX_ROUGHNESS_LOD, 1.0,
				1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near));
		vec3 sky_fog_color = fog_sample_radiance(vertex, mip_level);
		fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective);
	}
#endif

	if (scene_data.fog_sun_scatter > 0.001) {
		vec3 view = normalize(vertex);
		for (uint i = 0u; i < scene_data.directional_light_count; i++) {
			vec3 light_color = fog_get_directional_color(i);
			vec3 light_dir = fog_get_directional_direction(i);
			float light_amount = pow(max(dot(view, light_dir), 0.0), 8.0);
			fog_color += light_color * light_amount * scene_data.fog_sun_scatter;
		}
	}

	float fog_amount = 0.0;

	if (use_depth_fog) {
		float fog_z = smoothstep(scene_data.fog_depth_begin, scene_data.fog_depth_end, length(vertex));
		fog_amount = pow(fog_z, scene_data.fog_depth_curve) * scene_data.fog_density;
	} else {
		fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density));
	}

	if (abs(scene_data.fog_height_density) >= 0.0001) {
		mat4 inv_view_matrix = transpose(mat4(
				scene_data.inv_view_matrix[0],
				scene_data.inv_view_matrix[1],
				scene_data.inv_view_matrix[2],
				vec4(0.0, 0.0, 0.0, 1.0)));

		float y = (inv_view_matrix * vec4(vertex, 1.0)).y;
		float y_dist = y - scene_data.fog_height;
		float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density));
		fog_amount = max(vfog_amount, fog_amount);
	}

	return vec4(fog_color, fog_amount);
}