feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ void ClusterBuilderRD::bake_cluster() {
|
|||
|
||||
// Render elements.
|
||||
{
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
ClusterBuilderSharedDataRD::ClusterRender::PushConstant push_constant = {};
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shared->cluster_render.shader_pipelines[use_msaa ? ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_MSAA : ClusterBuilderSharedDataRD::ClusterRender::PIPELINE_NORMAL]);
|
||||
|
|
|
|||
|
|
@ -185,7 +185,14 @@ private:
|
|||
};
|
||||
|
||||
uint32_t cluster_size = 32;
|
||||
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
|
||||
// Results in visual artifacts on macOS and iOS when using MSAA and subgroups.
|
||||
// Using subgroups and disabling MSAA is the optimal solution for now and also works
|
||||
// with MoltenVK.
|
||||
bool use_msaa = false;
|
||||
#else
|
||||
bool use_msaa = true;
|
||||
#endif
|
||||
Divisor divisor = DIVISOR_4;
|
||||
|
||||
Size2i screen_size;
|
||||
|
|
@ -246,7 +253,11 @@ public:
|
|||
|
||||
radius *= p_radius;
|
||||
|
||||
if (p_type == LIGHT_TYPE_OMNI) {
|
||||
// Spotlights with wide angle are trated as Omni lights.
|
||||
// If the spot angle is above the threshold, we need a sphere instead of a cone for building the clusters
|
||||
// since the cone gets too flat/large (spot angle close to 90 degrees) or
|
||||
// can't even cover the affected area of the light (spot angle above 90 degrees).
|
||||
if (p_type == LIGHT_TYPE_OMNI || (p_type == LIGHT_TYPE_SPOT && p_spot_aperture > WIDE_SPOT_ANGLE_THRESHOLD_DEG)) {
|
||||
radius *= shared->sphere_overfit; // Overfit icosphere.
|
||||
|
||||
float depth = -xform.origin.z;
|
||||
|
|
@ -262,15 +273,21 @@ public:
|
|||
e.scale[0] = radius;
|
||||
e.scale[1] = radius;
|
||||
e.scale[2] = radius;
|
||||
e.type = ELEMENT_TYPE_OMNI_LIGHT;
|
||||
e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT];
|
||||
if (p_type == LIGHT_TYPE_OMNI) {
|
||||
e.type = ELEMENT_TYPE_OMNI_LIGHT;
|
||||
e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT];
|
||||
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
|
||||
} else { // LIGHT_TYPE_SPOT with wide angle.
|
||||
e.type = ELEMENT_TYPE_SPOT_LIGHT;
|
||||
e.has_wide_spot_angle = true;
|
||||
e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT];
|
||||
cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]++;
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
|
||||
|
||||
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
|
||||
|
||||
} else /*LIGHT_TYPE_SPOT */ {
|
||||
radius *= shared->cone_overfit; // Overfit icosphere
|
||||
} else /*LIGHT_TYPE_SPOT with no wide angle*/ {
|
||||
radius *= shared->cone_overfit; // Overfit cone.
|
||||
|
||||
real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
|
||||
// Approximate, probably better to use a cone support function.
|
||||
|
|
@ -303,24 +320,12 @@ public:
|
|||
}
|
||||
|
||||
e.touches_far = max_d > z_far;
|
||||
|
||||
// If the spot angle is above the threshold, use a sphere instead of a cone for building the clusters
|
||||
// since the cone gets too flat/large (spot angle close to 90 degrees) or
|
||||
// can't even cover the affected area of the light (spot angle above 90 degrees).
|
||||
if (p_spot_aperture > WIDE_SPOT_ANGLE_THRESHOLD_DEG) {
|
||||
e.scale[0] = radius;
|
||||
e.scale[1] = radius;
|
||||
e.scale[2] = radius;
|
||||
e.has_wide_spot_angle = true;
|
||||
} else {
|
||||
e.scale[0] = len * shared->cone_overfit;
|
||||
e.scale[1] = len * shared->cone_overfit;
|
||||
e.scale[2] = radius;
|
||||
e.has_wide_spot_angle = false;
|
||||
}
|
||||
|
||||
e.scale[0] = len * shared->cone_overfit;
|
||||
e.scale[1] = len * shared->cone_overfit;
|
||||
e.scale[2] = radius;
|
||||
e.has_wide_spot_angle = false;
|
||||
e.type = ELEMENT_TYPE_SPOT_LIGHT;
|
||||
e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; // Use omni light since they share index.
|
||||
e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT];
|
||||
|
||||
RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
@ -28,6 +29,8 @@ env.servers_sources += thirdparty_obj
|
|||
module_obj = []
|
||||
|
||||
env_effects.add_source_files(module_obj, "*.cpp")
|
||||
if env["metal"]:
|
||||
env_effects.add_source_files(module_obj, "metal_fx.mm")
|
||||
env.servers_sources += module_obj
|
||||
|
||||
# Needed to force rebuilding the module files when the thirdparty library is updated.
|
||||
|
|
|
|||
|
|
@ -30,10 +30,8 @@
|
|||
|
||||
#include "bokeh_dof.h"
|
||||
#include "copy_effects.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/storage/camera_attributes_storage.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
|
@ -356,7 +354,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RID framebuffer = p_buffers.base_weight_fb;
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[BOKEH_GEN_BLUR_SIZE].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_depth_texture), 0);
|
||||
|
||||
|
|
@ -388,7 +386,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
// Pass 1
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
|
||||
|
|
@ -412,7 +410,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
RD::Uniform texture = bokeh.push_constant.half_size ? u_half_texture0 : u_secondary_texture;
|
||||
RD::Uniform weight = bokeh.push_constant.half_size ? u_weight_texture2 : u_weight_texture1;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, weight), 1);
|
||||
|
|
@ -430,7 +428,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
|
||||
framebuffer = p_buffers.base_fb;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture1), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture3), 1);
|
||||
|
|
@ -463,7 +461,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
|
||||
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_base_texture), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture0), 1);
|
||||
|
|
@ -481,7 +479,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attr
|
|||
|
||||
framebuffer = p_buffers.base_fb;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, bokeh.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture0), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_weight_texture2), 1);
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@
|
|||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ void CopyEffects::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffe
|
|||
RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, p_rect);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, p_rect);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[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_source_rd_texture), 0);
|
||||
if (p_secondary.is_valid()) {
|
||||
|
|
@ -658,7 +658,7 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
// Just copy it back (we use our blur raster shader here)..
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[BLUR_MODE_COPY].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_source_texture), 0);
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
|
|
@ -731,7 +731,7 @@ void CopyEffects::gaussian_blur_raster(RID p_source_rd_texture, RID p_dest_textu
|
|||
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer);
|
||||
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_source_rd_texture), 0);
|
||||
|
||||
|
|
@ -833,7 +833,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
//HORIZONTAL
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer);
|
||||
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) {
|
||||
|
|
@ -853,7 +853,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_textu
|
|||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
//VERTICAL
|
||||
draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer);
|
||||
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);
|
||||
|
||||
|
|
@ -923,7 +923,7 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture
|
|||
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(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer);
|
||||
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_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
|
||||
|
|
@ -988,7 +988,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con
|
|||
RID shader = copy_to_fb.shader.version_get_shader(copy_to_fb.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, p_region);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, p_region);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_to_fb.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
|
||||
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, ©_to_fb.push_constant, sizeof(CopyToFbPushConstant));
|
||||
|
|
@ -1002,15 +1002,19 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf
|
|||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
Rect2i screen_rect;
|
||||
float atlas_width = p_dst_size.width / p_rect.size.width;
|
||||
float atlas_height = p_dst_size.height / p_rect.size.height;
|
||||
screen_rect.position.x = (int32_t)(Math::round(p_rect.position.x * atlas_width));
|
||||
screen_rect.position.y = (int32_t)(Math::round(p_rect.position.y * atlas_height));
|
||||
screen_rect.size.width = (int32_t)(Math::round(p_dst_size.width));
|
||||
screen_rect.size.height = (int32_t)(Math::round(p_dst_size.height));
|
||||
|
||||
CopyToDPPushConstant push_constant;
|
||||
push_constant.screen_rect[0] = p_rect.position.x;
|
||||
push_constant.screen_rect[1] = p_rect.position.y;
|
||||
push_constant.screen_rect[2] = p_rect.size.width;
|
||||
push_constant.screen_rect[3] = p_rect.size.height;
|
||||
push_constant.z_far = p_z_far;
|
||||
push_constant.z_near = p_z_near;
|
||||
push_constant.texel_size[0] = 1.0f / p_dst_size.x;
|
||||
push_constant.texel_size[1] = 1.0f / p_dst_size.y;
|
||||
push_constant.texel_size[0] = 1.0f / p_dst_size.width;
|
||||
push_constant.texel_size[1] = 1.0f / p_dst_size.height;
|
||||
push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign
|
||||
|
||||
// setup our uniforms
|
||||
|
|
@ -1021,7 +1025,7 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf
|
|||
RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, screen_rect);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_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());
|
||||
|
|
@ -1086,7 +1090,7 @@ void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_fra
|
|||
RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.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_source_cubemap), 0);
|
||||
|
||||
|
|
@ -1165,7 +1169,7 @@ void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebu
|
|||
RID shader = filter.raster_shader.version_get_shader(filter.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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[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_source_cubemap), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
|
||||
|
|
@ -1243,7 +1247,7 @@ void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_f
|
|||
RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.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_source_rd_texture), 0);
|
||||
|
||||
|
|
@ -1263,7 +1267,7 @@ void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_b
|
|||
|
||||
RD::get_singleton()->draw_command_begin_label("Merge specular");
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, Vector<Color>());
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
|
||||
int mode;
|
||||
if (p_reflection.is_valid()) {
|
||||
|
|
|
|||
|
|
@ -217,7 +217,6 @@ private:
|
|||
float z_far;
|
||||
float z_near;
|
||||
float texel_size[2];
|
||||
float screen_rect[4];
|
||||
};
|
||||
|
||||
struct CopyToDP {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
/**************************************************************************/
|
||||
|
||||
#include "debug_effects.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
|
@ -67,7 +66,7 @@ DebugEffects::DebugEffects() {
|
|||
void DebugEffects::_create_frustum_arrays() {
|
||||
if (frustum.vertex_buffer.is_null()) {
|
||||
// Create vertex buffer, but don't put data in it yet
|
||||
frustum.vertex_buffer = RD::get_singleton()->vertex_buffer_create(8 * sizeof(float) * 3, Vector<uint8_t>(), false);
|
||||
frustum.vertex_buffer = RD::get_singleton()->vertex_buffer_create(8 * sizeof(float) * 3, Vector<uint8_t>());
|
||||
|
||||
Vector<RD::VertexAttribute> attributes;
|
||||
Vector<RID> buffers;
|
||||
|
|
@ -282,7 +281,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
|
|||
// And draw our frustum.
|
||||
RD::FramebufferFormatID fb_format_id = RD::get_singleton()->framebuffer_get_format(p_dest_fb);
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, rect);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, rect);
|
||||
|
||||
RID pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline);
|
||||
|
|
@ -326,7 +325,7 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
|
|||
rect.size.x *= atlas_rect_norm.size.x;
|
||||
rect.size.y *= atlas_rect_norm.size.y;
|
||||
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 0.0, 0, rect);
|
||||
draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, rect);
|
||||
|
||||
pipeline = shadow_frustum.pipelines[SFP_TRANSPARENT].get_render_pipeline(frustum.vertex_format, fb_format_id);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline);
|
||||
|
|
@ -351,7 +350,7 @@ void DebugEffects::draw_motion_vectors(RID p_velocity, RID p_depth, RID p_dest_f
|
|||
RD::Uniform u_source_velocity(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_velocity }));
|
||||
RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_depth }));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, motion_vectors.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb), false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||
|
||||
Projection correction;
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@
|
|||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/motion_vectors.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/shadow_frustum.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -36,18 +36,11 @@ 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);
|
||||
|
||||
|
|
@ -59,7 +52,7 @@ 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) {
|
||||
void FSR::process(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();
|
||||
|
|
|
|||
|
|
@ -31,20 +31,23 @@
|
|||
#ifndef FSR_RD_H
|
||||
#define FSR_RD_H
|
||||
|
||||
#include "../pipeline_cache_rd.h"
|
||||
#include "spatial_upscaler.h"
|
||||
|
||||
#include "../storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
class FSR {
|
||||
class FSR : public SpatialUpscaler {
|
||||
String name = "FSR 1.0 Upscale";
|
||||
|
||||
public:
|
||||
FSR();
|
||||
~FSR();
|
||||
|
||||
void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
|
||||
virtual String get_label() const final { return name; }
|
||||
virtual void ensure_context(Ref<RenderSceneBuffersRD> p_render_buffers) final {}
|
||||
virtual void process(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) final;
|
||||
|
||||
private:
|
||||
enum FSRUpscalePass {
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ static FfxErrorCode create_resource_rd(FfxFsr2Interface *p_backend_interface, co
|
|||
texture_format.height = res_desc.height;
|
||||
texture_format.depth = res_desc.depth;
|
||||
texture_format.mipmaps = res_desc.mipCount;
|
||||
texture_format.is_discardable = true;
|
||||
|
||||
RID texture = rd->texture_create(texture_format, RD::TextureView(), initial_data);
|
||||
ERR_FAIL_COND_V(texture.is_null(), FFX_ERROR_BACKEND_API_ERROR);
|
||||
|
|
@ -393,7 +394,9 @@ static FfxErrorCode execute_gpu_job_compute_rd(FSR2Context::Scratch &p_scratch,
|
|||
FSR2Effect::Pipeline &backend_pipeline = *reinterpret_cast<FSR2Effect::Pipeline *>(p_job.pipeline.pipeline);
|
||||
ERR_FAIL_COND_V(backend_pipeline.pipeline_rid.is_null(), FFX_ERROR_INVALID_ARGUMENT);
|
||||
|
||||
Vector<RD::Uniform> compute_uniforms;
|
||||
thread_local LocalVector<RD::Uniform> compute_uniforms;
|
||||
compute_uniforms.clear();
|
||||
|
||||
for (uint32_t i = 0; i < p_job.pipeline.srvCount; i++) {
|
||||
RID texture_rid = p_scratch.resources.rids[p_job.srvs[i].internalIndex];
|
||||
RD::Uniform texture_uniform(RD::UNIFORM_TYPE_TEXTURE, p_job.pipeline.srvResourceBindings[i].slotIndex, texture_rid);
|
||||
|
|
@ -800,9 +803,6 @@ FSR2Effect::~FSR2Effect() {
|
|||
RD::get_singleton()->free(device.linear_clamp_sampler);
|
||||
|
||||
for (uint32_t i = 0; i < FFX_FSR2_PASS_COUNT; i++) {
|
||||
if (device.passes[i].pipeline.pipeline_rid.is_valid()) {
|
||||
RD::get_singleton()->free(device.passes[i].pipeline.pipeline_rid);
|
||||
}
|
||||
device.passes[i].shader->version_free(device.passes[i].shader_version);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ void Luminance::luminance_reduction(RID p_source_texture, const Size2i p_source_
|
|||
|
||||
RD::Uniform u_source_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, i == 0 ? p_source_texture : p_luminance_buffers->reduce[i - 1] }));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, luminance_reduce_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(framebuffer)));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_texture), 0);
|
||||
if (final) {
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/luminance_reduce_raster.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"
|
||||
|
||||
#define RB_LUMINANCE_BUFFERS SNAME("luminance_buffers")
|
||||
|
||||
|
|
|
|||
182
engine/servers/rendering/renderer_rd/effects/metal_fx.h
Normal file
182
engine/servers/rendering/renderer_rd/effects/metal_fx.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/**************************************************************************/
|
||||
/* metal_fx.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef METAL_FX_RD_H
|
||||
#define METAL_FX_RD_H
|
||||
|
||||
#ifdef METAL_ENABLED
|
||||
|
||||
#include "spatial_upscaler.h"
|
||||
|
||||
#include "core/templates/paged_allocator.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#ifdef __OBJC__
|
||||
@protocol MTLFXSpatialScaler;
|
||||
@protocol MTLFXTemporalScaler;
|
||||
#endif
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
struct MFXSpatialContext {
|
||||
#ifdef __OBJC__
|
||||
id<MTLFXSpatialScaler> scaler = nullptr;
|
||||
#else
|
||||
void *scaler = nullptr;
|
||||
#endif
|
||||
MFXSpatialContext() = default;
|
||||
~MFXSpatialContext();
|
||||
};
|
||||
|
||||
class MFXSpatialEffect : public SpatialUpscaler {
|
||||
struct CallbackArgs {
|
||||
MFXSpatialEffect *owner;
|
||||
RDD::TextureID src;
|
||||
RDD::TextureID dst;
|
||||
MFXSpatialContext ctx;
|
||||
|
||||
CallbackArgs(MFXSpatialEffect *p_owner, RDD::TextureID p_src, RDD::TextureID p_dst, MFXSpatialContext p_ctx) :
|
||||
owner(p_owner), src(p_src), dst(p_dst), ctx(p_ctx) {}
|
||||
|
||||
static void free(CallbackArgs **p_args) {
|
||||
(*p_args)->owner->args_allocator.free(*p_args);
|
||||
*p_args = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
PagedAllocator<CallbackArgs, true, 16> args_allocator;
|
||||
static void callback(RDD *p_driver, RDD::CommandBufferID p_command_buffer, CallbackArgs *p_userdata);
|
||||
String name = "MetalFX Spatial Upscale";
|
||||
|
||||
public:
|
||||
virtual String get_label() const final { return name; }
|
||||
virtual void ensure_context(Ref<RenderSceneBuffersRD> p_render_buffers) final;
|
||||
virtual void process(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_src, RID p_dst) final;
|
||||
|
||||
struct CreateParams {
|
||||
Vector2i input_size;
|
||||
Vector2i output_size;
|
||||
RD::DataFormat input_format;
|
||||
RD::DataFormat output_format;
|
||||
};
|
||||
|
||||
MFXSpatialContext *create_context(CreateParams p_params) const;
|
||||
|
||||
MFXSpatialEffect();
|
||||
~MFXSpatialEffect();
|
||||
};
|
||||
|
||||
struct MFXTemporalContext {
|
||||
#ifdef __OBJC__
|
||||
id<MTLFXTemporalScaler> scaler = nullptr;
|
||||
#else
|
||||
void *scaler = nullptr;
|
||||
#endif
|
||||
MFXTemporalContext() = default;
|
||||
~MFXTemporalContext();
|
||||
};
|
||||
|
||||
class MFXTemporalEffect {
|
||||
struct CallbackArgs {
|
||||
MFXTemporalEffect *owner;
|
||||
RDD::TextureID src;
|
||||
RDD::TextureID depth;
|
||||
RDD::TextureID motion;
|
||||
RDD::TextureID exposure;
|
||||
Vector2 jitter_offset;
|
||||
RDD::TextureID dst;
|
||||
MFXTemporalContext ctx;
|
||||
bool reset = false;
|
||||
|
||||
CallbackArgs(
|
||||
MFXTemporalEffect *p_owner,
|
||||
RDD::TextureID p_src,
|
||||
RDD::TextureID p_depth,
|
||||
RDD::TextureID p_motion,
|
||||
RDD::TextureID p_exposure,
|
||||
Vector2 p_jitter_offset,
|
||||
RDD::TextureID p_dst,
|
||||
MFXTemporalContext p_ctx,
|
||||
bool p_reset) :
|
||||
owner(p_owner),
|
||||
src(p_src),
|
||||
depth(p_depth),
|
||||
motion(p_motion),
|
||||
exposure(p_exposure),
|
||||
jitter_offset(p_jitter_offset),
|
||||
dst(p_dst),
|
||||
ctx(p_ctx),
|
||||
reset(p_reset) {}
|
||||
|
||||
static void free(CallbackArgs **p_args) {
|
||||
(*p_args)->owner->args_allocator.free(*p_args);
|
||||
*p_args = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
PagedAllocator<CallbackArgs, true, 16> args_allocator;
|
||||
|
||||
static void callback(RDD *p_driver, RDD::CommandBufferID p_command_buffer, CallbackArgs *p_userdata);
|
||||
|
||||
public:
|
||||
MFXTemporalEffect();
|
||||
~MFXTemporalEffect();
|
||||
|
||||
struct CreateParams {
|
||||
Vector2i input_size;
|
||||
Vector2i output_size;
|
||||
RD::DataFormat input_format;
|
||||
RD::DataFormat depth_format;
|
||||
RD::DataFormat motion_format;
|
||||
RD::DataFormat reactive_format;
|
||||
RD::DataFormat output_format;
|
||||
Vector2 motion_vector_scale;
|
||||
};
|
||||
|
||||
MFXTemporalContext *create_context(CreateParams p_params) const;
|
||||
|
||||
struct Params {
|
||||
RID src;
|
||||
RID depth;
|
||||
RID motion;
|
||||
RID exposure;
|
||||
RID dst;
|
||||
Vector2 jitter_offset;
|
||||
bool reset = false;
|
||||
};
|
||||
|
||||
void process(MFXTemporalContext *p_ctx, Params p_params);
|
||||
};
|
||||
|
||||
} //namespace RendererRD
|
||||
|
||||
#endif // METAL_ENABLED
|
||||
|
||||
#endif // METAL_FX_RD_H
|
||||
225
engine/servers/rendering/renderer_rd/effects/metal_fx.mm
Normal file
225
engine/servers/rendering/renderer_rd/effects/metal_fx.mm
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/**************************************************************************/
|
||||
/* metal_fx.mm */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#import "metal_fx.h"
|
||||
|
||||
#import "../storage_rd/render_scene_buffers_rd.h"
|
||||
#import "drivers/metal/pixel_formats.h"
|
||||
#import "drivers/metal/rendering_device_driver_metal.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <MetalFX/MetalFX.h>
|
||||
|
||||
using namespace RendererRD;
|
||||
|
||||
#pragma mark - Spatial Scaler
|
||||
|
||||
MFXSpatialContext::~MFXSpatialContext() {
|
||||
}
|
||||
|
||||
MFXSpatialEffect::MFXSpatialEffect() {
|
||||
}
|
||||
|
||||
MFXSpatialEffect::~MFXSpatialEffect() {
|
||||
}
|
||||
|
||||
void MFXSpatialEffect::callback(RDD *p_driver, RDD::CommandBufferID p_command_buffer, CallbackArgs *p_userdata) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
MDCommandBuffer *obj = (MDCommandBuffer *)(p_command_buffer.id);
|
||||
obj->end();
|
||||
|
||||
id<MTLTexture> src_texture = rid::get(p_userdata->src);
|
||||
id<MTLTexture> dst_texture = rid::get(p_userdata->dst);
|
||||
|
||||
__block id<MTLFXSpatialScaler> scaler = p_userdata->ctx.scaler;
|
||||
scaler.colorTexture = src_texture;
|
||||
scaler.outputTexture = dst_texture;
|
||||
[scaler encodeToCommandBuffer:obj->get_command_buffer()];
|
||||
// TODO(sgc): add API to retain objects until the command buffer completes
|
||||
[obj->get_command_buffer() addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
|
||||
// This block retains a reference to the scaler until the command buffer.
|
||||
// completes.
|
||||
scaler = nil;
|
||||
}];
|
||||
|
||||
CallbackArgs::free(&p_userdata);
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
void MFXSpatialEffect::ensure_context(Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
p_render_buffers->ensure_mfx(this);
|
||||
}
|
||||
|
||||
void MFXSpatialEffect::process(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_src, RID p_dst) {
|
||||
MFXSpatialContext *ctx = p_render_buffers->get_mfx_spatial_context();
|
||||
DEV_ASSERT(ctx); // this should have been done by the caller via ensure_context
|
||||
|
||||
CallbackArgs *userdata = args_allocator.alloc(
|
||||
this,
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_src)),
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_dst)),
|
||||
*ctx);
|
||||
RD::CallbackResource res[2] = {
|
||||
{ .rid = p_src, .usage = RD::CALLBACK_RESOURCE_USAGE_TEXTURE_SAMPLE },
|
||||
{ .rid = p_dst, .usage = RD::CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE }
|
||||
};
|
||||
RD::get_singleton()->driver_callback_add((RDD::DriverCallback)MFXSpatialEffect::callback, userdata, VectorView<RD::CallbackResource>(res, 2));
|
||||
}
|
||||
|
||||
MFXSpatialContext *MFXSpatialEffect::create_context(CreateParams p_params) const {
|
||||
DEV_ASSERT(RD::get_singleton()->has_feature(RD::SUPPORTS_METALFX_SPATIAL));
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
RenderingDeviceDriverMetal *rdd = (RenderingDeviceDriverMetal *)RD::get_singleton()->get_device_driver();
|
||||
PixelFormats &pf = rdd->get_pixel_formats();
|
||||
id<MTLDevice> dev = rdd->get_device();
|
||||
|
||||
MTLFXSpatialScalerDescriptor *desc = [MTLFXSpatialScalerDescriptor new];
|
||||
desc.inputWidth = (NSUInteger)p_params.input_size.width;
|
||||
desc.inputHeight = (NSUInteger)p_params.input_size.height;
|
||||
|
||||
desc.outputWidth = (NSUInteger)p_params.output_size.width;
|
||||
desc.outputHeight = (NSUInteger)p_params.output_size.height;
|
||||
|
||||
desc.colorTextureFormat = pf.getMTLPixelFormat(p_params.input_format);
|
||||
desc.outputTextureFormat = pf.getMTLPixelFormat(p_params.output_format);
|
||||
desc.colorProcessingMode = MTLFXSpatialScalerColorProcessingModeLinear;
|
||||
id<MTLFXSpatialScaler> scaler = [desc newSpatialScalerWithDevice:dev];
|
||||
MFXSpatialContext *context = memnew(MFXSpatialContext);
|
||||
context->scaler = scaler;
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
#pragma mark - Temporal Scaler
|
||||
|
||||
MFXTemporalContext::~MFXTemporalContext() {}
|
||||
|
||||
MFXTemporalEffect::MFXTemporalEffect() {}
|
||||
MFXTemporalEffect::~MFXTemporalEffect() {}
|
||||
|
||||
MFXTemporalContext *MFXTemporalEffect::create_context(CreateParams p_params) const {
|
||||
DEV_ASSERT(RD::get_singleton()->has_feature(RD::SUPPORTS_METALFX_TEMPORAL));
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
RenderingDeviceDriverMetal *rdd = (RenderingDeviceDriverMetal *)RD::get_singleton()->get_device_driver();
|
||||
PixelFormats &pf = rdd->get_pixel_formats();
|
||||
id<MTLDevice> dev = rdd->get_device();
|
||||
|
||||
MTLFXTemporalScalerDescriptor *desc = [MTLFXTemporalScalerDescriptor new];
|
||||
desc.inputWidth = (NSUInteger)p_params.input_size.width;
|
||||
desc.inputHeight = (NSUInteger)p_params.input_size.height;
|
||||
|
||||
desc.outputWidth = (NSUInteger)p_params.output_size.width;
|
||||
desc.outputHeight = (NSUInteger)p_params.output_size.height;
|
||||
|
||||
desc.colorTextureFormat = pf.getMTLPixelFormat(p_params.input_format);
|
||||
desc.depthTextureFormat = pf.getMTLPixelFormat(p_params.depth_format);
|
||||
desc.motionTextureFormat = pf.getMTLPixelFormat(p_params.motion_format);
|
||||
desc.autoExposureEnabled = NO;
|
||||
|
||||
desc.outputTextureFormat = pf.getMTLPixelFormat(p_params.output_format);
|
||||
|
||||
id<MTLFXTemporalScaler> scaler = [desc newTemporalScalerWithDevice:dev];
|
||||
MFXTemporalContext *context = memnew(MFXTemporalContext);
|
||||
context->scaler = scaler;
|
||||
|
||||
scaler.motionVectorScaleX = p_params.motion_vector_scale.x;
|
||||
scaler.motionVectorScaleY = p_params.motion_vector_scale.y;
|
||||
scaler.depthReversed = true; // Godot uses reverse Z per https://github.com/godotengine/godot/pull/88328
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void MFXTemporalEffect::process(RendererRD::MFXTemporalContext *p_ctx, RendererRD::MFXTemporalEffect::Params p_params) {
|
||||
CallbackArgs *userdata = args_allocator.alloc(
|
||||
this,
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_params.src)),
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_params.depth)),
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_params.motion)),
|
||||
p_params.exposure.is_valid() ? RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_params.exposure)) : RDD::TextureID(),
|
||||
p_params.jitter_offset,
|
||||
RDD::TextureID(RD::get_singleton()->get_driver_resource(RDC::DRIVER_RESOURCE_TEXTURE, p_params.dst)),
|
||||
*p_ctx,
|
||||
p_params.reset);
|
||||
RD::CallbackResource res[3] = {
|
||||
{ .rid = p_params.src, .usage = RD::CALLBACK_RESOURCE_USAGE_TEXTURE_SAMPLE },
|
||||
{ .rid = p_params.depth, .usage = RD::CALLBACK_RESOURCE_USAGE_TEXTURE_SAMPLE },
|
||||
{ .rid = p_params.dst, .usage = RD::CALLBACK_RESOURCE_USAGE_STORAGE_IMAGE_READ_WRITE },
|
||||
};
|
||||
RD::get_singleton()->driver_callback_add((RDD::DriverCallback)MFXTemporalEffect::callback, userdata, VectorView<RD::CallbackResource>(res, 3));
|
||||
}
|
||||
|
||||
void MFXTemporalEffect::callback(RDD *p_driver, RDD::CommandBufferID p_command_buffer, CallbackArgs *p_userdata) {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||
|
||||
MDCommandBuffer *obj = (MDCommandBuffer *)(p_command_buffer.id);
|
||||
obj->end();
|
||||
|
||||
id<MTLTexture> src_texture = rid::get(p_userdata->src);
|
||||
id<MTLTexture> depth = rid::get(p_userdata->depth);
|
||||
id<MTLTexture> motion = rid::get(p_userdata->motion);
|
||||
id<MTLTexture> exposure = rid::get(p_userdata->exposure);
|
||||
|
||||
id<MTLTexture> dst_texture = rid::get(p_userdata->dst);
|
||||
|
||||
__block id<MTLFXTemporalScaler> scaler = p_userdata->ctx.scaler;
|
||||
scaler.reset = p_userdata->reset;
|
||||
scaler.colorTexture = src_texture;
|
||||
scaler.depthTexture = depth;
|
||||
scaler.motionTexture = motion;
|
||||
scaler.exposureTexture = exposure;
|
||||
scaler.jitterOffsetX = p_userdata->jitter_offset.x;
|
||||
scaler.jitterOffsetY = p_userdata->jitter_offset.y;
|
||||
scaler.outputTexture = dst_texture;
|
||||
[scaler encodeToCommandBuffer:obj->get_command_buffer()];
|
||||
// TODO(sgc): add API to retain objects until the command buffer completes
|
||||
[obj->get_command_buffer() addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
|
||||
// This block retains a reference to the scaler until the command buffer.
|
||||
// completes.
|
||||
scaler = nil;
|
||||
}];
|
||||
|
||||
CallbackArgs::free(&p_userdata);
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/**************************************************************************/
|
||||
/* motion_vectors_store.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "motion_vectors_store.h"
|
||||
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
MotionVectorsStore::MotionVectorsStore() {
|
||||
Vector<String> modes;
|
||||
modes.push_back("");
|
||||
|
||||
motion_shader.initialize(modes);
|
||||
shader_version = motion_shader.version_create();
|
||||
|
||||
pipeline = RD::get_singleton()->compute_pipeline_create(motion_shader.version_get_shader(shader_version, 0));
|
||||
}
|
||||
|
||||
MotionVectorsStore::~MotionVectorsStore() {
|
||||
motion_shader.version_free(shader_version);
|
||||
}
|
||||
|
||||
void MotionVectorsStore::process(Ref<RenderSceneBuffersRD> p_render_buffers,
|
||||
const Projection &p_current_projection, const Transform3D &p_current_transform,
|
||||
const Projection &p_previous_projection, const Transform3D &p_previous_transform) {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
ERR_FAIL_NULL(material_storage);
|
||||
|
||||
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
|
||||
ERR_FAIL_NULL(uniform_set_cache);
|
||||
|
||||
uint32_t view_count = p_render_buffers->get_view_count();
|
||||
Size2i internal_size = p_render_buffers->get_internal_size();
|
||||
|
||||
PushConstant push_constant;
|
||||
{
|
||||
push_constant.resolution[0] = internal_size.width;
|
||||
push_constant.resolution[1] = internal_size.height;
|
||||
|
||||
Projection correction;
|
||||
correction.set_depth_correction(true, true, false);
|
||||
Projection reprojection = (correction * p_previous_projection) * p_previous_transform.affine_inverse() * p_current_transform * (correction * p_current_projection).inverse();
|
||||
RendererRD::MaterialStorage::store_camera(reprojection, push_constant.reprojection_matrix);
|
||||
}
|
||||
|
||||
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Motion Vector Store");
|
||||
|
||||
RID shader = motion_shader.version_get_shader(shader_version, 0);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
|
||||
|
||||
for (uint32_t v = 0; v < view_count; v++) {
|
||||
RID velocity = p_render_buffers->get_velocity_buffer(false, v);
|
||||
RID depth = p_render_buffers->get_depth_texture(v);
|
||||
RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, depth }));
|
||||
RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 1, velocity);
|
||||
|
||||
RID uniform_set = uniform_set_cache->get_cache(shader, 0, u_depth, u_velocity);
|
||||
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0);
|
||||
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
|
||||
RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.width, internal_size.height, 1);
|
||||
}
|
||||
|
||||
RD::get_singleton()->compute_list_end();
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
} //namespace RendererRD
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**************************************************************************/
|
||||
/* motion_vectors_store.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef MOTION_VECTORS_STORE_RD_H
|
||||
#define MOTION_VECTORS_STORE_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/motion_vectors_store.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 MotionVectorsStore {
|
||||
struct PushConstant {
|
||||
float reprojection_matrix[16];
|
||||
float resolution[2];
|
||||
uint32_t pad[2];
|
||||
};
|
||||
|
||||
MotionVectorsStoreShaderRD motion_shader;
|
||||
RID shader_version;
|
||||
RID pipeline;
|
||||
|
||||
public:
|
||||
MotionVectorsStore();
|
||||
~MotionVectorsStore();
|
||||
|
||||
void process(Ref<RenderSceneBuffersRD> p_render_buffers,
|
||||
const Projection &p_current_projection, const Transform3D &p_current_transform,
|
||||
const Projection &p_previous_projection, const Transform3D &p_previous_transform);
|
||||
};
|
||||
} //namespace RendererRD
|
||||
|
||||
#endif // MOTION_VECTORS_STORE_RD_H
|
||||
|
|
@ -29,7 +29,6 @@
|
|||
/**************************************************************************/
|
||||
|
||||
#include "resolve.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@
|
|||
#ifndef RESOLVE_RD_H
|
||||
#define RESOLVE_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/resolve.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@
|
|||
#ifndef ROUGHNESS_LIMITER_RD_H
|
||||
#define ROUGHNESS_LIMITER_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/roughness_limiter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
|
||||
#include "sort_effects.h"
|
||||
// #include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,7 @@
|
|||
#ifndef SORT_EFFECTS_RD_H
|
||||
#define SORT_EFFECTS_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/sort.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/**************************************************************************/
|
||||
/* spatial_upscaler.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef SPATIAL_UPSCALER_RD_H
|
||||
#define SPATIAL_UPSCALER_RD_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class RenderSceneBuffersRD;
|
||||
|
||||
class SpatialUpscaler {
|
||||
public:
|
||||
virtual String get_label() const = 0;
|
||||
virtual void ensure_context(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
|
||||
virtual void process(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) = 0;
|
||||
|
||||
SpatialUpscaler() = default;
|
||||
virtual ~SpatialUpscaler() = default;
|
||||
};
|
||||
|
||||
#endif // SPATIAL_UPSCALER_RD_H
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
#include "ss_effects.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#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"
|
||||
|
|
@ -464,7 +463,8 @@ void SSEffects::downsample_depth(Ref<RenderSceneBuffersRD> p_render_buffers, uin
|
|||
if (use_mips) {
|
||||
// Grab our downsample uniform set from cache, these are automatically cleaned up if the depth textures are cleared.
|
||||
// This also ensures we can switch between left eye and right eye uniform sets without recreating the uniform twice a frame.
|
||||
Vector<RD::Uniform> u_depths;
|
||||
thread_local LocalVector<RD::Uniform> u_depths;
|
||||
u_depths.clear();
|
||||
|
||||
// Note, use_full_mips is true if either SSAO or SSIL uses half size, but the other full size and we're using mips.
|
||||
// That means we're filling all 5 levels.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#ifndef SS_EFFECTS_RD_H
|
||||
#define SS_EFFECTS_RD_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h"
|
||||
|
|
@ -45,7 +44,6 @@
|
|||
#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"
|
||||
|
||||
#define RB_SCOPE_SSDS SNAME("rb_ssds")
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_pr
|
|||
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;
|
||||
push_constant.disocclusion_threshold = 2.5f; // If velocity changes by less than this amount of texels we can retain the accumulation buffer.
|
||||
push_constant.disocclusion_scale = 0.01f; // Scale the weight of this pixel calculated as (change in velocity - threshold) * scale.
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
|
||||
|
|
|
|||
|
|
@ -31,12 +31,8 @@
|
|||
#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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
|
|||
RID shader = tonemap.shader.version_get_shader(tonemap.shader_version, mode);
|
||||
ERR_FAIL_COND(shader.is_null());
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_DISCARD, RD::FINAL_ACTION_DISCARD);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer), false, RD::get_singleton()->draw_list_get_current_pass()));
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_color), 0);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_exposure_texture), 1);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/tonemap.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multi
|
|||
RID shader = vrs_shader.shader.version_get_shader(vrs_shader.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_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD, Vector<Color>());
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[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_source_rd_texture), 0);
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(VRSPushConstant));
|
||||
|
|
|
|||
|
|
@ -33,9 +33,6 @@
|
|||
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
namespace RendererRD {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() {
|
|||
|
||||
RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() {
|
||||
return Fog::get_singleton()->_create_fog_shader_func();
|
||||
};
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) {
|
||||
FogMaterialData *material_data = memnew(FogMaterialData);
|
||||
|
|
@ -168,7 +168,7 @@ RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogSha
|
|||
|
||||
RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
|
||||
return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// FOG VOLUMES INSTANCE
|
||||
|
|
@ -264,7 +264,7 @@ ALBEDO = vec3(1.0);
|
|||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX));
|
||||
material_storage->samplers_rd_get_default().append_uniforms(uniforms, SAMPLERS_BINDING_FIRST_INDEX);
|
||||
|
||||
volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
|
||||
}
|
||||
|
|
@ -622,6 +622,7 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
bool any_uses_time = false;
|
||||
Vector3 cam_position = p_cam_transform.get_origin();
|
||||
|
||||
for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
|
||||
FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
|
||||
|
|
@ -652,41 +653,68 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
|
||||
any_uses_time |= shader_data->uses_time;
|
||||
|
||||
Vector3i min;
|
||||
Vector3i max;
|
||||
Vector3i froxel_min;
|
||||
Vector3i froxel_max;
|
||||
Vector3i kernel_size;
|
||||
|
||||
Vector3 position = fog_volume_instance->transform.get_origin();
|
||||
Vector3 fog_position = fog_volume_instance->transform.get_origin();
|
||||
RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
|
||||
Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_size(fog_volume) / 2;
|
||||
|
||||
if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
|
||||
// Local fog volume.
|
||||
Vector3i points[8];
|
||||
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);
|
||||
points[2] = _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[3] = _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[4] = _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[5] = _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[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(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
|
||||
max = Vector3i(1, 1, 1);
|
||||
|
||||
Vector3 corners[8]{
|
||||
fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)),
|
||||
fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z))
|
||||
};
|
||||
Vector3i froxels[8];
|
||||
Vector3 corner_min = corners[0];
|
||||
Vector3 corner_max = corners[0];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
min = min.min(points[j]);
|
||||
max = max.max(points[j]);
|
||||
froxels[j] = _point_get_position_in_froxel_volume(corners[j], fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
|
||||
corner_min = corner_min.min(corners[j]);
|
||||
corner_max = corner_max.max(corners[j]);
|
||||
}
|
||||
|
||||
kernel_size = max - min;
|
||||
froxel_min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
|
||||
froxel_max = Vector3i(1, 1, 1);
|
||||
|
||||
// Tracking just the corners of the fog volume can result in missing some fog:
|
||||
// when the camera's near plane is inside the fog, we must always consider the entire screen
|
||||
Vector3 near_plane_corner(frustum_near_size.x, frustum_near_size.y, z_near);
|
||||
float expand = near_plane_corner.length();
|
||||
if (cam_position.x > (corner_min.x - expand) && cam_position.x < (corner_max.x + expand) &&
|
||||
cam_position.y > (corner_min.y - expand) && cam_position.y < (corner_max.y + expand) &&
|
||||
cam_position.z > (corner_min.z - expand) && cam_position.z < (corner_max.z + expand)) {
|
||||
froxel_min.x = 0;
|
||||
froxel_min.y = 0;
|
||||
froxel_min.z = 0;
|
||||
froxel_max.x = int32_t(fog->width);
|
||||
froxel_max.y = int32_t(fog->height);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
froxel_max.z = MAX(froxel_max.z, froxels[j].z);
|
||||
}
|
||||
} else {
|
||||
// Camera is guaranteed to be outside the fog volume
|
||||
for (int j = 0; j < 8; j++) {
|
||||
froxel_min = froxel_min.min(froxels[j]);
|
||||
froxel_max = froxel_max.max(froxels[j]);
|
||||
}
|
||||
}
|
||||
|
||||
kernel_size = froxel_max - froxel_min;
|
||||
} else {
|
||||
// Volume type global runs on all cells
|
||||
extents = Vector3(fog->width, fog->height, fog->depth);
|
||||
min = Vector3i(0, 0, 0);
|
||||
froxel_min = Vector3i(0, 0, 0);
|
||||
kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
|
||||
}
|
||||
|
||||
|
|
@ -695,15 +723,15 @@ void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const P
|
|||
}
|
||||
|
||||
VolumetricFogShader::FogPushConstant push_constant;
|
||||
push_constant.position[0] = position.x;
|
||||
push_constant.position[1] = position.y;
|
||||
push_constant.position[2] = position.z;
|
||||
push_constant.position[0] = fog_position.x;
|
||||
push_constant.position[1] = fog_position.y;
|
||||
push_constant.position[2] = fog_position.z;
|
||||
push_constant.size[0] = extents.x * 2;
|
||||
push_constant.size[1] = extents.y * 2;
|
||||
push_constant.size[2] = extents.z * 2;
|
||||
push_constant.corner[0] = min.x;
|
||||
push_constant.corner[1] = min.y;
|
||||
push_constant.corner[2] = min.z;
|
||||
push_constant.corner[0] = froxel_min.x;
|
||||
push_constant.corner[1] = froxel_min.y;
|
||||
push_constant.corner[2] = froxel_min.z;
|
||||
push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
|
||||
RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform);
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ public:
|
|||
|
||||
/* FOG VOLUMES */
|
||||
|
||||
bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
|
||||
bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }
|
||||
|
||||
virtual RID fog_volume_allocate() override;
|
||||
virtual void fog_volume_initialize(RID p_rid) override;
|
||||
|
|
@ -250,7 +250,7 @@ public:
|
|||
|
||||
/* FOG VOLUMES INSTANCE */
|
||||
|
||||
bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
|
||||
bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); }
|
||||
|
||||
RID fog_volume_instance_create(RID p_fog_volume);
|
||||
void fog_instance_free(RID p_rid);
|
||||
|
|
@ -316,8 +316,8 @@ public:
|
|||
|
||||
int last_shadow_filter = -1;
|
||||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
||||
virtual void free_data() override{};
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override {}
|
||||
virtual void free_data() override {}
|
||||
|
||||
bool sync_gi_dependent_sets_validity(bool p_ensure_freed = false);
|
||||
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
|
|||
|
||||
bool GI::voxel_gi_is_interior(RID p_voxel_gi) const {
|
||||
VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
|
||||
ERR_FAIL_NULL_V(voxel_gi, 0);
|
||||
ERR_FAIL_NULL_V(voxel_gi, false);
|
||||
return voxel_gi->interior;
|
||||
}
|
||||
|
||||
|
|
@ -1307,24 +1307,24 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
|
|||
push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env);
|
||||
|
||||
RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set;
|
||||
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
|
||||
push_constant.sky_flags = 0;
|
||||
push_constant.y_mult = y_mult;
|
||||
|
||||
if (reads_sky && p_env.is_valid()) {
|
||||
push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env);
|
||||
|
||||
if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) {
|
||||
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
|
||||
push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_COLOR;
|
||||
Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear();
|
||||
push_constant.sky_color[0] = c.r;
|
||||
push_constant.sky_color[1] = c.g;
|
||||
push_constant.sky_color[2] = c.b;
|
||||
push_constant.sky_color_or_orientation[0] = c.r;
|
||||
push_constant.sky_color_or_orientation[1] = c.g;
|
||||
push_constant.sky_color_or_orientation[2] = c.b;
|
||||
} else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) {
|
||||
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
|
||||
push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_COLOR;
|
||||
Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env);
|
||||
push_constant.sky_color[0] = c.r;
|
||||
push_constant.sky_color[1] = c.g;
|
||||
push_constant.sky_color[2] = c.b;
|
||||
push_constant.sky_color_or_orientation[0] = c.r;
|
||||
push_constant.sky_color_or_orientation[1] = c.g;
|
||||
push_constant.sky_color_or_orientation[2] = c.b;
|
||||
|
||||
} else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) {
|
||||
if (p_sky && p_sky->radiance.is_valid()) {
|
||||
|
|
@ -1350,7 +1350,16 @@ void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
|
|||
integrate_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 1);
|
||||
}
|
||||
sky_uniform_set = integrate_sky_uniform_set;
|
||||
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_SKY;
|
||||
push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_MODE_SKY;
|
||||
|
||||
// Encode sky orientation as quaternion in existing push constants.
|
||||
const Basis sky_basis = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
|
||||
const Quaternion sky_quaternion = sky_basis.get_quaternion().inverse();
|
||||
push_constant.sky_color_or_orientation[0] = sky_quaternion.x;
|
||||
push_constant.sky_color_or_orientation[1] = sky_quaternion.y;
|
||||
push_constant.sky_color_or_orientation[2] = sky_quaternion.z;
|
||||
// Ideally we would reconstruct the largest component for least error, but sky contribution to GI is low frequency so just needs to get the idea across.
|
||||
push_constant.sky_flags |= SDFGIShader::IntegratePushConstant::SKY_FLAGS_ORIENTATION_SIGN * (sky_quaternion.w < 0.0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1396,7 +1405,7 @@ void GI::SDFGI::store_probes() {
|
|||
push_constant.image_size[1] = probe_axis_count;
|
||||
push_constant.store_ambient_texture = false;
|
||||
|
||||
push_constant.sky_mode = 0;
|
||||
push_constant.sky_flags = 0;
|
||||
push_constant.y_mult = y_mult;
|
||||
|
||||
// Then store values into the lightprobe texture. Separating these steps has a small performance hit, but it allows for multiple bounces
|
||||
|
|
@ -1721,7 +1730,7 @@ void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, con
|
|||
|
||||
SDFGIShader::ProbeDebugMode mode = p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_PROBES_MULTIVIEW : SDFGIShader::PROBE_DEBUG_PROBES;
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer);
|
||||
RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
|
||||
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[mode].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
|
||||
|
|
@ -2092,11 +2101,11 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
ipush_constant.history_size = history_size;
|
||||
ipush_constant.ray_count = 0;
|
||||
ipush_constant.ray_bias = 0;
|
||||
ipush_constant.sky_mode = 0;
|
||||
ipush_constant.sky_flags = 0;
|
||||
ipush_constant.sky_energy = 0;
|
||||
ipush_constant.sky_color[0] = 0;
|
||||
ipush_constant.sky_color[1] = 0;
|
||||
ipush_constant.sky_color[2] = 0;
|
||||
ipush_constant.sky_color_or_orientation[0] = 0;
|
||||
ipush_constant.sky_color_or_orientation[1] = 0;
|
||||
ipush_constant.sky_color_or_orientation[2] = 0;
|
||||
ipush_constant.y_mult = y_mult;
|
||||
ipush_constant.store_ambient_texture = false;
|
||||
|
||||
|
|
@ -2150,8 +2159,8 @@ void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_
|
|||
}
|
||||
|
||||
//clear dispatch indirect data
|
||||
uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 };
|
||||
RD::get_singleton()->buffer_update(cascades[cascade].solid_cell_dispatch_buffer_storage, 0, sizeof(uint32_t) * 4, dispatch_indirct_data);
|
||||
uint32_t dispatch_indirect_data[4] = { 0, 0, 0, 0 };
|
||||
RD::get_singleton()->buffer_update(cascades[cascade].solid_cell_dispatch_buffer_storage, 0, sizeof(uint32_t) * 4, dispatch_indirect_data);
|
||||
|
||||
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
|
||||
|
||||
|
|
|
|||
|
|
@ -392,9 +392,9 @@ private:
|
|||
};
|
||||
struct IntegratePushConstant {
|
||||
enum {
|
||||
SKY_MODE_DISABLED,
|
||||
SKY_MODE_COLOR,
|
||||
SKY_MODE_SKY,
|
||||
SKY_FLAGS_MODE_COLOR = 0x01,
|
||||
SKY_FLAGS_MODE_SKY = 0x02,
|
||||
SKY_FLAGS_ORIENTATION_SIGN = 0x04,
|
||||
};
|
||||
|
||||
float grid_size[3];
|
||||
|
|
@ -410,12 +410,12 @@ private:
|
|||
int32_t image_size[2];
|
||||
|
||||
int32_t world_offset[3];
|
||||
uint32_t sky_mode;
|
||||
uint32_t sky_flags;
|
||||
|
||||
int32_t scroll[3];
|
||||
float sky_energy;
|
||||
|
||||
float sky_color[3];
|
||||
float sky_color_or_orientation[3];
|
||||
float y_mult;
|
||||
|
||||
uint32_t store_ambient_texture;
|
||||
|
|
@ -461,13 +461,13 @@ public:
|
|||
|
||||
RID get_voxel_gi_buffer();
|
||||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override {}
|
||||
virtual void free_data() override;
|
||||
};
|
||||
|
||||
/* VOXEL GI API */
|
||||
|
||||
bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
|
||||
bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }
|
||||
|
||||
virtual RID voxel_gi_allocate() override;
|
||||
virtual void voxel_gi_free(RID p_voxel_gi) override;
|
||||
|
|
@ -524,14 +524,14 @@ public:
|
|||
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
|
||||
ERR_FAIL_NULL_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);
|
||||
|
|
@ -675,7 +675,7 @@ 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 configure(RenderSceneBuffersRD *p_render_buffers) override {}
|
||||
virtual void free_data() override;
|
||||
~SDFGI();
|
||||
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
|
|||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {
|
||||
void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier, float p_brightness_multiplier) {
|
||||
SkyPushConstant sky_push_constant;
|
||||
|
||||
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
|
||||
|
|
@ -226,6 +226,7 @@ void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineC
|
|||
sky_push_constant.position[2] = p_position.z;
|
||||
sky_push_constant.time = p_time;
|
||||
sky_push_constant.luminance_multiplier = p_luminance_multiplier;
|
||||
sky_push_constant.brightness_multiplier = p_brightness_multiplier;
|
||||
store_transform_3x3(p_orientation, sky_push_constant.orientation);
|
||||
|
||||
RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb);
|
||||
|
|
@ -545,7 +546,6 @@ void SkyRD::Sky::free() {
|
|||
}
|
||||
|
||||
if (material.is_valid()) {
|
||||
RSG::material_storage->material_free(material);
|
||||
material = RID();
|
||||
}
|
||||
}
|
||||
|
|
@ -553,7 +553,9 @@ void SkyRD::Sky::free() {
|
|||
RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd, Ref<RenderSceneBuffersRD> p_render_buffers) {
|
||||
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
thread_local LocalVector<RD::Uniform> uniforms;
|
||||
uniforms.clear();
|
||||
|
||||
{
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
|
|
@ -702,7 +704,7 @@ RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() {
|
|||
RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() {
|
||||
// !BAS! Why isn't _create_sky_shader_func not just static too?
|
||||
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
|
||||
};
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
|
||||
SkyMaterialData *material_data = memnew(SkyMaterialData);
|
||||
|
|
@ -714,7 +716,7 @@ RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyS
|
|||
RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
|
||||
// !BAS! same here, we could just make _create_sky_material_func static?
|
||||
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
|
||||
};
|
||||
}
|
||||
|
||||
SkyRD::SkyRD() {
|
||||
roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
|
||||
|
|
@ -874,7 +876,7 @@ void sky() {
|
|||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX));
|
||||
material_storage->samplers_rd_get_default().append_uniforms(uniforms, SAMPLERS_BINDING_FIRST_INDEX);
|
||||
|
||||
sky_scene_state.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_UNIFORMS);
|
||||
}
|
||||
|
|
@ -973,26 +975,26 @@ SkyRD::~SkyRD() {
|
|||
}
|
||||
}
|
||||
|
||||
void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render) {
|
||||
void SkyRD::setup_sky(const RenderDataRD *p_render_data, const Size2i p_screen_size) {
|
||||
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_env.is_null());
|
||||
ERR_FAIL_COND(p_render_data->environment.is_null());
|
||||
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
ERR_FAIL_COND(p_render_data->render_buffers.is_null());
|
||||
|
||||
// make sure we support our view count
|
||||
ERR_FAIL_COND(p_view_count == 0);
|
||||
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
|
||||
ERR_FAIL_COND(p_render_data->scene_data->view_count == 0);
|
||||
ERR_FAIL_COND(p_render_data->scene_data->view_count > RendererSceneRender::MAX_RENDER_VIEWS);
|
||||
|
||||
SkyMaterialData *material = nullptr;
|
||||
Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
|
||||
Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_render_data->environment));
|
||||
|
||||
RID sky_material;
|
||||
|
||||
SkyShaderData *shader_data = nullptr;
|
||||
|
||||
if (sky) {
|
||||
sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
|
||||
sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_render_data->environment));
|
||||
|
||||
if (sky_material.is_valid()) {
|
||||
material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
|
||||
|
|
@ -1026,8 +1028,8 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
|
|||
update_dirty_skys();
|
||||
}
|
||||
|
||||
if (shader_data->uses_time && p_scene_render->time - sky->prev_time > 0.00001) {
|
||||
sky->prev_time = p_scene_render->time;
|
||||
if (shader_data->uses_time && p_render_data->scene_data->time - sky->prev_time > 0.00001) {
|
||||
sky->prev_time = p_render_data->scene_data->time;
|
||||
sky->reflection.dirty = true;
|
||||
RenderingServerDefault::redraw_request();
|
||||
}
|
||||
|
|
@ -1042,29 +1044,30 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
|
|||
sky->reflection.dirty = true;
|
||||
}
|
||||
|
||||
if (!p_cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
|
||||
sky->prev_position = p_cam_transform.origin;
|
||||
if (!p_render_data->scene_data->cam_transform.origin.is_equal_approx(sky->prev_position) && shader_data->uses_position) {
|
||||
sky->prev_position = p_render_data->scene_data->cam_transform.origin;
|
||||
sky->reflection.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
sky_scene_state.ubo.directional_light_count = 0;
|
||||
if (shader_data->uses_light) {
|
||||
const PagedArray<RID> &lights = *p_render_data->lights;
|
||||
// Run through the list of lights in the scene and pick out the Directional Lights.
|
||||
// This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called
|
||||
// after the depth prepass, but this runs before the depth prepass.
|
||||
for (int i = 0; i < (int)p_lights.size(); i++) {
|
||||
if (!light_storage->owns_light_instance(p_lights[i])) {
|
||||
for (int i = 0; i < (int)lights.size(); i++) {
|
||||
if (!light_storage->owns_light_instance(lights[i])) {
|
||||
continue;
|
||||
}
|
||||
RID base = light_storage->light_instance_get_base_light(p_lights[i]);
|
||||
RID base = light_storage->light_instance_get_base_light(lights[i]);
|
||||
|
||||
ERR_CONTINUE(base.is_null());
|
||||
|
||||
RS::LightType type = light_storage->light_get_type(base);
|
||||
if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
|
||||
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count];
|
||||
Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]);
|
||||
Transform3D light_transform = light_storage->light_instance_get_base_transform(lights[i]);
|
||||
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
|
||||
|
||||
sky_light_data.direction[0] = world_direction.x;
|
||||
|
|
@ -1074,12 +1077,12 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
|
|||
float sign = light_storage->light_is_negative(base) ? -1 : 1;
|
||||
sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
|
||||
|
||||
if (p_scene_render->is_using_physical_light_units()) {
|
||||
if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
|
||||
sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
|
||||
}
|
||||
|
||||
if (p_camera_attributes.is_valid()) {
|
||||
sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
|
||||
if (p_render_data->camera_attributes.is_valid()) {
|
||||
sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
|
||||
}
|
||||
|
||||
Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
|
||||
|
|
@ -1150,43 +1153,59 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
|
|||
|
||||
// Setup fog variables.
|
||||
sky_scene_state.ubo.volumetric_fog_enabled = false;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
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;
|
||||
if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG)) {
|
||||
Ref<RendererRD::Fog::VolumetricFog> fog = p_render_data->render_buffers->get_custom_data(RB_SCOPE_FOG);
|
||||
sky_scene_state.ubo.volumetric_fog_enabled = true;
|
||||
|
||||
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 = 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 = fog->sky_uniform_set;
|
||||
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 = 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 = fog->sky_uniform_set;
|
||||
}
|
||||
|
||||
Projection correction;
|
||||
correction.set_depth_correction(false, true);
|
||||
correction.add_jitter_offset(p_jitter);
|
||||
sky_scene_state.view_count = p_render_data->scene_data->view_count;
|
||||
sky_scene_state.cam_transform = p_render_data->scene_data->cam_transform;
|
||||
|
||||
sky_scene_state.view_count = p_view_count;
|
||||
sky_scene_state.cam_transform = p_cam_transform;
|
||||
sky_scene_state.cam_projection = correction * p_cam_projection; // We only use this when rendering a single view.
|
||||
Projection correction;
|
||||
correction.set_depth_correction(p_render_data->scene_data->flip_y, true);
|
||||
correction.add_jitter_offset(p_render_data->scene_data->taa_jitter);
|
||||
|
||||
Projection projection = p_render_data->scene_data->cam_projection;
|
||||
if (p_render_data->scene_data->cam_frustum) {
|
||||
// We don't use a full projection matrix for the sky, this is enough to make up for it.
|
||||
projection[2].y = -projection[2].y;
|
||||
}
|
||||
|
||||
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_render_data->environment);
|
||||
|
||||
if (custom_fov && sky_scene_state.view_count == 1) {
|
||||
// With custom fov we don't support stereo...
|
||||
float near_plane = projection.get_z_near();
|
||||
float far_plane = projection.get_z_far();
|
||||
float aspect = projection.get_aspect();
|
||||
|
||||
projection.set_perspective(custom_fov, aspect, near_plane, far_plane);
|
||||
}
|
||||
|
||||
sky_scene_state.cam_projection = correction * projection;
|
||||
|
||||
// Our info in our UBO is only used if we're rendering stereo.
|
||||
for (uint32_t i = 0; i < p_view_count; i++) {
|
||||
Projection view_inv_projection = (correction * p_view_projections[i]).inverse();
|
||||
if (p_view_count > 1) {
|
||||
for (uint32_t i = 0; i < p_render_data->scene_data->view_count; i++) {
|
||||
Projection view_inv_projection = (correction * p_render_data->scene_data->view_projection[i]).inverse();
|
||||
if (p_render_data->scene_data->view_count > 1) {
|
||||
// Reprojection is used when we need to have things in combined space.
|
||||
RendererRD::MaterialStorage::store_camera(p_cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]);
|
||||
RendererRD::MaterialStorage::store_camera(p_render_data->scene_data->cam_projection * view_inv_projection, sky_scene_state.ubo.combined_reprojection[i]);
|
||||
} else {
|
||||
// This is unused so just reset to identity.
|
||||
Projection ident;
|
||||
|
|
@ -1194,30 +1213,30 @@ void SkyRD::setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, con
|
|||
}
|
||||
|
||||
RendererRD::MaterialStorage::store_camera(view_inv_projection, sky_scene_state.ubo.view_inv_projections[i]);
|
||||
sky_scene_state.ubo.view_eye_offsets[i][0] = p_view_eye_offsets[i].x;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][1] = p_view_eye_offsets[i].y;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][2] = p_view_eye_offsets[i].z;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][0] = p_render_data->scene_data->view_eye_offset[i].x;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][1] = p_render_data->scene_data->view_eye_offset[i].y;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][2] = p_render_data->scene_data->view_eye_offset[i].z;
|
||||
sky_scene_state.ubo.view_eye_offsets[i][3] = 0.0;
|
||||
}
|
||||
|
||||
sky_scene_state.ubo.z_far = p_view_projections[0].get_z_far(); // Should be the same for all projection.
|
||||
sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env);
|
||||
sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env);
|
||||
sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env);
|
||||
Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_env).srgb_to_linear();
|
||||
float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_env);
|
||||
sky_scene_state.ubo.z_far = p_render_data->scene_data->view_projection[0].get_z_far(); // Should be the same for all projection.
|
||||
sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_render_data->environment);
|
||||
sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_render_data->environment);
|
||||
sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_render_data->environment);
|
||||
Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
|
||||
float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_render_data->environment);
|
||||
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
|
||||
sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
|
||||
sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
|
||||
sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env);
|
||||
sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_render_data->environment);
|
||||
|
||||
sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env);
|
||||
sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env);
|
||||
sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_render_data->environment);
|
||||
sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_render_data->environment);
|
||||
|
||||
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
|
||||
}
|
||||
|
||||
void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier) {
|
||||
void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier, float p_brightness_multiplier) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_env.is_null());
|
||||
|
|
@ -1251,7 +1270,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
RS::SkyMode sky_mode = sky->mode;
|
||||
|
||||
if (sky_mode == RS::SKY_MODE_AUTOMATIC) {
|
||||
if (shader_data->uses_time || shader_data->uses_position) {
|
||||
if ((shader_data->uses_time || shader_data->uses_position) && sky->radiance_size == 256) {
|
||||
update_single_frame = true;
|
||||
sky_mode = RS::SKY_MODE_REALTIME;
|
||||
} else if (shader_data->uses_light || shader_data->ubo_size > 0) {
|
||||
|
|
@ -1293,7 +1312,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
Projection cm;
|
||||
cm.set_perspective(90, 1, 0.01, 10.0);
|
||||
Projection correction;
|
||||
correction.set_depth_correction(true);
|
||||
correction.set_depth_correction(false);
|
||||
cm = correction * cm;
|
||||
|
||||
// Note, we ignore environment_get_sky_orientation here as this is applied when we do our lookup in our scene shader.
|
||||
|
|
@ -1310,8 +1329,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
|
||||
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd, p_render_buffers);
|
||||
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i]);
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier, p_brightness_multiplier);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
|
@ -1331,8 +1350,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
|
||||
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd, p_render_buffers);
|
||||
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i]);
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier, p_brightness_multiplier);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
|
@ -1348,8 +1367,8 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
|
||||
RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd, p_render_buffers);
|
||||
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_LOAD, RD::FINAL_ACTION_DISCARD);
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier);
|
||||
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0, Rect2(), RDD::BreadcrumbMarker::SKY_PASS | uint32_t(i));
|
||||
_render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, cm, local_view, p_global_pos, p_luminance_multiplier, p_brightness_multiplier);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
|
@ -1391,7 +1410,7 @@ void SkyRD::update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers,
|
|||
}
|
||||
}
|
||||
|
||||
void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier) {
|
||||
void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier, float p_brightness_multiplier) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_env.is_null());
|
||||
|
|
@ -1442,20 +1461,9 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p
|
|||
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
|
||||
sky_transform.invert();
|
||||
|
||||
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
|
||||
|
||||
// Camera
|
||||
Projection projection = sky_scene_state.cam_projection;
|
||||
|
||||
if (custom_fov && sky_scene_state.view_count == 1) {
|
||||
// With custom fov we don't support stereo...
|
||||
float near_plane = projection.get_z_near();
|
||||
float far_plane = projection.get_z_far();
|
||||
float aspect = projection.get_aspect();
|
||||
|
||||
projection.set_perspective(custom_fov, aspect, near_plane, far_plane);
|
||||
}
|
||||
|
||||
sky_transform = sky_transform * sky_scene_state.cam_transform.basis;
|
||||
|
||||
if (shader_data->uses_quarter_res) {
|
||||
|
|
@ -1472,8 +1480,8 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p
|
|||
Vector<Color> clear_colors;
|
||||
clear_colors.push_back(Color(0.0, 0.0, 0.0));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 0.0);
|
||||
_render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::DRAW_CLEAR_ALL, clear_colors);
|
||||
_render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier, p_brightness_multiplier);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
|
|
@ -1491,15 +1499,15 @@ void SkyRD::update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p
|
|||
Vector<Color> clear_colors;
|
||||
clear_colors.push_back(Color(0.0, 0.0, 0.0));
|
||||
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_STORE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors, 0.0);
|
||||
_render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, RD::DRAW_CLEAR_ALL, clear_colors);
|
||||
_render_sky(draw_list, p_time, framebuffer, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier, p_brightness_multiplier);
|
||||
RD::get_singleton()->draw_list_end();
|
||||
}
|
||||
|
||||
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
|
||||
}
|
||||
|
||||
void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier) {
|
||||
void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier, float p_brightness_multiplier) {
|
||||
ERR_FAIL_COND(p_render_buffers.is_null());
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
ERR_FAIL_COND(p_env.is_null());
|
||||
|
|
@ -1543,20 +1551,9 @@ void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_ren
|
|||
Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
|
||||
sky_transform.invert();
|
||||
|
||||
float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
|
||||
|
||||
// Camera
|
||||
Projection projection = sky_scene_state.cam_projection;
|
||||
|
||||
if (custom_fov && sky_scene_state.view_count == 1) {
|
||||
// With custom fov we don't support stereo...
|
||||
float near_plane = projection.get_z_near();
|
||||
float far_plane = projection.get_z_far();
|
||||
float aspect = projection.get_aspect();
|
||||
|
||||
projection.set_perspective(custom_fov, aspect, near_plane, far_plane);
|
||||
}
|
||||
|
||||
sky_transform = sky_transform * sky_scene_state.cam_transform.basis;
|
||||
|
||||
PipelineCacheRD *pipeline = &shader_data->pipelines[sky_scene_state.view_count > 1 ? SKY_VERSION_BACKGROUND_MULTIVIEW : SKY_VERSION_BACKGROUND];
|
||||
|
|
@ -1568,7 +1565,7 @@ void SkyRD::draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_ren
|
|||
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
|
||||
}
|
||||
|
||||
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier);
|
||||
_render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, projection, sky_transform, sky_scene_state.cam_transform.origin, p_luminance_multiplier, p_brightness_multiplier);
|
||||
}
|
||||
|
||||
void SkyRD::invalidate_sky(Sky *p_sky) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_data_rd.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering/shader_compiler.h"
|
||||
|
|
@ -100,8 +101,9 @@ private:
|
|||
float projection[4]; // 16 - 64
|
||||
float position[3]; // 12 - 76
|
||||
float time; // 4 - 80
|
||||
float pad[3]; // 12 - 92
|
||||
float luminance_multiplier; // 4 - 96
|
||||
float pad[2]; // 8 - 88
|
||||
float luminance_multiplier; // 4 - 92
|
||||
float brightness_multiplier; // 4 - 96
|
||||
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
|
||||
};
|
||||
|
||||
|
|
@ -132,7 +134,7 @@ private:
|
|||
virtual ~SkyShaderData();
|
||||
};
|
||||
|
||||
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
|
||||
void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const Projection &p_projection, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier, float p_brightness_modifier);
|
||||
|
||||
public:
|
||||
struct SkySceneState {
|
||||
|
|
@ -294,10 +296,10 @@ public:
|
|||
void set_texture_format(RD::DataFormat p_texture_format);
|
||||
~SkyRD();
|
||||
|
||||
void setup_sky(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, uint32_t p_view_count, const Projection *p_view_projections, const Vector3 *p_view_eye_offsets, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const Size2i p_screen_size, Vector2 p_jitter, RendererSceneRenderRD *p_scene_render);
|
||||
void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0);
|
||||
void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0);
|
||||
void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0);
|
||||
void setup_sky(const RenderDataRD *p_render_data, const Size2i p_screen_size);
|
||||
void update_radiance_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, const Vector3 &p_global_pos, double p_time, float p_luminance_multiplier = 1.0, float p_brightness_multiplier = 1.0);
|
||||
void update_res_buffers(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, double p_time, float p_luminance_multiplier = 1.0, float p_brightness_multiplier = 1.0);
|
||||
void draw_sky(RD::DrawListID p_draw_list, Ref<RenderSceneBuffersRD> p_render_buffers, RID p_env, RID p_fb, double p_time, float p_luminance_multiplier = 1.0, float p_brightness_multiplier = 1.0);
|
||||
|
||||
void invalidate_sky(Sky *p_sky);
|
||||
void update_dirty_skys();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,15 +34,16 @@
|
|||
#include "core/templates/paged_allocator.h"
|
||||
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
|
||||
#include "servers/rendering/renderer_rd/effects/fsr2.h"
|
||||
#ifdef METAL_ENABLED
|
||||
#include "servers/rendering/renderer_rd/effects/metal_fx.h"
|
||||
#endif
|
||||
#include "servers/rendering/renderer_rd/effects/motion_vectors_store.h"
|
||||
#include "servers/rendering/renderer_rd/effects/resolve.h"
|
||||
#include "servers/rendering/renderer_rd/effects/ss_effects.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/forward_clustered/best_fit_normal.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
|
||||
|
||||
#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
|
||||
|
||||
|
|
@ -65,16 +66,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
MATERIAL_UNIFORM_SET = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 6,
|
||||
SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 7,
|
||||
SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 8,
|
||||
SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 9,
|
||||
SPEC_CONSTANT_DECAL_FILTER = 10,
|
||||
SPEC_CONSTANT_PROJECTOR_FILTER = 11,
|
||||
SPEC_CONSTANT_USE_DEPTH_FOG = 12,
|
||||
};
|
||||
|
||||
enum {
|
||||
SDFGI_MAX_CASCADES = 8,
|
||||
MAX_VOXEL_GI_INSTANCESS = 8,
|
||||
|
|
@ -95,6 +86,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
|
||||
SceneShaderForwardClustered scene_shader;
|
||||
|
||||
public:
|
||||
/* Framebuffer */
|
||||
|
||||
class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD {
|
||||
|
|
@ -103,6 +95,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
private:
|
||||
RenderSceneBuffersRD *render_buffers = nullptr;
|
||||
RendererRD::FSR2Context *fsr2_context = nullptr;
|
||||
#ifdef METAL_ENABLED
|
||||
RendererRD::MFXTemporalContext *mfx_temporal_context = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
ClusterBuilderRD *cluster_builder = nullptr;
|
||||
|
|
@ -146,6 +141,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
void ensure_fsr2(RendererRD::FSR2Effect *p_effect);
|
||||
RendererRD::FSR2Context *get_fsr2_context() const { return fsr2_context; }
|
||||
|
||||
#ifdef METAL_ENABLED
|
||||
bool ensure_mfx_temporal(RendererRD::MFXTemporalEffect *p_effect);
|
||||
RendererRD::MFXTemporalContext *get_mfx_temporal_context() const { return mfx_temporal_context; }
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
|
@ -154,8 +154,16 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
|
||||
virtual void free_data() override;
|
||||
|
||||
static RD::DataFormat get_specular_format();
|
||||
static uint32_t get_specular_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
|
||||
static RD::DataFormat get_normal_roughness_format();
|
||||
static uint32_t get_normal_roughness_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
|
||||
static RD::DataFormat get_voxelgi_format();
|
||||
static uint32_t get_voxelgi_usage_bits(bool p_resolve, bool p_msaa, bool p_storage);
|
||||
};
|
||||
|
||||
private:
|
||||
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
RID render_base_uniform_set;
|
||||
|
|
@ -182,6 +190,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
PASS_MODE_SDF,
|
||||
PASS_MODE_MAX
|
||||
};
|
||||
|
||||
enum ColorPassFlags {
|
||||
|
|
@ -211,9 +220,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
bool use_directional_soft_shadow = false;
|
||||
uint32_t spec_constant_base_flags = 0;
|
||||
SceneShaderForwardClustered::ShaderSpecialization base_specialization = {};
|
||||
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_spec_constant_base_flags = 0) {
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, SceneShaderForwardClustered::ShaderSpecialization p_base_specialization = {}) {
|
||||
elements = p_elements;
|
||||
element_info = p_element_info;
|
||||
element_count = p_element_count;
|
||||
|
|
@ -229,14 +238,15 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
|
||||
element_offset = p_element_offset;
|
||||
use_directional_soft_shadow = p_use_directional_soft_shadows;
|
||||
spec_constant_base_flags = p_spec_constant_base_flags;
|
||||
base_specialization = p_base_specialization;
|
||||
}
|
||||
};
|
||||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
float pad[3];
|
||||
float texture_size[2];
|
||||
float exposure_normalization;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct LightmapCaptureData {
|
||||
|
|
@ -245,6 +255,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
|
||||
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
|
||||
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
|
||||
|
|
@ -291,11 +302,17 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
uint32_t volumetric_fog_pad;
|
||||
};
|
||||
|
||||
struct PushConstantUbershader {
|
||||
SceneShaderForwardClustered::ShaderSpecialization specialization;
|
||||
SceneShaderForwardClustered::UbershaderConstants constants;
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
uint32_t base_index; //
|
||||
uint32_t uv_offset; //packed
|
||||
uint32_t multimesh_motion_vectors_current_offset;
|
||||
uint32_t multimesh_motion_vectors_previous_offset;
|
||||
PushConstantUbershader ubershader;
|
||||
};
|
||||
|
||||
struct InstanceData {
|
||||
|
|
@ -343,7 +360,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
struct ShadowPass {
|
||||
uint32_t element_from;
|
||||
uint32_t element_count;
|
||||
bool flip_cull;
|
||||
PassMode pass_mode;
|
||||
|
||||
RID rp_uniform_set;
|
||||
|
|
@ -351,8 +367,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
float screen_mesh_lod_threshold;
|
||||
|
||||
RID framebuffer;
|
||||
RD::InitialAction initial_depth_action;
|
||||
Rect2i rect;
|
||||
bool clear_depth;
|
||||
bool flip_cull;
|
||||
};
|
||||
|
||||
LocalVector<ShadowPass> shadow_passes;
|
||||
|
|
@ -378,7 +395,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
template <PassMode p_pass_mode, uint32_t p_color_pass_flags = 0>
|
||||
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
|
||||
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField<RD::DrawFlags> p_draw_flags = RD::DRAW_DEFAULT_ALL, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth_value = 0.0, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2());
|
||||
|
||||
void _update_instance_data_buffer(RenderListType p_render_list);
|
||||
void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
|
||||
|
|
@ -411,6 +428,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
struct {
|
||||
uint64_t lod_index : 8;
|
||||
uint64_t surface_index : 8;
|
||||
|
|
@ -426,10 +447,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
};
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
} sort;
|
||||
|
||||
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
|
||||
|
|
@ -448,6 +465,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
|
||||
GeometryInstanceSurfaceDataCache *next = nullptr;
|
||||
GeometryInstanceForwardClustered *owner = nullptr;
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_dirty_element;
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_all_element;
|
||||
|
||||
GeometryInstanceSurfaceDataCache() :
|
||||
compilation_dirty_element(this), compilation_all_element(this) {}
|
||||
};
|
||||
|
||||
class GeometryInstanceForwardClustered : public RenderGeometryInstanceBase {
|
||||
|
|
@ -498,16 +520,63 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
|
||||
|
||||
SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_all_list;
|
||||
|
||||
PagedAllocator<GeometryInstanceForwardClustered> geometry_instance_alloc;
|
||||
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
|
||||
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
|
||||
|
||||
struct SurfacePipelineData {
|
||||
void *mesh_surface = nullptr;
|
||||
void *mesh_surface_shadow = nullptr;
|
||||
SceneShaderForwardClustered::ShaderData *shader = nullptr;
|
||||
SceneShaderForwardClustered::ShaderData *shader_shadow = nullptr;
|
||||
bool instanced = false;
|
||||
bool uses_opaque = false;
|
||||
bool uses_transparent = false;
|
||||
bool uses_depth = false;
|
||||
bool can_use_lightmap = false;
|
||||
};
|
||||
|
||||
struct GlobalPipelineData {
|
||||
union {
|
||||
uint32_t key;
|
||||
|
||||
struct {
|
||||
uint32_t texture_samples : 3;
|
||||
uint32_t use_reflection_probes : 1;
|
||||
uint32_t use_separate_specular : 1;
|
||||
uint32_t use_motion_vectors : 1;
|
||||
uint32_t use_normal_and_roughness : 1;
|
||||
uint32_t use_lightmaps : 1;
|
||||
uint32_t use_voxelgi : 1;
|
||||
uint32_t use_sdfgi : 1;
|
||||
uint32_t use_multiview : 1;
|
||||
uint32_t use_16_bit_shadows : 1;
|
||||
uint32_t use_32_bit_shadows : 1;
|
||||
uint32_t use_shadow_cubemaps : 1;
|
||||
uint32_t use_shadow_dual_paraboloid : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
GlobalPipelineData global_pipeline_data_compiled = {};
|
||||
GlobalPipelineData global_pipeline_data_required = {};
|
||||
|
||||
typedef Pair<SceneShaderForwardClustered::ShaderData *, SceneShaderForwardClustered::ShaderData::PipelineKey> ShaderPipelinePair;
|
||||
|
||||
void _update_global_pipeline_data_requirements_from_project();
|
||||
void _update_global_pipeline_data_requirements_from_light_storage();
|
||||
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
|
||||
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh);
|
||||
void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
|
||||
void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
|
||||
void _mesh_compile_pipeline_for_surface(SceneShaderForwardClustered::ShaderData *p_shader, void *p_mesh_surface, bool p_ubershader, bool p_instanced_surface, RS::PipelineSource p_source, SceneShaderForwardClustered::ShaderData::PipelineKey &r_pipeline_key, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_compile_pipelines_for_surface(const SurfacePipelineData &p_surface, const GlobalPipelineData &p_global, RS::PipelineSource p_source, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_generate_all_pipelines_for_surface_cache(GeometryInstanceSurfaceDataCache *p_surface_cache, const GlobalPipelineData &p_global);
|
||||
void _update_dirty_geometry_instances();
|
||||
void _update_dirty_geometry_pipelines();
|
||||
|
||||
/* Render List */
|
||||
|
||||
|
|
@ -578,6 +647,11 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
RendererRD::FSR2Effect *fsr2_effect = nullptr;
|
||||
RendererRD::SSEffects *ss_effects = nullptr;
|
||||
|
||||
#ifdef METAL_ENABLED
|
||||
RendererRD::MFXTemporalEffect *mfx_temporal_effect = nullptr;
|
||||
#endif
|
||||
RendererRD::MotionVectorsStore *motion_vectors_store = nullptr;
|
||||
|
||||
/* Cluster builder */
|
||||
|
||||
ClusterBuilderSharedDataRD cluster_builder_shared;
|
||||
|
|
@ -661,8 +735,15 @@ public:
|
|||
|
||||
virtual uint32_t geometry_instance_get_pair_mask() override;
|
||||
|
||||
/* PIPELINES */
|
||||
|
||||
virtual void mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) override;
|
||||
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override;
|
||||
|
||||
virtual bool free(RID p_rid) override;
|
||||
|
||||
virtual void update() override;
|
||||
|
||||
RenderForwardClustered();
|
||||
~RenderForwardClustered();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
//compile
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
_clear_vertex_input_mask_cache();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; //just invalid, but no error
|
||||
|
|
@ -51,10 +51,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_modei = CULL_BACK;
|
||||
blend_mode = BLEND_MODE_MIX;
|
||||
depth_testi = DEPTH_TEST_ENABLED;
|
||||
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_modei = RS::CULL_MODE_BACK;
|
||||
|
||||
uses_point_size = false;
|
||||
uses_alpha = false;
|
||||
|
|
@ -66,8 +66,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
uses_roughness = false;
|
||||
uses_normal = false;
|
||||
uses_tangent = false;
|
||||
bool uses_normal_map = false;
|
||||
bool wireframe = false;
|
||||
uses_normal_map = false;
|
||||
wireframe = false;
|
||||
|
||||
unshaded = false;
|
||||
uses_vertex = false;
|
||||
|
|
@ -90,7 +90,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
|
||||
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
|
||||
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
|
||||
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULT_ALPHA);
|
||||
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULTIPLIED_ALPHA);
|
||||
|
||||
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
|
@ -101,9 +101,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
||||
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_BACK);
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
|
|
@ -141,17 +141,24 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
|
||||
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
Error err = SceneShaderForwardClustered::singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
|
||||
if (err != OK) {
|
||||
if (version.is_valid()) {
|
||||
SceneShaderForwardClustered::singleton->shader.version_free(version);
|
||||
version = RID();
|
||||
}
|
||||
ERR_FAIL_MSG("Shader compilation failed.");
|
||||
}
|
||||
|
||||
if (version.is_null()) {
|
||||
version = shader_singleton->shader.version_create();
|
||||
version = SceneShaderForwardClustered::singleton->shader.version_create();
|
||||
}
|
||||
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
depth_test = DepthTest(depth_testi);
|
||||
cull_mode = Cull(cull_modei);
|
||||
cull_mode = RS::CullMode(cull_modei);
|
||||
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
||||
uses_screen_texture = gen_code.uses_screen_texture;
|
||||
uses_depth_texture = gen_code.uses_depth_texture;
|
||||
|
|
@ -178,235 +185,20 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
|
||||
SceneShaderForwardClustered::singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
//blend modes
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
// if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
|
||||
// If any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage.
|
||||
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
|
||||
blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment;
|
||||
|
||||
switch (blend_mode) {
|
||||
case BLEND_MODE_MIX: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_ADD: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_SUB: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_MUL: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
} break;
|
||||
case BLEND_MODE_ALPHA_TO_COVERAGE: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
} break;
|
||||
case BLEND_MODE_PREMULT_ALPHA: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
uses_blend_alpha = true; // Force alpha used because of blend.
|
||||
} break;
|
||||
}
|
||||
|
||||
// Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors
|
||||
RD::PipelineColorBlendState blend_state_color_blend;
|
||||
blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment(), RD::PipelineColorBlendState::Attachment() };
|
||||
RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(3);
|
||||
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
|
||||
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
|
||||
|
||||
//update pipelines
|
||||
|
||||
RD::PipelineDepthStencilState depth_stencil_state;
|
||||
|
||||
if (depth_test != DEPTH_TEST_DISABLED) {
|
||||
depth_stencil_state.enable_depth_test = true;
|
||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
||||
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||
}
|
||||
bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
|
||||
|
||||
for (int i = 0; i < CULL_VARIANT_MAX; i++) {
|
||||
RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
|
||||
};
|
||||
|
||||
RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull_mode];
|
||||
|
||||
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
|
||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||
RD::RENDER_PRIMITIVE_POINTS,
|
||||
RD::RENDER_PRIMITIVE_LINES,
|
||||
RD::RENDER_PRIMITIVE_LINESTRIPS,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLES,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
||||
};
|
||||
|
||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
|
||||
|
||||
for (int k = 0; k < PIPELINE_VERSION_MAX; k++) {
|
||||
ShaderVersion shader_version;
|
||||
static const ShaderVersion shader_version_table[PIPELINE_VERSION_MAX] = {
|
||||
SHADER_VERSION_DEPTH_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
|
||||
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW,
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
};
|
||||
|
||||
shader_version = shader_version_table[k];
|
||||
|
||||
if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(shader_version)) {
|
||||
continue;
|
||||
}
|
||||
RD::PipelineRasterizationState raster_state;
|
||||
raster_state.cull_mode = cull_mode_rd;
|
||||
raster_state.wireframe = wireframe;
|
||||
|
||||
if (k == PIPELINE_VERSION_COLOR_PASS) {
|
||||
for (int l = 0; l < PIPELINE_COLOR_PASS_FLAG_COUNT; l++) {
|
||||
if (!shader_singleton->valid_color_pass_pipelines[l]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
|
||||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
|
||||
int shader_flags = 0;
|
||||
if (l & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
blend_state = blend_state_color_blend;
|
||||
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
depth_stencil.enable_depth_write = false; //alpha does not draw depth
|
||||
}
|
||||
} else {
|
||||
blend_state = blend_state_color_opaque;
|
||||
|
||||
if (depth_pre_pass_enabled) {
|
||||
// We already have a depth from the depth pre-pass, there is no need to write it again.
|
||||
// In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL.
|
||||
// This way we can use the early depth test to discard transparent fragments before the fragment shader even starts.
|
||||
depth_stencil.depth_compare_operator = RD::COMPARE_OP_EQUAL;
|
||||
depth_stencil.enable_depth_write = false;
|
||||
}
|
||||
|
||||
if (l & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
|
||||
}
|
||||
}
|
||||
|
||||
if (l & PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_MOTION_VECTORS;
|
||||
}
|
||||
|
||||
if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
|
||||
}
|
||||
|
||||
if (l & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
|
||||
}
|
||||
|
||||
int variant = shader_version + shader_flags;
|
||||
|
||||
if (!static_cast<SceneShaderForwardClustered *>(singleton)->shader.is_variant_enabled(variant)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RID shader_variant = shader_singleton->shader.version_get_shader(version, variant);
|
||||
color_pipelines[i][j][l].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
|
||||
}
|
||||
} else {
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
|
||||
if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
|
||||
//none, leave empty
|
||||
} else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW) {
|
||||
blend_state = blend_state_depth_normal_roughness;
|
||||
} else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW) {
|
||||
blend_state = blend_state_depth_normal_roughness_giprobe;
|
||||
} else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
|
||||
} else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_SDF) {
|
||||
blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
|
||||
}
|
||||
|
||||
RID shader_variant = shader_singleton->shader.version_get_shader(version, shader_version);
|
||||
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valid = true;
|
||||
uses_blend_alpha = blend_mode_uses_blend_alpha(BlendMode(blend_mode));
|
||||
}
|
||||
|
||||
bool SceneShaderForwardClustered::ShaderData::is_animated() const {
|
||||
|
|
@ -422,25 +214,259 @@ bool SceneShaderForwardClustered::ShaderData::casts_shadows() const {
|
|||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SceneShaderForwardClustered::ShaderData::get_native_source_code() const {
|
||||
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
return SceneShaderForwardClustered::singleton->shader.version_get_native_source_code(version);
|
||||
} else {
|
||||
return RS::ShaderNativeSourceCode();
|
||||
}
|
||||
}
|
||||
|
||||
return shader_singleton->shader.version_get_native_source_code(version);
|
||||
uint16_t SceneShaderForwardClustered::ShaderData::_get_shader_version(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const {
|
||||
uint32_t ubershader_base = p_ubershader ? ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL : 0;
|
||||
switch (p_pipeline_version) {
|
||||
case PIPELINE_VERSION_DEPTH_PASS:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_DP:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_DP + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_MULTIVIEW + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW + ubershader_base;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_SDF:
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_SDF;
|
||||
case PIPELINE_VERSION_COLOR_PASS: {
|
||||
int shader_flags = 0;
|
||||
|
||||
if (p_ubershader) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_UBERSHADER;
|
||||
}
|
||||
|
||||
if (p_color_pass_flags & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR;
|
||||
}
|
||||
|
||||
if (p_color_pass_flags & PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_MOTION_VECTORS;
|
||||
}
|
||||
|
||||
if (p_color_pass_flags & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP;
|
||||
}
|
||||
|
||||
if (p_color_pass_flags & PIPELINE_COLOR_PASS_FLAG_MULTIVIEW) {
|
||||
shader_flags |= SHADER_COLOR_PASS_FLAG_MULTIVIEW;
|
||||
}
|
||||
|
||||
return ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_COLOR_PASS + shader_flags;
|
||||
} break;
|
||||
default: {
|
||||
DEV_ASSERT(false && "Unknown pipeline version.");
|
||||
return 0;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardClustered::ShaderData::_create_pipeline(PipelineKey p_pipeline_key) {
|
||||
#if PRINT_PIPELINE_COMPILATION_KEYS
|
||||
print_line(
|
||||
"HASH:", p_pipeline_key.hash(),
|
||||
"VERSION:", version,
|
||||
"VERTEX:", p_pipeline_key.vertex_format_id,
|
||||
"FRAMEBUFFER:", p_pipeline_key.framebuffer_format_id,
|
||||
"CULL:", p_pipeline_key.cull_mode,
|
||||
"PRIMITIVE:", p_pipeline_key.primitive_type,
|
||||
"VERSION:", p_pipeline_key.version,
|
||||
"PASS FLAGS:", p_pipeline_key.color_pass_flags,
|
||||
"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
|
||||
"WIREFRAME:", p_pipeline_key.wireframe);
|
||||
#endif
|
||||
|
||||
// Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment = blend_mode_to_blend_attachment(BlendMode(blend_mode));
|
||||
RD::PipelineColorBlendState blend_state_color_blend;
|
||||
blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment(), RD::PipelineColorBlendState::Attachment() };
|
||||
RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(3);
|
||||
RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1);
|
||||
RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2);
|
||||
|
||||
RD::PipelineDepthStencilState depth_stencil_state;
|
||||
|
||||
if (depth_test != DEPTH_TEST_DISABLED) {
|
||||
depth_stencil_state.enable_depth_test = true;
|
||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
||||
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||
}
|
||||
bool depth_pre_pass_enabled = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
|
||||
|
||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||
RD::RENDER_PRIMITIVE_POINTS,
|
||||
RD::RENDER_PRIMITIVE_LINES,
|
||||
RD::RENDER_PRIMITIVE_LINESTRIPS,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLES,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
||||
};
|
||||
|
||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
|
||||
|
||||
RD::PipelineRasterizationState raster_state;
|
||||
raster_state.cull_mode = p_pipeline_key.cull_mode;
|
||||
raster_state.wireframe = wireframe || p_pipeline_key.wireframe;
|
||||
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
multisample_state.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_pipeline_key.framebuffer_format_id, 0);
|
||||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
if (p_pipeline_key.version == PIPELINE_VERSION_COLOR_PASS) {
|
||||
if (p_pipeline_key.color_pass_flags & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) {
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
blend_state = blend_state_color_blend;
|
||||
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
depth_stencil_state.enable_depth_write = false; //alpha does not draw depth
|
||||
}
|
||||
} else {
|
||||
blend_state = blend_state_color_opaque;
|
||||
|
||||
if (depth_pre_pass_enabled) {
|
||||
// We already have a depth from the depth pre-pass, there is no need to write it again.
|
||||
// In addition we can use COMPARE_OP_EQUAL instead of COMPARE_OP_LESS_OR_EQUAL.
|
||||
// This way we can use the early depth test to discard transparent fragments before the fragment shader even starts.
|
||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_EQUAL;
|
||||
depth_stencil_state.enable_depth_write = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (p_pipeline_key.version) {
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS:
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW:
|
||||
blend_state = blend_state_depth_normal_roughness;
|
||||
break;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI:
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW:
|
||||
blend_state = blend_state_depth_normal_roughness_giprobe;
|
||||
break;
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL:
|
||||
// Writes to normal and roughness in opaque way.
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5);
|
||||
break;
|
||||
case PIPELINE_VERSION_DEPTH_PASS:
|
||||
case PIPELINE_VERSION_DEPTH_PASS_DP:
|
||||
case PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW:
|
||||
case PIPELINE_VERSION_DEPTH_PASS_WITH_SDF:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the specialization from the key to pipeline specialization constants.
|
||||
Vector<RD::PipelineSpecializationConstant> specialization_constants;
|
||||
RD::PipelineSpecializationConstant sc;
|
||||
sc.constant_id = 0;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_0;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 1;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_1;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.color_pass_flags, p_pipeline_key.ubershader);
|
||||
ERR_FAIL_COND(shader_rid.is_null());
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, primitive_rd, raster_state, multisample_state, depth_stencil_state, blend_state, 0, 0, specialization_constants);
|
||||
ERR_FAIL_COND(pipeline.is_null());
|
||||
|
||||
pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
|
||||
}
|
||||
|
||||
RD::PolygonCullMode SceneShaderForwardClustered::ShaderData::get_cull_mode_from_cull_variant(CullVariant p_cull_variant) {
|
||||
const RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
|
||||
};
|
||||
|
||||
return cull_mode_rd_table[p_cull_variant][cull_mode];
|
||||
}
|
||||
|
||||
RID SceneShaderForwardClustered::ShaderData::_get_shader_variant(uint16_t p_shader_version) const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardClustered::singleton, RID());
|
||||
return SceneShaderForwardClustered::singleton->shader.version_get_shader(version, p_shader_version);
|
||||
} else {
|
||||
return RID();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardClustered::ShaderData::_clear_vertex_input_mask_cache() {
|
||||
for (uint32_t i = 0; i < VERTEX_INPUT_MASKS_SIZE; i++) {
|
||||
vertex_input_masks[i].store(0);
|
||||
}
|
||||
}
|
||||
|
||||
RID SceneShaderForwardClustered::ShaderData::get_shader_variant(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const {
|
||||
return _get_shader_variant(_get_shader_version(p_pipeline_version, p_color_pass_flags, p_ubershader));
|
||||
}
|
||||
|
||||
uint64_t SceneShaderForwardClustered::ShaderData::get_vertex_input_mask(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) {
|
||||
// Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
|
||||
uint16_t shader_version = _get_shader_version(p_pipeline_version, p_color_pass_flags, p_ubershader);
|
||||
uint64_t input_mask = vertex_input_masks[shader_version].load(std::memory_order_relaxed);
|
||||
if (input_mask == 0) {
|
||||
RID shader_rid = _get_shader_variant(shader_version);
|
||||
ERR_FAIL_COND_V(shader_rid.is_null(), 0);
|
||||
|
||||
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_rid);
|
||||
vertex_input_masks[shader_version].store(input_mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return input_mask;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardClustered::ShaderData::is_valid() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardClustered::singleton, false);
|
||||
return SceneShaderForwardClustered::singleton->shader.version_is_valid(version);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardClustered::ShaderData::ShaderData() :
|
||||
shader_list_element(this) {
|
||||
pipeline_hash_map.set_creation_object_and_function(this, &ShaderData::_create_pipeline);
|
||||
pipeline_hash_map.set_compilations(SceneShaderForwardClustered::singleton->pipeline_compilations, &SceneShaderForwardClustered::singleton_mutex);
|
||||
}
|
||||
|
||||
SceneShaderForwardClustered::ShaderData::~ShaderData() {
|
||||
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
|
||||
ERR_FAIL_NULL(shader_singleton);
|
||||
//pipeline variants will clear themselves if shader is gone
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
if (version.is_valid()) {
|
||||
shader_singleton->shader.version_free(version);
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
ERR_FAIL_NULL(SceneShaderForwardClustered::singleton);
|
||||
SceneShaderForwardClustered::singleton->shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
ShaderData *shader_data = memnew(ShaderData);
|
||||
singleton->shader_list.add(&shader_data->shader_list_element);
|
||||
return shader_data;
|
||||
|
|
@ -455,9 +481,12 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
|
|||
}
|
||||
|
||||
bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true);
|
||||
if (shader_data->version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, SceneShaderForwardClustered::singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardClustered::MaterialData::~MaterialData() {
|
||||
|
|
@ -472,6 +501,7 @@ RendererRD::MaterialStorage::MaterialData *SceneShaderForwardClustered::_create_
|
|||
}
|
||||
|
||||
SceneShaderForwardClustered *SceneShaderForwardClustered::singleton = nullptr;
|
||||
Mutex SceneShaderForwardClustered::singleton_mutex;
|
||||
|
||||
SceneShaderForwardClustered::SceneShaderForwardClustered() {
|
||||
// there should be only one of these, contained within our RenderFM singleton.
|
||||
|
|
@ -498,17 +528,22 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
|
||||
{
|
||||
Vector<ShaderRD::VariantDefine> shader_versions;
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n", true)); // SHADER_VERSION_DEPTH_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n", true)); // SHADER_VERSION_DEPTH_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
|
||||
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
|
||||
const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n", true)); // SHADER_VERSION_DEPTH_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n", true)); // SHADER_VERSION_DEPTH_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_BASE, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", true)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n", false)); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED_MULTIVIEW, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
|
||||
}
|
||||
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_ADVANCED, "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n", false)); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(SHADER_GROUP_MULTIVIEW, "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n", false)); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
|
||||
|
||||
Vector<String> color_pass_flags = {
|
||||
"\n#define UBERSHADER\n", // SHADER_COLOR_PASS_FLAG_UBERSHADER
|
||||
"\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
|
||||
"\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP
|
||||
"\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW
|
||||
|
|
@ -545,16 +580,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
}
|
||||
}
|
||||
|
||||
// Set flag to true if a combination is valid.
|
||||
// The only invalid combinations are those that include both TRANSPARENT and SEPARATE_SPECULAR.
|
||||
for (int i = 0; i < PIPELINE_COLOR_PASS_FLAG_COUNT; i++) {
|
||||
if ((i & PIPELINE_COLOR_PASS_FLAG_TRANSPARENT) && (i & PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR)) {
|
||||
valid_color_pass_pipelines[i] = false;
|
||||
} else {
|
||||
valid_color_pass_pipelines[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
|
||||
material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
|
||||
|
||||
|
|
@ -596,6 +621,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
|
||||
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
|
|
@ -635,7 +662,6 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
actions.renames["CUSTOM1"] = "custom1_attrib";
|
||||
actions.renames["CUSTOM2"] = "custom2_attrib";
|
||||
actions.renames["CUSTOM3"] = "custom3_attrib";
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["LIGHT_VERTEX"] = "light_vertex";
|
||||
|
||||
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
|
||||
|
|
@ -729,13 +755,20 @@ void SceneShaderForwardClustered::init(const String p_defines) {
|
|||
actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
|
||||
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
|
||||
bool force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
|
||||
if (!force_vertex_shading) {
|
||||
// If forcing vertex shading, this will be defined already.
|
||||
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
|
||||
}
|
||||
|
||||
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
|
||||
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
|
||||
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 12;
|
||||
actions.base_varying_index = 14;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
|
|
@ -771,8 +804,7 @@ void fragment() {
|
|||
material_storage->material_set_shader(default_material, default_shader);
|
||||
|
||||
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
|
||||
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
|
||||
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
|
||||
default_shader_rd = md->shader_data->get_shader_variant(PIPELINE_VERSION_COLOR_PASS, 0, false);
|
||||
|
||||
default_material_shader_ptr = md->shader_data;
|
||||
default_material_uniform_set = md->uniform_set;
|
||||
|
|
@ -847,19 +879,11 @@ void fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardClustered::set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants) {
|
||||
default_specialization_constants = p_constants;
|
||||
void SceneShaderForwardClustered::set_default_specialization(const ShaderSpecialization &p_specialization) {
|
||||
default_specialization = p_specialization;
|
||||
|
||||
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
|
||||
for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
|
||||
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
|
||||
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
|
||||
E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
|
||||
}
|
||||
for (int k = 0; k < PIPELINE_COLOR_PASS_FLAG_COUNT; k++) {
|
||||
E->self()->color_pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
E->self()->pipeline_hash_map.clear_pipelines();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -869,3 +893,20 @@ void SceneShaderForwardClustered::enable_advanced_shader_group(bool p_needs_mult
|
|||
}
|
||||
shader.enable_group(SHADER_GROUP_ADVANCED);
|
||||
}
|
||||
|
||||
bool SceneShaderForwardClustered::is_multiview_shader_group_enabled() const {
|
||||
return shader.is_group_enabled(SHADER_GROUP_MULTIVIEW);
|
||||
}
|
||||
|
||||
bool SceneShaderForwardClustered::is_advanced_shader_group_enabled(bool p_multiview) const {
|
||||
if (p_multiview) {
|
||||
return shader.is_group_enabled(SHADER_GROUP_ADVANCED_MULTIVIEW);
|
||||
} else {
|
||||
return shader.is_group_enabled(SHADER_GROUP_ADVANCED);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SceneShaderForwardClustered::get_pipeline_compilations(RS::PipelineSource p_source) {
|
||||
MutexLock lock(SceneShaderForwardClustered::singleton_mutex);
|
||||
return pipeline_compilations[p_source];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H
|
||||
#define SCENE_SHADER_FORWARD_CLUSTERED_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "../storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_hash_map_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h"
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
|
@ -39,6 +40,7 @@ namespace RendererSceneRenderImplementation {
|
|||
class SceneShaderForwardClustered {
|
||||
private:
|
||||
static SceneShaderForwardClustered *singleton;
|
||||
static Mutex singleton_mutex;
|
||||
|
||||
public:
|
||||
enum ShaderGroup {
|
||||
|
|
@ -48,26 +50,28 @@ public:
|
|||
SHADER_GROUP_ADVANCED_MULTIVIEW,
|
||||
};
|
||||
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_DEPTH_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
|
||||
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW,
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_MAX
|
||||
// Not an enum because these values are constants that are processed as numbers
|
||||
// to arrive at a unique version for a particular shader.
|
||||
struct ShaderVersion {
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS = 0;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_DP = 1;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS = 2;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI = 3;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_MULTIVIEW = 4;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW = 5;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW = 6;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL = 7;
|
||||
constexpr static uint16_t SHADER_VERSION_DEPTH_PASS_WITH_SDF = 8;
|
||||
constexpr static uint16_t SHADER_VERSION_COLOR_PASS = 9;
|
||||
};
|
||||
|
||||
enum ShaderColorPassFlags {
|
||||
SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0,
|
||||
SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1,
|
||||
SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2,
|
||||
SHADER_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 3,
|
||||
SHADER_COLOR_PASS_FLAG_COUNT = 1 << 4
|
||||
SHADER_COLOR_PASS_FLAG_UBERSHADER = 1 << 0,
|
||||
SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1,
|
||||
SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
|
||||
SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
|
||||
SHADER_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4,
|
||||
SHADER_COLOR_PASS_FLAG_COUNT = 1 << 5
|
||||
};
|
||||
|
||||
enum PipelineVersion {
|
||||
|
|
@ -90,26 +94,55 @@ public:
|
|||
PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2,
|
||||
PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3,
|
||||
PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4,
|
||||
PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 5,
|
||||
PIPELINE_COLOR_PASS_FLAG_OPTIONS = 5,
|
||||
PIPELINE_COLOR_PASS_FLAG_COMBINATIONS = 1 << PIPELINE_COLOR_PASS_FLAG_OPTIONS,
|
||||
};
|
||||
|
||||
enum ShaderSpecializations {
|
||||
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
|
||||
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
|
||||
SHADER_SPECIALIZATION_SOFT_SHADOWS = 1 << 2,
|
||||
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
|
||||
struct ShaderSpecialization {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t use_forward_gi : 1;
|
||||
uint32_t use_light_projector : 1;
|
||||
uint32_t use_light_soft_shadows : 1;
|
||||
uint32_t use_directional_soft_shadows : 1;
|
||||
uint32_t decal_use_mipmaps : 1;
|
||||
uint32_t projector_use_mipmaps : 1;
|
||||
uint32_t use_depth_fog : 1;
|
||||
uint32_t use_lightmap_bicubic_filter : 1;
|
||||
uint32_t soft_shadow_samples : 6;
|
||||
uint32_t penumbra_shadow_samples : 6;
|
||||
uint32_t directional_soft_shadow_samples : 6;
|
||||
uint32_t directional_penumbra_shadow_samples : 6;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t packed_1;
|
||||
|
||||
struct {
|
||||
uint32_t multimesh : 1;
|
||||
uint32_t multimesh_format_2d : 1;
|
||||
uint32_t multimesh_has_color : 1;
|
||||
uint32_t multimesh_has_custom_data : 1;
|
||||
};
|
||||
};
|
||||
|
||||
uint32_t packed_2;
|
||||
};
|
||||
|
||||
struct UbershaderConstants {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t cull_mode : 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_ALPHA_TO_COVERAGE,
|
||||
BLEND_MODE_PREMULT_ALPHA,
|
||||
};
|
||||
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
|
|
@ -121,12 +154,6 @@ public:
|
|||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum CullVariant {
|
||||
CULL_VARIANT_NORMAL,
|
||||
CULL_VARIANT_REVERSED,
|
||||
|
|
@ -141,11 +168,40 @@ public:
|
|||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||
};
|
||||
|
||||
bool valid = false;
|
||||
struct PipelineKey {
|
||||
RD::VertexFormatID vertex_format_id;
|
||||
RD::FramebufferFormatID framebuffer_format_id;
|
||||
RD::PolygonCullMode cull_mode = RD::POLYGON_CULL_MAX;
|
||||
RS::PrimitiveType primitive_type = RS::PRIMITIVE_MAX;
|
||||
PipelineVersion version = PipelineVersion::PIPELINE_VERSION_MAX;
|
||||
uint32_t color_pass_flags = 0;
|
||||
ShaderSpecialization shader_specialization = {};
|
||||
uint32_t wireframe = false;
|
||||
uint32_t ubershader = false;
|
||||
|
||||
uint32_t hash() const {
|
||||
uint32_t h = hash_murmur3_one_64(vertex_format_id);
|
||||
h = hash_murmur3_one_32(framebuffer_format_id, h);
|
||||
h = hash_murmur3_one_32(cull_mode, h);
|
||||
h = hash_murmur3_one_32(primitive_type, h);
|
||||
h = hash_murmur3_one_32(version, h);
|
||||
h = hash_murmur3_one_32(color_pass_flags, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_0, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_1, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_2, h);
|
||||
h = hash_murmur3_one_32(wireframe, h);
|
||||
h = hash_murmur3_one_32(ubershader, h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
};
|
||||
|
||||
void _create_pipeline(PipelineKey p_pipeline_key);
|
||||
PipelineHashMapRD<PipelineKey, ShaderData, void (ShaderData::*)(PipelineKey)> pipeline_hash_map;
|
||||
|
||||
RID version;
|
||||
uint64_t vertex_input_mask = 0;
|
||||
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_VERSION_MAX];
|
||||
PipelineCacheRD color_pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][PIPELINE_COLOR_PASS_FLAG_COUNT];
|
||||
|
||||
static const uint32_t VERTEX_INPUT_MASKS_SIZE = ShaderVersion::SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL + ShaderVersion::SHADER_VERSION_COLOR_PASS + SHADER_COLOR_PASS_FLAG_COUNT;
|
||||
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
|
||||
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
|
|
@ -157,6 +213,10 @@ public:
|
|||
DepthDraw depth_draw = DEPTH_DRAW_OPAQUE;
|
||||
DepthTest depth_test = DEPTH_TEST_ENABLED;
|
||||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
|
||||
bool uses_point_size = false;
|
||||
bool uses_alpha = false;
|
||||
bool uses_blend_alpha = false;
|
||||
|
|
@ -168,6 +228,8 @@ public:
|
|||
bool uses_normal = false;
|
||||
bool uses_tangent = false;
|
||||
bool uses_particle_trails = false;
|
||||
bool uses_normal_map = false;
|
||||
bool wireframe = false;
|
||||
|
||||
bool unshaded = false;
|
||||
bool uses_vertex = false;
|
||||
|
|
@ -183,16 +245,44 @@ public:
|
|||
bool writes_modelview_or_projection = false;
|
||||
bool uses_world_coordinates = false;
|
||||
bool uses_screen_texture_mipmaps = false;
|
||||
Cull cull_mode = CULL_DISABLED;
|
||||
RS::CullMode cull_mode = RS::CULL_MODE_DISABLED;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
_FORCE_INLINE_ bool uses_alpha_pass() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||
bool has_blend_alpha = uses_blend_alpha;
|
||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
||||
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
||||
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_shared_shadow_material() const {
|
||||
bool backface_culling = cull_mode == RS::CULL_MODE_BACK;
|
||||
return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_position && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && backface_culling && !uses_point_size && !uses_world_coordinates && !wireframe;
|
||||
}
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
uint16_t _get_shader_version(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const;
|
||||
RID _get_shader_variant(uint16_t p_shader_version) const;
|
||||
void _clear_vertex_input_mask_cache();
|
||||
RID get_shader_variant(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader) const;
|
||||
uint64_t get_vertex_input_mask(PipelineVersion p_pipeline_version, uint32_t p_color_pass_flags, bool p_ubershader);
|
||||
RD::PolygonCullMode get_cull_mode_from_cull_variant(CullVariant p_cull_variant);
|
||||
bool is_valid() const;
|
||||
|
||||
SelfList<ShaderData> shader_list_element;
|
||||
ShaderData();
|
||||
|
|
@ -250,14 +340,19 @@ public:
|
|||
RID debug_shadow_splits_material_uniform_set;
|
||||
ShaderData *debug_shadow_splits_material_shader_ptr = nullptr;
|
||||
|
||||
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
|
||||
bool valid_color_pass_pipelines[PIPELINE_COLOR_PASS_FLAG_COUNT];
|
||||
ShaderSpecialization default_specialization = {};
|
||||
|
||||
uint32_t pipeline_compilations[RS::PIPELINE_SOURCE_MAX] = {};
|
||||
|
||||
SceneShaderForwardClustered();
|
||||
~SceneShaderForwardClustered();
|
||||
|
||||
void init(const String p_defines);
|
||||
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
|
||||
void set_default_specialization(const ShaderSpecialization &p_specialization);
|
||||
void enable_advanced_shader_group(bool p_needs_multiview = false);
|
||||
bool is_multiview_shader_group_enabled() const;
|
||||
bool is_advanced_shader_group_enabled(bool p_multiview) const;
|
||||
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
|
||||
};
|
||||
|
||||
} // namespace RendererSceneRenderImplementation
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -33,9 +33,7 @@
|
|||
|
||||
#include "core/templates/paged_allocator.h"
|
||||
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.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/storage_rd/utilities.h"
|
||||
|
||||
#define RB_SCOPE_MOBILE SNAME("mobile")
|
||||
|
||||
|
|
@ -59,32 +57,6 @@ private:
|
|||
MATERIAL_UNIFORM_SET = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
SPEC_CONSTANT_USING_PROJECTOR = 0,
|
||||
SPEC_CONSTANT_USING_SOFT_SHADOWS = 1,
|
||||
SPEC_CONSTANT_USING_DIRECTIONAL_SOFT_SHADOWS = 2,
|
||||
|
||||
SPEC_CONSTANT_SOFT_SHADOW_SAMPLES = 3,
|
||||
SPEC_CONSTANT_PENUMBRA_SHADOW_SAMPLES = 4,
|
||||
SPEC_CONSTANT_DIRECTIONAL_SOFT_SHADOW_SAMPLES = 5,
|
||||
SPEC_CONSTANT_DIRECTIONAL_PENUMBRA_SHADOW_SAMPLES = 6,
|
||||
|
||||
SPEC_CONSTANT_DECAL_USE_MIPMAPS = 7,
|
||||
SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS = 8,
|
||||
|
||||
SPEC_CONSTANT_DISABLE_OMNI_LIGHTS = 9,
|
||||
SPEC_CONSTANT_DISABLE_SPOT_LIGHTS = 10,
|
||||
SPEC_CONSTANT_DISABLE_REFLECTION_PROBES = 11,
|
||||
SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS = 12,
|
||||
|
||||
SPEC_CONSTANT_DISABLE_DECALS = 13,
|
||||
SPEC_CONSTANT_DISABLE_FOG = 14,
|
||||
SPEC_CONSTANT_USE_DEPTH_FOG = 16,
|
||||
SPEC_CONSTANT_IS_MULTIMESH = 17,
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_LIGHTMAPS = 8,
|
||||
MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance
|
||||
|
|
@ -152,14 +124,14 @@ private:
|
|||
RID render_pass_uniform_set;
|
||||
bool force_wireframe = false;
|
||||
Vector2 uv_offset;
|
||||
uint32_t spec_constant_base_flags = 0;
|
||||
SceneShaderForwardMobile::ShaderSpecialization base_specialization;
|
||||
float lod_distance_multiplier = 0.0;
|
||||
float screen_mesh_lod_threshold = 0.0;
|
||||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
uint32_t subpass = 0;
|
||||
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, SceneShaderForwardMobile::ShaderSpecialization p_base_specialization, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
|
||||
elements = p_elements;
|
||||
element_info = p_element_info;
|
||||
element_count = p_element_count;
|
||||
|
|
@ -173,7 +145,7 @@ private:
|
|||
lod_distance_multiplier = p_lod_distance_multiplier;
|
||||
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
|
||||
element_offset = p_element_offset;
|
||||
spec_constant_base_flags = p_spec_constant_base_flags;
|
||||
base_specialization = p_base_specialization;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -208,8 +180,9 @@ private:
|
|||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
float pad[3];
|
||||
float texture_size[2];
|
||||
float exposure_normalization;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct LightmapCaptureData {
|
||||
|
|
@ -221,10 +194,16 @@ private:
|
|||
struct SceneState {
|
||||
LocalVector<RID> uniform_buffers;
|
||||
|
||||
struct PushConstantUbershader {
|
||||
SceneShaderForwardMobile::ShaderSpecialization specialization;
|
||||
SceneShaderForwardMobile::UbershaderConstants constants;
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
float uv_offset[2];
|
||||
uint32_t base_index;
|
||||
uint32_t pad;
|
||||
PushConstantUbershader ubershader;
|
||||
};
|
||||
|
||||
struct InstanceData {
|
||||
|
|
@ -263,6 +242,7 @@ private:
|
|||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_sss = false;
|
||||
bool used_lightmap = false;
|
||||
|
||||
struct ShadowPass {
|
||||
uint32_t element_from;
|
||||
|
|
@ -275,8 +255,8 @@ private:
|
|||
float screen_mesh_lod_threshold;
|
||||
|
||||
RID framebuffer;
|
||||
RD::InitialAction initial_depth_action;
|
||||
Rect2i rect;
|
||||
bool clear_depth;
|
||||
};
|
||||
|
||||
LocalVector<ShadowPass> shadow_passes;
|
||||
|
|
@ -350,7 +330,7 @@ private:
|
|||
template <PassMode p_pass_mode>
|
||||
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 0.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2());
|
||||
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField<RD::DrawFlags> p_clear_colors = RD::DRAW_DEFAULT_ALL, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth_value = 0.0, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2());
|
||||
|
||||
RenderList render_list[RENDER_LIST_MAX];
|
||||
|
||||
|
|
@ -365,12 +345,12 @@ protected:
|
|||
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;
|
||||
|
||||
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
|
||||
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
|
||||
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override{};
|
||||
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
|
||||
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
|
||||
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override{};
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override{};
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
|
||||
|
||||
/* Geometry instance */
|
||||
|
||||
|
|
@ -378,6 +358,7 @@ protected:
|
|||
|
||||
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
|
||||
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
|
||||
|
|
@ -416,6 +397,10 @@ protected:
|
|||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
struct {
|
||||
// !BAS! CHECK BITS!!!
|
||||
|
||||
|
|
@ -432,10 +417,6 @@ protected:
|
|||
// uint64_t lod_index : 8; // no need to sort on LOD
|
||||
// uint64_t uses_forward_gi : 1; // no GI here, remove
|
||||
};
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
} sort;
|
||||
|
||||
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
|
||||
|
|
@ -454,6 +435,12 @@ protected:
|
|||
|
||||
GeometryInstanceSurfaceDataCache *next = nullptr;
|
||||
GeometryInstanceForwardMobile *owner = nullptr;
|
||||
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_dirty_element;
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_all_element;
|
||||
|
||||
GeometryInstanceSurfaceDataCache() :
|
||||
compilation_dirty_element(this), compilation_all_element(this) {}
|
||||
};
|
||||
|
||||
class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
|
||||
|
|
@ -541,6 +528,14 @@ protected:
|
|||
return forward_id_storage_mobile;
|
||||
}
|
||||
|
||||
struct ForwardIDByMapSort {
|
||||
uint8_t map;
|
||||
RendererRD::ForwardID forward_id;
|
||||
bool operator<(const ForwardIDByMapSort &p_sort) const {
|
||||
return map > p_sort.map;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
static RenderForwardMobile *get_singleton() { return singleton; }
|
||||
|
||||
|
|
@ -559,24 +554,79 @@ public:
|
|||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
|
||||
|
||||
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_all_list;
|
||||
|
||||
PagedAllocator<GeometryInstanceForwardMobile> geometry_instance_alloc;
|
||||
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
|
||||
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
|
||||
|
||||
struct SurfacePipelineData {
|
||||
void *mesh_surface = nullptr;
|
||||
void *mesh_surface_shadow = nullptr;
|
||||
SceneShaderForwardMobile::ShaderData *shader = nullptr;
|
||||
SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr;
|
||||
bool instanced = false;
|
||||
bool uses_opaque = false;
|
||||
bool uses_transparent = false;
|
||||
bool uses_depth = false;
|
||||
bool can_use_lightmap = false;
|
||||
};
|
||||
|
||||
struct GlobalPipelineData {
|
||||
union {
|
||||
uint32_t key;
|
||||
|
||||
struct {
|
||||
uint32_t texture_samples : 3;
|
||||
uint32_t target_samples : 3;
|
||||
uint32_t use_reflection_probes : 1;
|
||||
uint32_t use_lightmaps : 1;
|
||||
uint32_t use_multiview : 1;
|
||||
uint32_t use_16_bit_shadows : 1;
|
||||
uint32_t use_32_bit_shadows : 1;
|
||||
uint32_t use_shadow_cubemaps : 1;
|
||||
uint32_t use_shadow_dual_paraboloid : 1;
|
||||
uint32_t use_vrs : 1;
|
||||
uint32_t use_subpass_post_pass : 1;
|
||||
uint32_t use_separate_post_pass : 1;
|
||||
uint32_t use_hdr_render_target : 1;
|
||||
uint32_t use_ldr_render_target : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
GlobalPipelineData global_pipeline_data_compiled = {};
|
||||
GlobalPipelineData global_pipeline_data_required = {};
|
||||
|
||||
typedef Pair<SceneShaderForwardMobile::ShaderData *, SceneShaderForwardMobile::ShaderData::PipelineKey> ShaderPipelinePair;
|
||||
|
||||
void _update_global_pipeline_data_requirements_from_project();
|
||||
void _update_global_pipeline_data_requirements_from_light_storage();
|
||||
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
|
||||
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
|
||||
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
|
||||
void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
|
||||
void _mesh_compile_pipeline_for_surface(SceneShaderForwardMobile::ShaderData *p_shader, void *p_mesh_surface, bool p_instanced_surface, RS::PipelineSource p_source, SceneShaderForwardMobile::ShaderData::PipelineKey &r_pipeline_key, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_compile_pipelines_for_surface(const SurfacePipelineData &p_surface, const GlobalPipelineData &p_global, RS::PipelineSource p_source, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_generate_all_pipelines_for_surface_cache(GeometryInstanceSurfaceDataCache *p_surface_cache, const GlobalPipelineData &p_global);
|
||||
void _update_dirty_geometry_instances();
|
||||
void _update_dirty_geometry_pipelines();
|
||||
|
||||
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
|
||||
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
|
||||
|
||||
virtual uint32_t geometry_instance_get_pair_mask() override;
|
||||
|
||||
/* PIPELINES */
|
||||
|
||||
virtual void mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) override;
|
||||
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override;
|
||||
|
||||
virtual bool free(RID p_rid) override;
|
||||
|
||||
virtual void update() override;
|
||||
|
||||
virtual void base_uniforms_changed() override;
|
||||
|
||||
virtual bool is_dynamic_gi_supported() const override;
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
//compile
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
_clear_vertex_input_mask_cache();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; //just invalid, but no error
|
||||
|
|
@ -53,10 +53,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull = CULL_BACK;
|
||||
blend_mode = BLEND_MODE_MIX;
|
||||
depth_testi = DEPTH_TEST_ENABLED;
|
||||
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
uses_point_size = false;
|
||||
uses_alpha = false;
|
||||
|
|
@ -68,8 +68,8 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
uses_roughness = false;
|
||||
uses_normal = false;
|
||||
uses_tangent = false;
|
||||
bool uses_normal_map = false;
|
||||
bool wireframe = false;
|
||||
uses_normal_map = false;
|
||||
wireframe = false;
|
||||
|
||||
unshaded = false;
|
||||
uses_vertex = false;
|
||||
|
|
@ -91,7 +91,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MIX);
|
||||
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB);
|
||||
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL);
|
||||
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULT_ALPHA);
|
||||
actions.render_mode_values["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULTIPLIED_ALPHA);
|
||||
|
||||
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
|
@ -102,9 +102,9 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
||||
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull, CULL_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull, CULL_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull, CULL_BACK);
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_BACK);
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
|
|
@ -141,13 +141,19 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
Error err = SceneShaderForwardMobile::singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
|
||||
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
if (err != OK) {
|
||||
if (version.is_valid()) {
|
||||
SceneShaderForwardMobile::singleton->shader.version_free(version);
|
||||
version = RID();
|
||||
}
|
||||
ERR_FAIL_MSG("Shader compilation failed.");
|
||||
}
|
||||
|
||||
if (version.is_null()) {
|
||||
version = shader_singleton->shader.version_create();
|
||||
version = SceneShaderForwardMobile::singleton->shader.version_create();
|
||||
}
|
||||
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
|
|
@ -163,11 +169,11 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (uses_sss) {
|
||||
WARN_PRINT_ONCE_ED("Sub-surface scattering is only available when using the Forward+ rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
|
||||
}
|
||||
|
||||
if (uses_transmittance) {
|
||||
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ rendering backend.");
|
||||
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ renderer.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -189,86 +195,62 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
|
||||
SceneShaderForwardMobile::singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
//blend modes
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
// if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
|
||||
// If any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage.
|
||||
if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
|
||||
blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment;
|
||||
uses_blend_alpha = blend_mode_uses_blend_alpha(BlendMode(blend_mode));
|
||||
}
|
||||
|
||||
switch (blend_mode) {
|
||||
case BLEND_MODE_MIX: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
|
||||
return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
|
||||
}
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_ADD: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_SUB: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
|
||||
}
|
||||
|
||||
} break;
|
||||
case BLEND_MODE_MUL: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
uses_blend_alpha = true; //force alpha used because of blend
|
||||
} break;
|
||||
case BLEND_MODE_ALPHA_TO_COVERAGE: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
} break;
|
||||
case BLEND_MODE_PREMULT_ALPHA: {
|
||||
blend_attachment.enable_blend = true;
|
||||
blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
uses_blend_alpha = true; // Force alpha used because of blend.
|
||||
} break;
|
||||
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_native_source_code(version);
|
||||
} else {
|
||||
return RS::ShaderNativeSourceCode();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeline_key) {
|
||||
#if PRINT_PIPELINE_COMPILATION_KEYS
|
||||
print_line(
|
||||
"HASH:", p_pipeline_key.hash(),
|
||||
"VERSION:", version,
|
||||
"VERTEX:", p_pipeline_key.vertex_format_id,
|
||||
"FRAMEBUFFER:", p_pipeline_key.framebuffer_format_id,
|
||||
"CULL:", p_pipeline_key.cull_mode,
|
||||
"PRIMITIVE:", p_pipeline_key.primitive_type,
|
||||
"VERSION:", p_pipeline_key.version,
|
||||
"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
|
||||
"SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1,
|
||||
"SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2,
|
||||
"SPEC PACKED #3:", p_pipeline_key.shader_specialization.packed_3,
|
||||
"RENDER PASS:", p_pipeline_key.render_pass,
|
||||
"WIREFRAME:", p_pipeline_key.wireframe);
|
||||
#endif
|
||||
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment = blend_mode_to_blend_attachment(BlendMode(blend_mode));
|
||||
RD::PipelineColorBlendState blend_state_blend;
|
||||
blend_state_blend.attachments.push_back(blend_attachment);
|
||||
RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
|
||||
|
|
@ -286,113 +268,161 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
|||
depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CULL_VARIANT_MAX; i++) {
|
||||
RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
|
||||
};
|
||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||
RD::RENDER_PRIMITIVE_POINTS,
|
||||
RD::RENDER_PRIMITIVE_LINES,
|
||||
RD::RENDER_PRIMITIVE_LINESTRIPS,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLES,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
||||
};
|
||||
|
||||
RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
|
||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
|
||||
|
||||
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
|
||||
RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = {
|
||||
RD::RENDER_PRIMITIVE_POINTS,
|
||||
RD::RENDER_PRIMITIVE_LINES,
|
||||
RD::RENDER_PRIMITIVE_LINESTRIPS,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLES,
|
||||
RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS,
|
||||
};
|
||||
RD::PipelineRasterizationState raster_state;
|
||||
raster_state.cull_mode = p_pipeline_key.cull_mode;
|
||||
raster_state.wireframe = wireframe || p_pipeline_key.wireframe;
|
||||
|
||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
multisample_state.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_pipeline_key.framebuffer_format_id, 0);
|
||||
|
||||
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
|
||||
if (!static_cast<SceneShaderForwardMobile *>(singleton)->shader.is_variant_enabled(k)) {
|
||||
continue;
|
||||
}
|
||||
RD::PipelineRasterizationState raster_state;
|
||||
raster_state.cull_mode = cull_mode_rd;
|
||||
raster_state.wireframe = wireframe;
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
if (uses_alpha || uses_blend_alpha) {
|
||||
// These flags should only go through if we have some form of MSAA.
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
RD::PipelineDepthStencilState depth_stencil = depth_stencil_state;
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
|
||||
if (uses_alpha || uses_blend_alpha) {
|
||||
// only allow these flags to go through if we have some form of msaa
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
|
||||
depth_stencil.enable_depth_write = false; //alpha does not draw depth
|
||||
}
|
||||
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
//none, blend state contains nothing
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
|
||||
} else {
|
||||
pipelines[i][j][k].clear();
|
||||
continue; // do not use this version (will error if using it is attempted)
|
||||
}
|
||||
} else {
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_MULTIVIEW || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || k == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
//none, leave empty
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
|
||||
} else {
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
||||
RID shader_variant = shader_singleton->shader.version_get_shader(version, k);
|
||||
pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0, singleton->default_specialization_constants);
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
|
||||
// Alpha does not write to depth.
|
||||
depth_stencil_state.enable_depth_write = false;
|
||||
}
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
// Contains nothing.
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
// Writes to normal and roughness in opaque way.
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5);
|
||||
} else {
|
||||
// Do not use this version (error case).
|
||||
}
|
||||
} else {
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
// Contains nothing.
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
// Writes to normal and roughness in opaque way.
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5);
|
||||
} else {
|
||||
// Unknown pipeline version.
|
||||
}
|
||||
}
|
||||
|
||||
valid = true;
|
||||
// Convert the specialization from the key to pipeline specialization constants.
|
||||
Vector<RD::PipelineSpecializationConstant> specialization_constants;
|
||||
RD::PipelineSpecializationConstant sc;
|
||||
sc.constant_id = 0;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_0;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 1;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_1;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 2;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_2;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 3;
|
||||
sc.float_value = p_pipeline_key.shader_specialization.packed_3;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.ubershader);
|
||||
ERR_FAIL_COND(shader_rid.is_null());
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, primitive_rd, raster_state, multisample_state, depth_stencil_state, blend_state, 0, p_pipeline_key.render_pass, specialization_constants);
|
||||
ERR_FAIL_COND(pipeline.is_null());
|
||||
|
||||
pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
|
||||
return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
|
||||
RD::PolygonCullMode SceneShaderForwardMobile::ShaderData::get_cull_mode_from_cull_variant(CullVariant p_cull_variant) {
|
||||
const RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
|
||||
};
|
||||
|
||||
return cull_mode_rd_table[p_cull_variant][cull_mode];
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||
|
||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test == DEPTH_TEST_DISABLED));
|
||||
void SceneShaderForwardMobile::ShaderData::_clear_vertex_input_mask_cache() {
|
||||
for (uint32_t i = 0; i < VERTEX_INPUT_MASKS_SIZE; i++) {
|
||||
vertex_input_masks[i].store(0);
|
||||
}
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, RID());
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0));
|
||||
} else {
|
||||
return RID();
|
||||
}
|
||||
}
|
||||
|
||||
return shader_singleton->shader.version_get_native_source_code(version);
|
||||
uint64_t SceneShaderForwardMobile::ShaderData::get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader) {
|
||||
// Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
|
||||
uint32_t input_mask_index = p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0);
|
||||
uint64_t input_mask = vertex_input_masks[input_mask_index].load(std::memory_order_relaxed);
|
||||
if (input_mask == 0) {
|
||||
RID shader_rid = get_shader_variant(p_shader_version, p_ubershader);
|
||||
ERR_FAIL_COND_V(shader_rid.is_null(), 0);
|
||||
|
||||
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_rid);
|
||||
vertex_input_masks[input_mask_index].store(input_mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return input_mask;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_valid() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, false);
|
||||
return SceneShaderForwardMobile::singleton->shader.version_is_valid(version);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::ShaderData() :
|
||||
shader_list_element(this) {
|
||||
pipeline_hash_map.set_creation_object_and_function(this, &ShaderData::_create_pipeline);
|
||||
pipeline_hash_map.set_compilations(SceneShaderForwardMobile::singleton->pipeline_compilations, &SceneShaderForwardMobile::singleton_mutex);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::~ShaderData() {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
ERR_FAIL_NULL(shader_singleton);
|
||||
//pipeline variants will clear themselves if shader is gone
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
if (version.is_valid()) {
|
||||
shader_singleton->shader.version_free(version);
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL(SceneShaderForwardMobile::singleton);
|
||||
SceneShaderForwardMobile::singleton->shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ShaderData *shader_data = memnew(ShaderData);
|
||||
singleton->shader_list.add(&shader_data->shader_list_element);
|
||||
return shader_data;
|
||||
|
|
@ -407,9 +437,12 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
|
|||
}
|
||||
|
||||
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
|
||||
if (shader_data->version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::MaterialData::~MaterialData() {
|
||||
|
|
@ -426,6 +459,7 @@ RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_mat
|
|||
/* Scene Shader */
|
||||
|
||||
SceneShaderForwardMobile *SceneShaderForwardMobile::singleton = nullptr;
|
||||
Mutex SceneShaderForwardMobile::singleton_mutex;
|
||||
|
||||
SceneShaderForwardMobile::SceneShaderForwardMobile() {
|
||||
// there should be only one of these, contained within our RenderForwardMobile singleton.
|
||||
|
|
@ -435,27 +469,48 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
|
|||
void SceneShaderForwardMobile::init(const String p_defines) {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
// Immutable samplers : create the shadow sampler to be passed when creating the pipeline.
|
||||
{
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.enable_compare = true;
|
||||
sampler.compare_op = RD::COMPARE_OP_GREATER;
|
||||
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
|
||||
}
|
||||
|
||||
/* SCENE SHADER */
|
||||
|
||||
{
|
||||
Vector<String> shader_versions;
|
||||
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
|
||||
const String base_define = ubershader ? "\n#define UBERSHADER\n" : "";
|
||||
shader_versions.push_back(base_define + ""); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back(base_define + "\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS, should probably change this to MODE_RENDER_SHADOW because we don't have a depth pass here...
|
||||
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_SHADOW_PASS_DP
|
||||
shader_versions.push_back(base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
|
||||
// multiview versions of our shaders
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
|
||||
shader.initialize(shader_versions, p_defines);
|
||||
// Multiview versions of our shaders.
|
||||
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n"); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
}
|
||||
|
||||
Vector<RD::PipelineImmutableSampler> immutable_samplers;
|
||||
RD::PipelineImmutableSampler immutable_shadow_sampler;
|
||||
immutable_shadow_sampler.binding = 2;
|
||||
immutable_shadow_sampler.append_id(shadow_sampler);
|
||||
immutable_shadow_sampler.uniform_type = RenderingDeviceCommons::UNIFORM_TYPE_SAMPLER;
|
||||
immutable_samplers.push_back(immutable_shadow_sampler);
|
||||
shader.initialize(shader_versions, p_defines, immutable_samplers);
|
||||
if (!RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
|
||||
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
|
||||
uint32_t base_variant = ubershader ? SHADER_VERSION_MAX : 0;
|
||||
shader.set_variant_enabled(base_variant + SHADER_VERSION_COLOR_PASS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(base_variant + SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW, false);
|
||||
shader.set_variant_enabled(base_variant + SHADER_VERSION_SHADOW_PASS_MULTIVIEW, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -500,6 +555,8 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
|
||||
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
|
|
@ -539,7 +596,6 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
actions.renames["CUSTOM1"] = "custom1_attrib";
|
||||
actions.renames["CUSTOM2"] = "custom2_attrib";
|
||||
actions.renames["CUSTOM3"] = "custom3_attrib";
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["LIGHT_VERTEX"] = "light_vertex";
|
||||
|
||||
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
|
||||
|
|
@ -632,6 +688,13 @@ void SceneShaderForwardMobile::init(const String p_defines) {
|
|||
actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
|
||||
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
|
||||
bool force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
|
||||
if (!force_vertex_shading) {
|
||||
// If forcing vertex shading, this will be defined already.
|
||||
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
|
||||
}
|
||||
|
||||
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
|
||||
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
|
||||
|
||||
|
|
@ -741,27 +804,23 @@ void fragment() {
|
|||
|
||||
default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RenderForwardMobile::TRANSFORMS_UNIFORM_SET);
|
||||
}
|
||||
{
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.enable_compare = true;
|
||||
sampler.compare_op = RD::COMPARE_OP_GREATER;
|
||||
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::set_default_specialization(const ShaderSpecialization &p_specialization) {
|
||||
default_specialization = p_specialization;
|
||||
|
||||
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
|
||||
E->self()->pipeline_hash_map.clear_pipelines();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants) {
|
||||
default_specialization_constants = p_constants;
|
||||
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
|
||||
for (int i = 0; i < ShaderData::CULL_VARIANT_MAX; i++) {
|
||||
for (int j = 0; j < RS::PRIMITIVE_MAX; j++) {
|
||||
for (int k = 0; k < SHADER_VERSION_MAX; k++) {
|
||||
E->self()->pipelines[i][j][k].update_specialization_constants(default_specialization_constants);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t SceneShaderForwardMobile::get_pipeline_compilations(RS::PipelineSource p_source) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return pipeline_compilations[p_source];
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::is_multiview_enabled() const {
|
||||
return shader.is_variant_enabled(SHADER_VERSION_COLOR_PASS_MULTIVIEW);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@
|
|||
#ifndef SCENE_SHADER_FORWARD_MOBILE_H
|
||||
#define SCENE_SHADER_FORWARD_MOBILE_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "../storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_hash_map_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl.gen.h"
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
|
@ -39,6 +40,7 @@ namespace RendererSceneRenderImplementation {
|
|||
class SceneShaderForwardMobile {
|
||||
private:
|
||||
static SceneShaderForwardMobile *singleton;
|
||||
static Mutex singleton_mutex;
|
||||
|
||||
public:
|
||||
enum ShaderVersion {
|
||||
|
|
@ -55,16 +57,79 @@ public:
|
|||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_PREMULT_ALPHA,
|
||||
BLEND_MODE_ALPHA_TO_COVERAGE
|
||||
struct ShaderSpecialization {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t use_light_projector : 1;
|
||||
uint32_t use_light_soft_shadows : 1;
|
||||
uint32_t use_directional_soft_shadows : 1;
|
||||
uint32_t decal_use_mipmaps : 1;
|
||||
uint32_t projector_use_mipmaps : 1;
|
||||
uint32_t disable_fog : 1;
|
||||
uint32_t use_depth_fog : 1;
|
||||
uint32_t use_fog_aerial_perspective : 1;
|
||||
uint32_t use_fog_sun_scatter : 1;
|
||||
uint32_t use_fog_height_density : 1;
|
||||
uint32_t use_lightmap_bicubic_filter : 1;
|
||||
uint32_t multimesh : 1;
|
||||
uint32_t multimesh_format_2d : 1;
|
||||
uint32_t multimesh_has_color : 1;
|
||||
uint32_t multimesh_has_custom_data : 1;
|
||||
uint32_t scene_use_ambient_cubemap : 1;
|
||||
uint32_t scene_use_reflection_cubemap : 1;
|
||||
uint32_t scene_roughness_limiter_enabled : 1;
|
||||
uint32_t padding_0 : 2;
|
||||
uint32_t soft_shadow_samples : 6;
|
||||
uint32_t penumbra_shadow_samples : 6;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t packed_1;
|
||||
|
||||
struct {
|
||||
uint32_t directional_soft_shadow_samples : 6;
|
||||
uint32_t directional_penumbra_shadow_samples : 6;
|
||||
uint32_t omni_lights : 4;
|
||||
uint32_t spot_lights : 4;
|
||||
uint32_t reflection_probes : 4;
|
||||
uint32_t directional_lights : 4;
|
||||
uint32_t decals : 4;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t packed_2;
|
||||
|
||||
struct {
|
||||
uint32_t directional_light_blend_splits : 8;
|
||||
uint32_t padding_1 : 24;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
float packed_3;
|
||||
float luminance_multiplier;
|
||||
};
|
||||
};
|
||||
|
||||
struct UbershaderConstants {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t cull_mode : 2;
|
||||
};
|
||||
};
|
||||
|
||||
uint32_t padding_1;
|
||||
uint32_t padding_2;
|
||||
uint32_t padding_3;
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
|
|
@ -76,12 +141,6 @@ public:
|
|||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum CullVariant {
|
||||
CULL_VARIANT_NORMAL,
|
||||
CULL_VARIANT_REVERSED,
|
||||
|
|
@ -96,10 +155,41 @@ public:
|
|||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||
};
|
||||
|
||||
bool valid = false;
|
||||
struct PipelineKey {
|
||||
RD::VertexFormatID vertex_format_id;
|
||||
RD::FramebufferFormatID framebuffer_format_id;
|
||||
RD::PolygonCullMode cull_mode = RD::POLYGON_CULL_MAX;
|
||||
RS::PrimitiveType primitive_type = RS::PRIMITIVE_MAX;
|
||||
ShaderSpecialization shader_specialization = {};
|
||||
ShaderVersion version = SHADER_VERSION_MAX;
|
||||
uint32_t render_pass = 0;
|
||||
uint32_t wireframe = false;
|
||||
uint32_t ubershader = false;
|
||||
|
||||
uint32_t hash() const {
|
||||
uint32_t h = hash_murmur3_one_32(vertex_format_id);
|
||||
h = hash_murmur3_one_32(framebuffer_format_id, h);
|
||||
h = hash_murmur3_one_32(cull_mode, h);
|
||||
h = hash_murmur3_one_32(primitive_type, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_0, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_1, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_2, h);
|
||||
h = hash_murmur3_one_float(shader_specialization.packed_3, h);
|
||||
h = hash_murmur3_one_32(version, h);
|
||||
h = hash_murmur3_one_32(render_pass, h);
|
||||
h = hash_murmur3_one_32(wireframe, h);
|
||||
h = hash_murmur3_one_32(ubershader, h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
};
|
||||
|
||||
void _create_pipeline(PipelineKey p_pipeline_key);
|
||||
PipelineHashMapRD<PipelineKey, ShaderData, void (ShaderData::*)(PipelineKey)> pipeline_hash_map;
|
||||
|
||||
RID version;
|
||||
uint64_t vertex_input_mask = 0;
|
||||
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
|
||||
|
||||
static const uint32_t VERTEX_INPUT_MASKS_SIZE = SHADER_VERSION_MAX * 2;
|
||||
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
|
||||
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
|
|
@ -111,6 +201,11 @@ public:
|
|||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
bool uses_point_size = false;
|
||||
bool uses_alpha = false;
|
||||
bool uses_blend_alpha = false;
|
||||
|
|
@ -122,6 +217,8 @@ public:
|
|||
bool uses_normal = false;
|
||||
bool uses_tangent = false;
|
||||
bool uses_particle_trails = false;
|
||||
bool uses_normal_map = false;
|
||||
bool wireframe = false;
|
||||
|
||||
bool unshaded = false;
|
||||
bool uses_vertex = false;
|
||||
|
|
@ -140,10 +237,35 @@ public:
|
|||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
_FORCE_INLINE_ bool uses_alpha_pass() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing));
|
||||
bool has_blend_alpha = uses_blend_alpha;
|
||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
||||
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test == DEPTH_TEST_DISABLED;
|
||||
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_shared_shadow_material() const {
|
||||
return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && !uses_world_coordinates && !wireframe;
|
||||
}
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
RD::PolygonCullMode get_cull_mode_from_cull_variant(CullVariant p_cull_variant);
|
||||
void _clear_vertex_input_mask_cache();
|
||||
RID get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const;
|
||||
uint64_t get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader);
|
||||
bool is_valid() const;
|
||||
|
||||
SelfList<ShaderData> shader_list_element;
|
||||
|
||||
|
|
@ -204,10 +326,14 @@ public:
|
|||
SceneShaderForwardMobile();
|
||||
~SceneShaderForwardMobile();
|
||||
|
||||
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
|
||||
ShaderSpecialization default_specialization = {};
|
||||
|
||||
uint32_t pipeline_compilations[RS::PIPELINE_SOURCE_MAX] = {};
|
||||
|
||||
void init(const String p_defines);
|
||||
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
|
||||
void set_default_specialization(const ShaderSpecialization &p_specialization);
|
||||
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
|
||||
bool is_multiview_enabled() const;
|
||||
};
|
||||
|
||||
} // namespace RendererSceneRenderImplementation
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const
|
|||
ERR_FAIL_COND(p_shader.is_null());
|
||||
_clear();
|
||||
shader = p_shader;
|
||||
input_mask = 0;
|
||||
render_primitive = p_primitive;
|
||||
rasterization_state = p_rasterization_state;
|
||||
multisample_state = p_multisample;
|
||||
|
|
@ -112,13 +111,11 @@ void PipelineCacheRD::update_shader(RID p_shader) {
|
|||
void PipelineCacheRD::clear() {
|
||||
_clear();
|
||||
shader = RID(); //clear shader
|
||||
input_mask = 0;
|
||||
}
|
||||
|
||||
PipelineCacheRD::PipelineCacheRD() {
|
||||
version_count = 0;
|
||||
versions = nullptr;
|
||||
input_mask = 0;
|
||||
}
|
||||
|
||||
PipelineCacheRD::~PipelineCacheRD() {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ class PipelineCacheRD {
|
|||
SpinLock spin_lock;
|
||||
|
||||
RID shader;
|
||||
uint64_t input_mask;
|
||||
|
||||
RD::RenderPrimitive render_primitive;
|
||||
RD::PipelineRasterizationState rasterization_state;
|
||||
|
|
@ -92,11 +91,8 @@ public:
|
|||
}
|
||||
|
||||
_FORCE_INLINE_ uint64_t get_vertex_input_mask() {
|
||||
if (input_mask == 0) {
|
||||
ERR_FAIL_COND_V(shader.is_null(), 0);
|
||||
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader);
|
||||
}
|
||||
return input_mask;
|
||||
ERR_FAIL_COND_V(shader.is_null(), 0);
|
||||
return RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader);
|
||||
}
|
||||
void clear();
|
||||
PipelineCacheRD();
|
||||
|
|
|
|||
221
engine/servers/rendering/renderer_rd/pipeline_hash_map_rd.h
Normal file
221
engine/servers/rendering/renderer_rd/pipeline_hash_map_rd.h
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/**************************************************************************/
|
||||
/* pipeline_hash_map_rd.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef PIPELINE_HASH_MAP_RD_H
|
||||
#define PIPELINE_HASH_MAP_RD_H
|
||||
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
#define PRINT_PIPELINE_COMPILATION_KEYS 0
|
||||
|
||||
template <typename Key, typename CreationClass, typename CreationFunction>
|
||||
class PipelineHashMapRD {
|
||||
private:
|
||||
CreationClass *creation_object = nullptr;
|
||||
CreationFunction creation_function = nullptr;
|
||||
Mutex *compilations_mutex = nullptr;
|
||||
uint32_t *compilations = nullptr;
|
||||
RBMap<uint32_t, RID> hash_map;
|
||||
LocalVector<Pair<uint32_t, RID>> compiled_queue;
|
||||
Mutex compiled_queue_mutex;
|
||||
RBSet<uint32_t> compilation_set;
|
||||
HashMap<uint32_t, WorkerThreadPool::TaskID> compilation_tasks;
|
||||
Mutex local_mutex;
|
||||
|
||||
bool _add_new_pipelines_to_map() {
|
||||
thread_local Vector<uint32_t> hashes_added;
|
||||
hashes_added.clear();
|
||||
|
||||
{
|
||||
MutexLock lock(compiled_queue_mutex);
|
||||
for (const Pair<uint32_t, RID> &pair : compiled_queue) {
|
||||
hash_map[pair.first] = pair.second;
|
||||
hashes_added.push_back(pair.first);
|
||||
}
|
||||
|
||||
compiled_queue.clear();
|
||||
}
|
||||
|
||||
{
|
||||
MutexLock local_lock(local_mutex);
|
||||
for (uint32_t hash : hashes_added) {
|
||||
HashMap<uint32_t, WorkerThreadPool::TaskID>::Iterator task_it = compilation_tasks.find(hash);
|
||||
if (task_it != compilation_tasks.end()) {
|
||||
compilation_tasks.remove(task_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !hashes_added.is_empty();
|
||||
}
|
||||
|
||||
void _wait_for_all_pipelines() {
|
||||
MutexLock local_lock(local_mutex);
|
||||
for (KeyValue<uint32_t, WorkerThreadPool::TaskID> key_value : compilation_tasks) {
|
||||
WorkerThreadPool::get_singleton()->wait_for_task_completion(key_value.value);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void add_compiled_pipeline(uint32_t p_hash, RID p_pipeline) {
|
||||
compiled_queue_mutex.lock();
|
||||
compiled_queue.push_back({ p_hash, p_pipeline });
|
||||
compiled_queue_mutex.unlock();
|
||||
}
|
||||
|
||||
// Start compilation of a pipeline ahead of time in the background. Returns true if the compilation was started, false if it wasn't required. Source is only used for collecting statistics.
|
||||
void compile_pipeline(const Key &p_key, uint32_t p_key_hash, RS::PipelineSource p_source, bool p_high_priority) {
|
||||
DEV_ASSERT((creation_object != nullptr) && (creation_function != nullptr) && "Creation object and function was not set before attempting to compile a pipeline.");
|
||||
|
||||
MutexLock local_lock(local_mutex);
|
||||
if (compilation_set.has(p_key_hash)) {
|
||||
// Check if the pipeline was already submitted.
|
||||
return;
|
||||
}
|
||||
|
||||
// Record the pipeline as submitted, a task can't be started for it again.
|
||||
compilation_set.insert(p_key_hash);
|
||||
|
||||
if (compilations_mutex != nullptr) {
|
||||
MutexLock compilations_lock(*compilations_mutex);
|
||||
compilations[p_source]++;
|
||||
}
|
||||
|
||||
#if PRINT_PIPELINE_COMPILATION_KEYS
|
||||
String source_name = "UNKNOWN";
|
||||
switch (p_source) {
|
||||
case RS::PIPELINE_SOURCE_CANVAS:
|
||||
source_name = "CANVAS";
|
||||
break;
|
||||
case RS::PIPELINE_SOURCE_MESH:
|
||||
source_name = "MESH";
|
||||
break;
|
||||
case RS::PIPELINE_SOURCE_SURFACE:
|
||||
source_name = "SURFACE";
|
||||
break;
|
||||
case RS::PIPELINE_SOURCE_DRAW:
|
||||
source_name = "DRAW";
|
||||
break;
|
||||
case RS::PIPELINE_SOURCE_SPECIALIZATION:
|
||||
source_name = "SPECIALIZATION";
|
||||
break;
|
||||
}
|
||||
|
||||
print_line("HASH:", p_key_hash, "SOURCE:", source_name);
|
||||
#endif
|
||||
|
||||
// Queue a background compilation task.
|
||||
WorkerThreadPool::TaskID task_id = WorkerThreadPool::get_singleton()->add_template_task(creation_object, creation_function, p_key, p_high_priority, "PipelineCompilation");
|
||||
compilation_tasks.insert(p_key_hash, task_id);
|
||||
}
|
||||
|
||||
void wait_for_pipeline(uint32_t p_key_hash) {
|
||||
MutexLock local_lock(local_mutex);
|
||||
if (!compilation_set.has(p_key_hash)) {
|
||||
// The pipeline was never submitted, we can't wait for it.
|
||||
return;
|
||||
}
|
||||
|
||||
HashMap<uint32_t, WorkerThreadPool::TaskID>::Iterator task_it = compilation_tasks.find(p_key_hash);
|
||||
if (task_it != compilation_tasks.end()) {
|
||||
// Wait for and remove the compilation task if it exists.
|
||||
WorkerThreadPool::get_singleton()->wait_for_task_completion(task_it->value);
|
||||
compilation_tasks.remove(task_it);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve a pipeline. It'll return an empty pipeline if it's not available yet, but it'll be guaranteed to succeed if 'wait for compilation' is true and stall as necessary. Source is just an optional number to aid debugging.
|
||||
RID get_pipeline(const Key &p_key, uint32_t p_key_hash, bool p_wait_for_compilation, RS::PipelineSource p_source) {
|
||||
RBMap<uint32_t, RID>::Element *e = hash_map.find(p_key_hash);
|
||||
|
||||
if (e == nullptr) {
|
||||
// Check if there's any new pipelines that need to be added and try again. This method triggers a mutex lock.
|
||||
if (_add_new_pipelines_to_map()) {
|
||||
e = hash_map.find(p_key_hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (e == nullptr) {
|
||||
// Request compilation. The method will ignore the request if it's already being compiled.
|
||||
compile_pipeline(p_key, p_key_hash, p_source, p_wait_for_compilation);
|
||||
|
||||
if (p_wait_for_compilation) {
|
||||
wait_for_pipeline(p_key_hash);
|
||||
_add_new_pipelines_to_map();
|
||||
|
||||
e = hash_map.find(p_key_hash);
|
||||
if (e != nullptr) {
|
||||
return e->value();
|
||||
} else {
|
||||
// Pipeline could not be compiled due to an internal error. Store an empty RID so compilation is not attempted again.
|
||||
hash_map[p_key_hash] = RID();
|
||||
return RID();
|
||||
}
|
||||
} else {
|
||||
return RID();
|
||||
}
|
||||
} else {
|
||||
return e->value();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all cached pipelines. Can stall if background compilation is in progress.
|
||||
void clear_pipelines() {
|
||||
_wait_for_all_pipelines();
|
||||
_add_new_pipelines_to_map();
|
||||
|
||||
for (KeyValue<uint32_t, RID> entry : hash_map) {
|
||||
RD::get_singleton()->free(entry.value);
|
||||
}
|
||||
|
||||
hash_map.clear();
|
||||
compilation_set.clear();
|
||||
}
|
||||
|
||||
// Set the external pipeline compilations array to increase the counters on every time a pipeline is compiled.
|
||||
void set_compilations(uint32_t *p_compilations, Mutex *p_compilations_mutex) {
|
||||
compilations = p_compilations;
|
||||
compilations_mutex = p_compilations_mutex;
|
||||
}
|
||||
|
||||
void set_creation_object_and_function(CreationClass *p_creation_object, CreationFunction p_creation_function) {
|
||||
creation_object = p_creation_object;
|
||||
creation_function = p_creation_function;
|
||||
}
|
||||
|
||||
PipelineHashMapRD() {}
|
||||
|
||||
~PipelineHashMapRD() {
|
||||
clear_pipelines();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PIPELINE_HASH_MAP_RD_H
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -31,9 +31,9 @@
|
|||
#ifndef RENDERER_CANVAS_RENDER_RD_H
|
||||
#define RENDERER_CANVAS_RENDER_RD_H
|
||||
|
||||
#include "core/templates/lru.h"
|
||||
#include "servers/rendering/renderer_canvas_render.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_hash_map_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
|
|
@ -45,10 +45,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
BASE_UNIFORM_SET = 0,
|
||||
MATERIAL_UNIFORM_SET = 1,
|
||||
TRANSFORMS_UNIFORM_SET = 2,
|
||||
CANVAS_TEXTURE_UNIFORM_SET = 3,
|
||||
BATCH_UNIFORM_SET = 3,
|
||||
};
|
||||
|
||||
const int SAMPLERS_BINDING_FIRST_INDEX = 10;
|
||||
// The size of the ring buffer to store GPU buffers. Triple-buffering the max expected frames in flight.
|
||||
static const uint32_t BATCH_DATA_BUFFER_COUNT = 3;
|
||||
|
||||
enum ShaderVariant {
|
||||
SHADER_VARIANT_QUAD,
|
||||
|
|
@ -57,41 +59,35 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
SHADER_VARIANT_PRIMITIVE_POINTS,
|
||||
SHADER_VARIANT_ATTRIBUTES,
|
||||
SHADER_VARIANT_ATTRIBUTES_POINTS,
|
||||
SHADER_VARIANT_QUAD_LIGHT,
|
||||
SHADER_VARIANT_NINEPATCH_LIGHT,
|
||||
SHADER_VARIANT_PRIMITIVE_LIGHT,
|
||||
SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT,
|
||||
SHADER_VARIANT_ATTRIBUTES_LIGHT,
|
||||
SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
|
||||
SHADER_VARIANT_MAX
|
||||
};
|
||||
|
||||
enum {
|
||||
INSTANCE_FLAGS_LIGHT_COUNT_SHIFT = 0, // 4 bits for light count.
|
||||
|
||||
FLAGS_INSTANCING_MASK = 0x7F,
|
||||
FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
|
||||
FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),
|
||||
INSTANCE_FLAGS_CLIP_RECT_UV = (1 << 4),
|
||||
INSTANCE_FLAGS_TRANSPOSE_RECT = (1 << 5),
|
||||
INSTANCE_FLAGS_USE_MSDF = (1 << 6),
|
||||
INSTANCE_FLAGS_USE_LCD = (1 << 7),
|
||||
|
||||
FLAGS_CLIP_RECT_UV = (1 << 9),
|
||||
FLAGS_TRANSPOSE_RECT = (1 << 10),
|
||||
INSTANCE_FLAGS_NINEPACH_DRAW_CENTER = (1 << 8),
|
||||
INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT = 9,
|
||||
INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT = 11,
|
||||
|
||||
FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 11),
|
||||
INSTANCE_FLAGS_SHADOW_MASKED_SHIFT = 13, // 16 bits.
|
||||
};
|
||||
|
||||
FLAGS_NINEPACH_DRAW_CENTER = (1 << 12),
|
||||
enum {
|
||||
BATCH_FLAGS_INSTANCING_MASK = 0x7F,
|
||||
BATCH_FLAGS_INSTANCING_HAS_COLORS = (1 << 7),
|
||||
BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 8),
|
||||
|
||||
FLAGS_USE_SKELETON = (1 << 15),
|
||||
FLAGS_NINEPATCH_H_MODE_SHIFT = 16,
|
||||
FLAGS_NINEPATCH_V_MODE_SHIFT = 18,
|
||||
FLAGS_LIGHT_COUNT_SHIFT = 20,
|
||||
BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 9),
|
||||
BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 10),
|
||||
};
|
||||
|
||||
FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26),
|
||||
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
|
||||
|
||||
FLAGS_USE_MSDF = (1 << 28),
|
||||
FLAGS_USE_LCD = (1 << 29),
|
||||
|
||||
FLAGS_FLIP_H = (1 << 30),
|
||||
FLAGS_FLIP_V = (1 << 31),
|
||||
enum {
|
||||
CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR = (1 << 0),
|
||||
};
|
||||
|
||||
enum {
|
||||
|
|
@ -118,76 +114,82 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
/**** SHADER ****/
|
||||
/****************/
|
||||
|
||||
enum PipelineVariant {
|
||||
PIPELINE_VARIANT_QUAD,
|
||||
PIPELINE_VARIANT_NINEPATCH,
|
||||
PIPELINE_VARIANT_PRIMITIVE_TRIANGLES,
|
||||
PIPELINE_VARIANT_PRIMITIVE_LINES,
|
||||
PIPELINE_VARIANT_PRIMITIVE_POINTS,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_LINES,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
|
||||
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
|
||||
PIPELINE_VARIANT_QUAD_LCD_BLEND,
|
||||
PIPELINE_VARIANT_MAX
|
||||
};
|
||||
enum PipelineLightMode {
|
||||
PIPELINE_LIGHT_MODE_DISABLED,
|
||||
PIPELINE_LIGHT_MODE_ENABLED,
|
||||
PIPELINE_LIGHT_MODE_MAX
|
||||
struct ShaderSpecialization {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t use_lighting : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct PipelineVariants {
|
||||
PipelineCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX];
|
||||
struct PipelineKey {
|
||||
ShaderVariant variant = SHADER_VARIANT_MAX;
|
||||
RD::FramebufferFormatID framebuffer_format_id = RD::INVALID_FORMAT_ID;
|
||||
RD::VertexFormatID vertex_format_id = RD::INVALID_ID;
|
||||
RD::RenderPrimitive render_primitive = RD::RENDER_PRIMITIVE_MAX;
|
||||
ShaderSpecialization shader_specialization = {};
|
||||
uint32_t lcd_blend = 0;
|
||||
uint32_t ubershader = 0;
|
||||
|
||||
uint32_t hash() const {
|
||||
uint32_t h = hash_murmur3_one_32(variant);
|
||||
h = hash_murmur3_one_32(framebuffer_format_id, h);
|
||||
h = hash_murmur3_one_64((uint64_t)vertex_format_id, h);
|
||||
h = hash_murmur3_one_32(render_primitive, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_0, h);
|
||||
h = hash_murmur3_one_32(lcd_blend, h);
|
||||
h = hash_murmur3_one_32(ubershader, h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
};
|
||||
|
||||
struct {
|
||||
CanvasShaderRD canvas_shader;
|
||||
RID default_version;
|
||||
RID default_version_rd_shader;
|
||||
RID quad_index_buffer;
|
||||
RID quad_index_array;
|
||||
PipelineVariants pipeline_variants;
|
||||
|
||||
ShaderCompiler compiler;
|
||||
} shader;
|
||||
|
||||
struct CanvasShaderData : public RendererRD::MaterialStorage::ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_PMALPHA,
|
||||
BLEND_MODE_DISABLED,
|
||||
};
|
||||
|
||||
bool valid = false;
|
||||
RID version;
|
||||
PipelineVariants pipeline_variants;
|
||||
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
int blend_mode = 0;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size = 0;
|
||||
|
||||
String code;
|
||||
RID version;
|
||||
PipelineHashMapRD<PipelineKey, CanvasShaderData, void (CanvasShaderData::*)(PipelineKey)> pipeline_hash_map;
|
||||
|
||||
static const uint32_t VERTEX_INPUT_MASKS_SIZE = SHADER_VARIANT_MAX * 2;
|
||||
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
|
||||
|
||||
bool uses_screen_texture = false;
|
||||
bool uses_screen_texture_mipmaps = false;
|
||||
bool uses_sdf = false;
|
||||
bool uses_time = false;
|
||||
|
||||
void _clear_vertex_input_mask_cache();
|
||||
void _create_pipeline(PipelineKey p_pipeline_key);
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
RID get_shader(ShaderVariant p_shader_variant, bool p_ubershader) const;
|
||||
uint64_t get_vertex_input_mask(ShaderVariant p_shader_variant, bool p_ubershader);
|
||||
bool is_valid() const;
|
||||
|
||||
CanvasShaderData() {}
|
||||
CanvasShaderData();
|
||||
virtual ~CanvasShaderData();
|
||||
};
|
||||
|
||||
struct {
|
||||
// Data must be guaranteed to be erased before the rest on the destructor.
|
||||
CanvasShaderData *default_version_data = nullptr;
|
||||
CanvasShaderRD canvas_shader;
|
||||
RID default_version_rd_shader;
|
||||
RID quad_index_buffer;
|
||||
RID quad_index_array;
|
||||
ShaderCompiler compiler;
|
||||
uint32_t pipeline_compilations[RS::PIPELINE_SOURCE_MAX] = {};
|
||||
Mutex mutex;
|
||||
} shader;
|
||||
|
||||
RendererRD::MaterialStorage::ShaderData *_create_shader_func();
|
||||
static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
|
||||
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
|
||||
|
|
@ -264,12 +266,23 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
|
||||
RID_Owner<CanvasLight> canvas_light_owner;
|
||||
|
||||
struct PositionalShadowRenderPushConstant {
|
||||
float modelview[8];
|
||||
float rotation[4];
|
||||
float direction[2];
|
||||
float z_far;
|
||||
uint32_t pad;
|
||||
float z_near;
|
||||
uint32_t cull_mode;
|
||||
float pad2[2];
|
||||
};
|
||||
|
||||
struct ShadowRenderPushConstant {
|
||||
float projection[16];
|
||||
float modelview[8];
|
||||
float direction[2];
|
||||
float z_far;
|
||||
float pad;
|
||||
uint32_t cull_mode;
|
||||
};
|
||||
|
||||
struct OccluderPolygon {
|
||||
|
|
@ -309,7 +322,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
RID_Owner<OccluderPolygon> occluder_polygon_owner;
|
||||
|
||||
enum ShadowRenderMode {
|
||||
SHADOW_RENDER_MODE_SHADOW,
|
||||
SHADOW_RENDER_MODE_DIRECTIONAL_SHADOW,
|
||||
SHADOW_RENDER_MODE_POSITIONAL_SHADOW,
|
||||
SHADOW_RENDER_MODE_SDF,
|
||||
};
|
||||
|
||||
|
|
@ -321,7 +335,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
struct {
|
||||
CanvasOcclusionShaderRD shader;
|
||||
RID shader_version;
|
||||
RID render_pipelines[3];
|
||||
RID render_pipelines[2];
|
||||
RID sdf_render_pipelines[2];
|
||||
RD::VertexFormatID vertex_format;
|
||||
RD::VertexFormatID sdf_vertex_format;
|
||||
|
|
@ -335,51 +349,10 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
|
||||
//state that does not vary across rendering all items
|
||||
|
||||
struct State {
|
||||
//state buffer
|
||||
struct Buffer {
|
||||
float canvas_transform[16];
|
||||
float screen_transform[16];
|
||||
float canvas_normal_transform[16];
|
||||
float canvas_modulate[4];
|
||||
|
||||
float screen_pixel_size[2];
|
||||
float time;
|
||||
uint32_t use_pixel_snap;
|
||||
|
||||
float sdf_to_tex[4];
|
||||
float sdf_to_screen[2];
|
||||
float screen_to_sdf[2];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
float tex_to_sdf;
|
||||
uint32_t pad1;
|
||||
uint32_t pad2;
|
||||
};
|
||||
|
||||
LightUniform *light_uniforms = nullptr;
|
||||
|
||||
RID lights_uniform_buffer;
|
||||
RID canvas_state_buffer;
|
||||
RID shadow_sampler;
|
||||
RID shadow_texture;
|
||||
RID shadow_depth_texture;
|
||||
RID shadow_fb;
|
||||
int shadow_texture_size = 2048;
|
||||
|
||||
RID default_transforms_uniform_set;
|
||||
|
||||
uint32_t max_lights_per_render;
|
||||
uint32_t max_lights_per_item;
|
||||
|
||||
double time;
|
||||
|
||||
} state;
|
||||
|
||||
struct PushConstant {
|
||||
struct InstanceData {
|
||||
float world[6];
|
||||
uint32_t flags;
|
||||
uint32_t specular_shininess;
|
||||
uint32_t instance_uniforms_ofs;
|
||||
union {
|
||||
//rect
|
||||
struct {
|
||||
|
|
@ -403,8 +376,225 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
uint32_t lights[4];
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
uint32_t base_instance_index;
|
||||
ShaderSpecialization shader_specialization;
|
||||
uint32_t specular_shininess;
|
||||
uint32_t batch_flags;
|
||||
};
|
||||
|
||||
// TextureState is used to determine when a new batch is required due to a change of texture state.
|
||||
struct TextureState {
|
||||
static const uint32_t FILTER_SHIFT = 0;
|
||||
static const uint32_t FILTER_BITS = 3;
|
||||
static const uint32_t FILTER_MASK = (1 << FILTER_BITS) - 1;
|
||||
static const uint32_t REPEAT_SHIFT = FILTER_BITS;
|
||||
static const uint32_t REPEAT_BITS = 2;
|
||||
static const uint32_t REPEAT_MASK = (1 << REPEAT_BITS) - 1;
|
||||
static const uint32_t TEXTURE_IS_DATA_SHIFT = REPEAT_SHIFT + REPEAT_BITS;
|
||||
static const uint32_t TEXTURE_IS_DATA_BITS = 1;
|
||||
static const uint32_t TEXTURE_IS_DATA_MASK = (1 << TEXTURE_IS_DATA_BITS) - 1;
|
||||
static const uint32_t LINEAR_COLORS_SHIFT = TEXTURE_IS_DATA_SHIFT + TEXTURE_IS_DATA_BITS;
|
||||
static const uint32_t LINEAR_COLORS_BITS = 1;
|
||||
static const uint32_t LINEAR_COLORS_MASK = (1 << LINEAR_COLORS_BITS) - 1;
|
||||
|
||||
RID texture;
|
||||
uint32_t other = 0;
|
||||
|
||||
TextureState() {}
|
||||
|
||||
TextureState(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, bool p_texture_is_data, bool p_use_linear_colors) {
|
||||
texture = p_texture;
|
||||
other = (((uint32_t)p_base_filter & FILTER_MASK) << FILTER_SHIFT) |
|
||||
(((uint32_t)p_base_repeat & REPEAT_MASK) << REPEAT_SHIFT) |
|
||||
(((uint32_t)p_texture_is_data & TEXTURE_IS_DATA_MASK) << TEXTURE_IS_DATA_SHIFT) |
|
||||
(((uint32_t)p_use_linear_colors & LINEAR_COLORS_MASK) << LINEAR_COLORS_SHIFT);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ RS::CanvasItemTextureFilter texture_filter() const {
|
||||
return (RS::CanvasItemTextureFilter)((other >> FILTER_SHIFT) & FILTER_MASK);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ RS::CanvasItemTextureRepeat texture_repeat() const {
|
||||
return (RS::CanvasItemTextureRepeat)((other >> REPEAT_SHIFT) & REPEAT_MASK);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool linear_colors() const {
|
||||
return (other >> LINEAR_COLORS_SHIFT) & LINEAR_COLORS_MASK;
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool texture_is_data() const {
|
||||
return (other >> TEXTURE_IS_DATA_SHIFT) & TEXTURE_IS_DATA_MASK;
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool operator==(const TextureState &p_val) const {
|
||||
return (texture == p_val.texture) && (other == p_val.other);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool operator!=(const TextureState &p_val) const {
|
||||
return (texture != p_val.texture) || (other != p_val.other);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool is_valid() const { return texture.is_valid(); }
|
||||
_ALWAYS_INLINE_ bool is_null() const { return texture.is_null(); }
|
||||
|
||||
uint32_t hash() const {
|
||||
uint32_t hash = hash_murmur3_one_64(texture.get_id());
|
||||
return hash_murmur3_one_32(other, hash);
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureInfo {
|
||||
TextureState state;
|
||||
RID diffuse;
|
||||
RID normal;
|
||||
RID specular;
|
||||
RID sampler;
|
||||
Vector2 texpixel_size;
|
||||
uint32_t specular_shininess = 0;
|
||||
uint32_t flags = 0;
|
||||
};
|
||||
|
||||
/// A key used to uniquely identify a distinct BATCH_UNIFORM_SET
|
||||
struct RIDSetKey {
|
||||
TextureState state;
|
||||
RID instance_data;
|
||||
|
||||
RIDSetKey() {
|
||||
}
|
||||
|
||||
RIDSetKey(TextureState p_state, RID p_instance_data) :
|
||||
state(p_state),
|
||||
instance_data(p_instance_data) {
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool operator==(const RIDSetKey &p_val) const {
|
||||
return state == p_val.state && instance_data == p_val.instance_data;
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ bool operator!=(const RIDSetKey &p_val) const {
|
||||
return !(*this == p_val);
|
||||
}
|
||||
|
||||
_ALWAYS_INLINE_ uint32_t hash() const {
|
||||
uint32_t h = state.hash();
|
||||
h = hash_murmur3_one_64(instance_data.get_id(), h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
};
|
||||
|
||||
static void _before_evict(RendererCanvasRenderRD::RIDSetKey &p_key, RID &p_rid);
|
||||
static void _uniform_set_invalidation_callback(void *p_userdata);
|
||||
static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata);
|
||||
|
||||
typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
|
||||
RIDCache rid_set_to_uniform_set;
|
||||
/// Maps a CanvasTexture to its associated uniform sets, which must
|
||||
/// be invalidated when the CanvasTexture is updated, such as changing the
|
||||
/// diffuse texture.
|
||||
HashMap<RID, TightLocalVector<RID>> canvas_texture_to_uniform_set;
|
||||
|
||||
struct Batch {
|
||||
// Position in the UBO measured in bytes
|
||||
uint32_t start = 0;
|
||||
uint32_t instance_count = 0;
|
||||
uint32_t instance_buffer_index = 0;
|
||||
|
||||
TextureInfo *tex_info;
|
||||
|
||||
Color modulate = Color(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
Item *clip = nullptr;
|
||||
|
||||
RID material;
|
||||
CanvasMaterialData *material_data = nullptr;
|
||||
|
||||
const Item::Command *command = nullptr;
|
||||
Item::Command::Type command_type = Item::Command::TYPE_ANIMATION_SLICE; // Can default to any type that doesn't form a batch.
|
||||
ShaderVariant shader_variant = SHADER_VARIANT_QUAD;
|
||||
RD::RenderPrimitive render_primitive = RD::RENDER_PRIMITIVE_TRIANGLES;
|
||||
bool use_lighting = false;
|
||||
|
||||
// batch-specific data
|
||||
union {
|
||||
// TYPE_PRIMITIVE
|
||||
uint32_t primitive_points = 0;
|
||||
// TYPE_PARTICLES
|
||||
uint32_t mesh_instance_count;
|
||||
};
|
||||
bool has_blend = false;
|
||||
uint32_t flags = 0;
|
||||
};
|
||||
|
||||
HashMap<TextureState, TextureInfo, HashableHasher<TextureState>> texture_info_map;
|
||||
|
||||
// per-frame buffers
|
||||
struct DataBuffer {
|
||||
LocalVector<RID> instance_buffers;
|
||||
};
|
||||
|
||||
struct State {
|
||||
//state buffer
|
||||
struct Buffer {
|
||||
float canvas_transform[16];
|
||||
float screen_transform[16];
|
||||
float canvas_normal_transform[16];
|
||||
float canvas_modulate[4];
|
||||
|
||||
float screen_pixel_size[2];
|
||||
float time;
|
||||
uint32_t use_pixel_snap;
|
||||
|
||||
float sdf_to_tex[4];
|
||||
float sdf_to_screen[2];
|
||||
float screen_to_sdf[2];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
float tex_to_sdf;
|
||||
uint32_t flags;
|
||||
uint32_t pad2;
|
||||
};
|
||||
|
||||
DataBuffer canvas_instance_data_buffers[BATCH_DATA_BUFFER_COUNT];
|
||||
LocalVector<Batch> canvas_instance_batches;
|
||||
uint32_t current_data_buffer_index = 0;
|
||||
uint32_t current_instance_buffer_index = 0;
|
||||
uint32_t current_batch_index = 0;
|
||||
uint32_t last_instance_index = 0;
|
||||
InstanceData *instance_data_array = nullptr;
|
||||
|
||||
uint32_t max_instances_per_buffer = 16384;
|
||||
uint32_t max_instance_buffer_size = 16384 * sizeof(InstanceData);
|
||||
|
||||
Vector<RD::Uniform> batch_texture_uniforms;
|
||||
RID current_batch_uniform_set;
|
||||
|
||||
LightUniform *light_uniforms = nullptr;
|
||||
|
||||
RID lights_uniform_buffer;
|
||||
RID canvas_state_buffer;
|
||||
RID shadow_sampler;
|
||||
RID shadow_texture;
|
||||
RID shadow_depth_texture;
|
||||
RID shadow_fb;
|
||||
int shadow_texture_size = 2048;
|
||||
|
||||
RID shadow_occluder_buffer;
|
||||
uint32_t shadow_occluder_buffer_size;
|
||||
RID shadow_ocluder_uniform_set;
|
||||
|
||||
RID default_transforms_uniform_set;
|
||||
|
||||
uint32_t max_lights_per_render;
|
||||
|
||||
double time;
|
||||
|
||||
} state;
|
||||
|
||||
Item *items[MAX_RENDER_ITEMS];
|
||||
|
||||
TextureInfo default_texture_info;
|
||||
|
||||
bool using_directional_lights = false;
|
||||
RID default_canvas_texture;
|
||||
|
||||
|
|
@ -422,9 +612,22 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
Color debug_redraw_color;
|
||||
double debug_redraw_time = 1.0;
|
||||
|
||||
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size, bool p_texture_is_data = false); //recursive, so regular inline used instead.
|
||||
void _render_item(RenderingDevice::DrawListID p_draw_list, RID p_render_target, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants, bool &r_sdf_used, const Point2 &p_offset, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
// A structure to store cached render target information
|
||||
struct RenderTarget {
|
||||
// Current render target for the canvas.
|
||||
RID render_target;
|
||||
bool use_linear_colors = false;
|
||||
};
|
||||
|
||||
inline RID _get_pipeline_specialization_or_ubershader(CanvasShaderData *p_shader_data, PipelineKey &r_pipeline_key, PushConstant &r_push_constant, RID p_mesh_instance = RID(), void *p_surface = nullptr, uint32_t p_surface_index = 0, RID *r_vertex_array = nullptr);
|
||||
void _render_batch_items(RenderTarget p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool &r_sdf_used, bool p_to_backbuffer = false, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
void _record_item_commands(const Item *p_item, RenderTarget p_render_target, const Transform2D &p_base_transform, Item *&r_current_clip, Light *p_lights, uint32_t &r_index, bool &r_batch_broken, bool &r_sdf_used, Batch *&r_current_batch);
|
||||
void _render_batch(RD::DrawListID p_draw_list, CanvasShaderData *p_shader_data, RenderingDevice::FramebufferFormatID p_framebuffer_format, Light *p_lights, Batch const *p_batch, RenderingMethod::RenderInfo *r_render_info = nullptr);
|
||||
void _prepare_batch_texture_info(RID p_texture, TextureState &p_state, TextureInfo *p_info);
|
||||
InstanceData *new_instance_data(float *p_world, uint32_t *p_lights, uint32_t p_base_flags, uint32_t p_index, uint32_t p_uniforms_ofs, TextureInfo *p_info);
|
||||
[[nodiscard]] Batch *_new_batch(bool &r_batch_broken);
|
||||
void _add_to_batch(uint32_t &r_index, bool &r_batch_broken, Batch *&r_current_batch);
|
||||
void _allocate_instance_buffer();
|
||||
|
||||
_FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4);
|
||||
_FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3);
|
||||
|
|
@ -433,6 +636,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
|
|||
_FORCE_INLINE_ void _update_transform_to_mat4(const Transform3D &p_transform, float *p_mat4);
|
||||
|
||||
void _update_shadow_atlas();
|
||||
void _update_occluder_buffer(uint32_t p_size);
|
||||
|
||||
public:
|
||||
PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) override;
|
||||
|
|
@ -441,7 +645,7 @@ public:
|
|||
RID light_create() override;
|
||||
void light_set_texture(RID p_rid, RID p_texture) override;
|
||||
void light_set_use_shadow(RID p_rid, bool p_enable) override;
|
||||
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) override;
|
||||
void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders, const Rect2 &p_light_rect) override;
|
||||
void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) override;
|
||||
|
||||
virtual void render_sdf(RID p_render_target, LightOccluderInstance *p_occluders) override;
|
||||
|
|
@ -455,6 +659,7 @@ public:
|
|||
virtual void set_shadow_texture_size(int p_size) override;
|
||||
|
||||
void set_debug_redraw(bool p_enabled, double p_time, const Color &p_color) override;
|
||||
uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override;
|
||||
|
||||
void set_time(double p_time);
|
||||
void update() override;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
|
||||
#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h"
|
||||
#include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h"
|
||||
|
||||
void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
|
||||
Error err = RD::get_singleton()->screen_prepare_for_drawing(p_screen);
|
||||
if (err != OK) {
|
||||
|
|
@ -66,6 +69,16 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
|
|||
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0);
|
||||
|
||||
// We need to invert the phone rotation.
|
||||
const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(p_screen);
|
||||
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
|
||||
|
||||
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
|
||||
blit.push_constant.rotation_sin = Math::sin(screen_rotation);
|
||||
// Swap width and height when the orientation is not the native one.
|
||||
if (screen_rotation_degrees % 180 != 0) {
|
||||
SWAP(screen_size.width, screen_size.height);
|
||||
}
|
||||
blit.push_constant.src_rect[0] = p_render_targets[i].src_rect.position.x;
|
||||
blit.push_constant.src_rect[1] = p_render_targets[i].src_rect.position.y;
|
||||
blit.push_constant.src_rect[2] = p_render_targets[i].src_rect.size.width;
|
||||
|
|
@ -102,10 +115,8 @@ void RendererCompositorRD::begin_frame(double frame_step) {
|
|||
scene->set_time(time, frame_step);
|
||||
}
|
||||
|
||||
void RendererCompositorRD::end_frame(bool p_swap_buffers) {
|
||||
if (p_swap_buffers) {
|
||||
RD::get_singleton()->swap_buffers();
|
||||
}
|
||||
void RendererCompositorRD::end_frame(bool p_present) {
|
||||
RD::get_singleton()->swap_buffers(p_present);
|
||||
}
|
||||
|
||||
void RendererCompositorRD::initialize() {
|
||||
|
|
@ -123,6 +134,9 @@ void RendererCompositorRD::initialize() {
|
|||
|
||||
for (int i = 0; i < BLIT_MODE_MAX; i++) {
|
||||
blit.pipelines[i] = RD::get_singleton()->render_pipeline_create(blit.shader.version_get_shader(blit.shader_version, i), RD::get_singleton()->screen_get_framebuffer_format(DisplayServer::MAIN_WINDOW_ID), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), i == BLIT_MODE_NORMAL_ALPHA ? RenderingDevice::PipelineColorBlendState::create_blend() : RenderingDevice::PipelineColorBlendState::create_disabled(), 0);
|
||||
|
||||
// Unload shader modules to save memory.
|
||||
RD::get_singleton()->shader_destroy_modules(blit.shader.version_get_shader(blit.shader_version, i));
|
||||
}
|
||||
|
||||
//create index array for copy shader
|
||||
|
|
@ -202,18 +216,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());
|
||||
Rect2 screenrect;
|
||||
if (p_scale) {
|
||||
if (window_size.width > window_size.height) {
|
||||
//scale horizontally
|
||||
screenrect.size.y = window_size.height;
|
||||
screenrect.size.x = imgrect.size.x * window_size.height / imgrect.size.y;
|
||||
screenrect.position.x = (window_size.width - screenrect.size.x) / 2;
|
||||
|
||||
} else {
|
||||
//scale vertically
|
||||
screenrect.size.x = window_size.width;
|
||||
screenrect.size.y = imgrect.size.y * window_size.width / imgrect.size.x;
|
||||
screenrect.position.y = (window_size.height - screenrect.size.y) / 2;
|
||||
}
|
||||
screenrect = OS::get_singleton()->calculate_boot_screen_rect(window_size, imgrect.size);
|
||||
} else {
|
||||
screenrect = imgrect;
|
||||
screenrect.position += ((window_size - screenrect.size) / 2.0).floor();
|
||||
|
|
@ -228,6 +231,10 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
RD::get_singleton()->draw_list_bind_index_array(draw_list, blit.array);
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uset, 0);
|
||||
|
||||
const int screen_rotation_degrees = -RD::get_singleton()->screen_get_pre_rotation_degrees(DisplayServer::MAIN_WINDOW_ID);
|
||||
float screen_rotation = Math::deg_to_rad((float)screen_rotation_degrees);
|
||||
blit.push_constant.rotation_cos = Math::cos(screen_rotation);
|
||||
blit.push_constant.rotation_sin = Math::sin(screen_rotation);
|
||||
blit.push_constant.src_rect[0] = 0.0;
|
||||
blit.push_constant.src_rect[1] = 0.0;
|
||||
blit.push_constant.src_rect[2] = 1.0;
|
||||
|
|
@ -250,7 +257,7 @@ void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color
|
|||
|
||||
RD::get_singleton()->draw_list_end();
|
||||
|
||||
RD::get_singleton()->swap_buffers();
|
||||
RD::get_singleton()->swap_buffers(true);
|
||||
|
||||
texture_storage->texture_free(texture);
|
||||
RD::get_singleton()->free(sampler);
|
||||
|
|
|
|||
|
|
@ -31,13 +31,12 @@
|
|||
#ifndef RENDERER_COMPOSITOR_RD_H
|
||||
#define RENDERER_COMPOSITOR_RD_H
|
||||
|
||||
#include "core/os/os.h"
|
||||
#include "core/io/image.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#include "servers/rendering/renderer_rd/environment/fog.h"
|
||||
#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h"
|
||||
#include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h"
|
||||
#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
|
|
@ -73,6 +72,10 @@ protected:
|
|||
float src_rect[4];
|
||||
float dst_rect[4];
|
||||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
float pad[2];
|
||||
|
||||
float eye_center[2];
|
||||
float k1;
|
||||
float k2;
|
||||
|
|
@ -102,7 +105,7 @@ protected:
|
|||
static RendererCompositorRD *singleton;
|
||||
|
||||
public:
|
||||
RendererUtilities *get_utilities() { return utilities; };
|
||||
RendererUtilities *get_utilities() { return utilities; }
|
||||
RendererLightStorage *get_light_storage() { return light_storage; }
|
||||
RendererMaterialStorage *get_material_storage() { return material_storage; }
|
||||
RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
|
||||
|
|
@ -123,12 +126,13 @@ public:
|
|||
void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount);
|
||||
|
||||
void gl_end_frame(bool p_swap_buffers) {}
|
||||
void end_frame(bool p_swap_buffers);
|
||||
void end_frame(bool p_present);
|
||||
void finalize();
|
||||
|
||||
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
|
||||
_ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
|
||||
_ALWAYS_INLINE_ double get_total_time() const { return time; }
|
||||
_ALWAYS_INLINE_ bool can_create_resources_async() const { return true; }
|
||||
|
||||
static Error is_viable() {
|
||||
return OK;
|
||||
|
|
|
|||
|
|
@ -31,12 +31,15 @@
|
|||
#include "renderer_scene_render_rd.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/io/image.h"
|
||||
#include "renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/environment/fog.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/decal_data_inc.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/light_data_inc.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/scene_data_inc.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/shader_include_db.h"
|
||||
#include "servers/rendering/storage/camera_attributes_storage.h"
|
||||
|
||||
void get_vogel_disk(float *r_kernel, int p_sample_count) {
|
||||
|
|
@ -133,7 +136,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
|
|||
|
||||
if (use_cube_map) {
|
||||
Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy_multiplier(p_env), p_bake_irradiance, p_size);
|
||||
if (use_ambient_light) {
|
||||
if (use_ambient_light && panorama.is_valid()) {
|
||||
for (int x = 0; x < p_size.width; x++) {
|
||||
for (int y = 0; y < p_size.height; y++) {
|
||||
panorama->set_pixel(x, y, ambient_color.lerp(panorama->get_pixel(x, y), ambient_color_sky_mix));
|
||||
|
|
@ -426,8 +429,18 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
can_use_effects &= _debug_draw_can_use_effects(debug_draw);
|
||||
bool can_use_storage = _render_buffers_can_be_storage();
|
||||
|
||||
bool use_fsr = fsr && can_use_effects && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR;
|
||||
bool use_upscaled_texture = rb->has_upscaled_texture() && rb->get_scaling_3d_mode() == RS::VIEWPORT_SCALING_3D_MODE_FSR2;
|
||||
RS::ViewportScaling3DMode scale_mode = rb->get_scaling_3d_mode();
|
||||
bool use_upscaled_texture = rb->has_upscaled_texture() && (scale_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR2 || scale_mode == RS::VIEWPORT_SCALING_3D_MODE_METALFX_TEMPORAL);
|
||||
SpatialUpscaler *spatial_upscaler = nullptr;
|
||||
if (can_use_effects) {
|
||||
if (scale_mode == RS::VIEWPORT_SCALING_3D_MODE_FSR) {
|
||||
spatial_upscaler = fsr;
|
||||
} else if (scale_mode == RS::VIEWPORT_SCALING_3D_MODE_METALFX_SPATIAL) {
|
||||
#if METAL_ENABLED
|
||||
spatial_upscaler = mfx_spatial;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RID render_target = rb->get_render_target();
|
||||
RID color_texture = use_upscaled_texture ? rb->get_upscaled_texture() : rb->get_internal_texture();
|
||||
|
|
@ -641,11 +654,10 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
tonemap.convert_to_srgb = !texture_storage->render_target_is_using_hdr(render_target);
|
||||
|
||||
RID dest_fb;
|
||||
bool use_intermediate_fb = use_fsr;
|
||||
if (use_intermediate_fb) {
|
||||
// If we use FSR to upscale we need to write our result into an intermediate buffer.
|
||||
if (spatial_upscaler != nullptr) {
|
||||
// If we use a spatial upscaler to upscale we need to write our result into an intermediate buffer.
|
||||
// Note that this is cached so we only create the texture the first time.
|
||||
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT, RD::TEXTURE_SAMPLES_1, Size2i(), 0, 1, true, true);
|
||||
dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
|
||||
} else {
|
||||
// If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
|
||||
|
|
@ -665,14 +677,16 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
|
|||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
if (use_fsr) {
|
||||
RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
|
||||
if (rb.is_valid() && spatial_upscaler) {
|
||||
spatial_upscaler->ensure_context(rb);
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label(spatial_upscaler->get_label());
|
||||
|
||||
for (uint32_t v = 0; v < rb->get_view_count(); v++) {
|
||||
RID source_texture = rb->get_texture_slice(SNAME("Tonemapper"), SNAME("destination"), v, 0);
|
||||
RID dest_texture = texture_storage->render_target_get_rd_texture_slice(render_target, v);
|
||||
|
||||
fsr->fsr_upscale(rb, source_texture, dest_texture);
|
||||
spatial_upscaler->process(rb, source_texture, dest_texture);
|
||||
}
|
||||
|
||||
if (dest_is_msaa_2d) {
|
||||
|
|
@ -1040,6 +1054,14 @@ void RendererSceneRenderRD::light_projectors_set_filter(RenderingServer::LightPr
|
|||
_update_shader_quality_settings();
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::lightmaps_set_bicubic_filter(bool p_enable) {
|
||||
if (lightmap_filter_bicubic == p_enable) {
|
||||
return;
|
||||
}
|
||||
lightmap_filter_bicubic = p_enable;
|
||||
_update_shader_quality_settings();
|
||||
}
|
||||
|
||||
int RendererSceneRenderRD::get_roughness_layers() const {
|
||||
return sky.roughness_layers;
|
||||
}
|
||||
|
|
@ -1121,8 +1143,10 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
|
|||
scene_data.cam_transform = p_camera_data->main_transform;
|
||||
scene_data.cam_projection = p_camera_data->main_projection;
|
||||
scene_data.cam_orthogonal = p_camera_data->is_orthogonal;
|
||||
scene_data.cam_frustum = p_camera_data->is_frustum;
|
||||
scene_data.camera_visible_layers = p_camera_data->visible_layers;
|
||||
scene_data.taa_jitter = p_camera_data->taa_jitter;
|
||||
scene_data.taa_frame_count = p_camera_data->taa_frame_count;
|
||||
scene_data.main_cam_transform = p_camera_data->main_transform;
|
||||
scene_data.flip_y = !p_reflection_probe.is_valid();
|
||||
|
||||
|
|
@ -1204,6 +1228,7 @@ void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render
|
|||
|
||||
if (p_render_buffers.is_valid() && p_reflection_probe.is_null()) {
|
||||
render_data.transparent_bg = texture_storage->render_target_get_transparent(rb->get_render_target());
|
||||
render_data.render_region = texture_storage->render_target_get_render_region(rb->get_render_target());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1441,6 +1466,13 @@ void RendererSceneRenderRD::init() {
|
|||
/* Forward ID */
|
||||
forward_id_storage = create_forward_id_storage();
|
||||
|
||||
/* Register the include files we make available by default to our users */
|
||||
{
|
||||
ShaderIncludeDB::register_built_in_include_file("godot/decal_data_inc.glsl", decal_data_inc_shader_glsl);
|
||||
ShaderIncludeDB::register_built_in_include_file("godot/light_data_inc.glsl", light_data_inc_shader_glsl);
|
||||
ShaderIncludeDB::register_built_in_include_file("godot/scene_data_inc.glsl", scene_data_inc_shader_glsl);
|
||||
}
|
||||
|
||||
/* SKY SHADER */
|
||||
|
||||
sky.init();
|
||||
|
|
@ -1483,6 +1515,7 @@ void RendererSceneRenderRD::init() {
|
|||
|
||||
decals_set_filter(RS::DecalFilter(int(GLOBAL_GET("rendering/textures/decals/filter"))));
|
||||
light_projectors_set_filter(RS::LightProjectorFilter(int(GLOBAL_GET("rendering/textures/light_projectors/filter"))));
|
||||
lightmaps_set_bicubic_filter(GLOBAL_GET("rendering/lightmapping/lightmap_gi/use_bicubic_filter"));
|
||||
|
||||
cull_argument.set_page_pool(&cull_argument_pool);
|
||||
|
||||
|
|
@ -1499,6 +1532,9 @@ void RendererSceneRenderRD::init() {
|
|||
if (can_use_storage) {
|
||||
fsr = memnew(RendererRD::FSR);
|
||||
}
|
||||
#ifdef METAL_ENABLED
|
||||
mfx_spatial = memnew(RendererRD::MFXSpatialEffect);
|
||||
#endif
|
||||
}
|
||||
|
||||
RendererSceneRenderRD::~RendererSceneRenderRD() {
|
||||
|
|
@ -1527,6 +1563,11 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
|
|||
if (fsr) {
|
||||
memdelete(fsr);
|
||||
}
|
||||
#ifdef METAL_ENABLED
|
||||
if (mfx_spatial) {
|
||||
memdelete(mfx_spatial);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) {
|
||||
RD::get_singleton()->free(sky.sky_scene_state.uniform_set);
|
||||
|
|
|
|||
|
|
@ -31,25 +31,22 @@
|
|||
#ifndef RENDERER_SCENE_RENDER_RD_H
|
||||
#define RENDERER_SCENE_RENDER_RD_H
|
||||
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/rendering/renderer_compositor.h"
|
||||
#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/debug_effects.h"
|
||||
#include "servers/rendering/renderer_rd/effects/fsr.h"
|
||||
#include "servers/rendering/renderer_rd/effects/luminance.h"
|
||||
#ifdef METAL_ENABLED
|
||||
#include "servers/rendering/renderer_rd/effects/metal_fx.h"
|
||||
#endif
|
||||
#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/light_storage.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_data_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h"
|
||||
#include "servers/rendering/renderer_scene_render.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "servers/rendering/rendering_method.h"
|
||||
|
|
@ -67,6 +64,9 @@ protected:
|
|||
RendererRD::ToneMapper *tone_mapper = nullptr;
|
||||
RendererRD::FSR *fsr = nullptr;
|
||||
RendererRD::VRS *vrs = nullptr;
|
||||
#ifdef METAL_ENABLED
|
||||
RendererRD::MFXSpatialEffect *mfx_spatial = nullptr;
|
||||
#endif
|
||||
double time = 0.0;
|
||||
double time_step = 0.0;
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ protected:
|
|||
|
||||
////////////////////////////////
|
||||
|
||||
virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); };
|
||||
virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); }
|
||||
|
||||
void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers);
|
||||
|
||||
|
|
@ -133,6 +133,7 @@ private:
|
|||
float *directional_soft_shadow_kernel = nullptr;
|
||||
float *penumbra_shadow_kernel = nullptr;
|
||||
float *soft_shadow_kernel = nullptr;
|
||||
bool lightmap_filter_bicubic = false;
|
||||
int directional_penumbra_shadow_samples = 0;
|
||||
int directional_soft_shadow_samples = 0;
|
||||
int penumbra_shadow_samples = 0;
|
||||
|
|
@ -164,9 +165,9 @@ public:
|
|||
|
||||
/* LIGHTING */
|
||||
|
||||
virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size){};
|
||||
virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){};
|
||||
virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size){};
|
||||
virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_size) {}
|
||||
virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {}
|
||||
virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) {}
|
||||
|
||||
/* GI */
|
||||
|
||||
|
|
@ -262,6 +263,7 @@ public:
|
|||
|
||||
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
|
||||
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
|
||||
virtual void lightmaps_set_bicubic_filter(bool p_enable) override;
|
||||
|
||||
_FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const {
|
||||
return shadows_quality;
|
||||
|
|
@ -292,6 +294,9 @@ public:
|
|||
_FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const {
|
||||
return directional_penumbra_shadow_samples;
|
||||
}
|
||||
_FORCE_INLINE_ bool lightmap_filter_bicubic_get() const {
|
||||
return lightmap_filter_bicubic;
|
||||
}
|
||||
_FORCE_INLINE_ int directional_soft_shadow_samples_get() const {
|
||||
return directional_soft_shadow_samples;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,21 +30,22 @@
|
|||
|
||||
#include "shader_rd.h"
|
||||
|
||||
#include "core/io/compression.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/object/worker_thread_pool.h"
|
||||
#include "core/version.h"
|
||||
#include "renderer_compositor_rd.h"
|
||||
#include "servers/rendering/rendering_device.h"
|
||||
#include "thirdparty/misc/smolv.h"
|
||||
#include "servers/rendering/shader_include_db.h"
|
||||
|
||||
#define ENABLE_SHADER_CACHE 1
|
||||
|
||||
void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
|
||||
Vector<String> lines = String(p_code).split("\n");
|
||||
|
||||
String text;
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
int line_count = lines.size();
|
||||
for (int i = 0; i < line_count; i++) {
|
||||
const String &l = lines[i];
|
||||
bool push_chunk = false;
|
||||
|
||||
|
|
@ -76,6 +77,35 @@ void ShaderRD::_add_stage(const char *p_code, StageType p_stage_type) {
|
|||
chunk.type = StageTemplate::Chunk::TYPE_CODE;
|
||||
push_chunk = true;
|
||||
chunk.code = l.replace_first("#CODE", String()).replace(":", "").strip_edges().to_upper();
|
||||
} else if (l.begins_with("#include ")) {
|
||||
String include_file = l.replace("#include ", "").strip_edges();
|
||||
if (include_file[0] == '"') {
|
||||
int end_pos = include_file.find_char('"', 1);
|
||||
if (end_pos >= 0) {
|
||||
include_file = include_file.substr(1, end_pos - 1);
|
||||
|
||||
String include_code = ShaderIncludeDB::get_built_in_include_file(include_file);
|
||||
if (!include_code.is_empty()) {
|
||||
// Add these lines into our parse list so we parse them as well.
|
||||
Vector<String> include_lines = include_code.split("\n");
|
||||
|
||||
for (int j = include_lines.size() - 1; j >= 0; j--) {
|
||||
lines.insert(i + 1, include_lines[j]);
|
||||
}
|
||||
|
||||
line_count = lines.size();
|
||||
} else {
|
||||
// Add it in as is.
|
||||
text += l + "\n";
|
||||
}
|
||||
} else {
|
||||
// Add it in as is.
|
||||
text += l + "\n";
|
||||
}
|
||||
} else {
|
||||
// Add it in as is.
|
||||
text += l + "\n";
|
||||
}
|
||||
} else {
|
||||
text += l + "\n";
|
||||
}
|
||||
|
|
@ -144,7 +174,8 @@ RID ShaderRD::version_create() {
|
|||
version.dirty = true;
|
||||
version.valid = false;
|
||||
version.initialize_needed = true;
|
||||
version.variants = nullptr;
|
||||
version.variants.clear();
|
||||
version.variant_data.clear();
|
||||
return version_owner.make_rid(version);
|
||||
}
|
||||
|
||||
|
|
@ -154,23 +185,25 @@ void ShaderRD::_initialize_version(Version *p_version) {
|
|||
p_version->valid = false;
|
||||
p_version->dirty = false;
|
||||
|
||||
p_version->variants = memnew_arr(RID, variant_defines.size());
|
||||
p_version->variants.resize_zeroed(variant_defines.size());
|
||||
p_version->variant_data.resize(variant_defines.size());
|
||||
p_version->group_compilation_tasks.resize(group_enabled.size());
|
||||
p_version->group_compilation_tasks.fill(0);
|
||||
}
|
||||
|
||||
void ShaderRD::_clear_version(Version *p_version) {
|
||||
_compile_ensure_finished(p_version);
|
||||
|
||||
// Clear versions if they exist.
|
||||
if (p_version->variants) {
|
||||
if (!p_version->variants.is_empty()) {
|
||||
for (int i = 0; i < variant_defines.size(); i++) {
|
||||
if (p_version->variants[i].is_valid()) {
|
||||
RD::get_singleton()->free(p_version->variants[i]);
|
||||
}
|
||||
}
|
||||
|
||||
memdelete_arr(p_version->variants);
|
||||
if (p_version->variant_data) {
|
||||
memdelete_arr(p_version->variant_data);
|
||||
}
|
||||
p_version->variants = nullptr;
|
||||
p_version->variants.clear();
|
||||
p_version->variant_data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,10 +224,17 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
|
|||
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
|
||||
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
|
||||
}
|
||||
#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
|
||||
builder.append("#define MOLTENVK_USED\n");
|
||||
#if (defined(MACOS_ENABLED) || defined(IOS_ENABLED))
|
||||
if (RD::get_singleton()->get_device_capabilities().device_family == RDD::DEVICE_VULKAN) {
|
||||
builder.append("#define MOLTENVK_USED\n");
|
||||
}
|
||||
// Image atomics are supported on Metal 3.1 but no support in MoltenVK or SPIRV-Cross yet.
|
||||
builder.append("#define NO_IMAGE_ATOMICS\n");
|
||||
#endif
|
||||
|
||||
builder.append(String("#define RENDER_DRIVER_") + OS::get_singleton()->get_current_rendering_driver_name().to_upper() + "\n");
|
||||
builder.append("#define samplerExternalOES sampler2D\n");
|
||||
builder.append("#define textureExternalOES texture2D\n");
|
||||
} break;
|
||||
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
|
||||
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
|
||||
|
|
@ -220,8 +260,8 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
|
|||
}
|
||||
}
|
||||
|
||||
void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
|
||||
uint32_t variant = group_to_variant_map[p_data->group][p_variant];
|
||||
void ShaderRD::_compile_variant(uint32_t p_variant, CompileData p_data) {
|
||||
uint32_t variant = group_to_variant_map[p_data.group][p_variant];
|
||||
|
||||
if (!variants_enabled[variant]) {
|
||||
return; // Variant is disabled, return.
|
||||
|
|
@ -238,7 +278,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
|
|||
//vertex stage
|
||||
|
||||
StringBuilder builder;
|
||||
_build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_VERTEX]);
|
||||
_build_variant_code(builder, variant, p_data.version, stage_templates[STAGE_TYPE_VERTEX]);
|
||||
|
||||
current_source = builder.as_string();
|
||||
RD::ShaderStageSPIRVData stage;
|
||||
|
|
@ -256,7 +296,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
|
|||
current_stage = RD::SHADER_STAGE_FRAGMENT;
|
||||
|
||||
StringBuilder builder;
|
||||
_build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_FRAGMENT]);
|
||||
_build_variant_code(builder, variant, p_data.version, stage_templates[STAGE_TYPE_FRAGMENT]);
|
||||
|
||||
current_source = builder.as_string();
|
||||
RD::ShaderStageSPIRVData stage;
|
||||
|
|
@ -274,7 +314,7 @@ void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
|
|||
current_stage = RD::SHADER_STAGE_COMPUTE;
|
||||
|
||||
StringBuilder builder;
|
||||
_build_variant_code(builder, variant, p_data->version, stage_templates[STAGE_TYPE_COMPUTE]);
|
||||
_build_variant_code(builder, variant, p_data.version, stage_templates[STAGE_TYPE_COMPUTE]);
|
||||
|
||||
current_source = builder.as_string();
|
||||
|
||||
|
|
@ -306,8 +346,8 @@ void ShaderRD::_compile_variant(uint32_t p_variant, const CompileData *p_data) {
|
|||
{
|
||||
MutexLock lock(variant_set_mutex);
|
||||
|
||||
p_data->version->variants[variant] = RD::get_singleton()->shader_create_from_bytecode(shader_data, p_data->version->variants[variant]);
|
||||
p_data->version->variant_data[variant] = shader_data;
|
||||
p_data.version->variants.write[variant] = RD::get_singleton()->shader_create_from_bytecode_with_samplers(shader_data, p_data.version->variants[variant], immutable_samplers);
|
||||
p_data.version->variant_data.write[variant] = shader_data;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -436,19 +476,19 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) {
|
|||
|
||||
ERR_FAIL_COND_V(br != variant_size, false);
|
||||
|
||||
p_version->variant_data[variant_id] = variant_bytes;
|
||||
p_version->variant_data.write[variant_id] = variant_bytes;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < variant_count; i++) {
|
||||
int variant_id = group_to_variant_map[p_group][i];
|
||||
if (!variants_enabled[variant_id]) {
|
||||
MutexLock lock(variant_set_mutex);
|
||||
p_version->variants[variant_id] = RID();
|
||||
p_version->variants.write[variant_id] = RID();
|
||||
continue;
|
||||
}
|
||||
{
|
||||
MutexLock lock(variant_set_mutex);
|
||||
RID shader = RD::get_singleton()->shader_create_from_bytecode(p_version->variant_data[variant_id], p_version->variants[variant_id]);
|
||||
RID shader = RD::get_singleton()->shader_create_from_bytecode_with_samplers(p_version->variant_data[variant_id], p_version->variants[variant_id], immutable_samplers);
|
||||
if (shader.is_null()) {
|
||||
for (uint32_t j = 0; j < i; j++) {
|
||||
int variant_free_id = group_to_variant_map[p_group][j];
|
||||
|
|
@ -457,12 +497,10 @@ bool ShaderRD::_load_from_cache(Version *p_version, int p_group) {
|
|||
ERR_FAIL_COND_V(shader.is_null(), false);
|
||||
}
|
||||
|
||||
p_version->variants[variant_id] = shader;
|
||||
p_version->variants.write[variant_id] = shader;
|
||||
}
|
||||
}
|
||||
|
||||
memdelete_arr(p_version->variant_data); //clear stages
|
||||
p_version->variant_data = nullptr;
|
||||
p_version->valid = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -484,48 +522,51 @@ void ShaderRD::_save_to_cache(Version *p_version, int p_group) {
|
|||
}
|
||||
|
||||
void ShaderRD::_allocate_placeholders(Version *p_version, int p_group) {
|
||||
ERR_FAIL_NULL(p_version->variants);
|
||||
ERR_FAIL_COND(p_version->variants.is_empty());
|
||||
|
||||
for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
|
||||
int variant_id = group_to_variant_map[p_group][i];
|
||||
RID shader = RD::get_singleton()->shader_create_placeholder();
|
||||
{
|
||||
MutexLock lock(variant_set_mutex);
|
||||
p_version->variants[variant_id] = shader;
|
||||
p_version->variants.write[variant_id] = shader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to compile all variants for a given group.
|
||||
// Will skip variants that are disabled.
|
||||
void ShaderRD::_compile_version(Version *p_version, int p_group) {
|
||||
void ShaderRD::_compile_version_start(Version *p_version, int p_group) {
|
||||
if (!group_enabled[p_group]) {
|
||||
return;
|
||||
}
|
||||
|
||||
typedef Vector<uint8_t> ShaderStageData;
|
||||
p_version->variant_data = memnew_arr(ShaderStageData, variant_defines.size());
|
||||
|
||||
p_version->dirty = false;
|
||||
|
||||
#if ENABLE_SHADER_CACHE
|
||||
if (shader_cache_dir_valid) {
|
||||
if (_load_from_cache(p_version, p_group)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
CompileData compile_data;
|
||||
compile_data.version = p_version;
|
||||
compile_data.group = p_group;
|
||||
|
||||
#if 1
|
||||
WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, &compile_data, group_to_variant_map[p_group].size(), -1, true, SNAME("ShaderCompilation"));
|
||||
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
|
||||
WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, compile_data, group_to_variant_map[p_group].size(), -1, true, SNAME("ShaderCompilation"));
|
||||
p_version->group_compilation_tasks.write[p_group] = group_task;
|
||||
}
|
||||
|
||||
#else
|
||||
for (uint32_t i = 0; i < group_to_variant_map[p_group].size(); i++) {
|
||||
_compile_variant(i, &compile_data);
|
||||
void ShaderRD::_compile_version_end(Version *p_version, int p_group) {
|
||||
if (p_version->group_compilation_tasks.size() <= p_group || p_version->group_compilation_tasks[p_group] == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
WorkerThreadPool::GroupID group_task = p_version->group_compilation_tasks[p_group];
|
||||
WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
|
||||
p_version->group_compilation_tasks.write[p_group] = 0;
|
||||
|
||||
bool all_valid = true;
|
||||
|
||||
|
|
@ -550,29 +591,35 @@ void ShaderRD::_compile_version(Version *p_version, int p_group) {
|
|||
RD::get_singleton()->free(p_version->variants[i]);
|
||||
}
|
||||
}
|
||||
memdelete_arr(p_version->variants);
|
||||
if (p_version->variant_data) {
|
||||
memdelete_arr(p_version->variant_data);
|
||||
}
|
||||
p_version->variants = nullptr;
|
||||
p_version->variant_data = nullptr;
|
||||
|
||||
p_version->variants.clear();
|
||||
p_version->variant_data.clear();
|
||||
return;
|
||||
} else if (shader_cache_dir_valid) {
|
||||
// Save shader cache.
|
||||
}
|
||||
#if ENABLE_SHADER_CACHE
|
||||
else if (shader_cache_dir_valid) {
|
||||
_save_to_cache(p_version, p_group);
|
||||
}
|
||||
|
||||
memdelete_arr(p_version->variant_data); //clear stages
|
||||
p_version->variant_data = nullptr;
|
||||
#endif
|
||||
|
||||
p_version->valid = true;
|
||||
}
|
||||
|
||||
void ShaderRD::_compile_ensure_finished(Version *p_version) {
|
||||
// Wait for compilation of existing groups if necessary.
|
||||
for (int i = 0; i < group_enabled.size(); i++) {
|
||||
_compile_version_end(p_version, i);
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) {
|
||||
ERR_FAIL_COND(is_compute);
|
||||
|
||||
Version *version = version_owner.get_or_null(p_version);
|
||||
ERR_FAIL_NULL(version);
|
||||
|
||||
_compile_ensure_finished(version);
|
||||
|
||||
version->vertex_globals = p_vertex_globals.utf8();
|
||||
version->fragment_globals = p_fragment_globals.utf8();
|
||||
version->uniforms = p_uniforms.utf8();
|
||||
|
|
@ -594,7 +641,7 @@ void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_
|
|||
_allocate_placeholders(version, i);
|
||||
continue;
|
||||
}
|
||||
_compile_version(version, i);
|
||||
_compile_version_start(version, i);
|
||||
}
|
||||
version->initialize_needed = false;
|
||||
}
|
||||
|
|
@ -606,6 +653,8 @@ void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, Str
|
|||
Version *version = version_owner.get_or_null(p_version);
|
||||
ERR_FAIL_NULL(version);
|
||||
|
||||
_compile_ensure_finished(version);
|
||||
|
||||
version->compute_globals = p_compute_globals.utf8();
|
||||
version->uniforms = p_uniforms.utf8();
|
||||
|
||||
|
|
@ -627,7 +676,7 @@ void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, Str
|
|||
_allocate_placeholders(version, i);
|
||||
continue;
|
||||
}
|
||||
_compile_version(version, i);
|
||||
_compile_version_start(version, i);
|
||||
}
|
||||
version->initialize_needed = false;
|
||||
}
|
||||
|
|
@ -644,10 +693,12 @@ bool ShaderRD::version_is_valid(RID p_version) {
|
|||
_allocate_placeholders(version, i);
|
||||
continue;
|
||||
}
|
||||
_compile_version(version, i);
|
||||
_compile_version_start(version, i);
|
||||
}
|
||||
}
|
||||
|
||||
_compile_ensure_finished(version);
|
||||
|
||||
return version->valid;
|
||||
}
|
||||
|
||||
|
|
@ -689,7 +740,7 @@ void ShaderRD::enable_group(int p_group) {
|
|||
version_owner.get_owned_list(&all_versions);
|
||||
for (const RID &E : all_versions) {
|
||||
Version *version = version_owner.get_or_null(E);
|
||||
_compile_version(version, p_group);
|
||||
_compile_version_start(version, p_group);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -715,7 +766,8 @@ ShaderRD::ShaderRD() {
|
|||
base_compute_defines = base_compute_define_text.ascii();
|
||||
}
|
||||
|
||||
void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines) {
|
||||
void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines, const Vector<RD::PipelineImmutableSampler> &r_immutable_samplers) {
|
||||
immutable_samplers = r_immutable_samplers;
|
||||
ERR_FAIL_COND(variant_defines.size());
|
||||
ERR_FAIL_COND(p_variant_defines.is_empty());
|
||||
|
||||
|
|
@ -728,6 +780,7 @@ void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String
|
|||
for (int i = 0; i < p_variant_defines.size(); i++) {
|
||||
variant_defines.push_back(VariantDefine(0, p_variant_defines[i], true));
|
||||
variants_enabled.push_back(true);
|
||||
variant_to_group.push_back(0);
|
||||
group_to_variant_map[0].push_back(i);
|
||||
}
|
||||
|
||||
|
|
@ -789,6 +842,7 @@ void ShaderRD::initialize(const Vector<VariantDefine> &p_variant_defines, const
|
|||
// Fill variant array.
|
||||
variant_defines.push_back(p_variant_defines[i]);
|
||||
variants_enabled.push_back(true);
|
||||
variant_to_group.push_back(p_variant_defines[i].group);
|
||||
|
||||
// Map variant array index to group id, so we can iterate over groups later.
|
||||
if (!group_to_variant_map.has(p_variant_defines[i].group)) {
|
||||
|
|
|
|||
|
|
@ -35,9 +35,7 @@
|
|||
#include "core/string/string_builder.h"
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rb_map.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "servers/rendering_server.h"
|
||||
|
||||
class ShaderRD {
|
||||
|
|
@ -46,7 +44,7 @@ public:
|
|||
int group = 0;
|
||||
CharString text;
|
||||
bool default_enabled = true;
|
||||
VariantDefine(){};
|
||||
VariantDefine() {}
|
||||
VariantDefine(int p_group, const String &p_text, bool p_default_enabled) {
|
||||
group = p_group;
|
||||
default_enabled = p_default_enabled;
|
||||
|
|
@ -59,9 +57,12 @@ private:
|
|||
CharString general_defines;
|
||||
Vector<VariantDefine> variant_defines;
|
||||
Vector<bool> variants_enabled;
|
||||
Vector<uint32_t> variant_to_group;
|
||||
HashMap<int, LocalVector<int>> group_to_variant_map;
|
||||
Vector<bool> group_enabled;
|
||||
|
||||
Vector<RD::PipelineImmutableSampler> immutable_samplers;
|
||||
|
||||
struct Version {
|
||||
CharString uniforms;
|
||||
CharString vertex_globals;
|
||||
|
|
@ -69,9 +70,10 @@ private:
|
|||
CharString fragment_globals;
|
||||
HashMap<StringName, CharString> code_sections;
|
||||
Vector<CharString> custom_defines;
|
||||
Vector<WorkerThreadPool::GroupID> group_compilation_tasks;
|
||||
|
||||
Vector<uint8_t> *variant_data = nullptr;
|
||||
RID *variants = nullptr; // Same size as variant defines.
|
||||
Vector<Vector<uint8_t>> variant_data;
|
||||
Vector<RID> variants;
|
||||
|
||||
bool valid;
|
||||
bool dirty;
|
||||
|
|
@ -85,11 +87,13 @@ private:
|
|||
int group = 0;
|
||||
};
|
||||
|
||||
void _compile_variant(uint32_t p_variant, const CompileData *p_data);
|
||||
void _compile_variant(uint32_t p_variant, CompileData p_data);
|
||||
|
||||
void _initialize_version(Version *p_version);
|
||||
void _clear_version(Version *p_version);
|
||||
void _compile_version(Version *p_version, int p_group);
|
||||
void _compile_version_start(Version *p_version, int p_group);
|
||||
void _compile_version_end(Version *p_version, int p_group);
|
||||
void _compile_ensure_finished(Version *p_version);
|
||||
void _allocate_placeholders(Version *p_version, int p_group);
|
||||
|
||||
RID_Owner<Version> version_owner;
|
||||
|
|
@ -172,10 +176,15 @@ public:
|
|||
_allocate_placeholders(version, i);
|
||||
continue;
|
||||
}
|
||||
_compile_version(version, i);
|
||||
_compile_version_start(version, i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t group = variant_to_group[p_variant];
|
||||
if (version->group_compilation_tasks[group] != 0) {
|
||||
_compile_version_end(version, group);
|
||||
}
|
||||
|
||||
if (!version->valid) {
|
||||
return RID();
|
||||
}
|
||||
|
|
@ -202,7 +211,7 @@ public:
|
|||
|
||||
RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
|
||||
|
||||
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
|
||||
void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "", const Vector<RD::PipelineImmutableSampler> &r_immutable_samplers = Vector<RD::PipelineImmutableSampler>());
|
||||
void initialize(const Vector<VariantDefine> &p_variant_defines, const String &p_general_defines = "");
|
||||
|
||||
virtual ~ShaderRD();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
if "RD_GLSL" in env["BUILDERS"]:
|
||||
# find all include files
|
||||
# find just the include files
|
||||
gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
|
||||
|
||||
# find all shader code(all glsl files excluding our include files)
|
||||
# find all shader code (all glsl files excluding our include files)
|
||||
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
|
||||
|
||||
# make sure we recompile shaders if include files change
|
||||
env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
|
||||
|
||||
# compile shaders
|
||||
# compile include files
|
||||
for glsl_file in gl_include_files:
|
||||
env.GLSL_HEADER(glsl_file)
|
||||
|
||||
# compile RD shader
|
||||
for glsl_file in glsl_files:
|
||||
env.RD_GLSL(glsl_file)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ layout(push_constant, std140) uniform Pos {
|
|||
vec4 src_rect;
|
||||
vec4 dst_rect;
|
||||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
vec2 pad;
|
||||
|
||||
vec2 eye_center;
|
||||
float k1;
|
||||
float k2;
|
||||
|
|
@ -15,17 +19,23 @@ layout(push_constant, std140) uniform Pos {
|
|||
float upscale;
|
||||
float aspect_ratio;
|
||||
uint layer;
|
||||
uint pad1;
|
||||
bool convert_to_srgb;
|
||||
}
|
||||
data;
|
||||
|
||||
layout(location = 0) out vec2 uv;
|
||||
|
||||
void main() {
|
||||
mat4 swapchain_transform = mat4(1.0);
|
||||
swapchain_transform[0][0] = data.rotation_cos;
|
||||
swapchain_transform[0][1] = -data.rotation_sin;
|
||||
swapchain_transform[1][0] = data.rotation_sin;
|
||||
swapchain_transform[1][1] = data.rotation_cos;
|
||||
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv = data.src_rect.xy + base_arr[gl_VertexIndex] * data.src_rect.zw;
|
||||
vec2 vtx = data.dst_rect.xy + base_arr[gl_VertexIndex] * data.dst_rect.zw;
|
||||
gl_Position = vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
|
||||
gl_Position = swapchain_transform * vec4(vtx * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
|
@ -38,6 +48,10 @@ layout(push_constant, std140) uniform Pos {
|
|||
vec4 src_rect;
|
||||
vec4 dst_rect;
|
||||
|
||||
float rotation_sin;
|
||||
float rotation_cos;
|
||||
vec2 pad;
|
||||
|
||||
vec2 eye_center;
|
||||
float k1;
|
||||
float k2;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@ layout(location = 11) in vec4 weight_attrib;
|
|||
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
#ifndef USE_ATTRIBUTES
|
||||
|
||||
layout(location = 4) out flat uint instance_index_interp;
|
||||
|
||||
#endif // !USE_ATTRIBUTES
|
||||
|
||||
layout(location = 0) out vec2 uv_interp;
|
||||
layout(location = 1) out vec4 color_interp;
|
||||
layout(location = 2) out vec2 vertex_interp;
|
||||
|
|
@ -35,11 +41,11 @@ layout(location = 3) out vec2 pixel_size_interp;
|
|||
#endif
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
||||
|
||||
/* clang-format off */
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
} material;
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
|
@ -59,6 +65,14 @@ void main() {
|
|||
vec4 custom1 = vec4(0.0);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
uint instance_index = params.base_instance_index;
|
||||
#else
|
||||
uint instance_index = gl_InstanceIndex + params.base_instance_index;
|
||||
instance_index_interp = instance_index;
|
||||
#endif // USE_ATTRIBUTES
|
||||
const InstanceData draw_data = instances.data[instance_index];
|
||||
|
||||
#ifdef USE_PRIMITIVE
|
||||
|
||||
//weird bug,
|
||||
|
|
@ -87,7 +101,7 @@ void main() {
|
|||
|
||||
vec2 vertex = vertex_attrib;
|
||||
vec4 color = color_attrib;
|
||||
if (bool(draw_data.flags & FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) {
|
||||
if (bool(canvas_data.flags & CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR)) {
|
||||
color.rgb = srgb_to_linear(color.rgb);
|
||||
}
|
||||
color *= draw_data.modulation;
|
||||
|
|
@ -108,7 +122,7 @@ void main() {
|
|||
vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
vec2 vertex_base = vertex_base_arr[gl_VertexIndex];
|
||||
|
||||
vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy);
|
||||
vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy);
|
||||
vec4 color = draw_data.modulation;
|
||||
vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0)));
|
||||
uvec4 bones = uvec4(0, 0, 0, 0);
|
||||
|
|
@ -117,13 +131,10 @@ void main() {
|
|||
|
||||
mat4 model_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0));
|
||||
|
||||
#define FLAGS_INSTANCING_MASK 0x7F
|
||||
#define FLAGS_INSTANCING_HAS_COLORS (1 << 7)
|
||||
#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 8)
|
||||
|
||||
uint instancing = draw_data.flags & FLAGS_INSTANCING_MASK;
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
|
||||
uint instancing = params.batch_flags & BATCH_FLAGS_INSTANCING_MASK;
|
||||
|
||||
if (instancing > 1) {
|
||||
// trails
|
||||
|
||||
|
|
@ -160,42 +171,29 @@ void main() {
|
|||
|
||||
vertex = new_vertex;
|
||||
color *= pcolor;
|
||||
} else
|
||||
#endif // USE_ATTRIBUTES
|
||||
{
|
||||
if (instancing == 1) {
|
||||
uint stride = 2;
|
||||
{
|
||||
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
stride += 1;
|
||||
}
|
||||
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
stride += 1;
|
||||
}
|
||||
}
|
||||
} else if (instancing == 1) {
|
||||
uint stride = 2 + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT, 1) + bitfieldExtract(params.batch_flags, BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT, 1);
|
||||
|
||||
uint offset = stride * gl_InstanceIndex;
|
||||
uint offset = stride * gl_InstanceIndex;
|
||||
|
||||
mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
offset += 2;
|
||||
mat4 matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
offset += 2;
|
||||
|
||||
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
color *= transforms.data[offset];
|
||||
offset += 1;
|
||||
}
|
||||
|
||||
if (bool(draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
instance_custom = transforms.data[offset];
|
||||
}
|
||||
|
||||
matrix = transpose(matrix);
|
||||
model_matrix = model_matrix * matrix;
|
||||
if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_COLORS)) {
|
||||
color *= transforms.data[offset];
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_POINT_SIZE
|
||||
if (bool(params.batch_flags & BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA)) {
|
||||
instance_custom = transforms.data[offset];
|
||||
}
|
||||
|
||||
matrix = transpose(matrix);
|
||||
model_matrix = model_matrix * matrix;
|
||||
}
|
||||
#endif // USE_ATTRIBUTES
|
||||
|
||||
float point_size = 1.0;
|
||||
#endif
|
||||
|
||||
#ifdef USE_WORLD_VERTEX_COORDS
|
||||
vertex = (model_matrix * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
|
@ -214,6 +212,8 @@ void main() {
|
|||
|
||||
color_interp = color;
|
||||
|
||||
vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
if (canvas_data.use_pixel_snap) {
|
||||
vertex = floor(vertex + 0.5);
|
||||
// precision issue on some hardware creates artifacts within texture
|
||||
|
|
@ -221,8 +221,6 @@ void main() {
|
|||
uv += 1e-5;
|
||||
}
|
||||
|
||||
vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy;
|
||||
|
||||
vertex_interp = vertex;
|
||||
uv_interp = uv;
|
||||
|
||||
|
|
@ -241,6 +239,10 @@ void main() {
|
|||
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
|
||||
#ifndef USE_ATTRIBUTES
|
||||
layout(location = 4) in flat uint instance_index;
|
||||
#endif // USE_ATTRIBUTES
|
||||
|
||||
layout(location = 0) in vec2 uv_interp;
|
||||
layout(location = 1) in vec4 color_interp;
|
||||
layout(location = 2) in vec2 vertex_interp;
|
||||
|
|
@ -254,11 +256,11 @@ layout(location = 3) in vec2 pixel_size_interp;
|
|||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
||||
|
||||
/* clang-format off */
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
} material;
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
vec2 screen_uv_to_sdf(vec2 p_uv) {
|
||||
|
|
@ -320,6 +322,8 @@ vec4 light_compute(
|
|||
#ifdef USE_NINEPATCH
|
||||
|
||||
float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) {
|
||||
const InstanceData draw_data = instances.data[instance_index];
|
||||
|
||||
float tex_size = 1.0 / tex_pixel_size;
|
||||
|
||||
if (pixel < margin_begin) {
|
||||
|
|
@ -327,9 +331,7 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
|
|||
} else if (pixel >= draw_size - margin_end) {
|
||||
return (tex_size - (draw_size - pixel)) * tex_pixel_size;
|
||||
} else {
|
||||
if (!bool(draw_data.flags & FLAGS_NINEPACH_DRAW_CENTER)) {
|
||||
draw_center--;
|
||||
}
|
||||
draw_center -= 1 - int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT, 1));
|
||||
|
||||
// np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum.
|
||||
if (np_repeat == 0) { // Stretch.
|
||||
|
|
@ -360,8 +362,6 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 light_color, vec4 specular_shininess, bool specular_shininess_used) {
|
||||
float cNdotL = max(0.0, dot(normal, light_vec));
|
||||
|
||||
|
|
@ -451,8 +451,6 @@ void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) {
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
float msdf_median(float r, float g, float b, float a) {
|
||||
return min(max(min(r, g), min(max(r, g), b)), a);
|
||||
}
|
||||
|
|
@ -462,14 +460,20 @@ void main() {
|
|||
vec2 uv = uv_interp;
|
||||
vec2 vertex = vertex_interp;
|
||||
|
||||
#ifdef USE_ATTRIBUTES
|
||||
const InstanceData draw_data = instances.data[params.base_instance_index];
|
||||
#else
|
||||
const InstanceData draw_data = instances.data[instance_index];
|
||||
#endif // USE_ATTRIBUTES
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
|
||||
#ifdef USE_NINEPATCH
|
||||
|
||||
int draw_center = 2;
|
||||
uv = vec2(
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(draw_data.flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(draw_data.flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center));
|
||||
map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT, 2)), draw_center),
|
||||
map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(bitfieldExtract(draw_data.flags, INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT, 2)), draw_center));
|
||||
|
||||
if (draw_center == 0) {
|
||||
color.a = 0.0;
|
||||
|
|
@ -478,14 +482,15 @@ void main() {
|
|||
uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed
|
||||
|
||||
#endif
|
||||
if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) {
|
||||
uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw));
|
||||
if (bool(draw_data.flags & INSTANCE_FLAGS_CLIP_RECT_UV)) {
|
||||
vec2 half_texpixel = draw_data.color_texture_pixel_size * 0.5;
|
||||
uv = clamp(uv, draw_data.src_rect.xy + half_texpixel, draw_data.src_rect.xy + abs(draw_data.src_rect.zw) - half_texpixel);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef USE_PRIMITIVE
|
||||
if (bool(draw_data.flags & FLAGS_USE_MSDF)) {
|
||||
if (bool(draw_data.flags & INSTANCE_FLAGS_USE_MSDF)) {
|
||||
float px_range = draw_data.ninepatch_margins.x;
|
||||
float outline_thickness = draw_data.ninepatch_margins.y;
|
||||
//float reserved1 = draw_data.ninepatch_margins.z;
|
||||
|
|
@ -505,7 +510,7 @@ void main() {
|
|||
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
|
||||
color.a = a * color.a;
|
||||
}
|
||||
} else if (bool(draw_data.flags & FLAGS_USE_LCD)) {
|
||||
} else if (bool(draw_data.flags & INSTANCE_FLAGS_USE_LCD)) {
|
||||
vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv);
|
||||
if (lcd_sample.a == 1.0) {
|
||||
color.rgb = lcd_sample.rgb * color.a;
|
||||
|
|
@ -519,8 +524,8 @@ void main() {
|
|||
color *= texture(sampler2D(color_texture, texture_sampler), uv);
|
||||
}
|
||||
|
||||
uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights
|
||||
bool using_light = light_count > 0 || canvas_data.directional_light_count > 0;
|
||||
uint light_count = draw_data.flags & 15u; //max 15 lights
|
||||
bool using_light = (light_count + canvas_data.directional_light_count) > 0;
|
||||
|
||||
vec3 normal;
|
||||
|
||||
|
|
@ -530,17 +535,15 @@ void main() {
|
|||
bool normal_used = false;
|
||||
#endif
|
||||
|
||||
if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
if (normal_used || (using_light && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED))) {
|
||||
normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0);
|
||||
if (bool(draw_data.flags & FLAGS_TRANSPOSE_RECT)) {
|
||||
|
||||
#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE)
|
||||
if (bool(draw_data.flags & INSTANCE_FLAGS_TRANSPOSE_RECT)) {
|
||||
normal.xy = normal.yx;
|
||||
}
|
||||
if (bool(draw_data.flags & FLAGS_FLIP_H)) {
|
||||
normal.x = -normal.x;
|
||||
}
|
||||
if (bool(draw_data.flags & FLAGS_FLIP_V)) {
|
||||
normal.y = -normal.y;
|
||||
}
|
||||
normal.xy *= sign(draw_data.src_rect.zw);
|
||||
#endif
|
||||
normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy)));
|
||||
normal_used = true;
|
||||
} else {
|
||||
|
|
@ -556,9 +559,9 @@ void main() {
|
|||
bool specular_shininess_used = false;
|
||||
#endif
|
||||
|
||||
if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
if (specular_shininess_used || (using_light && normal_used && bool(params.batch_flags & BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED))) {
|
||||
specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv);
|
||||
specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess);
|
||||
specular_shininess *= unpackUnorm4x8(params.specular_shininess);
|
||||
specular_shininess_used = true;
|
||||
} else {
|
||||
specular_shininess = vec4(1.0);
|
||||
|
|
@ -603,136 +606,135 @@ void main() {
|
|||
color *= canvas_data.canvas_modulation;
|
||||
#endif
|
||||
|
||||
#if defined(USE_LIGHTING) && !defined(MODE_UNSHADED)
|
||||
#if !defined(MODE_UNSHADED)
|
||||
if (sc_use_lighting()) {
|
||||
// Directional Lights
|
||||
|
||||
// Directional Lights
|
||||
for (uint i = 0; i < canvas_data.directional_light_count; i++) {
|
||||
uint light_base = i;
|
||||
|
||||
for (uint i = 0; i < canvas_data.directional_light_count; i++) {
|
||||
uint light_base = i;
|
||||
|
||||
vec2 direction = light_array.data[light_base].position;
|
||||
vec4 light_color = light_array.data[light_base].color;
|
||||
vec2 direction = light_array.data[light_base].position;
|
||||
vec4 light_color = light_array.data[light_base].color;
|
||||
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, true);
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, true);
|
||||
#else
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array.data[light_base].height));
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Positional Lights
|
||||
|
||||
for (uint i = 0; i < MAX_LIGHTS_PER_ITEM; i++) {
|
||||
if (i >= light_count) {
|
||||
break;
|
||||
}
|
||||
uint light_base = draw_data.lights[i >> 2];
|
||||
light_base >>= (i & 3) * 8;
|
||||
light_base &= 0xFF;
|
||||
|
||||
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
vec2 tex_uv_atlas = tex_uv * light_array.data[light_base].atlas_rect.zw + light_array.data[light_base].atlas_rect.xy;
|
||||
|
||||
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
|
||||
//if outside the light texture, light color is zero
|
||||
continue;
|
||||
}
|
||||
|
||||
vec4 light_color = textureLod(sampler2D(atlas_texture, texture_sampler), tex_uv_atlas, 0.0);
|
||||
vec4 light_base_color = light_array.data[light_base].color;
|
||||
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
|
||||
light_color.rgb *= light_base_color.rgb;
|
||||
light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, false);
|
||||
#else
|
||||
|
||||
light_color.rgb *= light_base_color.rgb * light_base_color.a;
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
vec3 pos = light_vertex;
|
||||
vec3 light_vec = normalize(light_pos - pos);
|
||||
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec2 pos_norm = normalize(shadow_pos);
|
||||
vec2 pos_abs = abs(pos_norm);
|
||||
vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y);
|
||||
vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot?
|
||||
float tex_ofs;
|
||||
float distance;
|
||||
if (pos_rot.y > 0) {
|
||||
if (pos_rot.x > 0) {
|
||||
tex_ofs = pos_box.y * 0.125 + 0.125;
|
||||
distance = shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125);
|
||||
distance = shadow_pos.y;
|
||||
}
|
||||
if (normal_used) {
|
||||
vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array.data[light_base].height));
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
if (pos_rot.x < 0) {
|
||||
tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125);
|
||||
distance = -shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125);
|
||||
distance = -shadow_pos.y;
|
||||
}
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
distance *= light_array.data[light_base].shadow_zfar_inv;
|
||||
|
||||
//float distance = length(shadow_pos);
|
||||
vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
// Positional Lights
|
||||
|
||||
for (uint i = 0; i < MAX_LIGHTS_PER_ITEM; i++) {
|
||||
if (i >= light_count) {
|
||||
break;
|
||||
}
|
||||
uint light_base = bitfieldExtract(draw_data.lights[i >> 2], (int(i) & 0x3) * 8, 8);
|
||||
|
||||
vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
vec2 tex_uv_atlas = tex_uv * light_array.data[light_base].atlas_rect.zw + light_array.data[light_base].atlas_rect.xy;
|
||||
|
||||
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
|
||||
//if outside the light texture, light color is zero
|
||||
continue;
|
||||
}
|
||||
|
||||
vec4 light_color = textureLod(sampler2D(atlas_texture, texture_sampler), tex_uv_atlas, 0.0);
|
||||
vec4 light_base_color = light_array.data[light_base].color;
|
||||
|
||||
#ifdef LIGHT_CODE_USED
|
||||
|
||||
vec4 shadow_modulate = vec4(1.0);
|
||||
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
|
||||
light_color.rgb *= light_base_color.rgb;
|
||||
light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, false);
|
||||
#else
|
||||
|
||||
light_color.rgb *= light_base_color.rgb * light_base_color.a;
|
||||
|
||||
if (normal_used) {
|
||||
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
|
||||
vec3 pos = light_vertex;
|
||||
vec3 light_vec = normalize(light_pos - pos);
|
||||
|
||||
light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
|
||||
} else {
|
||||
light_color.rgb *= base_color.rgb;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW) && bool(draw_data.flags & (INSTANCE_FLAGS_SHADOW_MASKED << i))) {
|
||||
vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
|
||||
|
||||
vec2 pos_norm = normalize(shadow_pos);
|
||||
vec2 pos_abs = abs(pos_norm);
|
||||
vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y);
|
||||
vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot?
|
||||
float tex_ofs;
|
||||
float distance;
|
||||
if (pos_rot.y > 0) {
|
||||
if (pos_rot.x > 0) {
|
||||
tex_ofs = pos_box.y * 0.125 + 0.125;
|
||||
distance = shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125);
|
||||
distance = shadow_pos.y;
|
||||
}
|
||||
} else {
|
||||
if (pos_rot.x < 0) {
|
||||
tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125);
|
||||
distance = -shadow_pos.x;
|
||||
} else {
|
||||
tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125);
|
||||
distance = -shadow_pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
distance *= light_array.data[light_base].shadow_zfar_inv;
|
||||
|
||||
//float distance = length(shadow_pos);
|
||||
vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0);
|
||||
|
||||
light_color = light_shadow_compute(light_base, light_color, shadow_uv
|
||||
#ifdef LIGHT_CODE_USED
|
||||
,
|
||||
shadow_modulate.rgb
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
light_blend_compute(light_base, light_color, color.rgb);
|
||||
#ifdef MODE_LIGHT_ONLY
|
||||
light_only_alpha += light_color.a;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -6,26 +6,69 @@
|
|||
|
||||
layout(location = 0) in highp vec3 vertex;
|
||||
|
||||
#ifdef POSITIONAL_SHADOW
|
||||
layout(push_constant, std430) uniform Constants {
|
||||
mat2x4 modelview;
|
||||
vec4 rotation;
|
||||
vec2 direction;
|
||||
float z_far;
|
||||
uint pad;
|
||||
float z_near;
|
||||
uint cull_mode;
|
||||
float pad3;
|
||||
float pad4;
|
||||
}
|
||||
constants;
|
||||
|
||||
layout(set = 0, binding = 0, std430) restrict readonly buffer OccluderTransforms {
|
||||
mat2x4 transforms[];
|
||||
}
|
||||
occluder_transforms;
|
||||
|
||||
#else
|
||||
|
||||
layout(push_constant, std430) uniform Constants {
|
||||
mat4 projection;
|
||||
mat2x4 modelview;
|
||||
vec2 direction;
|
||||
float z_far;
|
||||
float pad;
|
||||
uint cull_mode;
|
||||
}
|
||||
constants;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
layout(location = 0) out highp float depth;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
#ifdef POSITIONAL_SHADOW
|
||||
float c = -(constants.z_far + constants.z_near) / (constants.z_far - constants.z_near);
|
||||
float d = -2.0 * constants.z_far * constants.z_near / (constants.z_far - constants.z_near);
|
||||
|
||||
mat4 projection = mat4(vec4(1.0, 0.0, 0.0, 0.0),
|
||||
vec4(0.0, 1.0, 0.0, 0.0),
|
||||
vec4(0.0, 0.0, c, -1.0),
|
||||
vec4(0.0, 0.0, d, 0.0));
|
||||
|
||||
// Precomputed:
|
||||
// Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
|
||||
// projection = projection * Projection(Transform3D().looking_at(cam_targets[i], Vector3(0, 0, -1)).affine_inverse());
|
||||
projection *= mat4(vec4(constants.rotation.x, 0.0, constants.rotation.y, 0.0), vec4(constants.rotation.z, 0.0, constants.rotation.w, 0.0), vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
mat4 modelview = mat4(occluder_transforms.transforms[constants.pad]) * mat4(constants.modelview);
|
||||
#else
|
||||
mat4 projection = constants.projection;
|
||||
mat4 modelview = mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
|
||||
#endif
|
||||
|
||||
highp vec4 vtx = vec4(vertex, 1.0) * modelview;
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
depth = dot(constants.direction, vtx.xy);
|
||||
#endif
|
||||
gl_Position = constants.projection * vtx;
|
||||
|
||||
gl_Position = projection * vtx;
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
|
@ -34,15 +77,33 @@ void main() {
|
|||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#ifdef POSITIONAL_SHADOW
|
||||
layout(push_constant, std430) uniform Constants {
|
||||
mat2x4 modelview;
|
||||
vec4 rotation;
|
||||
vec2 direction;
|
||||
float z_far;
|
||||
uint pad;
|
||||
float z_near;
|
||||
uint cull_mode;
|
||||
float pad3;
|
||||
float pad4;
|
||||
}
|
||||
constants;
|
||||
|
||||
#else
|
||||
|
||||
layout(push_constant, std430) uniform Constants {
|
||||
mat4 projection;
|
||||
mat2x4 modelview;
|
||||
vec2 direction;
|
||||
float z_far;
|
||||
float pad;
|
||||
uint cull_mode;
|
||||
}
|
||||
constants;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MODE_SHADOW
|
||||
layout(location = 0) in highp float depth;
|
||||
layout(location = 0) out highp float distance_buf;
|
||||
|
|
@ -50,8 +111,18 @@ layout(location = 0) out highp float distance_buf;
|
|||
layout(location = 0) out highp float sdf_buf;
|
||||
#endif
|
||||
|
||||
#define POLYGON_CULL_DISABLED 0
|
||||
#define POLYGON_CULL_FRONT 1
|
||||
#define POLYGON_CULL_BACK 2
|
||||
|
||||
void main() {
|
||||
#ifdef MODE_SHADOW
|
||||
bool front_facing = gl_FrontFacing;
|
||||
if (constants.cull_mode == POLYGON_CULL_BACK && !front_facing) {
|
||||
discard;
|
||||
} else if (constants.cull_mode == POLYGON_CULL_FRONT && front_facing) {
|
||||
discard;
|
||||
}
|
||||
distance_buf = depth / constants.z_far;
|
||||
#else
|
||||
sdf_buf = 1.0;
|
||||
|
|
|
|||
|
|
@ -1,42 +1,29 @@
|
|||
|
||||
#define MAX_LIGHTS_PER_ITEM 16
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#define SDF_MAX_LENGTH 16384.0
|
||||
|
||||
//1 means enabled, 2+ means trails in use
|
||||
#define FLAGS_INSTANCING_MASK 0x7F
|
||||
#define FLAGS_INSTANCING_HAS_COLORS (1 << 7)
|
||||
#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 8)
|
||||
#define INSTANCE_FLAGS_LIGHT_COUNT_SHIFT 0 // 4 bits.
|
||||
|
||||
#define FLAGS_CLIP_RECT_UV (1 << 9)
|
||||
#define FLAGS_TRANSPOSE_RECT (1 << 10)
|
||||
#define FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 11)
|
||||
#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12)
|
||||
#define INSTANCE_FLAGS_CLIP_RECT_UV (1 << 4)
|
||||
#define INSTANCE_FLAGS_TRANSPOSE_RECT (1 << 5)
|
||||
#define INSTANCE_FLAGS_USE_MSDF (1 << 6)
|
||||
#define INSTANCE_FLAGS_USE_LCD (1 << 7)
|
||||
|
||||
#define FLAGS_NINEPATCH_H_MODE_SHIFT 16
|
||||
#define FLAGS_NINEPATCH_V_MODE_SHIFT 18
|
||||
#define INSTANCE_FLAGS_NINEPATCH_DRAW_CENTER_SHIFT 8
|
||||
#define INSTANCE_FLAGS_NINEPATCH_H_MODE_SHIFT 9
|
||||
#define INSTANCE_FLAGS_NINEPATCH_V_MODE_SHIFT 11
|
||||
|
||||
#define FLAGS_LIGHT_COUNT_SHIFT 20
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED_SHIFT 13 // 16 bits.
|
||||
#define INSTANCE_FLAGS_SHADOW_MASKED (1 << INSTANCE_FLAGS_SHADOW_MASKED_SHIFT)
|
||||
|
||||
#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26)
|
||||
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
|
||||
|
||||
#define FLAGS_USE_MSDF (1 << 28)
|
||||
#define FLAGS_USE_LCD (1 << 29)
|
||||
|
||||
#define FLAGS_FLIP_H (1 << 30)
|
||||
#define FLAGS_FLIP_V (1 << 31)
|
||||
|
||||
// Push Constant
|
||||
|
||||
layout(push_constant, std430) uniform DrawData {
|
||||
struct InstanceData {
|
||||
vec2 world_x;
|
||||
vec2 world_y;
|
||||
vec2 world_ofs;
|
||||
uint flags;
|
||||
uint specular_shininess;
|
||||
uint instance_uniforms_ofs;
|
||||
#ifdef USE_PRIMITIVE
|
||||
vec2 points[3];
|
||||
vec2 uvs[3];
|
||||
|
|
@ -50,9 +37,50 @@ layout(push_constant, std430) uniform DrawData {
|
|||
|
||||
#endif
|
||||
vec2 color_texture_pixel_size;
|
||||
uint lights[4];
|
||||
uvec4 lights;
|
||||
};
|
||||
|
||||
//1 means enabled, 2+ means trails in use
|
||||
#define BATCH_FLAGS_INSTANCING_MASK 0x7F
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT 7
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_COLORS (1 << BATCH_FLAGS_INSTANCING_HAS_COLORS_SHIFT)
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT 8
|
||||
#define BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << BATCH_FLAGS_INSTANCING_HAS_CUSTOM_DATA_SHIFT)
|
||||
|
||||
#define BATCH_FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 9)
|
||||
#define BATCH_FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 10)
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
uint base_instance_index; // base index to instance data
|
||||
uint sc_packed_0;
|
||||
uint specular_shininess;
|
||||
uint batch_flags;
|
||||
}
|
||||
params;
|
||||
|
||||
// Specialization constants.
|
||||
|
||||
#ifdef UBERSHADER
|
||||
|
||||
// Pull the constants from the draw call's push constants.
|
||||
uint sc_packed_0() {
|
||||
return params.sc_packed_0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Pull the constants from the pipeline's specialization constants.
|
||||
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
|
||||
|
||||
uint sc_packed_0() {
|
||||
return pso_sc_packed_0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool sc_use_lighting() {
|
||||
return ((sc_packed_0() >> 0) & 1U) != 0;
|
||||
}
|
||||
draw_data;
|
||||
|
||||
// In vulkan, sets should always be ordered using the following logic:
|
||||
// Lower Sets: Sets that change format and layout less often
|
||||
|
|
@ -62,6 +90,8 @@ draw_data;
|
|||
|
||||
/* SET0: Globals */
|
||||
|
||||
#define CANVAS_FLAGS_CONVERT_ATTRIBUTES_TO_LINEAR (1 << 0)
|
||||
|
||||
// The values passed per draw primitives are cached within it
|
||||
|
||||
layout(set = 0, binding = 1, std140) uniform CanvasData {
|
||||
|
|
@ -79,7 +109,7 @@ layout(set = 0, binding = 1, std140) uniform CanvasData {
|
|||
|
||||
uint directional_light_count;
|
||||
float tex_to_sdf;
|
||||
uint pad1;
|
||||
uint flags;
|
||||
uint pad2;
|
||||
}
|
||||
canvas_data;
|
||||
|
|
@ -150,3 +180,8 @@ layout(set = 3, binding = 0) uniform texture2D color_texture;
|
|||
layout(set = 3, binding = 1) uniform texture2D normal_texture;
|
||||
layout(set = 3, binding = 2) uniform texture2D specular_texture;
|
||||
layout(set = 3, binding = 3) uniform sampler texture_sampler;
|
||||
|
||||
layout(set = 3, binding = 4, std430) restrict readonly buffer DrawData {
|
||||
InstanceData data[];
|
||||
}
|
||||
instances;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
struct DecalData {
|
||||
highp mat4 xform; //to decal transform
|
||||
highp vec3 inv_extents;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -260,14 +260,14 @@ void main() {
|
|||
#ifdef MODE_COMPOSITE_BOKEH
|
||||
frag_color.rgb = texture(source_color, uv).rgb;
|
||||
|
||||
float center_weigth = texture(source_weight, uv).r;
|
||||
float center_weight = texture(source_weight, uv).r;
|
||||
float sample_weight = texture(original_weight, uv).r;
|
||||
|
||||
float mix_amount;
|
||||
if (sample_weight < center_weigth) {
|
||||
mix_amount = min(1.0, max(0.0, max(abs(center_weigth), abs(sample_weight)) - DEPTH_GAP));
|
||||
if (sample_weight < center_weight) {
|
||||
mix_amount = min(1.0, max(0.0, max(abs(center_weight), abs(sample_weight)) - DEPTH_GAP));
|
||||
} else {
|
||||
mix_amount = min(1.0, max(0.0, abs(center_weigth) - DEPTH_GAP));
|
||||
mix_amount = min(1.0, max(0.0, abs(center_weight) - DEPTH_GAP));
|
||||
}
|
||||
|
||||
// let alpha blending take care of mixing
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ layout(push_constant, std430) uniform Params {
|
|||
float z_far;
|
||||
float z_near;
|
||||
vec2 texel_size;
|
||||
vec4 screen_rect;
|
||||
}
|
||||
params;
|
||||
|
||||
|
|
@ -17,8 +16,7 @@ layout(location = 0) out vec2 uv_interp;
|
|||
void main() {
|
||||
vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
|
||||
uv_interp = base_arr[gl_VertexIndex];
|
||||
vec2 screen_pos = uv_interp * params.screen_rect.zw + params.screen_rect.xy;
|
||||
gl_Position = vec4(screen_pos * 2.0 - 1.0, 0.0, 1.0);
|
||||
gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
|
@ -35,7 +33,6 @@ layout(push_constant, std430) uniform Params {
|
|||
float z_far;
|
||||
float z_near;
|
||||
vec2 texel_size;
|
||||
vec4 screen_rect;
|
||||
}
|
||||
params;
|
||||
|
||||
|
|
|
|||
|
|
@ -177,24 +177,27 @@ void main() {
|
|||
|
||||
float theta;
|
||||
if (Ny < Nx) {
|
||||
if (Ny <= -0.999)
|
||||
if (Ny <= -0.999) {
|
||||
theta = Nx;
|
||||
else
|
||||
} else {
|
||||
theta = Ny;
|
||||
}
|
||||
} else {
|
||||
if (Ny >= 0.999)
|
||||
if (Ny >= 0.999) {
|
||||
theta = -Nx;
|
||||
else
|
||||
} else {
|
||||
theta = -Ny;
|
||||
}
|
||||
}
|
||||
|
||||
float phi;
|
||||
if (Nz <= -0.999)
|
||||
if (Nz <= -0.999) {
|
||||
phi = -NmaxXY;
|
||||
else if (Nz >= 0.999)
|
||||
} else if (Nz >= 0.999) {
|
||||
phi = NmaxXY;
|
||||
else
|
||||
} else {
|
||||
phi = Nz;
|
||||
}
|
||||
|
||||
float theta2 = theta * theta;
|
||||
float phi2 = phi * phi;
|
||||
|
|
|
|||
|
|
@ -170,24 +170,27 @@ void main() {
|
|||
|
||||
float theta;
|
||||
if (Ny < Nx) {
|
||||
if (Ny <= -0.999)
|
||||
if (Ny <= -0.999) {
|
||||
theta = Nx;
|
||||
else
|
||||
} else {
|
||||
theta = Ny;
|
||||
}
|
||||
} else {
|
||||
if (Ny >= 0.999)
|
||||
if (Ny >= 0.999) {
|
||||
theta = -Nx;
|
||||
else
|
||||
} else {
|
||||
theta = -Ny;
|
||||
}
|
||||
}
|
||||
|
||||
float phi;
|
||||
if (Nz <= -0.999)
|
||||
if (Nz <= -0.999) {
|
||||
phi = -NmaxXY;
|
||||
else if (Nz >= 0.999)
|
||||
} else if (Nz >= 0.999) {
|
||||
phi = NmaxXY;
|
||||
else
|
||||
} else {
|
||||
phi = Nz;
|
||||
}
|
||||
|
||||
float theta2 = theta * theta;
|
||||
float phi2 = phi * phi;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
layout(push_constant, std430) uniform PushConstant {
|
||||
ivec2 source_size;
|
||||
ivec2 dest_size;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
#[compute]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "motion_vector_inc.glsl"
|
||||
|
||||
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
||||
layout(set = 0, binding = 0) uniform sampler2D depth_buffer;
|
||||
layout(rg16f, set = 0, binding = 1) uniform restrict writeonly image2D velocity_buffer;
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
highp mat4 reprojection_matrix;
|
||||
vec2 resolution;
|
||||
uint pad[2];
|
||||
}
|
||||
params;
|
||||
|
||||
void main() {
|
||||
// Out of bounds check.
|
||||
if (any(greaterThanEqual(vec2(gl_GlobalInvocationID.xy), params.resolution))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
float depth = texelFetch(depth_buffer, pos, 0).x;
|
||||
vec2 uv = (vec2(pos) + 0.5f) / params.resolution;
|
||||
vec2 velocity = derive_motion_vector(uv, depth, params.reprojection_matrix);
|
||||
imageStore(velocity_buffer, pos, vec4(velocity, 0.0f, 0.0f));
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ void main() {
|
|||
|
||||
// This is an ad-hoc term to fade out the SSR as roughness increases. Values used
|
||||
// are meant to match the visual appearance of a ReflectionProbe.
|
||||
float roughness_fade = smoothstep(0.4, 0.7, 1.0 - normal_roughness.w);
|
||||
float roughness_fade = smoothstep(0.4, 0.7, 1.0 - roughness);
|
||||
|
||||
// Schlick term.
|
||||
float metallic = texelFetch(source_metallic, ssC << 1, 0).w;
|
||||
|
|
|
|||
|
|
@ -70,8 +70,9 @@ void main() {
|
|||
|
||||
int i;
|
||||
for (i = 0; i < 2 * ITERATIONS; ++i) {
|
||||
if (GI + i * NUM_THREADS < numElementsInThreadGroup)
|
||||
if (GI + i * NUM_THREADS < numElementsInThreadGroup) {
|
||||
g_LDS[LocalBaseIndex + i * NUM_THREADS] = sort_buffer.data[GlobalBaseIndex + i * NUM_THREADS];
|
||||
}
|
||||
}
|
||||
|
||||
groupMemoryBarrier();
|
||||
|
|
@ -163,8 +164,9 @@ void main() {
|
|||
|
||||
// Load shared data
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (GI + i * NUM_THREADS < tgp.w)
|
||||
if (GI + i * NUM_THREADS < tgp.w) {
|
||||
g_LDS[LocalBaseIndex + i * NUM_THREADS] = sort_buffer.data[GlobalBaseIndex + i * NUM_THREADS];
|
||||
}
|
||||
}
|
||||
|
||||
groupMemoryBarrier();
|
||||
|
|
|
|||
|
|
@ -50,11 +50,14 @@ const int num_taps[5] = { 3, 5, 12, 0, 0 };
|
|||
//
|
||||
#define SSAO_DETAIL_AO_ENABLE_AT_QUALITY_PRESET (1) // whether to use detail; to disable simply set to 99 or similar
|
||||
//
|
||||
#define SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2) // !!warning!! the MIP generation on the C++ side will be enabled on quality preset 2 regardless of this value, so if changing here, change the C++ side too
|
||||
// WARNING: The MIP generation on the C++ side will be enabled on quality preset 2 regardless of
|
||||
// this value, so if changing here, change the C++ side too.
|
||||
#define SSAO_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2)
|
||||
#define SSAO_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically
|
||||
//
|
||||
// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for
|
||||
// testing purposes, it will not yield performance gains (or correct results)
|
||||
// WARNING: The edge handling is hard-coded to 'disabled' on quality level 0, and enabled above,
|
||||
// on the C++ side; while toggling it here will work for testing purposes, it will not yield
|
||||
// performance gains (or correct results).
|
||||
#define SSAO_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1)
|
||||
//
|
||||
#define SSAO_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1)
|
||||
|
|
|
|||
|
|
@ -49,8 +49,9 @@ const int num_taps[5] = { 3, 5, 12, 0, 0 };
|
|||
#define SSIL_DEPTH_MIPS_ENABLE_AT_QUALITY_PRESET (2)
|
||||
#define SSIL_DEPTH_MIPS_GLOBAL_OFFSET (-4.3) // best noise/quality/performance tradeoff, found empirically
|
||||
//
|
||||
// !!warning!! the edge handling is hard-coded to 'disabled' on quality level 0, and enabled above, on the C++ side; while toggling it here will work for
|
||||
// testing purposes, it will not yield performance gains (or correct results)
|
||||
// WARNING: The edge handling is hard-coded to 'disabled' on quality level 0, and enabled above,
|
||||
// on the C++ side; while toggling it here will work for testing purposes, it will not yield
|
||||
// performance gains (or correct results).
|
||||
#define SSIL_DEPTH_BASED_EDGES_ENABLE_AT_QUALITY_PRESET (1)
|
||||
//
|
||||
#define SSIL_REDUCE_RADIUS_NEAR_SCREEN_BORDER_ENABLE_AT_QUALITY_PRESET (1)
|
||||
|
|
|
|||
|
|
@ -152,10 +152,10 @@ void main() {
|
|||
float depth_scale;
|
||||
|
||||
if (params.orthogonal) {
|
||||
depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
|
||||
depth = -(depth * (params.camera_z_far - params.camera_z_near) - (params.camera_z_far + params.camera_z_near)) / 2.0;
|
||||
depth_scale = params.unit_size; //remember depth is negative by default in OpenGL
|
||||
} else {
|
||||
depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
|
||||
depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near + depth * (params.camera_z_far - params.camera_z_near));
|
||||
depth_scale = params.unit_size / depth; //remember depth is negative by default in OpenGL
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -250,19 +250,25 @@ vec3 clip_aabb(vec3 aabb_min, vec3 aabb_max, vec3 p, vec3 q) {
|
|||
vec3 rmax = (aabb_max - p.xyz);
|
||||
vec3 rmin = (aabb_min - p.xyz);
|
||||
|
||||
if (r.x > rmax.x + FLT_MIN)
|
||||
if (r.x > rmax.x + FLT_MIN) {
|
||||
r *= (rmax.x / r.x);
|
||||
if (r.y > rmax.y + FLT_MIN)
|
||||
}
|
||||
if (r.y > rmax.y + FLT_MIN) {
|
||||
r *= (rmax.y / r.y);
|
||||
if (r.z > rmax.z + FLT_MIN)
|
||||
}
|
||||
if (r.z > rmax.z + FLT_MIN) {
|
||||
r *= (rmax.z / r.z);
|
||||
}
|
||||
|
||||
if (r.x < rmin.x - FLT_MIN)
|
||||
if (r.x < rmin.x - FLT_MIN) {
|
||||
r *= (rmin.x / r.x);
|
||||
if (r.y < rmin.y - FLT_MIN)
|
||||
}
|
||||
if (r.y < rmin.y - FLT_MIN) {
|
||||
r *= (rmin.y / r.y);
|
||||
if (r.z < rmin.z - FLT_MIN)
|
||||
}
|
||||
if (r.z < rmin.z - FLT_MIN) {
|
||||
r *= (rmin.z / r.z);
|
||||
}
|
||||
|
||||
return p + r;
|
||||
}
|
||||
|
|
@ -307,6 +313,8 @@ float luminance(vec3 color) {
|
|||
return max(dot(color, lumCoeff), 0.0001f);
|
||||
}
|
||||
|
||||
// This is "velocity disocclusion" as described by https://www.elopezr.com/temporal-aa-and-the-quest-for-the-holy-trail/.
|
||||
// We use texel space, so our scale and threshold differ.
|
||||
float get_factor_disocclusion(vec2 uv_reprojected, vec2 velocity) {
|
||||
vec2 velocity_previous = imageLoad(last_velocity_buffer, ivec2(uv_reprojected * params.resolution)).xy;
|
||||
vec2 velocity_texels = velocity * params.resolution;
|
||||
|
|
@ -336,7 +344,7 @@ vec3 temporal_antialiasing(uvec2 pos_group_top_left, uvec2 pos_group, uvec2 pos_
|
|||
// Compute blend factor
|
||||
float blend_factor = RPC_16; // We want to be able to accumulate as many jitter samples as we generated, that is, 16.
|
||||
{
|
||||
// If re-projected UV is out of screen, converge to current color immediatel
|
||||
// If re-projected UV is out of screen, converge to current color immediately.
|
||||
float factor_screen = any(lessThan(uv_reprojected, vec2(0.0))) || any(greaterThan(uv_reprojected, vec2(1.0))) ? 1.0 : 0.0;
|
||||
|
||||
// Increase blend factor when there is disocclusion (fixes a lot of the remaining ghosting).
|
||||
|
|
|
|||
|
|
@ -207,6 +207,14 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) {
|
|||
|
||||
#endif // !USE_GLOW_FILTER_BICUBIC
|
||||
|
||||
// Based on Reinhard's extended formula, see equation 4 in https://doi.org/cjbgrt
|
||||
vec3 tonemap_reinhard(vec3 color, float white) {
|
||||
float white_squared = white * white;
|
||||
vec3 white_squared_color = white_squared * color;
|
||||
// Equivalent to color * (1 + color / white_squared) / (1 + color)
|
||||
return (white_squared_color + color * color) / (white_squared_color + white_squared);
|
||||
}
|
||||
|
||||
vec3 tonemap_filmic(vec3 color, float white) {
|
||||
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
|
||||
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
|
||||
|
|
@ -256,8 +264,77 @@ vec3 tonemap_aces(vec3 color, float white) {
|
|||
return color_tonemapped / white_tonemapped;
|
||||
}
|
||||
|
||||
vec3 tonemap_reinhard(vec3 color, float white) {
|
||||
return (white * color + color) / (color * white + white);
|
||||
// Polynomial approximation of EaryChow's AgX sigmoid curve.
|
||||
// x must be within the range [0.0, 1.0]
|
||||
vec3 agx_contrast_approx(vec3 x) {
|
||||
// Generated with Excel trendline
|
||||
// Input data: Generated using python sigmoid with EaryChow's configuration and 57 steps
|
||||
// Additional padding values were added to give correct intersections at 0.0 and 1.0
|
||||
// 6th order, intercept of 0.0 to remove an operation and ensure intersection at 0.0
|
||||
vec3 x2 = x * x;
|
||||
vec3 x4 = x2 * x2;
|
||||
return 0.021 * x + 4.0111 * x2 - 25.682 * x2 * x + 70.359 * x4 - 74.778 * x4 * x + 27.069 * x4 * x2;
|
||||
}
|
||||
|
||||
// This is an approximation and simplification of EaryChow's AgX implementation that is used by Blender.
|
||||
// This code is based off of the script that generates the AgX_Base_sRGB.cube LUT that Blender uses.
|
||||
// Source: https://github.com/EaryChow/AgX_LUT_Gen/blob/main/AgXBasesRGB.py
|
||||
vec3 tonemap_agx(vec3 color) {
|
||||
// Combined linear sRGB to linear Rec 2020 and Blender AgX inset matrices:
|
||||
const mat3 srgb_to_rec2020_agx_inset_matrix = mat3(
|
||||
0.54490813676363087053, 0.14044005884001287035, 0.088827411851915368603,
|
||||
0.37377945959812267119, 0.75410959864013760045, 0.17887712465043811023,
|
||||
0.081384976686407536266, 0.10543358536857773485, 0.73224999956948382528);
|
||||
|
||||
// Combined inverse AgX outset matrix and linear Rec 2020 to linear sRGB matrices.
|
||||
const mat3 agx_outset_rec2020_to_srgb_matrix = mat3(
|
||||
1.9645509602733325934, -0.29932243390911083839, -0.16436833806080403409,
|
||||
-0.85585845117807513559, 1.3264510741502356555, -0.23822464068860595117,
|
||||
-0.10886710826831608324, -0.027084020983874825605, 1.402665347143271889);
|
||||
|
||||
// LOG2_MIN = -10.0
|
||||
// LOG2_MAX = +6.5
|
||||
// MIDDLE_GRAY = 0.18
|
||||
const float min_ev = -12.4739311883324; // log2(pow(2, LOG2_MIN) * MIDDLE_GRAY)
|
||||
const float max_ev = 4.02606881166759; // log2(pow(2, LOG2_MAX) * MIDDLE_GRAY)
|
||||
|
||||
// Large negative values in one channel and large positive values in other
|
||||
// channels can result in a colour that appears darker and more saturated than
|
||||
// desired after passing it through the inset matrix. For this reason, it is
|
||||
// best to prevent negative input values.
|
||||
// This is done before the Rec. 2020 transform to allow the Rec. 2020
|
||||
// transform to be combined with the AgX inset matrix. This results in a loss
|
||||
// of color information that could be correctly interpreted within the
|
||||
// Rec. 2020 color space as positive RGB values, but it is less common for Godot
|
||||
// to provide this function with negative sRGB values and therefore not worth
|
||||
// the performance cost of an additional matrix multiplication.
|
||||
// A value of 2e-10 intentionally introduces insignificant error to prevent
|
||||
// log2(0.0) after the inset matrix is applied; color will be >= 1e-10 after
|
||||
// the matrix transform.
|
||||
color = max(color, 2e-10);
|
||||
|
||||
// Do AGX in rec2020 to match Blender and then apply inset matrix.
|
||||
color = srgb_to_rec2020_agx_inset_matrix * color;
|
||||
|
||||
// Log2 space encoding.
|
||||
// Must be clamped because agx_contrast_approx may not work
|
||||
// well with values outside of the range [0.0, 1.0]
|
||||
color = clamp(log2(color), min_ev, max_ev);
|
||||
color = (color - min_ev) / (max_ev - min_ev);
|
||||
|
||||
// Apply sigmoid function approximation.
|
||||
color = agx_contrast_approx(color);
|
||||
|
||||
// Convert back to linear before applying outset matrix.
|
||||
color = pow(color, vec3(2.4));
|
||||
|
||||
// Apply outset to make the result more chroma-laden and then go back to linear sRGB.
|
||||
color = agx_outset_rec2020_to_srgb_matrix * color;
|
||||
|
||||
// Blender's lusRGB.compensate_low_side is too complex for this shader, so
|
||||
// simply return the color, even if it has negative components. These negative
|
||||
// components may be useful for subsequent color adjustments.
|
||||
return color;
|
||||
}
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
|
|
@ -271,8 +348,9 @@ vec3 linear_to_srgb(vec3 color) {
|
|||
#define TONEMAPPER_REINHARD 1
|
||||
#define TONEMAPPER_FILMIC 2
|
||||
#define TONEMAPPER_ACES 3
|
||||
#define TONEMAPPER_AGX 4
|
||||
|
||||
vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color
|
||||
vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR
|
||||
// Ensure color values passed to tonemappers are positive.
|
||||
// They can be negative in the case of negative lights, which leads to undesired behavior.
|
||||
if (params.tonemapper == TONEMAPPER_LINEAR) {
|
||||
|
|
@ -281,8 +359,10 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o
|
|||
return tonemap_reinhard(max(vec3(0.0f), color), white);
|
||||
} else if (params.tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(max(vec3(0.0f), color), white);
|
||||
} else { // TONEMAPPER_ACES
|
||||
} else if (params.tonemapper == TONEMAPPER_ACES) {
|
||||
return tonemap_aces(max(vec3(0.0f), color), white);
|
||||
} else { // TONEMAPPER_AGX
|
||||
return tonemap_agx(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ layout(set = 1, binding = 1) uniform sampler linear_sampler_mipmaps;
|
|||
|
||||
#define HISTORY_BITS 10
|
||||
|
||||
#define SKY_MODE_DISABLED 0
|
||||
#define SKY_MODE_COLOR 1
|
||||
#define SKY_MODE_SKY 2
|
||||
#define SKY_FLAGS_MODE_COLOR 0x01
|
||||
#define SKY_FLAGS_MODE_SKY 0x02
|
||||
#define SKY_FLAGS_ORIENTATION_SIGN 0x04
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
vec3 grid_size;
|
||||
|
|
@ -67,12 +67,12 @@ layout(push_constant, std430) uniform Params {
|
|||
ivec2 image_size;
|
||||
|
||||
ivec3 world_offset;
|
||||
uint sky_mode;
|
||||
uint sky_flags;
|
||||
|
||||
ivec3 scroll;
|
||||
float sky_energy;
|
||||
|
||||
vec3 sky_color;
|
||||
vec3 sky_color_or_orientation;
|
||||
float y_mult;
|
||||
|
||||
bool store_ambient_texture;
|
||||
|
|
@ -265,17 +265,22 @@ void main() {
|
|||
}
|
||||
}
|
||||
|
||||
} else if (params.sky_mode == SKY_MODE_SKY) {
|
||||
} else if (bool(params.sky_flags & SKY_FLAGS_MODE_SKY)) {
|
||||
// Reconstruct sky orientation as quaternion and rotate ray_dir before sampling.
|
||||
float sky_sign = bool(params.sky_flags & SKY_FLAGS_ORIENTATION_SIGN) ? 1.0 : -1.0;
|
||||
vec4 sky_quat = vec4(params.sky_color_or_orientation, sky_sign * sqrt(1.0 - dot(params.sky_color_or_orientation, params.sky_color_or_orientation)));
|
||||
vec3 sky_dir = cross(sky_quat.xyz, ray_dir);
|
||||
sky_dir = ray_dir + ((sky_dir * sky_quat.w) + cross(sky_quat.xyz, sky_dir)) * 2.0;
|
||||
#ifdef USE_CUBEMAP_ARRAY
|
||||
light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(ray_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
|
||||
light.rgb = textureLod(samplerCubeArray(sky_irradiance, linear_sampler_mipmaps), vec4(sky_dir, 0.0), 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
|
||||
#else
|
||||
light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), ray_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
|
||||
light.rgb = textureLod(samplerCube(sky_irradiance, linear_sampler_mipmaps), sky_dir, 2.0).rgb; // Use second mipmap because we don't usually throw a lot of rays, so this compensates.
|
||||
#endif
|
||||
light.rgb *= params.sky_energy;
|
||||
light.a = 0.0;
|
||||
|
||||
} else if (params.sky_mode == SKY_MODE_COLOR) {
|
||||
light.rgb = params.sky_color;
|
||||
} else if (bool(params.sky_flags & SKY_FLAGS_MODE_COLOR)) {
|
||||
light.rgb = params.sky_color_or_orientation;
|
||||
light.rgb *= params.sky_energy;
|
||||
light.a = 0.0;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ layout(push_constant, std430) uniform Params {
|
|||
vec4 projection; // only applicable if not multiview
|
||||
vec3 position;
|
||||
float time;
|
||||
vec3 pad;
|
||||
vec2 pad;
|
||||
float luminance_multiplier;
|
||||
float brightness_multiplier;
|
||||
}
|
||||
params;
|
||||
|
||||
|
|
@ -57,8 +58,9 @@ layout(push_constant, std430) uniform Params {
|
|||
vec4 projection; // only applicable if not multiview
|
||||
vec3 position;
|
||||
float time;
|
||||
vec3 pad;
|
||||
vec2 pad;
|
||||
float luminance_multiplier;
|
||||
float brightness_multiplier;
|
||||
}
|
||||
params;
|
||||
|
||||
|
|
@ -106,9 +108,11 @@ layout(set = 0, binding = 3, std140) uniform DirectionalLights {
|
|||
directional_lights;
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
} material;
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
layout(set = 2, binding = 0) uniform textureCube radiance;
|
||||
|
|
@ -187,7 +191,7 @@ void main() {
|
|||
vec3 cube_normal;
|
||||
#ifdef USE_MULTIVIEW
|
||||
// In multiview our projection matrices will contain positional and rotational offsets that we need to properly unproject.
|
||||
vec4 unproject = vec4(uv_interp.x, -uv_interp.y, 0.0, 1.0); // unproject at the far plane
|
||||
vec4 unproject = vec4(uv_interp.x, uv_interp.y, 0.0, 1.0); // unproject at the far plane
|
||||
vec4 unprojected = sky_scene_data.view_inv_projections[ViewIndex] * unproject;
|
||||
cube_normal = unprojected.xyz / unprojected.w;
|
||||
|
||||
|
|
@ -196,7 +200,7 @@ void main() {
|
|||
#else
|
||||
cube_normal.z = -1.0;
|
||||
cube_normal.x = (cube_normal.z * (-uv_interp.x - params.projection.x)) / params.projection.y;
|
||||
cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.projection.z)) / params.projection.w;
|
||||
cube_normal.y = -(cube_normal.z * (uv_interp.y - params.projection.z)) / params.projection.w;
|
||||
#endif
|
||||
cube_normal = mat3(params.orientation) * cube_normal;
|
||||
cube_normal = normalize(cube_normal);
|
||||
|
|
@ -247,17 +251,14 @@ void main() {
|
|||
#endif //USE_CUBEMAP_PASS
|
||||
|
||||
{
|
||||
|
||||
#CODE : SKY
|
||||
|
||||
}
|
||||
|
||||
frag_color.rgb = color;
|
||||
frag_color.a = alpha;
|
||||
|
||||
// For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer.
|
||||
// For both mobile and clustered, we also bake in the exposure value for the environment and camera.
|
||||
frag_color.rgb = frag_color.rgb * params.luminance_multiplier;
|
||||
// Apply environment 'brightness' setting separately before fog to ensure consistent luminance.
|
||||
frag_color.rgb = frag_color.rgb * params.brightness_multiplier;
|
||||
|
||||
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
|
||||
|
||||
|
|
@ -278,6 +279,10 @@ void main() {
|
|||
|
||||
#endif // DISABLE_FOG
|
||||
|
||||
// For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer.
|
||||
// For both mobile and clustered, we also bake in the exposure value for the environment and camera.
|
||||
frag_color.rgb = frag_color.rgb * params.luminance_multiplier;
|
||||
|
||||
// Blending is disabled for Sky, so alpha doesn't blend.
|
||||
// Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky.
|
||||
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ layout(push_constant, std430) uniform Params {
|
|||
}
|
||||
params;
|
||||
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
layout(set = 1, binding = 1) volatile buffer emissive_only_map_buffer {
|
||||
uint emissive_only_map[];
|
||||
};
|
||||
|
|
@ -64,7 +64,7 @@ layout(set = 1, binding = 2, std140) uniform SceneParams {
|
|||
}
|
||||
scene_params;
|
||||
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
layout(set = 1, binding = 3) volatile buffer density_only_map_buffer {
|
||||
uint density_only_map[];
|
||||
};
|
||||
|
|
@ -77,9 +77,11 @@ layout(r32ui, set = 1, binding = 4) uniform volatile uimage3D light_only_map;
|
|||
#endif
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 2, binding = 0, std140) uniform MaterialUniforms{
|
||||
/* clang-format off */
|
||||
layout(set = 2, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
} material;
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
|
@ -117,7 +119,7 @@ void main() {
|
|||
if (any(greaterThanEqual(pos, scene_params.fog_volume_size))) {
|
||||
return; //do not compute
|
||||
}
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint lpos = pos.z * scene_params.fog_volume_size.x * scene_params.fog_volume_size.y + pos.y * scene_params.fog_volume_size.x + pos.x;
|
||||
#endif
|
||||
|
||||
|
|
@ -222,7 +224,7 @@ void main() {
|
|||
density *= cull_mask;
|
||||
if (abs(density) > 0.001) {
|
||||
int final_density = int(density * DENSITY_SCALE);
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
atomicAdd(density_only_map[lpos], uint(final_density));
|
||||
#else
|
||||
imageAtomicAdd(density_only_map, pos, uint(final_density));
|
||||
|
|
@ -236,7 +238,7 @@ void main() {
|
|||
uvec3 emission_u = uvec3(emission.r * 511.0, emission.g * 511.0, emission.b * 255.0);
|
||||
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
|
||||
uint final_emission = emission_u.r << 21 | emission_u.g << 10 | emission_u.b;
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint prev_emission = atomicAdd(emissive_only_map[lpos], final_emission);
|
||||
#else
|
||||
uint prev_emission = imageAtomicAdd(emissive_only_map, pos, final_emission);
|
||||
|
|
@ -252,7 +254,7 @@ void main() {
|
|||
if (any(overflowing)) {
|
||||
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
|
||||
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
atomicOr(emissive_only_map[lpos], force_max);
|
||||
#else
|
||||
imageAtomicOr(emissive_only_map, pos, force_max);
|
||||
|
|
@ -267,7 +269,7 @@ void main() {
|
|||
uvec3 scattering_u = uvec3(scattering.r * 2047.0, scattering.g * 2047.0, scattering.b * 1023.0);
|
||||
// R and G have 11 bits each and B has 10. Then pack them into a 32 bit uint
|
||||
uint final_scattering = scattering_u.r << 21 | scattering_u.g << 10 | scattering_u.b;
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint prev_scattering = atomicAdd(light_only_map[lpos], final_scattering);
|
||||
#else
|
||||
uint prev_scattering = imageAtomicAdd(light_only_map, pos, final_scattering);
|
||||
|
|
@ -283,7 +285,7 @@ void main() {
|
|||
if (any(overflowing)) {
|
||||
uvec3 overflow_factor = mix(uvec3(0), uvec3(2047 << 21, 2047 << 10, 1023), overflowing);
|
||||
uint force_max = overflow_factor.r | overflow_factor.g | overflow_factor.b;
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
atomicOr(light_only_map[lpos], force_max);
|
||||
#else
|
||||
imageAtomicOr(light_only_map, pos, force_max);
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ params;
|
|||
#ifndef MODE_COPY
|
||||
layout(set = 0, binding = 15) uniform texture3D prev_density_texture;
|
||||
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
layout(set = 0, binding = 16) buffer density_only_map_buffer {
|
||||
uint density_only_map[];
|
||||
};
|
||||
|
|
@ -287,7 +287,7 @@ void main() {
|
|||
if (any(greaterThanEqual(pos, params.fog_volume_size))) {
|
||||
return; //do not compute
|
||||
}
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint lpos = pos.z * params.fog_volume_size.x * params.fog_volume_size.y + pos.y * params.fog_volume_size.x + pos.x;
|
||||
#endif
|
||||
|
||||
|
|
@ -353,7 +353,7 @@ void main() {
|
|||
vec3 total_light = vec3(0.0);
|
||||
|
||||
float total_density = params.base_density;
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint local_density = density_only_map[lpos];
|
||||
#else
|
||||
uint local_density = imageLoad(density_only_map, pos).x;
|
||||
|
|
@ -362,7 +362,7 @@ void main() {
|
|||
total_density += float(int(local_density)) / DENSITY_SCALE;
|
||||
total_density = max(0.0, total_density);
|
||||
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint scattering_u = light_only_map[lpos];
|
||||
#else
|
||||
uint scattering_u = imageLoad(light_only_map, pos).x;
|
||||
|
|
@ -370,7 +370,7 @@ void main() {
|
|||
vec3 scattering = vec3(scattering_u >> 21, (scattering_u << 11) >> 21, scattering_u % 1024) / vec3(2047.0, 2047.0, 1023.0);
|
||||
scattering += params.base_scattering * params.base_density;
|
||||
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
uint emission_u = emissive_only_map[lpos];
|
||||
#else
|
||||
uint emission_u = imageLoad(emissive_only_map, pos).x;
|
||||
|
|
@ -513,6 +513,7 @@ void main() {
|
|||
shadow_sample.z = 1.0 + abs(shadow_sample.z);
|
||||
vec3 pos = vec3(shadow_sample.xy / shadow_sample.z, shadow_len - omni_lights.data[light_index].shadow_bias);
|
||||
pos.z *= omni_lights.data[light_index].inv_radius;
|
||||
pos.z = 1.0 - pos.z;
|
||||
|
||||
pos.xy = pos.xy * 0.5 + 0.5;
|
||||
pos.xy = uv_rect.xy + pos.xy * uv_rect.zw;
|
||||
|
|
@ -710,7 +711,7 @@ void main() {
|
|||
final_density = mix(final_density, reprojected_density, reproject_amount);
|
||||
|
||||
imageStore(density_map, pos, final_density);
|
||||
#ifdef MOLTENVK_USED
|
||||
#ifdef NO_IMAGE_ATOMICS
|
||||
density_only_map[lpos] = 0;
|
||||
light_only_map[lpos] = 0;
|
||||
emissive_only_map[lpos] = 0;
|
||||
|
|
|
|||
|
|
@ -128,38 +128,54 @@ void main() {
|
|||
int index = x + y * 4;
|
||||
float limit = 0.0;
|
||||
if (x < 8) {
|
||||
if (index == 0)
|
||||
if (index == 0) {
|
||||
limit = 0.0625;
|
||||
if (index == 1)
|
||||
}
|
||||
if (index == 1) {
|
||||
limit = 0.5625;
|
||||
if (index == 2)
|
||||
}
|
||||
if (index == 2) {
|
||||
limit = 0.1875;
|
||||
if (index == 3)
|
||||
}
|
||||
if (index == 3) {
|
||||
limit = 0.6875;
|
||||
if (index == 4)
|
||||
}
|
||||
if (index == 4) {
|
||||
limit = 0.8125;
|
||||
if (index == 5)
|
||||
}
|
||||
if (index == 5) {
|
||||
limit = 0.3125;
|
||||
if (index == 6)
|
||||
}
|
||||
if (index == 6) {
|
||||
limit = 0.9375;
|
||||
if (index == 7)
|
||||
}
|
||||
if (index == 7) {
|
||||
limit = 0.4375;
|
||||
if (index == 8)
|
||||
}
|
||||
if (index == 8) {
|
||||
limit = 0.25;
|
||||
if (index == 9)
|
||||
}
|
||||
if (index == 9) {
|
||||
limit = 0.75;
|
||||
if (index == 10)
|
||||
}
|
||||
if (index == 10) {
|
||||
limit = 0.125;
|
||||
if (index == 11)
|
||||
}
|
||||
if (index == 11) {
|
||||
limit = 0.625;
|
||||
if (index == 12)
|
||||
}
|
||||
if (index == 12) {
|
||||
limit = 1.0;
|
||||
if (index == 13)
|
||||
}
|
||||
if (index == 13) {
|
||||
limit = 0.5;
|
||||
if (index == 14)
|
||||
}
|
||||
if (index == 14) {
|
||||
limit = 0.875;
|
||||
if (index == 15)
|
||||
}
|
||||
if (index == 15) {
|
||||
limit = 0.375;
|
||||
}
|
||||
}
|
||||
if (frag_color.a < limit) {
|
||||
discard;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,9 +37,121 @@ layout(push_constant, std430) uniform DrawCall {
|
|||
uint uv_offset;
|
||||
uint multimesh_motion_vectors_current_offset;
|
||||
uint multimesh_motion_vectors_previous_offset;
|
||||
#ifdef UBERSHADER
|
||||
uint sc_packed_0;
|
||||
uint sc_packed_1;
|
||||
uint sc_packed_2;
|
||||
uint uc_packed_0;
|
||||
#endif
|
||||
}
|
||||
draw_call;
|
||||
|
||||
/* Specialization Constants */
|
||||
|
||||
#ifdef UBERSHADER
|
||||
|
||||
#define POLYGON_CULL_DISABLED 0
|
||||
#define POLYGON_CULL_FRONT 1
|
||||
#define POLYGON_CULL_BACK 2
|
||||
|
||||
// Pull the constants from the draw call's push constants.
|
||||
uint sc_packed_0() {
|
||||
return draw_call.sc_packed_0;
|
||||
}
|
||||
|
||||
uint sc_packed_1() {
|
||||
return draw_call.sc_packed_1;
|
||||
}
|
||||
|
||||
uint uc_cull_mode() {
|
||||
return (draw_call.uc_packed_0 >> 0) & 3U;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Pull the constants from the pipeline's specialization constants.
|
||||
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
|
||||
layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
|
||||
|
||||
uint sc_packed_0() {
|
||||
return pso_sc_packed_0;
|
||||
}
|
||||
|
||||
uint sc_packed_1() {
|
||||
return pso_sc_packed_1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool sc_use_forward_gi() {
|
||||
return ((sc_packed_0() >> 0) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_light_projector() {
|
||||
return ((sc_packed_0() >> 1) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_light_soft_shadows() {
|
||||
return ((sc_packed_0() >> 2) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_directional_soft_shadows() {
|
||||
return ((sc_packed_0() >> 3) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_decal_use_mipmaps() {
|
||||
return ((sc_packed_0() >> 4) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_projector_use_mipmaps() {
|
||||
return ((sc_packed_0() >> 5) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_depth_fog() {
|
||||
return ((sc_packed_0() >> 6) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_lightmap_bicubic_filter() {
|
||||
return ((sc_packed_0() >> 7) & 1U) != 0;
|
||||
}
|
||||
|
||||
uint sc_soft_shadow_samples() {
|
||||
return (sc_packed_0() >> 8) & 63U;
|
||||
}
|
||||
|
||||
uint sc_penumbra_shadow_samples() {
|
||||
return (sc_packed_0() >> 14) & 63U;
|
||||
}
|
||||
|
||||
uint sc_directional_soft_shadow_samples() {
|
||||
return (sc_packed_0() >> 20) & 63U;
|
||||
}
|
||||
|
||||
uint sc_directional_penumbra_shadow_samples() {
|
||||
return (sc_packed_0() >> 26) & 63U;
|
||||
}
|
||||
|
||||
bool sc_multimesh() {
|
||||
return ((sc_packed_1() >> 0) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_format_2d() {
|
||||
return ((sc_packed_1() >> 1) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_has_color() {
|
||||
return ((sc_packed_1() >> 2) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_has_custom_data() {
|
||||
return ((sc_packed_1() >> 3) & 1U) != 0;
|
||||
}
|
||||
|
||||
float sc_luminance_multiplier() {
|
||||
// Not used in clustered renderer but we share some code with the mobile renderer that requires this.
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
#define SDFGI_MAX_CASCADES 8
|
||||
|
||||
/* Set 0: Base Pass (never changes) */
|
||||
|
|
@ -57,10 +169,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
|||
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
|
||||
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
|
||||
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
|
||||
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
|
||||
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
|
||||
#define INSTANCE_FLAGS_FADE_SHIFT 24
|
||||
//3 bits of stride
|
||||
|
|
@ -92,10 +200,16 @@ directional_lights;
|
|||
#define LIGHTMAP_FLAG_USE_DIRECTION 1
|
||||
#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
|
||||
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_NONE 0
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_REPLACE 1
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_OVERLAY 2
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_ONLY 3
|
||||
|
||||
struct Lightmap {
|
||||
mat3 normal_xform;
|
||||
vec3 pad;
|
||||
vec2 light_texture_size;
|
||||
float exposure_normalization;
|
||||
uint flags;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
||||
|
|
@ -240,7 +354,7 @@ layout(set = 1, binding = 5) uniform texture2D shadow_atlas;
|
|||
|
||||
layout(set = 1, binding = 6) uniform texture2D directional_shadow_atlas;
|
||||
|
||||
layout(set = 1, binding = 7) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
|
||||
layout(set = 1, binding = 7) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES * 2];
|
||||
|
||||
layout(set = 1, binding = 8) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -20,9 +20,190 @@ layout(push_constant, std430) uniform DrawCall {
|
|||
vec2 uv_offset;
|
||||
uint instance_index;
|
||||
uint pad;
|
||||
#ifdef UBERSHADER
|
||||
uint sc_packed_0;
|
||||
uint sc_packed_1;
|
||||
uint sc_packed_2;
|
||||
float sc_packed_3;
|
||||
uint uc_packed_0;
|
||||
uint uc_padding_1;
|
||||
uint uc_padding_2;
|
||||
uint uc_padding_3;
|
||||
#endif
|
||||
}
|
||||
draw_call;
|
||||
|
||||
/* Specialization Constants */
|
||||
|
||||
#ifdef UBERSHADER
|
||||
|
||||
#define POLYGON_CULL_DISABLED 0
|
||||
#define POLYGON_CULL_FRONT 1
|
||||
#define POLYGON_CULL_BACK 2
|
||||
|
||||
// Pull the constants from the draw call's push constants.
|
||||
uint sc_packed_0() {
|
||||
return draw_call.sc_packed_0;
|
||||
}
|
||||
|
||||
uint sc_packed_1() {
|
||||
return draw_call.sc_packed_1;
|
||||
}
|
||||
|
||||
uint sc_packed_2() {
|
||||
return draw_call.sc_packed_2;
|
||||
}
|
||||
|
||||
float sc_packed_3() {
|
||||
return draw_call.sc_packed_3;
|
||||
}
|
||||
|
||||
uint uc_cull_mode() {
|
||||
return (draw_call.uc_packed_0 >> 0) & 3U;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Pull the constants from the pipeline's specialization constants.
|
||||
layout(constant_id = 0) const uint pso_sc_packed_0 = 0;
|
||||
layout(constant_id = 1) const uint pso_sc_packed_1 = 0;
|
||||
layout(constant_id = 2) const uint pso_sc_packed_2 = 0;
|
||||
layout(constant_id = 3) const float pso_sc_packed_3 = 2.0;
|
||||
|
||||
uint sc_packed_0() {
|
||||
return pso_sc_packed_0;
|
||||
}
|
||||
|
||||
uint sc_packed_1() {
|
||||
return pso_sc_packed_1;
|
||||
}
|
||||
|
||||
uint sc_packed_2() {
|
||||
return pso_sc_packed_2;
|
||||
}
|
||||
|
||||
float sc_packed_3() {
|
||||
return pso_sc_packed_3;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool sc_use_light_projector() {
|
||||
return ((sc_packed_0() >> 0) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_light_soft_shadows() {
|
||||
return ((sc_packed_0() >> 1) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_directional_soft_shadows() {
|
||||
return ((sc_packed_0() >> 2) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_decal_use_mipmaps() {
|
||||
return ((sc_packed_0() >> 3) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_projector_use_mipmaps() {
|
||||
return ((sc_packed_0() >> 4) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_disable_fog() {
|
||||
return ((sc_packed_0() >> 5) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_depth_fog() {
|
||||
return ((sc_packed_0() >> 6) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_fog_aerial_perspective() {
|
||||
return ((sc_packed_0() >> 7) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_fog_sun_scatter() {
|
||||
return ((sc_packed_0() >> 8) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_fog_height_density() {
|
||||
return ((sc_packed_0() >> 9) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_use_lightmap_bicubic_filter() {
|
||||
return ((sc_packed_0() >> 10) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh() {
|
||||
return ((sc_packed_0() >> 11) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_format_2d() {
|
||||
return ((sc_packed_0() >> 12) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_has_color() {
|
||||
return ((sc_packed_0() >> 13) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_multimesh_has_custom_data() {
|
||||
return ((sc_packed_0() >> 14) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_scene_use_ambient_cubemap() {
|
||||
return ((sc_packed_0() >> 15) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_scene_use_reflection_cubemap() {
|
||||
return ((sc_packed_0() >> 16) & 1U) != 0;
|
||||
}
|
||||
|
||||
bool sc_scene_roughness_limiter_enabled() {
|
||||
return ((sc_packed_0() >> 17) & 1U) != 0;
|
||||
}
|
||||
|
||||
uint sc_soft_shadow_samples() {
|
||||
return (sc_packed_0() >> 20) & 63U;
|
||||
}
|
||||
|
||||
uint sc_penumbra_shadow_samples() {
|
||||
return (sc_packed_0() >> 26) & 63U;
|
||||
}
|
||||
|
||||
uint sc_directional_soft_shadow_samples() {
|
||||
return (sc_packed_1() >> 0) & 63U;
|
||||
}
|
||||
|
||||
uint sc_directional_penumbra_shadow_samples() {
|
||||
return (sc_packed_1() >> 6) & 63U;
|
||||
}
|
||||
|
||||
uint sc_omni_lights() {
|
||||
return (sc_packed_1() >> 12) & 15U;
|
||||
}
|
||||
|
||||
uint sc_spot_lights() {
|
||||
return (sc_packed_1() >> 16) & 15U;
|
||||
}
|
||||
|
||||
uint sc_reflection_probes() {
|
||||
return (sc_packed_1() >> 20) & 15U;
|
||||
}
|
||||
|
||||
uint sc_directional_lights() {
|
||||
return (sc_packed_1() >> 24) & 15U;
|
||||
}
|
||||
|
||||
uint sc_decals() {
|
||||
return (sc_packed_1() >> 28) & 15U;
|
||||
}
|
||||
|
||||
bool sc_directional_light_blend_split(uint i) {
|
||||
return ((sc_packed_2() >> i) & 1U) != 0;
|
||||
}
|
||||
|
||||
float sc_luminance_multiplier() {
|
||||
return sc_packed_3();
|
||||
}
|
||||
|
||||
/* Set 0: Base Pass (never changes) */
|
||||
|
||||
#include "../light_data_inc.glsl"
|
||||
|
|
@ -38,10 +219,6 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
|||
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
|
||||
#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
|
||||
#define INSTANCE_FLAGS_PARTICLES (1 << 11)
|
||||
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
|
||||
#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15)
|
||||
#define INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT 16
|
||||
//3 bits of stride
|
||||
#define INSTANCE_FLAGS_PARTICLE_TRAIL_MASK 0xFF
|
||||
|
|
@ -69,10 +246,16 @@ directional_lights;
|
|||
#define LIGHTMAP_FLAG_USE_DIRECTION 1
|
||||
#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
|
||||
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_NONE 0
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_REPLACE 1
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_OVERLAY 2
|
||||
#define LIGHTMAP_SHADOWMASK_MODE_ONLY 3
|
||||
|
||||
struct Lightmap {
|
||||
mediump mat3 normal_xform;
|
||||
vec3 pad;
|
||||
vec2 light_texture_size;
|
||||
float exposure_normalization;
|
||||
uint flags;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
||||
|
|
@ -152,7 +335,7 @@ layout(set = 1, binding = 4) uniform highp texture2D shadow_atlas;
|
|||
layout(set = 1, binding = 5) uniform highp texture2D directional_shadow_atlas;
|
||||
|
||||
// this needs to change to providing just the lightmap we're using..
|
||||
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
|
||||
layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES * 2];
|
||||
|
||||
#ifdef USE_MULTIVIEW
|
||||
layout(set = 1, binding = 9) uniform highp texture2DArray depth_buffer;
|
||||
|
|
|
|||
|
|
@ -41,10 +41,14 @@ struct ReflectionData {
|
|||
uint mask;
|
||||
mediump vec3 ambient; // ambient color
|
||||
mediump float intensity;
|
||||
mediump float blend_distance;
|
||||
bool exterior;
|
||||
bool box_project;
|
||||
uint ambient_mode;
|
||||
float exposure_normalization;
|
||||
float pad0;
|
||||
float pad1;
|
||||
float pad2;
|
||||
//0-8 is intensity,8-9 is ambient, mode
|
||||
highp mat4 local_matrix; // up to here for spot and omni, rest is for directional
|
||||
// notes: for ambientblend, use distance to edge to blend between already existing global environment
|
||||
|
|
|
|||
|
|
@ -168,11 +168,11 @@ layout(set = 2, binding = 1) uniform texture2D height_field_texture;
|
|||
/* SET 3: MATERIAL */
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 3, binding = 0, std140) uniform MaterialUniforms{
|
||||
|
||||
/* clang-format off */
|
||||
layout(set = 3, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
} material;
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
layout(push_constant, std430) uniform Params {
|
||||
|
|
@ -488,7 +488,7 @@ void main() {
|
|||
}
|
||||
amount = pow(amount, FRAME.attractors[i].attenuation);
|
||||
dir = safe_normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality));
|
||||
attractor_force -= amount * dir * FRAME.attractors[i].strength;
|
||||
attractor_force -= mass * amount * dir * FRAME.attractors[i].strength;
|
||||
}
|
||||
|
||||
float particle_size = FRAME.particle_size;
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@ struct SceneData {
|
|||
uint fog_mode;
|
||||
highp float fog_density;
|
||||
highp float fog_height;
|
||||
highp float fog_height_density;
|
||||
|
||||
highp float fog_height_density;
|
||||
highp float fog_depth_curve;
|
||||
highp float pad;
|
||||
highp float fog_depth_begin;
|
||||
highp float taa_frame_count;
|
||||
|
||||
mediump vec3 fog_light_color;
|
||||
highp float fog_depth_end;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,82 @@
|
|||
// Simplified versions of light functions intended for the vertex shader.
|
||||
|
||||
// Eyeballed approximation of `exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25`.
|
||||
// Uses slightly more FMA instructions (2x rate) to avoid special instructions (0.25x rate).
|
||||
// Range is reduced to [0.64,4977] from [068,2,221,528] which makes mediump feasible for the rest of the shader.
|
||||
mediump float roughness_to_shininess(mediump float roughness) {
|
||||
mediump float r = 1.2 - roughness;
|
||||
mediump float r2 = r * r;
|
||||
return r * r2 * r2 * 2000.0;
|
||||
}
|
||||
|
||||
void light_compute_vertex(vec3 N, vec3 L, vec3 V, vec3 light_color, bool is_directional, float roughness,
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
float NdotL = min(dot(N, L), 1.0);
|
||||
float cNdotL = max(NdotL, 0.0); // clamped NdotL
|
||||
|
||||
#if defined(DIFFUSE_LAMBERT_WRAP)
|
||||
// Energy conserving lambert wrap shader.
|
||||
// https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
|
||||
float diffuse_brdf_NL = max(0.0, (cNdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
|
||||
#else
|
||||
// lambert
|
||||
float diffuse_brdf_NL = cNdotL * (1.0 / M_PI);
|
||||
#endif
|
||||
|
||||
diffuse_light += light_color * diffuse_brdf_NL;
|
||||
|
||||
#if !defined(SPECULAR_DISABLED)
|
||||
float specular_brdf_NL = 0.0;
|
||||
// Normalized blinn always unless disabled.
|
||||
vec3 H = normalize(V + L);
|
||||
float cNdotH = clamp(dot(N, H), 0.0, 1.0);
|
||||
float shininess = roughness_to_shininess(roughness);
|
||||
float blinn = pow(cNdotH, shininess);
|
||||
blinn *= (shininess + 2.0) * (1.0 / (8.0 * M_PI)) * cNdotL;
|
||||
specular_brdf_NL = blinn;
|
||||
specular_light += specular_brdf_NL * light_color;
|
||||
#endif
|
||||
}
|
||||
|
||||
float get_omni_attenuation(float distance, float inv_range, float decay) {
|
||||
float nd = distance * inv_range;
|
||||
nd *= nd;
|
||||
nd *= nd; // nd^4
|
||||
nd = max(1.0 - nd, 0.0);
|
||||
nd *= nd; // nd^2
|
||||
return nd * pow(max(distance, 0.0001), -decay);
|
||||
}
|
||||
|
||||
void light_process_omni_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness,
|
||||
inout vec3 diffuse_light, inout vec3 specular_light) {
|
||||
vec3 light_rel_vec = omni_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float omni_attenuation = get_omni_attenuation(light_length, omni_lights.data[idx].inv_radius, omni_lights.data[idx].attenuation);
|
||||
vec3 color = omni_lights.data[idx].color * omni_attenuation;
|
||||
|
||||
light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
|
||||
diffuse_light,
|
||||
specular_light);
|
||||
}
|
||||
|
||||
void light_process_spot_vertex(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness,
|
||||
inout vec3 diffuse_light,
|
||||
inout vec3 specular_light) {
|
||||
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
|
||||
float light_length = length(light_rel_vec);
|
||||
float spot_attenuation = get_omni_attenuation(light_length, spot_lights.data[idx].inv_radius, spot_lights.data[idx].attenuation);
|
||||
vec3 spot_dir = spot_lights.data[idx].direction;
|
||||
|
||||
// This conversion to a highp float is crucial to prevent light leaking
|
||||
// due to precision errors in the following calculations (cone angle is mediump).
|
||||
highp float cone_angle = spot_lights.data[idx].cone_angle;
|
||||
float scos = max(dot(-normalize(light_rel_vec), spot_dir), cone_angle);
|
||||
float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cone_angle));
|
||||
|
||||
spot_attenuation *= 1.0 - pow(spot_rim, spot_lights.data[idx].cone_attenuation);
|
||||
vec3 color = spot_lights.data[idx].color * spot_attenuation;
|
||||
float specular_amount = spot_lights.data[idx].specular_amount;
|
||||
|
||||
light_compute_vertex(normal, normalize(light_rel_vec), eye_vec, color, false, roughness,
|
||||
diffuse_light, specular_light);
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue