mirror of
https://github.com/godotengine/godot.git
synced 2024-11-22 04:06:14 +00:00
Extracting render buffers and changing it to a more generic solution
This commit is contained in:
parent
0c221f0284
commit
2cd84be64d
@ -568,7 +568,7 @@ void RasterizerSceneGLES3::_update_dirty_skys() {
|
||||
dirty_sky_list = nullptr;
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
|
||||
void RasterizerSceneGLES3::_setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size) {
|
||||
GLES3::LightStorage *light_storage = GLES3::LightStorage::get_singleton();
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_render_data->environment.is_null());
|
||||
@ -1718,23 +1718,23 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
|
||||
void RasterizerSceneGLES3::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
GLES3::Config *config = GLES3::Config::get_singleton();
|
||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||
|
||||
RenderBuffers *rb = nullptr;
|
||||
Ref<RenderSceneBuffersGLES3> rb;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
rb = render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
rb = p_render_buffers;
|
||||
ERR_FAIL_COND(rb.is_null());
|
||||
}
|
||||
|
||||
// Assign render data
|
||||
// Use the format from rendererRD
|
||||
RenderDataGLES3 render_data;
|
||||
{
|
||||
render_data.render_buffers = p_render_buffers;
|
||||
render_data.transparent_bg = rb->is_transparent;
|
||||
render_data.render_buffers = rb;
|
||||
render_data.transparent_bg = rb.is_valid() ? rb->is_transparent : false;
|
||||
// Our first camera is used by default
|
||||
render_data.cam_transform = p_camera_data->main_transform;
|
||||
render_data.inv_cam_transform = render_data.cam_transform.affine_inverse();
|
||||
@ -1886,7 +1886,7 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
|
||||
|
||||
sky_energy_multiplier *= bg_energy_multiplier;
|
||||
|
||||
_setup_sky(&render_data, p_render_buffers, *render_data.lights, projection, render_data.cam_transform, screen_size);
|
||||
_setup_sky(&render_data, *render_data.lights, projection, render_data.cam_transform, screen_size);
|
||||
|
||||
if (environment_get_sky(render_data.environment).is_valid()) {
|
||||
if (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(render_data.environment) == RS::ENV_AMBIENT_SOURCE_SKY || (environment_get_reflection_source(render_data.environment) == RS::ENV_REFLECTION_SOURCE_BG && environment_get_background(render_data.environment) == RS::ENV_BG_SKY)) {
|
||||
@ -2005,8 +2005,8 @@ void RasterizerSceneGLES3::render_scene(RID p_render_buffers, const CameraData *
|
||||
|
||||
_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(&render_list_params_alpha, &render_data, 0, render_list[RENDER_LIST_ALPHA].elements.size(), true);
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
|
||||
if (rb.is_valid()) {
|
||||
_render_buffers_debug_draw(rb, p_shadow_atlas, p_occluder_debug_tex);
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
texture_storage->render_target_disable_clear_request(rb->render_target);
|
||||
@ -2328,74 +2328,10 @@ void RasterizerSceneGLES3::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_dra
|
||||
debug_draw = p_debug_draw;
|
||||
}
|
||||
|
||||
RID RasterizerSceneGLES3::render_buffers_create() {
|
||||
RenderBuffers rb;
|
||||
return render_buffers_owner.make_rid(rb);
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
|
||||
RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb);
|
||||
|
||||
//rb->internal_width = p_internal_width; // ignore for now
|
||||
//rb->internal_height = p_internal_height;
|
||||
rb->width = p_width;
|
||||
rb->height = p_height;
|
||||
//rb->fsr_sharpness = p_fsr_sharpness;
|
||||
rb->render_target = p_render_target;
|
||||
//rb->msaa = p_msaa;
|
||||
//rb->screen_space_aa = p_screen_space_aa;
|
||||
//rb->use_debanding = p_use_debanding;
|
||||
//rb->view_count = p_view_count;
|
||||
|
||||
_free_render_buffer_data(rb);
|
||||
|
||||
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
|
||||
|
||||
rb->is_transparent = rt->is_transparent;
|
||||
|
||||
// framebuffer
|
||||
glGenFramebuffers(1, &rb->framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rb->framebuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, rt->color);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
|
||||
|
||||
glGenTextures(1, &rb->depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, rb->depth_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rb->depth_texture, 0);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
_free_render_buffer_data(rb);
|
||||
WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
|
||||
if (rb->depth_texture) {
|
||||
glDeleteTextures(1, &rb->depth_texture);
|
||||
rb->depth_texture = 0;
|
||||
}
|
||||
if (rb->framebuffer) {
|
||||
glDeleteFramebuffers(1, &rb->framebuffer);
|
||||
rb->framebuffer = 0;
|
||||
}
|
||||
Ref<RenderSceneBuffers> RasterizerSceneGLES3::render_buffers_create() {
|
||||
Ref<RenderSceneBuffersGLES3> rb;
|
||||
rb.instantiate();
|
||||
return rb;
|
||||
}
|
||||
|
||||
//clear render buffers
|
||||
@ -2423,7 +2359,7 @@ void RasterizerSceneGLES3::_free_render_buffer_data(RenderBuffers *rb) {
|
||||
}
|
||||
*/
|
||||
|
||||
void RasterizerSceneGLES3::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
|
||||
void RasterizerSceneGLES3::_render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::gi_set_use_half_resolution(bool p_enable) {
|
||||
@ -2454,12 +2390,6 @@ bool RasterizerSceneGLES3::free(RID p_rid) {
|
||||
ERR_FAIL_COND_V(!sky, false);
|
||||
_free_sky_data(sky);
|
||||
sky_owner.free(p_rid);
|
||||
} else if (render_buffers_owner.owns(p_rid)) {
|
||||
RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid);
|
||||
ERR_FAIL_COND_V(!rb, false);
|
||||
_free_render_buffer_data(rb);
|
||||
render_buffers_owner.free(p_rid);
|
||||
|
||||
} else if (light_instance_owner.owns(p_rid)) {
|
||||
LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
|
||||
ERR_FAIL_COND_V(!light_instance, false);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "shaders/cubemap_filter.glsl.gen.h"
|
||||
#include "shaders/sky.glsl.gen.h"
|
||||
#include "storage/material_storage.h"
|
||||
#include "storage/render_scene_buffers_gles3.h"
|
||||
#include "storage/utilities.h"
|
||||
|
||||
enum RenderListType {
|
||||
@ -91,7 +92,7 @@ enum {
|
||||
};
|
||||
|
||||
struct RenderDataGLES3 {
|
||||
RID render_buffers = RID();
|
||||
Ref<RenderSceneBuffersGLES3> render_buffers;
|
||||
bool transparent_bg = false;
|
||||
|
||||
Transform3D cam_transform = Transform3D();
|
||||
@ -490,52 +491,11 @@ protected:
|
||||
double time;
|
||||
double time_step = 0;
|
||||
|
||||
struct RenderBuffers {
|
||||
int internal_width = 0;
|
||||
int internal_height = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
//float fsr_sharpness = 0.2f;
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
//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
|
||||
GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
|
||||
|
||||
//built-in textures used for ping pong image processing and blurring
|
||||
struct Blur {
|
||||
RID texture;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
int width;
|
||||
int height;
|
||||
GLuint fbo;
|
||||
};
|
||||
|
||||
Vector<Mipmap> mipmaps;
|
||||
};
|
||||
|
||||
Blur blur[2]; //the second one starts from the first mipmap
|
||||
};
|
||||
|
||||
bool screen_space_roughness_limiter = false;
|
||||
float screen_space_roughness_limiter_amount = 0.25;
|
||||
float screen_space_roughness_limiter_limit = 0.18;
|
||||
|
||||
mutable RID_Owner<RenderBuffers, true> render_buffers_owner;
|
||||
|
||||
void _free_render_buffer_data(RenderBuffers *rb);
|
||||
void _allocate_blur_textures(RenderBuffers *rb);
|
||||
void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
|
||||
|
||||
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
|
||||
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
|
||||
|
||||
/* Camera Attributes */
|
||||
|
||||
@ -626,7 +586,7 @@ protected:
|
||||
Sky *dirty_sky_list = nullptr;
|
||||
mutable RID_Owner<Sky, true> sky_owner;
|
||||
|
||||
void _setup_sky(const RenderDataGLES3 *p_render_data, RID p_render_buffers, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
|
||||
void _setup_sky(const RenderDataGLES3 *p_render_data, const PagedArray<RID> &p_lights, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size);
|
||||
void _invalidate_sky(Sky *p_sky);
|
||||
void _update_dirty_skys();
|
||||
void _update_sky_radiance(RID p_env, const Projection &p_projection, const Transform3D &p_transform, float p_luminance_multiplier);
|
||||
@ -657,14 +617,14 @@ 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 {
|
||||
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
|
||||
int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override {
|
||||
return 0;
|
||||
}
|
||||
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override {
|
||||
AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &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 {
|
||||
uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -751,7 +711,7 @@ public:
|
||||
|
||||
void voxel_gi_set_quality(RS::VoxelGIQuality) override;
|
||||
|
||||
void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
|
||||
void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
|
||||
void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
|
||||
|
||||
@ -769,8 +729,7 @@ public:
|
||||
return debug_draw;
|
||||
}
|
||||
|
||||
RID render_buffers_create() override;
|
||||
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
Ref<RenderSceneBuffers> render_buffers_create() override;
|
||||
void gi_set_use_half_resolution(bool p_enable) override;
|
||||
|
||||
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override;
|
||||
|
103
drivers/gles3/storage/render_scene_buffers_gles3.cpp
Normal file
103
drivers/gles3/storage/render_scene_buffers_gles3.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers_gles3.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "render_scene_buffers_gles3.h"
|
||||
#include "texture_storage.h"
|
||||
|
||||
RenderSceneBuffersGLES3::~RenderSceneBuffersGLES3() {
|
||||
free_render_buffer_data();
|
||||
}
|
||||
|
||||
void RenderSceneBuffersGLES3::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
GLES3::TextureStorage *texture_storage = GLES3::TextureStorage::get_singleton();
|
||||
|
||||
//internal_size.x = p_internal_size.x; // ignore for now
|
||||
//internal_size.y = p_internal_size.y;
|
||||
width = p_target_size.x;
|
||||
height = p_target_size.y;
|
||||
//fsr_sharpness = p_fsr_sharpness;
|
||||
//texture_mipmap_bias = p_texture_mipmap_bias;
|
||||
render_target = p_render_target;
|
||||
//msaa = p_msaa;
|
||||
//screen_space_aa = p_screen_space_aa;
|
||||
//use_debanding = p_use_debanding;
|
||||
//view_count = p_view_count;
|
||||
|
||||
free_render_buffer_data();
|
||||
|
||||
GLES3::RenderTarget *rt = texture_storage->get_render_target(p_render_target);
|
||||
|
||||
is_transparent = rt->is_transparent;
|
||||
|
||||
// framebuffer
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, rt->color);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
|
||||
|
||||
glGenTextures(1, &depth_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, depth_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->size.x, rt->size.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0);
|
||||
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, texture_storage->system_fbo);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
free_render_buffer_data();
|
||||
WARN_PRINT("Could not create 3D renderbuffer, status: " + texture_storage->get_framebuffer_error(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSceneBuffersGLES3::free_render_buffer_data() {
|
||||
if (depth_texture) {
|
||||
glDeleteTextures(1, &depth_texture);
|
||||
depth_texture = 0;
|
||||
}
|
||||
if (framebuffer) {
|
||||
glDeleteFramebuffers(1, &framebuffer);
|
||||
framebuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GLES3_ENABLED
|
98
drivers/gles3/storage/render_scene_buffers_gles3.h
Normal file
98
drivers/gles3/storage/render_scene_buffers_gles3.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers_gles3.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 RENDER_SCENE_BUFFERS_GLES3_H
|
||||
#define RENDER_SCENE_BUFFERS_GLES3_H
|
||||
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "servers/rendering/storage/render_scene_buffers.h"
|
||||
|
||||
#include "platform_config.h"
|
||||
#ifndef OPENGL_INCLUDE_H
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include OPENGL_INCLUDE_H
|
||||
#endif
|
||||
|
||||
class RenderSceneBuffersGLES3 : public RenderSceneBuffers {
|
||||
GDCLASS(RenderSceneBuffersGLES3, RenderSceneBuffers);
|
||||
|
||||
public:
|
||||
// Original implementation, need to investigate which ones we'll keep like this and what we'll change...
|
||||
|
||||
int internal_width = 0;
|
||||
int internal_height = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
//float fsr_sharpness = 0.2f;
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
//RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
//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
|
||||
GLuint framebuffer = 0; // Main framebuffer, contains internal_texture and depth_texture or render_target->color and depth_texture
|
||||
|
||||
//built-in textures used for ping pong image processing and blurring
|
||||
struct Blur {
|
||||
RID texture;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
int width;
|
||||
int height;
|
||||
GLuint fbo;
|
||||
};
|
||||
|
||||
Vector<Mipmap> mipmaps;
|
||||
};
|
||||
|
||||
Blur blur[2]; //the second one starts from the first mipmap
|
||||
|
||||
private:
|
||||
public:
|
||||
virtual ~RenderSceneBuffersGLES3();
|
||||
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
|
||||
virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
|
||||
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};
|
||||
virtual void set_use_debanding(bool p_use_debanding) override{};
|
||||
|
||||
void free_render_buffer_data();
|
||||
};
|
||||
|
||||
#endif // GLES3_ENABLED
|
||||
|
||||
#endif // RENDER_SCENE_BUFFERS_GLES3_H
|
@ -106,10 +106,10 @@ 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; }
|
||||
void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
|
||||
int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
|
||||
AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
|
||||
uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
|
||||
|
||||
/* SKY API */
|
||||
|
||||
@ -180,7 +180,7 @@ public:
|
||||
|
||||
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
|
||||
|
||||
void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
|
||||
void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
|
||||
void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
|
||||
void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
|
||||
|
||||
@ -188,8 +188,7 @@ public:
|
||||
void set_time(double p_time, double p_step) override {}
|
||||
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
|
||||
|
||||
RID render_buffers_create() override { return RID(); }
|
||||
void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
|
||||
Ref<RenderSceneBuffers> render_buffers_create() override { return Ref<RenderSceneBuffers>(); }
|
||||
void gi_set_use_half_resolution(bool p_enable) override {}
|
||||
|
||||
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
|
||||
|
@ -705,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
|
||||
void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
@ -713,6 +713,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
|
||||
RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
|
||||
|
||||
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
|
||||
|
||||
BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
|
||||
@ -737,14 +740,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
|
||||
RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
|
||||
RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
|
||||
|
||||
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
//HORIZONTAL
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
if (p_auto_exposure.is_valid() && p_first_pass) {
|
||||
RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
|
||||
@ -764,9 +767,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
//VERTICAL
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
|
||||
|
||||
blur_raster.push_constant.flags = base_flags;
|
||||
@ -810,9 +813,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
|
||||
void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
|
||||
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
|
||||
|
||||
RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
@ -833,8 +838,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu
|
||||
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
|
@ -322,10 +322,10 @@ public:
|
||||
|
||||
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||
void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
|
||||
void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
|
||||
void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
|
||||
|
||||
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
|
||||
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
|
||||
void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
|
||||
|
||||
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
|
||||
|
||||
|
127
servers/rendering/renderer_rd/effects/fsr.cpp
Normal file
127
servers/rendering/renderer_rd/effects/fsr.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/*************************************************************************/
|
||||
/* fsr.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "fsr.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
||||
FSR::FSR() {
|
||||
Vector<String> FSR_upscale_modes;
|
||||
|
||||
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
|
||||
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
#else
|
||||
// Everyone else can use normal mode when available.
|
||||
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
|
||||
} else {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
fsr_shader.initialize(FSR_upscale_modes);
|
||||
|
||||
shader_version = fsr_shader.version_create();
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0));
|
||||
}
|
||||
|
||||
FSR::~FSR() {
|
||||
fsr_shader.version_free(shader_version);
|
||||
}
|
||||
|
||||
void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) {
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
Size2i internal_size = p_render_buffers->get_internal_size();
|
||||
Size2i target_size = p_render_buffers->get_target_size();
|
||||
float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness();
|
||||
|
||||
if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) {
|
||||
RD::DataFormat format = p_render_buffers->get_base_data_format();
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time.
|
||||
|
||||
p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers);
|
||||
}
|
||||
|
||||
RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture"));
|
||||
|
||||
FSRUpscalePushConstant push_constant;
|
||||
memset(&push_constant, 0, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
int dispatch_x = (target_size.x + 15) / 16;
|
||||
int dispatch_y = (target_size.y + 15) / 16;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
|
||||
|
||||
push_constant.resolution_width = internal_size.width;
|
||||
push_constant.resolution_height = internal_size.height;
|
||||
push_constant.upscaled_width = target_size.width;
|
||||
push_constant.upscaled_height = target_size.height;
|
||||
push_constant.sharpness = fsr_upscale_sharpness;
|
||||
|
||||
RID shader = fsr_shader.version_get_shader(shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
//FSR Easc
|
||||
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture });
|
||||
RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture });
|
||||
|
||||
push_constant.pass = FSR_UPSCALE_PASS_EASU;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
//FSR Rcas
|
||||
RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture });
|
||||
RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture });
|
||||
|
||||
push_constant.pass = FSR_UPSCALE_PASS_RCAS;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end(compute_list);
|
||||
}
|
73
servers/rendering/renderer_rd/effects/fsr.h
Normal file
73
servers/rendering/renderer_rd/effects/fsr.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*************************************************************************/
|
||||
/* fsr.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 FSR_RD_H
|
||||
#define FSR_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
class FSR {
|
||||
public:
|
||||
FSR();
|
||||
~FSR();
|
||||
|
||||
void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
|
||||
|
||||
private:
|
||||
enum FSRUpscalePass {
|
||||
FSR_UPSCALE_PASS_EASU = 0,
|
||||
FSR_UPSCALE_PASS_RCAS = 1
|
||||
};
|
||||
|
||||
struct FSRUpscalePushConstant {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float upscaled_width;
|
||||
float upscaled_height;
|
||||
float sharpness;
|
||||
int pass;
|
||||
int _unused0, _unused1;
|
||||
};
|
||||
|
||||
FsrUpscaleShaderRD fsr_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
};
|
||||
|
||||
} // namespace RendererRD
|
||||
|
||||
#endif // FSR_RD_H
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
@ -333,6 +334,22 @@ SSEffects::SSEffects() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Subsurface scattering
|
||||
{
|
||||
Vector<String> sss_modes;
|
||||
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
|
||||
sss_modes.push_back("\n#define USE_17_SAMPLES\n");
|
||||
sss_modes.push_back("\n#define USE_25_SAMPLES\n");
|
||||
|
||||
sss.shader.initialize(sss_modes);
|
||||
|
||||
sss.shader_version = sss.shader.version_create();
|
||||
|
||||
for (int i = 0; i < sss_modes.size(); i++) {
|
||||
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SSEffects::~SSEffects() {
|
||||
@ -376,6 +393,11 @@ SSEffects::~SSEffects() {
|
||||
RD::get_singleton()->free(ssao.importance_map_load_counter);
|
||||
}
|
||||
|
||||
{
|
||||
// Cleanup Subsurface scattering
|
||||
sss.shader.version_free(sss.shader_version);
|
||||
}
|
||||
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
@ -1713,3 +1735,73 @@ void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
|
||||
p_ssr_buffers.normal_scaled = RID();
|
||||
}
|
||||
}
|
||||
|
||||
/* Subsurface scattering */
|
||||
|
||||
void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
// Our intermediate buffer is only created if we haven't created it already.
|
||||
RD::DataFormat format = p_render_buffers->get_base_data_format();
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
uint32_t layers = 1; // We only need one layer, we're handling one view at a time
|
||||
uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
|
||||
RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
|
||||
|
||||
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
|
||||
p.normal /= p.d;
|
||||
float unit_size = p.normal.x;
|
||||
|
||||
{ //scale color and depth to half
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
sss.push_constant.camera_z_far = p_camera.get_z_far();
|
||||
sss.push_constant.camera_z_near = p_camera.get_z_near();
|
||||
sss.push_constant.orthogonal = p_camera.is_orthogonal();
|
||||
sss.push_constant.unit_size = unit_size;
|
||||
sss.push_constant.screen_size[0] = p_screen_size.x;
|
||||
sss.push_constant.screen_size[1] = p_screen_size.y;
|
||||
sss.push_constant.vertical = false;
|
||||
sss.push_constant.scale = p_scale;
|
||||
sss.push_constant.depth_scale = p_depth_scale;
|
||||
|
||||
RID shader = sss.shader.version_get_shader(sss.shader_version, p_quality - 1);
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
|
||||
|
||||
RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
|
||||
RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
|
||||
RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
|
||||
RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
|
||||
RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
|
||||
|
||||
// horizontal
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
// vertical
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
|
||||
|
||||
sss.push_constant.vertical = true;
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +44,12 @@
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RenderSceneBuffersRD;
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
class SSEffects {
|
||||
@ -168,6 +171,9 @@ public:
|
||||
void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, const RID *p_metallic_slices, const Color &p_metallic_mask, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
|
||||
void ssr_free(SSRRenderBuffers &p_ssr_buffers);
|
||||
|
||||
/* subsurface scattering */
|
||||
void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
|
||||
|
||||
private:
|
||||
/* SS Downsampler */
|
||||
|
||||
@ -501,6 +507,29 @@ private:
|
||||
RID shader_version;
|
||||
RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
|
||||
} ssr_filter;
|
||||
|
||||
/* Subsurface scattering */
|
||||
|
||||
struct SubSurfaceScatteringPushConstant {
|
||||
int32_t screen_size[2];
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
|
||||
uint32_t vertical;
|
||||
uint32_t orthogonal;
|
||||
float unit_size;
|
||||
float scale;
|
||||
|
||||
float depth_scale;
|
||||
uint32_t pad[3];
|
||||
};
|
||||
|
||||
struct SubSurfaceScattering {
|
||||
SubSurfaceScatteringPushConstant push_constant;
|
||||
SubsurfaceScatteringShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[3]; //3 quality levels
|
||||
} sss;
|
||||
};
|
||||
|
||||
} // namespace RendererRD
|
||||
|
138
servers/rendering/renderer_rd/effects/taa.cpp
Normal file
138
servers/rendering/renderer_rd/effects/taa.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*************************************************************************/
|
||||
/* taa.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "taa.h"
|
||||
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
||||
TAA::TAA() {
|
||||
Vector<String> taa_modes;
|
||||
taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
|
||||
taa_shader.initialize(taa_modes);
|
||||
shader_version = taa_shader.version_create();
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0));
|
||||
}
|
||||
|
||||
TAA::~TAA() {
|
||||
taa_shader.version_free(shader_version);
|
||||
}
|
||||
|
||||
void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
if (!p_render_buffers->has_velocity_buffer(true)) {
|
||||
// nothing to resolve
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
|
||||
RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v);
|
||||
RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
|
||||
|
||||
RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
RID shader = taa_shader.version_get_shader(shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
TAAResolvePushConstant push_constant;
|
||||
memset(&push_constant, 0, sizeof(TAAResolvePushConstant));
|
||||
push_constant.resolution_width = p_resolution.width;
|
||||
push_constant.resolution_height = p_resolution.height;
|
||||
push_constant.disocclusion_threshold = 0.025f;
|
||||
push_constant.disocclusion_scale = 10.0f;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
|
||||
|
||||
RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
|
||||
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
|
||||
RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
|
||||
RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
|
||||
RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
|
||||
RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) {
|
||||
CopyEffects *copy_effects = CopyEffects::get_singleton();
|
||||
|
||||
uint32_t view_count = p_render_buffers->get_view_count();
|
||||
Size2i internal_size = p_render_buffers->get_internal_size();
|
||||
Size2i target_size = p_render_buffers->get_target_size();
|
||||
|
||||
bool just_allocated = false;
|
||||
if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) {
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits);
|
||||
p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits);
|
||||
|
||||
p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
|
||||
|
||||
just_allocated = true;
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("TAA");
|
||||
|
||||
for (uint32_t v = 0; v < view_count; v++) {
|
||||
// Get our (cached) slices
|
||||
RID internal_texture = p_render_buffers->get_internal_texture(v);
|
||||
RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
|
||||
RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0);
|
||||
RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0);
|
||||
|
||||
if (!just_allocated) {
|
||||
RID depth_texture = p_render_buffers->get_depth_texture(v);
|
||||
RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0);
|
||||
resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far);
|
||||
copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y));
|
||||
}
|
||||
|
||||
copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y));
|
||||
copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y));
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
68
servers/rendering/renderer_rd/effects/taa.h
Normal file
68
servers/rendering/renderer_rd/effects/taa.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*************************************************************************/
|
||||
/* taa.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 TAA_RD_H
|
||||
#define TAA_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
class TAA {
|
||||
public:
|
||||
TAA();
|
||||
~TAA();
|
||||
|
||||
void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far);
|
||||
|
||||
private:
|
||||
struct TAAResolvePushConstant {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float disocclusion_threshold;
|
||||
float disocclusion_scale;
|
||||
};
|
||||
|
||||
TaaResolveShaderRD taa_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
|
||||
void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
|
||||
};
|
||||
|
||||
} // namespace RendererRD
|
||||
|
||||
#endif // TAA_RD_H
|
@ -91,47 +91,22 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) {
|
||||
// TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm
|
||||
|
||||
Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
|
||||
// TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
|
||||
// obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
|
||||
// our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
|
||||
// of the VRS buffer to supply.
|
||||
Size2i texel_size = Size2i(16, 16);
|
||||
|
||||
RD::TextureFormat tf;
|
||||
if (p_view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
} else {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
int width = p_base_size.x / texel_size.x;
|
||||
if (p_base_size.x % texel_size.x != 0) {
|
||||
width++;
|
||||
}
|
||||
tf.format = RD::DATA_FORMAT_R8_UINT;
|
||||
tf.width = p_base_width / texel_size.x;
|
||||
if (p_base_width % texel_size.x != 0) {
|
||||
tf.width++;
|
||||
int height = p_base_size.y / texel_size.y;
|
||||
if (p_base_size.y % texel_size.y != 0) {
|
||||
height++;
|
||||
}
|
||||
tf.height = p_base_height / texel_size.y;
|
||||
if (p_base_height % texel_size.y != 0) {
|
||||
tf.height++;
|
||||
}
|
||||
tf.array_layers = p_view_count; // create a layer for every view
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
tf.samples = RD::TEXTURE_SAMPLES_1;
|
||||
|
||||
p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
// by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_vrs_texture);
|
||||
|
||||
RD::FramebufferPass pass;
|
||||
pass.color_attachments.push_back(0);
|
||||
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
passes.push_back(pass);
|
||||
|
||||
p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count);
|
||||
return Size2i(width, height);
|
||||
}
|
||||
|
||||
void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
|
||||
void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
|
||||
|
||||
void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb);
|
||||
Size2i get_vrs_texture_size(const Size2i p_base_size) const;
|
||||
void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
|
||||
};
|
||||
|
||||
|
@ -108,115 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
|
||||
return uniform_set;
|
||||
}
|
||||
|
||||
void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
|
||||
memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
int dispatch_x = (p_size.x + 15) / 16;
|
||||
int dispatch_y = (p_size.y + 15) / 16;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
|
||||
|
||||
FSR_upscale.push_constant.resolution_width = p_internal_size.width;
|
||||
FSR_upscale.push_constant.resolution_height = p_internal_size.height;
|
||||
FSR_upscale.push_constant.upscaled_width = p_size.width;
|
||||
FSR_upscale.push_constant.upscaled_height = p_size.height;
|
||||
FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
|
||||
|
||||
//FSR Easc
|
||||
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
//FSR Rcas
|
||||
FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end(compute_list);
|
||||
}
|
||||
|
||||
void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
|
||||
RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant));
|
||||
TAA_resolve.push_constant.resolution_width = p_resolution.width;
|
||||
TAA_resolve.push_constant.resolution_height = p_resolution.height;
|
||||
TAA_resolve.push_constant.disocclusion_threshold = 0.025f;
|
||||
TAA_resolve.push_constant.disocclusion_scale = 10.0f;
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline);
|
||||
|
||||
RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
|
||||
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
|
||||
RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
|
||||
RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
|
||||
RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
|
||||
RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
|
||||
p.normal /= p.d;
|
||||
float unit_size = p.normal.x;
|
||||
|
||||
{ //scale color and depth to half
|
||||
sss.push_constant.camera_z_far = p_camera.get_z_far();
|
||||
sss.push_constant.camera_z_near = p_camera.get_z_near();
|
||||
sss.push_constant.orthogonal = p_camera.is_orthogonal();
|
||||
sss.push_constant.unit_size = unit_size;
|
||||
sss.push_constant.screen_size[0] = p_screen_size.x;
|
||||
sss.push_constant.screen_size[1] = p_screen_size.y;
|
||||
sss.push_constant.vertical = false;
|
||||
sss.push_constant.scale = p_scale;
|
||||
sss.push_constant.depth_scale = p_depth_scale;
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
|
||||
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
|
||||
|
||||
sss.push_constant.vertical = true;
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
|
||||
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
|
||||
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
|
||||
|
||||
@ -377,27 +268,6 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
|
||||
}
|
||||
|
||||
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
{
|
||||
Vector<String> FSR_upscale_modes;
|
||||
|
||||
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
|
||||
// MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
#else
|
||||
// Everyone else can use normal mode when available.
|
||||
if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
|
||||
} else {
|
||||
FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
FSR_upscale.shader.initialize(FSR_upscale_modes);
|
||||
|
||||
FSR_upscale.shader_version = FSR_upscale.shader.version_create();
|
||||
FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
|
||||
}
|
||||
|
||||
prefer_raster_effects = p_prefer_raster_effects;
|
||||
|
||||
if (prefer_raster_effects) {
|
||||
@ -445,23 +315,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0));
|
||||
}
|
||||
|
||||
if (!prefer_raster_effects) {
|
||||
{
|
||||
Vector<String> sss_modes;
|
||||
sss_modes.push_back("\n#define USE_11_SAMPLES\n");
|
||||
sss_modes.push_back("\n#define USE_17_SAMPLES\n");
|
||||
sss_modes.push_back("\n#define USE_25_SAMPLES\n");
|
||||
|
||||
sss.shader.initialize(sss_modes);
|
||||
|
||||
sss.shader_version = sss.shader.version_create();
|
||||
|
||||
for (int i = 0; i < sss_modes.size(); i++) {
|
||||
sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Vector<String> sort_modes;
|
||||
sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
|
||||
@ -477,14 +330,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Vector<String> taa_modes;
|
||||
taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
|
||||
TAA_resolve.shader.initialize(taa_modes);
|
||||
TAA_resolve.shader_version = TAA_resolve.shader.version_create();
|
||||
TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0));
|
||||
}
|
||||
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
@ -523,8 +368,6 @@ EffectsRD::~EffectsRD() {
|
||||
RD::get_singleton()->free(default_mipmap_sampler);
|
||||
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
|
||||
|
||||
FSR_upscale.shader.version_free(FSR_upscale.shader_version);
|
||||
TAA_resolve.shader.version_free(TAA_resolve.shader_version);
|
||||
if (prefer_raster_effects) {
|
||||
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
|
||||
} else {
|
||||
@ -532,7 +375,6 @@ EffectsRD::~EffectsRD() {
|
||||
}
|
||||
if (!prefer_raster_effects) {
|
||||
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
|
||||
sss.shader.version_free(sss.shader_version);
|
||||
}
|
||||
sort.shader.version_free(sort.shader_version);
|
||||
}
|
||||
|
@ -33,13 +33,10 @@
|
||||
|
||||
#include "core/math/projection.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
@ -48,42 +45,6 @@ class EffectsRD {
|
||||
private:
|
||||
bool prefer_raster_effects;
|
||||
|
||||
enum FSRUpscalePass {
|
||||
FSR_UPSCALE_PASS_EASU = 0,
|
||||
FSR_UPSCALE_PASS_RCAS = 1
|
||||
};
|
||||
|
||||
struct FSRUpscalePushConstant {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float upscaled_width;
|
||||
float upscaled_height;
|
||||
float sharpness;
|
||||
int pass;
|
||||
int _unused0, _unused1;
|
||||
};
|
||||
|
||||
struct FSRUpscale {
|
||||
FSRUpscalePushConstant push_constant;
|
||||
FsrUpscaleShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
} FSR_upscale;
|
||||
|
||||
struct TAAResolvePushConstant {
|
||||
float resolution_width;
|
||||
float resolution_height;
|
||||
float disocclusion_threshold;
|
||||
float disocclusion_scale;
|
||||
};
|
||||
|
||||
struct TAAResolve {
|
||||
TAAResolvePushConstant push_constant;
|
||||
TaaResolveShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
} TAA_resolve;
|
||||
|
||||
enum LuminanceReduceMode {
|
||||
LUMINANCE_REDUCE_READ,
|
||||
LUMINANCE_REDUCE,
|
||||
@ -143,27 +104,6 @@ private:
|
||||
|
||||
} roughness_limiter;
|
||||
|
||||
struct SubSurfaceScatteringPushConstant {
|
||||
int32_t screen_size[2];
|
||||
float camera_z_far;
|
||||
float camera_z_near;
|
||||
|
||||
uint32_t vertical;
|
||||
uint32_t orthogonal;
|
||||
float unit_size;
|
||||
float scale;
|
||||
|
||||
float depth_scale;
|
||||
uint32_t pad[3];
|
||||
};
|
||||
|
||||
struct SubSurfaceScattering {
|
||||
SubSurfaceScatteringPushConstant push_constant;
|
||||
SubsurfaceScatteringShaderRD shader;
|
||||
RID shader_version;
|
||||
RID pipelines[3]; //3 quality levels
|
||||
} sss;
|
||||
|
||||
enum SortMode {
|
||||
SORT_MODE_BLOCK,
|
||||
SORT_MODE_STEP,
|
||||
@ -230,16 +170,11 @@ private:
|
||||
public:
|
||||
bool get_prefer_raster_effects();
|
||||
|
||||
void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
|
||||
void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
|
||||
|
||||
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
|
||||
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
|
||||
|
||||
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
|
||||
|
||||
void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
|
||||
|
||||
void sort_buffer(RID p_uniform_set, int p_size);
|
||||
|
||||
EffectsRD(bool p_prefer_raster_effects);
|
||||
|
@ -473,7 +473,7 @@ Fog::FogShaderData::~FogShaderData() {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Volumetric Fog
|
||||
|
||||
Fog::VolumetricFog::VolumetricFog(const Vector3i &fog_size, RID p_sky_shader) {
|
||||
void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {
|
||||
width = fog_size.x;
|
||||
height = fog_size.y;
|
||||
depth = fog_size.z;
|
||||
@ -591,6 +591,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RENDER_TIMESTAMP("> Volumetric Fog");
|
||||
RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
|
||||
|
||||
Ref<VolumetricFog> fog = p_settings.vfog;
|
||||
|
||||
if (p_fog_volumes.size() > 0) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
|
||||
|
||||
@ -623,9 +625,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
params.z_far = z_far;
|
||||
params.time = p_settings.time;
|
||||
|
||||
params.fog_volume_size[0] = p_settings.vfog->width;
|
||||
params.fog_volume_size[1] = p_settings.vfog->height;
|
||||
params.fog_volume_size[2] = p_settings.vfog->depth;
|
||||
params.fog_volume_size[0] = fog->width;
|
||||
params.fog_volume_size[1] = fog->height;
|
||||
params.fog_volume_size[2] = fog->depth;
|
||||
|
||||
params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
|
||||
params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
|
||||
@ -638,7 +640,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
|
||||
RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE);
|
||||
|
||||
if (p_settings.vfog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->fog_uniform_set)) {
|
||||
if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
|
||||
Vector<RD::Uniform> uniforms;
|
||||
|
||||
{
|
||||
@ -649,7 +651,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 1;
|
||||
u.append_id(p_settings.vfog->emissive_map);
|
||||
u.append_id(fog->emissive_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -669,7 +671,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 3;
|
||||
u.append_id(p_settings.vfog->density_map);
|
||||
u.append_id(fog->density_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -681,11 +683,11 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 4;
|
||||
u.append_id(p_settings.vfog->light_map);
|
||||
u.append_id(fog->light_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
p_settings.vfog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
|
||||
fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
|
||||
}
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
@ -731,7 +733,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
|
||||
// Local fog volume.
|
||||
Vector3i points[8];
|
||||
Vector3 fog_size = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
|
||||
float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
|
||||
points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
|
||||
points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
|
||||
@ -742,7 +744,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
|
||||
points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
|
||||
|
||||
min = Vector3i(int32_t(p_settings.vfog->width) - 1, int32_t(p_settings.vfog->height) - 1, int32_t(p_settings.vfog->depth) - 1);
|
||||
min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
|
||||
max = Vector3i(1, 1, 1);
|
||||
|
||||
for (int j = 0; j < 8; j++) {
|
||||
@ -753,9 +755,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
kernel_size = max - min;
|
||||
} else {
|
||||
// Volume type global runs on all cells
|
||||
extents = Vector3(p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
extents = Vector3(fog->width, fog->height, fog->depth);
|
||||
min = Vector3i(0, 0, 0);
|
||||
kernel_size = Vector3i(int32_t(p_settings.vfog->width), int32_t(p_settings.vfog->height), int32_t(p_settings.vfog->depth));
|
||||
kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
|
||||
}
|
||||
|
||||
if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
|
||||
@ -777,7 +779,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
|
||||
if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
|
||||
@ -795,7 +797,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::get_singleton()->compute_list_end();
|
||||
}
|
||||
|
||||
if (p_settings.vfog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->process_uniform_set_density)) {
|
||||
if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {
|
||||
//re create uniform set if needed
|
||||
Vector<RD::Uniform> uniforms;
|
||||
Vector<RD::Uniform> copy_uniforms;
|
||||
@ -875,7 +877,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 8;
|
||||
u.append_id(p_settings.vfog->light_density_map);
|
||||
u.append_id(fog->light_density_map);
|
||||
uniforms.push_back(u);
|
||||
copy_uniforms.push_back(u);
|
||||
}
|
||||
@ -884,7 +886,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 9;
|
||||
u.append_id(p_settings.vfog->fog_map);
|
||||
u.append_id(fog->fog_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -892,7 +894,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 9;
|
||||
u.append_id(p_settings.vfog->prev_light_density_map);
|
||||
u.append_id(fog->prev_light_density_map);
|
||||
copy_uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -909,7 +911,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.binding = 11;
|
||||
u.append_id(p_settings.voxel_gl_buffer);
|
||||
u.append_id(p_settings.voxel_gi_buffer);
|
||||
uniforms.push_back(u);
|
||||
copy_uniforms.push_back(u);
|
||||
}
|
||||
@ -944,7 +946,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 15;
|
||||
u.append_id(p_settings.vfog->prev_light_density_map);
|
||||
u.append_id(fog->prev_light_density_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
@ -955,7 +957,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 16;
|
||||
u.append_id(p_settings.vfog->density_map);
|
||||
u.append_id(fog->density_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
@ -966,7 +968,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 17;
|
||||
u.append_id(p_settings.vfog->light_map);
|
||||
u.append_id(fog->light_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -978,7 +980,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
#endif
|
||||
u.binding = 18;
|
||||
u.append_id(p_settings.vfog->emissive_map);
|
||||
u.append_id(fog->emissive_map);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -992,9 +994,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
p_settings.vfog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
|
||||
fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
|
||||
|
||||
p_settings.vfog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
|
||||
fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
|
||||
|
||||
RID aux7 = uniforms.write[7].get_id(0);
|
||||
RID aux8 = uniforms.write[8].get_id(0);
|
||||
@ -1002,17 +1004,17 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
uniforms.write[7].set_id(0, aux8);
|
||||
uniforms.write[8].set_id(0, aux7);
|
||||
|
||||
p_settings.vfog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
|
||||
fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
|
||||
|
||||
uniforms.remove_at(8);
|
||||
uniforms.write[7].set_id(0, aux7);
|
||||
p_settings.vfog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
|
||||
fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
|
||||
}
|
||||
|
||||
bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi != nullptr);
|
||||
bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid());
|
||||
|
||||
if (using_sdfgi) {
|
||||
if (p_settings.vfog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(p_settings.vfog->sdfgi_uniform_set)) {
|
||||
if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) {
|
||||
Vector<RD::Uniform> uniforms;
|
||||
|
||||
{
|
||||
@ -1039,12 +1041,12 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
p_settings.vfog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
|
||||
fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
|
||||
}
|
||||
}
|
||||
|
||||
p_settings.vfog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
|
||||
p_settings.vfog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
|
||||
fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
|
||||
fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
|
||||
|
||||
VolumetricFogShader::ParamsUBO params;
|
||||
|
||||
@ -1079,9 +1081,9 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
params.ambient_color[2] = ambient_color.b;
|
||||
params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env);
|
||||
|
||||
params.fog_volume_size[0] = p_settings.vfog->width;
|
||||
params.fog_volume_size[1] = p_settings.vfog->height;
|
||||
params.fog_volume_size[2] = p_settings.vfog->depth;
|
||||
params.fog_volume_size[0] = fog->width;
|
||||
params.fog_volume_size[1] = fog->height;
|
||||
params.fog_volume_size[2] = fog->depth;
|
||||
|
||||
params.directional_light_count = p_directional_light_count;
|
||||
|
||||
@ -1149,19 +1151,19 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
|
||||
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set_density, 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);
|
||||
|
||||
if (using_sdfgi) {
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->sdfgi_uniform_set, 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);
|
||||
}
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
|
||||
// Copy fog to history buffer
|
||||
if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->copy_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
@ -1172,8 +1174,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RENDER_TIMESTAMP("Filter Fog");
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
//need restart for buffer update
|
||||
@ -1183,8 +1185,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
|
||||
compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set2, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, p_settings.vfog->depth);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
|
||||
|
||||
RD::get_singleton()->compute_list_add_barrier(compute_list);
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
@ -1194,8 +1196,8 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
||||
RD::get_singleton()->draw_command_begin_label("Integrate Fog");
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, p_settings.vfog->process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.vfog->width, p_settings.vfog->height, 1);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);
|
||||
|
||||
RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
|
||||
|
||||
|
@ -38,8 +38,11 @@
|
||||
#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 {
|
||||
@ -261,7 +264,10 @@ public:
|
||||
void fog_instance_free(RID p_rid);
|
||||
|
||||
/* Volumetric FOG */
|
||||
struct VolumetricFog {
|
||||
class VolumetricFog : public RenderBufferCustomDataRD {
|
||||
GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
|
||||
|
||||
public:
|
||||
enum {
|
||||
MAX_TEMPORAL_FRAMES = 16
|
||||
};
|
||||
@ -290,7 +296,10 @@ public:
|
||||
|
||||
int last_shadow_filter = -1;
|
||||
|
||||
VolumetricFog(const Vector3i &fog_size, RID p_sky_shader);
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
||||
virtual void free_data() override{};
|
||||
|
||||
void init(const Vector3i &fog_size, RID p_sky_shader);
|
||||
~VolumetricFog();
|
||||
};
|
||||
|
||||
@ -304,7 +313,7 @@ public:
|
||||
uint32_t max_cluster_elements;
|
||||
bool volumetric_fog_filter_active;
|
||||
RID shadow_sampler;
|
||||
RID voxel_gl_buffer;
|
||||
RID voxel_gi_buffer;
|
||||
RID shadow_atlas_depth;
|
||||
RID omni_light_buffer;
|
||||
RID spot_light_buffer;
|
||||
@ -312,11 +321,11 @@ public:
|
||||
RID directional_light_buffer;
|
||||
|
||||
// Objects related to our render buffer
|
||||
VolumetricFog *vfog;
|
||||
Ref<VolumetricFog> vfog;
|
||||
ClusterBuilderRD *cluster_builder;
|
||||
GI *gi;
|
||||
GI::SDFGI *sdfgi;
|
||||
GI::RenderBuffersGI *rbgi;
|
||||
Ref<GI::SDFGI> sdfgi;
|
||||
Ref<GI::RenderBuffersGI> rbgi;
|
||||
RID env;
|
||||
SkyRD *sky;
|
||||
};
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
|
||||
@ -384,6 +385,13 @@ RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
|
||||
return voxel_gi->sdf_texture;
|
||||
}
|
||||
|
||||
Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
|
||||
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
|
||||
ERR_FAIL_COND_V(!voxel_gi, nullptr);
|
||||
|
||||
return &voxel_gi->dependency;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SDFGI
|
||||
|
||||
@ -1121,7 +1129,11 @@ void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_re
|
||||
reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
|
||||
}
|
||||
|
||||
void GI::SDFGI::erase() {
|
||||
void GI::SDFGI::free_data() {
|
||||
// we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change.
|
||||
}
|
||||
|
||||
GI::SDFGI::~SDFGI() {
|
||||
for (uint32_t i = 0; i < cascades.size(); i++) {
|
||||
const SDFGI::Cascade &c = cascades[i];
|
||||
RD::get_singleton()->free(c.light_data);
|
||||
@ -1982,10 +1994,9 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r
|
||||
}
|
||||
}
|
||||
|
||||
void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
|
||||
void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization) {
|
||||
//print_line("rendering region " + itos(p_region));
|
||||
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
|
||||
ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
|
||||
AABB bounds;
|
||||
Vector3i from;
|
||||
Vector3i size;
|
||||
@ -2342,9 +2353,8 @@ void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArr
|
||||
}
|
||||
}
|
||||
|
||||
void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
|
||||
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
|
||||
void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights");
|
||||
|
||||
@ -3572,25 +3582,27 @@ void GI::free() {
|
||||
}
|
||||
}
|
||||
|
||||
GI::SDFGI *GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
|
||||
SDFGI *sdfgi = memnew(SDFGI);
|
||||
Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
|
||||
Ref<SDFGI> sdfgi;
|
||||
sdfgi.instantiate();
|
||||
|
||||
sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
|
||||
|
||||
return sdfgi;
|
||||
}
|
||||
|
||||
void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
|
||||
void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
ERR_FAIL_NULL(texture_storage);
|
||||
|
||||
r_voxel_gi_instances_used = 0;
|
||||
|
||||
// feels a little dirty to use our container this way but....
|
||||
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(rb == nullptr);
|
||||
|
||||
RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
|
||||
Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
|
||||
ERR_FAIL_COND(rbgi.is_null());
|
||||
|
||||
RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer();
|
||||
VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
|
||||
|
||||
bool voxel_gi_instances_changed = false;
|
||||
@ -3601,7 +3613,7 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
|
||||
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
|
||||
RID texture;
|
||||
if (i < (int)p_voxel_gi_instances.size()) {
|
||||
VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]);
|
||||
VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
|
||||
|
||||
if (gipi) {
|
||||
texture = gipi->texture;
|
||||
@ -3653,28 +3665,30 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
|
||||
texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
|
||||
}
|
||||
|
||||
if (texture != rb->rbgi.voxel_gi_textures[i]) {
|
||||
if (texture != rbgi->voxel_gi_textures[i]) {
|
||||
voxel_gi_instances_changed = true;
|
||||
rb->rbgi.voxel_gi_textures[i] = texture;
|
||||
rbgi->voxel_gi_textures[i] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
if (voxel_gi_instances_changed) {
|
||||
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
|
||||
RD::get_singleton()->free(rb->rbgi.uniform_set[v]);
|
||||
if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
|
||||
RD::get_singleton()->free(rbgi->uniform_set[v]);
|
||||
}
|
||||
rb->rbgi.uniform_set[v] = RID();
|
||||
rbgi->uniform_set[v] = RID();
|
||||
}
|
||||
if (rb->volumetric_fog) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
|
||||
RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
|
||||
RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
|
||||
RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
|
||||
if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
|
||||
Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
|
||||
|
||||
if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
|
||||
RD::get_singleton()->free(fog->fog_uniform_set);
|
||||
RD::get_singleton()->free(fog->process_uniform_set);
|
||||
RD::get_singleton()->free(fog->process_uniform_set2);
|
||||
}
|
||||
rb->volumetric_fog->fog_uniform_set = RID();
|
||||
rb->volumetric_fog->process_uniform_set = RID();
|
||||
rb->volumetric_fog->process_uniform_set2 = RID();
|
||||
fog->fog_uniform_set = RID();
|
||||
fog->process_uniform_set = RID();
|
||||
fog->process_uniform_set2 = RID();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3687,7 +3701,14 @@ void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buff
|
||||
}
|
||||
}
|
||||
|
||||
void GI::RenderBuffersGI::free() {
|
||||
RID GI::RenderBuffersGI::get_voxel_gi_buffer() {
|
||||
if (voxel_gi_buffer.is_null()) {
|
||||
voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES);
|
||||
}
|
||||
return voxel_gi_buffer;
|
||||
}
|
||||
|
||||
void GI::RenderBuffersGI::free_data() {
|
||||
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||
if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) {
|
||||
RD::get_singleton()->free(uniform_set[v]);
|
||||
@ -3700,28 +3721,13 @@ void GI::RenderBuffersGI::free() {
|
||||
scene_data_ubo = RID();
|
||||
}
|
||||
|
||||
if (ambient_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(ambient_buffer);
|
||||
RD::get_singleton()->free(reflection_buffer);
|
||||
ambient_buffer = RID();
|
||||
reflection_buffer = RID();
|
||||
|
||||
// these are automatically freed when we free the textures, so just reset..
|
||||
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||
ambient_slice[v] = RID();
|
||||
reflection_slice[v] = RID();
|
||||
}
|
||||
|
||||
view_count = 0;
|
||||
}
|
||||
|
||||
if (voxel_gi_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(voxel_gi_buffer);
|
||||
voxel_gi_buffer = RID();
|
||||
}
|
||||
}
|
||||
|
||||
void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
|
||||
void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) {
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
@ -3729,65 +3735,38 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("GI Render");
|
||||
|
||||
RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
|
||||
ERR_FAIL_COND(rb == nullptr);
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
|
||||
if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) {
|
||||
// Free our old buffer if applicable
|
||||
if (rb->rbgi.ambient_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(rb->rbgi.ambient_buffer);
|
||||
RD::get_singleton()->free(rb->rbgi.reflection_buffer);
|
||||
Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
|
||||
ERR_FAIL_COND(rbgi.is_null());
|
||||
|
||||
for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
|
||||
rb->rbgi.ambient_slice[v] = RID();
|
||||
rb->rbgi.reflection_slice[v] = RID();
|
||||
}
|
||||
}
|
||||
Size2i internal_size = p_render_buffers->get_internal_size();
|
||||
|
||||
// Remember the view count we're using
|
||||
rb->rbgi.view_count = p_view_count;
|
||||
if (rbgi->using_half_size_gi != half_resolution) {
|
||||
p_render_buffers->clear_context(RB_SCOPE_GI);
|
||||
}
|
||||
|
||||
if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
|
||||
Size2i size = internal_size;
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
// Create textures for our ambient and reflection data
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
tf.width = rb->internal_width;
|
||||
tf.height = rb->internal_height;
|
||||
if (half_resolution) {
|
||||
tf.width >>= 1;
|
||||
tf.height >>= 1;
|
||||
size.x >>= 1;
|
||||
size.y >>= 1;
|
||||
}
|
||||
if (p_view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
tf.array_layers = p_view_count;
|
||||
} else {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
tf.array_layers = 1;
|
||||
}
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer");
|
||||
rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer");
|
||||
rb->rbgi.using_half_size_gi = half_resolution;
|
||||
|
||||
if (p_view_count == 1) {
|
||||
// Just copy, we don't need to create slices
|
||||
rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer;
|
||||
rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer;
|
||||
} else {
|
||||
for (uint32_t v = 0; v < p_view_count; v++) {
|
||||
rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0);
|
||||
rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0);
|
||||
}
|
||||
}
|
||||
p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
|
||||
p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
|
||||
|
||||
rbgi->using_half_size_gi = half_resolution;
|
||||
}
|
||||
|
||||
// Setup our scene data
|
||||
{
|
||||
SceneData scene_data;
|
||||
|
||||
if (rb->rbgi.scene_data_ubo.is_null()) {
|
||||
rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
|
||||
if (rbgi->scene_data_ubo.is_null()) {
|
||||
rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
|
||||
}
|
||||
|
||||
for (uint32_t v = 0; v < p_view_count; v++) {
|
||||
@ -3801,10 +3780,10 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
// Note that we will be ignoring the origin of this transform.
|
||||
RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform);
|
||||
|
||||
scene_data.screen_size[0] = rb->internal_width;
|
||||
scene_data.screen_size[1] = rb->internal_height;
|
||||
scene_data.screen_size[0] = internal_size.x;
|
||||
scene_data.screen_size[1] = internal_size.y;
|
||||
|
||||
RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
|
||||
RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
|
||||
}
|
||||
|
||||
// Now compute the contents of our buffers.
|
||||
@ -3826,22 +3805,28 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
push_constant.z_far = p_projections[0].get_z_far();
|
||||
|
||||
// these are only used if we have 1 view, else we use the projections in our scene data
|
||||
push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]);
|
||||
push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]);
|
||||
push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].matrix[0][0]);
|
||||
push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].matrix[1][1]);
|
||||
push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0];
|
||||
push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1];
|
||||
|
||||
bool use_sdfgi = rb->sdfgi != nullptr;
|
||||
bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);
|
||||
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
|
||||
|
||||
Ref<SDFGI> sdfgi;
|
||||
if (use_sdfgi) {
|
||||
sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
|
||||
}
|
||||
|
||||
uint32_t pipeline_specialization = 0;
|
||||
if (rb->rbgi.using_half_size_gi) {
|
||||
if (rbgi->using_half_size_gi) {
|
||||
pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
|
||||
}
|
||||
if (p_view_count > 1) {
|
||||
pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
|
||||
}
|
||||
if (p_vrs_slices[0].is_valid()) {
|
||||
bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE);
|
||||
if (has_vrs_texture) {
|
||||
pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
|
||||
}
|
||||
|
||||
@ -3851,15 +3836,15 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
push_constant.view_index = v;
|
||||
|
||||
// setup our uniform set
|
||||
if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) {
|
||||
if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.binding = 1;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
|
||||
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
|
||||
u.append_id(rb->sdfgi->cascades[j].sdf_tex);
|
||||
if (use_sdfgi && j < sdfgi->cascades.size()) {
|
||||
u.append_id(sdfgi->cascades[j].sdf_tex);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
|
||||
}
|
||||
@ -3871,8 +3856,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
u.binding = 2;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
|
||||
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
|
||||
u.append_id(rb->sdfgi->cascades[j].light_tex);
|
||||
if (use_sdfgi && j < sdfgi->cascades.size()) {
|
||||
u.append_id(sdfgi->cascades[j].light_tex);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
|
||||
}
|
||||
@ -3884,8 +3869,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
u.binding = 3;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
|
||||
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
|
||||
u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
|
||||
if (use_sdfgi && j < sdfgi->cascades.size()) {
|
||||
u.append_id(sdfgi->cascades[j].light_aniso_0_tex);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
|
||||
}
|
||||
@ -3897,8 +3882,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
u.binding = 4;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
|
||||
if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
|
||||
u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
|
||||
if (use_sdfgi && j < sdfgi->cascades.size()) {
|
||||
u.append_id(sdfgi->cascades[j].light_aniso_1_tex);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
|
||||
}
|
||||
@ -3909,8 +3894,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 5;
|
||||
if (rb->sdfgi) {
|
||||
u.append_id(rb->sdfgi->occlusion_texture);
|
||||
if (use_sdfgi) {
|
||||
u.append_id(sdfgi->occlusion_texture);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
|
||||
}
|
||||
@ -3935,7 +3920,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 9;
|
||||
u.append_id(rb->rbgi.ambient_slice[v]);
|
||||
u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -3943,7 +3928,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 10;
|
||||
u.append_id(rb->rbgi.reflection_slice[v]);
|
||||
u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
@ -3951,8 +3936,8 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 11;
|
||||
if (rb->sdfgi) {
|
||||
u.append_id(rb->sdfgi->lightprobe_texture);
|
||||
if (use_sdfgi) {
|
||||
u.append_id(sdfgi->lightprobe_texture);
|
||||
} else {
|
||||
u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
|
||||
}
|
||||
@ -3962,7 +3947,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 12;
|
||||
u.append_id(rb->views[v].view_depth);
|
||||
u.append_id(p_render_buffers->get_depth_texture(v));
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
@ -3991,7 +3976,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.binding = 16;
|
||||
u.append_id(rb->rbgi.voxel_gi_buffer);
|
||||
u.append_id(rbgi->get_voxel_gi_buffer());
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
@ -3999,7 +3984,7 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 17;
|
||||
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
|
||||
u.append_id(rb->rbgi.voxel_gi_textures[i]);
|
||||
u.append_id(rbgi->voxel_gi_textures[i]);
|
||||
}
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
@ -4007,29 +3992,29 @@ void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices,
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.binding = 18;
|
||||
u.append_id(rb->rbgi.scene_data_ubo);
|
||||
u.append_id(rbgi->scene_data_ubo);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
|
||||
u.binding = 19;
|
||||
RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
|
||||
RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
|
||||
u.append_id(buffer);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
|
||||
rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
||||
|
||||
if (rb->rbgi.using_half_size_gi) {
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
|
||||
if (rbgi->using_half_size_gi) {
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1);
|
||||
} else {
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4053,21 +4038,21 @@ void GI::voxel_gi_instance_free(RID p_rid) {
|
||||
}
|
||||
|
||||
void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
|
||||
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
|
||||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_COND(!voxel_gi);
|
||||
|
||||
voxel_gi->transform = p_xform;
|
||||
}
|
||||
|
||||
bool GI::voxel_gi_needs_update(RID p_probe) const {
|
||||
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
|
||||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_COND_V(!voxel_gi, false);
|
||||
|
||||
return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
|
||||
}
|
||||
|
||||
void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
|
||||
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
|
||||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_COND(!voxel_gi);
|
||||
|
||||
voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
|
||||
|
@ -44,10 +44,17 @@
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering/storage/utilities.h"
|
||||
|
||||
#define RB_SCOPE_GI SNAME("rbgi")
|
||||
#define RB_SCOPE_SDFGI SNAME("sdfgi")
|
||||
|
||||
#define RB_TEX_AMBIENT SNAME("ambient")
|
||||
#define RB_TEX_REFLECTION SNAME("reflection")
|
||||
|
||||
// Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
|
||||
struct RenderDataRD;
|
||||
class RendererSceneRenderRD;
|
||||
@ -89,6 +96,60 @@ public:
|
||||
Dependency dependency;
|
||||
};
|
||||
|
||||
/* VOXEL_GI INSTANCE */
|
||||
|
||||
//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
|
||||
|
||||
struct VoxelGIInstance {
|
||||
// access to our containers
|
||||
GI *gi = nullptr;
|
||||
|
||||
RID probe;
|
||||
RID texture;
|
||||
RID write_buffer;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
RID uniform_set;
|
||||
RID second_bounce_uniform_set;
|
||||
RID write_uniform_set;
|
||||
uint32_t level;
|
||||
uint32_t cell_offset;
|
||||
uint32_t cell_count;
|
||||
};
|
||||
Vector<Mipmap> mipmaps;
|
||||
|
||||
struct DynamicMap {
|
||||
RID texture; //color normally, or emission on first pass
|
||||
RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
|
||||
RID depth; //actual depth buffer for the first pass, float depth for later passes
|
||||
RID normal; //normal buffer for the first pass
|
||||
RID albedo; //emission buffer for the first pass
|
||||
RID orm; //orm buffer for the first pass
|
||||
RID fb; //used for rendering, only valid on first map
|
||||
RID uniform_set;
|
||||
uint32_t size;
|
||||
int mipmap; // mipmap to write to, -1 if no mipmap assigned
|
||||
};
|
||||
|
||||
Vector<DynamicMap> dynamic_maps;
|
||||
|
||||
int slot = -1;
|
||||
uint32_t last_probe_version = 0;
|
||||
uint32_t last_probe_data_version = 0;
|
||||
|
||||
//uint64_t last_pass = 0;
|
||||
uint32_t render_index = 0;
|
||||
|
||||
bool has_dynamic_object_data = false;
|
||||
|
||||
Transform3D transform;
|
||||
|
||||
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
|
||||
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
|
||||
void free_resources();
|
||||
};
|
||||
|
||||
private:
|
||||
static GI *singleton;
|
||||
|
||||
@ -98,6 +159,8 @@ private:
|
||||
|
||||
/* VOXEL_GI INSTANCE */
|
||||
|
||||
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
|
||||
|
||||
struct VoxelGILight {
|
||||
uint32_t type;
|
||||
float energy;
|
||||
@ -370,9 +433,40 @@ private:
|
||||
public:
|
||||
static GI *get_singleton() { return singleton; }
|
||||
|
||||
/* GI */
|
||||
|
||||
enum {
|
||||
MAX_VOXEL_GI_INSTANCES = 8
|
||||
};
|
||||
|
||||
// Struct for use in render buffer
|
||||
class RenderBuffersGI : public RenderBufferCustomDataRD {
|
||||
GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD)
|
||||
|
||||
private:
|
||||
RID voxel_gi_buffer;
|
||||
|
||||
public:
|
||||
RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
|
||||
|
||||
RID full_buffer;
|
||||
RID full_dispatch;
|
||||
RID full_mask;
|
||||
|
||||
/* GI buffers */
|
||||
bool using_half_size_gi = false;
|
||||
|
||||
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID scene_data_ubo;
|
||||
|
||||
RID get_voxel_gi_buffer();
|
||||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
||||
virtual void free_data() override;
|
||||
};
|
||||
|
||||
/* VOXEL GI API */
|
||||
|
||||
VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); };
|
||||
bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
|
||||
|
||||
virtual RID voxel_gi_allocate() override;
|
||||
@ -422,72 +516,23 @@ public:
|
||||
|
||||
RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
|
||||
|
||||
Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const;
|
||||
|
||||
/* VOXEL_GI INSTANCE */
|
||||
|
||||
//@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
|
||||
|
||||
struct VoxelGIInstance {
|
||||
// access to our containers
|
||||
GI *gi = nullptr;
|
||||
|
||||
RID probe;
|
||||
RID texture;
|
||||
RID write_buffer;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
RID uniform_set;
|
||||
RID second_bounce_uniform_set;
|
||||
RID write_uniform_set;
|
||||
uint32_t level;
|
||||
uint32_t cell_offset;
|
||||
uint32_t cell_count;
|
||||
};
|
||||
Vector<Mipmap> mipmaps;
|
||||
|
||||
struct DynamicMap {
|
||||
RID texture; //color normally, or emission on first pass
|
||||
RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
|
||||
RID depth; //actual depth buffer for the first pass, float depth for later passes
|
||||
RID normal; //normal buffer for the first pass
|
||||
RID albedo; //emission buffer for the first pass
|
||||
RID orm; //orm buffer for the first pass
|
||||
RID fb; //used for rendering, only valid on first map
|
||||
RID uniform_set;
|
||||
uint32_t size;
|
||||
int mipmap; // mipmap to write to, -1 if no mipmap assigned
|
||||
};
|
||||
|
||||
Vector<DynamicMap> dynamic_maps;
|
||||
|
||||
int slot = -1;
|
||||
uint32_t last_probe_version = 0;
|
||||
uint32_t last_probe_data_version = 0;
|
||||
|
||||
//uint64_t last_pass = 0;
|
||||
uint32_t render_index = 0;
|
||||
|
||||
bool has_dynamic_object_data = false;
|
||||
|
||||
Transform3D transform;
|
||||
|
||||
void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
|
||||
void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
|
||||
void free_resources();
|
||||
};
|
||||
|
||||
mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
|
||||
|
||||
_FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
|
||||
return voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
|
||||
VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
|
||||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_COND_V(!voxel_gi, RID());
|
||||
return voxel_gi->texture;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) {
|
||||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_NULL(voxel_gi);
|
||||
|
||||
voxel_gi->render_index = p_index;
|
||||
};
|
||||
|
||||
bool voxel_gi_instance_owns(RID p_rid) const {
|
||||
return voxel_gi_instance_owner.owns(p_rid);
|
||||
}
|
||||
@ -498,7 +543,10 @@ public:
|
||||
|
||||
/* SDFGI */
|
||||
|
||||
struct SDFGI {
|
||||
class SDFGI : public RenderBufferCustomDataRD {
|
||||
GDCLASS(SDFGI, RenderBufferCustomDataRD)
|
||||
|
||||
public:
|
||||
enum {
|
||||
MAX_CASCADES = 8,
|
||||
CASCADE_SIZE = 128,
|
||||
@ -624,8 +672,11 @@ public:
|
||||
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
|
||||
RID integrate_sky_uniform_set;
|
||||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
||||
virtual void free_data() override;
|
||||
~SDFGI();
|
||||
|
||||
void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
|
||||
void erase();
|
||||
void update(RID p_env, const Vector3 &p_world_position);
|
||||
void update_light();
|
||||
void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky);
|
||||
@ -637,8 +688,8 @@ public:
|
||||
void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
|
||||
|
||||
void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
|
||||
void render_region(RID p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
|
||||
void render_static_lights(RenderDataRD *p_render_data, RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
|
||||
void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render, float p_exposure_normalization);
|
||||
void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
|
||||
};
|
||||
|
||||
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
|
||||
@ -655,34 +706,6 @@ public:
|
||||
|
||||
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
|
||||
|
||||
/* GI */
|
||||
enum {
|
||||
MAX_VOXEL_GI_INSTANCES = 8
|
||||
};
|
||||
|
||||
// Struct for use in render buffer
|
||||
struct RenderBuffersGI {
|
||||
RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
|
||||
RID voxel_gi_buffer;
|
||||
|
||||
RID full_buffer;
|
||||
RID full_dispatch;
|
||||
RID full_mask;
|
||||
|
||||
/* GI buffers */
|
||||
RID ambient_buffer;
|
||||
RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID reflection_buffer;
|
||||
RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
bool using_half_size_gi = false;
|
||||
uint32_t view_count = 1;
|
||||
|
||||
RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID scene_data_ubo;
|
||||
|
||||
void free();
|
||||
};
|
||||
|
||||
struct SDFGIData {
|
||||
float grid_size[3];
|
||||
uint32_t max_cascades;
|
||||
@ -787,10 +810,10 @@ public:
|
||||
void init(RendererRD::SkyRD *p_sky);
|
||||
void free();
|
||||
|
||||
SDFGI *create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
|
||||
Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
|
||||
|
||||
void setup_voxel_gi_instances(RenderDataRD *p_render_data, RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
|
||||
void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
|
||||
void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
|
||||
void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances);
|
||||
|
||||
RID voxel_gi_instance_create(RID p_base);
|
||||
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/rendering_server_globals.h"
|
||||
@ -1109,7 +1110,7 @@ SkyRD::~SkyRD() {
|
||||
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
|
||||
}
|
||||
|
||||
void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
|
||||
void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
|
||||
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_env.is_null());
|
||||
@ -1294,24 +1295,25 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh
|
||||
//setup fog variables
|
||||
sky_scene_state.ubo.volumetric_fog_enabled = false;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) {
|
||||
if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
|
||||
Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
|
||||
sky_scene_state.ubo.volumetric_fog_enabled = true;
|
||||
|
||||
float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers);
|
||||
float fog_end = fog->length;
|
||||
if (fog_end > 0.0) {
|
||||
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
|
||||
} else {
|
||||
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
|
||||
}
|
||||
|
||||
float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
|
||||
float fog_detail_spread = fog->spread; //reverse lookup
|
||||
if (fog_detail_spread > 0.0) {
|
||||
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
|
||||
} else {
|
||||
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
|
||||
}
|
||||
|
||||
sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
|
||||
sky_scene_state.fog_uniform_set = fog->sky_uniform_set;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
// 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 {
|
||||
|
||||
@ -296,7 +297,7 @@ public:
|
||||
void set_texture_format(RD::DataFormat p_texture_format);
|
||||
~SkyRD();
|
||||
|
||||
void setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
|
||||
void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
|
||||
void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
|
||||
void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer
|
||||
void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,12 +33,22 @@
|
||||
|
||||
#include "core/templates/paged_allocator.h"
|
||||
#include "servers/rendering/renderer_rd/effects/resolve.h"
|
||||
#include "servers/rendering/renderer_rd/effects/taa.h"
|
||||
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
|
||||
|
||||
#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
|
||||
|
||||
#define RB_TEX_SPECULAR SNAME("specular")
|
||||
#define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa")
|
||||
#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss")
|
||||
#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa")
|
||||
#define RB_TEX_VOXEL_GI SNAME("voxel_gi")
|
||||
#define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa")
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
@ -81,73 +91,67 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
|
||||
/* Framebuffer */
|
||||
|
||||
struct RenderBufferDataForwardClustered : public RenderBufferData {
|
||||
class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD {
|
||||
GDCLASS(RenderBufferDataForwardClustered, RenderBufferCustomDataRD)
|
||||
|
||||
private:
|
||||
RenderSceneBuffersRD *render_buffers = nullptr;
|
||||
RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
|
||||
|
||||
public:
|
||||
//for rendering, may be MSAAd
|
||||
|
||||
RID color;
|
||||
RID depth;
|
||||
RID specular;
|
||||
RID normal_roughness_buffer;
|
||||
RID voxelgi_buffer;
|
||||
RID velocity_buffer;
|
||||
|
||||
RS::ViewportMSAA msaa;
|
||||
RD::TextureSamples texture_samples;
|
||||
bool use_taa;
|
||||
|
||||
RID color_msaa;
|
||||
RID depth_msaa;
|
||||
RID specular_msaa;
|
||||
RID normal_roughness_buffer_msaa;
|
||||
RID voxelgi_buffer_msaa;
|
||||
RID velocity_buffer_msaa;
|
||||
|
||||
RID depth_fb;
|
||||
RID depth_normal_roughness_fb;
|
||||
RID depth_normal_roughness_voxelgi_fb;
|
||||
RID color_only_fb;
|
||||
RID specular_only_fb;
|
||||
|
||||
RID vrs;
|
||||
|
||||
int width, height;
|
||||
HashMap<uint32_t, RID> color_framebuffers;
|
||||
|
||||
// for multiview
|
||||
uint32_t view_count = 1;
|
||||
RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
||||
RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this
|
||||
RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID specular_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
enum DepthFrameBufferType {
|
||||
DEPTH_FB,
|
||||
DEPTH_FB_ROUGHNESS,
|
||||
DEPTH_FB_ROUGHNESS_VOXELGI
|
||||
};
|
||||
|
||||
RID render_sdfgi_uniform_set;
|
||||
void ensure_specular();
|
||||
void ensure_voxelgi();
|
||||
void ensure_velocity();
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
|
||||
RID get_color_pass_fb(uint32_t p_color_pass_flags);
|
||||
|
||||
~RenderBufferDataForwardClustered();
|
||||
RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA); }
|
||||
RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, p_layer, 0); }
|
||||
|
||||
RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA); }
|
||||
RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, p_layer, 0); }
|
||||
|
||||
void ensure_specular();
|
||||
bool has_specular() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
|
||||
RID get_specular() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
|
||||
RID get_specular(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, p_layer, 0); }
|
||||
RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); }
|
||||
|
||||
void ensure_normal_roughness_texture();
|
||||
bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
|
||||
RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
|
||||
RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); }
|
||||
RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); }
|
||||
RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); }
|
||||
|
||||
void ensure_voxelgi();
|
||||
bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
|
||||
RID get_voxelgi() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
|
||||
RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); }
|
||||
RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); }
|
||||
|
||||
RID get_color_only_fb();
|
||||
RID get_color_pass_fb(uint32_t p_color_pass_flags);
|
||||
RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB);
|
||||
RID get_specular_only_fb();
|
||||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
|
||||
virtual void free_data() override;
|
||||
};
|
||||
|
||||
virtual RenderBufferData *_create_render_buffer_data() override;
|
||||
void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
|
||||
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
RID render_base_uniform_set;
|
||||
|
||||
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
|
||||
|
||||
virtual void _base_uniforms_changed() override;
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
bool base_uniform_set_updated = false;
|
||||
void _update_render_base_uniform_set();
|
||||
@ -612,6 +616,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
||||
virtual void _update_shader_quality_settings() override;
|
||||
|
||||
RendererRD::Resolve *resolve_effects = nullptr;
|
||||
RendererRD::TAA *taa = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
|
||||
@ -623,7 +628,7 @@ protected:
|
||||
|
||||
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
|
||||
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
|
||||
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
|
||||
|
||||
public:
|
||||
|
@ -69,102 +69,28 @@ void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id,
|
||||
|
||||
/* Render buffer */
|
||||
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
|
||||
if (color_msaa.is_valid()) {
|
||||
RD::get_singleton()->free(color_msaa);
|
||||
color_msaa = RID();
|
||||
}
|
||||
|
||||
if (depth_msaa.is_valid()) {
|
||||
RD::get_singleton()->free(depth_msaa);
|
||||
depth_msaa = RID();
|
||||
}
|
||||
|
||||
color = RID();
|
||||
depth = RID();
|
||||
for (int i = 0; i < FB_CONFIG_MAX; i++) {
|
||||
color_fbs[i] = RID();
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() {
|
||||
// this should already be done but JIC..
|
||||
if (render_buffers) {
|
||||
render_buffers->clear_context(RB_SCOPE_MOBILE);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) {
|
||||
clear();
|
||||
void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBuffersRD *p_render_buffers) {
|
||||
if (render_buffers) {
|
||||
// JIC
|
||||
free_data();
|
||||
}
|
||||
|
||||
msaa = p_msaa;
|
||||
vrs = p_vrs_texture;
|
||||
render_buffers = p_render_buffers;
|
||||
ERR_FAIL_NULL(render_buffers); // Huh? really?
|
||||
|
||||
Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
|
||||
RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
|
||||
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
// Create our MSAA textures...
|
||||
|
||||
width = p_width;
|
||||
height = p_height;
|
||||
bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
|
||||
view_count = p_view_count;
|
||||
|
||||
color = p_color_buffer;
|
||||
depth = p_depth_buffer;
|
||||
|
||||
// We are creating 4 configurations here for our framebuffers.
|
||||
|
||||
if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
|
||||
Vector<RID> fb;
|
||||
fb.push_back(p_color_buffer); // 0 - color buffer
|
||||
fb.push_back(depth); // 1 - depth buffer
|
||||
if (vrs.is_valid()) {
|
||||
fb.push_back(vrs); // 2 - vrs texture
|
||||
}
|
||||
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
|
||||
// re-using the same attachments
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
if (vrs.is_valid()) {
|
||||
pass.vrs_attachment = 2;
|
||||
}
|
||||
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
// - add sky pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
// - add alpha pass
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
if (!is_scaled) {
|
||||
// - add blit to 2D pass
|
||||
int target_buffer_id = fb.size();
|
||||
fb.push_back(p_target_buffer); // 2/3 - target buffer
|
||||
|
||||
RD::FramebufferPass blit_pass;
|
||||
blit_pass.color_attachments.push_back(target_buffer_id);
|
||||
blit_pass.input_attachments.push_back(0);
|
||||
passes.push_back(blit_pass); // this doesn't need VRS
|
||||
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
} else {
|
||||
// can't do our blit pass if resolutions don't match
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
|
||||
}
|
||||
} else {
|
||||
RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
|
||||
|
||||
RD::TextureFormat tf;
|
||||
if (view_count > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
} else {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
}
|
||||
tf.format = color_format;
|
||||
tf.width = p_width;
|
||||
tf.height = p_height;
|
||||
tf.array_layers = view_count; // create a layer for every view
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
RD::DataFormat format = render_buffers->get_base_data_format();
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
|
||||
RD::TEXTURE_SAMPLES_1,
|
||||
@ -173,79 +99,145 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b
|
||||
RD::TEXTURE_SAMPLES_8,
|
||||
};
|
||||
|
||||
texture_samples = ts[p_msaa];
|
||||
tf.samples = texture_samples;
|
||||
texture_samples = ts[msaa_3d];
|
||||
|
||||
color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
|
||||
|
||||
tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Vector<RID> fb;
|
||||
fb.push_back(color_msaa); // 0 - msaa color buffer
|
||||
fb.push_back(depth_msaa); // 1 - msaa depth buffer
|
||||
if (vrs.is_valid()) {
|
||||
fb.push_back(vrs); // 2 - vrs texture
|
||||
RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
|
||||
ERR_FAIL_NULL_V(render_buffers, RID());
|
||||
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
ERR_FAIL_NULL_V(texture_storage, RID());
|
||||
|
||||
// We use our framebuffer cache here instead of building these in RenderBufferDataForwardMobile::configure
|
||||
// This approach ensures we only build the framebuffers we actually need for this viewport.
|
||||
// In the (near) future this means that if we cycle through a texture chain for our render target, we'll also support
|
||||
// this.
|
||||
|
||||
RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
|
||||
bool use_msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
|
||||
|
||||
uint32_t view_count = render_buffers->get_view_count();
|
||||
|
||||
RID vrs_texture;
|
||||
if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
|
||||
vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
|
||||
}
|
||||
|
||||
Vector<RID> textures;
|
||||
int color_buffer_id = 0;
|
||||
textures.push_back(use_msaa ? get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer
|
||||
textures.push_back(use_msaa ? get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer
|
||||
if (vrs_texture.is_valid()) {
|
||||
textures.push_back(vrs_texture); // 2 - vrs texture
|
||||
}
|
||||
if (use_msaa) {
|
||||
color_buffer_id = textures.size();
|
||||
textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve
|
||||
|
||||
// TODO add support for resolving depth buffer!!!
|
||||
}
|
||||
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
|
||||
// Define our base pass, we'll be re-using this
|
||||
RD::FramebufferPass pass;
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
if (vrs_texture.is_valid()) {
|
||||
pass.vrs_attachment = 2;
|
||||
}
|
||||
|
||||
switch (p_config_type) {
|
||||
case FB_CONFIG_ONE_PASS: {
|
||||
// just one pass
|
||||
if (use_msaa) {
|
||||
// Add resolve
|
||||
pass.resolve_attachments.push_back(color_buffer_id);
|
||||
}
|
||||
passes.push_back(pass);
|
||||
|
||||
// Now define our subpasses
|
||||
Vector<RD::FramebufferPass> passes;
|
||||
RD::FramebufferPass pass;
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
|
||||
} break;
|
||||
case FB_CONFIG_TWO_SUBPASSES: {
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// re-using the same attachments
|
||||
pass.color_attachments.push_back(0);
|
||||
pass.depth_attachment = 1;
|
||||
if (vrs.is_valid()) {
|
||||
pass.vrs_attachment = 2;
|
||||
// - add sky pass
|
||||
if (use_msaa) {
|
||||
// add resolve
|
||||
pass.resolve_attachments.push_back(color_buffer_id);
|
||||
}
|
||||
passes.push_back(pass);
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
|
||||
} break;
|
||||
case FB_CONFIG_THREE_SUBPASSES: {
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - add sky pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - add alpha pass
|
||||
if (use_msaa) {
|
||||
// add resolve
|
||||
pass.resolve_attachments.push_back(color_buffer_id);
|
||||
}
|
||||
passes.push_back(pass);
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
|
||||
} break;
|
||||
case FB_CONFIG_FOUR_SUBPASSES: {
|
||||
Size2i target_size = render_buffers->get_target_size();
|
||||
Size2i internal_size = render_buffers->get_internal_size();
|
||||
|
||||
// can't do our blit pass if resolutions don't match
|
||||
ERR_FAIL_COND_V(target_size != internal_size, RID());
|
||||
|
||||
// - opaque pass
|
||||
passes.push_back(pass);
|
||||
|
||||
// - add sky pass
|
||||
int color_buffer_id = fb.size();
|
||||
fb.push_back(color); // color buffer
|
||||
passes.push_back(pass); // without resolve for our 3 + 4 subpass config
|
||||
{
|
||||
// but with resolve for our 2 subpass config
|
||||
Vector<RD::FramebufferPass> two_passes;
|
||||
two_passes.push_back(pass); // opaque subpass without resolve
|
||||
pass.resolve_attachments.push_back(color_buffer_id);
|
||||
two_passes.push_back(pass); // sky subpass with resolve
|
||||
|
||||
color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
|
||||
}
|
||||
|
||||
// - add alpha pass (with resolve, we just added that above)
|
||||
passes.push_back(pass);
|
||||
color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
|
||||
{
|
||||
// we also need our one pass with resolve
|
||||
Vector<RD::FramebufferPass> one_pass_with_resolve;
|
||||
one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
|
||||
color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
|
||||
// - add alpha pass
|
||||
if (use_msaa) {
|
||||
// add resolve
|
||||
pass.resolve_attachments.push_back(color_buffer_id);
|
||||
}
|
||||
passes.push_back(pass);
|
||||
|
||||
if (!is_scaled) {
|
||||
// - add blit to 2D pass
|
||||
int target_buffer_id = fb.size();
|
||||
fb.push_back(p_target_buffer); // target buffer
|
||||
RD::FramebufferPass blit_pass;
|
||||
blit_pass.color_attachments.push_back(target_buffer_id);
|
||||
blit_pass.input_attachments.push_back(color_buffer_id);
|
||||
passes.push_back(blit_pass);
|
||||
// - add blit to 2D pass
|
||||
RID render_target = render_buffers->get_render_target();
|
||||
ERR_FAIL_COND_V(render_target.is_null(), RID());
|
||||
RID target_buffer = texture_storage->render_target_get_rd_texture(render_target);
|
||||
ERR_FAIL_COND_V(target_buffer.is_null(), RID());
|
||||
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
|
||||
} else {
|
||||
// can't do our blit pass if resolutions don't match
|
||||
color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
|
||||
}
|
||||
}
|
||||
}
|
||||
int target_buffer_id = textures.size();
|
||||
textures.push_back(target_buffer); // target buffer
|
||||
|
||||
RD::FramebufferPass blit_pass;
|
||||
blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer
|
||||
blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer
|
||||
// this doesn't need VRS
|
||||
passes.push_back(blit_pass);
|
||||
|
||||
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
|
||||
@ -274,12 +266,11 @@ RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_
|
||||
return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
|
||||
}
|
||||
|
||||
RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
|
||||
clear();
|
||||
}
|
||||
void RenderForwardMobile::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
Ref<RenderBufferDataForwardMobile> data;
|
||||
data.instantiate();
|
||||
|
||||
RendererSceneRenderRD::RenderBufferData *RenderForwardMobile::_create_render_buffer_data() {
|
||||
return memnew(RenderBufferDataForwardMobile);
|
||||
p_render_buffers->set_custom_data(RB_SCOPE_MOBILE, data);
|
||||
}
|
||||
|
||||
bool RenderForwardMobile::free(RID p_rid) {
|
||||
@ -314,9 +305,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
|
||||
//there should always be enough uniform buffers for render passes, otherwise bugs
|
||||
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
|
||||
|
||||
RenderBufferDataForwardMobile *rb = nullptr;
|
||||
Ref<RenderBufferDataForwardMobile> rb_data;
|
||||
Ref<RenderSceneBuffersRD> rb;
|
||||
if (p_render_data && p_render_data->render_buffers.is_valid()) {
|
||||
rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
|
||||
rb = p_render_data->render_buffers;
|
||||
rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
|
||||
}
|
||||
|
||||
// default render buffer and scene state uniform set
|
||||
@ -442,8 +435,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
|
||||
RD::Uniform u;
|
||||
u.binding = 9;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
|
||||
RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
|
||||
RID texture;
|
||||
if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) {
|
||||
texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH);
|
||||
} else {
|
||||
texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
|
||||
}
|
||||
u.append_id(texture);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
@ -451,7 +448,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
|
||||
RD::Uniform u;
|
||||
u.binding = 10;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
|
||||
RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID();
|
||||
RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
|
||||
u.append_id(texture);
|
||||
uniforms.push_back(u);
|
||||
@ -500,9 +497,9 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co
|
||||
}
|
||||
|
||||
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
|
||||
RenderBufferDataForwardMobile *render_buffer = nullptr;
|
||||
Ref<RenderBufferDataForwardMobile> rb_data;
|
||||
if (p_render_data->render_buffers.is_valid()) {
|
||||
render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
|
||||
rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE);
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Setup 3D Scene");
|
||||
@ -538,12 +535,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
|
||||
}
|
||||
|
||||
if (render_buffer) {
|
||||
if (rb_data.is_valid()) {
|
||||
// setup rendering to render buffer
|
||||
screen_size.x = render_buffer->width;
|
||||
screen_size.y = render_buffer->height;
|
||||
screen_size = p_render_data->render_buffers->get_internal_size();
|
||||
|
||||
if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
|
||||
if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
|
||||
// can't do blit subpass
|
||||
using_subpass_post_process = false;
|
||||
} else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
|
||||
@ -559,13 +555,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
|
||||
if (using_subpass_post_process) {
|
||||
// all as subpasses
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
|
||||
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
|
||||
} else if (using_subpass_transparent) {
|
||||
// our tonemap pass is separate
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
|
||||
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES);
|
||||
} else {
|
||||
// only opaque and sky as subpasses
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
|
||||
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES);
|
||||
}
|
||||
} else if (p_render_data->reflection_probe.is_valid()) {
|
||||
uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
|
||||
@ -626,7 +622,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
clear_color.g *= bg_energy_multiplier;
|
||||
clear_color.b *= bg_energy_multiplier;
|
||||
/*
|
||||
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
|
||||
if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
|
||||
draw_sky_fog_only = true;
|
||||
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
|
||||
}
|
||||
@ -638,7 +634,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
clear_color.g *= bg_energy_multiplier;
|
||||
clear_color.b *= bg_energy_multiplier;
|
||||
/*
|
||||
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_get_fog_enabled(p_render_data->environment)) {
|
||||
if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
|
||||
draw_sky_fog_only = true;
|
||||
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
|
||||
}
|
||||
@ -708,7 +704,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
}
|
||||
|
||||
RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS];
|
||||
_pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids);
|
||||
_pre_opaque_render(p_render_data, false, false, false, nullrids, RID());
|
||||
|
||||
uint32_t spec_constant_base_flags = 0;
|
||||
|
||||
@ -728,7 +724,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
}
|
||||
}
|
||||
{
|
||||
if (render_buffer) {
|
||||
if (rb_data.is_valid()) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
|
||||
} else {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
|
||||
@ -759,8 +755,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
// regular forward for now
|
||||
Vector<Color> c;
|
||||
c.push_back(clear_color.srgb_to_linear()); // our render buffer
|
||||
if (render_buffer) {
|
||||
if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
if (rb_data.is_valid()) {
|
||||
if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
|
||||
}
|
||||
if (using_subpass_post_process) {
|
||||
@ -859,8 +855,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
|
||||
|
||||
// blit to tonemap
|
||||
if (render_buffer && using_subpass_post_process) {
|
||||
_post_process_subpass(render_buffer->color, framebuffer, p_render_data);
|
||||
if (rb_data.is_valid() && using_subpass_post_process) {
|
||||
_post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data);
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
|
||||
@ -869,7 +865,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
} else {
|
||||
RENDER_TIMESTAMP("Render Transparent");
|
||||
|
||||
framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
|
||||
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
|
||||
|
||||
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
|
||||
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
|
||||
@ -897,7 +893,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
}
|
||||
}
|
||||
|
||||
if (render_buffer && !using_subpass_post_process) {
|
||||
if (rb_data.is_valid() && !using_subpass_post_process) {
|
||||
RD::get_singleton()->draw_command_begin_label("Post process pass");
|
||||
|
||||
// If we need extra effects we do this in its own pass
|
||||
@ -908,7 +904,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
RD::get_singleton()->draw_command_end_label(); // Post process pass
|
||||
}
|
||||
|
||||
if (render_buffer) {
|
||||
if (rb_data.is_valid()) {
|
||||
_disable_clear_request(p_render_data);
|
||||
}
|
||||
}
|
||||
@ -1132,7 +1128,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *>
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
|
||||
void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
|
||||
// we don't do GI in low end..
|
||||
}
|
||||
|
||||
@ -1364,15 +1360,11 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers) {
|
||||
// RenderBufferDataForwardMobile *rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers);
|
||||
|
||||
// We don't have this. This is for debugging
|
||||
// return rb->normal_roughness_buffer;
|
||||
RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) {
|
||||
RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
@ -1625,37 +1617,6 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data,
|
||||
//time global variables
|
||||
scene_state.ubo.time = time;
|
||||
|
||||
/*
|
||||
scene_state.ubo.gi_upscale_for_msaa = false;
|
||||
scene_state.ubo.volumetric_fog_enabled = false;
|
||||
scene_state.ubo.fog_enabled = false;
|
||||
|
||||
if (p_render_data->render_buffers.is_valid()) {
|
||||
RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
|
||||
if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
scene_state.ubo.gi_upscale_for_msaa = true;
|
||||
}
|
||||
|
||||
if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
|
||||
scene_state.ubo.volumetric_fog_enabled = true;
|
||||
float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers);
|
||||
if (fog_end > 0.0) {
|
||||
scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
|
||||
} else {
|
||||
scene_state.ubo.volumetric_fog_inv_length = 1.0;
|
||||
}
|
||||
|
||||
float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup
|
||||
if (fog_detail_spread > 0.0) {
|
||||
scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
|
||||
} else {
|
||||
scene_state.ubo.volumetric_fog_detail_spread = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
|
||||
scene_state.ubo.use_ambient_light = true;
|
||||
scene_state.ubo.ambient_light_color_energy[0] = 1;
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
|
||||
|
||||
#define RB_SCOPE_MOBILE SNAME("mobile")
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class RenderForwardMobile : public RendererSceneRenderRD {
|
||||
@ -107,43 +109,38 @@ protected:
|
||||
|
||||
/* Render Buffer */
|
||||
|
||||
// We can have:
|
||||
// - 4 subpasses combining the full render cycle
|
||||
// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
enum RenderBufferMobileFramebufferConfigType {
|
||||
FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
|
||||
FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
|
||||
FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
|
||||
FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
|
||||
FB_CONFIG_MAX
|
||||
class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD {
|
||||
GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD);
|
||||
|
||||
public:
|
||||
// We can have:
|
||||
// - 4 subpasses combining the full render cycle
|
||||
// - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
// - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
|
||||
enum FramebufferConfigType {
|
||||
FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
|
||||
FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
|
||||
FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
|
||||
FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
|
||||
FB_CONFIG_MAX
|
||||
};
|
||||
|
||||
RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA); }
|
||||
RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, p_layer, 0); }
|
||||
|
||||
RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA); }
|
||||
RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, p_layer, 0); }
|
||||
|
||||
RID get_color_fbs(FramebufferConfigType p_config_type);
|
||||
virtual void free_data() override;
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
|
||||
|
||||
private:
|
||||
RenderSceneBuffersRD *render_buffers = nullptr;
|
||||
RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
|
||||
};
|
||||
|
||||
struct RenderBufferDataForwardMobile : public RenderBufferData {
|
||||
RID color;
|
||||
RID depth;
|
||||
// RID normal_roughness_buffer;
|
||||
|
||||
RS::ViewportMSAA msaa;
|
||||
RD::TextureSamples texture_samples;
|
||||
|
||||
RID color_msaa;
|
||||
RID depth_msaa;
|
||||
// RID normal_roughness_buffer_msaa;
|
||||
|
||||
RID vrs;
|
||||
|
||||
RID color_fbs[FB_CONFIG_MAX];
|
||||
int width, height;
|
||||
uint32_t view_count;
|
||||
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture);
|
||||
|
||||
~RenderBufferDataForwardMobile();
|
||||
};
|
||||
|
||||
virtual RenderBufferData *_create_render_buffer_data() override;
|
||||
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
/* Rendering */
|
||||
|
||||
@ -218,15 +215,15 @@ protected:
|
||||
|
||||
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
|
||||
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
|
||||
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
|
||||
|
||||
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
|
||||
|
||||
virtual void _base_uniforms_changed() override;
|
||||
void _update_render_base_uniform_set();
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
|
||||
void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
RID get_cache(Args... args) {
|
||||
uint32_t h = hash_murmur3_one_32(1); //1 view
|
||||
h = hash_murmur3_one_32(sizeof...(Args), h);
|
||||
h = _hash_args(h, args...);
|
||||
h = _hash_rids(h, args...);
|
||||
h = hash_murmur3_one_32(0, h); // 0 passes
|
||||
h = hash_fmix32(h);
|
||||
|
||||
@ -228,7 +228,7 @@ public:
|
||||
RID get_cache_multiview(uint32_t p_views, Args... args) {
|
||||
uint32_t h = hash_murmur3_one_32(p_views);
|
||||
h = hash_murmur3_one_32(sizeof...(Args), h);
|
||||
h = _hash_args(h, args...);
|
||||
h = _hash_rids(h, args...);
|
||||
h = hash_murmur3_one_32(0, h); // 0 passes
|
||||
h = hash_fmix32(h);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -37,18 +37,21 @@
|
||||
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
||||
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
|
||||
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
|
||||
#include "servers/rendering/renderer_rd/effects/fsr.h"
|
||||
#include "servers/rendering/renderer_rd/effects/ss_effects.h"
|
||||
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
|
||||
#include "servers/rendering/renderer_rd/effects/vrs.h"
|
||||
#include "servers/rendering/renderer_rd/environment/fog.h"
|
||||
#include "servers/rendering/renderer_rd/environment/gi.h"
|
||||
#include "servers/rendering/renderer_rd/environment/sky.h"
|
||||
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_scene.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
|
||||
struct RenderDataRD {
|
||||
RID render_buffers;
|
||||
Ref<RenderSceneBuffersRD> render_buffers;
|
||||
|
||||
Transform3D cam_transform;
|
||||
Projection cam_projection;
|
||||
@ -104,15 +107,12 @@ protected:
|
||||
RendererRD::BokehDOF *bokeh_dof = nullptr;
|
||||
RendererRD::CopyEffects *copy_effects = nullptr;
|
||||
RendererRD::ToneMapper *tone_mapper = nullptr;
|
||||
RendererRD::FSR *fsr = nullptr;
|
||||
RendererRD::VRS *vrs = nullptr;
|
||||
double time = 0.0;
|
||||
double time_step = 0.0;
|
||||
|
||||
struct RenderBufferData {
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0;
|
||||
virtual ~RenderBufferData() {}
|
||||
};
|
||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
|
||||
|
||||
void _setup_lights(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
|
||||
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
|
||||
@ -127,31 +127,28 @@ protected:
|
||||
|
||||
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0;
|
||||
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
|
||||
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
|
||||
|
||||
void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
|
||||
void _debug_draw_cluster(RID p_render_buffers);
|
||||
|
||||
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
|
||||
void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
|
||||
void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
|
||||
virtual void _base_uniforms_changed() = 0;
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
|
||||
|
||||
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
|
||||
void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
|
||||
void _process_sss(RID p_render_buffers, const Projection &p_camera);
|
||||
void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
|
||||
void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
|
||||
void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, const Color &p_metallic_mask, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
|
||||
void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera);
|
||||
void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
|
||||
|
||||
void _copy_framebuffer_to_ssil(RID p_render_buffers);
|
||||
void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
|
||||
void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
|
||||
bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
|
||||
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
|
||||
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
|
||||
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices);
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
|
||||
|
||||
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
|
||||
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
|
||||
@ -424,131 +421,22 @@ private:
|
||||
|
||||
bool use_physical_light_units = false;
|
||||
|
||||
/* RENDER BUFFERS */
|
||||
/* Cluster builder */
|
||||
|
||||
ClusterBuilderSharedDataRD cluster_builder_shared;
|
||||
ClusterBuilderRD *current_cluster_builder = nullptr;
|
||||
|
||||
struct RenderBuffers {
|
||||
RenderBufferData *data = nullptr;
|
||||
int internal_width = 0;
|
||||
int internal_height = 0;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
float fsr_sharpness = 0.2f;
|
||||
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
|
||||
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
bool use_taa = false;
|
||||
bool use_debanding = false;
|
||||
uint32_t view_count = 1;
|
||||
/* RENDER BUFFERS */
|
||||
|
||||
RID render_target;
|
||||
void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb);
|
||||
|
||||
uint64_t auto_exposure_version = 1;
|
||||
|
||||
RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
|
||||
RID internal_texture; //main texture for rendering to, must be filled after done rendering
|
||||
RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
|
||||
RID depth_texture; //main depth texture
|
||||
RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
||||
RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
|
||||
RID vrs_texture; // texture for vrs.
|
||||
RID vrs_fb; // framebuffer to write to our vrs texture
|
||||
|
||||
// Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
|
||||
struct View {
|
||||
RID view_texture; // texture slice for this view/layer
|
||||
RID view_depth; // depth slice for this view/layer
|
||||
RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
|
||||
};
|
||||
Vector<View> views;
|
||||
|
||||
RendererRD::GI::SDFGI *sdfgi = nullptr;
|
||||
RendererRD::GI::RenderBuffersGI rbgi;
|
||||
RendererRD::Fog::VolumetricFog *volumetric_fog = nullptr;
|
||||
|
||||
ClusterBuilderRD *cluster_builder = nullptr;
|
||||
|
||||
//built-in textures used for ping pong image processing and blurring
|
||||
struct Blur {
|
||||
RID texture;
|
||||
|
||||
struct Mipmap {
|
||||
RID texture;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// only used on mobile renderer
|
||||
RID fb;
|
||||
RID half_texture;
|
||||
RID half_fb;
|
||||
};
|
||||
|
||||
struct Layer {
|
||||
Vector<Mipmap> mipmaps;
|
||||
};
|
||||
|
||||
Vector<Layer> layers;
|
||||
};
|
||||
|
||||
Blur blur[2]; //the second one starts from the first mipmap
|
||||
|
||||
struct WeightBuffers {
|
||||
RID weight;
|
||||
RID fb; // FB with both texture and weight writing into one level lower
|
||||
};
|
||||
|
||||
// 2 full size, 2 half size
|
||||
WeightBuffers weight_buffers[4]; // Only used in raster
|
||||
|
||||
RID depth_back_texture;
|
||||
RID depth_back_fb; // only used on mobile
|
||||
|
||||
struct Luminance {
|
||||
Vector<RID> reduce;
|
||||
RID current;
|
||||
|
||||
// used only on mobile renderer
|
||||
Vector<RID> fb;
|
||||
RID current_fb;
|
||||
} luminance;
|
||||
|
||||
struct SSEffects {
|
||||
RID linear_depth;
|
||||
Vector<RID> linear_depth_slices;
|
||||
|
||||
RID downsample_uniform_set;
|
||||
|
||||
Projection last_frame_projection;
|
||||
Transform3D last_frame_transform;
|
||||
|
||||
RendererRD::SSEffects::SSAORenderBuffers ssao;
|
||||
RendererRD::SSEffects::SSILRenderBuffers ssil;
|
||||
} ss_effects;
|
||||
|
||||
RendererRD::SSEffects::SSRRenderBuffers ssr;
|
||||
|
||||
struct TAA {
|
||||
RID history;
|
||||
RID temp;
|
||||
RID prev_velocity; // Last frame velocity buffer
|
||||
} taa;
|
||||
};
|
||||
void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
|
||||
|
||||
/* GI */
|
||||
bool screen_space_roughness_limiter = false;
|
||||
float screen_space_roughness_limiter_amount = 0.25;
|
||||
float screen_space_roughness_limiter_limit = 0.18;
|
||||
|
||||
mutable RID_Owner<RenderBuffers> render_buffers_owner;
|
||||
|
||||
void _free_render_buffer_data(RenderBuffers *rb);
|
||||
void _allocate_blur_textures(RenderBuffers *rb);
|
||||
void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
|
||||
void _allocate_luminance_textures(RenderBuffers *rb);
|
||||
|
||||
void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
|
||||
|
||||
/* Cluster */
|
||||
|
||||
struct Cluster {
|
||||
@ -727,11 +615,14 @@ private:
|
||||
uint32_t volumetric_fog_depth = 128;
|
||||
bool volumetric_fog_filter_active = true;
|
||||
|
||||
void _update_volumetric_fog(RID p_render_buffers, RID p_environment, 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);
|
||||
void _update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, 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);
|
||||
|
||||
public:
|
||||
static RendererSceneRenderRD *get_singleton() { return singleton; }
|
||||
|
||||
/* Cluster builder */
|
||||
ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; }
|
||||
|
||||
/* GI */
|
||||
|
||||
RendererRD::GI *get_gi() { return &gi; }
|
||||
@ -774,10 +665,10 @@ public:
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
|
||||
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
|
||||
virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
|
||||
virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
|
||||
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
|
||||
|
||||
/* SKY API */
|
||||
@ -1071,42 +962,14 @@ public:
|
||||
virtual float _render_buffers_get_luminance_multiplier();
|
||||
virtual RD::DataFormat _render_buffers_get_color_format();
|
||||
virtual bool _render_buffers_can_be_storage();
|
||||
virtual RID render_buffers_create() override;
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
virtual Ref<RenderSceneBuffers> render_buffers_create() override;
|
||||
virtual void gi_set_use_half_resolution(bool p_enable) override;
|
||||
|
||||
RID render_buffers_get_depth_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_ao_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_ssil_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_back_depth_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
|
||||
RID render_buffers_get_default_voxel_gi_buffer();
|
||||
RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
|
||||
|
||||
uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
|
||||
bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
|
||||
RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const;
|
||||
Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const;
|
||||
float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const;
|
||||
uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const;
|
||||
uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const;
|
||||
bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const;
|
||||
float render_buffers_get_sdfgi_energy(RID p_render_buffers) const;
|
||||
RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const;
|
||||
|
||||
bool render_buffers_has_volumetric_fog(RID p_render_buffers) const;
|
||||
RID render_buffers_get_volumetric_fog_texture(RID p_render_buffers);
|
||||
RID render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers);
|
||||
float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
|
||||
float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
|
||||
|
||||
virtual void update_uniform_sets(){};
|
||||
|
||||
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
|
||||
virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
|
||||
|
||||
virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*************************************************************************/
|
||||
/* render_buffer_custom_data_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 RENDER_BUFFER_CUSTOM_DATA_RD_H
|
||||
#define RENDER_BUFFER_CUSTOM_DATA_RD_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class RenderSceneBuffersRD;
|
||||
|
||||
class RenderBufferCustomDataRD : public RefCounted {
|
||||
GDCLASS(RenderBufferCustomDataRD, RefCounted);
|
||||
|
||||
public:
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0;
|
||||
virtual void free_data() = 0; // called on cleanup
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // RENDER_BUFFER_CUSTOM_DATA_RD_H
|
@ -0,0 +1,559 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers_rd.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
|
||||
|
||||
RenderSceneBuffersRD::RenderSceneBuffersRD() {
|
||||
}
|
||||
|
||||
RenderSceneBuffersRD::~RenderSceneBuffersRD() {
|
||||
cleanup();
|
||||
|
||||
data_buffers.clear();
|
||||
|
||||
// need to investigate if we can remove these things.
|
||||
if (cluster_builder) {
|
||||
memdelete(cluster_builder);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture);
|
||||
// FIXME we can't pass RD::DataFormat, RD::TextureSamples and RD::TextureView in ClassDB, need to solve views differently...
|
||||
// ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture);
|
||||
// ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::create_texture_from_format);
|
||||
// ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
|
||||
ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
|
||||
// ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
|
||||
ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
|
||||
ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
|
||||
ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
|
||||
ERR_FAIL_COND(p_named_texture.texture.is_null());
|
||||
|
||||
uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
|
||||
p_named_texture.sizes.resize(size);
|
||||
|
||||
Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
|
||||
|
||||
for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
|
||||
for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
|
||||
uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
|
||||
|
||||
p_named_texture.sizes.ptrw()[index] = mipmap_size;
|
||||
}
|
||||
|
||||
mipmap_size.width = MAX(1, mipmap_size.width >> 1);
|
||||
mipmap_size.height = MAX(1, mipmap_size.height >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) {
|
||||
if (p_named_texture.texture.is_valid()) {
|
||||
RD::get_singleton()->free(p_named_texture.texture);
|
||||
}
|
||||
p_named_texture.texture = RID();
|
||||
p_named_texture.slices.clear(); // slices should be freed automatically as dependents...
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::cleanup() {
|
||||
// Free our data buffers (but don't destroy them)
|
||||
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
|
||||
E.value->free_data();
|
||||
}
|
||||
|
||||
// Clear our named textures
|
||||
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
|
||||
free_named_texture(E.value);
|
||||
}
|
||||
named_textures.clear();
|
||||
|
||||
// old stuff, to be re-evaluated...
|
||||
|
||||
for (int i = 0; i < luminance.fb.size(); i++) {
|
||||
RD::get_singleton()->free(luminance.fb[i]);
|
||||
}
|
||||
luminance.fb.clear();
|
||||
|
||||
for (int i = 0; i < luminance.reduce.size(); i++) {
|
||||
RD::get_singleton()->free(luminance.reduce[i]);
|
||||
}
|
||||
luminance.reduce.clear();
|
||||
|
||||
if (luminance.current_fb.is_valid()) {
|
||||
RD::get_singleton()->free(luminance.current_fb);
|
||||
luminance.current_fb = RID();
|
||||
}
|
||||
|
||||
if (luminance.current.is_valid()) {
|
||||
RD::get_singleton()->free(luminance.current);
|
||||
luminance.current = RID();
|
||||
}
|
||||
|
||||
if (ss_effects.linear_depth.is_valid()) {
|
||||
RD::get_singleton()->free(ss_effects.linear_depth);
|
||||
ss_effects.linear_depth = RID();
|
||||
ss_effects.linear_depth_slices.clear();
|
||||
}
|
||||
|
||||
sse->ssao_free(ss_effects.ssao);
|
||||
sse->ssil_free(ss_effects.ssil);
|
||||
sse->ssr_free(ssr);
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
|
||||
|
||||
target_size = p_target_size;
|
||||
internal_size = p_internal_size;
|
||||
|
||||
// FIXME, right now we do this because only our clustered renderer supports FSR upscale
|
||||
// this does mean that with linear upscale if we use subpasses, we could get into trouble.
|
||||
if (!can_be_storage) {
|
||||
internal_size = target_size;
|
||||
}
|
||||
|
||||
if (p_use_taa) {
|
||||
// Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
|
||||
// This restores sharpness in still images to be roughly at the same level as without TAA,
|
||||
// but moving scenes will still be blurrier.
|
||||
p_texture_mipmap_bias -= 0.5;
|
||||
}
|
||||
|
||||
if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
|
||||
// Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
|
||||
// If both TAA and FXAA are enabled, combine their negative LOD biases together.
|
||||
p_texture_mipmap_bias -= 0.25;
|
||||
}
|
||||
|
||||
material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
|
||||
|
||||
// need to check if we really need to do this here..
|
||||
RendererSceneRenderRD::get_singleton()->update_uniform_sets();
|
||||
|
||||
render_target = p_render_target;
|
||||
fsr_sharpness = p_fsr_sharpness;
|
||||
msaa_3d = p_msaa_3d;
|
||||
screen_space_aa = p_screen_space_aa;
|
||||
use_taa = p_use_taa;
|
||||
use_debanding = p_use_debanding;
|
||||
view_count = p_view_count;
|
||||
|
||||
/* may move this into our clustered renderer data object */
|
||||
if (can_be_storage) {
|
||||
if (cluster_builder == nullptr) {
|
||||
cluster_builder = memnew(ClusterBuilderRD);
|
||||
}
|
||||
cluster_builder->set_shared(RendererSceneRenderRD::get_singleton()->get_cluster_builder_shared());
|
||||
}
|
||||
|
||||
// cleanout any old buffers we had.
|
||||
cleanup();
|
||||
|
||||
// create our 3D render buffers
|
||||
{
|
||||
// Create our color buffer(s)
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
|
||||
|
||||
// our internal texture should have MSAA support if applicable
|
||||
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
}
|
||||
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, usage_bits);
|
||||
}
|
||||
|
||||
// Create our depth buffer
|
||||
{
|
||||
// TODO If we have depth buffer supplied externally, pick this up
|
||||
|
||||
RD::DataFormat format;
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
|
||||
format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
} else {
|
||||
format = RD::DATA_FORMAT_R32_SFLOAT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
}
|
||||
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, format, usage_bits);
|
||||
}
|
||||
|
||||
// VRS (note, our vrs object will only be set if VRS is supported)
|
||||
RID vrs_texture;
|
||||
RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
|
||||
if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
|
||||
}
|
||||
|
||||
for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
|
||||
E.value->configure(this);
|
||||
}
|
||||
|
||||
if (cluster_builder) {
|
||||
RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
cluster_builder->setup(internal_size, max_cluster_elements, get_depth_texture(), sampler, get_internal_texture());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) {
|
||||
fsr_sharpness = p_fsr_sharpness;
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) {
|
||||
use_debanding = p_use_debanding;
|
||||
}
|
||||
|
||||
// Named textures
|
||||
|
||||
bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const {
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
return named_textures.has(key);
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) {
|
||||
// Keep some useful data, we use default values when these are 0.
|
||||
Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size;
|
||||
uint32_t layers = p_layers == 0 ? view_count : p_layers;
|
||||
uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps;
|
||||
|
||||
// Create our texture
|
||||
RD::TextureFormat tf;
|
||||
tf.format = p_data_format;
|
||||
if (layers > 1) {
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
|
||||
}
|
||||
|
||||
tf.width = size.x;
|
||||
tf.height = size.y;
|
||||
tf.depth = 1;
|
||||
tf.array_layers = layers;
|
||||
tf.mipmaps = mipmaps;
|
||||
tf.usage_bits = p_usage_bits;
|
||||
tf.samples = p_texture_samples;
|
||||
|
||||
return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique);
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
|
||||
// TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
|
||||
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
// check if this is a known texture
|
||||
if (named_textures.has(key)) {
|
||||
return named_textures[key].texture;
|
||||
}
|
||||
|
||||
// Add a new entry..
|
||||
NamedTexture &named_texture = named_textures[key];
|
||||
named_texture.format = p_texture_format;
|
||||
named_texture.is_unique = p_unique;
|
||||
named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view);
|
||||
|
||||
Array arr;
|
||||
arr.push_back(p_context);
|
||||
arr.push_back(p_texture_name);
|
||||
RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr));
|
||||
|
||||
update_sizes(named_texture);
|
||||
|
||||
// The rest is lazy created..
|
||||
|
||||
return named_texture.texture;
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) {
|
||||
NTKey view_key(p_context, p_view_name);
|
||||
|
||||
// check if this is a known texture
|
||||
if (named_textures.has(view_key)) {
|
||||
return named_textures[view_key].texture;
|
||||
}
|
||||
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
ERR_FAIL_COND_V(!named_textures.has(key), RID());
|
||||
|
||||
NamedTexture &named_texture = named_textures[key];
|
||||
NamedTexture &view_texture = named_textures[view_key];
|
||||
|
||||
view_texture.format = named_texture.format;
|
||||
view_texture.is_unique = named_texture.is_unique;
|
||||
|
||||
view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture);
|
||||
|
||||
Array arr;
|
||||
arr.push_back(p_context);
|
||||
arr.push_back(p_view_name);
|
||||
RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr));
|
||||
|
||||
update_sizes(named_texture);
|
||||
|
||||
return view_texture.texture;
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const {
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
ERR_FAIL_COND_V(!named_textures.has(key), RID());
|
||||
|
||||
return named_textures[key].texture;
|
||||
}
|
||||
|
||||
const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat());
|
||||
|
||||
return named_textures[key].format;
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
// check if this is a known texture
|
||||
ERR_FAIL_COND_V(!named_textures.has(key), RID());
|
||||
NamedTexture &named_texture = named_textures[key];
|
||||
ERR_FAIL_COND_V(named_texture.texture.is_null(), RID());
|
||||
|
||||
// check if we're in bounds
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
|
||||
|
||||
// if we don't have multiple layers or mipmaps, we can just return our texture as is
|
||||
if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
|
||||
return named_texture.texture;
|
||||
}
|
||||
|
||||
// get our index and make sure we have enough entries in our slices vector
|
||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
||||
while (named_texture.slices.size() <= int(index)) {
|
||||
named_texture.slices.push_back(RID());
|
||||
}
|
||||
|
||||
// create our slice if we don't have it already
|
||||
if (named_texture.slices[index].is_null()) {
|
||||
named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
|
||||
|
||||
Array arr;
|
||||
arr.push_back(p_context);
|
||||
arr.push_back(p_texture_name);
|
||||
arr.push_back(itos(p_layer));
|
||||
arr.push_back(itos(p_mipmap));
|
||||
RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
|
||||
}
|
||||
|
||||
// and return our slice
|
||||
return named_texture.slices[index];
|
||||
}
|
||||
|
||||
Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
|
||||
NTKey key(p_context, p_texture_name);
|
||||
|
||||
// check if this is a known texture
|
||||
ERR_FAIL_COND_V(!named_textures.has(key), Size2i());
|
||||
NamedTexture &named_texture = named_textures[key];
|
||||
ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
|
||||
|
||||
// check if we're in bounds
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
|
||||
|
||||
// get our index
|
||||
uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
|
||||
|
||||
// and return our size
|
||||
return named_texture.sizes[index];
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
|
||||
Vector<NTKey> to_free; // free these
|
||||
|
||||
// Find all entries for our context, we don't want to free them yet or our loop fails.
|
||||
for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
|
||||
if (E.key.context == p_context) {
|
||||
to_free.push_back(E.key);
|
||||
}
|
||||
}
|
||||
|
||||
// Now free these and remove them from our textures
|
||||
for (NTKey &key : to_free) {
|
||||
free_named_texture(named_textures[key]);
|
||||
named_textures.erase(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate shared buffers
|
||||
void RenderSceneBuffersRD::allocate_blur_textures() {
|
||||
if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
|
||||
// already allocated...
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH);
|
||||
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
if (can_be_storage) {
|
||||
usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
} else {
|
||||
usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required);
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1);
|
||||
|
||||
// if !can_be_storage we need a half width version
|
||||
if (!can_be_storage) {
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required);
|
||||
}
|
||||
|
||||
// TODO redo this:
|
||||
if (!can_be_storage) {
|
||||
// create 4 weight textures, 2 full size, 2 half size
|
||||
|
||||
RD::TextureFormat tf;
|
||||
tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
|
||||
tf.width = internal_size.x;
|
||||
tf.height = internal_size.y;
|
||||
tf.texture_type = RD::TEXTURE_TYPE_2D;
|
||||
tf.array_layers = 1; // Our DOF effect handles one eye per turn
|
||||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
tf.mipmaps = 1;
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
// associated blur texture
|
||||
RID texture;
|
||||
if (i == 1) {
|
||||
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
|
||||
} else if (i == 2) {
|
||||
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
|
||||
} else if (i == 3) {
|
||||
texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
|
||||
}
|
||||
|
||||
// create weight texture
|
||||
weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
|
||||
// create frame buffer
|
||||
Vector<RID> fb;
|
||||
if (i != 0) {
|
||||
fb.push_back(texture);
|
||||
}
|
||||
fb.push_back(weight_buffers[i].weight);
|
||||
weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
|
||||
if (i == 1) {
|
||||
// next 2 are half size
|
||||
tf.width = MAX(1u, tf.width >> 1);
|
||||
tf.height = MAX(1u, tf.height >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data buffers
|
||||
|
||||
bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) {
|
||||
return data_buffers.has(p_name);
|
||||
}
|
||||
|
||||
void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) {
|
||||
if (p_data.is_valid()) {
|
||||
data_buffers[p_name] = p_data;
|
||||
} else if (has_custom_data(p_name)) {
|
||||
data_buffers.erase(p_name);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const {
|
||||
ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>());
|
||||
|
||||
Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Velocity texture.
|
||||
|
||||
void RenderSceneBuffersRD::ensure_velocity() {
|
||||
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
|
||||
if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
uint32_t msaa_usage_bits = usage_bits | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
|
||||
const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
|
||||
RD::TEXTURE_SAMPLES_1,
|
||||
RD::TEXTURE_SAMPLES_2,
|
||||
RD::TEXTURE_SAMPLES_4,
|
||||
RD::TEXTURE_SAMPLES_8,
|
||||
};
|
||||
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, RD::DATA_FORMAT_R16G16_SFLOAT, msaa_usage_bits, ts[msaa_3d]);
|
||||
}
|
||||
|
||||
create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
|
||||
}
|
||||
}
|
||||
|
||||
RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
|
||||
if (p_get_msaa) {
|
||||
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
|
||||
return RID();
|
||||
} else {
|
||||
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
|
||||
}
|
||||
} else {
|
||||
if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
|
||||
return RID();
|
||||
} else {
|
||||
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers_rd.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 RENDER_SCENE_BUFFERS_RD_H
|
||||
#define RENDER_SCENE_BUFFERS_RD_H
|
||||
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "servers/rendering/renderer_rd/effects/vrs.h"
|
||||
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
|
||||
#include "servers/rendering/renderer_scene.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering/storage/render_scene_buffers.h"
|
||||
|
||||
// These can be retired in due time
|
||||
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
||||
#include "servers/rendering/renderer_rd/effects/ss_effects.h"
|
||||
#include "servers/rendering/renderer_rd/environment/fog.h"
|
||||
|
||||
#define RB_SCOPE_BUFFERS SNAME("render_buffers")
|
||||
#define RB_SCOPE_VRS SNAME("VRS")
|
||||
|
||||
#define RB_TEXTURE SNAME("texture")
|
||||
#define RB_TEX_COLOR SNAME("color")
|
||||
#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
|
||||
#define RB_TEX_DEPTH SNAME("depth")
|
||||
#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
|
||||
#define RB_TEX_VELOCITY SNAME("velocity")
|
||||
#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
|
||||
|
||||
#define RB_TEX_BLUR_0 SNAME("blur_0")
|
||||
#define RB_TEX_BLUR_1 SNAME("blur_1")
|
||||
#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
|
||||
|
||||
#define RB_TEX_BACK_DEPTH SNAME("back_depth")
|
||||
|
||||
class RenderSceneBuffersRD : public RenderSceneBuffers {
|
||||
GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
|
||||
|
||||
private:
|
||||
bool can_be_storage = true;
|
||||
uint32_t max_cluster_elements = 512;
|
||||
RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
|
||||
RendererRD::SSEffects *sse = nullptr;
|
||||
RendererRD::VRS *vrs = nullptr;
|
||||
uint64_t auto_exposure_version = 1;
|
||||
|
||||
// Our render target represents our final destination that we display on screen.
|
||||
RID render_target;
|
||||
Size2i target_size = Size2i(0, 0);
|
||||
uint32_t view_count = 1;
|
||||
|
||||
// The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
|
||||
Size2i internal_size = Size2i(0, 0);
|
||||
float fsr_sharpness = 0.2f;
|
||||
|
||||
// Aliassing settings
|
||||
RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
|
||||
RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
|
||||
bool use_taa = false;
|
||||
bool use_debanding = false;
|
||||
|
||||
// Named Textures
|
||||
|
||||
struct NTKey {
|
||||
StringName context;
|
||||
StringName buffer_name;
|
||||
|
||||
bool operator==(const NTKey &p_val) const {
|
||||
return (context == p_val.context) && (buffer_name == p_val.buffer_name);
|
||||
}
|
||||
|
||||
static uint32_t hash(const NTKey &p_val) {
|
||||
// FIXME, properly hash two stringnames together
|
||||
uint32_t h = p_val.context.hash();
|
||||
h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
|
||||
NTKey() {}
|
||||
NTKey(const StringName p_context, const StringName p_texture_name) {
|
||||
context = p_context;
|
||||
buffer_name = p_texture_name;
|
||||
}
|
||||
};
|
||||
|
||||
struct NamedTexture {
|
||||
// Cache the data used to create our texture
|
||||
RD::TextureFormat format;
|
||||
bool is_unique; // If marked as unique, we return it into our pool
|
||||
|
||||
// Our texture objects, slices are lazy (i.e. only created when requested).
|
||||
RID texture;
|
||||
Vector<RID> slices;
|
||||
Vector<Size2i> sizes;
|
||||
};
|
||||
|
||||
mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
|
||||
void update_sizes(NamedTexture &p_named_texture);
|
||||
void free_named_texture(NamedTexture &p_named_texture);
|
||||
|
||||
// Data buffers
|
||||
mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
RenderSceneBuffersRD();
|
||||
virtual ~RenderSceneBuffersRD();
|
||||
|
||||
// info from our renderer
|
||||
void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
|
||||
void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
|
||||
void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
|
||||
RD::DataFormat get_base_data_format() const { return base_data_format; }
|
||||
void set_sseffects(RendererRD::SSEffects *p_ss_effects) { sse = p_ss_effects; }
|
||||
void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
|
||||
|
||||
void cleanup();
|
||||
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
|
||||
virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
|
||||
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
|
||||
virtual void set_use_debanding(bool p_use_debanding) override;
|
||||
|
||||
// Named Textures
|
||||
|
||||
bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
|
||||
RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true);
|
||||
RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true);
|
||||
RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
|
||||
RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
|
||||
const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
|
||||
RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
|
||||
Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
|
||||
|
||||
void clear_context(const StringName &p_context);
|
||||
|
||||
// Allocate shared buffers
|
||||
void allocate_blur_textures();
|
||||
|
||||
// Custom data
|
||||
bool has_custom_data(const StringName &p_name);
|
||||
void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
|
||||
Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
|
||||
|
||||
// Getters
|
||||
|
||||
_FORCE_INLINE_ RID get_render_target() const { return render_target; }
|
||||
_FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
|
||||
_FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
|
||||
_FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
|
||||
_FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
|
||||
_FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
|
||||
_FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
|
||||
_FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
|
||||
_FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
|
||||
|
||||
uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
|
||||
void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
|
||||
|
||||
// For our internal textures we provide some easy access methods.
|
||||
|
||||
_FORCE_INLINE_ RID get_internal_texture() const {
|
||||
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
|
||||
}
|
||||
_FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
|
||||
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ RID get_depth_texture() const {
|
||||
return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
|
||||
}
|
||||
_FORCE_INLINE_ RID get_depth_texture(const uint32_t p_layer) {
|
||||
return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
|
||||
}
|
||||
|
||||
// back buffer (color)
|
||||
RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
|
||||
|
||||
// Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
|
||||
|
||||
void ensure_velocity();
|
||||
bool has_velocity_buffer(bool p_has_msaa) { return has_texture(RB_SCOPE_BUFFERS, p_has_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY); }
|
||||
RID get_velocity_buffer(bool p_get_msaa);
|
||||
RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) { return get_texture_slice(RB_SCOPE_BUFFERS, p_get_msaa ? RB_TEX_VELOCITY_MSAA : RB_TEX_VELOCITY, p_layer, 0); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Everything after this needs to be re-evaluated, this is all old implementation
|
||||
|
||||
ClusterBuilderRD *cluster_builder = nullptr;
|
||||
|
||||
struct WeightBuffers {
|
||||
RID weight;
|
||||
RID fb; // FB with both texture and weight writing into one level lower
|
||||
};
|
||||
|
||||
// 2 full size, 2 half size
|
||||
WeightBuffers weight_buffers[4]; // Only used in raster
|
||||
|
||||
struct Luminance {
|
||||
Vector<RID> reduce;
|
||||
RID current;
|
||||
|
||||
// used only on mobile renderer
|
||||
Vector<RID> fb;
|
||||
RID current_fb;
|
||||
} luminance;
|
||||
|
||||
struct SSEffects {
|
||||
RID linear_depth;
|
||||
Vector<RID> linear_depth_slices;
|
||||
|
||||
RID downsample_uniform_set;
|
||||
|
||||
Projection last_frame_projection;
|
||||
Transform3D last_frame_transform;
|
||||
|
||||
RendererRD::SSEffects::SSAORenderBuffers ssao;
|
||||
RendererRD::SSEffects::SSILRenderBuffers ssil;
|
||||
} ss_effects;
|
||||
|
||||
RendererRD::SSEffects::SSRRenderBuffers ssr;
|
||||
|
||||
RID get_ao_texture() const { return ss_effects.ssao.ao_final; }
|
||||
RID get_ssil_texture() const { return ss_effects.ssil.ssil_final; }
|
||||
};
|
||||
|
||||
#endif // RENDER_SCENE_BUFFERS_RD_H
|
@ -2120,6 +2120,7 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
|
||||
if (rt->color.is_valid()) {
|
||||
RD::get_singleton()->free(rt->color);
|
||||
}
|
||||
rt->color_slices.clear(); // these are automatically freed.
|
||||
|
||||
if (rt->color_multisample.is_valid()) {
|
||||
RD::get_singleton()->free(rt->color_multisample);
|
||||
@ -2174,6 +2175,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||
}
|
||||
rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1;
|
||||
rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
|
||||
rd_color_attachment_format.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; // FIXME we need this only when FSR is enabled
|
||||
rd_color_attachment_format.shareable_formats.push_back(rt->color_format);
|
||||
rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb);
|
||||
if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
|
||||
@ -2392,6 +2394,24 @@ RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
|
||||
return rt->color;
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
||||
if (rt->view_count == 1) {
|
||||
return rt->color;
|
||||
} else {
|
||||
ERR_FAIL_UNSIGNED_INDEX_V(p_layer, rt->view_count, RID());
|
||||
if (rt->color_slices.size() == 0) {
|
||||
for (uint32_t v = 0; v < rt->view_count; v++) {
|
||||
RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->color, v, 0);
|
||||
rt->color_slices.push_back(slice);
|
||||
}
|
||||
}
|
||||
return rt->color_slices[p_layer];
|
||||
}
|
||||
}
|
||||
|
||||
RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
|
||||
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
|
||||
ERR_FAIL_COND_V(!rt, RID());
|
||||
|
@ -254,6 +254,7 @@ private:
|
||||
uint32_t view_count;
|
||||
RID framebuffer;
|
||||
RID color;
|
||||
Vector<RID> color_slices;
|
||||
RID color_multisample; // Needed when MSAA is enabled.
|
||||
|
||||
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
|
||||
@ -589,6 +590,7 @@ public:
|
||||
Size2 render_target_get_size(RID p_render_target);
|
||||
RID render_target_get_rd_framebuffer(RID p_render_target);
|
||||
RID render_target_get_rd_texture(RID p_render_target);
|
||||
RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
|
||||
RID render_target_get_rd_backbuffer(RID p_render_target);
|
||||
RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
|
||||
|
||||
|
@ -155,8 +155,8 @@ void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance
|
||||
Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
|
||||
p_instance->update_dependency(dependency);
|
||||
} else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
|
||||
GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base);
|
||||
p_instance->update_dependency(&gip->dependency);
|
||||
Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);
|
||||
p_instance->update_dependency(dependency);
|
||||
} else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
|
||||
Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
|
||||
p_instance->update_dependency(dependency);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#ifndef RENDERER_SCENE_H
|
||||
#define RENDERER_SCENE_H
|
||||
|
||||
#include "servers/rendering/storage/render_scene_buffers.h"
|
||||
#include "servers/rendering_server.h"
|
||||
#include "servers/xr/xr_interface.h"
|
||||
|
||||
@ -287,9 +288,7 @@ public:
|
||||
|
||||
/* Render Buffers */
|
||||
|
||||
virtual RID render_buffers_create() = 0;
|
||||
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
|
||||
virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
|
||||
|
||||
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
|
||||
|
||||
@ -300,13 +299,13 @@ public:
|
||||
|
||||
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
|
||||
|
||||
virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
|
||||
virtual void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
|
||||
|
||||
struct RenderInfo {
|
||||
int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
|
||||
};
|
||||
|
||||
virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
|
||||
virtual void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
virtual void render_probes() = 0;
|
||||
|
@ -2450,7 +2450,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
|
||||
return animated_material_found;
|
||||
}
|
||||
|
||||
void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
|
||||
void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
|
||||
#ifndef _3D_DISABLED
|
||||
|
||||
Camera *camera = camera_owner.get_or_null(p_camera);
|
||||
@ -2910,7 +2910,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
|
||||
void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
|
||||
Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
|
||||
|
||||
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
|
||||
@ -3270,8 +3270,6 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
|
||||
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
|
||||
render_sdfgi_data[i].instances.clear();
|
||||
}
|
||||
|
||||
// virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
|
||||
}
|
||||
|
||||
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
|
||||
@ -3295,7 +3293,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
|
||||
return RID();
|
||||
}
|
||||
|
||||
void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||
void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
|
||||
#ifndef _3D_DISABLED
|
||||
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
|
||||
|
||||
@ -3383,7 +3381,8 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
|
||||
RendererSceneRender::CameraData camera_data;
|
||||
camera_data.set_camera(xform, cm, false, false);
|
||||
|
||||
_render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
|
||||
Ref<RenderSceneBuffers> render_buffers;
|
||||
_render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
|
||||
|
||||
} else {
|
||||
//do roughness postprocess step until it believes it's done
|
||||
|
@ -1055,10 +1055,10 @@ public:
|
||||
_FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
|
||||
|
||||
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
|
||||
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
|
||||
void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
|
||||
void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas);
|
||||
|
||||
void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
|
||||
void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
|
||||
void update_dirty_instances();
|
||||
|
||||
void render_particle_colliders();
|
||||
@ -1253,8 +1253,7 @@ public:
|
||||
|
||||
/* Render Buffers */
|
||||
|
||||
PASS0R(RID, render_buffers_create)
|
||||
PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t)
|
||||
PASS0R(Ref<RenderSceneBuffers>, render_buffers_create)
|
||||
PASS1(gi_set_use_half_resolution, bool)
|
||||
|
||||
/* Shadow Atlas */
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "servers/rendering/renderer_geometry_instance.h"
|
||||
#include "servers/rendering/renderer_scene.h"
|
||||
#include "servers/rendering/storage/environment_storage.h"
|
||||
#include "storage/render_scene_buffers.h"
|
||||
#include "storage/utilities.h"
|
||||
|
||||
class RendererSceneRender {
|
||||
@ -68,10 +69,10 @@ public:
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
|
||||
virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
|
||||
virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
|
||||
virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const = 0;
|
||||
virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
|
||||
|
||||
/* SKY API */
|
||||
|
||||
@ -317,7 +318,7 @@ public:
|
||||
void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
|
||||
};
|
||||
|
||||
virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
|
||||
virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
|
||||
|
||||
virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
|
||||
virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
|
||||
@ -326,8 +327,7 @@ public:
|
||||
virtual void set_time(double p_time, double p_step) = 0;
|
||||
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
|
||||
|
||||
virtual RID render_buffers_create() = 0;
|
||||
virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
|
||||
virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
|
||||
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
|
||||
|
||||
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
|
||||
|
@ -110,8 +110,7 @@ Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports()
|
||||
void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
|
||||
if (p_viewport->render_buffers.is_valid()) {
|
||||
if (p_viewport->size.width == 0 || p_viewport->size.height == 0) {
|
||||
RSG::scene->free(p_viewport->render_buffers);
|
||||
p_viewport->render_buffers = RID();
|
||||
p_viewport->render_buffers.unref();
|
||||
} else {
|
||||
const float scaling_3d_scale = p_viewport->scaling_3d_scale;
|
||||
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
|
||||
@ -177,7 +176,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
|
||||
// to compensate for the loss of sharpness.
|
||||
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
|
||||
|
||||
RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
|
||||
p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -784,7 +783,9 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->fsr_sharpness = p_sharpness;
|
||||
_configure_3d_render_buffers(viewport);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
viewport->render_buffers->set_fsr_sharpness(p_sharpness);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
|
||||
@ -792,7 +793,9 @@ void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_
|
||||
ERR_FAIL_COND(!viewport);
|
||||
|
||||
viewport->texture_mipmap_bias = p_mipmap_bias;
|
||||
_configure_3d_render_buffers(viewport);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
viewport->render_buffers->set_texture_mipmap_bias(p_mipmap_bias);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
|
||||
@ -1128,7 +1131,9 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
|
||||
return;
|
||||
}
|
||||
viewport->use_debanding = p_use_debanding;
|
||||
_configure_3d_render_buffers(viewport);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
viewport->render_buffers->set_use_debanding(p_use_debanding);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
|
||||
@ -1284,7 +1289,7 @@ bool RendererViewport::free(RID p_rid) {
|
||||
RSG::texture_storage->render_target_free(viewport->render_target);
|
||||
RSG::scene->free(viewport->shadow_atlas);
|
||||
if (viewport->render_buffers.is_valid()) {
|
||||
RSG::scene->free(viewport->render_buffers);
|
||||
viewport->render_buffers.unref();
|
||||
}
|
||||
|
||||
while (viewport->canvas_map.begin()) {
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering_server.h"
|
||||
#include "servers/xr/xr_interface.h"
|
||||
#include "storage/render_scene_buffers.h"
|
||||
|
||||
class RendererViewport {
|
||||
public:
|
||||
@ -64,7 +65,7 @@ public:
|
||||
RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
|
||||
RID render_target;
|
||||
RID render_target_texture;
|
||||
RID render_buffers;
|
||||
Ref<RenderSceneBuffers> render_buffers;
|
||||
|
||||
RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED;
|
||||
RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED;
|
||||
|
@ -464,6 +464,32 @@ public:
|
||||
Vector<DataFormat> shareable_formats;
|
||||
bool is_resolve_buffer = false;
|
||||
|
||||
bool operator==(const TextureFormat &b) const {
|
||||
if (format != b.format) {
|
||||
return false;
|
||||
} else if (width != b.width) {
|
||||
return false;
|
||||
} else if (height != b.height) {
|
||||
return false;
|
||||
} else if (depth != b.depth) {
|
||||
return false;
|
||||
} else if (array_layers != b.array_layers) {
|
||||
return false;
|
||||
} else if (mipmaps != b.mipmaps) {
|
||||
return false;
|
||||
} else if (texture_type != b.texture_type) {
|
||||
return false;
|
||||
} else if (samples != b.samples) {
|
||||
return false;
|
||||
} else if (usage_bits != b.usage_bits) {
|
||||
return false;
|
||||
} else if (shareable_formats != b.shareable_formats) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TextureFormat() {
|
||||
format = DATA_FORMAT_R8_UNORM;
|
||||
width = 1;
|
||||
|
51
servers/rendering/storage/render_scene_buffers.cpp
Normal file
51
servers/rendering/storage/render_scene_buffers.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "render_scene_buffers.h"
|
||||
|
||||
void RenderSceneBuffers::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
|
||||
}
|
||||
|
||||
void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
|
||||
GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
|
||||
};
|
||||
|
||||
void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {
|
||||
GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);
|
||||
}
|
||||
|
||||
void RenderSceneBuffers::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
|
||||
GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias);
|
||||
}
|
||||
|
||||
void RenderSceneBuffers::set_use_debanding(bool p_use_debanding) {
|
||||
GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding);
|
||||
}
|
60
servers/rendering/storage/render_scene_buffers.h
Normal file
60
servers/rendering/storage/render_scene_buffers.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*************************************************************************/
|
||||
/* render_scene_buffers.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* 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 RENDER_SCENE_BUFFERS_H
|
||||
#define RENDER_SCENE_BUFFERS_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class RenderSceneBuffers : public RefCounted {
|
||||
GDCLASS(RenderSceneBuffers, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
|
||||
GDVIRTUAL1(_set_fsr_sharpness, float)
|
||||
GDVIRTUAL1(_set_texture_mipmap_bias, float)
|
||||
GDVIRTUAL1(_set_use_debanding, bool)
|
||||
|
||||
public:
|
||||
RenderSceneBuffers(){};
|
||||
virtual ~RenderSceneBuffers(){};
|
||||
|
||||
virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
|
||||
|
||||
// for those settings that are unlikely to require buffers to be recreated, we'll add setters
|
||||
virtual void set_fsr_sharpness(float p_fsr_sharpness);
|
||||
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias);
|
||||
virtual void set_use_debanding(bool p_use_debanding);
|
||||
};
|
||||
|
||||
#endif // RENDER_SCENE_BUFFERS_H
|
@ -358,9 +358,5 @@ RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
|
||||
RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
|
||||
// TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
|
||||
// but we don't have access to our render buffers from here....
|
||||
RendererSceneRenderRD * rd_scene = ?????;
|
||||
ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup");
|
||||
|
||||
return rd_scene->render_buffers_get_depth_texture(????????????);
|
||||
}
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user