diff options
Diffstat (limited to 'drivers/gles3/rasterizer_scene_gles3.h')
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 517 |
1 files changed, 485 insertions, 32 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index ed529beb25..d9a848c0f6 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -34,6 +34,7 @@ #ifdef GLES3_ENABLED #include "core/math/camera_matrix.h" +#include "core/templates/paged_allocator.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "rasterizer_storage_gles3.h" @@ -42,15 +43,60 @@ #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" #include "shader_gles3.h" +#include "shaders/cubemap_filter.glsl.gen.h" #include "shaders/sky.glsl.gen.h" -// Copied from renderer_scene_render_rd +enum RenderListType { + RENDER_LIST_OPAQUE, //used for opaque objects + RENDER_LIST_ALPHA, //used for transparent objects + RENDER_LIST_SECONDARY, //used for shadows and other objects + RENDER_LIST_MAX +}; + +enum PassMode { + PASS_MODE_COLOR, + PASS_MODE_COLOR_TRANSPARENT, + PASS_MODE_COLOR_ADDITIVE, + PASS_MODE_SHADOW, + PASS_MODE_DEPTH, +}; + +// These should share as much as possible with SkyUniform Location +enum SceneUniformLocation { + SCENE_TONEMAP_UNIFORM_LOCATION, + SCENE_GLOBALS_UNIFORM_LOCATION, + SCENE_DATA_UNIFORM_LOCATION, + SCENE_MATERIAL_UNIFORM_LOCATION, + SCENE_EMPTY, // Unused, put here to avoid conflicts with SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION. + SCENE_OMNILIGHT_UNIFORM_LOCATION, + SCENE_SPOTLIGHT_UNIFORM_LOCATION, + SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, +}; + +enum SkyUniformLocation { + SKY_TONEMAP_UNIFORM_LOCATION, + SKY_GLOBALS_UNIFORM_LOCATION, + SKY_EMPTY, // Unused, put here to avoid conflicts with SCENE_DATA_UNIFORM_LOCATION. + SKY_MATERIAL_UNIFORM_LOCATION, + SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION, +}; + +enum { + SPEC_CONSTANT_DISABLE_LIGHTMAP = 0, + SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 1, + SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 2, + SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 3, + SPEC_CONSTANT_DISABLE_FOG = 4, +}; + struct RenderDataGLES3 { RID render_buffers = RID(); + bool transparent_bg = false; Transform3D cam_transform = Transform3D(); + Transform3D inv_cam_transform = Transform3D(); CameraMatrix cam_projection = CameraMatrix(); - bool cam_ortogonal = false; + bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; @@ -62,14 +108,8 @@ struct RenderDataGLES3 { const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr; const PagedArray<RID> *lights = nullptr; const PagedArray<RID> *reflection_probes = nullptr; - //const PagedArray<RID> *voxel_gi_instances = nullptr; - //const PagedArray<RID> *decals = nullptr; - //const PagedArray<RID> *lightmaps = nullptr; - //const PagedArray<RID> *fog_volumes = nullptr; RID environment = RID(); RID camera_effects = RID(); - RID shadow_atlas = RID(); - RID reflection_atlas = RID(); RID reflection_probe = RID(); int reflection_probe_pass = 0; @@ -78,6 +118,8 @@ struct RenderDataGLES3 { float screen_mesh_lod_threshold = 0.0; uint32_t directional_light_count = 0; + uint32_t spot_light_count = 0; + uint32_t omni_light_count = 0; RendererScene::RenderInfo *render_info = nullptr; }; @@ -91,16 +133,388 @@ private: RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; uint64_t scene_pass = 0; - /* Sky */ - struct SkyGlobals { - RID shader_current_version; + template <class T> + struct InstanceSort { + float depth; + T *instance = nullptr; + bool operator<(const InstanceSort &p_sort) const { + return depth < p_sort.depth; + } + }; + + struct SceneGlobals { RID shader_default_version; RID default_material; RID default_shader; - uint32_t max_directional_lights = 4; - uint32_t roughness_layers = 8; - uint32_t ggx_samples = 128; - } sky_globals; + RID cubemap_filter_shader_version; + } scene_globals; + + /* LIGHT INSTANCE */ + + struct LightData { + float position[3]; + float inv_radius; + + float direction[3]; // Only used by SpotLight + float size; + + float color[3]; + float attenuation; + + float inv_spot_attenuation; + float cos_spot_angle; + float specular_amount; + uint32_t shadow_enabled; + }; + static_assert(sizeof(LightData) % 16 == 0, "LightData size must be a multiple of 16 bytes"); + + struct DirectionalLightData { + float direction[3]; + float energy; + + float color[3]; + float size; + + uint32_t enabled; // For use by SkyShaders + float pad[2]; + float specular; + }; + static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes"); + + struct LightInstance { + RS::LightType light_type = RS::LIGHT_DIRECTIONAL; + + AABB aabb; + RID self; + RID light; + Transform3D transform; + + Vector3 light_vector; + Vector3 spot_vector; + float linear_att = 0.0; + + uint64_t shadow_pass = 0; + uint64_t last_scene_pass = 0; + uint64_t last_scene_shadow_pass = 0; + uint64_t last_pass = 0; + uint32_t cull_mask = 0; + uint32_t light_directional_index = 0; + + Rect2 directional_rect; + + uint32_t gl_id = -1; + + LightInstance() {} + }; + + mutable RID_Owner<LightInstance> light_instance_owner; + + struct GeometryInstanceGLES3; + + // Cached data for drawing surfaces + struct GeometryInstanceSurface { + enum { + FLAG_PASS_DEPTH = 1, + FLAG_PASS_OPAQUE = 2, + FLAG_PASS_ALPHA = 4, + FLAG_PASS_SHADOW = 8, + FLAG_USES_SHARED_SHADOW_MATERIAL = 128, + FLAG_USES_SCREEN_TEXTURE = 2048, + FLAG_USES_DEPTH_TEXTURE = 4096, + FLAG_USES_NORMAL_TEXTURE = 8192, + FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384, + }; + + union { + struct { + uint64_t lod_index : 8; + uint64_t surface_index : 8; + uint64_t geometry_id : 32; + uint64_t material_id_low : 16; + + uint64_t material_id_hi : 16; + uint64_t shader_id : 32; + uint64_t uses_softshadow : 1; + uint64_t uses_projector : 1; + uint64_t uses_forward_gi : 1; + uint64_t uses_lightmap : 1; + uint64_t depth_layer : 4; + uint64_t priority : 8; + }; + struct { + uint64_t sort_key1; + uint64_t sort_key2; + }; + } sort; + + RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; + uint32_t flags = 0; + uint32_t surface_index = 0; + uint32_t lod_index = 0; + + void *surface = nullptr; + GLES3::SceneShaderData *shader = nullptr; + GLES3::SceneMaterialData *material = nullptr; + + void *surface_shadow = nullptr; + GLES3::SceneShaderData *shader_shadow = nullptr; + GLES3::SceneMaterialData *material_shadow = nullptr; + + GeometryInstanceSurface *next = nullptr; + GeometryInstanceGLES3 *owner = nullptr; + }; + + struct GeometryInstanceGLES3 : public GeometryInstance { + //used during rendering + bool mirror = false; + bool non_uniform_scale = false; + float lod_bias = 0.0; + float lod_model_scale = 1.0; + AABB transformed_aabb; //needed for LOD + float depth = 0; + uint32_t flags_cache = 0; + bool store_transform_cache = true; + int32_t shader_parameters_offset = -1; + + uint32_t layer_mask = 1; + uint32_t instance_count = 0; + + RID mesh_instance; + bool can_sdfgi = false; + bool using_projectors = false; + bool using_softshadows = false; + bool fade_near = false; + float fade_near_begin = 0; + float fade_near_end = 0; + bool fade_far = false; + float fade_far_begin = 0; + float fade_far_end = 0; + float force_alpha = 1.0; + float parent_fade_alpha = 1.0; + + uint32_t omni_light_count = 0; + LocalVector<RID> omni_lights; + uint32_t spot_light_count = 0; + LocalVector<RID> spot_lights; + LocalVector<uint32_t> omni_light_gl_cache; + LocalVector<uint32_t> spot_light_gl_cache; + + //used during setup + uint32_t base_flags = 0; + Transform3D transform; + GeometryInstanceSurface *surface_caches = nullptr; + SelfList<GeometryInstanceGLES3> dirty_list_element; + + struct Data { + //data used less often goes into regular heap + RID base; + RS::InstanceType base_type; + + RID skeleton; + Vector<RID> surface_materials; + RID material_override; + RID material_overlay; + AABB aabb; + + bool use_dynamic_gi = false; + bool use_baked_light = false; + bool cast_double_sided_shadows = false; + bool mirror = false; + bool dirty_dependencies = false; + + RendererStorage::DependencyTracker dependency_tracker; + }; + + Data *data = nullptr; + + GeometryInstanceGLES3() : + dirty_list_element(this) {} + }; + + enum { + INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5, + INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6, + INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8, + INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9, + INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10, + INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11, + INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, + INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, + }; + + static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + + SelfList<GeometryInstanceGLES3>::List geometry_instance_dirty_list; + + // Use PagedAllocator instead of RID to maximize performance + PagedAllocator<GeometryInstanceGLES3> geometry_instance_alloc; + PagedAllocator<GeometryInstanceSurface> geometry_instance_surface_alloc; + + void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); + void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh); + void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); + void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); + void _geometry_instance_update(GeometryInstance *p_geometry_instance); + void _update_dirty_geometry_instances(); + + struct SceneState { + struct UBO { + float projection_matrix[16]; + float inv_projection_matrix[16]; + float inv_view_matrix[16]; + float view_matrix[16]; + + float viewport_size[2]; + float screen_pixel_size[2]; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t material_uv2_mode; + float pad2; + uint32_t use_ambient_light = 0; + + uint32_t use_ambient_cubemap = 0; + uint32_t use_reflection_cubemap = 0; + float fog_aerial_perspective; + float time; + + float radiance_inverse_xform[12]; + + uint32_t directional_light_count; + float z_far; + float z_near; + float pad1; + + uint32_t fog_enabled; + float fog_density; + float fog_height; + float fog_height_density; + + float fog_light_color[3]; + float fog_sun_scatter; + }; + static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes"); + + struct TonemapUBO { + float exposure = 1.0; + float white = 1.0; + int32_t tonemapper = 0; + int32_t pad = 0; + }; + static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes"); + + UBO ubo; + GLuint ubo_buffer = 0; + GLuint tonemap_buffer = 0; + + bool used_depth_prepass = false; + + GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX; + GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE; + GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED; + GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK; + + bool texscreen_copied = false; + bool used_screen_texture = false; + bool used_normal_texture = false; + bool used_depth_texture = false; + + LightData *omni_lights = nullptr; + LightData *spot_lights = nullptr; + + InstanceSort<LightInstance> *omni_light_sort; + InstanceSort<LightInstance> *spot_light_sort; + GLuint omni_light_buffer = 0; + GLuint spot_light_buffer = 0; + uint32_t omni_light_count = 0; + uint32_t spot_light_count = 0; + + DirectionalLightData *directional_lights = nullptr; + GLuint directional_light_buffer = 0; + } scene_state; + + struct RenderListParameters { + GeometryInstanceSurface **elements = nullptr; + int element_count = 0; + bool reverse_cull = false; + uint32_t spec_constant_base_flags = 0; + bool force_wireframe = false; + + RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false) { + elements = p_elements; + element_count = p_element_count; + reverse_cull = p_reverse_cull; + spec_constant_base_flags = p_spec_constant_base_flags; + force_wireframe = p_force_wireframe; + } + }; + + struct RenderList { + LocalVector<GeometryInstanceSurface *> elements; + + void clear() { + elements.clear(); + } + + //should eventually be replaced by radix + + struct SortByKey { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2); + } + }; + + void sort_by_key() { + SortArray<GeometryInstanceSurface *, SortByKey> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + void sort_by_key_range(uint32_t p_from, uint32_t p_size) { + SortArray<GeometryInstanceSurface *, SortByKey> sorter; + sorter.sort(elements.ptr() + p_from, p_size); + } + + struct SortByDepth { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->owner->depth < B->owner->depth); + } + }; + + void sort_by_depth() { //used for shadows + + SortArray<GeometryInstanceSurface *, SortByDepth> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + struct SortByReverseDepthAndPriority { + _FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const { + return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority); + } + }; + + void sort_by_reverse_depth_and_priority() { //used for alpha + + SortArray<GeometryInstanceSurface *, SortByReverseDepthAndPriority> sorter; + sorter.sort(elements.ptr(), elements.size()); + } + + _FORCE_INLINE_ void add_element(GeometryInstanceSurface *p_element) { + elements.push_back(p_element); + } + }; + + RenderList render_list[RENDER_LIST_MAX]; + + void _setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count); + void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows); + void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false); + + template <PassMode p_pass_mode> + _FORCE_INLINE_ void _render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass = false); protected: double time; @@ -117,6 +531,8 @@ protected: //bool use_debanding = false; //uint32_t view_count = 1; + bool is_transparent = false; + RID render_target; GLuint internal_texture = 0; // Used for rendering when post effects are enabled GLuint depth_texture = 0; // Main depth texture @@ -293,6 +709,33 @@ protected: /* Sky */ + struct SkyGlobals { + float fog_aerial_perspective = 0.0; + Color fog_light_color; + float fog_sun_scatter = 0.0; + bool fog_enabled = false; + float fog_density = 0.0; + float z_far = 0.0; + uint32_t directional_light_count = 0; + + DirectionalLightData *directional_lights = nullptr; + DirectionalLightData *last_frame_directional_lights = nullptr; + uint32_t last_frame_directional_light_count = 0; + GLuint directional_light_buffer = 0; + + RID shader_default_version; + RID default_material; + RID default_shader; + RID fog_material; + RID fog_shader; + GLuint screen_triangle = 0; + GLuint screen_triangle_array = 0; + GLuint radical_inverse_vdc_cache_tex = 0; + uint32_t max_directional_lights = 4; + uint32_t roughness_layers = 8; + uint32_t ggx_samples = 128; + } sky_globals; + struct Sky { // Screen Buffers GLuint half_res_pass = 0; @@ -304,11 +747,13 @@ protected: // Radiance Cubemap GLuint radiance = 0; GLuint radiance_framebuffer = 0; + GLuint raw_radiance = 0; RID material; - RID uniform_buffer; + GLuint uniform_buffer; int radiance_size = 256; + int mipmap_count = 1; RS::SkyMode mode = RS::SKY_MODE_AUTOMATIC; @@ -319,33 +764,26 @@ protected: Sky *dirty_list = nullptr; //State to track when radiance cubemap needs updating - //SkyMaterialData *prev_material; + GLES3::SkyMaterialData *prev_material; Vector3 prev_position = Vector3(0.0, 0.0, 0.0); float prev_time = 0.0f; - - void free(); - 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); }; Sky *dirty_sky_list = nullptr; mutable RID_Owner<Sky, true> sky_owner; + void _setup_sky(Environment *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size); void _invalidate_sky(Sky *p_sky); void _update_dirty_skys(); - void _draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation); + void _update_sky_radiance(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _filter_sky_radiance(Sky *p_sky, int p_base_layer); + void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform); + void _free_sky_data(Sky *p_sky); public: RasterizerStorageGLES3 *storage; RasterizerCanvasGLES3 *canvas; - // References to shaders are needed in public space so they can be accessed in RasterizerStorageGLES3 - struct State { - SkyShaderGLES3 sky_shader; - } state; - GeometryInstance *geometry_instance_create(RID p_base) override; void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override; void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override; @@ -388,9 +826,15 @@ public: /* SDFGI UPDATE */ void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {} - int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; } - AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); } - uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; } + int sdfgi_get_pending_region_count(RID p_render_buffers) const override { + return 0; + } + AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { + return AABB(); + } + uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { + return 0; + } /* SKY API */ @@ -463,6 +907,15 @@ public: void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override; void light_instance_mark_visible(RID p_light_instance) override; + _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->light_type; + } + _FORCE_INLINE_ uint32_t light_instance_get_gl_id(RID p_light_instance) { + LightInstance *li = light_instance_owner.get_or_null(p_light_instance); + return li->gl_id; + } + RID fog_volume_instance_create(RID p_fog_volume) override; void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override; void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override; |