initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
6
servers/rendering/renderer_rd/forward_mobile/SCsub
Normal file
6
servers/rendering/renderer_rd/forward_mobile/SCsub
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.servers_sources, "*.cpp")
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,722 @@
|
||||
/**************************************************************************/
|
||||
/* render_forward_mobile.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/templates/paged_allocator.h"
|
||||
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
|
||||
#define RB_SCOPE_MOBILE SNAME("mobile")
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class RenderForwardMobile : public RendererSceneRenderRD {
|
||||
friend SceneShaderForwardMobile;
|
||||
|
||||
protected:
|
||||
struct GeometryInstanceSurfaceDataCache;
|
||||
|
||||
private:
|
||||
static RenderForwardMobile *singleton;
|
||||
|
||||
/* 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 */
|
||||
|
||||
class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD {
|
||||
GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD);
|
||||
|
||||
public:
|
||||
enum FramebufferConfigType {
|
||||
FB_CONFIG_RENDER_PASS, // Single pass framebuffer for normal rendering.
|
||||
FB_CONFIG_RENDER_AND_POST_PASS, // Two subpasses, one for normal rendering, one for post processing.
|
||||
FB_CONFIG_MAX
|
||||
};
|
||||
|
||||
RID get_color_fbs(FramebufferConfigType p_config_type);
|
||||
virtual void free_data() override;
|
||||
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
|
||||
|
||||
RID get_motion_vectors_fb();
|
||||
|
||||
private:
|
||||
RenderSceneBuffersRD *render_buffers = nullptr;
|
||||
};
|
||||
|
||||
virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
/* 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_VOXEL_GI,
|
||||
PASS_MODE_DEPTH_MATERIAL,
|
||||
// PASS_MODE_SDF,
|
||||
PASS_MODE_MOTION_VECTORS,
|
||||
};
|
||||
|
||||
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;
|
||||
uint32_t view_count = 1;
|
||||
RID render_pass_uniform_set;
|
||||
bool force_wireframe = false;
|
||||
Vector2 uv_offset;
|
||||
SceneShaderForwardMobile::ShaderSpecialization base_specialization;
|
||||
float lod_distance_multiplier = 0.0;
|
||||
float screen_mesh_lod_threshold = 0.0;
|
||||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
uint32_t subpass = 0;
|
||||
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, SceneShaderForwardMobile::ShaderSpecialization p_base_specialization, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0) {
|
||||
elements = p_elements;
|
||||
element_info = p_element_info;
|
||||
element_count = p_element_count;
|
||||
reverse_cull = p_reverse_cull;
|
||||
pass_mode = p_pass_mode;
|
||||
// no_gi = p_no_gi;
|
||||
view_count = p_view_count;
|
||||
render_pass_uniform_set = p_render_pass_uniform_set;
|
||||
force_wireframe = p_force_wireframe;
|
||||
uv_offset = p_uv_offset;
|
||||
lod_distance_multiplier = p_lod_distance_multiplier;
|
||||
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
|
||||
element_offset = p_element_offset;
|
||||
base_specialization = p_base_specialization;
|
||||
}
|
||||
};
|
||||
|
||||
/* Render shadows */
|
||||
|
||||
void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
|
||||
void _render_shadow_begin();
|
||||
void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &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, float p_lod_distance_multiplier = 0.0, float p_screen_mesh_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, RenderingMethod::RenderInfo *p_render_info = nullptr, const Transform3D &p_main_cam_transform = Transform3D());
|
||||
void _render_shadow_process();
|
||||
void _render_shadow_end();
|
||||
|
||||
/* Render Scene */
|
||||
|
||||
RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, bool p_use_directional_shadow_atlas = false, int p_index = 0);
|
||||
void _pre_opaque_render(RenderDataRD *p_render_data);
|
||||
|
||||
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
|
||||
|
||||
void _update_render_base_uniform_set();
|
||||
|
||||
void _update_instance_data_buffer(RenderListType p_render_list);
|
||||
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 _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
|
||||
|
||||
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
|
||||
void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
|
||||
|
||||
RID render_base_uniform_set;
|
||||
|
||||
/* Light map */
|
||||
|
||||
struct LightmapData {
|
||||
float normal_xform[12];
|
||||
float texture_size[2];
|
||||
float exposure_normalization;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct LightmapCaptureData {
|
||||
float sh[9 * 4];
|
||||
};
|
||||
|
||||
/* Scene state */
|
||||
|
||||
struct SceneState {
|
||||
LocalVector<RID> uniform_buffers;
|
||||
|
||||
struct PushConstantUbershader {
|
||||
SceneShaderForwardMobile::ShaderSpecialization specialization;
|
||||
SceneShaderForwardMobile::UbershaderConstants constants;
|
||||
};
|
||||
|
||||
struct PushConstant {
|
||||
uint32_t uv_offset;
|
||||
uint32_t base_index;
|
||||
uint32_t multimesh_motion_vectors_current_offset;
|
||||
uint32_t multimesh_motion_vectors_previous_offset;
|
||||
PushConstantUbershader ubershader;
|
||||
};
|
||||
|
||||
struct InstanceData {
|
||||
float transform[16];
|
||||
float prev_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;
|
||||
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.
|
||||
float compressed_aabb_position[4];
|
||||
float compressed_aabb_size[4];
|
||||
float uv_scale[4];
|
||||
|
||||
// These setters allow us to copy the data over with operation when using floats.
|
||||
inline void set_lightmap_uv_scale(const Rect2 &p_rect) {
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
lightmap_uv_scale[0] = p_rect.position.x;
|
||||
lightmap_uv_scale[1] = p_rect.position.y;
|
||||
lightmap_uv_scale[2] = p_rect.size.x;
|
||||
lightmap_uv_scale[3] = p_rect.size.y;
|
||||
#else
|
||||
Rect2 *rect = reinterpret_cast<Rect2 *>(lightmap_uv_scale);
|
||||
*rect = p_rect;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void set_compressed_aabb(const AABB &p_aabb) {
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
compressed_aabb_position[0] = p_aabb.position.x;
|
||||
compressed_aabb_position[1] = p_aabb.position.y;
|
||||
compressed_aabb_position[2] = p_aabb.position.z;
|
||||
|
||||
compressed_aabb_size[0] = p_aabb.size.x;
|
||||
compressed_aabb_size[1] = p_aabb.size.y;
|
||||
compressed_aabb_size[2] = p_aabb.size.z;
|
||||
#else
|
||||
Vector3 *compressed_aabb_position_vec3 = reinterpret_cast<Vector3 *>(compressed_aabb_position);
|
||||
Vector3 *compressed_aabb_size_vec3 = reinterpret_cast<Vector3 *>(compressed_aabb_size);
|
||||
*compressed_aabb_position_vec3 = p_aabb.position;
|
||||
*compressed_aabb_size_vec3 = p_aabb.size;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void set_uv_scale(const Vector4 &p_uv_scale) {
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
uv_scale[0] = p_uv_scale.x;
|
||||
uv_scale[1] = p_uv_scale.y;
|
||||
uv_scale[2] = p_uv_scale.z;
|
||||
uv_scale[3] = p_uv_scale.w;
|
||||
#else
|
||||
Vector4 *uv_scale_vec4 = reinterpret_cast<Vector4 *>(uv_scale);
|
||||
*uv_scale_vec4 = p_uv_scale;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(std::is_trivially_destructible_v<InstanceData>);
|
||||
static_assert(std::is_trivially_constructible_v<InstanceData>);
|
||||
|
||||
RID instance_buffer[RENDER_LIST_MAX];
|
||||
uint32_t instance_buffer_size[RENDER_LIST_MAX] = { 0, 0, 0 };
|
||||
LocalVector<InstanceData> instance_data[RENDER_LIST_MAX];
|
||||
|
||||
// !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 = nullptr;
|
||||
uint32_t max_lightmap_captures;
|
||||
RID lightmap_capture_buffer;
|
||||
|
||||
bool used_screen_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_lightmap = false;
|
||||
bool used_opaque_stencil = false;
|
||||
|
||||
struct ShadowPass {
|
||||
uint32_t element_from;
|
||||
uint32_t element_count;
|
||||
bool flip_cull;
|
||||
PassMode pass_mode;
|
||||
|
||||
RID rp_uniform_set;
|
||||
float lod_distance_multiplier;
|
||||
float screen_mesh_lod_threshold;
|
||||
|
||||
RID framebuffer;
|
||||
Rect2i rect;
|
||||
bool clear_depth;
|
||||
};
|
||||
|
||||
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 SortByKeyAndStencil {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const {
|
||||
bool a_stencil = A->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_STENCIL;
|
||||
bool b_stencil = B->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_STENCIL;
|
||||
if (a_stencil != b_stencil) {
|
||||
return a_stencil < b_stencil;
|
||||
}
|
||||
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_and_stencil() {
|
||||
SortArray<GeometryInstanceSurfaceDataCache *, SortByKeyAndStencil> sorter;
|
||||
sorter.sort(elements.ptr(), elements.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() { //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 {
|
||||
union {
|
||||
struct {
|
||||
uint32_t lod_index : 8;
|
||||
uint32_t uses_lightmap : 1;
|
||||
uint32_t reserved : 23;
|
||||
};
|
||||
uint32_t value;
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(std::is_trivially_destructible_v<RenderElementInfo>);
|
||||
static_assert(std::is_trivially_constructible_v<RenderElementInfo>);
|
||||
|
||||
template <PassMode p_pass_mode>
|
||||
_FORCE_INLINE_ void _render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element);
|
||||
void _render_list_with_draw_list(RenderListParameters *p_params, RID p_framebuffer, BitField<RD::DrawFlags> p_clear_colors = RD::DRAW_DEFAULT_ALL, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth_value = 0.0, uint32_t p_clear_stencil_value = 0, const Rect2 &p_region = Rect2());
|
||||
|
||||
RenderList render_list[RENDER_LIST_MAX];
|
||||
|
||||
protected:
|
||||
/* setup */
|
||||
virtual void _update_shader_quality_settings() override;
|
||||
|
||||
virtual float _render_buffers_get_luminance_multiplier() override;
|
||||
virtual RD::DataFormat _render_buffers_get_color_format() override;
|
||||
virtual bool _render_buffers_can_be_storage() override;
|
||||
|
||||
virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
|
||||
|
||||
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
|
||||
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
|
||||
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
|
||||
|
||||
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
|
||||
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
|
||||
|
||||
/* Geometry instance */
|
||||
|
||||
class GeometryInstanceForwardMobile;
|
||||
|
||||
// When changing any of these enums, remember to change the corresponding enums in the shader files as well.
|
||||
enum {
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_INDIRECT = 1 << 2,
|
||||
INSTANCE_DATA_FLAGS_DYNAMIC = 1 << 3,
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
|
||||
INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
|
||||
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
|
||||
INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
|
||||
INSTANCE_DATA_FLAG_PARTICLES = 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,
|
||||
};
|
||||
|
||||
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,
|
||||
FLAG_USES_STENCIL = 131072,
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
struct {
|
||||
uint64_t lod_index : 8;
|
||||
uint64_t uses_lightmap : 1;
|
||||
uint64_t pad : 3;
|
||||
uint64_t depth_layer : 4;
|
||||
uint64_t surface_index : 8;
|
||||
uint64_t priority : 8;
|
||||
uint64_t geometry_id : 32;
|
||||
|
||||
uint64_t material_id : 32;
|
||||
uint64_t shader_id : 32;
|
||||
};
|
||||
} sort;
|
||||
|
||||
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
|
||||
uint32_t flags = 0;
|
||||
uint32_t surface_index = 0;
|
||||
|
||||
void *surface = nullptr;
|
||||
RID material_uniform_set;
|
||||
SceneShaderForwardMobile::ShaderData *shader = nullptr;
|
||||
SceneShaderForwardMobile::MaterialData *material = nullptr;
|
||||
|
||||
void *surface_shadow = nullptr;
|
||||
RID material_uniform_set_shadow;
|
||||
SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr;
|
||||
|
||||
GeometryInstanceSurfaceDataCache *next = nullptr;
|
||||
GeometryInstanceForwardMobile *owner = nullptr;
|
||||
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_dirty_element;
|
||||
SelfList<GeometryInstanceSurfaceDataCache> compilation_all_element;
|
||||
|
||||
GeometryInstanceSurfaceDataCache() :
|
||||
compilation_dirty_element(this), compilation_all_element(this) {}
|
||||
};
|
||||
|
||||
class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
|
||||
public:
|
||||
//used during rendering
|
||||
RID transforms_uniform_set;
|
||||
bool use_projector = false;
|
||||
bool use_soft_shadow = false;
|
||||
bool store_transform_cache = true; // If true we copy our transform into our per-draw buffer, if false we use our transforms UBO and clear our per-draw transform.
|
||||
uint32_t instance_count = 0;
|
||||
uint32_t trail_steps = 1;
|
||||
|
||||
uint64_t prev_transform_change_frame = UINT_MAX;
|
||||
bool prev_transform_dirty = true;
|
||||
Transform3D prev_transform;
|
||||
|
||||
// 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
|
||||
RID lightmap_instance;
|
||||
Rect2 lightmap_uv_scale;
|
||||
uint32_t lightmap_slice_index;
|
||||
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
|
||||
|
||||
// culled light info
|
||||
uint32_t reflection_probe_count = 0;
|
||||
RendererRD::ForwardID reflection_probes[MAX_RDL_CULL];
|
||||
uint32_t omni_light_count = 0;
|
||||
RendererRD::ForwardID omni_lights[MAX_RDL_CULL];
|
||||
uint32_t spot_light_count = 0;
|
||||
RendererRD::ForwardID spot_lights[MAX_RDL_CULL];
|
||||
uint32_t decals_count = 0;
|
||||
RendererRD::ForwardID decals[MAX_RDL_CULL];
|
||||
|
||||
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
|
||||
|
||||
// do we use this?
|
||||
SelfList<GeometryInstanceForwardMobile> dirty_list_element;
|
||||
|
||||
GeometryInstanceForwardMobile() :
|
||||
dirty_list_element(this) {}
|
||||
|
||||
virtual void _mark_dirty() override;
|
||||
|
||||
virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
|
||||
virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
|
||||
virtual void set_lightmap_capture(const Color *p_sh9) override;
|
||||
|
||||
virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override;
|
||||
virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
|
||||
virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
|
||||
virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
|
||||
|
||||
virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
|
||||
};
|
||||
|
||||
/* Rendering */
|
||||
|
||||
virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
|
||||
|
||||
virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
|
||||
virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
|
||||
virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
|
||||
virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
|
||||
|
||||
/* Forward ID */
|
||||
|
||||
class ForwardIDStorageMobile : public RendererRD::ForwardIDStorage {
|
||||
public:
|
||||
struct ForwardIDAllocator {
|
||||
LocalVector<bool> allocations;
|
||||
LocalVector<uint8_t> map;
|
||||
LocalVector<uint64_t> last_pass;
|
||||
};
|
||||
|
||||
ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX];
|
||||
|
||||
public:
|
||||
virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override;
|
||||
virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override;
|
||||
virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index, uint64_t p_last_pass) override;
|
||||
virtual bool uses_forward_ids() const override { return true; }
|
||||
};
|
||||
|
||||
ForwardIDStorageMobile *forward_id_storage_mobile = nullptr;
|
||||
|
||||
void fill_push_constant_instance_indices(SceneState::InstanceData *p_instance_data, const GeometryInstanceForwardMobile *p_instance);
|
||||
|
||||
virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override {
|
||||
forward_id_storage_mobile = memnew(ForwardIDStorageMobile);
|
||||
return forward_id_storage_mobile;
|
||||
}
|
||||
|
||||
struct ForwardIDByMapSort {
|
||||
uint8_t map;
|
||||
RendererRD::ForwardID forward_id;
|
||||
bool operator<(const ForwardIDByMapSort &p_sort) const {
|
||||
return map > p_sort.map;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
static RenderForwardMobile *get_singleton() { return singleton; }
|
||||
|
||||
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
|
||||
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
|
||||
virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
|
||||
virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
|
||||
virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
|
||||
|
||||
/* GEOMETRY INSTANCE */
|
||||
|
||||
static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
|
||||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
|
||||
|
||||
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_dirty_list;
|
||||
SelfList<GeometryInstanceSurfaceDataCache>::List geometry_surface_compilation_all_list;
|
||||
|
||||
PagedAllocator<GeometryInstanceForwardMobile> geometry_instance_alloc;
|
||||
PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc;
|
||||
PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh;
|
||||
|
||||
struct SurfacePipelineData {
|
||||
void *mesh_surface = nullptr;
|
||||
void *mesh_surface_shadow = nullptr;
|
||||
SceneShaderForwardMobile::ShaderData *shader = nullptr;
|
||||
SceneShaderForwardMobile::ShaderData *shader_shadow = nullptr;
|
||||
bool instanced = false;
|
||||
bool uses_opaque = false;
|
||||
bool uses_transparent = false;
|
||||
bool uses_depth = false;
|
||||
bool can_use_lightmap = false;
|
||||
};
|
||||
|
||||
struct GlobalPipelineData {
|
||||
union {
|
||||
uint32_t key;
|
||||
|
||||
struct {
|
||||
uint32_t texture_samples : 3;
|
||||
uint32_t target_samples : 3;
|
||||
uint32_t use_reflection_probes : 1;
|
||||
uint32_t use_lightmaps : 1;
|
||||
uint32_t use_multiview : 1;
|
||||
uint32_t use_16_bit_shadows : 1;
|
||||
uint32_t use_32_bit_shadows : 1;
|
||||
uint32_t use_shadow_cubemaps : 1;
|
||||
uint32_t use_shadow_dual_paraboloid : 1;
|
||||
uint32_t use_vrs : 1;
|
||||
uint32_t use_subpass_post_pass : 1;
|
||||
uint32_t use_separate_post_pass : 1;
|
||||
uint32_t use_hdr_render_target : 1;
|
||||
uint32_t use_ldr_render_target : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
GlobalPipelineData global_pipeline_data_compiled = {};
|
||||
GlobalPipelineData global_pipeline_data_required = {};
|
||||
|
||||
typedef Pair<SceneShaderForwardMobile::ShaderData *, SceneShaderForwardMobile::ShaderData::PipelineKey> ShaderPipelinePair;
|
||||
|
||||
void _update_global_pipeline_data_requirements_from_project();
|
||||
void _update_global_pipeline_data_requirements_from_light_storage();
|
||||
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
|
||||
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
|
||||
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
|
||||
void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
|
||||
void _mesh_compile_pipeline_for_surface(SceneShaderForwardMobile::ShaderData *p_shader, void *p_mesh_surface, bool p_instanced_surface, RS::PipelineSource p_source, SceneShaderForwardMobile::ShaderData::PipelineKey &r_pipeline_key, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_compile_pipelines_for_surface(const SurfacePipelineData &p_surface, const GlobalPipelineData &p_global, RS::PipelineSource p_source, Vector<ShaderPipelinePair> *r_pipeline_pairs = nullptr);
|
||||
void _mesh_generate_all_pipelines_for_surface_cache(GeometryInstanceSurfaceDataCache *p_surface_cache, const GlobalPipelineData &p_global);
|
||||
void _update_dirty_geometry_instances();
|
||||
void _update_dirty_geometry_pipelines();
|
||||
|
||||
// Global data about the scene that can be used to pre-allocate resources without relying on culling.
|
||||
struct GlobalSurfaceData {
|
||||
bool screen_texture_used = false;
|
||||
bool depth_texture_used = false;
|
||||
} global_surface_data;
|
||||
|
||||
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
|
||||
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
|
||||
|
||||
virtual uint32_t geometry_instance_get_pair_mask() override;
|
||||
|
||||
/* PIPELINES */
|
||||
|
||||
virtual void mesh_generate_pipelines(RID p_mesh, bool p_background_compilation) override;
|
||||
virtual uint32_t get_pipeline_compilations(RS::PipelineSource p_source) override;
|
||||
|
||||
/* SHADER LIBRARY */
|
||||
|
||||
virtual void enable_features(BitField<FeatureBits> p_feature_bits) override;
|
||||
virtual String get_name() const override;
|
||||
|
||||
virtual bool free(RID p_rid) override;
|
||||
|
||||
virtual void update() override;
|
||||
|
||||
virtual void base_uniforms_changed() override;
|
||||
|
||||
virtual bool is_dynamic_gi_supported() const override;
|
||||
virtual bool is_volumetric_supported() const override;
|
||||
virtual uint32_t get_max_elements() const override;
|
||||
|
||||
RenderForwardMobile();
|
||||
~RenderForwardMobile();
|
||||
};
|
||||
} // namespace RendererSceneRenderImplementation
|
@@ -0,0 +1,966 @@
|
||||
/**************************************************************************/
|
||||
/* scene_shader_forward_mobile.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "scene_shader_forward_mobile.h"
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/math/math_defs.h"
|
||||
#include "render_forward_mobile.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
|
||||
|
||||
using namespace RendererSceneRenderImplementation;
|
||||
|
||||
/* ShaderData */
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
|
||||
//compile
|
||||
|
||||
code = p_code;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
_clear_vertex_input_mask_cache();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; //just invalid, but no error
|
||||
}
|
||||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
blend_mode = BLEND_MODE_MIX;
|
||||
depth_test_disabledi = 0;
|
||||
depth_test_invertedi = 0;
|
||||
alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
uses_point_size = false;
|
||||
uses_alpha = false;
|
||||
uses_alpha_clip = false;
|
||||
uses_alpha_antialiasing = false;
|
||||
uses_blend_alpha = false;
|
||||
uses_depth_prepass_alpha = false;
|
||||
uses_discard = false;
|
||||
uses_roughness = false;
|
||||
uses_normal = false;
|
||||
uses_tangent = false;
|
||||
uses_normal_map = false;
|
||||
uses_bent_normal_map = false;
|
||||
wireframe = false;
|
||||
|
||||
unshaded = false;
|
||||
uses_vertex = false;
|
||||
uses_sss = false;
|
||||
uses_transmittance = false;
|
||||
uses_time = false;
|
||||
writes_modelview_or_projection = false;
|
||||
uses_world_coordinates = false;
|
||||
uses_particle_trails = false;
|
||||
|
||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||
|
||||
int stencil_readi = 0;
|
||||
int stencil_writei = 0;
|
||||
int stencil_write_depth_faili = 0;
|
||||
int stencil_comparei = STENCIL_COMPARE_ALWAYS;
|
||||
int stencil_referencei = -1;
|
||||
|
||||
ShaderCompiler::IdentifierActions actions;
|
||||
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
|
||||
actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||
actions.entry_point_stages["light"] = ShaderCompiler::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["blend_premul_alpha"] = Pair<int *, int>(&blend_mode, BLEND_MODE_PREMULTIPLIED_ALPHA);
|
||||
|
||||
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
||||
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_test_disabledi, 1);
|
||||
actions.render_mode_values["depth_test_inverted"] = Pair<int *, int>(&depth_test_invertedi, 1);
|
||||
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_mode, RS::CULL_MODE_BACK);
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
|
||||
actions.render_mode_flags["world_vertex_coords"] = &uses_world_coordinates;
|
||||
|
||||
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
|
||||
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
|
||||
actions.usage_flag_pointers["ALPHA_HASH_SCALE"] = &uses_alpha_clip;
|
||||
actions.usage_flag_pointers["ALPHA_ANTIALIASING_EDGE"] = &uses_alpha_antialiasing;
|
||||
actions.usage_flag_pointers["ALPHA_TEXTURE_COORDINATE"] = &uses_alpha_antialiasing;
|
||||
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_prepass_alpha;
|
||||
|
||||
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
|
||||
actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
|
||||
|
||||
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_map;
|
||||
actions.usage_flag_pointers["BENT_NORMAL_MAP"] = &uses_bent_normal_map;
|
||||
|
||||
actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
|
||||
actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
|
||||
actions.usage_flag_pointers["ANISOTROPY"] = &uses_tangent;
|
||||
actions.usage_flag_pointers["ANISOTROPY_FLOW"] = &uses_tangent;
|
||||
|
||||
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.stencil_mode_values["read"] = Pair<int *, int>(&stencil_readi, STENCIL_FLAG_READ);
|
||||
actions.stencil_mode_values["write"] = Pair<int *, int>(&stencil_writei, STENCIL_FLAG_WRITE);
|
||||
actions.stencil_mode_values["write_depth_fail"] = Pair<int *, int>(&stencil_write_depth_faili, STENCIL_FLAG_WRITE_DEPTH_FAIL);
|
||||
|
||||
actions.stencil_mode_values["compare_less"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS);
|
||||
actions.stencil_mode_values["compare_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_EQUAL);
|
||||
actions.stencil_mode_values["compare_less_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_LESS_OR_EQUAL);
|
||||
actions.stencil_mode_values["compare_greater"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER);
|
||||
actions.stencil_mode_values["compare_not_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_NOT_EQUAL);
|
||||
actions.stencil_mode_values["compare_greater_or_equal"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_GREATER_OR_EQUAL);
|
||||
actions.stencil_mode_values["compare_always"] = Pair<int *, int>(&stencil_comparei, STENCIL_COMPARE_ALWAYS);
|
||||
|
||||
actions.stencil_reference = &stencil_referencei;
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
Error err = SceneShaderForwardMobile::singleton->compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
|
||||
if (err != OK) {
|
||||
if (version.is_valid()) {
|
||||
SceneShaderForwardMobile::singleton->shader.version_free(version);
|
||||
version = RID();
|
||||
}
|
||||
ERR_FAIL_MSG("Shader compilation failed.");
|
||||
}
|
||||
|
||||
if (version.is_null()) {
|
||||
version = SceneShaderForwardMobile::singleton->shader.version_create(false);
|
||||
}
|
||||
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
if (depth_test_disabledi) {
|
||||
depth_test = DEPTH_TEST_DISABLED;
|
||||
} else if (depth_test_invertedi) {
|
||||
depth_test = DEPTH_TEST_ENABLED_INVERTED;
|
||||
} else {
|
||||
depth_test = DEPTH_TEST_ENABLED;
|
||||
}
|
||||
uses_vertex_time = gen_code.uses_vertex_time;
|
||||
uses_fragment_time = gen_code.uses_fragment_time;
|
||||
uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
|
||||
uses_screen_texture = gen_code.uses_screen_texture;
|
||||
uses_depth_texture = gen_code.uses_depth_texture;
|
||||
uses_normal_texture = gen_code.uses_normal_roughness_texture;
|
||||
uses_normal |= uses_normal_map;
|
||||
uses_normal |= uses_bent_normal_map;
|
||||
uses_tangent |= uses_normal_map;
|
||||
uses_tangent |= uses_bent_normal_map;
|
||||
|
||||
stencil_enabled = stencil_referencei != -1;
|
||||
stencil_flags = stencil_readi | stencil_writei | stencil_write_depth_faili;
|
||||
stencil_compare = StencilCompare(stencil_comparei);
|
||||
stencil_reference = stencil_referencei;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (uses_sss) {
|
||||
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
|
||||
}
|
||||
|
||||
if (uses_transmittance) {
|
||||
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ renderer.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#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]);
|
||||
}
|
||||
|
||||
HashMap<String, String>::Iterator el = gen_code.code.begin();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key + ":\n" + el->value);
|
||||
++el;
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
SceneShaderForwardMobile::singleton->shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
uses_blend_alpha = blend_mode_uses_blend_alpha(BlendMode(blend_mode));
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_animated() const {
|
||||
return (uses_fragment_time && uses_discard) || (uses_vertex_time && uses_vertex);
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::casts_shadows() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing)) || has_read_screen_alpha;
|
||||
bool has_alpha = has_base_alpha || uses_blend_alpha;
|
||||
|
||||
return !has_alpha || (uses_depth_prepass_alpha && !(depth_draw == DEPTH_DRAW_DISABLED || depth_test != DEPTH_TEST_ENABLED));
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SceneShaderForwardMobile::ShaderData::get_native_source_code() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_native_source_code(version);
|
||||
} else {
|
||||
return RS::ShaderNativeSourceCode();
|
||||
}
|
||||
}
|
||||
|
||||
Pair<ShaderRD *, RID> SceneShaderForwardMobile::ShaderData::get_native_shader_and_version() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return { &SceneShaderForwardMobile::singleton->shader, version };
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::_create_pipeline(PipelineKey p_pipeline_key) {
|
||||
#if PRINT_PIPELINE_COMPILATION_KEYS
|
||||
print_line(
|
||||
"HASH:", p_pipeline_key.hash(),
|
||||
"VERSION:", version,
|
||||
"VERTEX:", p_pipeline_key.vertex_format_id,
|
||||
"FRAMEBUFFER:", p_pipeline_key.framebuffer_format_id,
|
||||
"CULL:", p_pipeline_key.cull_mode,
|
||||
"PRIMITIVE:", p_pipeline_key.primitive_type,
|
||||
"VERSION:", p_pipeline_key.version,
|
||||
"SPEC PACKED #0:", p_pipeline_key.shader_specialization.packed_0,
|
||||
"SPEC PACKED #1:", p_pipeline_key.shader_specialization.packed_1,
|
||||
"SPEC PACKED #2:", p_pipeline_key.shader_specialization.packed_2,
|
||||
"RENDER PASS:", p_pipeline_key.render_pass,
|
||||
"WIREFRAME:", p_pipeline_key.wireframe);
|
||||
#endif
|
||||
|
||||
RD::PipelineColorBlendState::Attachment blend_attachment = blend_mode_to_blend_attachment(BlendMode(blend_mode));
|
||||
RD::PipelineColorBlendState blend_state_blend;
|
||||
blend_state_blend.attachments.push_back(blend_attachment);
|
||||
RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1);
|
||||
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.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false;
|
||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_GREATER_OR_EQUAL;
|
||||
|
||||
if (depth_test == DEPTH_TEST_ENABLED_INVERTED) {
|
||||
depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
depth_stencil_state.enable_stencil = stencil_enabled;
|
||||
if (stencil_enabled) {
|
||||
static const RD::CompareOperator stencil_compare_rd_table[STENCIL_COMPARE_MAX] = {
|
||||
RD::COMPARE_OP_LESS,
|
||||
RD::COMPARE_OP_EQUAL,
|
||||
RD::COMPARE_OP_LESS_OR_EQUAL,
|
||||
RD::COMPARE_OP_GREATER,
|
||||
RD::COMPARE_OP_NOT_EQUAL,
|
||||
RD::COMPARE_OP_GREATER_OR_EQUAL,
|
||||
RD::COMPARE_OP_ALWAYS,
|
||||
};
|
||||
|
||||
uint32_t stencil_mask = 255;
|
||||
|
||||
RD::PipelineDepthStencilState::StencilOperationState op;
|
||||
op.fail = RD::STENCIL_OP_KEEP;
|
||||
op.pass = RD::STENCIL_OP_KEEP;
|
||||
op.depth_fail = RD::STENCIL_OP_KEEP;
|
||||
op.compare = stencil_compare_rd_table[stencil_compare];
|
||||
op.compare_mask = 0;
|
||||
op.write_mask = 0;
|
||||
op.reference = stencil_reference;
|
||||
|
||||
if (stencil_flags & STENCIL_FLAG_READ) {
|
||||
op.compare_mask = stencil_mask;
|
||||
}
|
||||
|
||||
if (stencil_flags & STENCIL_FLAG_WRITE) {
|
||||
op.pass = RD::STENCIL_OP_REPLACE;
|
||||
op.write_mask = stencil_mask;
|
||||
}
|
||||
|
||||
if (stencil_flags & STENCIL_FLAG_WRITE_DEPTH_FAIL) {
|
||||
op.depth_fail = RD::STENCIL_OP_REPLACE;
|
||||
op.write_mask = stencil_mask;
|
||||
}
|
||||
|
||||
depth_stencil_state.front_op = op;
|
||||
depth_stencil_state.back_op = op;
|
||||
}
|
||||
|
||||
RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[p_pipeline_key.primitive_type];
|
||||
|
||||
RD::PipelineRasterizationState raster_state;
|
||||
raster_state.cull_mode = p_pipeline_key.cull_mode;
|
||||
raster_state.wireframe = wireframe || p_pipeline_key.wireframe;
|
||||
|
||||
RD::PipelineMultisampleState multisample_state;
|
||||
multisample_state.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_pipeline_key.framebuffer_format_id, 0);
|
||||
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
if (uses_alpha || uses_blend_alpha) {
|
||||
// These flags should only go through if we have some form of MSAA.
|
||||
if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
} else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) {
|
||||
multisample_state.enable_alpha_to_coverage = true;
|
||||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE && !uses_alpha_clip) {
|
||||
// Alpha does not write to depth.
|
||||
depth_stencil_state.enable_depth_write = false;
|
||||
}
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
// Contains nothing.
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
// Writes to normal and roughness in opaque way.
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5);
|
||||
} else {
|
||||
// Do not use this version (error case).
|
||||
}
|
||||
} else {
|
||||
if (p_pipeline_key.version == SHADER_VERSION_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS || p_pipeline_key.version == SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_MOTION_VECTORS_MULTIVIEW) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_MULTIVIEW || p_pipeline_key.version == SHADER_VERSION_SHADOW_PASS_DP) {
|
||||
// Contains nothing.
|
||||
} else if (p_pipeline_key.version == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) {
|
||||
// Writes to normal and roughness in opaque way.
|
||||
blend_state = RD::PipelineColorBlendState::create_disabled(5);
|
||||
} else {
|
||||
// Unknown pipeline version.
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the specialization from the key to pipeline specialization constants.
|
||||
Vector<RD::PipelineSpecializationConstant> specialization_constants;
|
||||
RD::PipelineSpecializationConstant sc;
|
||||
sc.constant_id = 0;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_0;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 1;
|
||||
sc.int_value = p_pipeline_key.shader_specialization.packed_1;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_INT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
sc.constant_id = 2;
|
||||
sc.float_value = p_pipeline_key.shader_specialization.packed_2;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_FLOAT;
|
||||
specialization_constants.push_back(sc);
|
||||
|
||||
RID shader_rid = get_shader_variant(p_pipeline_key.version, p_pipeline_key.ubershader);
|
||||
ERR_FAIL_COND(shader_rid.is_null());
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader_rid, p_pipeline_key.framebuffer_format_id, p_pipeline_key.vertex_format_id, primitive_rd, raster_state, multisample_state, depth_stencil_state, blend_state, 0, p_pipeline_key.render_pass, specialization_constants);
|
||||
ERR_FAIL_COND(pipeline.is_null());
|
||||
|
||||
pipeline_hash_map.add_compiled_pipeline(p_pipeline_key.hash(), pipeline);
|
||||
}
|
||||
|
||||
RD::PolygonCullMode SceneShaderForwardMobile::ShaderData::get_cull_mode_from_cull_variant(CullVariant p_cull_variant) {
|
||||
const RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = {
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT },
|
||||
{ RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED }
|
||||
};
|
||||
|
||||
return cull_mode_rd_table[p_cull_variant][cull_mode];
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::ShaderData::_clear_vertex_input_mask_cache() {
|
||||
for (uint32_t i = 0; i < VERTEX_INPUT_MASKS_SIZE; i++) {
|
||||
vertex_input_masks[i].store(0);
|
||||
}
|
||||
}
|
||||
|
||||
RID SceneShaderForwardMobile::ShaderData::get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, RID());
|
||||
return SceneShaderForwardMobile::singleton->shader.version_get_shader(version, p_shader_version + (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + (p_ubershader ? SHADER_VERSION_MAX : 0));
|
||||
} else {
|
||||
return RID();
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t SceneShaderForwardMobile::ShaderData::get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader) {
|
||||
// Vertex input masks require knowledge of the shader. Since querying the shader can be expensive due to high contention and the necessary mutex, we cache the result instead.
|
||||
// It is intentional for the range of the input masks to be different than the versions available in the shaders as it'll only ever use the regular variants or the FP16 ones.
|
||||
uint32_t input_mask_index = p_shader_version + (p_ubershader ? SHADER_VERSION_MAX : 0);
|
||||
uint64_t input_mask = vertex_input_masks[input_mask_index].load(std::memory_order_relaxed);
|
||||
if (input_mask == 0) {
|
||||
RID shader_rid = get_shader_variant(p_shader_version, p_ubershader);
|
||||
ERR_FAIL_COND_V(shader_rid.is_null(), 0);
|
||||
|
||||
input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(shader_rid);
|
||||
vertex_input_masks[input_mask_index].store(input_mask, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
return input_mask;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::ShaderData::is_valid() const {
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL_V(SceneShaderForwardMobile::singleton, false);
|
||||
return SceneShaderForwardMobile::singleton->shader.version_is_valid(version);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::ShaderData() :
|
||||
shader_list_element(this) {
|
||||
pipeline_hash_map.set_creation_object_and_function(this, &ShaderData::_create_pipeline);
|
||||
pipeline_hash_map.set_compilations(SceneShaderForwardMobile::singleton->pipeline_compilations, &SceneShaderForwardMobile::singleton_mutex);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::ShaderData::~ShaderData() {
|
||||
pipeline_hash_map.clear_pipelines();
|
||||
|
||||
if (version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ERR_FAIL_NULL(SceneShaderForwardMobile::singleton);
|
||||
SceneShaderForwardMobile::singleton->shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
ShaderData *shader_data = memnew(ShaderData);
|
||||
singleton->shader_list.add(&shader_data->shader_list_element);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
if (shader_data->version.is_valid()) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
RID base_shader = SceneShaderForwardMobile::singleton->shader.version_get_shader(shader_data->version, (SceneShaderForwardMobile::singleton->use_fp16 ? SHADER_VERSION_MAX * 2 : 0));
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, base_shader, RenderForwardMobile::MATERIAL_UNIFORM_SET, true, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::MaterialData::~MaterialData() {
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
|
||||
MaterialData *material_data = memnew(MaterialData);
|
||||
material_data->shader_data = p_shader;
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
/* Scene Shader */
|
||||
|
||||
SceneShaderForwardMobile *SceneShaderForwardMobile::singleton = nullptr;
|
||||
Mutex SceneShaderForwardMobile::singleton_mutex;
|
||||
|
||||
SceneShaderForwardMobile::SceneShaderForwardMobile() {
|
||||
// there should be only one of these, contained within our RenderForwardMobile singleton.
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::init(const String p_defines) {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
// Store whether the shader will prefer using the FP16 variant.
|
||||
use_fp16 = RD::get_singleton()->has_feature(RD::SUPPORTS_HALF_FLOAT);
|
||||
|
||||
// Immutable samplers : create the shadow sampler to be passed when creating the pipeline.
|
||||
{
|
||||
RD::SamplerState sampler;
|
||||
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
|
||||
sampler.enable_compare = true;
|
||||
sampler.compare_op = RD::COMPARE_OP_GREATER;
|
||||
shadow_sampler = RD::get_singleton()->sampler_create(sampler);
|
||||
}
|
||||
|
||||
/* SCENE SHADER */
|
||||
|
||||
{
|
||||
Vector<ShaderRD::VariantDefine> shader_versions;
|
||||
for (uint32_t fp16 = 0; fp16 < 2; fp16++) {
|
||||
for (uint32_t ubershader = 0; ubershader < 2; ubershader++) {
|
||||
String base_define = fp16 ? "\n#define EXPLICIT_FP16\n" : "";
|
||||
int shader_group = fp16 ? SHADER_GROUP_FP16 : SHADER_GROUP_FP32;
|
||||
int shader_group_multiview = fp16 ? SHADER_GROUP_FP16_MULTIVIEW : SHADER_GROUP_FP32_MULTIVIEW;
|
||||
base_define += ubershader ? "\n#define UBERSHADER\n" : "";
|
||||
|
||||
bool default_enabled = (uint32_t(use_fp16) == fp16);
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "", default_enabled)); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define USE_LIGHTMAP\n", default_enabled)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", default_enabled)); // 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(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n#define SHADOW_PASS\n", default_enabled)); // SHADER_VERSION_SHADOW_PASS_DP
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group, base_define + "\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n", default_enabled)); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
|
||||
// Multiview versions of our shaders.
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n", false)); // SHADER_VERSION_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define USE_LIGHTMAP\n", false)); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define SHADOW_PASS\n", false)); // SHADER_VERSION_SHADOW_PASS_MULTIVIEW
|
||||
shader_versions.push_back(ShaderRD::VariantDefine(shader_group_multiview, base_define + "\n#define USE_MULTIVIEW\n#define MODE_RENDER_MOTION_VECTORS\n", false)); // SHADER_VERSION_MOTION_VECTORS_MULTIVIEW
|
||||
}
|
||||
}
|
||||
|
||||
Vector<RD::PipelineImmutableSampler> immutable_samplers;
|
||||
RD::PipelineImmutableSampler immutable_shadow_sampler;
|
||||
immutable_shadow_sampler.binding = 2;
|
||||
immutable_shadow_sampler.append_id(shadow_sampler);
|
||||
immutable_shadow_sampler.uniform_type = RenderingDeviceCommons::UNIFORM_TYPE_SAMPLER;
|
||||
immutable_samplers.push_back(immutable_shadow_sampler);
|
||||
shader.initialize(shader_versions, p_defines, immutable_samplers);
|
||||
|
||||
if (RendererCompositorRD::get_singleton()->is_xr_enabled()) {
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
|
||||
material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
|
||||
|
||||
{
|
||||
//shader compiler
|
||||
ShaderCompiler::DefaultIdentifierActions actions;
|
||||
|
||||
actions.renames["MODEL_MATRIX"] = "read_model_matrix";
|
||||
actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix";
|
||||
actions.renames["VIEW_MATRIX"] = "read_view_matrix";
|
||||
actions.renames["INV_VIEW_MATRIX"] = "inv_view_matrix";
|
||||
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
|
||||
actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
|
||||
actions.renames["MODELVIEW_MATRIX"] = "modelview";
|
||||
actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal";
|
||||
actions.renames["MAIN_CAM_INV_VIEW_MATRIX"] = "scene_data.main_cam_inv_view_matrix";
|
||||
|
||||
actions.renames["VERTEX"] = "vertex";
|
||||
actions.renames["NORMAL"] = "normal_highp";
|
||||
actions.renames["TANGENT"] = "tangent_highp";
|
||||
actions.renames["BINORMAL"] = "binormal_highp";
|
||||
actions.renames["POSITION"] = "position";
|
||||
actions.renames["UV"] = "uv_interp";
|
||||
actions.renames["UV2"] = "uv2_interp";
|
||||
actions.renames["COLOR"] = "color_highp";
|
||||
actions.renames["POINT_SIZE"] = "gl_PointSize";
|
||||
actions.renames["INSTANCE_ID"] = "gl_InstanceIndex";
|
||||
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
|
||||
actions.renames["Z_CLIP_SCALE"] = "z_clip_scale";
|
||||
|
||||
actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold_highp";
|
||||
actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale_highp";
|
||||
actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge_highp";
|
||||
actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate";
|
||||
|
||||
//builtins
|
||||
|
||||
actions.renames["TIME"] = "scene_data_block.data.time";
|
||||
actions.renames["EXPOSURE"] = "(1.0 / scene_data_block.data.emissive_exposure_normalization)";
|
||||
actions.renames["PI"] = String::num(Math::PI);
|
||||
actions.renames["TAU"] = String::num(Math::TAU);
|
||||
actions.renames["E"] = String::num(Math::E);
|
||||
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
|
||||
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
|
||||
actions.renames["IN_SHADOW_PASS"] = "IN_SHADOW_PASS";
|
||||
actions.renames["VIEWPORT_SIZE"] = "read_viewport_size";
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
actions.renames["FRONT_FACING"] = "gl_FrontFacing";
|
||||
actions.renames["NORMAL_MAP"] = "normal_map_highp";
|
||||
actions.renames["NORMAL_MAP_DEPTH"] = "normal_map_depth_highp";
|
||||
actions.renames["BENT_NORMAL_MAP"] = "bent_normal_map_highp";
|
||||
actions.renames["ALBEDO"] = "albedo_highp";
|
||||
actions.renames["ALPHA"] = "alpha_highp";
|
||||
actions.renames["PREMUL_ALPHA_FACTOR"] = "premul_alpha_highp";
|
||||
actions.renames["METALLIC"] = "metallic_highp";
|
||||
actions.renames["SPECULAR"] = "specular_highp";
|
||||
actions.renames["ROUGHNESS"] = "roughness_highp";
|
||||
actions.renames["RIM"] = "rim_highp";
|
||||
actions.renames["RIM_TINT"] = "rim_tint_highp";
|
||||
actions.renames["CLEARCOAT"] = "clearcoat_highp";
|
||||
actions.renames["CLEARCOAT_ROUGHNESS"] = "clearcoat_roughness_highp";
|
||||
actions.renames["ANISOTROPY"] = "anisotropy_highp";
|
||||
actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow_highp";
|
||||
actions.renames["SSS_STRENGTH"] = "sss_strength_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_COLOR"] = "transmittance_color_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_DEPTH"] = "transmittance_depth_highp";
|
||||
actions.renames["SSS_TRANSMITTANCE_BOOST"] = "transmittance_boost_highp";
|
||||
actions.renames["BACKLIGHT"] = "backlight_highp";
|
||||
actions.renames["AO"] = "ao_highp";
|
||||
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect_highp";
|
||||
actions.renames["EMISSION"] = "emission_highp";
|
||||
actions.renames["POINT_COORD"] = "gl_PointCoord";
|
||||
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
|
||||
actions.renames["SCREEN_UV"] = "screen_uv";
|
||||
actions.renames["DEPTH"] = "gl_FragDepth";
|
||||
actions.renames["FOG"] = "fog_highp";
|
||||
actions.renames["RADIANCE"] = "custom_radiance_highp";
|
||||
actions.renames["IRRADIANCE"] = "custom_irradiance_highp";
|
||||
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";
|
||||
actions.renames["LIGHT_VERTEX"] = "light_vertex";
|
||||
|
||||
actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
|
||||
actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
|
||||
actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.inv_view_matrix[2].xyz";
|
||||
actions.renames["CAMERA_VISIBLE_LAYERS"] = "scene_data.camera_visible_layers";
|
||||
actions.renames["NODE_POSITION_VIEW"] = "(scene_data.view_matrix * read_model_matrix)[3].xyz";
|
||||
|
||||
actions.renames["VIEW_INDEX"] = "ViewIndex";
|
||||
actions.renames["VIEW_MONO_LEFT"] = "0";
|
||||
actions.renames["VIEW_RIGHT"] = "1";
|
||||
actions.renames["EYE_OFFSET"] = "eye_offset";
|
||||
|
||||
//for light
|
||||
actions.renames["VIEW"] = "view_highp";
|
||||
actions.renames["SPECULAR_AMOUNT"] = "specular_amount_highp";
|
||||
actions.renames["LIGHT_COLOR"] = "light_color_highp";
|
||||
actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
|
||||
actions.renames["LIGHT"] = "light_highp";
|
||||
actions.renames["ATTENUATION"] = "attenuation_highp";
|
||||
actions.renames["DIFFUSE_LIGHT"] = "diffuse_light_highp";
|
||||
actions.renames["SPECULAR_LIGHT"] = "specular_light_highp";
|
||||
|
||||
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_ROUGHNESS"] = "@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_USED\n";
|
||||
actions.usage_defines["CUSTOM1"] = "#define CUSTOM1_USED\n";
|
||||
actions.usage_defines["CUSTOM2"] = "#define CUSTOM2_USED\n";
|
||||
actions.usage_defines["CUSTOM3"] = "#define CUSTOM3_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
|
||||
actions.usage_defines["NORMAL_MAP_DEPTH"] = "@NORMAL_MAP";
|
||||
actions.usage_defines["BENT_NORMAL_MAP"] = "#define BENT_NORMAL_MAP_USED\n";
|
||||
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["LIGHT_VERTEX"] = "#define LIGHT_VERTEX_USED\n";
|
||||
actions.usage_defines["Z_CLIP_SCALE"] = "#define Z_CLIP_SCALE_USED\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["PREMUL_ALPHA_FACTOR"] = "#define PREMUL_ALPHA_USED";
|
||||
|
||||
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_UV"] = "#define SCREEN_UV_USED\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.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_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";
|
||||
actions.render_mode_defines["depth_prepass_alpha"] = "#define USE_OPAQUE_PREPASS\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_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";
|
||||
|
||||
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\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";
|
||||
|
||||
bool force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
|
||||
if (!force_vertex_shading) {
|
||||
// If forcing vertex shading, this will be defined already.
|
||||
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
|
||||
}
|
||||
|
||||
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
|
||||
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
|
||||
|
||||
actions.render_mode_defines["specular_occlusion_disabled"] = "#define SPECULAR_OCCLUSION_DISABLED\n";
|
||||
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 14;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
actions.global_buffer_array_variable = "global_shader_uniforms.data";
|
||||
actions.instance_uniform_index_variable = "instances.data[draw_call.instance_index].instance_uniforms_ofs";
|
||||
|
||||
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
|
||||
actions.check_multiview_samplers = true;
|
||||
|
||||
compiler.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
//default material and shader
|
||||
default_shader = material_storage->shader_allocate();
|
||||
material_storage->shader_initialize(default_shader);
|
||||
material_storage->shader_set_code(default_shader, R"(
|
||||
// Default 3D material shader (Mobile).
|
||||
|
||||
shader_type spatial;
|
||||
|
||||
void vertex() {
|
||||
ROUGHNESS = 0.8;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = vec3(0.6);
|
||||
ROUGHNESS = 0.8;
|
||||
METALLIC = 0.2;
|
||||
}
|
||||
)");
|
||||
default_material = material_storage->material_allocate();
|
||||
material_storage->material_initialize(default_material);
|
||||
material_storage->material_set_shader(default_material, default_shader);
|
||||
|
||||
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
|
||||
default_shader_rd = shader.version_get_shader(md->shader_data->version, (use_fp16 ? SHADER_VERSION_MAX * 2 : 0) + SHADER_VERSION_COLOR_PASS);
|
||||
|
||||
default_material_shader_ptr = md->shader_data;
|
||||
default_material_uniform_set = md->uniform_set;
|
||||
}
|
||||
|
||||
{
|
||||
overdraw_material_shader = material_storage->shader_allocate();
|
||||
material_storage->shader_initialize(overdraw_material_shader);
|
||||
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
|
||||
material_storage->shader_set_code(overdraw_material_shader, R"(
|
||||
// 3D editor Overdraw debug draw mode shader (Mobile).
|
||||
|
||||
shader_type spatial;
|
||||
|
||||
render_mode blend_add, unshaded, fog_disabled;
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = vec3(0.4, 0.8, 0.8);
|
||||
ALPHA = 0.1;
|
||||
}
|
||||
)");
|
||||
overdraw_material = material_storage->material_allocate();
|
||||
material_storage->material_initialize(overdraw_material);
|
||||
material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
|
||||
|
||||
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
|
||||
overdraw_material_shader_ptr = md->shader_data;
|
||||
overdraw_material_uniform_set = md->uniform_set;
|
||||
}
|
||||
|
||||
{
|
||||
debug_shadow_splits_material_shader = material_storage->shader_allocate();
|
||||
material_storage->shader_initialize(debug_shadow_splits_material_shader);
|
||||
// Use relatively low opacity so that more "layers" of overlapping objects can be distinguished.
|
||||
material_storage->shader_set_code(debug_shadow_splits_material_shader, R"(
|
||||
// 3D debug shadow splits mode shader (Mobile).
|
||||
|
||||
shader_type spatial;
|
||||
|
||||
render_mode debug_shadow_splits, fog_disabled;
|
||||
|
||||
void fragment() {
|
||||
ALBEDO = vec3(1.0, 1.0, 1.0);
|
||||
}
|
||||
)");
|
||||
debug_shadow_splits_material = material_storage->material_allocate();
|
||||
material_storage->material_initialize(debug_shadow_splits_material);
|
||||
material_storage->material_set_shader(debug_shadow_splits_material, debug_shadow_splits_material_shader);
|
||||
|
||||
MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(debug_shadow_splits_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
|
||||
debug_shadow_splits_material_shader_ptr = md->shader_data;
|
||||
debug_shadow_splits_material_uniform_set = md->uniform_set;
|
||||
}
|
||||
|
||||
{
|
||||
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.append_id(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);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::set_default_specialization(const ShaderSpecialization &p_specialization) {
|
||||
default_specialization = p_specialization;
|
||||
|
||||
for (SelfList<ShaderData> *E = shader_list.first(); E; E = E->next()) {
|
||||
E->self()->pipeline_hash_map.clear_pipelines();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SceneShaderForwardMobile::get_pipeline_compilations(RS::PipelineSource p_source) {
|
||||
MutexLock lock(SceneShaderForwardMobile::singleton_mutex);
|
||||
return pipeline_compilations[p_source];
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_fp32_shader_group() {
|
||||
shader.enable_group(SHADER_GROUP_FP32);
|
||||
|
||||
if (is_multiview_shader_group_enabled()) {
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_fp16_shader_group() {
|
||||
shader.enable_group(SHADER_GROUP_FP16);
|
||||
|
||||
if (is_multiview_shader_group_enabled()) {
|
||||
enable_multiview_shader_group();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderForwardMobile::enable_multiview_shader_group() {
|
||||
if (shader.is_group_enabled(SHADER_GROUP_FP32)) {
|
||||
shader.enable_group(SHADER_GROUP_FP32_MULTIVIEW);
|
||||
}
|
||||
|
||||
if (shader.is_group_enabled(SHADER_GROUP_FP16)) {
|
||||
shader.enable_group(SHADER_GROUP_FP16_MULTIVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneShaderForwardMobile::is_multiview_shader_group_enabled() const {
|
||||
return shader.is_group_enabled(SHADER_GROUP_FP32_MULTIVIEW) || shader.is_group_enabled(SHADER_GROUP_FP16_MULTIVIEW);
|
||||
}
|
||||
|
||||
SceneShaderForwardMobile::~SceneShaderForwardMobile() {
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
RD::get_singleton()->free(default_vec4_xform_buffer);
|
||||
RD::get_singleton()->free(shadow_sampler);
|
||||
|
||||
material_storage->shader_free(overdraw_material_shader);
|
||||
material_storage->shader_free(default_shader);
|
||||
material_storage->shader_free(debug_shadow_splits_material_shader);
|
||||
|
||||
material_storage->material_free(overdraw_material);
|
||||
material_storage->material_free(default_material);
|
||||
material_storage->material_free(debug_shadow_splits_material);
|
||||
}
|
@@ -0,0 +1,380 @@
|
||||
/**************************************************************************/
|
||||
/* scene_shader_forward_mobile.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../storage_rd/material_storage.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_hash_map_rd.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl.gen.h"
|
||||
|
||||
namespace RendererSceneRenderImplementation {
|
||||
|
||||
class SceneShaderForwardMobile {
|
||||
private:
|
||||
static SceneShaderForwardMobile *singleton;
|
||||
static Mutex singleton_mutex;
|
||||
|
||||
public:
|
||||
enum ShaderVersion {
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
|
||||
SHADER_VERSION_SHADOW_PASS,
|
||||
SHADER_VERSION_SHADOW_PASS_DP,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
|
||||
SHADER_VERSION_COLOR_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_SHADOW_PASS_MULTIVIEW,
|
||||
SHADER_VERSION_MOTION_VECTORS_MULTIVIEW,
|
||||
|
||||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
enum ShaderCount {
|
||||
SHADER_COUNT_NONE,
|
||||
SHADER_COUNT_SINGLE,
|
||||
SHADER_COUNT_MULTIPLE
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ static ShaderCount shader_count_for(uint32_t p_count) {
|
||||
if (p_count == 0) {
|
||||
return SHADER_COUNT_NONE;
|
||||
} else if (p_count == 1) {
|
||||
return SHADER_COUNT_SINGLE;
|
||||
} else {
|
||||
return SHADER_COUNT_MULTIPLE;
|
||||
}
|
||||
}
|
||||
|
||||
enum ShaderGroup {
|
||||
SHADER_GROUP_FP32,
|
||||
SHADER_GROUP_FP32_MULTIVIEW,
|
||||
SHADER_GROUP_FP16,
|
||||
SHADER_GROUP_FP16_MULTIVIEW,
|
||||
};
|
||||
|
||||
struct ShaderSpecialization {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t use_light_projector : 1;
|
||||
uint32_t use_light_soft_shadows : 1;
|
||||
uint32_t use_directional_soft_shadows : 1;
|
||||
uint32_t decal_use_mipmaps : 1;
|
||||
uint32_t projector_use_mipmaps : 1;
|
||||
uint32_t disable_fog : 1;
|
||||
uint32_t use_depth_fog : 1;
|
||||
uint32_t use_fog_aerial_perspective : 1;
|
||||
uint32_t use_fog_sun_scatter : 1;
|
||||
uint32_t use_fog_height_density : 1;
|
||||
uint32_t use_lightmap_bicubic_filter : 1;
|
||||
uint32_t multimesh : 1;
|
||||
uint32_t multimesh_format_2d : 1;
|
||||
uint32_t multimesh_has_color : 1;
|
||||
uint32_t multimesh_has_custom_data : 1;
|
||||
uint32_t scene_use_ambient_cubemap : 1;
|
||||
uint32_t scene_use_reflection_cubemap : 1;
|
||||
uint32_t scene_roughness_limiter_enabled : 1;
|
||||
uint32_t padding_0 : 2;
|
||||
uint32_t soft_shadow_samples : 6;
|
||||
uint32_t penumbra_shadow_samples : 6;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
uint32_t packed_1;
|
||||
|
||||
struct {
|
||||
uint32_t directional_soft_shadow_samples : 6;
|
||||
uint32_t directional_penumbra_shadow_samples : 6;
|
||||
uint32_t omni_lights : 2;
|
||||
uint32_t spot_lights : 2;
|
||||
uint32_t reflection_probes : 2;
|
||||
uint32_t directional_lights : 2;
|
||||
uint32_t decals : 1;
|
||||
uint32_t directional_light_blend_splits : 8;
|
||||
uint32_t padding_1 : 3;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
float packed_2;
|
||||
float luminance_multiplier;
|
||||
};
|
||||
};
|
||||
|
||||
struct UbershaderConstants {
|
||||
union {
|
||||
uint32_t packed_0;
|
||||
|
||||
struct {
|
||||
uint32_t cull_mode : 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
DEPTH_DRAW_ALWAYS
|
||||
};
|
||||
|
||||
enum DepthTest {
|
||||
DEPTH_TEST_DISABLED,
|
||||
DEPTH_TEST_ENABLED,
|
||||
DEPTH_TEST_ENABLED_INVERTED,
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
enum StencilFlags {
|
||||
STENCIL_FLAG_READ = 1,
|
||||
STENCIL_FLAG_WRITE = 2,
|
||||
STENCIL_FLAG_WRITE_DEPTH_FAIL = 4,
|
||||
};
|
||||
|
||||
enum StencilCompare {
|
||||
STENCIL_COMPARE_LESS,
|
||||
STENCIL_COMPARE_EQUAL,
|
||||
STENCIL_COMPARE_LESS_OR_EQUAL,
|
||||
STENCIL_COMPARE_GREATER,
|
||||
STENCIL_COMPARE_NOT_EQUAL,
|
||||
STENCIL_COMPARE_GREATER_OR_EQUAL,
|
||||
STENCIL_COMPARE_ALWAYS,
|
||||
STENCIL_COMPARE_MAX // Not an actual operator, just the amount of operators.
|
||||
};
|
||||
|
||||
struct PipelineKey {
|
||||
RD::VertexFormatID vertex_format_id;
|
||||
RD::FramebufferFormatID framebuffer_format_id;
|
||||
RD::PolygonCullMode cull_mode = RD::POLYGON_CULL_MAX;
|
||||
RS::PrimitiveType primitive_type = RS::PRIMITIVE_MAX;
|
||||
ShaderSpecialization shader_specialization = {};
|
||||
ShaderVersion version = SHADER_VERSION_MAX;
|
||||
uint32_t render_pass = 0;
|
||||
uint32_t wireframe = false;
|
||||
uint32_t ubershader = false;
|
||||
|
||||
uint32_t hash() const {
|
||||
uint32_t h = hash_murmur3_one_32(vertex_format_id);
|
||||
h = hash_murmur3_one_32(framebuffer_format_id, h);
|
||||
h = hash_murmur3_one_32(cull_mode, h);
|
||||
h = hash_murmur3_one_32(primitive_type, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_0, h);
|
||||
h = hash_murmur3_one_32(shader_specialization.packed_1, h);
|
||||
h = hash_murmur3_one_float(shader_specialization.packed_2, h);
|
||||
h = hash_murmur3_one_32(version, h);
|
||||
h = hash_murmur3_one_32(render_pass, h);
|
||||
h = hash_murmur3_one_32(wireframe, h);
|
||||
h = hash_murmur3_one_32(ubershader, h);
|
||||
return hash_fmix32(h);
|
||||
}
|
||||
};
|
||||
|
||||
void _create_pipeline(PipelineKey p_pipeline_key);
|
||||
PipelineHashMapRD<PipelineKey, ShaderData, void (ShaderData::*)(PipelineKey)> pipeline_hash_map;
|
||||
|
||||
RID version;
|
||||
|
||||
static const uint32_t VERTEX_INPUT_MASKS_SIZE = SHADER_VERSION_MAX * 2;
|
||||
std::atomic<uint64_t> vertex_input_masks[VERTEX_INPUT_MASKS_SIZE] = {};
|
||||
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size = 0;
|
||||
|
||||
String code;
|
||||
|
||||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
|
||||
int blend_mode = BLEND_MODE_MIX;
|
||||
int depth_test_disabledi = 0;
|
||||
int depth_test_invertedi = 0;
|
||||
int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_mode = RS::CULL_MODE_BACK;
|
||||
|
||||
bool uses_point_size = false;
|
||||
bool uses_alpha = false;
|
||||
bool uses_blend_alpha = false;
|
||||
bool uses_alpha_clip = false;
|
||||
bool uses_alpha_antialiasing = false;
|
||||
bool uses_depth_prepass_alpha = false;
|
||||
bool uses_discard = false;
|
||||
bool uses_roughness = false;
|
||||
bool uses_normal = false;
|
||||
bool uses_tangent = false;
|
||||
bool uses_particle_trails = false;
|
||||
bool uses_normal_map = false;
|
||||
bool uses_bent_normal_map = false;
|
||||
bool wireframe = false;
|
||||
|
||||
bool unshaded = false;
|
||||
bool uses_vertex = false;
|
||||
bool uses_sss = false;
|
||||
bool uses_transmittance = false;
|
||||
bool uses_screen_texture = false;
|
||||
bool uses_depth_texture = false;
|
||||
bool uses_normal_texture = false;
|
||||
bool uses_screen_texture_mipmaps = false;
|
||||
bool uses_time = false;
|
||||
bool uses_vertex_time = false;
|
||||
bool uses_fragment_time = false;
|
||||
bool writes_modelview_or_projection = false;
|
||||
bool uses_world_coordinates = false;
|
||||
|
||||
bool stencil_enabled = false;
|
||||
uint32_t stencil_flags = 0;
|
||||
StencilCompare stencil_compare = STENCIL_COMPARE_LESS;
|
||||
uint32_t stencil_reference = 0;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
_FORCE_INLINE_ bool uses_alpha_pass() const {
|
||||
bool has_read_screen_alpha = uses_screen_texture || uses_depth_texture || uses_normal_texture;
|
||||
bool has_base_alpha = (uses_alpha && (!uses_alpha_clip || uses_alpha_antialiasing));
|
||||
bool has_blend_alpha = uses_blend_alpha;
|
||||
bool has_alpha = has_base_alpha || has_blend_alpha;
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||
return has_alpha || has_read_screen_alpha || no_depth_draw || no_depth_test;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_depth_in_alpha_pass() const {
|
||||
bool no_depth_draw = depth_draw == DEPTH_DRAW_DISABLED;
|
||||
bool no_depth_test = depth_test != DEPTH_TEST_ENABLED;
|
||||
return (uses_depth_prepass_alpha || uses_alpha_antialiasing) && !(no_depth_draw || no_depth_test);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool uses_shared_shadow_material() const {
|
||||
return !uses_particle_trails && !writes_modelview_or_projection && !uses_vertex && !uses_discard && !uses_depth_prepass_alpha && !uses_alpha_clip && !uses_alpha_antialiasing && !uses_world_coordinates && !wireframe && !stencil_enabled;
|
||||
}
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
virtual Pair<ShaderRD *, RID> get_native_shader_and_version() const;
|
||||
RD::PolygonCullMode get_cull_mode_from_cull_variant(CullVariant p_cull_variant);
|
||||
void _clear_vertex_input_mask_cache();
|
||||
RID get_shader_variant(ShaderVersion p_shader_version, bool p_ubershader) const;
|
||||
uint64_t get_vertex_input_mask(ShaderVersion p_shader_version, bool p_ubershader);
|
||||
bool is_valid() const;
|
||||
|
||||
SelfList<ShaderData> shader_list_element;
|
||||
|
||||
ShaderData();
|
||||
virtual ~ShaderData();
|
||||
};
|
||||
|
||||
RendererRD::MaterialStorage::ShaderData *_create_shader_func();
|
||||
static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
|
||||
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
|
||||
}
|
||||
|
||||
struct MaterialData : public RendererRD::MaterialStorage::MaterialData {
|
||||
ShaderData *shader_data = nullptr;
|
||||
RID uniform_set;
|
||||
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 bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual ~MaterialData();
|
||||
};
|
||||
|
||||
SelfList<ShaderData>::List shader_list;
|
||||
|
||||
RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader);
|
||||
static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
|
||||
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
|
||||
}
|
||||
|
||||
SceneForwardMobileShaderRD shader;
|
||||
ShaderCompiler compiler;
|
||||
bool use_fp16 = false;
|
||||
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
RID overdraw_material_shader;
|
||||
RID overdraw_material;
|
||||
RID debug_shadow_splits_material_shader;
|
||||
RID debug_shadow_splits_material;
|
||||
RID default_shader_rd;
|
||||
|
||||
RID default_vec4_xform_buffer;
|
||||
RID default_vec4_xform_uniform_set;
|
||||
|
||||
RID shadow_sampler;
|
||||
|
||||
RID default_material_uniform_set;
|
||||
ShaderData *default_material_shader_ptr = nullptr;
|
||||
|
||||
RID overdraw_material_uniform_set;
|
||||
ShaderData *overdraw_material_shader_ptr = nullptr;
|
||||
|
||||
RID debug_shadow_splits_material_uniform_set;
|
||||
ShaderData *debug_shadow_splits_material_shader_ptr = nullptr;
|
||||
|
||||
SceneShaderForwardMobile();
|
||||
~SceneShaderForwardMobile();
|
||||
|
||||
ShaderSpecialization default_specialization = {};
|
||||
|
||||
uint32_t pipeline_compilations[RS::PIPELINE_SOURCE_MAX] = {};
|
||||
|
||||
void init(const String p_defines);
|
||||
void set_default_specialization(const ShaderSpecialization &p_specialization);
|
||||
uint32_t get_pipeline_compilations(RS::PipelineSource p_source);
|
||||
void enable_fp32_shader_group();
|
||||
void enable_fp16_shader_group();
|
||||
void enable_multiview_shader_group();
|
||||
bool is_multiview_shader_group_enabled() const;
|
||||
};
|
||||
|
||||
} // namespace RendererSceneRenderImplementation
|
Reference in New Issue
Block a user