Create mobile renderer
This commit is contained in:
parent
a4afa05efe
commit
58ff0dac1a
28 changed files with 7137 additions and 1506 deletions
|
@ -1356,10 +1356,6 @@
|
|||
[b]FIXME:[/b] No longer valid after DisplayServer split:
|
||||
In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time.
|
||||
</member>
|
||||
<member name="rendering/driver/rd_renderer/use_low_end_renderer" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/driver/rd_renderer/use_low_end_renderer.mobile" type="bool" setter="" getter="" default="true">
|
||||
</member>
|
||||
<member name="rendering/driver/threads/thread_model" type="int" setter="" getter="" default="1">
|
||||
Thread model for rendering. Rendering on a thread can vastly improve performance, but synchronizing to the main thread can cause a bit more jitter.
|
||||
</member>
|
||||
|
|
|
@ -5,4 +5,5 @@ Import("env")
|
|||
env.add_source_files(env.servers_sources, "*.cpp")
|
||||
|
||||
SConscript("forward_clustered/SCsub")
|
||||
SConscript("forward_mobile/SCsub")
|
||||
SConscript("shaders/SCsub")
|
||||
|
|
|
@ -284,8 +284,6 @@ void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferData
|
|||
fb.push_back(rb->normal_roughness_buffer_msaa);
|
||||
rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
|
||||
}
|
||||
|
||||
_render_buffers_clear_uniform_set(rb);
|
||||
}
|
||||
|
||||
RendererSceneRenderRD::RenderBufferData *RenderForwardClustered::_create_render_buffer_data() {
|
||||
|
@ -2305,15 +2303,6 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
|
|||
return sdfgi_pass_uniform_set;
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_render_buffers_clear_uniform_set(RenderBufferDataForwardClustered *rb) {
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_render_buffers_uniform_set_changed(RID p_render_buffers) {
|
||||
RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
|
||||
|
||||
_render_buffers_clear_uniform_set(rb);
|
||||
}
|
||||
|
||||
RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
|
||||
RenderBufferDataForwardClustered *rb = (RenderBufferDataForwardClustered *)render_buffers_get_data(p_render_buffers);
|
||||
|
||||
|
|
|
@ -118,8 +118,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
|
||||
|
||||
virtual void _base_uniforms_changed();
|
||||
void _render_buffers_clear_uniform_set(RenderBufferDataForwardClustered *rb);
|
||||
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
|
||||
|
||||
void _update_render_base_uniform_set();
|
||||
|
@ -202,6 +200,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
};
|
||||
|
||||
struct SceneState {
|
||||
// This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
|
||||
struct UBO {
|
||||
float projection_matrix[16];
|
||||
float inv_projection_matrix[16];
|
||||
|
|
|
@ -146,12 +146,17 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
for (int i = 0; i < gen_code.defines.size(); i++) {
|
||||
print_line(gen_code.defines[i]);
|
||||
}
|
||||
|
||||
Map<String, String>::Element * el = gen_code.code.front();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key() + ":\n" + el->value());
|
||||
|
||||
el = el->next();
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
|
||||
print_line("\n**vertex_code:\n" + gen_code.vertex);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
|
||||
print_line("\n**fragment_code:\n" + gen_code.fragment);
|
||||
print_line("\n**light_code:\n" + gen_code.light);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
|
||||
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
|
||||
|
@ -566,18 +571,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
|
|||
shader_versions.push_back("\n#define USE_LIGHTMAP\n");
|
||||
shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n");
|
||||
shader.initialize(shader_versions, p_defines);
|
||||
|
||||
/*
|
||||
if (p_is_low_end) {
|
||||
//disable the high end versions
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_SDF, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, false);
|
||||
shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, false);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
|
||||
|
|
5
servers/rendering/renderer_rd/forward_mobile/SCsub
Normal file
5
servers/rendering/renderer_rd/forward_mobile/SCsub
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.servers_sources, "*.cpp")
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,604 @@
|
|||
/*************************************************************************/
|
||||
/* render_forward_mobile.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
|
||||
#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
|
||||
|
||||
#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/renderer_storage_rd.h"
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class RenderForwardMobile : public RendererSceneRenderRD {
|
||||
friend SceneShaderForwardMobile;
|
||||
|
||||
protected:
|
||||
/* Scene Shader */
|
||||
|
||||
enum {
|
||||
SCENE_UNIFORM_SET = 0,
|
||||
RENDER_PASS_UNIFORM_SET = 1,
|
||||
TRANSFORMS_UNIFORM_SET = 2,
|
||||
MATERIAL_UNIFORM_SET = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_LIGHTMAPS = 8,
|
||||
MAX_RDL_CULL = 8, // maximum number of reflection probes, decals or lights we can cull per geometry instance
|
||||
INSTANCE_DATA_BUFFER_MIN_SIZE = 4096
|
||||
};
|
||||
|
||||
enum RenderListType {
|
||||
RENDER_LIST_OPAQUE, //used for opaque objects
|
||||
RENDER_LIST_ALPHA, //used for transparent objects
|
||||
RENDER_LIST_SECONDARY, //used for shadows and other objects
|
||||
RENDER_LIST_MAX
|
||||
};
|
||||
|
||||
/* Scene Shader */
|
||||
|
||||
SceneShaderForwardMobile scene_shader;
|
||||
|
||||
/* Render Buffer */
|
||||
|
||||
struct RenderBufferDataForwardMobile : public RenderBufferData {
|
||||
RID color;
|
||||
RID depth;
|
||||
// RID normal_roughness_buffer;
|
||||
|
||||
RS::ViewportMSAA msaa;
|
||||
RD::TextureSamples texture_samples;
|
||||
|
||||
RID color_msaa;
|
||||
RID depth_msaa;
|
||||
// RID normal_roughness_buffer_msaa;
|
||||
|
||||
RID color_fb;
|
||||
int width, height;
|
||||
|
||||
void clear();
|
||||
virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa);
|
||||
|
||||
~RenderBufferDataForwardMobile();
|
||||
};
|
||||
|
||||
virtual RenderBufferData *_create_render_buffer_data();
|
||||
|
||||
/* Rendering */
|
||||
|
||||
enum PassMode {
|
||||
PASS_MODE_COLOR,
|
||||
// PASS_MODE_COLOR_SPECULAR,
|
||||
PASS_MODE_COLOR_TRANSPARENT,
|
||||
PASS_MODE_SHADOW,
|
||||
PASS_MODE_SHADOW_DP,
|
||||
// PASS_MODE_DEPTH,
|
||||
// PASS_MODE_DEPTH_NORMAL_ROUGHNESS,
|
||||
// PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
// PASS_MODE_SDF,
|
||||
};
|
||||
|
||||
struct GeometryInstanceForwardMobile;
|
||||
struct GeometryInstanceSurfaceDataCache;
|
||||
struct RenderElementInfo;
|
||||
|
||||
struct RenderListParameters {
|
||||
GeometryInstanceSurfaceDataCache **elements = nullptr;
|
||||
RenderElementInfo *element_info = nullptr;
|
||||
int element_count = 0;
|
||||
bool reverse_cull = false;
|
||||
PassMode pass_mode = PASS_MODE_COLOR;
|
||||
// bool no_gi = false;
|
||||
RID render_pass_uniform_set;
|
||||
bool force_wireframe = false;
|
||||
Vector2 uv_offset;
|
||||
Plane lod_plane;
|
||||
float lod_distance_multiplier = 0.0;
|
||||
float screen_lod_threshold = 0.0;
|
||||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
uint32_t barrier = RD::BARRIER_MASK_ALL;
|
||||
|
||||
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, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
|
||||
elements = p_elements;
|
||||
element_info = p_element_info;
|
||||
element_count = p_element_count;
|
||||
reverse_cull = p_reverse_cull;
|
||||
pass_mode = p_pass_mode;
|
||||
// no_gi = p_no_gi;
|
||||
render_pass_uniform_set = p_render_pass_uniform_set;
|
||||
force_wireframe = p_force_wireframe;
|
||||
uv_offset = p_uv_offset;
|
||||
lod_plane = p_lod_plane;
|
||||
lod_distance_multiplier = p_lod_distance_multiplier;
|
||||
screen_lod_threshold = p_screen_lod_threshold;
|
||||
element_offset = p_element_offset;
|
||||
barrier = p_barrier;
|
||||
}
|
||||
};
|
||||
|
||||
RID _setup_render_pass_uniform_set(RenderListType p_render_list, RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_lightmaps, bool p_use_directional_shadow_atlas = false, int p_index = 0);
|
||||
virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_cluster_buffer, uint32_t p_cluster_size, uint32_t p_cluster_max_elements, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold);
|
||||
|
||||
virtual void _render_shadow_begin();
|
||||
virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true);
|
||||
virtual void _render_shadow_process();
|
||||
virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
|
||||
|
||||
virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region);
|
||||
virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture);
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);
|
||||
|
||||
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
|
||||
|
||||
virtual void _base_uniforms_changed();
|
||||
void _update_render_base_uniform_set();
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);
|
||||
|
||||
void _fill_render_list(RenderListType p_render_list, const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, const Plane &p_lod_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, bool p_append = false);
|
||||
void _fill_instance_data(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
|
||||
// void _update_instance_data_buffer(RenderListType p_render_list);
|
||||
|
||||
static RenderForwardMobile *singleton;
|
||||
|
||||
void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2i &p_screen_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
|
||||
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform);
|
||||
|
||||
RID render_base_uniform_set;
|
||||
LocalVector<RID> render_pass_uniform_sets;
|
||||
|
||||
/* Light map */
|
||||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
};
|
||||
|
||||
struct LightmapCaptureData {
|
||||
float sh[9 * 4];
|
||||
};
|
||||
|
||||
/* Scene state */
|
||||
|
||||
struct SceneState {
|
||||
// This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
|
||||
struct UBO {
|
||||
float projection_matrix[16];
|
||||
float inv_projection_matrix[16];
|
||||
|
||||
float camera_matrix[16];
|
||||
float inv_camera_matrix[16];
|
||||
|
||||
float viewport_size[2];
|
||||
float screen_pixel_size[2];
|
||||
|
||||
float directional_penumbra_shadow_kernel[128]; //32 vec4s
|
||||
float directional_soft_shadow_kernel[128];
|
||||
float penumbra_shadow_kernel[128];
|
||||
float soft_shadow_kernel[128];
|
||||
|
||||
uint32_t directional_penumbra_shadow_samples;
|
||||
uint32_t directional_soft_shadow_samples;
|
||||
uint32_t penumbra_shadow_samples;
|
||||
uint32_t soft_shadow_samples;
|
||||
|
||||
float ambient_light_color_energy[4];
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
uint32_t use_ambient_light;
|
||||
uint32_t use_ambient_cubemap;
|
||||
uint32_t use_reflection_cubemap;
|
||||
|
||||
float radiance_inverse_xform[12];
|
||||
|
||||
float shadow_atlas_pixel_size[2];
|
||||
float directional_shadow_pixel_size[2];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
float dual_paraboloid_side;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
uint32_t ssao_enabled;
|
||||
float ssao_light_affect;
|
||||
float ssao_ao_affect;
|
||||
uint32_t roughness_limiter_enabled;
|
||||
|
||||
float roughness_limiter_amount;
|
||||
float roughness_limiter_limit;
|
||||
uint32_t roughness_limiter_pad[2];
|
||||
|
||||
float ao_color[4];
|
||||
|
||||
// Fog
|
||||
uint32_t fog_enabled;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
float fog_light_color[3];
|
||||
float fog_sun_scatter;
|
||||
|
||||
float fog_aerial_perspective;
|
||||
uint32_t material_uv2_mode;
|
||||
|
||||
float time;
|
||||
float reflection_multiplier;
|
||||
|
||||
uint32_t pancake_shadows;
|
||||
uint32_t pad1;
|
||||
uint32_t pad2;
|
||||
uint32_t pad3;
|
||||
};
|
||||
|
||||
UBO ubo;
|
||||
|
||||
LocalVector<RID> uniform_buffers;
|
||||
|
||||
// !BAS! We need to change lightmaps, we're not going to do this with a buffer but pushing the used lightmap in
|
||||
LightmapData lightmaps[MAX_LIGHTMAPS];
|
||||
RID lightmap_ids[MAX_LIGHTMAPS];
|
||||
bool lightmap_has_sh[MAX_LIGHTMAPS];
|
||||
uint32_t lightmaps_used = 0;
|
||||
uint32_t max_lightmaps;
|
||||
RID lightmap_buffer;
|
||||
|
||||
LightmapCaptureData *lightmap_captures;
|
||||
uint32_t max_lightmap_captures;
|
||||
RID lightmap_capture_buffer;
|
||||
|
||||
bool used_screen_texture = false;
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_sss = false;
|
||||
|
||||
struct ShadowPass {
|
||||
uint32_t element_from;
|
||||
uint32_t element_count;
|
||||
bool flip_cull;
|
||||
PassMode pass_mode;
|
||||
|
||||
RID rp_uniform_set;
|
||||
Plane camera_plane;
|
||||
float lod_distance_multiplier;
|
||||
float screen_lod_threshold;
|
||||
|
||||
RID framebuffer;
|
||||
RD::InitialAction initial_depth_action;
|
||||
RD::FinalAction final_depth_action;
|
||||
Rect2i rect;
|
||||
};
|
||||
|
||||
LocalVector<ShadowPass> shadow_passes;
|
||||
} scene_state;
|
||||
|
||||
/* Render List */
|
||||
|
||||
// !BAS! Render list can probably be reused between clustered and mobile?
|
||||
struct RenderList {
|
||||
LocalVector<GeometryInstanceSurfaceDataCache *> elements;
|
||||
LocalVector<RenderElementInfo> element_info;
|
||||
|
||||
void clear() {
|
||||
elements.clear();
|
||||
element_info.clear();
|
||||
}
|
||||
|
||||
//should eventually be replaced by radix
|
||||
|
||||
struct SortByKey {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
|
||||
return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_key() {
|
||||
SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
void sort_by_key_range(uint32_t p_from, uint32_t p_size) {
|
||||
SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;
|
||||
sorter.sort(elements.ptr() + p_from, p_size);
|
||||
}
|
||||
|
||||
struct SortByDepth {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
|
||||
return (A->owner->depth < B->owner->depth);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_depth() { //used for shadows
|
||||
|
||||
SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
struct SortByReverseDepthAndPriority {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
|
||||
return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha
|
||||
|
||||
SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {
|
||||
elements.push_back(p_element);
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderElementInfo {
|
||||
uint32_t repeat : 22;
|
||||
uint32_t uses_lightmap : 1;
|
||||
uint32_t lod_index : 8;
|
||||
uint32_t reserved : 1; // was uses_forward_gi but we don't use that here
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
LocalVector<RD::DrawListID> thread_draw_lists;
|
||||
void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params);
|
||||
void _render_list_with_threads(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 = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>());
|
||||
|
||||
uint32_t render_list_thread_threshold = 500;
|
||||
|
||||
RenderList render_list[RENDER_LIST_MAX];
|
||||
|
||||
/* Geometry instance */
|
||||
|
||||
// check which ones of these apply, probably all except GI and SDFGI
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
|
||||
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
|
||||
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
|
||||
INSTANCE_DATA_FLAG_USE_GIPROBE = 1 << 11,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
||||
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_SHIFT = 16,
|
||||
INSTANCE_DATA_FLAGS_PARTICLE_TRAIL_MASK = 0xFF,
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 24,
|
||||
};
|
||||
|
||||
struct GeometryInstanceLightmapSH {
|
||||
Color sh[9];
|
||||
};
|
||||
|
||||
// Cached data for drawing surfaces
|
||||
struct GeometryInstanceSurfaceDataCache {
|
||||
enum {
|
||||
FLAG_PASS_DEPTH = 1,
|
||||
FLAG_PASS_OPAQUE = 2,
|
||||
FLAG_PASS_ALPHA = 4,
|
||||
FLAG_PASS_SHADOW = 8,
|
||||
FLAG_USES_SHARED_SHADOW_MATERIAL = 128,
|
||||
FLAG_USES_SUBSURFACE_SCATTERING = 2048,
|
||||
FLAG_USES_SCREEN_TEXTURE = 4096,
|
||||
FLAG_USES_DEPTH_TEXTURE = 8192,
|
||||
FLAG_USES_NORMAL_TEXTURE = 16384,
|
||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768,
|
||||
FLAG_USES_PARTICLE_TRAILS = 65536,
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
// !BAS! CHECK BITS!!!
|
||||
|
||||
uint64_t surface_index : 10;
|
||||
uint64_t geometry_id : 32;
|
||||
uint64_t material_id_low : 16;
|
||||
|
||||
uint64_t material_id_hi : 16;
|
||||
uint64_t shader_id : 32;
|
||||
uint64_t uses_lightmap : 4; // sort by lightmap id here, not whether its yes/no (is 4 bits enough?)
|
||||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
|
||||
// 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;
|
||||
uint32_t flags = 0;
|
||||
uint32_t surface_index = 0;
|
||||
uint32_t lod_index = 0;
|
||||
|
||||
void *surface = nullptr;
|
||||
RID material_uniform_set;
|
||||
SceneShaderForwardMobile::ShaderData *shader = nullptr;
|
||||
|
||||
void *surface_shadow = nullptr;
|
||||
RID material_uniform_set_shadow;
|
||||
SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr;
|
||||
|
||||
GeometryInstanceSurfaceDataCache *next = nullptr;
|
||||
GeometryInstanceForwardMobile *owner = nullptr;
|
||||
};
|
||||
|
||||
// !BAS! GeometryInstanceForwardClustered and GeometryInstanceForwardMobile will likely have a lot of overlap
|
||||
// may need to think about making this its own class like GeometryInstanceRD?
|
||||
|
||||
struct GeometryInstanceForwardMobile : public GeometryInstance {
|
||||
// setup
|
||||
uint32_t base_flags = 0;
|
||||
uint32_t flags_cache = 0;
|
||||
|
||||
// this structure maps to our push constant in our shader and is populated right before our draw call
|
||||
struct PushConstant {
|
||||
float transform[16];
|
||||
uint32_t flags;
|
||||
uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables
|
||||
uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index)
|
||||
uint32_t layer_mask = 1;
|
||||
float lightmap_uv_scale[4]; // doubles as uv_offset when needed
|
||||
uint32_t reflection_probes[2]; // packed reflection probes
|
||||
uint32_t omni_lights[2]; // packed omni lights
|
||||
uint32_t spot_lights[2]; // packed spot lights
|
||||
uint32_t decals[2]; // packed spot lights
|
||||
};
|
||||
|
||||
// PushConstant push_constant; // we populate this from our instance data
|
||||
|
||||
//used during rendering
|
||||
uint32_t layer_mask = 1;
|
||||
RID transforms_uniform_set;
|
||||
float depth = 0;
|
||||
bool mirror = false;
|
||||
Transform transform;
|
||||
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
|
||||
bool non_uniform_scale = false;
|
||||
AABB transformed_aabb; //needed for LOD
|
||||
float lod_bias = 0.0;
|
||||
float lod_model_scale = 1.0;
|
||||
int32_t shader_parameters_offset = -1;
|
||||
uint32_t instance_count = 0;
|
||||
uint32_t trail_steps = 1;
|
||||
RID mesh_instance;
|
||||
|
||||
// lightmap
|
||||
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
|
||||
uint32_t lightmap_slice_index;
|
||||
Rect2 lightmap_uv_scale;
|
||||
RID lightmap_instance;
|
||||
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
|
||||
|
||||
// culled light info
|
||||
uint32_t reflection_probe_count;
|
||||
RID reflection_probes[MAX_RDL_CULL];
|
||||
uint32_t omni_light_count;
|
||||
RID omni_lights[MAX_RDL_CULL];
|
||||
uint32_t spot_light_count;
|
||||
RID spot_lights[MAX_RDL_CULL];
|
||||
uint32_t decals_count;
|
||||
RID decals[MAX_RDL_CULL];
|
||||
|
||||
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
|
||||
|
||||
// do we use this?
|
||||
SelfList<GeometryInstanceForwardMobile> dirty_list_element;
|
||||
|
||||
struct Data {
|
||||
//data used less often goes into regular heap
|
||||
RID base;
|
||||
RS::InstanceType base_type;
|
||||
|
||||
RID skeleton;
|
||||
Vector<RID> surface_materials;
|
||||
RID material_override;
|
||||
AABB aabb;
|
||||
|
||||
bool use_baked_light = false;
|
||||
bool cast_double_sided_shadows = false;
|
||||
// bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct
|
||||
|
||||
bool dirty_dependencies = false;
|
||||
|
||||
RendererStorage::DependencyTracker dependency_tracker;
|
||||
};
|
||||
|
||||
Data *data = nullptr;
|
||||
|
||||
GeometryInstanceForwardMobile() :
|
||||
dirty_list_element(this) {}
|
||||
};
|
||||
|
||||
public:
|
||||
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
|
||||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
|
||||
|
||||
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
|
||||
|
||||
PagedAllocator<GeometryInstanceForwardMobile> geometry_instance_alloc;
|
||||
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
|
||||
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
|
||||
|
||||
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(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
|
||||
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
|
||||
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
|
||||
void _update_dirty_geometry_instances();
|
||||
|
||||
virtual GeometryInstance *geometry_instance_create(RID p_base);
|
||||
virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton);
|
||||
virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override);
|
||||
virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials);
|
||||
virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance);
|
||||
virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb);
|
||||
virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask);
|
||||
virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias);
|
||||
virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable);
|
||||
virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable);
|
||||
virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index);
|
||||
virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9);
|
||||
virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset);
|
||||
virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable);
|
||||
|
||||
virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance);
|
||||
virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance);
|
||||
|
||||
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance);
|
||||
|
||||
virtual uint32_t geometry_instance_get_pair_mask();
|
||||
virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count);
|
||||
virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count);
|
||||
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count);
|
||||
virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count);
|
||||
|
||||
virtual bool free(RID p_rid);
|
||||
|
||||
virtual bool is_dynamic_gi_supported() const;
|
||||
virtual bool is_clustered_enabled() const;
|
||||
virtual bool is_volumetric_supported() const;
|
||||
virtual uint32_t get_max_elements() const;
|
||||
|
||||
RenderForwardMobile(RendererStorageRD *p_storage);
|
||||
~RenderForwardMobile();
|
||||
};
|
||||
} // namespace RendererSceneRenderImplementation
|
||||
#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
|
|
@ -0,0 +1,833 @@
|
|||
/*************************************************************************/
|
||||
/* scene_shader_forward_mobile.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "scene_shader_forward_mobile.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "render_forward_mobile.h"
|
||||
|
||||
using namespace RendererSceneRenderImplementation;
|
||||
|
||||
/* ShaderData */
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||
//compile
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
uses_screen_texture = false;
|
||||
|
||||
if (code == String()) {
|
||||
return; //just invalid, but no error
|
||||
}
|
||||
|
||||
ShaderCompilerRD::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;
|
||||
|
||||
uses_point_size = false;
|
||||
uses_alpha = false;
|
||||
uses_blend_alpha = false;
|
||||
uses_depth_pre_pass = false;
|
||||
uses_discard = false;
|
||||
uses_roughness = false;
|
||||
uses_normal = false;
|
||||
bool wireframe = false;
|
||||
|
||||
unshaded = false;
|
||||
uses_vertex = false;
|
||||
uses_sss = false;
|
||||
uses_transmittance = false;
|
||||
uses_screen_texture = false;
|
||||
uses_depth_texture = false;
|
||||
uses_normal_texture = false;
|
||||
uses_time = false;
|
||||
writes_modelview_or_projection = false;
|
||||
uses_world_coordinates = false;
|
||||
uses_particle_trails = false;
|
||||
|
||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||
|
||||
ShaderCompilerRD::IdentifierActions actions;
|
||||
actions.entry_point_stages["vertex"] = ShaderCompilerRD::STAGE_VERTEX;
|
||||
actions.entry_point_stages["fragment"] = ShaderCompilerRD::STAGE_FRAGMENT;
|
||||
actions.entry_point_stages["light"] = ShaderCompilerRD::STAGE_FRAGMENT;
|
||||
|
||||
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_mode, BLEND_MODE_ADD);
|
||||
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["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);
|
||||
|
||||
actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
|
||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
||||
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||
|
||||
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_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
|
||||
|
||||
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
|
||||
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
|
||||
|
||||
// actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
|
||||
// actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
|
||||
|
||||
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
|
||||
actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
|
||||
actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture;
|
||||
actions.usage_flag_pointers["DISCARD"] = &uses_discard;
|
||||
actions.usage_flag_pointers["TIME"] = &uses_time;
|
||||
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
|
||||
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
|
||||
actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
|
||||
|
||||
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
|
||||
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
|
||||
|
||||
actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
|
||||
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
|
||||
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
|
||||
Error err = shader_singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
|
||||
ERR_FAIL_COND(err != OK);
|
||||
|
||||
if (version.is_null()) {
|
||||
version = shader_singleton->shader.version_create();
|
||||
}
|
||||
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
depth_test = DepthTest(depth_testi);
|
||||
|
||||
#if 0
|
||||
print_line("**compiling shader:");
|
||||
print_line("**defines:\n");
|
||||
for (int i = 0; i < gen_code.defines.size(); i++) {
|
||||
print_line(gen_code.defines[i]);
|
||||
}
|
||||
|
||||
Map<String, String>::Element * el = gen_code.code.front();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key() + ":\n" + el->value());
|
||||
|
||||
el = el->next();
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
shader_singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompilerRD::STAGE_VERTEX], gen_code.stage_globals[ShaderCompilerRD::STAGE_FRAGMENT], gen_code.defines);
|
||||
ERR_FAIL_COND(!shader_singleton->shader.version_is_valid(version));
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
//blend modes
|
||||
|
||||
// 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_SUBTRACT;
|
||||
blend_attachment.color_blend_op = RD::BLEND_OP_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;
|
||||
}
|
||||
}
|
||||
|
||||
RD::PipelineColorBlendState blend_state_blend;
|
||||
blend_state_blend.attachments.push_back(blend_attachment);
|
||||
RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
|
||||
RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2);
|
||||
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_LESS_OR_EQUAL;
|
||||
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::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull];
|
||||
|
||||
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 < 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;
|
||||
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_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
depth_stencil.enable_depth_write = false; //alpha does not draw depth
|
||||
}
|
||||
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_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)
|
||||
}
|
||||
|
||||
/*
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
depth_stencil.enable_depth_write = false; //alpha does not draw depth
|
||||
}
|
||||
} else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) {
|
||||
if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_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 {
|
||||
blend_state = blend_state_opaque; //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_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (k == SHADER_VERSION_SHADOW_PASS || k == SHADER_VERSION_DEPTH_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 {
|
||||
// ???
|
||||
}
|
||||
|
||||
/*
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
|
||||
//none, leave empty
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
|
||||
blend_state = blend_state_depth_normal_roughness;
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE) {
|
||||
blend_state = blend_state_depth_normal_roughness_giprobe;
|
||||
} 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 if (k == SHADER_VERSION_DEPTH_PASS_WITH_SDF) {
|
||||
blend_state = RD::PipelineColorBlendState(); //no color targets for SDF
|
||||
} else {
|
||||
//specular write
|
||||
blend_state = blend_state_opaque_specular;
|
||||
depth_stencil.enable_depth_test = false;
|
||||
depth_stencil.enable_depth_write = false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) {
|
||||
if (!p_texture.is_valid()) {
|
||||
default_texture_params.erase(p_name);
|
||||
} else {
|
||||
default_texture_params[p_name] = p_texture;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
|
||||
Map<int, StringName> order;
|
||||
|
||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (E->get().texture_order >= 0) {
|
||||
order[E->get().texture_order + 100000] = E->key();
|
||||
} else {
|
||||
order[E->get().order] = E->key();
|
||||
}
|
||||
}
|
||||
|
||||
for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) {
|
||||
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]);
|
||||
pi.name = E->get();
|
||||
p_param_list->push_back(pi);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const {
|
||||
for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) {
|
||||
if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RendererStorage::InstanceShaderParam p;
|
||||
p.info = ShaderLanguage::uniform_to_property_info(E->get());
|
||||
p.info.name = E->key(); //supply name
|
||||
p.index = E->get().instance_index;
|
||||
p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().hint);
|
||||
p_param_list->push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_param_texture(const StringName &p_param) const {
|
||||
if (!uniforms.has(p_param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return uniforms[p_param].texture_order >= 0;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant SceneShaderForwardMobile::ShaderData::get_default_parameter(const StringName &p_parameter) const {
|
||||
if (uniforms.has(p_parameter)) {
|
||||
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
|
||||
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
|
||||
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint);
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
|
||||
return shader_singleton->shader.version_get_native_source_code(version);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::ShaderData() {
|
||||
valid = false;
|
||||
uses_screen_texture = false;
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::~ShaderData() {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
ERR_FAIL_COND(!shader_singleton);
|
||||
//pipeline variants will clear themselves if shader is gone
|
||||
if (version.is_valid()) {
|
||||
shader_singleton->shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
RendererStorageRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
|
||||
ShaderData *shader_data = memnew(ShaderData);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::MaterialData::set_render_priority(int p_priority) {
|
||||
priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
|
||||
next_pass = p_pass;
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
|
||||
|
||||
if ((uint32_t)ubo_data.size() != shader_data->ubo_size) {
|
||||
p_uniform_dirty = true;
|
||||
if (uniform_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(uniform_buffer);
|
||||
uniform_buffer = RID();
|
||||
}
|
||||
|
||||
ubo_data.resize(shader_data->ubo_size);
|
||||
if (ubo_data.size()) {
|
||||
uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size());
|
||||
memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear
|
||||
}
|
||||
|
||||
//clear previous uniform set
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
uniform_set = RID();
|
||||
}
|
||||
}
|
||||
|
||||
//check whether buffer changed
|
||||
if (p_uniform_dirty && ubo_data.size()) {
|
||||
update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false);
|
||||
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), RD::BARRIER_MASK_RASTER);
|
||||
}
|
||||
|
||||
uint32_t tex_uniform_count = shader_data->texture_uniforms.size();
|
||||
|
||||
if ((uint32_t)texture_cache.size() != tex_uniform_count) {
|
||||
texture_cache.resize(tex_uniform_count);
|
||||
p_textures_dirty = true;
|
||||
|
||||
//clear previous uniform set
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
uniform_set = RID();
|
||||
}
|
||||
}
|
||||
|
||||
if (p_textures_dirty && tex_uniform_count) {
|
||||
update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true);
|
||||
}
|
||||
|
||||
if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) {
|
||||
// This material does not require an uniform set, so don't create it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
//no reason to update uniform set, only UBO (or nothing) was needed to update
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
|
||||
{
|
||||
if (shader_data->ubo_size) {
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
|
||||
u.binding = 0;
|
||||
u.ids.push_back(uniform_buffer);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
|
||||
const RID *textures = texture_cache.ptrw();
|
||||
for (uint32_t i = 0; i < tex_uniform_count; i++) {
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = 1 + i;
|
||||
u.ids.push_back(textures[i]);
|
||||
uniforms.push_back(u);
|
||||
}
|
||||
}
|
||||
|
||||
uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::MaterialData::~MaterialData() {
|
||||
if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
|
||||
RD::get_singleton()->free(uniform_set);
|
||||
}
|
||||
|
||||
if (uniform_buffer.is_valid()) {
|
||||
RD::get_singleton()->free(uniform_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
RendererStorageRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
|
||||
MaterialData *material_data = memnew(MaterialData);
|
||||
material_data->shader_data = p_shader;
|
||||
material_data->last_frame = false;
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
/* Scene Shader */
|
||||
|
||||
SceneShaderForwardMobile *SceneShaderForwardMobile::singleton = nullptr;
|
||||
|
||||
SceneShaderForwardMobile::SceneShaderForwardMobile() {
|
||||
// there should be only one of these, contained within our RenderForwardMobile singleton.
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
|
||||
storage = p_storage;
|
||||
|
||||
/* 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"); // !BAS! 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_DEPTH_PASS_DP (maybe rename to 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
|
||||
shader.initialize(shader_versions, p_defines);
|
||||
}
|
||||
|
||||
storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs);
|
||||
storage->material_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_material_funcs);
|
||||
|
||||
{
|
||||
//shader compiler
|
||||
ShaderCompilerRD::DefaultIdentifierActions actions;
|
||||
|
||||
actions.renames["WORLD_MATRIX"] = "world_matrix";
|
||||
actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix";
|
||||
actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix";
|
||||
actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix";
|
||||
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
|
||||
actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix";
|
||||
actions.renames["MODELVIEW_MATRIX"] = "modelview";
|
||||
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
|
||||
|
||||
actions.renames["VERTEX"] = "vertex";
|
||||
actions.renames["NORMAL"] = "normal";
|
||||
actions.renames["TANGENT"] = "tangent";
|
||||
actions.renames["BINORMAL"] = "binormal";
|
||||
actions.renames["POSITION"] = "position";
|
||||
actions.renames["UV"] = "uv_interp";
|
||||
actions.renames["UV2"] = "uv2_interp";
|
||||
actions.renames["COLOR"] = "color_interp";
|
||||
actions.renames["POINT_SIZE"] = "gl_PointSize";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
|
||||
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale";
|
||||
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge";
|
||||
actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
|
||||
|
||||
//builtins
|
||||
|
||||
actions.renames["TIME"] = "scene_data.time";
|
||||
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
|
||||
actions.renames["NORMAL_MAP"] = "normal_map";
|
||||
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth";
|
||||
actions.renames["ALBEDO"] = "albedo";
|
||||
actions.renames["ALPHA"] = "alpha";
|
||||
actions.renames["METALLIC"] = "metallic";
|
||||
actions.renames["SPECULAR"] = "specular";
|
||||
actions.renames["ROUGHNESS"] = "roughness";
|
||||
actions.renames["RIM"] = "rim";
|
||||
actions.renames["RIM_TINT"] = "rim_tint";
|
||||
actions.renames["CLEARCOAT"] = "clearcoat";
|
||||
actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss";
|
||||
actions.renames["ANISOTROPY"] = "anisotropy";
|
||||
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow";
|
||||
actions.renames["SSS_STRENGTH"] = "sss_strength";
|
||||
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color";
|
||||
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth";
|
||||
actions.renames["SSS_TRANSMITTANCE_CURVE"] = "transmittance_curve";
|
||||
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost";
|
||||
actions.renames["BACKLIGHT"] = "backlight";
|
||||
actions.renames["AO"] = "ao";
|
||||
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
|
||||
actions.renames["EMISSION"] = "emission";
|
||||
actions.renames["POINT_COORD"] = "gl_PointCoord";
|
||||
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
|
||||
actions.renames["SCREEN_UV"] = "screen_uv";
|
||||
actions.renames["SCREEN_TEXTURE"] = "color_buffer";
|
||||
actions.renames["DEPTH_TEXTURE"] = "depth_buffer";
|
||||
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
|
||||
actions.renames["DEPTH"] = "gl_FragDepth";
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "true";
|
||||
actions.renames["FOG"] = "custom_fog";
|
||||
actions.renames["RADIANCE"] = "custom_radiance";
|
||||
actions.renames["IRRADIANCE"] = "custom_irradiance";
|
||||
actions.renames["BONE_INDICES"] = "bone_attrib";
|
||||
actions.renames["BONE_WEIGHTS"] = "weight_attrib";
|
||||
actions.renames["CUSTOM0"] = "custom0_attrib";
|
||||
actions.renames["CUSTOM1"] = "custom1_attrib";
|
||||
actions.renames["CUSTOM2"] = "custom2_attrib";
|
||||
actions.renames["CUSTOM3"] = "custom3_attrib";
|
||||
|
||||
//for light
|
||||
actions.renames["VIEW"] = "view";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color";
|
||||
actions.renames["LIGHT"] = "light";
|
||||
actions.renames["ATTENUATION"] = "attenuation";
|
||||
actions.renames["SHADOW_ATTENUATION"] = "shadow_attenuation";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light";
|
||||
|
||||
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
|
||||
actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n";
|
||||
actions.usage_defines["BINORMAL"] = "@TANGENT";
|
||||
actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n";
|
||||
actions.usage_defines["RIM_TINT"] = "@RIM";
|
||||
actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n";
|
||||
actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT";
|
||||
actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n";
|
||||
actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
|
||||
actions.usage_defines["AO"] = "#define AO_USED\n";
|
||||
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
|
||||
actions.usage_defines["UV"] = "#define UV_USED\n";
|
||||
actions.usage_defines["UV2"] = "#define UV2_USED\n";
|
||||
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";
|
||||
actions.usage_defines["BONE_WEIGHTS"] = "#define WEIGHTS_USED\n";
|
||||
actions.usage_defines["CUSTOM0"] = "#define CUSTOM0\n";
|
||||
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1\n";
|
||||
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2\n";
|
||||
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3\n";
|
||||
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
|
||||
actions.usage_defines["COLOR"] = "#define COLOR_USED\n";
|
||||
actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n";
|
||||
actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n";
|
||||
|
||||
actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n";
|
||||
actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n";
|
||||
actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n";
|
||||
actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE";
|
||||
|
||||
actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n";
|
||||
actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n";
|
||||
actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n";
|
||||
actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n";
|
||||
actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n";
|
||||
|
||||
actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
|
||||
actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n";
|
||||
|
||||
actions.usage_defines["FOG"] = "#define CUSTOM_FOG_USED\n";
|
||||
actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n";
|
||||
actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n";
|
||||
|
||||
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
|
||||
actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
|
||||
actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
|
||||
actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n";
|
||||
actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n";
|
||||
actions.render_mode_defines["particle_trails"] = "#define USE_PARTICLE_TRAILS\n";
|
||||
|
||||
bool force_lambert = GLOBAL_GET("rendering/shading/overrides/force_lambert_over_burley");
|
||||
if (!force_lambert) {
|
||||
actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n";
|
||||
}
|
||||
|
||||
actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n";
|
||||
actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n";
|
||||
actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n";
|
||||
|
||||
actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";
|
||||
|
||||
bool force_blinn = GLOBAL_GET("rendering/shading/overrides/force_blinn_over_ggx");
|
||||
if (!force_blinn) {
|
||||
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
|
||||
} else {
|
||||
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n";
|
||||
}
|
||||
|
||||
actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n";
|
||||
actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n";
|
||||
actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
|
||||
actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
|
||||
actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
|
||||
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";
|
||||
|
||||
actions.sampler_array_name = "material_samplers";
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 10;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
actions.global_buffer_array_variable = "global_variables.data";
|
||||
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
|
||||
|
||||
compiler.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
//default material and shader
|
||||
default_shader = storage->shader_allocate();
|
||||
storage->shader_initialize(default_shader);
|
||||
storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n");
|
||||
default_material = storage->material_allocate();
|
||||
storage->material_initialize(default_material);
|
||||
storage->material_set_shader(default_material, default_shader);
|
||||
|
||||
MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);
|
||||
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
|
||||
}
|
||||
|
||||
{
|
||||
overdraw_material_shader = storage->shader_allocate();
|
||||
storage->shader_initialize(overdraw_material_shader);
|
||||
storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }");
|
||||
overdraw_material = storage->material_allocate();
|
||||
storage->material_initialize(overdraw_material);
|
||||
storage->material_set_shader(overdraw_material, overdraw_material_shader);
|
||||
|
||||
wireframe_material_shader = storage->shader_allocate();
|
||||
storage->shader_initialize(wireframe_material_shader);
|
||||
storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }");
|
||||
wireframe_material = storage->material_allocate();
|
||||
storage->material_initialize(wireframe_material);
|
||||
storage->material_set_shader(wireframe_material, wireframe_material_shader);
|
||||
}
|
||||
|
||||
{
|
||||
default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256);
|
||||
Vector<RD::Uniform> uniforms;
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
|
||||
u.ids.push_back(default_vec4_xform_buffer);
|
||||
u.binding = 0;
|
||||
uniforms.push_back(u);
|
||||
|
||||
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_LESS;
|
||||
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
|
||||
RD::get_singleton()->free(default_vec4_xform_buffer);
|
||||
RD::get_singleton()->free(shadow_sampler);
|
||||
|
||||
storage->free(wireframe_material_shader);
|
||||
storage->free(overdraw_material_shader);
|
||||
storage->free(default_shader);
|
||||
|
||||
storage->free(wireframe_material);
|
||||
storage->free(overdraw_material);
|
||||
storage->free(default_material);
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*************************************************************************/
|
||||
/* scene_shader_forward_mobile.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef RSSR_SCENE_SHADER_FM_H
|
||||
#define RSSR_SCENE_SHADER_FM_H
|
||||
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h"
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class SceneShaderForwardMobile {
|
||||
private:
|
||||
static SceneShaderForwardMobile *singleton;
|
||||
RendererStorageRD *storage;
|
||||
|
||||
public:
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
|
||||
SHADER_VERSION_SHADOW_PASS,
|
||||
SHADER_VERSION_DEPTH_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererStorageRD::ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_ALPHA_TO_COVERAGE
|
||||
};
|
||||
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
DEPTH_DRAW_ALWAYS
|
||||
};
|
||||
|
||||
enum DepthTest {
|
||||
DEPTH_TEST_DISABLED,
|
||||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum CullVariant {
|
||||
CULL_VARIANT_NORMAL,
|
||||
CULL_VARIANT_REVERSED,
|
||||
CULL_VARIANT_DOUBLE_SIDED,
|
||||
CULL_VARIANT_MAX
|
||||
|
||||
};
|
||||
|
||||
enum AlphaAntiAliasing {
|
||||
ALPHA_ANTIALIASING_OFF,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
uint32_t vertex_input_mask;
|
||||
PipelineCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX];
|
||||
|
||||
String path;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
|
||||
Vector<ShaderCompilerRD::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
Map<StringName, RID> default_texture_params;
|
||||
|
||||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
|
||||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
bool uses_blend_alpha;
|
||||
bool uses_alpha_clip;
|
||||
bool uses_depth_pre_pass;
|
||||
bool uses_discard;
|
||||
bool uses_roughness;
|
||||
bool uses_normal;
|
||||
bool uses_particle_trails;
|
||||
|
||||
bool unshaded;
|
||||
bool uses_vertex;
|
||||
bool uses_sss;
|
||||
bool uses_transmittance;
|
||||
bool uses_screen_texture;
|
||||
bool uses_depth_texture;
|
||||
bool uses_normal_texture;
|
||||
bool uses_time;
|
||||
bool writes_modelview_or_projection;
|
||||
bool uses_world_coordinates;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture);
|
||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||
void get_instance_param_list(List<RendererStorage::InstanceShaderParam> *p_param_list) const;
|
||||
|
||||
virtual bool is_param_texture(const StringName &p_param) const;
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual Variant get_default_parameter(const StringName &p_parameter) const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
|
||||
ShaderData();
|
||||
virtual ~ShaderData();
|
||||
};
|
||||
|
||||
RendererStorageRD::ShaderData *_create_shader_func();
|
||||
static RendererStorageRD::ShaderData *_create_shader_funcs() {
|
||||
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
|
||||
}
|
||||
|
||||
struct MaterialData : public RendererStorageRD::MaterialData {
|
||||
uint64_t last_frame;
|
||||
ShaderData *shader_data;
|
||||
RID uniform_buffer;
|
||||
RID uniform_set;
|
||||
Vector<RID> texture_cache;
|
||||
Vector<uint8_t> ubo_data;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
RID next_pass;
|
||||
uint8_t priority;
|
||||
virtual void set_render_priority(int p_priority);
|
||||
virtual void set_next_pass(RID p_pass);
|
||||
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual ~MaterialData();
|
||||
};
|
||||
|
||||
RendererStorageRD::MaterialData *_create_material_func(ShaderData *p_shader);
|
||||
static RendererStorageRD::MaterialData *_create_material_funcs(RendererStorageRD::ShaderData *p_shader) {
|
||||
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
|
||||
}
|
||||
|
||||
SceneForwardMobileShaderRD shader;
|
||||
ShaderCompilerRD compiler;
|
||||
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
RID overdraw_material_shader;
|
||||
RID overdraw_material;
|
||||
RID wireframe_material_shader;
|
||||
RID wireframe_material;
|
||||
RID default_shader_rd;
|
||||
|
||||
RID default_vec4_xform_buffer;
|
||||
RID default_vec4_xform_uniform_set;
|
||||
|
||||
RID shadow_sampler;
|
||||
|
||||
SceneShaderForwardMobile();
|
||||
~SceneShaderForwardMobile();
|
||||
|
||||
void init(RendererStorageRD *p_storage, const String p_defines);
|
||||
};
|
||||
|
||||
} // namespace RendererSceneRenderImplementation
|
||||
#endif // !RSSR_SCENE_SHADER_FM_H
|
|
@ -175,5 +175,14 @@ RendererCompositorRD::RendererCompositorRD() {
|
|||
|
||||
storage = memnew(RendererStorageRD);
|
||||
canvas = memnew(RendererCanvasRenderRD(storage));
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
|
||||
|
||||
uint32_t back_end = GLOBAL_GET("rendering/vulkan/rendering/back_end");
|
||||
uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
|
||||
|
||||
if (back_end == 1 || textures_per_stage < 48) {
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
|
||||
} else { // back_end == 0
|
||||
// default to our high end renderer
|
||||
scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "core/templates/thread_work_pool.h"
|
||||
#include "servers/rendering/renderer_compositor.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/renderer_canvas_render_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
|
||||
|
||||
|
|
|
@ -3144,8 +3144,6 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_
|
|||
rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
rb->gi.using_half_size_gi = half_resolution;
|
||||
|
||||
p_scene_render->_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
PushConstant push_constant;
|
||||
|
|
|
@ -58,8 +58,6 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
|
|||
rb->sdfgi->erase();
|
||||
memdelete(rb->sdfgi);
|
||||
rb->sdfgi = nullptr;
|
||||
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -78,8 +76,6 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
|
|||
if (sdfgi == nullptr) {
|
||||
// re-create
|
||||
rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size);
|
||||
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
} else {
|
||||
//check for updates
|
||||
rb->sdfgi->update(env, p_world_position);
|
||||
|
@ -1533,7 +1529,6 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri
|
|||
|
||||
if (rb->blur[0].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
storage->get_effects()->sub_surface_scattering(rb->texture, rb->blur[0].mipmaps[0].texture, rb->depth_texture, p_camera, Size2i(rb->width, rb->height), sss_scale, sss_depth_scale, sss_quality);
|
||||
|
@ -1585,7 +1580,6 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb
|
|||
|
||||
if (rb->blur[0].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
storage->get_effects()->screen_space_reflection(rb->texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].mipmaps[1].texture, rb->blur[1].mipmaps[0].texture, Size2i(rb->width / 2, rb->height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
|
||||
|
@ -1711,7 +1705,6 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen
|
|||
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
rb->ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
RD::get_singleton()->set_resource_name(rb->ssao.ao_final, "SSAO Final");
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
ssao_using_half_size = ssao_half_size;
|
||||
uniform_sets_are_invalid = true;
|
||||
|
@ -1751,7 +1744,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_rende
|
|||
if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
|
||||
if (rb->blur[0].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
float bokeh_size = camfx->dof_blur_amount * 64.0;
|
||||
|
@ -1761,7 +1753,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_rende
|
|||
if (can_use_effects && env && env->auto_exposure) {
|
||||
if (rb->luminance.current.is_null()) {
|
||||
_allocate_luminance_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version;
|
||||
|
@ -1782,7 +1773,6 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(RID p_rende
|
|||
|
||||
if (rb->blur[1].texture.is_null()) {
|
||||
_allocate_blur_textures(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
|
||||
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
|
||||
|
@ -2177,7 +2167,6 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p
|
|||
}
|
||||
|
||||
rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
|
||||
if (is_clustered_enabled()) {
|
||||
rb->cluster_builder->setup(Size2i(p_width, p_height), max_cluster_elements, rb->depth_texture, storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->texture);
|
||||
|
@ -2329,6 +2318,8 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
|
|||
|
||||
Vector3 extents = storage->reflection_probe_get_extents(base_probe);
|
||||
|
||||
rpi->cull_mask = storage->reflection_probe_get_cull_mask(base_probe);
|
||||
|
||||
reflection_ubo.box_extents[0] = extents.x;
|
||||
reflection_ubo.box_extents[1] = extents.y;
|
||||
reflection_ubo.box_extents[2] = extents.z;
|
||||
|
@ -2357,7 +2348,9 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
|
|||
Transform proj = (p_camera_inverse_transform * transform).inverse();
|
||||
RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix);
|
||||
|
||||
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents);
|
||||
if (current_cluster_builder != nullptr) {
|
||||
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents);
|
||||
}
|
||||
|
||||
rpi->last_pass = RSG::rasterizer->get_frame_number();
|
||||
}
|
||||
|
@ -2747,8 +2740,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
|||
}
|
||||
|
||||
li->light_index = index;
|
||||
li->cull_mask = storage->light_get_cull_mask(base);
|
||||
|
||||
current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
|
||||
if (current_cluster_builder != nullptr) {
|
||||
current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
|
||||
}
|
||||
|
||||
r_positional_light_count++;
|
||||
}
|
||||
|
@ -2816,6 +2812,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
|
|||
DecalInstance *di = cluster.decal_sort[i].instance;
|
||||
RID decal = di->decal;
|
||||
|
||||
di->render_index = i;
|
||||
di->cull_mask = storage->decal_get_cull_mask(decal);
|
||||
|
||||
Transform xform = di->transform;
|
||||
float fade = 1.0;
|
||||
|
||||
|
@ -2920,7 +2919,9 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
|
|||
dd.upper_fade = storage->decal_get_upper_fade(decal);
|
||||
dd.lower_fade = storage->decal_get_lower_fade(decal);
|
||||
|
||||
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
|
||||
if (current_cluster_builder != nullptr) {
|
||||
current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster.decal_count > 0) {
|
||||
|
@ -2928,6 +2929,116 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_fill_instance_indices(const RID *p_omni_light_instances, uint32_t p_omni_light_instance_count, uint32_t *p_omni_light_indices, const RID *p_spot_light_instances, uint32_t p_spot_light_instance_count, uint32_t *p_spot_light_indices, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count, uint32_t *p_reflection_probe_indices, const RID *p_decal_instances, uint32_t p_decal_instance_count, uint32_t *p_decal_instance_indices, uint32_t p_layer_mask, uint32_t p_max_dst_words) {
|
||||
// first zero out our indices
|
||||
for (uint32_t i = 0; i < p_max_dst_words; i++) {
|
||||
p_omni_light_indices[i] = 0;
|
||||
p_spot_light_indices[i] = 0;
|
||||
p_reflection_probe_indices[i] = 0;
|
||||
p_decal_instance_indices[i] = 0;
|
||||
}
|
||||
|
||||
{
|
||||
// process omni lights
|
||||
uint32_t dword = 0;
|
||||
uint32_t shift = 0;
|
||||
|
||||
for (uint32_t i = 0; i < p_omni_light_instance_count && dword < p_max_dst_words; i++) {
|
||||
LightInstance *li = light_instance_owner.getornull(p_omni_light_instances[i]);
|
||||
|
||||
if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) {
|
||||
p_omni_light_indices[dword] += li->light_index << shift;
|
||||
if (shift == 24) {
|
||||
dword++;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dword < 2) {
|
||||
// put in ending mark
|
||||
p_omni_light_indices[dword] += 0xFF << shift;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// process spot lights
|
||||
uint32_t dword = 0;
|
||||
uint32_t shift = 0;
|
||||
|
||||
for (uint32_t i = 0; i < p_spot_light_instance_count && dword < p_max_dst_words; i++) {
|
||||
LightInstance *li = light_instance_owner.getornull(p_spot_light_instances[i]);
|
||||
|
||||
if ((li->cull_mask & p_layer_mask) && (li->light_index < 255)) {
|
||||
p_spot_light_indices[dword] += li->light_index << shift;
|
||||
if (shift == 24) {
|
||||
dword++;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dword < 2) {
|
||||
// put in ending mark
|
||||
p_spot_light_indices[dword] += 0xFF << shift;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// process reflection probes
|
||||
uint32_t dword = 0;
|
||||
uint32_t shift = 0;
|
||||
|
||||
for (uint32_t i = 0; i < p_reflection_probe_instance_count && dword < p_max_dst_words; i++) {
|
||||
ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_reflection_probe_instances[i]);
|
||||
|
||||
if ((rpi->cull_mask & p_layer_mask) && (rpi->render_index < 255)) {
|
||||
p_reflection_probe_indices[dword] += rpi->render_index << shift;
|
||||
if (shift == 24) {
|
||||
dword++;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dword < 2) {
|
||||
// put in ending mark
|
||||
p_reflection_probe_indices[dword] += 0xFF << shift;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// process decals
|
||||
uint32_t dword = 0;
|
||||
uint32_t shift = 0;
|
||||
|
||||
for (uint32_t i = 0; i < p_decal_instance_count && dword < p_max_dst_words; i++) {
|
||||
DecalInstance *decal = decal_instance_owner.getornull(p_decal_instances[i]);
|
||||
|
||||
if ((decal->cull_mask & p_layer_mask) && (decal->render_index < 255)) {
|
||||
p_decal_instance_indices[dword] += decal->render_index << shift;
|
||||
if (shift == 24) {
|
||||
dword++;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dword < 2) {
|
||||
// put in ending mark
|
||||
p_decal_instance_indices[dword] += 0xFF << shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
|
||||
ERR_FAIL_COND(!rb->volumetric_fog);
|
||||
|
||||
|
@ -2967,7 +3078,6 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
|
|||
//validate
|
||||
if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) {
|
||||
_volumetric_fog_erase(rb);
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3003,7 +3113,6 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
|
|||
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
|
||||
rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
|
||||
_render_buffers_uniform_set_changed(p_render_buffers);
|
||||
|
||||
Vector<RD::Uniform> uniforms;
|
||||
{
|
||||
|
@ -3528,7 +3637,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
RenderBuffers *rb = nullptr;
|
||||
if (p_render_buffers.is_valid()) {
|
||||
rb = render_buffers_owner.getornull(p_render_buffers);
|
||||
ERR_FAIL_COND(!rb); // !BAS! Do we fail here or skip the parts that won't work. can't really see a case why we would be rendering without buffers....
|
||||
ERR_FAIL_COND(!rb);
|
||||
}
|
||||
|
||||
//assign render data
|
||||
|
@ -3584,10 +3693,12 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
}
|
||||
|
||||
//assign render indices to giprobes
|
||||
for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
|
||||
RendererSceneGIRD::GIProbeInstance *giprobe_inst = gi.gi_probe_instance_owner.getornull(p_gi_probes[i]);
|
||||
if (giprobe_inst) {
|
||||
giprobe_inst->render_index = i;
|
||||
if (is_dynamic_gi_supported()) {
|
||||
for (uint32_t i = 0; i < (uint32_t)p_gi_probes.size(); i++) {
|
||||
RendererSceneGIRD::GIProbeInstance *giprobe_inst = gi.gi_probe_instance_owner.getornull(p_gi_probes[i]);
|
||||
if (giprobe_inst) {
|
||||
giprobe_inst->render_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3623,7 +3734,11 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
|
||||
render_state.depth_prepass_used = false;
|
||||
//calls _pre_opaque_render between depth pre-pass and opaque pass
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
|
||||
if (current_cluster_builder != nullptr) {
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, current_cluster_builder->get_cluster_buffer(), current_cluster_builder->get_cluster_size(), current_cluster_builder->get_max_cluster_elements(), p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
|
||||
} else {
|
||||
_render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, *render_state.gi_probes, p_lightmaps, p_environment, RID(), 0, 0, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color, p_screen_lod_threshold);
|
||||
}
|
||||
|
||||
if (p_render_buffers.is_valid()) {
|
||||
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || debug_draw == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
|
||||
|
@ -3644,7 +3759,9 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &
|
|||
default: {
|
||||
}
|
||||
}
|
||||
current_cluster_builder->debug(elem_type);
|
||||
if (current_cluster_builder != nullptr) {
|
||||
current_cluster_builder->debug(elem_type);
|
||||
}
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP("Tonemap");
|
||||
|
@ -4105,8 +4222,12 @@ bool RendererSceneRenderRD::is_volumetric_supported() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
uint32_t RendererSceneRenderRD::get_max_elements() const {
|
||||
return GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements");
|
||||
}
|
||||
|
||||
RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
|
||||
max_cluster_elements = GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements");
|
||||
max_cluster_elements = get_max_elements();
|
||||
|
||||
storage = p_storage;
|
||||
singleton = this;
|
||||
|
|
|
@ -79,7 +79,6 @@ protected:
|
|||
RenderBufferData *render_buffers_get_data(RID p_render_buffers);
|
||||
|
||||
virtual void _base_uniforms_changed() = 0;
|
||||
virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0;
|
||||
virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
|
||||
|
||||
void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
|
||||
|
@ -150,6 +149,7 @@ private:
|
|||
uint32_t render_step = 0;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t render_index = 0;
|
||||
uint32_t cull_mask = 0;
|
||||
|
||||
Transform transform;
|
||||
};
|
||||
|
@ -161,6 +161,8 @@ private:
|
|||
struct DecalInstance {
|
||||
RID decal;
|
||||
Transform transform;
|
||||
uint32_t render_index;
|
||||
uint32_t cull_mask;
|
||||
};
|
||||
|
||||
mutable RID_Owner<DecalInstance> decal_instance_owner;
|
||||
|
@ -305,6 +307,7 @@ private:
|
|||
uint64_t last_scene_shadow_pass = 0;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t light_index = 0;
|
||||
uint32_t cull_mask = 0;
|
||||
uint32_t light_directional_index = 0;
|
||||
|
||||
uint32_t current_shadow_atlas_key = 0;
|
||||
|
@ -449,6 +452,8 @@ private:
|
|||
struct Cluster {
|
||||
/* Scene State UBO */
|
||||
|
||||
// !BAS! Most data here is not just used by our clustering logic but also by other lighting implementations. Maybe rename this struct to something more appropriate
|
||||
|
||||
enum {
|
||||
REFLECTION_AMBIENT_DISABLED = 0,
|
||||
REFLECTION_AMBIENT_ENVIRONMENT = 1,
|
||||
|
@ -1085,6 +1090,8 @@ public:
|
|||
return li->transform;
|
||||
}
|
||||
|
||||
void _fill_instance_indices(const RID *p_omni_light_instances, uint32_t p_omni_light_instance_count, uint32_t *p_omni_light_indices, const RID *p_spot_light_instances, uint32_t p_spot_light_instance_count, uint32_t *p_spot_light_indices, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count, uint32_t *p_reflection_probe_indices, const RID *p_decal_instances, uint32_t p_decal_instance_count, uint32_t *p_decal_instance_indices, uint32_t p_layer_mask, uint32_t p_max_dst_words = 2);
|
||||
|
||||
/* gi light probes */
|
||||
|
||||
RID gi_probe_instance_create(RID p_base);
|
||||
|
@ -1192,6 +1199,7 @@ public:
|
|||
virtual bool is_dynamic_gi_supported() const;
|
||||
virtual bool is_clustered_enabled() const;
|
||||
virtual bool is_volumetric_supported() const;
|
||||
virtual uint32_t get_max_elements() const;
|
||||
|
||||
RendererSceneRenderRD(RendererStorageRD *p_storage);
|
||||
~RendererSceneRenderRD();
|
||||
|
|
|
@ -1,105 +1,3 @@
|
|||
|
||||
#define CLUSTER_COUNTER_SHIFT 20
|
||||
#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1)
|
||||
#define CLUSTER_COUNTER_MASK 0xfff
|
||||
|
||||
struct LightData { //this structure needs to be as packed as possible
|
||||
vec3 position;
|
||||
float inv_radius;
|
||||
|
||||
vec3 direction;
|
||||
float size;
|
||||
|
||||
vec3 color;
|
||||
float attenuation;
|
||||
|
||||
float cone_attenuation;
|
||||
float cone_angle;
|
||||
float specular_amount;
|
||||
bool shadow_enabled;
|
||||
|
||||
vec4 atlas_rect; // rect in the shadow atlas
|
||||
mat4 shadow_matrix;
|
||||
float shadow_bias;
|
||||
float shadow_normal_bias;
|
||||
float transmittance_bias;
|
||||
float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
|
||||
float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
|
||||
uint mask;
|
||||
float shadow_volumetric_fog_fade;
|
||||
uint pad;
|
||||
vec4 projector_rect; //projector rect in srgb decal atlas
|
||||
};
|
||||
|
||||
#define REFLECTION_AMBIENT_DISABLED 0
|
||||
#define REFLECTION_AMBIENT_ENVIRONMENT 1
|
||||
#define REFLECTION_AMBIENT_COLOR 2
|
||||
|
||||
struct ReflectionData {
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
vec3 ambient; // ambient color
|
||||
float intensity;
|
||||
bool exterior;
|
||||
bool box_project;
|
||||
uint ambient_mode;
|
||||
uint pad;
|
||||
//0-8 is intensity,8-9 is ambient, mode
|
||||
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
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec3 direction;
|
||||
float energy;
|
||||
vec3 color;
|
||||
float size;
|
||||
float specular;
|
||||
uint mask;
|
||||
float softshadow_angle;
|
||||
float soft_shadow_scale;
|
||||
bool blend_splits;
|
||||
bool shadow_enabled;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
uvec3 pad;
|
||||
float shadow_volumetric_fog_fade;
|
||||
vec4 shadow_bias;
|
||||
vec4 shadow_normal_bias;
|
||||
vec4 shadow_transmittance_bias;
|
||||
vec4 shadow_z_range;
|
||||
vec4 shadow_range_begin;
|
||||
vec4 shadow_split_offsets;
|
||||
mat4 shadow_matrix1;
|
||||
mat4 shadow_matrix2;
|
||||
mat4 shadow_matrix3;
|
||||
mat4 shadow_matrix4;
|
||||
vec4 shadow_color1;
|
||||
vec4 shadow_color2;
|
||||
vec4 shadow_color3;
|
||||
vec4 shadow_color4;
|
||||
vec2 uv_scale1;
|
||||
vec2 uv_scale2;
|
||||
vec2 uv_scale3;
|
||||
vec2 uv_scale4;
|
||||
};
|
||||
|
||||
struct DecalData {
|
||||
mat4 xform; //to decal transform
|
||||
vec3 inv_extents;
|
||||
float albedo_mix;
|
||||
vec4 albedo_rect;
|
||||
vec4 normal_rect;
|
||||
vec4 orm_rect;
|
||||
vec4 emission_rect;
|
||||
vec4 modulate;
|
||||
float emission_energy;
|
||||
uint mask;
|
||||
float upper_fade;
|
||||
float lower_fade;
|
||||
mat3x4 normal_xform;
|
||||
vec3 normal;
|
||||
float normal_fade;
|
||||
};
|
||||
|
|
18
servers/rendering/renderer_rd/shaders/decal_data_inc.glsl
Normal file
18
servers/rendering/renderer_rd/shaders/decal_data_inc.glsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
struct DecalData {
|
||||
mat4 xform; //to decal transform
|
||||
vec3 inv_extents;
|
||||
float albedo_mix;
|
||||
vec4 albedo_rect;
|
||||
vec4 normal_rect;
|
||||
vec4 orm_rect;
|
||||
vec4 emission_rect;
|
||||
vec4 modulate;
|
||||
float emission_energy;
|
||||
uint mask;
|
||||
float upper_fade;
|
||||
float lower_fade;
|
||||
mat3x4 normal_xform;
|
||||
vec3 normal;
|
||||
float normal_fade;
|
||||
};
|
83
servers/rendering/renderer_rd/shaders/light_data_inc.glsl
Normal file
83
servers/rendering/renderer_rd/shaders/light_data_inc.glsl
Normal file
|
@ -0,0 +1,83 @@
|
|||
|
||||
struct LightData { //this structure needs to be as packed as possible
|
||||
vec3 position;
|
||||
float inv_radius;
|
||||
|
||||
vec3 direction;
|
||||
float size;
|
||||
|
||||
vec3 color;
|
||||
float attenuation;
|
||||
|
||||
float cone_attenuation;
|
||||
float cone_angle;
|
||||
float specular_amount;
|
||||
bool shadow_enabled;
|
||||
|
||||
vec4 atlas_rect; // rect in the shadow atlas
|
||||
mat4 shadow_matrix;
|
||||
float shadow_bias;
|
||||
float shadow_normal_bias;
|
||||
float transmittance_bias;
|
||||
float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
|
||||
float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
|
||||
uint mask;
|
||||
float shadow_volumetric_fog_fade;
|
||||
uint pad;
|
||||
vec4 projector_rect; //projector rect in srgb decal atlas
|
||||
};
|
||||
|
||||
#define REFLECTION_AMBIENT_DISABLED 0
|
||||
#define REFLECTION_AMBIENT_ENVIRONMENT 1
|
||||
#define REFLECTION_AMBIENT_COLOR 2
|
||||
|
||||
struct ReflectionData {
|
||||
vec3 box_extents;
|
||||
float index;
|
||||
vec3 box_offset;
|
||||
uint mask;
|
||||
vec3 ambient; // ambient color
|
||||
float intensity;
|
||||
bool exterior;
|
||||
bool box_project;
|
||||
uint ambient_mode;
|
||||
uint pad;
|
||||
//0-8 is intensity,8-9 is ambient, mode
|
||||
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
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec3 direction;
|
||||
float energy;
|
||||
vec3 color;
|
||||
float size;
|
||||
float specular;
|
||||
uint mask;
|
||||
float softshadow_angle;
|
||||
float soft_shadow_scale;
|
||||
bool blend_splits;
|
||||
bool shadow_enabled;
|
||||
float fade_from;
|
||||
float fade_to;
|
||||
uvec3 pad;
|
||||
float shadow_volumetric_fog_fade;
|
||||
vec4 shadow_bias;
|
||||
vec4 shadow_normal_bias;
|
||||
vec4 shadow_transmittance_bias;
|
||||
vec4 shadow_z_range;
|
||||
vec4 shadow_range_begin;
|
||||
vec4 shadow_split_offsets;
|
||||
mat4 shadow_matrix1;
|
||||
mat4 shadow_matrix2;
|
||||
mat4 shadow_matrix3;
|
||||
mat4 shadow_matrix4;
|
||||
vec4 shadow_color1;
|
||||
vec4 shadow_color2;
|
||||
vec4 shadow_color3;
|
||||
vec4 shadow_color4;
|
||||
vec2 uv_scale1;
|
||||
vec2 uv_scale2;
|
||||
vec2 uv_scale3;
|
||||
vec2 uv_scale4;
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
#ifdef ALPHA_HASH_USED
|
||||
|
||||
float hash_2d(vec2 p) {
|
||||
return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) *
|
||||
(0.1 + abs(sin(13.0 * p.y + p.x))));
|
||||
}
|
||||
|
||||
float hash_3d(vec3 p) {
|
||||
return hash_2d(vec2(hash_2d(p.xy), p.z));
|
||||
}
|
||||
|
||||
float compute_alpha_hash_threshold(vec3 pos, float hash_scale) {
|
||||
vec3 dx = dFdx(pos);
|
||||
vec3 dy = dFdx(pos);
|
||||
float delta_max_sqr = max(length(dx), length(dy));
|
||||
float pix_scale = 1.0 / (hash_scale * delta_max_sqr);
|
||||
|
||||
vec2 pix_scales =
|
||||
vec2(exp2(floor(log2(pix_scale))), exp2(ceil(log2(pix_scale))));
|
||||
|
||||
vec2 a_thresh = vec2(hash_3d(floor(pix_scales.x * pos.xyz)),
|
||||
hash_3d(floor(pix_scales.y * pos.xyz)));
|
||||
|
||||
float lerp_factor = fract(log2(pix_scale));
|
||||
|
||||
float a_interp = (1.0 - lerp_factor) * a_thresh.x + lerp_factor * a_thresh.y;
|
||||
|
||||
float min_lerp = min(lerp_factor, 1.0 - lerp_factor);
|
||||
|
||||
vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)),
|
||||
(a_interp - 0.5 * min_lerp) / (1.0 - min_lerp),
|
||||
1.0 - ((1.0 - a_interp) * (1.0 - a_interp) /
|
||||
(2.0 * min_lerp * (1.0 - min_lerp))));
|
||||
|
||||
float alpha_hash_threshold =
|
||||
(lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z;
|
||||
|
||||
return clamp(alpha_hash_threshold, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif // ALPHA_HASH_USED
|
||||
|
||||
#ifdef ALPHA_ANTIALIASING_EDGE_USED
|
||||
|
||||
float calc_mip_level(vec2 texture_coord) {
|
||||
vec2 dx = dFdx(texture_coord);
|
||||
vec2 dy = dFdy(texture_coord);
|
||||
float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
|
||||
return max(0.0, 0.5 * log2(delta_max_sqr));
|
||||
}
|
||||
|
||||
float compute_alpha_antialiasing_edge(float input_alpha, vec2 texture_coord, float alpha_edge) {
|
||||
input_alpha *= 1.0 + max(0, calc_mip_level(texture_coord)) * 0.25; // 0.25 mip scale, magic number
|
||||
input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), 0.0001) + 0.5;
|
||||
return clamp(input_alpha, 0.0, 1.0);
|
||||
}
|
||||
|
||||
#endif // ALPHA_ANTIALIASING_USED
|
File diff suppressed because it is too large
Load diff
|
@ -13,6 +13,7 @@
|
|||
#endif
|
||||
|
||||
#include "cluster_data_inc.glsl"
|
||||
#include "decal_data_inc.glsl"
|
||||
|
||||
#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_GIPROBE) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED)
|
||||
#ifndef NORMAL_USED
|
||||
|
@ -28,7 +29,11 @@ layout(push_constant, binding = 0, std430) uniform DrawCall {
|
|||
}
|
||||
draw_call;
|
||||
|
||||
/* Set 0 Scene data that never changes, ever */
|
||||
#define SDFGI_MAX_CASCADES 8
|
||||
|
||||
/* Set 0: Base Pass (never changes) */
|
||||
|
||||
#include "light_data_inc.glsl"
|
||||
|
||||
#define SAMPLER_NEAREST_CLAMP 0
|
||||
#define SAMPLER_LINEAR_CLAMP 1
|
||||
|
@ -43,10 +48,6 @@ draw_call;
|
|||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
#define SDFGI_MAX_CASCADES 8
|
||||
|
||||
/* Set 1: Base Pass (never changes) */
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
|
||||
|
||||
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
||||
|
@ -156,7 +157,7 @@ layout(set = 0, binding = 13, std140) uniform SDFGI {
|
|||
}
|
||||
sdfgi;
|
||||
|
||||
/* Set 2: Render Pass (changes per render pass) */
|
||||
/* Set 1: Render Pass (changes per render pass) */
|
||||
|
||||
layout(set = 1, binding = 0, std140) uniform SceneData {
|
||||
mat4 projection_matrix;
|
||||
|
@ -240,7 +241,6 @@ layout(set = 1, binding = 0, std140) uniform SceneData {
|
|||
|
||||
bool pancake_shadows;
|
||||
}
|
||||
|
||||
scene_data;
|
||||
|
||||
struct InstanceData {
|
||||
|
|
242
servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
Normal file
242
servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Functions related to gi/sdfgi for our forward renderer
|
||||
|
||||
//standard voxel cone trace
|
||||
vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
float diameter = max(1.0, 2.0 * tan_half_angle * dist);
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
float half_diameter = diameter * 0.5;
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter));
|
||||
float a = (1.0 - color.a);
|
||||
color += a * scolor;
|
||||
dist += half_diameter;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) {
|
||||
float dist = p_bias;
|
||||
vec4 color = vec4(0.0);
|
||||
float radius = max(0.5, tan_half_angle * dist);
|
||||
float lod_level = log2(radius * 2.0);
|
||||
|
||||
while (dist < max_distance && color.a < 0.95) {
|
||||
vec3 uvw_pos = (pos + dist * direction) * cell_size;
|
||||
|
||||
//check if outside, then break
|
||||
if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) {
|
||||
break;
|
||||
}
|
||||
vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level);
|
||||
lod_level += 1.0;
|
||||
|
||||
float a = (1.0 - color.a);
|
||||
scolor *= a;
|
||||
color += scolor;
|
||||
dist += radius;
|
||||
radius = max(0.5, tan_half_angle * dist);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) {
|
||||
position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz;
|
||||
ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz);
|
||||
normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz);
|
||||
|
||||
position += normal * gi_probes.data[index].normal_bias;
|
||||
|
||||
//this causes corrupted pixels, i have no idea why..
|
||||
if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) {
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0);
|
||||
float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0);
|
||||
//float blend=1.0;
|
||||
|
||||
float max_distance = length(gi_probes.data[index].bounds);
|
||||
vec3 cell_size = 1.0 / gi_probes.data[index].bounds;
|
||||
|
||||
//radiance
|
||||
|
||||
#define MAX_CONE_DIRS 4
|
||||
|
||||
vec3 cone_dirs[MAX_CONE_DIRS] = vec3[](
|
||||
vec3(0.707107, 0.0, 0.707107),
|
||||
vec3(0.0, 0.707107, 0.707107),
|
||||
vec3(-0.707107, 0.0, 0.707107),
|
||||
vec3(0.0, -0.707107, 0.707107));
|
||||
|
||||
float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25);
|
||||
float cone_angle_tan = 0.98269;
|
||||
|
||||
vec3 light = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < MAX_CONE_DIRS; i++) {
|
||||
vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz);
|
||||
|
||||
vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[index], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias);
|
||||
|
||||
if (gi_probes.data[index].blend_ambient) {
|
||||
cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95));
|
||||
}
|
||||
|
||||
light += cone_weights[i] * cone_light.rgb;
|
||||
}
|
||||
|
||||
light *= gi_probes.data[index].dynamic_range;
|
||||
out_diff += vec4(light * blend, blend);
|
||||
|
||||
//irradiance
|
||||
vec4 irr_light = voxel_cone_trace(gi_probe_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias);
|
||||
if (gi_probes.data[index].blend_ambient) {
|
||||
irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));
|
||||
}
|
||||
irr_light.rgb *= gi_probes.data[index].dynamic_range;
|
||||
//irr_light=vec3(0.0);
|
||||
|
||||
out_spec += vec4(irr_light.rgb * blend, blend);
|
||||
}
|
||||
|
||||
vec2 octahedron_wrap(vec2 v) {
|
||||
vec2 signVal;
|
||||
signVal.x = v.x >= 0.0 ? 1.0 : -1.0;
|
||||
signVal.y = v.y >= 0.0 ? 1.0 : -1.0;
|
||||
return (1.0 - abs(v.yx)) * signVal;
|
||||
}
|
||||
|
||||
vec2 octahedron_encode(vec3 n) {
|
||||
// https://twitter.com/Stubbesaurus/status/937994790553227264
|
||||
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
||||
n.xy = n.z >= 0.0 ? n.xy : octahedron_wrap(n.xy);
|
||||
n.xy = n.xy * 0.5 + 0.5;
|
||||
return n.xy;
|
||||
}
|
||||
|
||||
void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, bool use_specular, float roughness, out vec3 diffuse_light, out vec3 specular_light, out float blend) {
|
||||
cascade_pos += cam_normal * sdfgi.normal_bias;
|
||||
|
||||
vec3 base_pos = floor(cascade_pos);
|
||||
//cascade_pos += mix(vec3(0.0),vec3(0.01),lessThan(abs(cascade_pos-base_pos),vec3(0.01))) * cam_normal;
|
||||
ivec3 probe_base_pos = ivec3(base_pos);
|
||||
|
||||
vec4 diffuse_accum = vec4(0.0);
|
||||
vec3 specular_accum;
|
||||
|
||||
ivec3 tex_pos = ivec3(probe_base_pos.xy, int(cascade));
|
||||
tex_pos.x += probe_base_pos.z * sdfgi.probe_axis_size;
|
||||
tex_pos.xy = tex_pos.xy * (SDFGI_OCT_SIZE + 2) + ivec2(1);
|
||||
|
||||
vec3 diffuse_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
|
||||
vec3 specular_posf;
|
||||
|
||||
if (use_specular) {
|
||||
specular_accum = vec3(0.0);
|
||||
specular_posf = (vec3(tex_pos) + vec3(octahedron_encode(cam_specular_normal) * float(SDFGI_OCT_SIZE), 0.0)) * sdfgi.lightprobe_tex_pixel_size;
|
||||
}
|
||||
|
||||
vec4 light_accum = vec4(0.0);
|
||||
float weight_accum = 0.0;
|
||||
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
ivec3 offset = (ivec3(j) >> ivec3(0, 1, 2)) & ivec3(1, 1, 1);
|
||||
ivec3 probe_posi = probe_base_pos;
|
||||
probe_posi += offset;
|
||||
|
||||
// Compute weight
|
||||
|
||||
vec3 probe_pos = vec3(probe_posi);
|
||||
vec3 probe_to_pos = cascade_pos - probe_pos;
|
||||
vec3 probe_dir = normalize(-probe_to_pos);
|
||||
|
||||
vec3 trilinear = vec3(1.0) - abs(probe_to_pos);
|
||||
float weight = trilinear.x * trilinear.y * trilinear.z * max(0.005, dot(cam_normal, probe_dir));
|
||||
|
||||
// Compute lightprobe occlusion
|
||||
|
||||
if (sdfgi.use_occlusion) {
|
||||
ivec3 occ_indexv = abs((sdfgi.cascades[cascade].probe_world_offset + probe_posi) & ivec3(1, 1, 1)) * ivec3(1, 2, 4);
|
||||
vec4 occ_mask = mix(vec4(0.0), vec4(1.0), equal(ivec4(occ_indexv.x | occ_indexv.y), ivec4(0, 1, 2, 3)));
|
||||
|
||||
vec3 occ_pos = clamp(cascade_pos, probe_pos - sdfgi.occlusion_clamp, probe_pos + sdfgi.occlusion_clamp) * sdfgi.probe_to_uvw;
|
||||
occ_pos.z += float(cascade);
|
||||
if (occ_indexv.z != 0) { //z bit is on, means index is >=4, so make it switch to the other half of textures
|
||||
occ_pos.x += 1.0;
|
||||
}
|
||||
|
||||
occ_pos *= sdfgi.occlusion_renormalize;
|
||||
float occlusion = dot(textureLod(sampler3D(sdfgi_occlusion_cascades, material_samplers[SAMPLER_LINEAR_CLAMP]), occ_pos, 0.0), occ_mask);
|
||||
|
||||
weight *= max(occlusion, 0.01);
|
||||
}
|
||||
|
||||
// Compute lightprobe texture position
|
||||
|
||||
vec3 diffuse;
|
||||
vec3 pos_uvw = diffuse_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb;
|
||||
|
||||
diffuse_accum += vec4(diffuse * weight, weight);
|
||||
|
||||
if (use_specular) {
|
||||
vec3 specular = vec3(0.0);
|
||||
vec3 pos_uvw = specular_posf;
|
||||
pos_uvw.xy += vec2(offset.xy) * sdfgi.lightprobe_uv_offset.xy;
|
||||
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
|
||||
if (roughness < 0.99) {
|
||||
specular = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw + vec3(0, 0, float(sdfgi.max_cascades)), 0.0).rgb;
|
||||
}
|
||||
if (roughness > 0.5) {
|
||||
specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0);
|
||||
}
|
||||
|
||||
specular_accum += specular * weight;
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
diffuse_accum.rgb /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
diffuse_light = diffuse_accum.rgb;
|
||||
|
||||
if (use_specular) {
|
||||
if (diffuse_accum.a > 0.0) {
|
||||
specular_accum /= diffuse_accum.a;
|
||||
}
|
||||
|
||||
specular_light = specular_accum;
|
||||
}
|
||||
|
||||
{
|
||||
//process blend
|
||||
float blend_from = (float(sdfgi.probe_axis_size - 1) / 2.0) - 2.5;
|
||||
float blend_to = blend_from + 2.0;
|
||||
|
||||
vec3 inner_pos = cam_pos * sdfgi.cascades[cascade].to_probe;
|
||||
|
||||
float len = length(inner_pos);
|
||||
|
||||
inner_pos = abs(normalize(inner_pos));
|
||||
len *= max(inner_pos.x, max(inner_pos.y, inner_pos.z));
|
||||
|
||||
if (len >= blend_from) {
|
||||
blend = smoothstep(blend_from, blend_to, len);
|
||||
} else {
|
||||
blend = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
1023
servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
Normal file
1023
servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
Normal file
File diff suppressed because it is too large
Load diff
1476
servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
Normal file
1476
servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,220 @@
|
|||
#define M_PI 3.14159265359
|
||||
|
||||
#include "decal_data_inc.glsl"
|
||||
|
||||
#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED)
|
||||
#ifndef NORMAL_USED
|
||||
#define NORMAL_USED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* don't exceed 128 bytes!! */
|
||||
/* put instance data into our push content, not a array */
|
||||
layout(push_constant, binding = 0, std430) uniform DrawCall {
|
||||
mat4 transform; // 64 - 64
|
||||
uint flags; // 04 - 68
|
||||
uint instance_uniforms_ofs; //base offset in global buffer for instance variables // 04 - 72
|
||||
uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) // 04 - 76
|
||||
uint layer_mask; // 04 - 80
|
||||
vec4 lightmap_uv_scale; // 16 - 96 doubles as uv_offset when needed
|
||||
|
||||
uvec2 reflection_probes; // 08 - 104
|
||||
uvec2 omni_lights; // 08 - 112
|
||||
uvec2 spot_lights; // 08 - 120
|
||||
uvec2 decals; // 08 - 128
|
||||
}
|
||||
draw_call;
|
||||
|
||||
/* Set 0: Base Pass (never changes) */
|
||||
|
||||
#include "light_data_inc.glsl"
|
||||
|
||||
#define SAMPLER_NEAREST_CLAMP 0
|
||||
#define SAMPLER_LINEAR_CLAMP 1
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5
|
||||
#define SAMPLER_NEAREST_REPEAT 6
|
||||
#define SAMPLER_LINEAR_REPEAT 7
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9
|
||||
#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10
|
||||
#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11
|
||||
|
||||
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
|
||||
|
||||
layout(set = 0, binding = 2) uniform sampler shadow_sampler;
|
||||
|
||||
#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
|
||||
#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
|
||||
#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
|
||||
#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
|
||||
#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
|
||||
#define INSTANCE_FLAGS_USE_GIPROBE (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
|
||||
|
||||
#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 24)
|
||||
|
||||
layout(set = 0, binding = 3, std430) restrict readonly buffer OmniLights {
|
||||
LightData data[];
|
||||
}
|
||||
omni_lights;
|
||||
|
||||
layout(set = 0, binding = 4, std430) restrict readonly buffer SpotLights {
|
||||
LightData data[];
|
||||
}
|
||||
spot_lights;
|
||||
|
||||
layout(set = 0, binding = 5, std430) restrict readonly buffer ReflectionProbeData {
|
||||
ReflectionData data[];
|
||||
}
|
||||
reflections;
|
||||
|
||||
layout(set = 0, binding = 6, std140) uniform DirectionalLights {
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
directional_lights;
|
||||
|
||||
#define LIGHTMAP_FLAG_USE_DIRECTION 1
|
||||
#define LIGHTMAP_FLAG_USE_SPECULAR_DIRECTION 2
|
||||
|
||||
struct Lightmap {
|
||||
mat3 normal_xform;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 7, std140) restrict readonly buffer Lightmaps {
|
||||
Lightmap data[];
|
||||
}
|
||||
lightmaps;
|
||||
|
||||
struct LightmapCapture {
|
||||
vec4 sh[9];
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 8, std140) restrict readonly buffer LightmapCaptures {
|
||||
LightmapCapture data[];
|
||||
}
|
||||
lightmap_captures;
|
||||
|
||||
layout(set = 0, binding = 9) uniform texture2D decal_atlas;
|
||||
layout(set = 0, binding = 10) uniform texture2D decal_atlas_srgb;
|
||||
|
||||
layout(set = 0, binding = 11, std430) restrict readonly buffer Decals {
|
||||
DecalData data[];
|
||||
}
|
||||
decals;
|
||||
|
||||
layout(set = 0, binding = 12, std430) restrict readonly buffer GlobalVariableData {
|
||||
vec4 data[];
|
||||
}
|
||||
global_variables;
|
||||
|
||||
/* Set 1: Render Pass (changes per render pass) */
|
||||
|
||||
layout(set = 1, binding = 0, std140) uniform SceneData {
|
||||
mat4 projection_matrix;
|
||||
mat4 inv_projection_matrix;
|
||||
|
||||
mat4 camera_matrix;
|
||||
mat4 inv_camera_matrix;
|
||||
|
||||
vec2 viewport_size;
|
||||
vec2 screen_pixel_size;
|
||||
|
||||
//use vec4s because std140 doesnt play nice with vec2s, z and w are wasted
|
||||
vec4 directional_penumbra_shadow_kernel[32];
|
||||
vec4 directional_soft_shadow_kernel[32];
|
||||
vec4 penumbra_shadow_kernel[32];
|
||||
vec4 soft_shadow_kernel[32];
|
||||
|
||||
uint directional_penumbra_shadow_samples;
|
||||
uint directional_soft_shadow_samples;
|
||||
uint penumbra_shadow_samples;
|
||||
uint soft_shadow_samples;
|
||||
|
||||
vec4 ambient_light_color_energy;
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
bool use_ambient_light;
|
||||
bool use_ambient_cubemap;
|
||||
bool use_reflection_cubemap;
|
||||
|
||||
mat3 radiance_inverse_xform;
|
||||
|
||||
vec2 shadow_atlas_pixel_size;
|
||||
vec2 directional_shadow_pixel_size;
|
||||
|
||||
uint directional_light_count;
|
||||
float dual_paraboloid_side;
|
||||
float z_far;
|
||||
float z_near;
|
||||
|
||||
bool ssao_enabled;
|
||||
float ssao_light_affect;
|
||||
float ssao_ao_affect;
|
||||
bool roughness_limiter_enabled;
|
||||
|
||||
float roughness_limiter_amount;
|
||||
float roughness_limiter_limit;
|
||||
uvec2 roughness_limiter_pad;
|
||||
|
||||
vec4 ao_color;
|
||||
|
||||
bool fog_enabled;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
vec3 fog_light_color;
|
||||
float fog_sun_scatter;
|
||||
|
||||
float fog_aerial_perspective;
|
||||
bool material_uv2_mode;
|
||||
|
||||
float time;
|
||||
float reflection_multiplier; // one normally, zero when rendering reflections
|
||||
|
||||
bool pancake_shadows;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
uint pad3;
|
||||
}
|
||||
scene_data;
|
||||
|
||||
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
|
||||
|
||||
layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap;
|
||||
|
||||
#else
|
||||
|
||||
layout(set = 1, binding = 2) uniform textureCube radiance_cubemap;
|
||||
|
||||
#endif
|
||||
|
||||
layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas;
|
||||
|
||||
layout(set = 1, binding = 4) uniform texture2D shadow_atlas;
|
||||
|
||||
layout(set = 1, binding = 5) uniform 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 = 9) uniform texture2D depth_buffer;
|
||||
layout(set = 1, binding = 10) uniform texture2D color_buffer;
|
||||
|
||||
/* Set 2 Skeleton & Instancing (can change per item) */
|
||||
|
||||
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {
|
||||
vec4 data[];
|
||||
}
|
||||
transforms;
|
||||
|
||||
/* Set 3 User Material */
|
|
@ -26,6 +26,7 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
|||
#endif
|
||||
|
||||
#include "cluster_data_inc.glsl"
|
||||
#include "light_data_inc.glsl"
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
|
|
|
@ -2453,18 +2453,19 @@ void RendererSceneCull::_frustum_cull(CullData &cull_data, FrustumCullResult &cu
|
|||
}
|
||||
|
||||
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_DECAL) && (idata.flags & InstanceData::FLAG_GEOM_DECAL_DIRTY)) {
|
||||
//InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
|
||||
//todo for GLES3
|
||||
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
|
||||
/*for (Set<Instance *>::Element *E = geom->dec.front(); E; E = E->next()) {
|
||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(E->get()->base_data);
|
||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
|
||||
uint32_t idx = 0;
|
||||
|
||||
instance_pair_buffer[idx++] = reflection_probe->instance;
|
||||
if (idx==MAX_INSTANCE_PAIRS) {
|
||||
break;
|
||||
for (Set<Instance *>::Element *E = geom->decals.front(); E; E = E->next()) {
|
||||
InstanceDecalData *decal = static_cast<InstanceDecalData *>(E->get()->base_data);
|
||||
|
||||
instance_pair_buffer[idx++] = decal->instance;
|
||||
if (idx == MAX_INSTANCE_PAIRS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, light_instances, idx);
|
||||
scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
|
||||
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
|
||||
}
|
||||
|
||||
if (idata.flags & InstanceData::FLAG_GEOM_GI_PROBE_DIRTY) {
|
||||
|
|
|
@ -2297,8 +2297,12 @@ RenderingServer::RenderingServer() {
|
|||
|
||||
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
|
||||
|
||||
GLOBAL_DEF("rendering/driver/rd_renderer/use_low_end_renderer", false);
|
||||
GLOBAL_DEF("rendering/driver/rd_renderer/use_low_end_renderer.mobile", true);
|
||||
GLOBAL_DEF_RST("rendering/vulkan/rendering/back_end", 0);
|
||||
GLOBAL_DEF_RST("rendering/vulkan/rendering/back_end.mobile", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/vulkan/rendering/back_end",
|
||||
PropertyInfo(Variant::INT,
|
||||
"rendering/vulkan/rendering/back_end",
|
||||
PROPERTY_HINT_ENUM, "ForwardClustered,ForwardMobile"));
|
||||
|
||||
GLOBAL_DEF("rendering/reflections/sky_reflections/roughness_layers", 8);
|
||||
GLOBAL_DEF("rendering/reflections/sky_reflections/texture_array_reflections", true);
|
||||
|
|
Loading…
Reference in a new issue