360 lines
11 KiB
C++
360 lines
11 KiB
C++
/**************************************************************************/
|
|
/* fog.h */
|
|
/**************************************************************************/
|
|
/* This file is part of: */
|
|
/* GODOT ENGINE */
|
|
/* https://godotengine.org */
|
|
/**************************************************************************/
|
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
|
/* */
|
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
/* a copy of this software and associated documentation files (the */
|
|
/* "Software"), to deal in the Software without restriction, including */
|
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
/* the following conditions: */
|
|
/* */
|
|
/* The above copyright notice and this permission notice shall be */
|
|
/* included in all copies or substantial portions of the Software. */
|
|
/* */
|
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/**************************************************************************/
|
|
|
|
#ifndef FOG_RD_H
|
|
#define FOG_RD_H
|
|
|
|
#include "core/templates/local_vector.h"
|
|
#include "core/templates/rid_owner.h"
|
|
#include "servers/rendering/environment/renderer_fog.h"
|
|
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
|
#include "servers/rendering/renderer_rd/environment/gi.h"
|
|
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
|
|
#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
|
|
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
|
|
#include "servers/rendering/storage/utilities.h"
|
|
|
|
#define RB_SCOPE_FOG SNAME("Fog")
|
|
|
|
namespace RendererRD {
|
|
|
|
class Fog : public RendererFog {
|
|
private:
|
|
static Fog *singleton;
|
|
|
|
/* FOG VOLUMES */
|
|
|
|
struct FogVolume {
|
|
RID material;
|
|
Vector3 size = Vector3(2, 2, 2);
|
|
|
|
RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
|
|
|
|
Dependency dependency;
|
|
};
|
|
|
|
mutable RID_Owner<FogVolume, true> fog_volume_owner;
|
|
|
|
struct FogVolumeInstance {
|
|
RID volume;
|
|
Transform3D transform;
|
|
bool active = false;
|
|
};
|
|
|
|
mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
|
|
|
|
const int SAMPLERS_BINDING_FIRST_INDEX = 3;
|
|
|
|
/* Volumetric Fog */
|
|
struct VolumetricFogShader {
|
|
enum FogSet {
|
|
FOG_SET_BASE,
|
|
FOG_SET_UNIFORMS,
|
|
FOG_SET_MATERIAL,
|
|
FOG_SET_MAX,
|
|
};
|
|
|
|
struct FogPushConstant {
|
|
float position[3];
|
|
float pad;
|
|
|
|
float size[3];
|
|
float pad2;
|
|
|
|
int32_t corner[3];
|
|
uint32_t shape;
|
|
|
|
float transform[16];
|
|
};
|
|
|
|
struct VolumeUBO {
|
|
float fog_frustum_size_begin[2];
|
|
float fog_frustum_size_end[2];
|
|
|
|
float fog_frustum_end;
|
|
float z_near;
|
|
float z_far;
|
|
float time;
|
|
|
|
int32_t fog_volume_size[3];
|
|
uint32_t directional_light_count;
|
|
|
|
uint32_t use_temporal_reprojection;
|
|
uint32_t temporal_frame;
|
|
float detail_spread;
|
|
float temporal_blend;
|
|
|
|
float to_prev_view[16];
|
|
float transform[16];
|
|
};
|
|
|
|
ShaderCompiler compiler;
|
|
VolumetricFogShaderRD shader;
|
|
RID volume_ubo;
|
|
|
|
RID default_shader;
|
|
RID default_material;
|
|
RID default_shader_rd;
|
|
|
|
RID base_uniform_set;
|
|
|
|
RID params_ubo;
|
|
|
|
enum {
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
|
|
VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
|
|
};
|
|
|
|
struct ParamsUBO {
|
|
float fog_frustum_size_begin[2];
|
|
float fog_frustum_size_end[2];
|
|
|
|
float fog_frustum_end;
|
|
float ambient_inject;
|
|
float z_far;
|
|
uint32_t filter_axis;
|
|
|
|
float ambient_color[3];
|
|
float sky_contribution;
|
|
|
|
int32_t fog_volume_size[3];
|
|
uint32_t directional_light_count;
|
|
|
|
float base_emission[3];
|
|
float base_density;
|
|
|
|
float base_scattering[3];
|
|
float phase_g;
|
|
|
|
float detail_spread;
|
|
float gi_inject;
|
|
uint32_t max_voxel_gi_instances;
|
|
uint32_t cluster_type_size;
|
|
|
|
float screen_size[2];
|
|
uint32_t cluster_shift;
|
|
uint32_t cluster_width;
|
|
|
|
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];
|
|
float radiance_inverse_xform[12];
|
|
};
|
|
|
|
VolumetricFogProcessShaderRD process_shader;
|
|
|
|
RID process_shader_version;
|
|
RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
|
|
|
|
} volumetric_fog;
|
|
|
|
Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
|
|
|
|
struct FogShaderData : public RendererRD::MaterialStorage::ShaderData {
|
|
bool valid = false;
|
|
RID version;
|
|
|
|
RID pipeline;
|
|
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
|
|
|
Vector<uint32_t> ubo_offsets;
|
|
uint32_t ubo_size = 0;
|
|
|
|
String code;
|
|
|
|
bool uses_time = false;
|
|
|
|
virtual void set_code(const String &p_Code);
|
|
virtual bool is_animated() const;
|
|
virtual bool casts_shadows() const;
|
|
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
|
|
|
FogShaderData() {}
|
|
virtual ~FogShaderData();
|
|
};
|
|
|
|
struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData {
|
|
FogShaderData *shader_data = nullptr;
|
|
RID uniform_set;
|
|
bool uniform_set_updated;
|
|
|
|
virtual void set_render_priority(int p_priority) {}
|
|
virtual void set_next_pass(RID p_pass) {}
|
|
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
|
virtual ~FogMaterialData();
|
|
};
|
|
|
|
RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func();
|
|
static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs();
|
|
|
|
RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
|
|
static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
|
|
|
|
public:
|
|
static Fog *get_singleton() { return singleton; }
|
|
|
|
Fog();
|
|
~Fog();
|
|
|
|
/* FOG VOLUMES */
|
|
|
|
bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
|
|
|
|
virtual RID fog_volume_allocate() override;
|
|
virtual void fog_volume_initialize(RID p_rid) override;
|
|
virtual void fog_volume_free(RID p_rid) override;
|
|
Dependency *fog_volume_get_dependency(RID p_fog_volume) const;
|
|
|
|
virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
|
|
virtual void fog_volume_set_size(RID p_fog_volume, const Vector3 &p_size) override;
|
|
virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
|
|
virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
|
|
RID fog_volume_get_material(RID p_fog_volume) const;
|
|
virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
|
|
Vector3 fog_volume_get_size(RID p_fog_volume) const;
|
|
|
|
/* FOG VOLUMES INSTANCE */
|
|
|
|
bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
|
|
|
|
RID fog_volume_instance_create(RID p_fog_volume);
|
|
void fog_instance_free(RID p_rid);
|
|
|
|
void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
|
|
Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
|
|
ERR_FAIL_NULL(fvi);
|
|
fvi->transform = p_transform;
|
|
}
|
|
|
|
void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
|
|
Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
|
|
ERR_FAIL_NULL(fvi);
|
|
fvi->active = p_active;
|
|
}
|
|
|
|
RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
|
|
Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
|
|
ERR_FAIL_NULL_V(fvi, RID());
|
|
return fvi->volume;
|
|
}
|
|
|
|
Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const {
|
|
Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
|
|
ERR_FAIL_NULL_V(fvi, Vector3());
|
|
return fvi->transform.get_origin();
|
|
}
|
|
|
|
/* Volumetric FOG */
|
|
class VolumetricFog : public RenderBufferCustomDataRD {
|
|
GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
|
|
|
|
public:
|
|
enum {
|
|
MAX_TEMPORAL_FRAMES = 16
|
|
};
|
|
|
|
uint32_t width = 0;
|
|
uint32_t height = 0;
|
|
uint32_t depth = 0;
|
|
|
|
float length;
|
|
float spread;
|
|
|
|
RID light_density_map;
|
|
RID prev_light_density_map;
|
|
RID fog_map;
|
|
RID density_map;
|
|
RID light_map;
|
|
RID emissive_map;
|
|
|
|
RID fog_uniform_set;
|
|
RID copy_uniform_set;
|
|
|
|
struct {
|
|
RID process_uniform_set_density;
|
|
RID process_uniform_set;
|
|
RID process_uniform_set2;
|
|
} gi_dependent_sets;
|
|
|
|
RID sdfgi_uniform_set;
|
|
RID sky_uniform_set;
|
|
|
|
int last_shadow_filter = -1;
|
|
|
|
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
|
virtual void free_data() override{};
|
|
|
|
bool sync_gi_dependent_sets_validity(bool p_ensure_freed = false);
|
|
|
|
void init(const Vector3i &fog_size, RID p_sky_shader);
|
|
~VolumetricFog();
|
|
};
|
|
|
|
void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array);
|
|
void free_fog_shader();
|
|
|
|
struct VolumetricFogSettings {
|
|
Vector2i rb_size;
|
|
double time;
|
|
bool is_using_radiance_cubemap_array;
|
|
uint32_t max_cluster_elements;
|
|
bool volumetric_fog_filter_active;
|
|
RID shadow_sampler;
|
|
RID voxel_gi_buffer;
|
|
RID shadow_atlas_depth;
|
|
RID omni_light_buffer;
|
|
RID spot_light_buffer;
|
|
RID directional_shadow_depth;
|
|
RID directional_light_buffer;
|
|
|
|
// Objects related to our render buffer
|
|
Ref<VolumetricFog> vfog;
|
|
ClusterBuilderRD *cluster_builder;
|
|
GI *gi;
|
|
Ref<GI::SDFGI> sdfgi;
|
|
Ref<GI::RenderBuffersGI> rbgi;
|
|
RID env;
|
|
SkyRD *sky;
|
|
};
|
|
void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
|
|
};
|
|
|
|
} // namespace RendererRD
|
|
|
|
#endif // FOG_RD_H
|