Skip to content

Commit

Permalink
Merge pull request #45731 from reduz/reprojected-volumetric-fog
Browse files Browse the repository at this point in the history
Added temporal reprojection to Volumetric Fog
  • Loading branch information
reduz committed Feb 5, 2021
2 parents 80a4d0f + 7997544 commit b7e1014
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 15 deletions.
25 changes: 24 additions & 1 deletion scene/resources/environment.cpp
Expand Up @@ -797,7 +797,7 @@ void Environment::_update_fog() {
// Volumetric Fog

void Environment::_update_volumetric_fog() {
RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_light, volumetric_fog_light_energy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, RS::EnvVolumetricFogShadowFilter(volumetric_fog_shadow_filter));
RS::get_singleton()->environment_set_volumetric_fog(environment, volumetric_fog_enabled, volumetric_fog_density, volumetric_fog_light, volumetric_fog_light_energy, volumetric_fog_length, volumetric_fog_detail_spread, volumetric_fog_gi_inject, RS::EnvVolumetricFogShadowFilter(volumetric_fog_shadow_filter), volumetric_fog_temporal_reproject, volumetric_fog_temporal_reproject_amount);
}

void Environment::set_volumetric_fog_enabled(bool p_enable) {
Expand Down Expand Up @@ -854,6 +854,22 @@ float Environment::get_volumetric_fog_gi_inject() const {
return volumetric_fog_gi_inject;
}

void Environment::set_volumetric_fog_temporal_reprojection_enabled(bool p_enable) {
volumetric_fog_temporal_reproject = p_enable;
_update_volumetric_fog();
}
bool Environment::is_volumetric_fog_temporal_reprojection_enabled() const {
return volumetric_fog_temporal_reproject;
}
void Environment::set_volumetric_fog_temporal_reprojection_amount(float p_amount) {
volumetric_fog_temporal_reproject_amount = p_amount;
_update_volumetric_fog();
}

float Environment::get_volumetric_fog_temporal_reprojection_amount() const {
return volumetric_fog_temporal_reproject_amount;
}

void Environment::set_volumetric_fog_shadow_filter(VolumetricFogShadowFilter p_filter) {
volumetric_fog_shadow_filter = p_filter;
_update_volumetric_fog();
Expand Down Expand Up @@ -1319,6 +1335,10 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_volumetric_fog_gi_inject"), &Environment::get_volumetric_fog_gi_inject);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_shadow_filter", "shadow_filter"), &Environment::set_volumetric_fog_shadow_filter);
ClassDB::bind_method(D_METHOD("get_volumetric_fog_shadow_filter"), &Environment::get_volumetric_fog_shadow_filter);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_enabled", "enabled"), &Environment::set_volumetric_fog_temporal_reprojection_enabled);
ClassDB::bind_method(D_METHOD("is_volumetric_fog_temporal_reprojection_enabled"), &Environment::is_volumetric_fog_temporal_reprojection_enabled);
ClassDB::bind_method(D_METHOD("set_volumetric_fog_temporal_reprojection_amount", "temporal_reprojection_amount"), &Environment::set_volumetric_fog_temporal_reprojection_amount);
ClassDB::bind_method(D_METHOD("get_volumetric_fog_temporal_reprojection_amount"), &Environment::get_volumetric_fog_temporal_reprojection_amount);

ADD_GROUP("Volumetric Fog", "volumetric_fog_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_enabled"), "set_volumetric_fog_enabled", "is_volumetric_fog_enabled");
Expand All @@ -1329,6 +1349,9 @@ void Environment::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_length", PROPERTY_HINT_RANGE, "0,1024,0.01,or_greater"), "set_volumetric_fog_length", "get_volumetric_fog_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_detail_spread", PROPERTY_HINT_EXP_EASING, "0.01,16,0.01"), "set_volumetric_fog_detail_spread", "get_volumetric_fog_detail_spread");
ADD_PROPERTY(PropertyInfo(Variant::INT, "volumetric_fog_shadow_filter", PROPERTY_HINT_ENUM, "Disabled,Low,Medium,High"), "set_volumetric_fog_shadow_filter", "get_volumetric_fog_shadow_filter");
ADD_SUBGROUP("Temporal Reprojection", "volumetric_fog_temporal_reprojection_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "volumetric_fog_temporal_reprojection_enabled"), "set_volumetric_fog_temporal_reprojection_enabled", "is_volumetric_fog_temporal_reprojection_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "volumetric_fog_temporal_reprojection_amount", PROPERTY_HINT_RANGE, "0.0,0.999,0.001"), "set_volumetric_fog_temporal_reprojection_amount", "get_volumetric_fog_temporal_reprojection_amount");

