mirror of
https://github.com/godotengine/godot.git
synced 2024-11-25 21:52:51 +00:00
Merge pull request #60643 from clayjohn/GLES3-3D
This commit is contained in:
commit
ff30a09993
@ -82,11 +82,6 @@ public:
|
||||
RENDER_SEPARATE_THREAD
|
||||
};
|
||||
|
||||
enum RenderMainThreadMode {
|
||||
RENDER_MAIN_THREAD_ONLY,
|
||||
RENDER_ANY_THREAD,
|
||||
};
|
||||
|
||||
protected:
|
||||
friend class Main;
|
||||
// Needed by tests to setup command-line args.
|
||||
@ -94,7 +89,6 @@ protected:
|
||||
|
||||
HasServerFeatureCallback has_server_feature_callback = nullptr;
|
||||
RenderThreadMode _render_thread_mode = RENDER_THREAD_SAFE;
|
||||
RenderMainThreadMode _render_main_thread_mode = RENDER_ANY_THREAD;
|
||||
|
||||
// Functions used by Main to initialize/deinitialize the OS.
|
||||
void add_logger(Logger *p_logger);
|
||||
@ -258,8 +252,6 @@ public:
|
||||
virtual uint64_t get_free_static_memory() const;
|
||||
|
||||
RenderThreadMode get_render_thread_mode() const { return _render_thread_mode; }
|
||||
RenderMainThreadMode get_render_main_thread_mode() const { return _render_main_thread_mode; }
|
||||
void set_render_main_thread_mode(RenderMainThreadMode p_thread_mode) { _render_main_thread_mode = p_thread_mode; }
|
||||
|
||||
virtual String get_locale() const;
|
||||
String get_locale_language() const;
|
||||
|
@ -1557,18 +1557,6 @@
|
||||
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_ticks_per_second] instead.
|
||||
[b]Note:[/b] Only 8 physics ticks may be simulated per rendered frame at most. If more than 8 physics ticks have to be simulated per rendered frame to keep up with rendering, the game will appear to slow down (even if [code]delta[/code] is used consistently in physics calculations). Therefore, it is recommended not to increase [member physics/common/physics_ticks_per_second] above 240. Otherwise, the game will slow down when the rendering framerate goes below 30 FPS.
|
||||
</member>
|
||||
<member name="rendering/2d/opengl/batching_send_null" type="int" setter="" getter="" default="0">
|
||||
</member>
|
||||
<member name="rendering/2d/opengl/batching_stream" type="int" setter="" getter="" default="0">
|
||||
</member>
|
||||
<member name="rendering/2d/opengl/legacy_orphan_buffers" type="int" setter="" getter="" default="0">
|
||||
</member>
|
||||
<member name="rendering/2d/opengl/legacy_stream" type="int" setter="" getter="" default="0">
|
||||
</member>
|
||||
<member name="rendering/2d/options/ninepatch_mode" type="int" setter="" getter="" default="1">
|
||||
</member>
|
||||
<member name="rendering/2d/options/use_software_skinning" type="bool" setter="" getter="" default="true">
|
||||
</member>
|
||||
<member name="rendering/2d/sdf/oversize" type="int" setter="" getter="" default="1">
|
||||
</member>
|
||||
<member name="rendering/2d/sdf/scale" type="int" setter="" getter="" default="1">
|
||||
@ -1594,32 +1582,6 @@
|
||||
</member>
|
||||
<member name="rendering/anti_aliasing/screen_space_roughness_limiter/limit" type="float" setter="" getter="" default="0.18">
|
||||
</member>
|
||||
<member name="rendering/batching/debug/diagnose_frame" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/debug/flash_batching" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/lights/max_join_items" type="int" setter="" getter="" default="32">
|
||||
</member>
|
||||
<member name="rendering/batching/lights/scissor_area_threshold" type="float" setter="" getter="" default="1.0">
|
||||
</member>
|
||||
<member name="rendering/batching/options/single_rect_fallback" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/options/use_batching" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/options/use_batching_in_editor" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/parameters/batch_buffer_size" type="int" setter="" getter="" default="16384">
|
||||
</member>
|
||||
<member name="rendering/batching/parameters/colored_vertex_format_threshold" type="float" setter="" getter="" default="0.25">
|
||||
</member>
|
||||
<member name="rendering/batching/parameters/item_reordering_lookahead" type="int" setter="" getter="" default="4">
|
||||
</member>
|
||||
<member name="rendering/batching/parameters/max_join_item_commands" type="int" setter="" getter="" default="16">
|
||||
</member>
|
||||
<member name="rendering/batching/precision/uv_contract" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/batching/precision/uv_contract_amount" type="int" setter="" getter="" default="100">
|
||||
</member>
|
||||
<member name="rendering/camera/depth_of_field/depth_of_field_bokeh_quality" type="int" setter="" getter="" default="1">
|
||||
Sets the quality of the depth of field effect. Higher quality takes more samples, which is slower but looks smoother.
|
||||
</member>
|
||||
@ -1629,13 +1591,16 @@
|
||||
<member name="rendering/camera/depth_of_field/depth_of_field_use_jitter" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], jitters DOF samples to make effect slightly blurrier and hide lines created from low sample rates. This can result in a slightly grainy appearance when used with a low number of samples.
|
||||
</member>
|
||||
<member name="rendering/driver/depth_prepass/disable_for_vendors" type="String" setter="" getter="" default=""PowerVR,Mali,Adreno,Apple"">
|
||||
Disables [member rendering/driver/depth_prepass/enable] conditionally for certain venders. By default, disables the depth prepass for mobile devices as mobile devices do not benefit from the depth prepass due to their unique architecture.
|
||||
</member>
|
||||
<member name="rendering/driver/depth_prepass/enable" type="bool" setter="" getter="" default="true">
|
||||
If [code]true[/code], performs a previous depth pass before rendering 3D materials. This increases performance significantly in scenes with high overdraw, when complex materials and lighting are used. However, in scenes with few occluded surfaces, the depth prepass may reduce performance. If your game is viewed from a fixed angle that makes it easy to avoid overdraw (such as top-down or side-scrolling perspective), consider disabling the depth prepass to improve performance. This setting can be changed at run-time to optimize performance depending on the scene currently being viewed.
|
||||
[b]Note:[/b] Only supported when using the Vulkan Clustered backend (not Vulkan Mobile or OpenGL). When using Vulkan Mobile or OpenGL, there is no depth prepass performed.
|
||||
[b]Note:[/b] Only supported when using the Vulkan Clustered backend or the OpenGL backend. When using Vulkan Mobile there is no depth prepass performed.
|
||||
</member>
|
||||
<member name="rendering/driver/driver_name" type="String" setter="" getter="" default=""vulkan"">
|
||||
The video driver to use.
|
||||
[b]Note:[/b] OpenGL support is currently incomplete. Only basic 2D rendering is supported, and single-window mode is required for correct operation.
|
||||
[b]Note:[/b] OpenGL support is currently incomplete. Only basic rendering is supported.
|
||||
[b]Note:[/b] The backend in use can be overridden at runtime via the [code]--rendering-driver[/code] command line argument.
|
||||
[b]FIXME:[/b] No longer valid after DisplayServer split:
|
||||
In such cases, this property is not updated, so use [code]OS.get_current_video_driver[/code] to query it at run-time.
|
||||
@ -1715,10 +1680,6 @@
|
||||
<member name="rendering/environment/volumetric_fog/volume_size" type="int" setter="" getter="" default="64">
|
||||
Base size used to determine size of froxel buffer in the camera X-axis and Y-axis. The final size is scaled by the aspect ratio of the screen, so actual values may differ from what is set. Set a larger size for more detailed fog, set a smaller size for better performance.
|
||||
</member>
|
||||
<member name="rendering/gles2/compatibility/disable_half_float" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/gles2/compatibility/enable_high_float.Android" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="rendering/global_illumination/gi/use_half_resolution" type="bool" setter="" getter="" default="false">
|
||||
If [code]true[/code], renders [VoxelGI] and SDFGI ([member Environment.sdfgi_enabled]) buffers at halved resolution (e.g. 960×540 when the viewport size is 1920×1080). This improves performance significantly when VoxelGI or SDFGI is enabled, at the cost of artifacts that may be visible on polygon edges. The loss in quality becomes less noticeable as the viewport resolution increases. [LightmapGI] rendering is not affected by this setting.
|
||||
[b]Note:[/b] This property is only read when the project starts. To set half-resolution GI at run-time, call [method RenderingServer.gi_set_use_half_resolution] instead.
|
||||
@ -1761,6 +1722,15 @@
|
||||
</member>
|
||||
<member name="rendering/limits/global_shader_variables/buffer_size" type="int" setter="" getter="" default="65536">
|
||||
</member>
|
||||
<member name="rendering/limits/opengl/max_lights_per_object" type="int" setter="" getter="" default="8">
|
||||
Max number of lights renderable per object. This is further limited by hardware support. Setting this low will slightly reduce memory usage, may decrease shader compile times, and may result in faster rendering on low-end, mobile, or web devices.
|
||||
</member>
|
||||
<member name="rendering/limits/opengl/max_renderable_elements" type="int" setter="" getter="" default="65536">
|
||||
Max amount of elements renderable in a frame. If more elements than this are visible per frame, they will not be drawn. Keep in mind elements refer to mesh surfaces and not meshes themselves. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export.
|
||||
</member>
|
||||
<member name="rendering/limits/opengl/max_renderable_lights" type="int" setter="" getter="" default="256">
|
||||
Max number of lights renderable in a frame. If more lights than this number are used, they will be ignored. Setting this low will slightly reduce memory usage and may decrease shader compile times, particularly on web. For most uses, the default value is suitable, but consider lowering as much as possible on web export.
|
||||
</member>
|
||||
<member name="rendering/limits/spatial_indexer/threaded_cull_minimum_instances" type="int" setter="" getter="" default="1000">
|
||||
</member>
|
||||
<member name="rendering/limits/spatial_indexer/update_iterations_per_frame" type="int" setter="" getter="" default="10">
|
||||
|
@ -179,12 +179,12 @@ void RasterizerCanvasGLES3::canvas_render_items(RID p_to_render_target, Item *p_
|
||||
|
||||
//print_line("w: " + itos(ssize.width) + " s: " + rtos(canvas_scale));
|
||||
state_buffer.tex_to_sdf = 1.0 / ((canvas_scale.x + canvas_scale.y) * 0.5);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_BUFFER_OBJECT, state.canvas_state_buffer);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, BASE_UNIFORM_LOCATION, state.canvas_state_buffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(StateBuffer), &state_buffer, GL_STREAM_DRAW);
|
||||
|
||||
GLuint global_buffer = material_storage->global_variables_get_uniform_buffer();
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_BUFFER_OBJECT, global_buffer);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, GLOBAL_UNIFORM_LOCATION, global_buffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
@ -522,7 +522,7 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item
|
||||
}
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData), &state.instance_data_array[0], GL_DYNAMIC_DRAW);
|
||||
@ -728,7 +728,7 @@ void RasterizerCanvasGLES3::_render_batch(uint32_t &r_index) {
|
||||
}
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_BUFFER_OBJECT, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, INSTANCE_UNIFORM_LOCATION, state.canvas_instance_data_buffers[state.current_buffer]);
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
//WebGL 2.0 does not support mapping buffers, so use slow glBufferData instead
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(InstanceData) * r_index, state.instance_data_array, GL_DYNAMIC_DRAW);
|
||||
|
@ -97,13 +97,12 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender {
|
||||
};
|
||||
|
||||
public:
|
||||
//TODO move to Material storage
|
||||
enum {
|
||||
BASE_UNIFORM_BUFFER_OBJECT = 0,
|
||||
GLOBAL_UNIFORM_BUFFER_OBJECT = 1,
|
||||
LIGHT_UNIFORM_BUFFER_OBJECT = 2,
|
||||
INSTANCE_UNIFORM_BUFFER_OBJECT = 3,
|
||||
MATERIAL_UNIFORM_BUFFER_OBJECT = 4,
|
||||
BASE_UNIFORM_LOCATION = 0,
|
||||
GLOBAL_UNIFORM_LOCATION = 1,
|
||||
LIGHT_UNIFORM_LOCATION = 2,
|
||||
INSTANCE_UNIFORM_LOCATION = 3,
|
||||
MATERIAL_UNIFORM_LOCATION = 4,
|
||||
};
|
||||
|
||||
struct StateBuffer {
|
||||
|
@ -268,10 +268,6 @@ RasterizerGLES3::RasterizerGLES3() {
|
||||
storage = memnew(RasterizerStorageGLES3);
|
||||
canvas = memnew(RasterizerCanvasGLES3(storage));
|
||||
scene = memnew(RasterizerSceneGLES3(storage));
|
||||
|
||||
texture_storage->set_main_thread_id(Thread::get_caller_id());
|
||||
// make sure the OS knows to only access the renderer from the main thread
|
||||
OS::get_singleton()->set_render_main_thread_mode(OS::RENDER_MAIN_THREAD_ONLY);
|
||||
}
|
||||
|
||||
RasterizerGLES3::~RasterizerGLES3() {
|
||||
|
@ -92,9 +92,9 @@ public:
|
||||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
low_end = true;
|
||||
}
|
||||
|
||||
virtual bool is_low_end() const { return true; }
|
||||
uint64_t get_frame_number() const { return frame; }
|
||||
double get_frame_delta_time() const { return delta; }
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,6 +34,7 @@
|
||||
#ifdef GLES3_ENABLED
|
||||
|
||||
#include "core/math/camera_matrix.h"
|
||||
#include "core/templates/paged_allocator.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "rasterizer_storage_gles3.h"
|
||||
@ -44,13 +45,47 @@
|
||||
#include "shader_gles3.h"
|
||||
#include "shaders/sky.glsl.gen.h"
|
||||
|
||||
// Copied from renderer_scene_render_rd
|
||||
enum RenderListType {
|
||||
RENDER_LIST_OPAQUE, //used for opaque objects
|
||||
RENDER_LIST_ALPHA, //used for transparent objects
|
||||
RENDER_LIST_SECONDARY, //used for shadows and other objects
|
||||
RENDER_LIST_MAX
|
||||
};
|
||||
|
||||
enum PassMode {
|
||||
PASS_MODE_COLOR,
|
||||
PASS_MODE_COLOR_TRANSPARENT,
|
||||
PASS_MODE_COLOR_ADDITIVE,
|
||||
PASS_MODE_SHADOW,
|
||||
PASS_MODE_DEPTH,
|
||||
};
|
||||
|
||||
// These should share as much as possible with SkyUniform Location
|
||||
enum SceneUniformLocation {
|
||||
SCENE_TONEMAP_UNIFORM_LOCATION,
|
||||
SCENE_GLOBALS_UNIFORM_LOCATION,
|
||||
SCENE_DATA_UNIFORM_LOCATION,
|
||||
SCENE_MATERIAL_UNIFORM_LOCATION,
|
||||
SCENE_RADIANCE_UNIFORM_LOCATION,
|
||||
SCENE_OMNILIGHT_UNIFORM_LOCATION,
|
||||
SCENE_SPOTLIGHT_UNIFORM_LOCATION,
|
||||
};
|
||||
|
||||
enum SkyUniformLocation {
|
||||
SKY_TONEMAP_UNIFORM_LOCATION,
|
||||
SKY_GLOBALS_UNIFORM_LOCATION,
|
||||
SKY_SCENE_DATA_UNIFORM_LOCATION,
|
||||
SKY_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
|
||||
SKY_MATERIAL_UNIFORM_LOCATION,
|
||||
};
|
||||
|
||||
struct RenderDataGLES3 {
|
||||
RID render_buffers = RID();
|
||||
bool transparent_bg = false;
|
||||
|
||||
Transform3D cam_transform = Transform3D();
|
||||
CameraMatrix cam_projection = CameraMatrix();
|
||||
bool cam_ortogonal = false;
|
||||
bool cam_orthogonal = false;
|
||||
|
||||
// For stereo rendering
|
||||
uint32_t view_count = 1;
|
||||
@ -91,17 +126,324 @@ private:
|
||||
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
|
||||
uint64_t scene_pass = 0;
|
||||
|
||||
/* Sky */
|
||||
struct SkyGlobals {
|
||||
RID shader_current_version;
|
||||
RID shader_default_version;
|
||||
RID default_material;
|
||||
RID default_shader;
|
||||
RID fog_material;
|
||||
RID fog_shader;
|
||||
GLuint quad = 0;
|
||||
GLuint quad_array = 0;
|
||||
uint32_t max_directional_lights = 4;
|
||||
uint32_t roughness_layers = 8;
|
||||
uint32_t ggx_samples = 128;
|
||||
} sky_globals;
|
||||
|
||||
struct SceneGlobals {
|
||||
RID shader_default_version;
|
||||
RID default_material;
|
||||
RID default_shader;
|
||||
} scene_globals;
|
||||
|
||||
struct SceneState {
|
||||
struct UBO {
|
||||
float projection_matrix[16];
|
||||
float inv_projection_matrix[16];
|
||||
float inv_view_matrix[16];
|
||||
float view_matrix[16];
|
||||
|
||||
float viewport_size[2];
|
||||
float screen_pixel_size[2];
|
||||
|
||||
float ambient_light_color_energy[4];
|
||||
|
||||
float ambient_color_sky_mix;
|
||||
uint32_t ambient_flags;
|
||||
uint32_t material_uv2_mode;
|
||||
float opaque_prepass_threshold;
|
||||
//bool use_ambient_light;
|
||||
//bool use_ambient_cubemap;
|
||||
//bool use_reflection_cubemap;
|
||||
|
||||
float radiance_inverse_xform[12];
|
||||
|
||||
uint32_t directional_light_count;
|
||||
float z_far;
|
||||
float z_near;
|
||||
uint32_t pancake_shadows;
|
||||
|
||||
uint32_t fog_enabled;
|
||||
float fog_density;
|
||||
float fog_height;
|
||||
float fog_height_density;
|
||||
|
||||
float fog_light_color[3];
|
||||
float fog_sun_scatter;
|
||||
|
||||
float fog_aerial_perspective;
|
||||
float time;
|
||||
uint32_t pad[2];
|
||||
};
|
||||
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
|
||||
|
||||
struct TonemapUBO {
|
||||
float exposure = 1.0;
|
||||
float white = 1.0;
|
||||
int32_t tonemapper = 0;
|
||||
int32_t pad = 0;
|
||||
};
|
||||
static_assert(sizeof(TonemapUBO) % 16 == 0, "Tonemap UBO size must be a multiple of 16 bytes");
|
||||
|
||||
UBO ubo;
|
||||
GLuint ubo_buffer = 0;
|
||||
GLuint tonemap_buffer = 0;
|
||||
|
||||
bool used_depth_prepass = false;
|
||||
|
||||
GLES3::SceneShaderData::BlendMode current_blend_mode = GLES3::SceneShaderData::BLEND_MODE_MIX;
|
||||
GLES3::SceneShaderData::DepthDraw current_depth_draw = GLES3::SceneShaderData::DEPTH_DRAW_OPAQUE;
|
||||
GLES3::SceneShaderData::DepthTest current_depth_test = GLES3::SceneShaderData::DEPTH_TEST_DISABLED;
|
||||
GLES3::SceneShaderData::Cull cull_mode = GLES3::SceneShaderData::CULL_BACK;
|
||||
|
||||
bool texscreen_copied = false;
|
||||
bool used_screen_texture = false;
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
} scene_state;
|
||||
|
||||
struct GeometryInstanceGLES3;
|
||||
|
||||
// Cached data for drawing surfaces
|
||||
struct GeometryInstanceSurface {
|
||||
enum {
|
||||
FLAG_PASS_DEPTH = 1,
|
||||
FLAG_PASS_OPAQUE = 2,
|
||||
FLAG_PASS_ALPHA = 4,
|
||||
FLAG_PASS_SHADOW = 8,
|
||||
FLAG_USES_SHARED_SHADOW_MATERIAL = 128,
|
||||
FLAG_USES_SCREEN_TEXTURE = 2048,
|
||||
FLAG_USES_DEPTH_TEXTURE = 4096,
|
||||
FLAG_USES_NORMAL_TEXTURE = 8192,
|
||||
FLAG_USES_DOUBLE_SIDED_SHADOWS = 16384,
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t lod_index : 8;
|
||||
uint64_t surface_index : 8;
|
||||
uint64_t geometry_id : 32;
|
||||
uint64_t material_id_low : 16;
|
||||
|
||||
uint64_t material_id_hi : 16;
|
||||
uint64_t shader_id : 32;
|
||||
uint64_t uses_softshadow : 1;
|
||||
uint64_t uses_projector : 1;
|
||||
uint64_t uses_forward_gi : 1;
|
||||
uint64_t uses_lightmap : 1;
|
||||
uint64_t depth_layer : 4;
|
||||
uint64_t priority : 8;
|
||||
};
|
||||
struct {
|
||||
uint64_t sort_key1;
|
||||
uint64_t sort_key2;
|
||||
};
|
||||
} sort;
|
||||
|
||||
RS::PrimitiveType primitive = RS::PRIMITIVE_MAX;
|
||||
uint32_t flags = 0;
|
||||
uint32_t surface_index = 0;
|
||||
uint32_t lod_index = 0;
|
||||
|
||||
void *surface = nullptr;
|
||||
GLES3::SceneShaderData *shader = nullptr;
|
||||
GLES3::SceneMaterialData *material = nullptr;
|
||||
|
||||
void *surface_shadow = nullptr;
|
||||
GLES3::SceneShaderData *shader_shadow = nullptr;
|
||||
GLES3::SceneMaterialData *material_shadow = nullptr;
|
||||
|
||||
GeometryInstanceSurface *next = nullptr;
|
||||
GeometryInstanceGLES3 *owner = nullptr;
|
||||
};
|
||||
|
||||
struct GeometryInstanceGLES3 : public GeometryInstance {
|
||||
//used during rendering
|
||||
bool mirror = false;
|
||||
bool non_uniform_scale = false;
|
||||
float lod_bias = 0.0;
|
||||
float lod_model_scale = 1.0;
|
||||
AABB transformed_aabb; //needed for LOD
|
||||
float depth = 0;
|
||||
uint32_t flags_cache = 0;
|
||||
bool store_transform_cache = true;
|
||||
int32_t shader_parameters_offset = -1;
|
||||
|
||||
uint32_t layer_mask = 1;
|
||||
uint32_t instance_count = 0;
|
||||
|
||||
RID mesh_instance;
|
||||
bool can_sdfgi = false;
|
||||
bool using_projectors = false;
|
||||
bool using_softshadows = false;
|
||||
bool fade_near = false;
|
||||
float fade_near_begin = 0;
|
||||
float fade_near_end = 0;
|
||||
bool fade_far = false;
|
||||
float fade_far_begin = 0;
|
||||
float fade_far_end = 0;
|
||||
float force_alpha = 1.0;
|
||||
float parent_fade_alpha = 1.0;
|
||||
|
||||
uint32_t omni_light_count = 0;
|
||||
uint32_t omni_lights[8];
|
||||
uint32_t spot_light_count = 0;
|
||||
uint32_t spot_lights[8];
|
||||
|
||||
//used during setup
|
||||
uint32_t base_flags = 0;
|
||||
Transform3D transform;
|
||||
GeometryInstanceSurface *surface_caches = nullptr;
|
||||
SelfList<GeometryInstanceGLES3> dirty_list_element;
|
||||
|
||||
struct Data {
|
||||
//data used less often goes into regular heap
|
||||
RID base;
|
||||
RS::InstanceType base_type;
|
||||
|
||||
RID skeleton;
|
||||
Vector<RID> surface_materials;
|
||||
RID material_override;
|
||||
RID material_overlay;
|
||||
AABB aabb;
|
||||
|
||||
bool use_dynamic_gi = false;
|
||||
bool use_baked_light = false;
|
||||
bool cast_double_sided_shadows = false;
|
||||
bool mirror = false;
|
||||
bool dirty_dependencies = false;
|
||||
|
||||
RendererStorage::DependencyTracker dependency_tracker;
|
||||
};
|
||||
|
||||
Data *data = nullptr;
|
||||
|
||||
GeometryInstanceGLES3() :
|
||||
dirty_list_element(this) {}
|
||||
};
|
||||
|
||||
enum {
|
||||
INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
|
||||
INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
|
||||
INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
|
||||
INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
|
||||
INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
|
||||
INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15,
|
||||
};
|
||||
|
||||
static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
|
||||
static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
|
||||
|
||||
SelfList<GeometryInstanceGLES3>::List geometry_instance_dirty_list;
|
||||
|
||||
// Use PagedAllocator instead of RID to maximize performance
|
||||
PagedAllocator<GeometryInstanceGLES3> geometry_instance_alloc;
|
||||
PagedAllocator<GeometryInstanceSurface> geometry_instance_surface_alloc;
|
||||
|
||||
void _geometry_instance_add_surface_with_material(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
|
||||
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, GLES3::SceneMaterialData *p_material, RID p_mat_src, RID p_mesh);
|
||||
void _geometry_instance_add_surface(GeometryInstanceGLES3 *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
|
||||
void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
|
||||
void _geometry_instance_update(GeometryInstance *p_geometry_instance);
|
||||
void _update_dirty_geometry_instances();
|
||||
|
||||
struct RenderListParameters {
|
||||
GeometryInstanceSurface **elements = nullptr;
|
||||
int element_count = 0;
|
||||
bool reverse_cull = false;
|
||||
uint32_t spec_constant_base_flags = 0;
|
||||
bool force_wireframe = false;
|
||||
Plane lod_plane;
|
||||
float lod_distance_multiplier = 0.0;
|
||||
float screen_mesh_lod_threshold = 0.0;
|
||||
|
||||
RenderListParameters(GeometryInstanceSurface **p_elements, int p_element_count, bool p_reverse_cull, uint32_t p_spec_constant_base_flags, bool p_force_wireframe = false, const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0) {
|
||||
elements = p_elements;
|
||||
element_count = p_element_count;
|
||||
reverse_cull = p_reverse_cull;
|
||||
spec_constant_base_flags = p_spec_constant_base_flags;
|
||||
force_wireframe = p_force_wireframe;
|
||||
lod_plane = p_lod_plane;
|
||||
lod_distance_multiplier = p_lod_distance_multiplier;
|
||||
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderList {
|
||||
LocalVector<GeometryInstanceSurface *> elements;
|
||||
|
||||
void clear() {
|
||||
elements.clear();
|
||||
}
|
||||
|
||||
//should eventually be replaced by radix
|
||||
|
||||
struct SortByKey {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const {
|
||||
return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_key() {
|
||||
SortArray<GeometryInstanceSurface *, SortByKey> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
void sort_by_key_range(uint32_t p_from, uint32_t p_size) {
|
||||
SortArray<GeometryInstanceSurface *, SortByKey> sorter;
|
||||
sorter.sort(elements.ptr() + p_from, p_size);
|
||||
}
|
||||
|
||||
struct SortByDepth {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const {
|
||||
return (A->owner->depth < B->owner->depth);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_depth() { //used for shadows
|
||||
|
||||
SortArray<GeometryInstanceSurface *, SortByDepth> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
struct SortByReverseDepthAndPriority {
|
||||
_FORCE_INLINE_ bool operator()(const GeometryInstanceSurface *A, const GeometryInstanceSurface *B) const {
|
||||
return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);
|
||||
}
|
||||
};
|
||||
|
||||
void sort_by_reverse_depth_and_priority() { //used for alpha
|
||||
|
||||
SortArray<GeometryInstanceSurface *, SortByReverseDepthAndPriority> sorter;
|
||||
sorter.sort(elements.ptr(), elements.size());
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void add_element(GeometryInstanceSurface *p_element) {
|
||||
elements.push_back(p_element);
|
||||
}
|
||||
};
|
||||
|
||||
RenderList render_list[RENDER_LIST_MAX];
|
||||
|
||||
void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows);
|
||||
void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false);
|
||||
|
||||
template <PassMode p_pass_mode>
|
||||
_FORCE_INLINE_ void _render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass = false);
|
||||
|
||||
protected:
|
||||
double time;
|
||||
double time_step = 0;
|
||||
@ -117,6 +459,8 @@ protected:
|
||||
//bool use_debanding = false;
|
||||
//uint32_t view_count = 1;
|
||||
|
||||
bool is_transparent = false;
|
||||
|
||||
RID render_target;
|
||||
GLuint internal_texture = 0; // Used for rendering when post effects are enabled
|
||||
GLuint depth_texture = 0; // Main depth texture
|
||||
@ -319,7 +663,7 @@ protected:
|
||||
Sky *dirty_list = nullptr;
|
||||
|
||||
//State to track when radiance cubemap needs updating
|
||||
//SkyMaterialData *prev_material;
|
||||
GLES3::SkyMaterialData *prev_material;
|
||||
Vector3 prev_position = Vector3(0.0, 0.0, 0.0);
|
||||
float prev_time = 0.0f;
|
||||
|
||||
@ -335,17 +679,12 @@ protected:
|
||||
|
||||
void _invalidate_sky(Sky *p_sky);
|
||||
void _update_dirty_skys();
|
||||
void _draw_sky(Sky *p_sky, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_custom_fov, float p_energy, const Basis &p_sky_orientation);
|
||||
void _draw_sky(Environment *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform);
|
||||
|
||||
public:
|
||||
RasterizerStorageGLES3 *storage;
|
||||
RasterizerCanvasGLES3 *canvas;
|
||||
|
||||
// References to shaders are needed in public space so they can be accessed in RasterizerStorageGLES3
|
||||
struct State {
|
||||
SkyShaderGLES3 sky_shader;
|
||||
} state;
|
||||
|
||||
GeometryInstance *geometry_instance_create(RID p_base) override;
|
||||
void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
|
||||
void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
|
||||
@ -388,9 +727,15 @@ public:
|
||||
/* SDFGI UPDATE */
|
||||
|
||||
void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
|
||||
int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
|
||||
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
|
||||
uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
|
||||
int sdfgi_get_pending_region_count(RID p_render_buffers) const override {
|
||||
return 0;
|
||||
}
|
||||
AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override {
|
||||
return AABB();
|
||||
}
|
||||
uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SKY API */
|
||||
|
||||
|
@ -342,25 +342,14 @@ void RasterizerStorageGLES3::canvas_light_occluder_set_polylines(RID p_occluder,
|
||||
*/
|
||||
|
||||
RS::InstanceType RasterizerStorageGLES3::get_base_type(RID p_rid) const {
|
||||
return RS::INSTANCE_NONE;
|
||||
|
||||
/*
|
||||
if (mesh_owner.owns(p_rid)) {
|
||||
if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
|
||||
return RS::INSTANCE_MESH;
|
||||
} else if (light_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_LIGHT;
|
||||
} else if (multimesh_owner.owns(p_rid)) {
|
||||
} else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
|
||||
return RS::INSTANCE_MULTIMESH;
|
||||
} else if (immediate_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_IMMEDIATE;
|
||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_REFLECTION_PROBE;
|
||||
} else if (lightmap_capture_data_owner.owns(p_rid)) {
|
||||
return RS::INSTANCE_LIGHTMAP_CAPTURE;
|
||||
} else {
|
||||
return RS::INSTANCE_NONE;
|
||||
} else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
|
||||
return RS::INSTANCE_LIGHT;
|
||||
}
|
||||
*/
|
||||
return RS::INSTANCE_NONE;
|
||||
}
|
||||
|
||||
bool RasterizerStorageGLES3::free(RID p_rid) {
|
||||
@ -379,89 +368,23 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
|
||||
} else if (GLES3::MaterialStorage::get_singleton()->owns_material(p_rid)) {
|
||||
GLES3::MaterialStorage::get_singleton()->material_free(p_rid);
|
||||
return true;
|
||||
} else if (GLES3::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
|
||||
GLES3::MeshStorage::get_singleton()->mesh_free(p_rid);
|
||||
return true;
|
||||
} else if (GLES3::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
|
||||
GLES3::MeshStorage::get_singleton()->multimesh_free(p_rid);
|
||||
return true;
|
||||
} else if (GLES3::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
|
||||
GLES3::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
|
||||
return true;
|
||||
} else if (GLES3::LightStorage::get_singleton()->owns_light(p_rid)) {
|
||||
GLES3::LightStorage::get_singleton()->light_free(p_rid);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
} else if (skeleton_owner.owns(p_rid)) {
|
||||
Skeleton *s = skeleton_owner.get_or_null(p_rid);
|
||||
|
||||
if (s->update_list.in_list()) {
|
||||
skeleton_update_list.remove(&s->update_list);
|
||||
}
|
||||
|
||||
for (Set<InstanceBaseDependency *>::Element *E = s->instances.front(); E; E = E->next()) {
|
||||
E->get()->skeleton = RID();
|
||||
}
|
||||
|
||||
skeleton_allocate(p_rid, 0, false);
|
||||
|
||||
if (s->tex_id) {
|
||||
glDeleteTextures(1, &s->tex_id);
|
||||
}
|
||||
|
||||
skeleton_owner.free(p_rid);
|
||||
memdelete(s);
|
||||
|
||||
return true;
|
||||
} else if (mesh_owner.owns(p_rid)) {
|
||||
Mesh *mesh = mesh_owner.get_or_null(p_rid);
|
||||
|
||||
mesh->instance_remove_deps();
|
||||
mesh_clear(p_rid);
|
||||
|
||||
while (mesh->multimeshes.first()) {
|
||||
MultiMesh *multimesh = mesh->multimeshes.first()->self();
|
||||
multimesh->mesh = RID();
|
||||
multimesh->dirty_aabb = true;
|
||||
|
||||
mesh->multimeshes.remove(mesh->multimeshes.first());
|
||||
|
||||
if (!multimesh->update_list.in_list()) {
|
||||
multimesh_update_list.add(&multimesh->update_list);
|
||||
}
|
||||
}
|
||||
|
||||
mesh_owner.free(p_rid);
|
||||
memdelete(mesh);
|
||||
|
||||
return true;
|
||||
} else if (multimesh_owner.owns(p_rid)) {
|
||||
MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
|
||||
multimesh->instance_remove_deps();
|
||||
|
||||
if (multimesh->mesh.is_valid()) {
|
||||
Mesh *mesh = mesh_owner.get_or_null(multimesh->mesh);
|
||||
if (mesh) {
|
||||
mesh->multimeshes.remove(&multimesh->mesh_list);
|
||||
}
|
||||
}
|
||||
|
||||
multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_3D, RS::MULTIMESH_COLOR_NONE);
|
||||
|
||||
_update_dirty_multimeshes();
|
||||
|
||||
multimesh_owner.free(p_rid);
|
||||
memdelete(multimesh);
|
||||
|
||||
return true;
|
||||
} else if (immediate_owner.owns(p_rid)) {
|
||||
Immediate *im = immediate_owner.get_or_null(p_rid);
|
||||
im->instance_remove_deps();
|
||||
|
||||
immediate_owner.free(p_rid);
|
||||
memdelete(im);
|
||||
|
||||
return true;
|
||||
} else if (light_owner.owns(p_rid)) {
|
||||
Light *light = light_owner.get_or_null(p_rid);
|
||||
light->instance_remove_deps();
|
||||
|
||||
light_owner.free(p_rid);
|
||||
memdelete(light);
|
||||
|
||||
return true;
|
||||
} else if (reflection_probe_owner.owns(p_rid)) {
|
||||
else if (reflection_probe_owner.owns(p_rid)) {
|
||||
// delete the texture
|
||||
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_rid);
|
||||
reflection_probe->instance_remove_deps();
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "servers/rendering/shader_compiler.h"
|
||||
#include "servers/rendering/shader_language.h"
|
||||
#include "storage/config.h"
|
||||
#include "storage/light_storage.h"
|
||||
#include "storage/material_storage.h"
|
||||
#include "storage/mesh_storage.h"
|
||||
#include "storage/texture_storage.h"
|
||||
@ -55,6 +56,48 @@ public:
|
||||
|
||||
GLES3::Config *config = nullptr;
|
||||
|
||||
static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.basis.rows[0][0];
|
||||
p_array[1] = p_mtx.basis.rows[1][0];
|
||||
p_array[2] = p_mtx.basis.rows[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.basis.rows[0][1];
|
||||
p_array[5] = p_mtx.basis.rows[1][1];
|
||||
p_array[6] = p_mtx.basis.rows[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.basis.rows[0][2];
|
||||
p_array[9] = p_mtx.basis.rows[1][2];
|
||||
p_array[10] = p_mtx.basis.rows[2][2];
|
||||
p_array[11] = 0;
|
||||
p_array[12] = p_mtx.origin.x;
|
||||
p_array[13] = p_mtx.origin.y;
|
||||
p_array[14] = p_mtx.origin.z;
|
||||
p_array[15] = 1;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
|
||||
p_array[0] = p_mtx.rows[0][0];
|
||||
p_array[1] = p_mtx.rows[1][0];
|
||||
p_array[2] = p_mtx.rows[2][0];
|
||||
p_array[3] = 0;
|
||||
p_array[4] = p_mtx.rows[0][1];
|
||||
p_array[5] = p_mtx.rows[1][1];
|
||||
p_array[6] = p_mtx.rows[2][1];
|
||||
p_array[7] = 0;
|
||||
p_array[8] = p_mtx.rows[0][2];
|
||||
p_array[9] = p_mtx.rows[1][2];
|
||||
p_array[10] = p_mtx.rows[2][2];
|
||||
p_array[11] = 0;
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
p_array[i * 4 + j] = p_mtx.matrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Resources {
|
||||
GLuint mipmap_blur_fbo;
|
||||
GLuint mipmap_blur_color;
|
||||
|
@ -171,6 +171,15 @@ void ShaderGLES3::_build_variant_code(StringBuilder &builder, uint32_t p_variant
|
||||
}
|
||||
builder.append("\n"); //make sure defines begin at newline
|
||||
|
||||
// Default to highp precision unless specified otherwise.
|
||||
builder.append("precision highp float;\n");
|
||||
builder.append("precision highp int;\n");
|
||||
#ifndef GLES_OVER_GL
|
||||
builder.append("precision highp sampler2D;\n");
|
||||
builder.append("precision highp samplerCube;\n");
|
||||
builder.append("precision highp sampler2DArray;\n");
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < p_template.chunks.size(); i++) {
|
||||
const StageTemplate::Chunk &chunk = p_template.chunks[i];
|
||||
switch (chunk.type) {
|
||||
|
@ -73,10 +73,11 @@ private:
|
||||
//versions
|
||||
CharString general_defines;
|
||||
|
||||
// A version is a high-level construct which is a combination of built-in and user-defined shader code
|
||||
// Variants use #idefs to toggle behaviour on and off to change behaviour of the shader
|
||||
// A version is a high-level construct which is a combination of built-in and user-defined shader code, Each user-created Shader makes one version
|
||||
// Variants use #ifdefs to toggle behaviour on and off to change behaviour of the shader
|
||||
// All variants are compiled each time a new version is created
|
||||
// Specializations use #ifdefs to toggle behaviour on and off for performance, on supporting hardware, they will compile a version with everything enabled, and then compile more copies to improve performance
|
||||
// Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler)
|
||||
// Use specializations to enable and disabled advanced features, use variants to toggle behaviour when different data may be used (e.g. using a samplerArray vs a sampler, or doing a depth prepass vs a color pass)
|
||||
struct Version {
|
||||
Vector<StringName> texture_uniforms;
|
||||
CharString uniforms;
|
||||
@ -217,6 +218,7 @@ protected:
|
||||
ERR_FAIL_INDEX_V(p_which, uniform_count, -1);
|
||||
Version *version = version_owner.get_or_null(p_version);
|
||||
ERR_FAIL_COND_V(!version, -1);
|
||||
ERR_FAIL_INDEX_V(p_variant, int(version->variants.size()), -1);
|
||||
return version->variants[p_variant].lookup_ptr(p_specialization)->uniform_location[p_which];
|
||||
}
|
||||
|
||||
|
@ -8,4 +8,5 @@ env.Depends("#drivers/gles3/shaders/copy.glsl.gen.h", "#core/math/transform_2d.h
|
||||
if "GLES3_GLSL" in env["BUILDERS"]:
|
||||
env.GLES3_GLSL("canvas.glsl")
|
||||
env.GLES3_GLSL("copy.glsl")
|
||||
env.GLES3_GLSL("scene.glsl")
|
||||
env.GLES3_GLSL("sky.glsl")
|
||||
|
@ -20,6 +20,15 @@ layout(location = 4) in vec2 uv_attrib;
|
||||
layout(location = 10) in uvec4 bone_attrib;
|
||||
layout(location = 11) in vec4 weight_attrib;
|
||||
|
||||
#endif
|
||||
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
/* clang-format on */
|
||||
#include "canvas_uniforms_inc.glsl"
|
||||
@ -38,15 +47,6 @@ out vec2 pixel_size_interp;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{
|
||||
//ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
||||
void main() {
|
||||
@ -518,8 +518,8 @@ void main() {
|
||||
float px_size = max(0.5 * dot((vec2(px_range) / msdf_size), dest_size), 1.0);
|
||||
float d = msdf_median(msdf_sample.r, msdf_sample.g, msdf_sample.b, msdf_sample.a) - 0.5;
|
||||
|
||||
if (outline_thickness > 0) {
|
||||
float cr = clamp(outline_thickness, 0.0, px_range / 2) / px_range;
|
||||
if (outline_thickness > 0.0) {
|
||||
float cr = clamp(outline_thickness, 0.0, px_range / 2.0) / px_range;
|
||||
float a = clamp((d + cr) * px_size, 0.0, 1.0);
|
||||
color.a = a * color.a;
|
||||
} else {
|
||||
@ -710,8 +710,8 @@ void main() {
|
||||
vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot?
|
||||
float tex_ofs;
|
||||
float distance;
|
||||
if (pos_rot.y > 0) {
|
||||
if (pos_rot.x > 0) {
|
||||
if (pos_rot.y > 0.0) {
|
||||
if (pos_rot.x > 0.0) {
|
||||
tex_ofs = pos_box.y * 0.125 + 0.125;
|
||||
distance = shadow_pos.x;
|
||||
} else {
|
||||
@ -719,7 +719,7 @@ void main() {
|
||||
distance = shadow_pos.y;
|
||||
}
|
||||
} else {
|
||||
if (pos_rot.x < 0) {
|
||||
if (pos_rot.x < 0.0) {
|
||||
tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125);
|
||||
distance = -shadow_pos.x;
|
||||
} else {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,21 +12,12 @@ mode_cubemap_quarter_res = #define USE_CUBEMAP_PASS \n#define USE_QUARTER_RES_PA
|
||||
|
||||
#[vertex]
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#endif
|
||||
|
||||
out vec2 uv_interp;
|
||||
/* clang-format on */
|
||||
|
||||
void main() {
|
||||
// One big triangle to cover the whole screen
|
||||
vec2 base_arr[3] = vec2[](vec2(-1.0, -2.0), vec2(-1.0, 2.0), vec2(2.0, 2.0));
|
||||
vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));
|
||||
uv_interp = base_arr[gl_VertexID];
|
||||
gl_Position = vec4(uv_interp, 1.0, 1.0);
|
||||
}
|
||||
@ -36,19 +27,7 @@ void main() {
|
||||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
#define lowp
|
||||
#define mediump
|
||||
#define highp
|
||||
#else
|
||||
#if defined(USE_HIGHP_PRECISION)
|
||||
precision highp float;
|
||||
precision highp int;
|
||||
#else
|
||||
precision mediump float;
|
||||
precision mediump int;
|
||||
#endif
|
||||
#endif
|
||||
#include "tonemap_inc.glsl"
|
||||
|
||||
in vec2 uv_interp;
|
||||
|
||||
@ -63,40 +42,36 @@ uniform sampler2D half_res; //texunit:-2
|
||||
uniform sampler2D quarter_res; //texunit:-3
|
||||
#endif
|
||||
|
||||
layout(std140) uniform CanvasData { //ubo:0
|
||||
mat3 orientation;
|
||||
vec4 projection;
|
||||
vec4 position_multiplier;
|
||||
float time;
|
||||
float luminance_multiplier;
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
|
||||
layout(std140) uniform GlobalVariableData { //ubo:1
|
||||
vec4 global_variables[MAX_GLOBAL_VARIABLES];
|
||||
};
|
||||
|
||||
layout(std140) uniform SceneData { //ubo:2
|
||||
float pad1;
|
||||
float pad2;
|
||||
};
|
||||
|
||||
struct DirectionalLightData {
|
||||
vec4 direction_energy;
|
||||
vec4 color_size;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
layout(std140) uniform DirectionalLights { //ubo:2
|
||||
layout(std140) uniform DirectionalLights { //ubo:3
|
||||
DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS];
|
||||
}
|
||||
directional_lights;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{
|
||||
//ubo:3
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:4
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
} material;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* clang-format on */
|
||||
#GLOBALS
|
||||
|
||||
#ifdef USE_CUBEMAP_PASS
|
||||
@ -117,6 +92,12 @@ layout(std140) uniform MaterialUniforms{
|
||||
#define AT_QUARTER_RES_PASS false
|
||||
#endif
|
||||
|
||||
// mat4 is a waste of space, but we don't have an easy way to set a mat3 uniform for now
|
||||
uniform mat4 orientation;
|
||||
uniform vec4 projection;
|
||||
uniform vec3 position;
|
||||
uniform float time;
|
||||
|
||||
layout(location = 0) out vec4 frag_color;
|
||||
|
||||
void main() {
|
||||
@ -128,7 +109,7 @@ void main() {
|
||||
cube_normal.z = -cube_normal.z;
|
||||
cube_normal = normalize(cube_normal);
|
||||
|
||||
vec2 uv = uv_interp * 0.5 + 0.5;
|
||||
vec2 uv = gl_FragCoord.xy; // uv_interp * 0.5 + 0.5;
|
||||
|
||||
vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y));
|
||||
|
||||
@ -148,17 +129,17 @@ void main() {
|
||||
vec3 inverted_cube_normal = cube_normal;
|
||||
inverted_cube_normal.z *= -1.0;
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier;
|
||||
half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
|
||||
#endif
|
||||
#ifdef USES_QUARTER_RES_COLOR
|
||||
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal) * luminance_multiplier;
|
||||
quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), inverted_cube_normal);
|
||||
#endif
|
||||
#else
|
||||
#ifdef USES_HALF_RES_COLOR
|
||||
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier;
|
||||
half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
|
||||
#endif
|
||||
#ifdef USES_QUARTER_RES_COLOR
|
||||
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * luminance_multiplier;
|
||||
quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -168,12 +149,19 @@ void main() {
|
||||
|
||||
}
|
||||
|
||||
frag_color.rgb = color * position_multiplier.w / luminance_multiplier;
|
||||
frag_color.a = alpha;
|
||||
// Tonemap before writing as we are writing to an sRGB framebuffer
|
||||
color *= exposure;
|
||||
color = apply_tonemapping(color, white);
|
||||
color = linear_to_srgb(color);
|
||||
|
||||
// Blending is disabled for Sky, so alpha doesn't blend
|
||||
// alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
|
||||
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
|
||||
frag_color.a = 0.0;
|
||||
}
|
||||
#ifdef USE_BCS
|
||||
color = apply_bcs(color, bcs);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
color = apply_color_correction(color, color_correction);
|
||||
#endif
|
||||
|
||||
frag_color.rgb = color;
|
||||
frag_color.a = alpha;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
//TODO: only needed by GLES_OVER_GL
|
||||
|
||||
#ifdef USE_GLES_OVER_GL
|
||||
// Floating point pack/unpack functions are part of the GLSL ES 300 specification used by web and mobile.
|
||||
uint float2half(uint f) {
|
||||
return ((f >> uint(16)) & uint(0x8000)) |
|
||||
((((f & uint(0x7f800000)) - uint(0x38000000)) >> uint(13)) & uint(0x7c00)) |
|
||||
@ -37,6 +38,7 @@ vec2 unpackSnorm2x16(uint p) {
|
||||
vec2 v = vec2(float(p & uint(0xffff)), float(p >> uint(16)));
|
||||
return clamp((v - 32767.0) * vec2(0.00003051851), vec2(-1.0), vec2(1.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
uint packUnorm4x8(vec4 v) {
|
||||
uvec4 uv = uvec4(round(clamp(v, vec4(0.0), vec4(1.0)) * 255.0));
|
||||
|
119
drivers/gles3/shaders/tonemap_inc.glsl
Normal file
119
drivers/gles3/shaders/tonemap_inc.glsl
Normal file
@ -0,0 +1,119 @@
|
||||
#ifdef USE_BCS
|
||||
uniform vec3 bcs;
|
||||
#endif
|
||||
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
#ifdef USE_1D_LUT
|
||||
uniform sampler2D source_color_correction; //texunit:-1
|
||||
#else
|
||||
uniform sampler3D source_color_correction; //texunit:-1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
layout(std140) uniform TonemapData { //ubo:0
|
||||
float exposure;
|
||||
float white;
|
||||
int tonemapper;
|
||||
int pad;
|
||||
};
|
||||
|
||||
vec3 apply_bcs(vec3 color, vec3 bcs) {
|
||||
color = mix(vec3(0.0), color, bcs.x);
|
||||
color = mix(vec3(0.5), color, bcs.y);
|
||||
color = mix(vec3(dot(vec3(1.0), color) * 0.33333), color, bcs.z);
|
||||
|
||||
return color;
|
||||
}
|
||||
#ifdef USE_COLOR_CORRECTION
|
||||
#ifdef USE_1D_LUT
|
||||
vec3 apply_color_correction(vec3 color) {
|
||||
color.r = texture(source_color_correction, vec2(color.r, 0.0f)).r;
|
||||
color.g = texture(source_color_correction, vec2(color.g, 0.0f)).g;
|
||||
color.b = texture(source_color_correction, vec2(color.b, 0.0f)).b;
|
||||
return color;
|
||||
}
|
||||
#else
|
||||
vec3 apply_color_correction(vec3 color) {
|
||||
return textureLod(source_color_correction, color, 0.0).rgb;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec3 tonemap_filmic(vec3 color, float p_white) {
|
||||
// exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers
|
||||
// also useful to scale the input to the range that the tonemapper is designed for (some require very high input values)
|
||||
// has no effect on the curve's general shape or visual properties
|
||||
const float exposure_bias = 2.0f;
|
||||
const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance
|
||||
const float B = 0.30f * exposure_bias;
|
||||
const float C = 0.10f;
|
||||
const float D = 0.20f;
|
||||
const float E = 0.01f;
|
||||
const float F = 0.30f;
|
||||
|
||||
vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F;
|
||||
float p_white_tonemapped = ((p_white * (A * p_white + C * B) + D * E) / (p_white * (A * p_white + B) + D * F)) - E / F;
|
||||
|
||||
return color_tonemapped / p_white_tonemapped;
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
// (MIT License).
|
||||
vec3 tonemap_aces(vec3 color, float p_white) {
|
||||
const float exposure_bias = 1.8f;
|
||||
const float A = 0.0245786f;
|
||||
const float B = 0.000090537f;
|
||||
const float C = 0.983729f;
|
||||
const float D = 0.432951f;
|
||||
const float E = 0.238081f;
|
||||
|
||||
// Exposure bias baked into transform to save shader instructions. Equivalent to `color *= exposure_bias`
|
||||
const mat3 rgb_to_rrt = mat3(
|
||||
vec3(0.59719f * exposure_bias, 0.35458f * exposure_bias, 0.04823f * exposure_bias),
|
||||
vec3(0.07600f * exposure_bias, 0.90834f * exposure_bias, 0.01566f * exposure_bias),
|
||||
vec3(0.02840f * exposure_bias, 0.13383f * exposure_bias, 0.83777f * exposure_bias));
|
||||
|
||||
const mat3 odt_to_rgb = mat3(
|
||||
vec3(1.60475f, -0.53108f, -0.07367f),
|
||||
vec3(-0.10208f, 1.10813f, -0.00605f),
|
||||
vec3(-0.00327f, -0.07276f, 1.07602f));
|
||||
|
||||
color *= rgb_to_rrt;
|
||||
vec3 color_tonemapped = (color * (color + A) - B) / (color * (C * color + D) + E);
|
||||
color_tonemapped *= odt_to_rgb;
|
||||
|
||||
p_white *= exposure_bias;
|
||||
float p_white_tonemapped = (p_white * (p_white + A) - B) / (p_white * (C * p_white + D) + E);
|
||||
|
||||
return color_tonemapped / p_white_tonemapped;
|
||||
}
|
||||
|
||||
vec3 tonemap_reinhard(vec3 color, float p_white) {
|
||||
return (p_white * color + color) / (color * p_white + p_white);
|
||||
}
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
//if going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
#define TONEMAPPER_LINEAR 0
|
||||
#define TONEMAPPER_REINHARD 1
|
||||
#define TONEMAPPER_FILMIC 2
|
||||
#define TONEMAPPER_ACES 3
|
||||
|
||||
vec3 apply_tonemapping(vec3 color, float p_white) { // inputs are LINEAR, always outputs clamped [0;1] color
|
||||
// Ensure color values passed to tonemappers are positive.
|
||||
// They can be negative in the case of negative lights, which leads to undesired behavior.
|
||||
if (tonemapper == TONEMAPPER_LINEAR) {
|
||||
return color;
|
||||
} else if (tonemapper == TONEMAPPER_REINHARD) {
|
||||
return tonemap_reinhard(max(vec3(0.0f), color), p_white);
|
||||
} else if (tonemapper == TONEMAPPER_FILMIC) {
|
||||
return tonemap_filmic(max(vec3(0.0f), color), p_white);
|
||||
} else { // TONEMAPPER_ACES
|
||||
return tonemap_aces(max(vec3(0.0f), color), p_white);
|
||||
}
|
||||
}
|
@ -120,16 +120,6 @@ Config::Config() {
|
||||
support_write_depth = extensions.has("GL_EXT_frag_depth");
|
||||
#endif
|
||||
|
||||
support_half_float_vertices = true;
|
||||
//every platform should support this except web, iOS has issues with their support, so add option to disable
|
||||
#ifdef JAVASCRIPT_ENABLED
|
||||
support_half_float_vertices = false;
|
||||
#endif
|
||||
bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
|
||||
if (disable_half_float) {
|
||||
support_half_float_vertices = false;
|
||||
}
|
||||
|
||||
//picky requirements for these
|
||||
support_shadow_cubemaps = support_write_depth && support_depth_cubemaps;
|
||||
// the use skeleton software path should be used if either float texture is not supported,
|
||||
@ -149,6 +139,27 @@ Config::Config() {
|
||||
|
||||
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
|
||||
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
|
||||
|
||||
use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
|
||||
if (use_depth_prepass) {
|
||||
String vendors = GLOBAL_GET("rendering/driver/depth_prepass/disable_for_vendors");
|
||||
Vector<String> vendor_match = vendors.split(",");
|
||||
String renderer = (const char *)glGetString(GL_RENDERER);
|
||||
for (int i = 0; i < vendor_match.size(); i++) {
|
||||
String v = vendor_match[i].strip_edges();
|
||||
if (v == String()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (renderer.findn(v) != -1) {
|
||||
use_depth_prepass = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements");
|
||||
max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights");
|
||||
max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object");
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
|
@ -58,6 +58,9 @@ public:
|
||||
int max_texture_image_units = 0;
|
||||
int max_texture_size = 0;
|
||||
int max_uniform_buffer_size = 0;
|
||||
int max_renderable_elements = 0;
|
||||
int max_renderable_lights = 0;
|
||||
int max_lights_per_object = 0;
|
||||
|
||||
// TODO implement wireframe in OpenGL
|
||||
// bool generate_wireframes;
|
||||
@ -82,7 +85,6 @@ public:
|
||||
|
||||
bool support_32_bits_indices = false;
|
||||
bool support_write_depth = false;
|
||||
bool support_half_float_vertices = false;
|
||||
bool support_npot_repeat_mipmap = false;
|
||||
bool support_depth_cubemaps = false;
|
||||
bool support_shadow_cubemaps = false;
|
||||
@ -97,6 +99,8 @@ public:
|
||||
// so the user can switch orphaning off for them.
|
||||
bool should_orphan = true;
|
||||
|
||||
bool use_depth_prepass = true;
|
||||
|
||||
static Config *get_singleton() { return singleton; };
|
||||
|
||||
Config();
|
||||
|
@ -43,7 +43,7 @@ using namespace GLES3;
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// UBI helper functions
|
||||
|
||||
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
|
||||
_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) {
|
||||
switch (type) {
|
||||
case ShaderLanguage::TYPE_BOOL: {
|
||||
uint32_t *gui = (uint32_t *)data;
|
||||
@ -399,9 +399,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
|
||||
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
|
||||
if (i < s) {
|
||||
Color color = a[i];
|
||||
if (p_linear_color) {
|
||||
color = color.srgb_to_linear();
|
||||
}
|
||||
gui[j] = color.r;
|
||||
gui[j + 1] = color.g;
|
||||
gui[j + 2] = color.b;
|
||||
@ -433,10 +430,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
|
||||
if (value.get_type() == Variant::COLOR) {
|
||||
Color v = value;
|
||||
|
||||
if (p_linear_color) {
|
||||
v = v.srgb_to_linear();
|
||||
}
|
||||
|
||||
gui[0] = v.r;
|
||||
gui[1] = v.g;
|
||||
gui[2] = v.b;
|
||||
@ -459,9 +452,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
|
||||
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
|
||||
if (i < s) {
|
||||
Color color = a[i];
|
||||
if (p_linear_color) {
|
||||
color = color.srgb_to_linear();
|
||||
}
|
||||
gui[j] = color.r;
|
||||
gui[j + 1] = color.g;
|
||||
gui[j + 2] = color.b;
|
||||
@ -496,10 +486,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
|
||||
if (value.get_type() == Variant::COLOR) {
|
||||
Color v = value;
|
||||
|
||||
if (p_linear_color) {
|
||||
v = v.srgb_to_linear();
|
||||
}
|
||||
|
||||
gui[0] = v.r;
|
||||
gui[1] = v.g;
|
||||
gui[2] = v.b;
|
||||
@ -900,6 +886,42 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MaterialData
|
||||
|
||||
// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
|
||||
static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
|
||||
GL_TEXTURE_2D, // TYPE_VOID,
|
||||
GL_TEXTURE_2D, // TYPE_BOOL,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_INT,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_UINT,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_FLOAT,
|
||||
GL_TEXTURE_2D, // TYPE_VEC2,
|
||||
GL_TEXTURE_2D, // TYPE_VEC3,
|
||||
GL_TEXTURE_2D, // TYPE_VEC4,
|
||||
GL_TEXTURE_2D, // TYPE_MAT2,
|
||||
GL_TEXTURE_2D, // TYPE_MAT3,
|
||||
GL_TEXTURE_2D, // TYPE_MAT4,
|
||||
GL_TEXTURE_2D, // TYPE_SAMPLER2D,
|
||||
GL_TEXTURE_2D, // TYPE_ISAMPLER2D,
|
||||
GL_TEXTURE_2D, // TYPE_USAMPLER2D,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY,
|
||||
GL_TEXTURE_3D, // TYPE_SAMPLER3D,
|
||||
GL_TEXTURE_3D, // TYPE_ISAMPLER3D,
|
||||
GL_TEXTURE_3D, // TYPE_USAMPLER3D,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
|
||||
GL_TEXTURE_2D, // TYPE_STRUCT
|
||||
};
|
||||
|
||||
void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
bool uses_global_buffer = false;
|
||||
@ -951,7 +973,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
|
||||
|
||||
if (V) {
|
||||
//user provided
|
||||
_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
|
||||
_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data);
|
||||
|
||||
} else if (E.value.default_value.size()) {
|
||||
//default value
|
||||
@ -961,7 +983,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
|
||||
//zero because it was not provided
|
||||
if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
|
||||
//colors must be set as black, with alpha as 1.0
|
||||
_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
|
||||
_fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data);
|
||||
} else {
|
||||
//else just zero it out
|
||||
_fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
|
||||
@ -1275,16 +1297,16 @@ MaterialStorage *MaterialStorage::get_singleton() {
|
||||
MaterialStorage::MaterialStorage() {
|
||||
singleton = this;
|
||||
|
||||
shader_data_request_func[RS::SHADER_SPATIAL] = nullptr;
|
||||
shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func;
|
||||
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
|
||||
shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;
|
||||
shader_data_request_func[RS::SHADER_SKY] = nullptr;
|
||||
shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
|
||||
shader_data_request_func[RS::SHADER_FOG] = nullptr;
|
||||
|
||||
material_data_request_func[RS::SHADER_SPATIAL] = nullptr;
|
||||
material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;
|
||||
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
|
||||
material_data_request_func[RS::SHADER_PARTICLES] = nullptr;
|
||||
material_data_request_func[RS::SHADER_SKY] = nullptr;
|
||||
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
|
||||
material_data_request_func[RS::SHADER_FOG] = nullptr;
|
||||
|
||||
static_assert(sizeof(GlobalVariables::Value) == 16);
|
||||
@ -1365,16 +1387,12 @@ MaterialStorage::MaterialStorage() {
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n";
|
||||
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.base_uniform_string = "";
|
||||
actions.global_buffer_array_variable = "";
|
||||
|
||||
shaders.compiler_canvas.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
// Setup Scene compiler
|
||||
/*
|
||||
|
||||
//shader compiler
|
||||
ShaderCompiler::DefaultIdentifierActions actions;
|
||||
|
||||
@ -1529,11 +1547,6 @@ MaterialStorage::MaterialStorage() {
|
||||
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.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps
|
||||
actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]";
|
||||
actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter
|
||||
|
||||
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";
|
||||
@ -1541,19 +1554,10 @@ MaterialStorage::MaterialStorage() {
|
||||
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
|
||||
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
|
||||
|
||||
actions.sampler_array_name = "material_samplers";
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 10;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
actions.global_buffer_array_variable = "global_variables.data";
|
||||
actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
|
||||
|
||||
compiler.initialize(actions);
|
||||
*/
|
||||
shaders.compiler_scene.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
@ -1626,10 +1630,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
|
||||
actions.renames["COLOR"] = "color";
|
||||
actions.renames["ALPHA"] = "alpha";
|
||||
actions.renames["EYEDIR"] = "cube_normal";
|
||||
actions.renames["POSITION"] = "params.position_multiplier.xyz";
|
||||
actions.renames["POSITION"] = "position";
|
||||
actions.renames["SKY_COORDS"] = "panorama_coords";
|
||||
actions.renames["SCREEN_UV"] = "uv";
|
||||
actions.renames["TIME"] = "params.time";
|
||||
actions.renames["TIME"] = "time";
|
||||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
@ -1660,20 +1664,12 @@ ShaderCompiler::DefaultIdentifierActions actions;
|
||||
actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
|
||||
actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
|
||||
actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
|
||||
actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
|
||||
actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
|
||||
actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
|
||||
actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
|
||||
|
||||
actions.sampler_array_name = "material_samplers";
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = 1;
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_varying_index = 10;
|
||||
|
||||
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
|
||||
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
|
||||
actions.global_buffer_array_variable = "global_variables";
|
||||
|
||||
shaders.compiler_sky.initialize(actions);
|
||||
}
|
||||
@ -1873,7 +1869,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
|
||||
bv.w = v.a;
|
||||
|
||||
GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
|
||||
v = v.srgb_to_linear();
|
||||
//v = v.srgb_to_linear();
|
||||
bv_linear.x = v.r;
|
||||
bv_linear.y = v.g;
|
||||
bv_linear.z = v.b;
|
||||
@ -2311,7 +2307,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
|
||||
|
||||
pos += p_index;
|
||||
|
||||
_fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
|
||||
_fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]);
|
||||
_global_variable_mark_buffer_dirty(pos, 1);
|
||||
}
|
||||
|
||||
@ -2738,7 +2734,8 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage
|
||||
}
|
||||
}
|
||||
|
||||
// Canvas Shader Data
|
||||
/* Canvas Shader Data */
|
||||
|
||||
void CanvasShaderData::set_code(const String &p_code) {
|
||||
// compile the shader
|
||||
|
||||
@ -2915,51 +2912,15 @@ void CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_par
|
||||
return update_parameters_internal(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);
|
||||
}
|
||||
|
||||
// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
|
||||
static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
|
||||
GL_TEXTURE_2D, // TYPE_VOID,
|
||||
GL_TEXTURE_2D, // TYPE_BOOL,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_BVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_INT,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_IVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_UINT,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC2,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC3,
|
||||
GL_TEXTURE_2D, // TYPE_UVEC4,
|
||||
GL_TEXTURE_2D, // TYPE_FLOAT,
|
||||
GL_TEXTURE_2D, // TYPE_VEC2,
|
||||
GL_TEXTURE_2D, // TYPE_VEC3,
|
||||
GL_TEXTURE_2D, // TYPE_VEC4,
|
||||
GL_TEXTURE_2D, // TYPE_MAT2,
|
||||
GL_TEXTURE_2D, // TYPE_MAT3,
|
||||
GL_TEXTURE_2D, // TYPE_MAT4,
|
||||
GL_TEXTURE_2D, // TYPE_SAMPLER2D,
|
||||
GL_TEXTURE_2D, // TYPE_ISAMPLER2D,
|
||||
GL_TEXTURE_2D, // TYPE_USAMPLER2D,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY,
|
||||
GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY,
|
||||
GL_TEXTURE_3D, // TYPE_SAMPLER3D,
|
||||
GL_TEXTURE_3D, // TYPE_ISAMPLER3D,
|
||||
GL_TEXTURE_3D, // TYPE_USAMPLER3D,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
|
||||
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
|
||||
GL_TEXTURE_2D, // TYPE_STRUCT
|
||||
};
|
||||
|
||||
void CanvasMaterialData::bind_uniforms() {
|
||||
// Bind Material Uniforms
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_BUFFER_OBJECT, uniform_buffer);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_LOCATION, uniform_buffer);
|
||||
|
||||
RID *textures = texture_cache.ptrw();
|
||||
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
|
||||
for (int ti = 0; ti < texture_cache.size(); ti++) {
|
||||
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
|
||||
glActiveTexture(GL_TEXTURE1 + ti);
|
||||
glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
|
||||
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
|
||||
|
||||
// Set sampler state here as the same texture can be used in multiple places with different flags
|
||||
@ -2981,4 +2942,543 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) {
|
||||
return material_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SKY SHADER
|
||||
|
||||
void SkyShaderData::set_code(const String &p_code) {
|
||||
//compile
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; //just invalid, but no error
|
||||
}
|
||||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
ShaderCompiler::IdentifierActions actions;
|
||||
actions.entry_point_stages["sky"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||
|
||||
uses_time = false;
|
||||
uses_half_res = false;
|
||||
uses_quarter_res = false;
|
||||
uses_position = false;
|
||||
uses_light = false;
|
||||
|
||||
actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
|
||||
actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
|
||||
|
||||
actions.usage_flag_pointers["TIME"] = &uses_time;
|
||||
actions.usage_flag_pointers["POSITION"] = &uses_position;
|
||||
actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
|
||||
actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
Error err = MaterialStorage::get_singleton()->shaders.compiler_sky.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
|
||||
if (version.is_null()) {
|
||||
version = MaterialStorage::get_singleton()->shaders.sky_shader.version_create();
|
||||
}
|
||||
|
||||
#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]);
|
||||
}
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
// print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
|
||||
// print_line("\n**vertex_code:\n" + gen_code.vertex);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
|
||||
print_line("\n**fragment_code:\n" + gen_code.fragment);
|
||||
print_line("\n**light_code:\n" + gen_code.light);
|
||||
#endif
|
||||
|
||||
Vector<StringName> texture_uniform_names;
|
||||
for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
|
||||
texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
|
||||
}
|
||||
|
||||
MaterialStorage::get_singleton()->shaders.sky_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, texture_uniform_names);
|
||||
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.sky_shader.version_is_valid(version));
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
|
||||
if (!p_texture.is_valid()) {
|
||||
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
|
||||
default_texture_params[p_name].erase(p_index);
|
||||
|
||||
if (default_texture_params[p_name].is_empty()) {
|
||||
default_texture_params.erase(p_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!default_texture_params.has(p_name)) {
|
||||
default_texture_params[p_name] = Map<int, RID>();
|
||||
}
|
||||
default_texture_params[p_name][p_index] = p_texture;
|
||||
}
|
||||
}
|
||||
|
||||
void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
|
||||
Map<int, StringName> order;
|
||||
|
||||
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
|
||||
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (E.value.texture_order >= 0) {
|
||||
order[E.value.texture_order + 100000] = E.key;
|
||||
} else {
|
||||
order[E.value.order] = E.key;
|
||||
}
|
||||
}
|
||||
|
||||
for (const KeyValue<int, StringName> &E : order) {
|
||||
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
|
||||
pi.name = E.value;
|
||||
p_param_list->push_back(pi);
|
||||
}
|
||||
}
|
||||
|
||||
void SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
|
||||
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
|
||||
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RendererMaterialStorage::InstanceShaderParam p;
|
||||
p.info = ShaderLanguage::uniform_to_property_info(E.value);
|
||||
p.info.name = E.key; //supply name
|
||||
p.index = E.value.instance_index;
|
||||
p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
|
||||
p_param_list->push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool SkyShaderData::is_param_texture(const StringName &p_param) const {
|
||||
if (!uniforms.has(p_param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return uniforms[p_param].texture_order >= 0;
|
||||
}
|
||||
|
||||
bool SkyShaderData::is_animated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkyShaderData::casts_shadows() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
|
||||
if (uniforms.has(p_parameter)) {
|
||||
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
|
||||
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
|
||||
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SkyShaderData::get_native_source_code() const {
|
||||
return MaterialStorage::get_singleton()->shaders.sky_shader.version_get_native_source_code(version);
|
||||
}
|
||||
|
||||
SkyShaderData::SkyShaderData() {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
SkyShaderData::~SkyShaderData() {
|
||||
if (version.is_valid()) {
|
||||
MaterialStorage::get_singleton()->shaders.sky_shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
GLES3::ShaderData *GLES3::_create_sky_shader_func() {
|
||||
SkyShaderData *shader_data = memnew(SkyShaderData);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Sky material
|
||||
|
||||
void SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
return update_parameters_internal(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);
|
||||
}
|
||||
|
||||
SkyMaterialData::~SkyMaterialData() {
|
||||
}
|
||||
GLES3::MaterialData *GLES3::_create_sky_material_func(ShaderData *p_shader) {
|
||||
SkyMaterialData *material_data = memnew(SkyMaterialData);
|
||||
material_data->shader_data = static_cast<SkyShaderData *>(p_shader);
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
void SkyMaterialData::bind_uniforms() {
|
||||
// Bind Material Uniforms
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
|
||||
|
||||
RID *textures = texture_cache.ptrw();
|
||||
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
|
||||
for (int ti = 0; ti < texture_cache.size(); ti++) {
|
||||
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
|
||||
glActiveTexture(GL_TEXTURE0 + ti);
|
||||
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
|
||||
|
||||
// Set sampler state here as the same texture can be used in multiple places with different flags
|
||||
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
|
||||
RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
|
||||
RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
|
||||
texture->gl_set_filter(filter);
|
||||
texture->gl_set_repeat(repeat);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Scene SHADER
|
||||
|
||||
void SceneShaderData::set_code(const String &p_code) {
|
||||
//compile
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
uses_screen_texture = false;
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; //just invalid, but no error
|
||||
}
|
||||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
int blend_modei = BLEND_MODE_MIX;
|
||||
int depth_testi = DEPTH_TEST_ENABLED;
|
||||
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
|
||||
int cull_modei = CULL_BACK;
|
||||
int depth_drawi = DEPTH_DRAW_OPAQUE;
|
||||
|
||||
uses_point_size = false;
|
||||
uses_alpha = false;
|
||||
uses_alpha_clip = false;
|
||||
uses_blend_alpha = false;
|
||||
uses_depth_pre_pass = false;
|
||||
uses_discard = false;
|
||||
uses_roughness = false;
|
||||
uses_normal = false;
|
||||
wireframe = false;
|
||||
|
||||
unshaded = false;
|
||||
uses_vertex = false;
|
||||
uses_position = false;
|
||||
uses_sss = false;
|
||||
uses_transmittance = false;
|
||||
uses_screen_texture = false;
|
||||
uses_depth_texture = false;
|
||||
uses_normal_texture = false;
|
||||
uses_time = false;
|
||||
writes_modelview_or_projection = false;
|
||||
uses_world_coordinates = false;
|
||||
uses_particle_trails = false;
|
||||
|
||||
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_modei, BLEND_MODE_ADD);
|
||||
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
|
||||
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
|
||||
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
|
||||
|
||||
actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
|
||||
actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
|
||||
|
||||
actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
|
||||
actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
|
||||
actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
|
||||
|
||||
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
|
||||
|
||||
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
|
||||
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
|
||||
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
|
||||
|
||||
actions.render_mode_flags["unshaded"] = &unshaded;
|
||||
actions.render_mode_flags["wireframe"] = &wireframe;
|
||||
actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
|
||||
|
||||
actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
|
||||
actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
|
||||
actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
|
||||
|
||||
actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
|
||||
actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
|
||||
|
||||
actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
|
||||
actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
|
||||
actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture;
|
||||
actions.usage_flag_pointers["DISCARD"] = &uses_discard;
|
||||
actions.usage_flag_pointers["TIME"] = &uses_time;
|
||||
actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
|
||||
actions.usage_flag_pointers["NORMAL"] = &uses_normal;
|
||||
actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
|
||||
|
||||
actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
|
||||
actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
|
||||
|
||||
actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
|
||||
actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
|
||||
actions.write_flag_pointers["VERTEX"] = &uses_vertex;
|
||||
actions.write_flag_pointers["POSITION"] = &uses_position;
|
||||
|
||||
actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
|
||||
actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
|
||||
actions.usage_flag_pointers["COLOR"] = &uses_color;
|
||||
actions.usage_flag_pointers["UV"] = &uses_uv;
|
||||
actions.usage_flag_pointers["UV2"] = &uses_uv2;
|
||||
actions.usage_flag_pointers["CUSTOM0"] = &uses_custom0;
|
||||
actions.usage_flag_pointers["CUSTOM1"] = &uses_custom1;
|
||||
actions.usage_flag_pointers["CUSTOM2"] = &uses_custom2;
|
||||
actions.usage_flag_pointers["CUSTOM3"] = &uses_custom3;
|
||||
actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones;
|
||||
actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights;
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
|
||||
Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
|
||||
if (version.is_null()) {
|
||||
version = MaterialStorage::get_singleton()->shaders.scene_shader.version_create();
|
||||
}
|
||||
|
||||
depth_draw = DepthDraw(depth_drawi);
|
||||
depth_test = DepthTest(depth_testi);
|
||||
cull_mode = Cull(cull_modei);
|
||||
blend_mode = BlendMode(blend_modei);
|
||||
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
|
||||
vertex_input_mask = uint32_t(uses_normal);
|
||||
vertex_input_mask |= uses_tangent << 1;
|
||||
vertex_input_mask |= uses_color << 2;
|
||||
vertex_input_mask |= uses_uv << 3;
|
||||
vertex_input_mask |= uses_uv2 << 4;
|
||||
vertex_input_mask |= uses_custom0 << 5;
|
||||
vertex_input_mask |= uses_custom1 << 6;
|
||||
vertex_input_mask |= uses_custom2 << 7;
|
||||
vertex_input_mask |= uses_custom3 << 8;
|
||||
vertex_input_mask |= uses_bones << 9;
|
||||
vertex_input_mask |= uses_weights << 10;
|
||||
|
||||
#if 0
|
||||
print_line("**compiling shader:");
|
||||
print_line("**defines:\n");
|
||||
for (int i = 0; i < gen_code.defines.size(); i++) {
|
||||
print_line(gen_code.defines[i]);
|
||||
}
|
||||
|
||||
Map<String, String>::Element *el = gen_code.code.front();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key() + ":\n" + el->value());
|
||||
|
||||
el = el->next();
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
Vector<StringName> texture_uniform_names;
|
||||
for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
|
||||
texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
|
||||
}
|
||||
|
||||
MaterialStorage::get_singleton()->shaders.scene_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, texture_uniform_names);
|
||||
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.scene_shader.version_is_valid(version));
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
|
||||
if (!p_texture.is_valid()) {
|
||||
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
|
||||
default_texture_params[p_name].erase(p_index);
|
||||
|
||||
if (default_texture_params[p_name].is_empty()) {
|
||||
default_texture_params.erase(p_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!default_texture_params.has(p_name)) {
|
||||
default_texture_params[p_name] = Map<int, RID>();
|
||||
}
|
||||
default_texture_params[p_name][p_index] = p_texture;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
|
||||
Map<int, StringName> order;
|
||||
|
||||
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
|
||||
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (E.value.texture_order >= 0) {
|
||||
order[E.value.texture_order + 100000] = E.key;
|
||||
} else {
|
||||
order[E.value.order] = E.key;
|
||||
}
|
||||
}
|
||||
|
||||
for (const KeyValue<int, StringName> &E : order) {
|
||||
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
|
||||
pi.name = E.value;
|
||||
p_param_list->push_back(pi);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
|
||||
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
|
||||
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RendererMaterialStorage::InstanceShaderParam p;
|
||||
p.info = ShaderLanguage::uniform_to_property_info(E.value);
|
||||
p.info.name = E.key; //supply name
|
||||
p.index = E.value.instance_index;
|
||||
p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
|
||||
p_param_list->push_back(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneShaderData::is_param_texture(const StringName &p_param) const {
|
||||
if (!uniforms.has(p_param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return uniforms[p_param].texture_order >= 0;
|
||||
}
|
||||
|
||||
bool SceneShaderData::is_animated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SceneShaderData::casts_shadows() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Variant SceneShaderData::get_default_parameter(const StringName &p_parameter) const {
|
||||
if (uniforms.has(p_parameter)) {
|
||||
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
|
||||
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
|
||||
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const {
|
||||
return MaterialStorage::get_singleton()->shaders.scene_shader.version_get_native_source_code(version);
|
||||
}
|
||||
|
||||
SceneShaderData::SceneShaderData() {
|
||||
valid = false;
|
||||
uses_screen_texture = false;
|
||||
}
|
||||
|
||||
SceneShaderData::~SceneShaderData() {
|
||||
if (version.is_valid()) {
|
||||
MaterialStorage::get_singleton()->shaders.scene_shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
GLES3::ShaderData *GLES3::_create_scene_shader_func() {
|
||||
SceneShaderData *shader_data = memnew(SceneShaderData);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
void SceneMaterialData::set_render_priority(int p_priority) {
|
||||
priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
|
||||
}
|
||||
|
||||
void SceneMaterialData::set_next_pass(RID p_pass) {
|
||||
next_pass = p_pass;
|
||||
}
|
||||
|
||||
void SceneMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
return update_parameters_internal(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);
|
||||
}
|
||||
|
||||
SceneMaterialData::~SceneMaterialData() {
|
||||
}
|
||||
|
||||
GLES3::MaterialData *GLES3::_create_scene_material_func(ShaderData *p_shader) {
|
||||
SceneMaterialData *material_data = memnew(SceneMaterialData);
|
||||
material_data->shader_data = static_cast<SceneShaderData *>(p_shader);
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
void SceneMaterialData::bind_uniforms() {
|
||||
// Bind Material Uniforms
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
|
||||
|
||||
RID *textures = texture_cache.ptrw();
|
||||
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
|
||||
for (int ti = 0; ti < texture_cache.size(); ti++) {
|
||||
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
|
||||
glActiveTexture(GL_TEXTURE0 + ti);
|
||||
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
|
||||
|
||||
// Set sampler state here as the same texture can be used in multiple places with different flags
|
||||
// Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
|
||||
RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
|
||||
RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
|
||||
texture->gl_set_filter(filter);
|
||||
texture->gl_set_repeat(repeat);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !GLES3_ENABLED
|
||||
|
@ -45,15 +45,17 @@
|
||||
#include "drivers/gles3/shaders/copy.glsl.gen.h"
|
||||
|
||||
#include "../shaders/canvas.glsl.gen.h"
|
||||
#include "../shaders/scene.glsl.gen.h"
|
||||
#include "../shaders/sky.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
/* SHADER Structs */
|
||||
/* Shader Structs */
|
||||
|
||||
struct Shaders {
|
||||
CanvasShaderGLES3 canvas_shader;
|
||||
SkyShaderGLES3 sky_shader;
|
||||
SceneShaderGLES3 scene_shader;
|
||||
|
||||
ShaderCompiler compiler_canvas;
|
||||
ShaderCompiler compiler_scene;
|
||||
@ -141,7 +143,7 @@ struct Material {
|
||||
update_element(this) {}
|
||||
};
|
||||
|
||||
// CanvasItem Materials
|
||||
/* CanvasItem Materials */
|
||||
|
||||
struct CanvasShaderData : public ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
@ -200,6 +202,179 @@ struct CanvasMaterialData : public MaterialData {
|
||||
|
||||
MaterialData *_create_canvas_material_func(ShaderData *p_shader);
|
||||
|
||||
/* Sky Materials */
|
||||
|
||||
struct SkyShaderData : public ShaderData {
|
||||
bool valid;
|
||||
RID version;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String path;
|
||||
String code;
|
||||
Map<StringName, Map<int, RID>> default_texture_params;
|
||||
|
||||
bool uses_time;
|
||||
bool uses_position;
|
||||
bool uses_half_res;
|
||||
bool uses_quarter_res;
|
||||
bool uses_light;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
|
||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
|
||||
virtual bool is_param_texture(const StringName &p_param) const;
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual Variant get_default_parameter(const StringName &p_parameter) const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
SkyShaderData();
|
||||
virtual ~SkyShaderData();
|
||||
};
|
||||
|
||||
ShaderData *_create_sky_shader_func();
|
||||
|
||||
struct SkyMaterialData : public MaterialData {
|
||||
SkyShaderData *shader_data = nullptr;
|
||||
|
||||
virtual void set_render_priority(int p_priority) {}
|
||||
virtual void set_next_pass(RID p_pass) {}
|
||||
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual void bind_uniforms();
|
||||
virtual ~SkyMaterialData();
|
||||
};
|
||||
|
||||
MaterialData *_create_sky_material_func(ShaderData *p_shader);
|
||||
|
||||
/* Scene Materials */
|
||||
|
||||
struct SceneShaderData : public ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_ALPHA_TO_COVERAGE
|
||||
};
|
||||
|
||||
enum DepthDraw {
|
||||
DEPTH_DRAW_DISABLED,
|
||||
DEPTH_DRAW_OPAQUE,
|
||||
DEPTH_DRAW_ALWAYS
|
||||
};
|
||||
|
||||
enum DepthTest {
|
||||
DEPTH_TEST_DISABLED,
|
||||
DEPTH_TEST_ENABLED
|
||||
};
|
||||
|
||||
enum Cull {
|
||||
CULL_DISABLED,
|
||||
CULL_FRONT,
|
||||
CULL_BACK
|
||||
};
|
||||
|
||||
enum AlphaAntiAliasing {
|
||||
ALPHA_ANTIALIASING_OFF,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
|
||||
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
|
||||
String path;
|
||||
|
||||
Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
Map<StringName, Map<int, RID>> default_texture_params;
|
||||
|
||||
BlendMode blend_mode;
|
||||
AlphaAntiAliasing alpha_antialiasing_mode;
|
||||
DepthDraw depth_draw;
|
||||
DepthTest depth_test;
|
||||
Cull cull_mode;
|
||||
|
||||
bool uses_point_size;
|
||||
bool uses_alpha;
|
||||
bool uses_blend_alpha;
|
||||
bool uses_alpha_clip;
|
||||
bool uses_depth_pre_pass;
|
||||
bool uses_discard;
|
||||
bool uses_roughness;
|
||||
bool uses_normal;
|
||||
bool uses_particle_trails;
|
||||
bool wireframe;
|
||||
|
||||
bool unshaded;
|
||||
bool uses_vertex;
|
||||
bool uses_position;
|
||||
bool uses_sss;
|
||||
bool uses_transmittance;
|
||||
bool uses_screen_texture;
|
||||
bool uses_depth_texture;
|
||||
bool uses_normal_texture;
|
||||
bool uses_time;
|
||||
bool writes_modelview_or_projection;
|
||||
bool uses_world_coordinates;
|
||||
bool uses_tangent;
|
||||
bool uses_color;
|
||||
bool uses_uv;
|
||||
bool uses_uv2;
|
||||
bool uses_custom0;
|
||||
bool uses_custom1;
|
||||
bool uses_custom2;
|
||||
bool uses_custom3;
|
||||
bool uses_bones;
|
||||
bool uses_weights;
|
||||
|
||||
uint32_t vertex_input_mask = 0;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
|
||||
virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
|
||||
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
|
||||
|
||||
virtual bool is_param_texture(const StringName &p_param) const;
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual Variant get_default_parameter(const StringName &p_parameter) const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
|
||||
SceneShaderData();
|
||||
virtual ~SceneShaderData();
|
||||
};
|
||||
|
||||
ShaderData *_create_scene_shader_func();
|
||||
|
||||
struct SceneMaterialData : public MaterialData {
|
||||
SceneShaderData *shader_data = nullptr;
|
||||
uint64_t last_pass = 0;
|
||||
uint32_t index = 0;
|
||||
RID next_pass;
|
||||
uint8_t priority = 0;
|
||||
virtual void set_render_priority(int p_priority);
|
||||
virtual void set_next_pass(RID p_pass);
|
||||
virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual void bind_uniforms();
|
||||
virtual ~SceneMaterialData();
|
||||
};
|
||||
|
||||
MaterialData *_create_scene_material_func(ShaderData *p_shader);
|
||||
|
||||
/* Global variable structs */
|
||||
struct GlobalVariables {
|
||||
enum {
|
||||
|
@ -194,6 +194,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
s->attribute_buffer_size = p_surface.attribute_data.size();
|
||||
}
|
||||
if (p_surface.skin_data.size()) {
|
||||
glGenBuffers(1, &s->skin_buffer);
|
||||
@ -216,6 +217,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
|
||||
s->index_count = p_surface.index_count;
|
||||
s->index_buffer_size = p_surface.index_data.size();
|
||||
|
||||
if (p_surface.lods.size()) {
|
||||
s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
|
||||
@ -323,7 +325,97 @@ RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
|
||||
}
|
||||
|
||||
RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
|
||||
return RS::SurfaceData();
|
||||
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
|
||||
ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
|
||||
ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
|
||||
|
||||
Mesh::Surface &s = *mesh->surfaces[p_surface];
|
||||
|
||||
RS::SurfaceData sd;
|
||||
sd.format = s.format;
|
||||
{
|
||||
Vector<uint8_t> ret;
|
||||
ret.resize(s.vertex_buffer_size);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w);
|
||||
}
|
||||
#else
|
||||
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT);
|
||||
ERR_FAIL_NULL_V(data, RS::SurfaceData());
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
memcpy(w, data, s.vertex_buffer_size);
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
#endif
|
||||
sd.vertex_data = ret;
|
||||
}
|
||||
|
||||
if (s.attribute_buffer != 0) {
|
||||
Vector<uint8_t> ret;
|
||||
ret.resize(s.attribute_buffer_size);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer);
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w);
|
||||
}
|
||||
#else
|
||||
void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT);
|
||||
ERR_FAIL_NULL_V(data, RS::SurfaceData());
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
memcpy(w, data, s.attribute_buffer_size);
|
||||
}
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
#endif
|
||||
sd.attribute_data = ret;
|
||||
}
|
||||
|
||||
sd.vertex_count = s.vertex_count;
|
||||
sd.index_count = s.index_count;
|
||||
sd.primitive = s.primitive;
|
||||
|
||||
if (sd.index_count) {
|
||||
Vector<uint8_t> ret;
|
||||
ret.resize(s.index_buffer_size);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer);
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w);
|
||||
}
|
||||
#else
|
||||
void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT);
|
||||
ERR_FAIL_NULL_V(data, RS::SurfaceData());
|
||||
{
|
||||
uint8_t *w = ret.ptrw();
|
||||
memcpy(w, data, s.index_buffer_size);
|
||||
}
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
#endif
|
||||
sd.index_data = ret;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
sd.aabb = s.aabb;
|
||||
for (uint32_t i = 0; i < s.lod_count; i++) {
|
||||
RS::SurfaceData::LOD lod;
|
||||
lod.edge_length = s.lods[i].edge_length;
|
||||
//lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
|
||||
sd.lods.push_back(lod);
|
||||
}
|
||||
|
||||
sd.bone_aabbs = s.bone_aabbs;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
|
||||
@ -496,7 +588,6 @@ void MeshStorage::mesh_clear(RID p_mesh) {
|
||||
|
||||
if (s.index_buffer != 0) {
|
||||
glDeleteBuffers(1, &s.index_buffer);
|
||||
glDeleteVertexArrays(1, &s.index_array);
|
||||
}
|
||||
memdelete(mesh->surfaces[i]);
|
||||
}
|
||||
@ -553,14 +644,14 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
|
||||
case RS::ARRAY_NORMAL: {
|
||||
attribs[i].offset = vertex_stride;
|
||||
// Will need to change to accommodate octahedral compression
|
||||
attribs[i].size = 1;
|
||||
attribs[i].size = 4;
|
||||
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
vertex_stride += sizeof(float);
|
||||
attribs[i].normalized = GL_TRUE;
|
||||
} break;
|
||||
case RS::ARRAY_TANGENT: {
|
||||
attribs[i].offset = vertex_stride;
|
||||
attribs[i].size = 1;
|
||||
attribs[i].size = 4;
|
||||
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
vertex_stride += sizeof(float);
|
||||
attribs[i].normalized = GL_TRUE;
|
||||
@ -629,14 +720,17 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
|
||||
continue;
|
||||
}
|
||||
if (i <= RS::ARRAY_TANGENT) {
|
||||
attribs[i].stride = vertex_stride;
|
||||
if (mis) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer);
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
|
||||
}
|
||||
} else if (i <= RS::ARRAY_CUSTOM3) {
|
||||
attribs[i].stride = attributes_stride;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
|
||||
} else {
|
||||
attribs[i].stride = skin_stride;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer);
|
||||
}
|
||||
|
||||
@ -645,7 +739,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
|
||||
} else {
|
||||
glVertexAttribPointer(i, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
|
||||
}
|
||||
glEnableVertexAttribArray(attribs[i].index);
|
||||
glEnableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
// Do not bind index here as we want to switch between index buffers for LOD
|
||||
|
@ -54,7 +54,6 @@ struct Mesh {
|
||||
struct Attrib {
|
||||
bool enabled;
|
||||
bool integer;
|
||||
GLuint index;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLboolean normalized;
|
||||
@ -69,6 +68,7 @@ struct Mesh {
|
||||
GLuint skin_buffer = 0;
|
||||
uint32_t vertex_count = 0;
|
||||
uint32_t vertex_buffer_size = 0;
|
||||
uint32_t attribute_buffer_size = 0;
|
||||
uint32_t skin_buffer_size = 0;
|
||||
|
||||
// Cache vertex arrays so they can be created
|
||||
@ -84,8 +84,8 @@ struct Mesh {
|
||||
uint32_t version_count = 0;
|
||||
|
||||
GLuint index_buffer = 0;
|
||||
GLuint index_array = 0;
|
||||
uint32_t index_count = 0;
|
||||
uint32_t index_buffer_size = 0;
|
||||
|
||||
struct LOD {
|
||||
float edge_length = 0.0;
|
||||
@ -357,6 +357,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
|
||||
return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
// Use this to cache Vertex Array Objects so they are only generated once
|
||||
_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
|
||||
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
|
||||
@ -388,6 +394,9 @@ public:
|
||||
|
||||
/* MESH INSTANCE API */
|
||||
|
||||
MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
|
||||
bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
|
||||
|
||||
virtual RID mesh_instance_create(RID p_base) override;
|
||||
virtual void mesh_instance_free(RID p_rid) override;
|
||||
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
|
||||
@ -431,6 +440,9 @@ public:
|
||||
|
||||
/* MULTIMESH API */
|
||||
|
||||
MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
|
||||
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
|
||||
|
||||
virtual RID multimesh_allocate() override;
|
||||
virtual void multimesh_initialize(RID p_rid) override;
|
||||
virtual void multimesh_free(RID p_rid) override;
|
||||
@ -483,6 +495,9 @@ public:
|
||||
|
||||
/* SKELETON API */
|
||||
|
||||
Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
|
||||
bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
|
||||
|
||||
virtual RID skeleton_allocate() override;
|
||||
virtual void skeleton_initialize(RID p_rid) override;
|
||||
virtual void skeleton_free(RID p_rid) override;
|
||||
|
@ -62,8 +62,9 @@ TextureStorage::TextureStorage() {
|
||||
|
||||
Ref<Image> image;
|
||||
image.instantiate();
|
||||
image->create(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->create(4, 4, true, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1, 1, 1, 1));
|
||||
image->generate_mipmaps();
|
||||
|
||||
default_gl_textures[DEFAULT_GL_TEXTURE_WHITE] = texture_allocate();
|
||||
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE], image);
|
||||
@ -92,8 +93,9 @@ TextureStorage::TextureStorage() {
|
||||
{ // black
|
||||
Ref<Image> image;
|
||||
image.instantiate();
|
||||
image->create(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->create(4, 4, true, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(0, 0, 0, 1));
|
||||
image->generate_mipmaps();
|
||||
|
||||
default_gl_textures[DEFAULT_GL_TEXTURE_BLACK] = texture_allocate();
|
||||
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_BLACK], image);
|
||||
@ -117,8 +119,9 @@ TextureStorage::TextureStorage() {
|
||||
{
|
||||
Ref<Image> image;
|
||||
image.instantiate();
|
||||
image->create(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->create(4, 4, true, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(0.5, 0.5, 1, 1));
|
||||
image->generate_mipmaps();
|
||||
|
||||
default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL] = texture_allocate();
|
||||
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL], image);
|
||||
@ -127,8 +130,9 @@ TextureStorage::TextureStorage() {
|
||||
{
|
||||
Ref<Image> image;
|
||||
image.instantiate();
|
||||
image->create(4, 4, false, Image::FORMAT_RGBA8);
|
||||
image->create(4, 4, true, Image::FORMAT_RGBA8);
|
||||
image->fill(Color(1.0, 0.5, 1, 1));
|
||||
image->generate_mipmaps();
|
||||
|
||||
default_gl_textures[DEFAULT_GL_TEXTURE_ANISO] = texture_allocate();
|
||||
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
|
||||
@ -189,18 +193,7 @@ TextureStorage::~TextureStorage() {
|
||||
}
|
||||
}
|
||||
|
||||
void TextureStorage::set_main_thread_id(Thread::ID p_id) {
|
||||
_main_thread_id = p_id;
|
||||
}
|
||||
|
||||
bool TextureStorage::_is_main_thread() {
|
||||
//#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
|
||||
// must be called from main thread in OpenGL
|
||||
bool is_main_thread = _main_thread_id == Thread::get_caller_id();
|
||||
//#endif
|
||||
return is_main_thread;
|
||||
}
|
||||
|
||||
//TODO, move back to storage
|
||||
bool TextureStorage::can_create_resources_async() const {
|
||||
return false;
|
||||
}
|
||||
@ -644,10 +637,14 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
|
||||
Texture texture;
|
||||
texture.width = p_image->get_width();
|
||||
texture.height = p_image->get_height();
|
||||
texture.alloc_width = texture.width;
|
||||
texture.alloc_height = texture.height;
|
||||
texture.mipmaps = p_image->get_mipmap_count();
|
||||
texture.format = p_image->get_format();
|
||||
texture.type = Texture::TYPE_2D;
|
||||
texture.target = GL_TEXTURE_2D;
|
||||
texture.image_cache_2d = p_image; //TODO, remove this once texture_2d_get is implemented
|
||||
_get_gl_image_and_format(Ref<Image>(), texture.format, 0, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false);
|
||||
//texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes
|
||||
texture.active = true;
|
||||
glGenTextures(1, &texture.tex_id);
|
||||
texture_owner.initialize_rid(p_texture, texture);
|
||||
@ -740,49 +737,66 @@ void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
|
||||
}
|
||||
|
||||
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
|
||||
Texture *tex = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_COND_V(!tex, Ref<Image>());
|
||||
Texture *texture = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_COND_V(!texture, Ref<Image>());
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
|
||||
return tex->image_cache_2d;
|
||||
if (texture->image_cache_2d.is_valid() && !texture->is_render_target) {
|
||||
return texture->image_cache_2d;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (tex->image_cache_2d.is_valid()) {
|
||||
return tex->image_cache_2d;
|
||||
#ifdef GLES_OVER_GL
|
||||
// OpenGL 3.3 supports glGetTexImage which is faster and simpler than glReadPixels.
|
||||
Vector<uint8_t> data;
|
||||
|
||||
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
|
||||
|
||||
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
|
||||
uint8_t *w = data.ptrw();
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(texture->target, texture->tex_id);
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
for (int i = 0; i < texture->mipmaps; i++) {
|
||||
int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
|
||||
|
||||
if (texture->compressed) {
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glGetCompressedTexImage(texture->target, i, &w[ofs]);
|
||||
|
||||
} else {
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &w[ofs]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
|
||||
|
||||
data.resize(data_size);
|
||||
|
||||
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
|
||||
Ref<Image> image;
|
||||
image.instance();
|
||||
image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
|
||||
ERR_FAIL_COND_V(image->empty(), Ref<Image>());
|
||||
if (tex->format != tex->validated_format) {
|
||||
image->convert(tex->format);
|
||||
image.instantiate();
|
||||
image->create(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data);
|
||||
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
|
||||
if (texture->format != texture->real_format) {
|
||||
image->convert(texture->format);
|
||||
}
|
||||
#else
|
||||
// Support for Web and Mobile will come later.
|
||||
Ref<Image> image;
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
tex->image_cache_2d = image;
|
||||
if (Engine::get_singleton()->is_editor_hint() && !texture->is_render_target) {
|
||||
texture->image_cache_2d = image;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
/*
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
|
||||
tex->image_cache_2d = image;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
// return image;
|
||||
|
||||
return Ref<Image>();
|
||||
return image;
|
||||
}
|
||||
|
||||
void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
|
||||
@ -1357,6 +1371,9 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
|
||||
}
|
||||
|
||||
texture->format = rt->image_format;
|
||||
texture->real_format = rt->image_format;
|
||||
texture->type = Texture::TYPE_2D;
|
||||
texture->target = GL_TEXTURE_2D;
|
||||
texture->gl_format_cache = rt->color_format;
|
||||
texture->gl_type_cache = GL_UNSIGNED_BYTE;
|
||||
texture->gl_internal_format_cache = rt->color_internal_format;
|
||||
|
@ -141,6 +141,7 @@ struct Texture {
|
||||
int alloc_width = 0;
|
||||
int alloc_height = 0;
|
||||
Image::Format format = Image::FORMAT_R8;
|
||||
Image::Format real_format = Image::FORMAT_R8;
|
||||
|
||||
enum Type {
|
||||
TYPE_2D,
|
||||
@ -370,9 +371,6 @@ private:
|
||||
|
||||
RID default_gl_textures[DEFAULT_GL_TEXTURE_MAX];
|
||||
|
||||
Thread::ID _main_thread_id = 0;
|
||||
bool _is_main_thread();
|
||||
|
||||
/* Canvas Texture API */
|
||||
|
||||
RID_Owner<CanvasTexture, true> canvas_texture_owner;
|
||||
@ -440,8 +438,6 @@ public:
|
||||
};
|
||||
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
|
||||
|
||||
void set_main_thread_id(Thread::ID p_id);
|
||||
|
||||
virtual bool can_create_resources_async() const override;
|
||||
|
||||
RID texture_create();
|
||||
|
@ -623,8 +623,6 @@ void EditorNode::_notification(int p_what) {
|
||||
|
||||
ResourceImporterTexture::get_singleton()->update_imports();
|
||||
|
||||
// if using a main thread only renderer, we need to update the resource previews
|
||||
EditorResourcePreview::get_singleton()->update();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
@ -430,12 +430,8 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
|
||||
}
|
||||
|
||||
void EditorResourcePreview::start() {
|
||||
if (OS::get_singleton()->get_render_main_thread_mode() == OS::RENDER_ANY_THREAD) {
|
||||
ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
|
||||
thread.start(_thread_func, this);
|
||||
} else {
|
||||
_mainthread_only = true;
|
||||
}
|
||||
ERR_FAIL_COND_MSG(thread.is_started(), "Thread already started.");
|
||||
thread.start(_thread_func, this);
|
||||
}
|
||||
|
||||
void EditorResourcePreview::stop() {
|
||||
@ -458,18 +454,3 @@ EditorResourcePreview::EditorResourcePreview() {
|
||||
EditorResourcePreview::~EditorResourcePreview() {
|
||||
stop();
|
||||
}
|
||||
|
||||
void EditorResourcePreview::update() {
|
||||
if (!_mainthread_only) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!exit.is_set()) {
|
||||
// no need to even lock the mutex if the size is zero
|
||||
// there is no problem if queue.size() is wrong, even if
|
||||
// there was a race condition.
|
||||
if (queue.size()) {
|
||||
_iterate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,11 +81,6 @@ class EditorResourcePreview : public Node {
|
||||
SafeFlag exit;
|
||||
SafeFlag exited;
|
||||
|
||||
// when running from GLES, we want to run the previews
|
||||
// in the main thread using an update, rather than create
|
||||
// a separate thread
|
||||
bool _mainthread_only = false;
|
||||
|
||||
struct Item {
|
||||
Ref<Texture2D> preview;
|
||||
Ref<Texture2D> small_preview;
|
||||
@ -125,9 +120,6 @@ public:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
// for single threaded mode
|
||||
void update();
|
||||
|
||||
EditorResourcePreview();
|
||||
~EditorResourcePreview();
|
||||
};
|
||||
|
@ -4112,13 +4112,13 @@ void DisplayServerX11::process_events() {
|
||||
|
||||
void DisplayServerX11::release_rendering_thread() {
|
||||
#if defined(GLES3_ENABLED)
|
||||
// gl_manager->release_current();
|
||||
gl_manager->release_current();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DisplayServerX11::make_rendering_thread() {
|
||||
#if defined(GLES3_ENABLED)
|
||||
// gl_manager->make_current();
|
||||
gl_manager->make_current();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1096,7 +1096,6 @@ void Environment::_validate_property(PropertyInfo &property) const {
|
||||
|
||||
static const char *high_end_prefixes[] = {
|
||||
"auto_exposure_",
|
||||
"tonemap_",
|
||||
"ssr_",
|
||||
"ssao_",
|
||||
nullptr
|
||||
|
@ -95,9 +95,9 @@ public:
|
||||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
low_end = true;
|
||||
}
|
||||
|
||||
bool is_low_end() const override { return true; }
|
||||
uint64_t get_frame_number() const override { return frame; }
|
||||
double get_frame_delta_time() const override { return delta; }
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "core/string/print_string.h"
|
||||
|
||||
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
|
||||
bool RendererCompositor::low_end = false;
|
||||
|
||||
RendererCompositor *RendererCompositor::create() {
|
||||
return _create_func();
|
||||
|
@ -71,6 +71,7 @@ private:
|
||||
protected:
|
||||
static RendererCompositor *(*_create_func)();
|
||||
bool back_end = false;
|
||||
static bool low_end;
|
||||
|
||||
public:
|
||||
static RendererCompositor *create();
|
||||
@ -97,7 +98,7 @@ public:
|
||||
virtual uint64_t get_frame_number() const = 0;
|
||||
virtual double get_frame_delta_time() const = 0;
|
||||
|
||||
_FORCE_INLINE_ virtual bool is_low_end() const { return back_end; };
|
||||
static bool is_low_end() { return low_end; };
|
||||
virtual bool is_xr_enabled() const;
|
||||
|
||||
RendererCompositor();
|
||||
|
@ -131,6 +131,7 @@ public:
|
||||
|
||||
static void make_current() {
|
||||
_create_func = _create_current;
|
||||
low_end = false;
|
||||
}
|
||||
|
||||
static RendererCompositorRD *singleton;
|
||||
|
@ -321,11 +321,7 @@ void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
|
||||
}
|
||||
|
||||
bool RenderingServerDefault::is_low_end() const {
|
||||
// FIXME: Commented out when rebasing vulkan branch on master,
|
||||
// causes a crash, it seems rasterizer is not initialized yet the
|
||||
// first time it's called.
|
||||
//return RSG::rasterizer->is_low_end();
|
||||
return false;
|
||||
return RendererCompositor::is_low_end();
|
||||
}
|
||||
|
||||
void RenderingServerDefault::_thread_exit() {
|
||||
|
@ -113,7 +113,9 @@ public:
|
||||
_changes_changed();
|
||||
|
||||
#else
|
||||
_FORCE_INLINE_ static void redraw_request() { changes++; }
|
||||
_FORCE_INLINE_ static void redraw_request() {
|
||||
changes++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define WRITE_ACTION redraw_request();
|
||||
|
@ -48,8 +48,8 @@ static String _mktab(int p_level) {
|
||||
|
||||
static String _typestr(SL::DataType p_type) {
|
||||
String type = ShaderLanguage::get_datatype_name(p_type);
|
||||
if (ShaderLanguage::is_sampler_type(p_type)) {
|
||||
type = type.replace("sampler", "texture"); //we use textures instead of samplers
|
||||
if (!RS::get_singleton()->is_low_end() && ShaderLanguage::is_sampler_type(p_type)) {
|
||||
type = type.replace("sampler", "texture"); //we use textures instead of samplers in Vulkan GLSL
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@ -538,7 +538,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
||||
continue; // Instances are indexed directly, don't need index uniforms.
|
||||
}
|
||||
if (SL::is_sampler_type(uniform.type)) {
|
||||
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") uniform ";
|
||||
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
|
||||
if (!RS::get_singleton()->is_low_end()) {
|
||||
ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + uniform.texture_binding) + ") ";
|
||||
}
|
||||
ucode += "uniform ";
|
||||
}
|
||||
|
||||
bool is_buffer_global = !SL::is_sampler_type(uniform.type) && uniform.scope == SL::ShaderNode::Uniform::SCOPE_GLOBAL;
|
||||
@ -681,9 +685,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
||||
}
|
||||
|
||||
vcode += ";\n";
|
||||
|
||||
r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode;
|
||||
r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode;
|
||||
// GLSL ES 3.0 does not allow layout qualifiers for varyings
|
||||
if (!RS::get_singleton()->is_low_end()) {
|
||||
r_gen_code.stage_globals[STAGE_VERTEX] += "layout(location=" + itos(index) + ") ";
|
||||
r_gen_code.stage_globals[STAGE_FRAGMENT] += "layout(location=" + itos(index) + ") ";
|
||||
}
|
||||
r_gen_code.stage_globals[STAGE_VERTEX] += interp_mode + "out " + vcode;
|
||||
r_gen_code.stage_globals[STAGE_FRAGMENT] += interp_mode + "in " + vcode;
|
||||
|
||||
index += inc;
|
||||
}
|
||||
@ -1125,8 +1133,8 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
||||
code += ", ";
|
||||
}
|
||||
String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
|
||||
if (is_texture_func && i == 1) {
|
||||
//need to map from texture to sampler in order to sample
|
||||
if (!RS::get_singleton()->is_low_end() && is_texture_func && i == 1) {
|
||||
//need to map from texture to sampler in order to sample when using Vulkan GLSL
|
||||
StringName texture_uniform;
|
||||
bool correct_texture_uniform = false;
|
||||
|
||||
|
@ -2885,6 +2885,7 @@ RenderingServer::RenderingServer() {
|
||||
GLOBAL_DEF("rendering/shading/overrides/force_lambert_over_burley.mobile", true);
|
||||
|
||||
GLOBAL_DEF("rendering/driver/depth_prepass/enable", true);
|
||||
GLOBAL_DEF("rendering/driver/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple");
|
||||
|
||||
GLOBAL_DEF_RST("rendering/textures/default_filters/use_nearest_mipmap_filter", false);
|
||||
GLOBAL_DEF_RST("rendering/textures/default_filters/anisotropic_filtering_level", 2);
|
||||
@ -3002,44 +3003,15 @@ RenderingServer::RenderingServer() {
|
||||
GLOBAL_DEF("rendering/limits/cluster_builder/max_clustered_elements", 512);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/cluster_builder/max_clustered_elements", PropertyInfo(Variant::FLOAT, "rendering/limits/cluster_builder/max_clustered_elements", PROPERTY_HINT_RANGE, "32,8192,1"));
|
||||
|
||||
// OpenGL limits
|
||||
GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_elements", 65536);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_elements", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_elements", PROPERTY_HINT_RANGE, "1024,65536,1"));
|
||||
GLOBAL_DEF_RST("rendering/limits/opengl/max_renderable_lights", 256);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_renderable_lights", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_renderable_lights", PROPERTY_HINT_RANGE, "16,4096,1"));
|
||||
GLOBAL_DEF_RST("rendering/limits/opengl/max_lights_per_object", 8);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/opengl/max_lights_per_object", PropertyInfo(Variant::INT, "rendering/limits/opengl/max_lights_per_object", PROPERTY_HINT_RANGE, "2,1024,1"));
|
||||
|
||||
GLOBAL_DEF_RST_BASIC("xr/shaders/enabled", false);
|
||||
|
||||
GLOBAL_DEF_RST("rendering/2d/options/use_software_skinning", true);
|
||||
GLOBAL_DEF_RST("rendering/2d/options/ninepatch_mode", 1);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/options/ninepatch_mode", PropertyInfo(Variant::INT, "rendering/2d/options/ninepatch_mode", PROPERTY_HINT_ENUM, "Fixed,Scaling"));
|
||||
|
||||
GLOBAL_DEF_RST("rendering/2d/opengl/batching_send_null", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_send_null", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_send_null", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
|
||||
GLOBAL_DEF_RST("rendering/2d/opengl/batching_stream", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/batching_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/batching_stream", PROPERTY_HINT_ENUM, "Default (Off),Off,On"));
|
||||
GLOBAL_DEF_RST("rendering/2d/opengl/legacy_orphan_buffers", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_orphan_buffers", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_orphan_buffers", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
|
||||
GLOBAL_DEF_RST("rendering/2d/opengl/legacy_stream", 0);
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/2d/opengl/legacy_stream", PropertyInfo(Variant::INT, "rendering/2d/opengl/legacy_stream", PROPERTY_HINT_ENUM, "Default (On),Off,On"));
|
||||
|
||||
GLOBAL_DEF("rendering/batching/options/use_batching", false);
|
||||
GLOBAL_DEF_RST("rendering/batching/options/use_batching_in_editor", false);
|
||||
GLOBAL_DEF("rendering/batching/options/single_rect_fallback", false);
|
||||
GLOBAL_DEF("rendering/batching/parameters/max_join_item_commands", 16);
|
||||
GLOBAL_DEF("rendering/batching/parameters/colored_vertex_format_threshold", 0.25f);
|
||||
GLOBAL_DEF("rendering/batching/lights/scissor_area_threshold", 1.0f);
|
||||
GLOBAL_DEF("rendering/batching/lights/max_join_items", 32);
|
||||
GLOBAL_DEF("rendering/batching/parameters/batch_buffer_size", 16384);
|
||||
GLOBAL_DEF("rendering/batching/parameters/item_reordering_lookahead", 4);
|
||||
GLOBAL_DEF("rendering/batching/debug/flash_batching", false);
|
||||
GLOBAL_DEF("rendering/batching/debug/diagnose_frame", false);
|
||||
GLOBAL_DEF("rendering/gles2/compatibility/disable_half_float", false);
|
||||
GLOBAL_DEF("rendering/gles2/compatibility/enable_high_float.Android", false);
|
||||
GLOBAL_DEF("rendering/batching/precision/uv_contract", false);
|
||||
GLOBAL_DEF("rendering/batching/precision/uv_contract_amount", 100);
|
||||
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/max_join_item_commands", PropertyInfo(Variant::INT, "rendering/batching/parameters/max_join_item_commands", PROPERTY_HINT_RANGE, "0,65535"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/colored_vertex_format_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/parameters/colored_vertex_format_threshold", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/batch_buffer_size", PropertyInfo(Variant::INT, "rendering/batching/parameters/batch_buffer_size", PROPERTY_HINT_RANGE, "1024,65535,1024"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/scissor_area_threshold", PropertyInfo(Variant::FLOAT, "rendering/batching/lights/scissor_area_threshold", PROPERTY_HINT_RANGE, "0.0,1.0"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/lights/max_join_items", PropertyInfo(Variant::INT, "rendering/batching/lights/max_join_items", PROPERTY_HINT_RANGE, "0,512"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/parameters/item_reordering_lookahead", PropertyInfo(Variant::INT, "rendering/batching/parameters/item_reordering_lookahead", PROPERTY_HINT_RANGE, "0,256"));
|
||||
ProjectSettings::get_singleton()->set_custom_property_info("rendering/batching/precision/uv_contract_amount", PropertyInfo(Variant::INT, "rendering/batching/precision/uv_contract_amount", PROPERTY_HINT_RANGE, "0,10000"));
|
||||
}
|
||||
|
||||
RenderingServer::~RenderingServer() {
|
||||
|
Loading…
Reference in New Issue
Block a user