godot/servers/rendering/renderer_rd/environment/sky.h

323 lines
11 KiB
C++

/**************************************************************************/
/* sky.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 SKY_RD_H
#define SKY_RD_H
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;
class RenderSceneBuffersRD;
namespace RendererRD {
class SkyRD {
public:
enum SkySet {
SKY_SET_UNIFORMS,
SKY_SET_MATERIAL,
SKY_SET_TEXTURES,
SKY_SET_FOG,
SKY_SET_MAX
};
// Skys need less info from Directional Lights than the normal shaders
struct SkyDirectionalLightData {
float direction[3];
float energy;
float color[3];
float size;
uint32_t enabled;
uint32_t pad[3];
};
private:
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
RID index_array;
enum SkyTextureSetVersion {
SKY_TEXTURE_SET_BACKGROUND,
SKY_TEXTURE_SET_HALF_RES,
SKY_TEXTURE_SET_QUARTER_RES,
SKY_TEXTURE_SET_CUBEMAP,
SKY_TEXTURE_SET_CUBEMAP_HALF_RES,
SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES,
SKY_TEXTURE_SET_MAX
};
enum SkyVersion {
SKY_VERSION_BACKGROUND,
SKY_VERSION_HALF_RES,
SKY_VERSION_QUARTER_RES,
SKY_VERSION_CUBEMAP,
SKY_VERSION_CUBEMAP_HALF_RES,
SKY_VERSION_CUBEMAP_QUARTER_RES,
SKY_VERSION_BACKGROUND_MULTIVIEW,
SKY_VERSION_HALF_RES_MULTIVIEW,
SKY_VERSION_QUARTER_RES_MULTIVIEW,
SKY_VERSION_MAX
};
struct SkyPushConstant {
float orientation[12]; // 48 - 48
float projection[4]; // 16 - 64
float position[3]; // 12 - 76
float time; // 4 - 80
float pad[3]; // 12 - 92
float luminance_multiplier; // 4 - 96
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData {
bool valid = false;
RID version;
PipelineCacheRD pipelines[SKY_VERSION_MAX];
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size = 0;
String code;
bool uses_time = false;
bool uses_position = false;
bool uses_half_res = false;
bool uses_quarter_res = false;
bool uses_light = 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;
SkyShaderData() {}
virtual ~SkyShaderData();
};
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
struct UBO {
float view_inv_projections[RendererSceneRender::MAX_RENDER_VIEWS][16]; // 2 x 64 - 128
float view_eye_offsets[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 160
uint32_t volumetric_fog_enabled; // 4 - 164
float volumetric_fog_inv_length; // 4 - 168
float volumetric_fog_detail_spread; // 4 - 172
float volumetric_fog_sky_affect; // 4 - 176
uint32_t fog_enabled; // 4 - 180
float fog_sky_affect; // 4 - 184
float fog_density; // 4 - 188
float fog_sun_scatter; // 4 - 192
float fog_light_color[3]; // 12 - 204
float fog_aerial_perspective; // 4 - 208
float z_far; // 4 - 212
uint32_t directional_light_count; // 4 - 216
uint32_t pad1; // 4 - 220
uint32_t pad2; // 4 - 224
};
UBO ubo;
uint32_t view_count = 1;
Transform3D cam_transform;
Projection cam_projection;
SkyDirectionalLightData *directional_lights = nullptr;
SkyDirectionalLightData *last_frame_directional_lights = nullptr;
uint32_t max_directional_lights;
uint32_t last_frame_directional_light_count;
RID directional_light_buffer;
RID uniform_set;
RID uniform_buffer;
RID fog_uniform_set;
RID default_fog_uniform_set;
RID fog_shader;
RID fog_material;
RID fog_only_texture_uniform_set;
} sky_scene_state;
struct ReflectionData {
struct Layer {
struct Mipmap {
RID framebuffers[6];
RID views[6];
Size2i size;
};
Vector<Mipmap> mipmaps; //per-face view
Vector<RID> views; // per-cubemap view
};
struct DownsampleLayer {
struct Mipmap {
RID view;
Size2i size;
// for mobile only
RID views[6];
RID framebuffers[6];
};
Vector<Mipmap> mipmaps;
};
RID radiance_base_cubemap; //cubemap for first layer, first cubemap
RID downsampled_radiance_cubemap;
DownsampleLayer downsampled_layer;
RID coefficient_buffer;
bool dirty = true;
Vector<Layer> layers;
void clear_reflection_data();
void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
void create_reflection_fast_filter(bool p_use_arrays);
void create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
void update_reflection_mipmaps(int p_start, int p_end);
};
/* Sky shader */
struct SkyShader {
SkyShaderRD shader;
ShaderCompiler compiler;
RID default_shader;
RID default_material;
RID default_shader_rd;
} sky_shader;
struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData {
SkyShaderData *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 ~SkyMaterialData();
};
struct Sky {
RID radiance;
RID quarter_res_pass;
RID quarter_res_framebuffer;
Size2i screen_size;
RID uniform_set;
RID material;
RID uniform_buffer;
int radiance_size = 256;
RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC;
ReflectionData reflection;
bool dirty = false;
int processing_layer = 0;
Sky *dirty_list = nullptr;
float baked_exposure = 1.0;
//State to track when radiance cubemap needs updating
SkyMaterialData *prev_material = nullptr;
Vector3 prev_position;
float prev_time;
void free();
RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers);
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
Ref<Image> bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size);
};
uint32_t sky_ggx_samples_quality;
bool sky_use_cubemap_array;
Sky *dirty_sky_list = nullptr;
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func();
static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs();
RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
SkyRD();
void init();
void set_texture_format(RD::DataFormat p_texture_format);
~SkyRD();
void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0);
void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0);
void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
RID sky_get_material(RID p_sky) const;
RID sky_get_radiance_texture_rd(RID p_sky) const;
float sky_get_baked_exposure(RID p_sky) const;
RID allocate_sky_rid();
void initialize_sky_rid(RID p_rid);
Sky *get_sky(RID p_sky) const;
void free_sky(RID p_sky);
void sky_set_radiance_size(RID p_sky, int p_radiance_size);
void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
void sky_set_material(RID p_sky, RID p_material);
Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
};
} // namespace RendererRD
#endif // SKY_RD_H