// Adjustment

Expand Down
6 changes: 6 additions & 0 deletions scene/resources/environment.h
Expand Up @@ -198,6 +198,8 @@ class Environment : public Resource {
float volumetric_fog_detail_spread = 2.0;
VolumetricFogShadowFilter volumetric_fog_shadow_filter = VOLUMETRIC_FOG_SHADOW_FILTER_LOW;
float volumetric_fog_gi_inject = 0.0;
bool volumetric_fog_temporal_reproject = false;
float volumetric_fog_temporal_reproject_amount = 0.95;
void _update_volumetric_fog();

// Adjustment
Expand Down Expand Up @@ -389,6 +391,10 @@ class Environment : public Resource {
VolumetricFogShadowFilter get_volumetric_fog_shadow_filter() const;
void set_volumetric_fog_gi_inject(float p_gi_inject);
float get_volumetric_fog_gi_inject() const;
void set_volumetric_fog_temporal_reprojection_enabled(bool p_enable);
bool is_volumetric_fog_temporal_reprojection_enabled() const;
void set_volumetric_fog_temporal_reprojection_amount(float p_amount);
float get_volumetric_fog_temporal_reprojection_amount() const;

// Adjustment
void set_adjustment_enabled(bool p_enabled);
Expand Down
37 changes: 33 additions & 4 deletions servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
Expand Up @@ -3151,7 +3151,7 @@ float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) c
return env->fog_aerial_perspective;
}

void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter) {
void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter, bool p_temporal_reprojection, float p_temporal_reprojection_amount) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);

Expand All @@ -3167,6 +3167,8 @@ void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_ena
env->volumetric_fog_detail_spread = p_detail_spread;
env->volumetric_fog_shadow_filter = p_shadow_filter;
env->volumetric_fog_gi_inject = p_gi_inject;
env->volumetric_fog_temporal_reprojection = p_temporal_reprojection;
env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
}

void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
Expand Down Expand Up @@ -6796,6 +6798,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
ERR_FAIL_COND(!rb->volumetric_fog);

RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
RD::get_singleton()->free(rb->volumetric_fog->fog_map);

Expand Down Expand Up @@ -6897,11 +6900,16 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
tf.height = target_height;
tf.depth = volumetric_fog_depth;
tf.texture_type = RD::TEXTURE_TYPE_3D;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;

rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());

tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;

rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);

tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;

rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
_render_buffers_uniform_set_changed(p_render_buffers);
Expand Down Expand Up @@ -7211,6 +7219,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
u.ids.push_back(volumetric_fog.params_ubo);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 15;
u.ids.push_back(rb->volumetric_fog->prev_light_density_map);
uniforms.push_back(u);
}

rb->volumetric_fog->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, 0), 0);

Expand Down Expand Up @@ -7312,6 +7327,13 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
params.cam_rotation[11] = 0;
params.filter_axis = 0;
params.max_gi_probes = env->volumetric_fog_gi_inject > 0.001 ? p_gi_probe_count : 0;
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;

Transform to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform;
storage->store_transform(to_prev_cam_view, params.to_prev_view);

params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;

{
uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
Expand Down Expand Up @@ -7351,7 +7373,12 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);

RD::get_singleton()->draw_command_end_label();
RD::get_singleton()->compute_list_add_barrier(compute_list);

RD::get_singleton()->compute_list_end();

RD::get_singleton()->texture_copy(rb->volumetric_fog->light_density_map, rb->volumetric_fog->prev_light_density_map, Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), 0, 0, 0, 0);

compute_list = RD::get_singleton()->compute_list_begin();

if (use_filter) {
RD::get_singleton()->draw_command_begin_label("Filter Fog");
Expand Down Expand Up @@ -7392,6 +7419,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e

RENDER_TIMESTAMP("<Volumetric Fog");
RD::get_singleton()->draw_command_end_label();

rb->volumetric_fog->prev_cam_transform = p_cam_transform;
}

uint32_t RendererSceneRenderRD::_get_render_state_directional_light_count() const {
Expand Down
17 changes: 15 additions & 2 deletions servers/rendering/renderer_rd/renderer_scene_render_rd.h
Expand Up @@ -745,6 +745,8 @@ class RendererSceneRenderRD : public RendererSceneRender {
float volumetric_fog_detail_spread = 2.0;
RS::EnvVolumetricFogShadowFilter volumetric_fog_shadow_filter = RS::ENV_VOLUMETRIC_FOG_SHADOW_FILTER_LOW;
float volumetric_fog_gi_inject = 0.0;
bool volumetric_fog_temporal_reprojection = false;
float volumetric_fog_temporal_reprojection_amount = 0.95;

/// Glow

Expand Down Expand Up @@ -1515,6 +1517,10 @@ class RendererSceneRenderRD : public RendererSceneRender {
} render_state;

struct VolumetricFog {
enum {
MAX_TEMPORAL_FRAMES = 16
};

uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 0;
Expand All @@ -1523,13 +1529,17 @@ class RendererSceneRenderRD : public RendererSceneRender {
float spread;

RID light_density_map;
RID prev_light_density_map;

RID fog_map;
RID uniform_set;
RID uniform_set2;
RID sdfgi_uniform_set;
RID sky_uniform_set;

int last_shadow_filter = -1;

Transform prev_cam_transform;
};

enum {
Expand Down Expand Up @@ -1565,10 +1575,13 @@ class RendererSceneRenderRD : public RendererSceneRender {
uint32_t cluster_shift;
uint32_t cluster_width;

uint32_t cluster_pad[3];
uint32_t max_cluster_element_count_div_32;
uint32_t use_temporal_reprojection;
uint32_t temporal_frame;
float temporal_blend;

float cam_rotation[12];
float to_prev_view[16];
};

VolumetricFogShaderRD shader;
Expand Down Expand Up @@ -1708,7 +1721,7 @@ class RendererSceneRenderRD : public RendererSceneRender {
float environment_get_fog_height_density(RID p_env) const;
float environment_get_fog_aerial_perspective(RID p_env) const;

void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter);
void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter, bool p_temporal_reprojection, float p_temporal_reprojection_amount);

virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth);
virtual void environment_set_volumetric_fog_filter_active(bool p_enable);
Expand Down
72 changes: 70 additions & 2 deletions servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
Expand Up @@ -168,13 +168,18 @@ layout(set = 0, binding = 14, std140) uniform Params {
uint cluster_shift;
uint cluster_width;

uvec3 cluster_pad;
uint max_cluster_element_count_div_32;
bool use_temporal_reprojection;
uint temporal_frame;
float temporal_blend;

mat3x4 cam_rotation;
mat4 to_prev_view;
}
params;

layout(set = 0, binding = 15) uniform texture3D prev_density_texture;

float get_depth_at_pos(float cell_depth_size, int z) {
float d = float(z) * cell_depth_size + cell_depth_size * 0.5; //center of voxels
d = pow(d, params.detail_spread);
Expand Down Expand Up @@ -213,6 +218,26 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) {
return bitfieldInsert(uint(0), uint(0xFFFFFFFF), local_min, mask_width);
}

#define TEMPORAL_FRAMES 16

const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
vec3(0.5, 0.33333333, 0.2),
vec3(0.25, 0.66666667, 0.4),
vec3(0.75, 0.11111111, 0.6),
vec3(0.125, 0.44444444, 0.8),
vec3(0.625, 0.77777778, 0.04),
vec3(0.375, 0.22222222, 0.24),
vec3(0.875, 0.55555556, 0.44),
vec3(0.0625, 0.88888889, 0.64),
vec3(0.5625, 0.03703704, 0.84),
vec3(0.3125, 0.37037037, 0.08),
vec3(0.8125, 0.7037037, 0.28),
vec3(0.1875, 0.14814815, 0.48),
vec3(0.6875, 0.48148148, 0.68),
vec3(0.4375, 0.81481481, 0.88),
vec3(0.9375, 0.25925926, 0.12),
vec3(0.03125, 0.59259259, 0.32));

void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);

Expand Down Expand Up @@ -241,6 +266,45 @@ void main() {
view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;

vec4 reprojected_density = vec4(0.0);
float reproject_amount = 0.0;

if (params.use_temporal_reprojection) {
vec3 prev_view = (params.to_prev_view * vec4(view_pos, 1.0)).xyz;
//undo transform into prev view
prev_view.y = -prev_view.y;
//z back to unit size
prev_view.z /= -params.fog_frustum_end;
//xy back to unit size
prev_view.xy /= mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(prev_view.z));
prev_view.xy = prev_view.xy * 0.5 + 0.5;
//z back to unspread value
prev_view.z = pow(prev_view.z, 1.0 / params.detail_spread);

if (all(greaterThan(prev_view, vec3(0.0))) && all(lessThan(prev_view, vec3(1.0)))) {
//reprojectinon fits

reprojected_density = textureLod(sampler3D(prev_density_texture, linear_sampler), prev_view, 0.0);
reproject_amount = params.temporal_blend;

// Since we can reproject, now we must jitter the current view pos.
// This is done here because cells that can't reproject should not jitter.

fog_unit_pos = posf * fog_cell_size + fog_cell_size * halton_map[params.temporal_frame]; //center of voxels, offset by halton table

screen_pos = uvec2(fog_unit_pos.xy * params.screen_size);
cluster_pos = screen_pos >> params.cluster_shift;
cluster_offset = (params.cluster_width * cluster_pos.y + cluster_pos.x) * (params.max_cluster_element_count_div_32 + 32);
//positions in screen are too spread apart, no hopes for optimizing with subgroups

fog_unit_pos.z = pow(fog_unit_pos.z, params.detail_spread);

view_pos.xy = (fog_unit_pos.xy * 2.0 - 1.0) * mix(params.fog_frustum_size_begin, params.fog_frustum_size_end, vec2(fog_unit_pos.z));
view_pos.z = -params.fog_frustum_end * fog_unit_pos.z;
view_pos.y = -view_pos.y;
}
}

uint cluster_z = uint(clamp((abs(view_pos.z) / params.z_far) * 32.0, 0.0, 31.0));

vec3 total_light = params.light_color;
Expand Down Expand Up @@ -565,7 +629,11 @@ void main() {

#endif

imageStore(density_map, pos, vec4(total_light, total_density));
vec4 final_density = vec4(total_light, total_density);

final_density = mix(final_density, reprojected_density, reproject_amount);

imageStore(density_map, pos, final_density);
#endif

#ifdef MODE_FOG
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/renderer_scene.h
Expand Up @@ -122,7 +122,7 @@ class RendererScene {
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;

virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;

virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/renderer_scene_cull.h
Expand Up @@ -991,7 +991,7 @@ class RendererSceneCull : public RendererScene {
PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)

PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
PASS9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, RS::EnvVolumetricFogShadowFilter)
PASS11(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, RS::EnvVolumetricFogShadowFilter, bool, float)

PASS2(environment_set_volumetric_fog_volume_size, int, int)
PASS1(environment_set_volumetric_fog_filter_active, bool)
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/renderer_scene_render.h
Expand Up @@ -117,7 +117,7 @@ class RendererSceneRender {
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;

virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter) = 0;
virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter, bool p_temporal_reprojection, float p_temporal_reprojection_amount) = 0;

virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/rendering_server_default.h
Expand Up @@ -615,7 +615,7 @@ class RenderingServerDefault : public RenderingServer {
BIND7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)

BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter)
BIND11(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter, bool, float)

BIND2(environment_set_volumetric_fog_volume_size, int, int)
BIND1(environment_set_volumetric_fog_filter_active, bool)
Expand Down
2 changes: 1 addition & 1 deletion servers/rendering/rendering_server_wrap_mt.h
Expand Up @@ -520,7 +520,7 @@ class RenderingServerWrapMT : public RenderingServer {

FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)

FUNC9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter)
FUNC11(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter, bool, float)

FUNC2(environment_set_volumetric_fog_volume_size, int, int)
FUNC1(environment_set_volumetric_fog_filter_active, bool)
Expand Down

0 comments on commit b7e1014

Please sign in to comment.