feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -33,7 +33,6 @@
#include "config.h"
#include "../rasterizer_gles3.h"
#include "texture_storage.h"
#ifdef WEB_ENABLED
#include <emscripten/html5_webgl.h>
@ -80,16 +79,19 @@ Config::Config() {
bptc_supported = extensions.has("GL_ARB_texture_compression_bptc") || extensions.has("EXT_texture_compression_bptc");
astc_supported = extensions.has("GL_KHR_texture_compression_astc") || extensions.has("GL_OES_texture_compression_astc") || extensions.has("GL_KHR_texture_compression_astc_ldr") || extensions.has("GL_KHR_texture_compression_astc_hdr");
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_ldr");
astc_hdr_supported = extensions.has("GL_KHR_texture_compression_astc_hdr");
astc_layered_supported = extensions.has("GL_KHR_texture_compression_astc_sliced_3d");
if (RasterizerGLES3::is_gles_over_gl()) {
float_texture_supported = true;
float_texture_linear_supported = true;
etc2_supported = false;
s3tc_supported = true;
rgtc_supported = true; //RGTC - core since OpenGL version 3.0
srgb_framebuffer_supported = true;
} else {
float_texture_supported = extensions.has("GL_EXT_color_buffer_float");
float_texture_linear_supported = extensions.has("GL_OES_texture_float_linear");
etc2_supported = true;
#if defined(ANDROID_ENABLED) || defined(IOS_ENABLED)
// Some Android devices report support for S3TC but we don't expect that and don't export the textures.
@ -100,6 +102,7 @@ Config::Config() {
s3tc_supported = extensions.has("GL_EXT_texture_compression_dxt1") || extensions.has("GL_EXT_texture_compression_s3tc") || extensions.has("WEBGL_compressed_texture_s3tc");
#endif
rgtc_supported = extensions.has("GL_EXT_texture_compression_rgtc") || extensions.has("GL_ARB_texture_compression_rgtc") || extensions.has("EXT_texture_compression_rgtc");
srgb_framebuffer_supported = extensions.has("GL_EXT_sRGB_write_control");
}
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &max_vertex_texture_image_units);
@ -107,6 +110,11 @@ Config::Config() {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size);
glGetInteger64v(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_buffer_size);
GLint max_vertex_output;
glGetIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &max_vertex_output);
GLint max_fragment_input;
glGetIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &max_fragment_input);
max_shader_varyings = (uint32_t)MIN(max_vertex_output, max_fragment_input) / 4;
// sanity clamp buffer size to 16K..1MB
max_uniform_buffer_size = CLAMP(max_uniform_buffer_size, 16384, 1048576);
@ -121,7 +129,7 @@ Config::Config() {
#ifdef WEB_ENABLED
msaa_supported = (msaa_max_samples > 0);
#else
msaa_supported = extensions.has("GL_EXT_framebuffer_multisample");
msaa_supported = true;
#endif
#ifndef IOS_ENABLED
#ifdef WEB_ENABLED
@ -138,6 +146,7 @@ Config::Config() {
// These are GLES only
rt_msaa_supported = extensions.has("GL_EXT_multisampled_render_to_texture");
rt_msaa_multiview_supported = extensions.has("GL_OVR_multiview_multisampled_render_to_texture");
external_texture_supported = extensions.has("GL_OES_EGL_image_external_essl3");
if (multiview_supported) {
eglFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)eglGetProcAddress("glFramebufferTextureMultiviewOVR");
@ -166,9 +175,16 @@ Config::Config() {
rt_msaa_multiview_supported = false;
}
}
if (external_texture_supported) {
eglEGLImageTargetTexture2DOES = (PFNEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
if (eglEGLImageTargetTexture2DOES == nullptr) {
external_texture_supported = false;
}
}
#endif
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/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"));
@ -218,7 +234,16 @@ Config::Config() {
//https://github.com/godotengine/godot/issues/92662#issuecomment-2161199477
//disable_particles_workaround = false;
}
} else if (rendering_device_name == "PowerVR Rogue GE8320") {
disable_transform_feedback_shader_cache = true;
}
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3_angle") {
polyfill_half2float = false;
}
#ifdef WEB_ENABLED
polyfill_half2float = false;
#endif
}
Config::~Config() {

View file

@ -36,7 +36,6 @@
#include "core/config/project_settings.h"
#include "core/string/ustring.h"
#include "core/templates/hash_set.h"
#include "core/templates/vector.h"
#include "platform_gl.h"
@ -45,6 +44,7 @@ typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint,
typedef void (*PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean);
typedef void (*PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei);
typedef void (*PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei);
typedef void (*PFNEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum, void *);
#endif
namespace GLES3 {
@ -62,6 +62,7 @@ public:
GLint max_texture_size = 0;
GLint max_viewport_size[2] = { 0, 0 };
GLint64 max_uniform_buffer_size = 0;
uint32_t max_shader_varyings = 0;
int64_t max_renderable_elements = 0;
int64_t max_renderable_lights = 0;
@ -72,6 +73,7 @@ public:
HashSet<String> extensions;
bool float_texture_supported = false;
bool float_texture_linear_supported = false;
bool s3tc_supported = false;
bool rgtc_supported = false;
bool bptc_supported = false;
@ -79,6 +81,7 @@ public:
bool astc_supported = false;
bool astc_hdr_supported = false;
bool astc_layered_supported = false;
bool srgb_framebuffer_supported = false;
bool force_vertex_shading = false;
@ -91,19 +94,27 @@ public:
bool rt_msaa_supported = false;
bool rt_msaa_multiview_supported = false;
bool multiview_supported = false;
bool external_texture_supported = false;
// Adreno 3XX compatibility
bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles'
// Adreno 3XX compatibility.
bool disable_particles_workaround = false; // Set to 'true' to disable 'GPUParticles'.
bool flip_xy_workaround = false;
// PowerVR GE 8320 workaround.
bool disable_transform_feedback_shader_cache = false;
// ANGLE shader workaround.
bool polyfill_half2float = true;
#ifdef ANDROID_ENABLED
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
PFNGLTEXSTORAGE3DMULTISAMPLEPROC eglTexStorage3DMultisample = nullptr;
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC eglFramebufferTexture2DMultisampleEXT = nullptr;
PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC eglFramebufferTextureMultisampleMultiviewOVR = nullptr;
PFNEGLIMAGETARGETTEXTURE2DOESPROC eglEGLImageTargetTexture2DOES = nullptr;
#endif
static Config *get_singleton() { return singleton; };
static Config *get_singleton() { return singleton; }
Config();
~Config();

View file

@ -33,7 +33,6 @@
#include "light_storage.h"
#include "../rasterizer_gles3.h"
#include "../rasterizer_scene_gles3.h"
#include "config.h"
#include "core/config/project_settings.h"
#include "texture_storage.h"
@ -213,6 +212,23 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
light->shadow_caster_mask = p_caster_mask;
light->version++;
light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
uint32_t LightStorage::light_get_shadow_caster_mask(RID p_light) const {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL_V(light, 0);
return light->shadow_caster_mask;
}
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_NULL(light);
@ -454,6 +470,13 @@ void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity
reflection_probe->intensity = p_intensity;
}
void LightStorage::reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_NULL(reflection_probe);
reflection_probe->blend_distance = p_blend_distance;
}
void LightStorage::reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) {
ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_NULL(reflection_probe);
@ -1046,6 +1069,9 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
lightmap->light_texture = p_light;
lightmap->uses_spherical_harmonics = p_uses_spherical_haromics;
Vector3i light_texture_size = GLES3::TextureStorage::get_singleton()->texture_get_size(lightmap->light_texture);
lightmap->light_texture_size = Vector2i(light_texture_size.x, light_texture_size.y);
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->light_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -1184,6 +1210,33 @@ float LightStorage::lightmap_get_probe_capture_update_speed() const {
return lightmap_probe_capture_update_speed;
}
void LightStorage::lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lightmap);
lightmap->shadow_texture = p_shadow;
GLuint tex = GLES3::TextureStorage::get_singleton()->texture_get_texid(lightmap->shadow_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
}
RS::ShadowmaskMode LightStorage::lightmap_get_shadowmask_mode(RID p_lightmap) {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL_V(lightmap, RS::SHADOWMASK_MODE_NONE);
return lightmap->shadowmask_mode;
}
void LightStorage::lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) {
Lightmap *lightmap = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_NULL(lightmap);
lightmap->shadowmask_mode = p_mode;
}
/* LIGHTMAP INSTANCE */
RID LightStorage::lightmap_instance_create(RID p_lightmap) {
@ -1385,7 +1438,7 @@ bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance,
old_shadow = old_key & SHADOW_INDEX_MASK;
// Only re-allocate if a better option is available, and enough time has passed.
should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (tick - shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick > shadow_atlas_realloc_tolerance_msec);
should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version;
if (!should_realloc) {
@ -1518,6 +1571,11 @@ bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_i
uint64_t min_pass = 0; // Pass of the existing one, try to use the least recently used one (LRU fashion).
for (int j = 0; j < sc; j++) {
if (sarr[j].owner_is_omni != is_omni) {
// Existing light instance type doesn't match new light instance type skip.
continue;
}
LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
if (!sli) {
// Found a released light instance.

View file

@ -38,9 +38,7 @@
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "drivers/gles3/storage/texture_storage.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/utilities.h"
@ -59,6 +57,7 @@ struct Light {
RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
uint32_t max_sdfgi_cascade = 2;
uint32_t cull_mask = 0xFFFFFFFF;
uint32_t shadow_caster_mask = 0xFFFFFFFF;
bool distance_fade = false;
real_t distance_fade_begin = 40.0;
real_t distance_fade_shadow = 50.0;
@ -117,6 +116,7 @@ struct ReflectionProbe {
RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
int resolution = 256;
float intensity = 1.0;
float blend_distance = 1.0;
RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
Color ambient_color;
float ambient_color_energy = 1.0;
@ -176,11 +176,14 @@ struct ReflectionProbeInstance {
struct Lightmap {
RID light_texture;
RID shadow_texture;
bool uses_spherical_harmonics = false;
bool interior = false;
AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
float baked_exposure = 1.0;
Vector2i light_texture_size;
int32_t array_index = -1; //unassigned
RS::ShadowmaskMode shadowmask_mode = RS::SHADOWMASK_MODE_NONE;
PackedVector3Array points;
PackedColorArray point_sh;
PackedInt32Array tetrahedra;
@ -202,7 +205,7 @@ struct LightmapInstance {
class LightStorage : public RendererLightStorage {
public:
enum ShadowAtlastQuadrant {
enum ShadowAtlastQuadrant : uint32_t {
QUADRANT_SHIFT = 27,
OMNI_LIGHT_FLAG = 1 << 26,
SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,
@ -229,8 +232,6 @@ private:
mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
/* LIGHTMAP */
Vector<RID> lightmap_textures;
float lightmap_probe_capture_update_speed = 4;
mutable RID_Owner<Lightmap, true> lightmap_owner;
@ -304,8 +305,8 @@ public:
/* Light API */
Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); }
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); }
void _light_initialize(RID p_rid, RS::LightType p_type);
@ -326,6 +327,8 @@ public:
virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) override;
virtual void light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) override;
virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) override;
virtual void light_set_shadow_caster_mask(RID p_light, uint32_t p_caster_mask) override;
virtual uint32_t light_get_shadow_caster_mask(RID p_light) const override;
virtual void light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) override;
virtual void light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) override {}
@ -430,8 +433,8 @@ public:
/* LIGHT INSTANCE API */
LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); };
bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); };
LightInstance *get_light_instance(RID p_rid) { return light_instance_owner.get_or_null(p_rid); }
bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); }
virtual RID light_instance_create(RID p_light) override;
virtual void light_instance_free(RID p_light_instance) override;
@ -629,8 +632,8 @@ public:
/* PROBE API */
ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); }
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); }
virtual RID reflection_probe_allocate() override;
virtual void reflection_probe_initialize(RID p_rid) override;
@ -638,6 +641,7 @@ public:
virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) override;
virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) override;
virtual void reflection_probe_set_blend_distance(RID p_probe, float p_blend_distance) override;
virtual void reflection_probe_set_ambient_mode(RID p_probe, RS::ReflectionProbeAmbientMode p_mode) override;
virtual void reflection_probe_set_ambient_color(RID p_probe, const Color &p_color) override;
virtual void reflection_probe_set_ambient_energy(RID p_probe, float p_energy) override;
@ -711,8 +715,8 @@ public:
/* LIGHTMAP CAPTURE */
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); }
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); }
virtual RID lightmap_allocate() override;
virtual void lightmap_initialize(RID p_rid) override;
@ -733,23 +737,27 @@ public:
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
virtual float lightmap_get_probe_capture_update_speed() const override;
virtual void lightmap_set_shadowmask_textures(RID p_lightmap, RID p_shadow) override;
virtual RS::ShadowmaskMode lightmap_get_shadowmask_mode(RID p_lightmap) override;
virtual void lightmap_set_shadowmask_mode(RID p_lightmap, RS::ShadowmaskMode p_mode) override;
/* LIGHTMAP INSTANCE */
LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); };
bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); };
LightmapInstance *get_lightmap_instance(RID p_rid) { return lightmap_instance_owner.get_or_null(p_rid); }
bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); }
virtual RID lightmap_instance_create(RID p_lightmap) override;
virtual void lightmap_instance_free(RID p_lightmap) override;
virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
/* SHADOW ATLAS API */
bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); };
bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); }
virtual RID shadow_atlas_create() override;
virtual void shadow_atlas_free(RID p_atlas) override;
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override;
virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override;
_FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_instance) {
ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
@ -875,7 +883,7 @@ public:
virtual void shadow_atlas_update(RID p_atlas) override;
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
virtual int get_directional_light_shadow_size(RID p_light_intance) override;
virtual int get_directional_light_shadow_size(RID p_light_instance) override;
virtual void set_directional_shadow_count(int p_count) override;
Rect2i get_directional_shadow_rect();

View file

@ -348,7 +348,7 @@ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_
}
}
_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value> &value, uint8_t *data) {
_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::Scalar> &value, uint8_t *data) {
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
uint32_t *gui = (uint32_t *)data;
@ -572,7 +572,10 @@ void ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_t
Variant ShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
Vector<ShaderLanguage::Scalar> default_value = uniform.default_value;
if (default_value.is_empty()) {
return ShaderLanguage::get_default_datatype_value(uniform.type, uniform.array_size, uniform.hint);
}
return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
}
return Variant();
@ -586,11 +589,7 @@ void ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
continue;
}
if (E.value.texture_order >= 0) {
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.texture_order + 100000));
} else {
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.order));
}
filtered_uniforms.push_back(Pair<StringName, int>(E.key, E.value.prop_order));
}
int uniform_count = filtered_uniforms.size();
sorter.sort(filtered_uniforms.ptr(), uniform_count);
@ -640,7 +639,7 @@ bool ShaderData::is_parameter_texture(const StringName &p_param) const {
return false;
}
return uniforms[p_param].texture_order >= 0;
return uniforms[p_param].is_texture();
}
///////////////////////////////////////////////////////////////////////////
@ -679,6 +678,7 @@ static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
GL_TEXTURE_3D, // TYPE_USAMPLER3D,
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
_GL_TEXTURE_EXTERNAL_OES, // TYPE_SAMPLEREXT
GL_TEXTURE_2D, // TYPE_STRUCT
};
@ -719,7 +719,7 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
bool uses_global_buffer = false;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : p_uniforms) {
if (E.value.order < 0) {
if (E.value.is_texture()) {
continue; // texture, does not go here
}
@ -948,7 +948,10 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
}
} break;
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
ERR_PRINT_ONCE("Type: SamplerCubeArray not supported in GL Compatibility rendering backend, please use another type.");
ERR_PRINT_ONCE("Type: SamplerCubeArray is not supported in the Compatibility renderer, please use another type.");
} break;
case ShaderLanguage::TYPE_SAMPLEREXT: {
gl_texture = texture_storage->texture_gl_get_default(DEFAULT_GL_TEXTURE_EXT);
} break;
case ShaderLanguage::TYPE_ISAMPLER3D:
@ -1193,6 +1196,7 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["world_vertex_coords"] = "#define USE_WORLD_VERTEX_COORDS\n";
actions.global_buffer_array_variable = "global_shader_uniforms";
actions.instance_uniform_index_variable = "read_draw_data_instance_offset";
shaders.compiler_canvas.initialize(actions);
}
@ -1237,6 +1241,8 @@ MaterialStorage::MaterialStorage() {
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["CLIP_SPACE_FAR"] = "SHADER_SPACE_FAR";
actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@ -1276,7 +1282,6 @@ MaterialStorage::MaterialStorage() {
actions.renames["CUSTOM1"] = "custom1_attrib";
actions.renames["CUSTOM2"] = "custom2_attrib";
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
actions.renames["LIGHT_VERTEX"] = "light_vertex";
actions.renames["NODE_POSITION_WORLD"] = "model_matrix[3].xyz";
@ -1367,6 +1372,10 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n";
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
if (!GLES3::Config::get_singleton()->force_vertex_shading) {
// If forcing vertex shading, this will be defined already.
actions.render_mode_defines["vertex_lighting"] = "#define USE_VERTEX_LIGHTING\n";
}
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
@ -1374,6 +1383,7 @@ MaterialStorage::MaterialStorage() {
actions.check_multiview_samplers = RasterizerGLES3::get_singleton()->is_xr_enabled();
actions.global_buffer_array_variable = "global_shader_uniforms";
actions.instance_uniform_index_variable = "instance_offset";
shaders.compiler_scene.initialize(actions);
}
@ -1385,7 +1395,7 @@ MaterialStorage::MaterialStorage() {
actions.renames["COLOR"] = "out_color";
actions.renames["VELOCITY"] = "out_velocity_flags.xyz";
//actions.renames["MASS"] = "mass"; ?
actions.renames["MASS"] = "mass";
actions.renames["ACTIVE"] = "particle_active";
actions.renames["RESTART"] = "restart";
actions.renames["CUSTOM"] = "out_custom";
@ -1952,6 +1962,7 @@ void MaterialStorage::global_shader_parameters_load_settings(bool p_load_texture
"sampler2DArray",
"sampler3D",
"samplerCube",
"samplerExternalOES"
};
RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
@ -2498,6 +2509,19 @@ bool MaterialStorage::material_casts_shadows(RID p_material) {
return true; //by default everything casts shadows
}
RS::CullMode MaterialStorage::material_get_cull_mode(RID p_material) const {
const GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_NULL_V(material, RS::CULL_MODE_DISABLED);
ERR_FAIL_NULL_V(material->shader, RS::CULL_MODE_DISABLED);
if (material->shader->data) {
SceneShaderData *data = dynamic_cast<SceneShaderData *>(material->shader->data);
if (data) {
return (RS::CullMode)data->cull_mode;
}
}
return RS::CULL_MODE_DISABLED;
}
void MaterialStorage::material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) {
GLES3::Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_NULL(material);
@ -2664,7 +2688,11 @@ static void bind_uniforms_generic(const Vector<RID> &p_textures, const Vector<Sh
const ShaderCompiler::GeneratedCode::Texture &texture_uniform = texture_uniforms[texture_uniform_index];
if (texture) {
glActiveTexture(GL_TEXTURE0 + texture_offset + ti);
glBindTexture(target_from_type[texture_uniform.type], texture->tex_id);
GLenum target = target_from_type[texture_uniform.type];
if (target == _GL_TEXTURE_EXTERNAL_OES && !GLES3::Config::get_singleton()->external_texture_supported) {
target = GL_TEXTURE_2D;
}
glBindTexture(target, texture->tex_id);
if (texture->render_target) {
texture->render_target->used_in_frame = true;
}
@ -2896,7 +2924,7 @@ void SceneShaderData::set_code(const String &p_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 cull_modei = RS::CULL_MODE_BACK;
int depth_drawi = DEPTH_DRAW_OPAQUE;
ShaderCompiler::IdentifierActions actions;
@ -2919,9 +2947,9 @@ void SceneShaderData::set_code(const String &p_code) {
actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_DISABLED);
actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_FRONT);
actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, RS::CULL_MODE_BACK);
actions.render_mode_flags["unshaded"] = &unshaded;
actions.render_mode_flags["wireframe"] = &wireframe;
@ -2979,7 +3007,7 @@ void SceneShaderData::set_code(const String &p_code) {
alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
cull_mode = RS::CullMode(cull_modei);
vertex_input_mask = RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL; // We can always read vertices and normals.
vertex_input_mask |= uses_tangent << RS::ARRAY_TANGENT;
@ -3002,19 +3030,19 @@ void SceneShaderData::set_code(const String &p_code) {
#ifdef DEBUG_ENABLED
if (uses_particle_trails) {
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile rendering backends.");
WARN_PRINT_ONCE_ED("Particle trails are only available when using the Forward+ or Mobile renderers.");
}
if (uses_sss) {
WARN_PRINT_ONCE_ED("Sub-surface scattering is only available when using the Forward+ rendering backend.");
WARN_PRINT_ONCE_ED("Subsurface scattering is only available when using the Forward+ renderer.");
}
if (uses_transmittance) {
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ rendering backend.");
WARN_PRINT_ONCE_ED("Transmittance is only available when using the Forward+ renderer.");
}
if (uses_normal_texture) {
WARN_PRINT_ONCE_ED("Reading from the normal-roughness texture is only available when using the Forward+ or Mobile rendering backends.");
WARN_PRINT_ONCE_ED("Reading from the normal-roughness texture is only available when using the Forward+ or Mobile renderers.");
}
#endif

View file

@ -33,10 +33,8 @@
#ifdef GLES3_ENABLED
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/storage/material_storage.h"
@ -263,12 +261,6 @@ struct SceneShaderData : public ShaderData {
DEPTH_TEST_ENABLED
};
enum Cull {
CULL_DISABLED,
CULL_FRONT,
CULL_BACK
};
enum AlphaAntiAliasing {
ALPHA_ANTIALIASING_OFF,
ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
@ -292,7 +284,7 @@ struct SceneShaderData : public ShaderData {
AlphaAntiAliasing alpha_antialiasing_mode;
DepthDraw depth_draw;
DepthTest depth_test;
Cull cull_mode;
RS::CullMode cull_mode;
bool uses_point_size;
bool uses_alpha;
@ -576,8 +568,8 @@ public:
/* SHADER API */
Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); }
void _shader_make_dirty(Shader *p_shader);
@ -598,8 +590,8 @@ public:
/* MATERIAL API */
Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); }
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); }
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
void _update_queued_materials();
@ -618,6 +610,7 @@ public:
virtual bool material_is_animated(RID p_material) override;
virtual bool material_casts_shadows(RID p_material) override;
virtual RS::CullMode material_get_cull_mode(RID p_material) const override;
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;

View file

@ -32,7 +32,6 @@
#include "mesh_storage.h"
#include "config.h"
#include "material_storage.h"
#include "texture_storage.h"
#include "utilities.h"
@ -301,7 +300,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
Vector<uint8_t> ir = new_surface.index_data;
wr = wf_indices.ptrw();
if (new_surface.vertex_count < (1 << 16)) {
if (new_surface.vertex_count <= 65536) {
// Read 16 bit indices.
const uint16_t *src_idx = (const uint16_t *)ir.ptr();
for (uint32_t i = 0; i + 5 < wf_index_count; i += 6) {
@ -448,6 +447,72 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
mesh->material_cache.clear();
}
void MeshStorage::_mesh_surface_clear(Mesh *mesh, int p_surface) {
Mesh::Surface &s = *mesh->surfaces[p_surface];
if (s.vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.vertex_buffer);
s.vertex_buffer = 0;
}
if (s.version_count != 0) {
for (uint32_t j = 0; j < s.version_count; j++) {
glDeleteVertexArrays(1, &s.versions[j].vertex_array);
s.versions[j].vertex_array = 0;
}
}
if (s.attribute_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.attribute_buffer);
s.attribute_buffer = 0;
}
if (s.skin_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.skin_buffer);
s.skin_buffer = 0;
}
if (s.index_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.index_buffer);
s.index_buffer = 0;
}
if (s.versions) {
memfree(s.versions); // reallocs, so free with memfree.
}
if (s.wireframe) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
memdelete(s.wireframe);
}
if (s.lod_count) {
for (uint32_t j = 0; j < s.lod_count; j++) {
if (s.lods[j].index_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.lods[j].index_buffer);
s.lods[j].index_buffer = 0;
}
}
memdelete_arr(s.lods);
}
if (mesh->blend_shape_count) {
for (uint32_t j = 0; j < mesh->blend_shape_count; j++) {
if (s.blend_shapes[j].vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.blend_shapes[j].vertex_buffer);
s.blend_shapes[j].vertex_buffer = 0;
}
if (s.blend_shapes[j].vertex_array != 0) {
glDeleteVertexArrays(1, &s.blend_shapes[j].vertex_array);
s.blend_shapes[j].vertex_array = 0;
}
}
memdelete_arr(s.blend_shapes);
}
memdelete(mesh->surfaces[p_surface]);
}
int MeshStorage::mesh_get_blend_shape_count(RID p_mesh) const {
const Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL_V(mesh, -1);
@ -743,6 +808,7 @@ String MeshStorage::mesh_get_path(RID p_mesh) const {
}
void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
ERR_FAIL_COND_MSG(p_mesh == p_shadow_mesh, "Cannot set a mesh as its own shadow mesh.");
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL(mesh);
@ -771,69 +837,7 @@ void MeshStorage::mesh_clear(RID p_mesh) {
}
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
if (s.vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.vertex_buffer);
s.vertex_buffer = 0;
}
if (s.version_count != 0) {
for (uint32_t j = 0; j < s.version_count; j++) {
glDeleteVertexArrays(1, &s.versions[j].vertex_array);
s.versions[j].vertex_array = 0;
}
}
if (s.attribute_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.attribute_buffer);
s.attribute_buffer = 0;
}
if (s.skin_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.skin_buffer);
s.skin_buffer = 0;
}
if (s.index_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.index_buffer);
s.index_buffer = 0;
}
if (s.versions) {
memfree(s.versions); //reallocs, so free with memfree.
}
if (s.wireframe) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.wireframe->index_buffer);
memdelete(s.wireframe);
}
if (s.lod_count) {
for (uint32_t j = 0; j < s.lod_count; j++) {
if (s.lods[j].index_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.lods[j].index_buffer);
s.lods[j].index_buffer = 0;
}
}
memdelete_arr(s.lods);
}
if (mesh->blend_shape_count) {
for (uint32_t j = 0; j < mesh->blend_shape_count; j++) {
if (s.blend_shapes[j].vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(s.blend_shapes[j].vertex_buffer);
s.blend_shapes[j].vertex_buffer = 0;
}
if (s.blend_shapes[j].vertex_array != 0) {
glDeleteVertexArrays(1, &s.blend_shapes[j].vertex_array);
s.blend_shapes[j].vertex_array = 0;
}
}
memdelete_arr(s.blend_shapes);
}
memdelete(mesh->surfaces[i]);
_mesh_surface_clear(mesh, i);
}
if (mesh->surfaces) {
memfree(mesh->surfaces);
@ -843,6 +847,7 @@ void MeshStorage::mesh_clear(RID p_mesh) {
mesh->surface_count = 0;
mesh->material_cache.clear();
mesh->has_bone_weights = false;
mesh->aabb = AABB();
mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
@ -1032,6 +1037,56 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
v.input_mask = p_input_mask;
}
void MeshStorage::mesh_surface_remove(RID p_mesh, int p_surface) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
ERR_FAIL_NULL(mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
// Clear instance data before mesh data.
for (MeshInstance *mi : mesh->instances) {
_mesh_instance_remove_surface(mi, p_surface);
}
_mesh_surface_clear(mesh, p_surface);
if ((uint32_t)p_surface < mesh->surface_count - 1) {
memmove(mesh->surfaces + p_surface, mesh->surfaces + p_surface + 1, sizeof(Mesh::Surface *) * (mesh->surface_count - (p_surface + 1)));
}
mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count - 1));
--mesh->surface_count;
mesh->material_cache.clear();
mesh->skeleton_aabb_version = 0;
if (mesh->has_bone_weights) {
mesh->has_bone_weights = false;
for (uint32_t i = 0; i < mesh->surface_count; i++) {
if (mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) {
mesh->has_bone_weights = true;
break;
}
}
}
if (mesh->surface_count == 0) {
mesh->aabb = AABB();
} else {
mesh->aabb = mesh->surfaces[0]->aabb;
for (uint32_t i = 1; i < mesh->surface_count; i++) {
mesh->aabb.merge_with(mesh->surfaces[i]->aabb);
}
}
mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
/* MESH INSTANCE API */
RID MeshStorage::mesh_instance_create(RID p_base) {
@ -1082,30 +1137,10 @@ void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int
}
void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
for (uint32_t i = 0; i < mi->surfaces.size(); i++) {
if (mi->surfaces[i].version_count != 0) {
for (uint32_t j = 0; j < mi->surfaces[i].version_count; j++) {
glDeleteVertexArrays(1, &mi->surfaces[i].versions[j].vertex_array);
mi->surfaces[i].versions[j].vertex_array = 0;
}
memfree(mi->surfaces[i].versions);
}
if (mi->surfaces[i].vertex_buffers[0] != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[0]);
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffers[1]);
mi->surfaces[i].vertex_buffers[0] = 0;
mi->surfaces[i].vertex_buffers[1] = 0;
}
if (mi->surfaces[i].vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(mi->surfaces[i].vertex_buffer);
mi->surfaces[i].vertex_buffer = 0;
}
while (mi->surfaces.size()) {
_mesh_instance_remove_surface(mi, mi->surfaces.size() - 1);
}
mi->surfaces.clear();
mi->blend_weights.clear();
mi->skeleton_version = 0;
mi->dirty = false;
}
void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface) {
@ -1158,6 +1193,39 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
mi->dirty = true;
}
void MeshStorage::_mesh_instance_remove_surface(MeshInstance *mi, int p_surface) {
MeshInstance::Surface &surface = mi->surfaces[p_surface];
if (surface.version_count != 0) {
for (uint32_t j = 0; j < surface.version_count; j++) {
glDeleteVertexArrays(1, &surface.versions[j].vertex_array);
surface.versions[j].vertex_array = 0;
}
memfree(surface.versions);
}
if (surface.vertex_buffers[0] != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffers[0]);
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffers[1]);
surface.vertex_buffers[0] = 0;
surface.vertex_buffers[1] = 0;
}
if (surface.vertex_buffer != 0) {
GLES3::Utilities::get_singleton()->buffer_free_data(surface.vertex_buffer);
surface.vertex_buffer = 0;
}
mi->surfaces.remove_at(p_surface);
if (mi->surfaces.is_empty()) {
mi->blend_weights.clear();
mi->weights_dirty = false;
mi->skeleton_version = 0;
}
mi->dirty = true;
}
void MeshStorage::mesh_instance_check_for_update(RID p_mesh_instance) {
MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
@ -1258,7 +1326,7 @@ void MeshStorage::update_mesh_instances() {
// Precompute base weight if using blend shapes.
float base_weight = 1.0;
if (mi->mesh->blend_shape_count && mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED) {
if (mi->surfaces.size() && mi->mesh->blend_shape_count && mi->mesh->blend_shape_mode == RS::BLEND_SHAPE_MODE_NORMALIZED) {
for (uint32_t i = 0; i < mi->mesh->blend_shape_count; i++) {
base_weight -= mi->blend_weights[i];
}
@ -1432,15 +1500,17 @@ void MeshStorage::update_mesh_instances() {
/* MULTIMESH API */
RID MeshStorage::multimesh_allocate() {
RID MeshStorage::_multimesh_allocate() {
return multimesh_owner.allocate_rid();
}
void MeshStorage::multimesh_initialize(RID p_rid) {
void MeshStorage::_multimesh_initialize(RID p_rid) {
multimesh_owner.initialize_rid(p_rid, MultiMesh());
}
void MeshStorage::multimesh_free(RID p_rid) {
void MeshStorage::_multimesh_free(RID p_rid) {
// Remove from interpolator.
_interpolation_data.notify_free_multimesh(p_rid);
_update_dirty_multimeshes();
multimesh_allocate_data(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);
MultiMesh *multimesh = multimesh_owner.get_or_null(p_rid);
@ -1448,7 +1518,7 @@ void MeshStorage::multimesh_free(RID p_rid) {
multimesh_owner.free(p_rid);
}
void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) {
void MeshStorage::_multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data, bool p_use_indirect) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
@ -1495,13 +1565,13 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
}
int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
int MeshStorage::_multimesh_get_instance_count(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, 0);
return multimesh->instances;
}
void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
void MeshStorage::_multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
if (multimesh->mesh == p_mesh || p_mesh.is_null()) {
@ -1651,7 +1721,7 @@ void MeshStorage::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p
multimesh->aabb = aabb;
}
void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
void MeshStorage::_multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@ -1681,7 +1751,7 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
_multimesh_mark_dirty(multimesh, p_index, true);
}
void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
void MeshStorage::_multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@ -1707,7 +1777,7 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind
_multimesh_mark_dirty(multimesh, p_index, true);
}
void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
void MeshStorage::_multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@ -1727,7 +1797,7 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con
_multimesh_mark_dirty(multimesh, p_index, false);
}
void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
void MeshStorage::_multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
ERR_FAIL_INDEX(p_index, multimesh->instances);
@ -1746,39 +1816,39 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde
_multimesh_mark_dirty(multimesh, p_index, false);
}
RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
RID MeshStorage::_multimesh_get_mesh(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, RID());
return multimesh->mesh;
}
void MeshStorage::multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
void MeshStorage::_multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
multimesh->custom_aabb = p_aabb;
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
AABB MeshStorage::multimesh_get_custom_aabb(RID p_multimesh) const {
AABB MeshStorage::_multimesh_get_custom_aabb(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, AABB());
return multimesh->custom_aabb;
}
AABB MeshStorage::multimesh_get_aabb(RID p_multimesh) const {
AABB MeshStorage::_multimesh_get_aabb(RID p_multimesh) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, AABB());
if (multimesh->custom_aabb != AABB()) {
return multimesh->custom_aabb;
}
if (multimesh->aabb_dirty) {
const_cast<MeshStorage *>(this)->_update_dirty_multimeshes();
_update_dirty_multimeshes();
}
return multimesh->aabb;
}
Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
Transform3D MeshStorage::_multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Transform3D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform3D());
@ -1809,7 +1879,7 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p
return t;
}
Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
Transform2D MeshStorage::_multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Transform2D());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D());
@ -1834,7 +1904,7 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in
return t;
}
Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) const {
Color MeshStorage::_multimesh_instance_get_color(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
@ -1858,7 +1928,7 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co
return c;
}
Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
Color MeshStorage::_multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Color());
ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color());
@ -1882,7 +1952,7 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
return c;
}
void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
void MeshStorage::_multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
@ -1971,7 +2041,15 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
}
}
Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
RID MeshStorage::_multimesh_get_command_buffer_rd_rid(RID p_multimesh) const {
ERR_FAIL_V_MSG(RID(), "GLES3 does not implement indirect multimeshes.");
}
RID MeshStorage::_multimesh_get_buffer_rd_rid(RID p_multimesh) const {
ERR_FAIL_V_MSG(RID(), "GLES3 does not contain a Rid for the multimesh buffer.");
}
Vector<float> MeshStorage::_multimesh_get_buffer(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, Vector<float>());
Vector<float> ret;
@ -2043,7 +2121,7 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
}
}
void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
void MeshStorage::_multimesh_set_visible_instances(RID p_multimesh, int p_visible) {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL(multimesh);
ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances);
@ -2065,12 +2143,19 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
int MeshStorage::_multimesh_get_visible_instances(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V(multimesh, 0);
return multimesh->visible_instances;
}
MeshStorage::MultiMeshInterpolator *MeshStorage::_multimesh_get_interpolator(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_NULL_V_MSG(multimesh, nullptr, "Multimesh not found: " + itos(p_multimesh.get_id()));
return &multimesh->interpolator;
}
void MeshStorage::_update_dirty_multimeshes() {
while (multimesh_dirty_list) {
MultiMesh *multimesh = multimesh_dirty_list;
@ -2191,7 +2276,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
glBindTexture(GL_TEXTURE_2D, 0);
GLES3::Utilities::get_singleton()->texture_allocated_data(skeleton->transforms_texture, skeleton->data.size() * sizeof(float), "Skeleton transforms texture");
memset(skeleton->data.ptrw(), 0, skeleton->data.size() * sizeof(float));
memset(skeleton->data.ptr(), 0, skeleton->data.size() * sizeof(float));
_skeleton_make_dirty(skeleton);
}
@ -2222,7 +2307,7 @@ void MeshStorage::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(skeleton->use_2d);
float *dataptr = skeleton->data.ptrw() + p_bone * 12;
float *dataptr = skeleton->data.ptr() + p_bone * 12;
dataptr[0] = p_transform.basis.rows[0][0];
dataptr[1] = p_transform.basis.rows[0][1];
@ -2274,7 +2359,7 @@ void MeshStorage::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, con
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(!skeleton->use_2d);
float *dataptr = skeleton->data.ptrw() + p_bone * 8;
float *dataptr = skeleton->data.ptr() + p_bone * 8;
dataptr[0] = p_transform.columns[0][0];
dataptr[1] = p_transform.columns[1][0];

View file

@ -205,6 +205,8 @@ struct MultiMesh {
bool dirty = false;
MultiMesh *dirty_list = nullptr;
RendererMeshStorage::MultiMeshInterpolator interpolator;
Dependency dependency;
};
@ -212,7 +214,7 @@ struct Skeleton {
bool use_2d = false;
int size = 0;
int height = 0;
Vector<float> data;
LocalVector<float> data;
bool dirty = false;
Skeleton *dirty_list = nullptr;
@ -239,6 +241,7 @@ private:
mutable RID_Owner<Mesh, true> mesh_owner;
void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint64_t p_input_mask, MeshInstance::Surface *mis = nullptr);
void _mesh_surface_clear(Mesh *mesh, int p_surface);
/* Mesh Instance API */
@ -246,6 +249,7 @@ private:
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
void _mesh_instance_remove_surface(MeshInstance *mi, int p_surface);
void _blend_shape_bind_mesh_instance_buffer(MeshInstance *p_mi, uint32_t p_surface);
SelfList<MeshInstance>::List dirty_mesh_instance_weights;
SelfList<MeshInstance>::List dirty_mesh_instance_arrays;
@ -278,8 +282,8 @@ public:
/* MESH API */
Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); }
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); }
virtual RID mesh_allocate() override;
virtual void mesh_initialize(RID p_rid) override;
@ -313,7 +317,9 @@ public:
virtual String mesh_get_path(RID p_mesh) const override;
virtual void mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) override;
virtual void mesh_clear(RID p_mesh) override;
virtual void mesh_surface_remove(RID p_mesh, int p_surface) override;
_FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) {
Mesh *mesh = mesh_owner.get_or_null(p_mesh);
@ -441,8 +447,8 @@ 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); };
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;
@ -490,35 +496,39 @@ 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); };
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;
virtual void multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) override;
virtual int multimesh_get_instance_count(RID p_multimesh) const override;
virtual RID _multimesh_allocate() override;
virtual void _multimesh_initialize(RID p_rid) override;
virtual void _multimesh_free(RID p_rid) override;
virtual void _multimesh_allocate_data(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false, bool p_use_indirect = false) override;
virtual int _multimesh_get_instance_count(RID p_multimesh) const override;
virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
virtual void _multimesh_set_mesh(RID p_multimesh, RID p_mesh) override;
virtual void _multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform3D &p_transform) override;
virtual void _multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) override;
virtual void _multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) override;
virtual void _multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) override;
virtual RID multimesh_get_mesh(RID p_multimesh) const override;
virtual void multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override;
virtual AABB multimesh_get_custom_aabb(RID p_multimesh) const override;
virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
virtual RID _multimesh_get_mesh(RID p_multimesh) const override;
virtual void _multimesh_set_custom_aabb(RID p_multimesh, const AABB &p_aabb) override;
virtual AABB _multimesh_get_custom_aabb(RID p_multimesh) const override;
virtual AABB _multimesh_get_aabb(RID p_multimesh) override;
virtual Transform3D multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
virtual Vector<float> multimesh_get_buffer(RID p_multimesh) const override;
virtual Transform3D _multimesh_instance_get_transform(RID p_multimesh, int p_index) const override;
virtual Transform2D _multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_color(RID p_multimesh, int p_index) const override;
virtual Color _multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const override;
virtual void _multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_buffer) override;
virtual RID _multimesh_get_command_buffer_rd_rid(RID p_multimesh) const override;
virtual RID _multimesh_get_buffer_rd_rid(RID p_multimesh) const override;
virtual Vector<float> _multimesh_get_buffer(RID p_multimesh) const override;
virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
virtual int multimesh_get_visible_instances(RID p_multimesh) const override;
virtual void _multimesh_set_visible_instances(RID p_multimesh, int p_visible) override;
virtual int _multimesh_get_visible_instances(RID p_multimesh) const override;
virtual MultiMeshInterpolator *_multimesh_get_interpolator(RID p_multimesh) const override;
void _update_dirty_multimeshes();
@ -567,8 +577,8 @@ 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); };
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;

View file

@ -38,7 +38,7 @@
#include "texture_storage.h"
#include "utilities.h"
#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/rendering_server_globals.h"
using namespace GLES3;
@ -223,6 +223,19 @@ void ParticlesStorage::particles_set_pre_process_time(RID p_particles, double p_
ERR_FAIL_NULL(particles);
particles->pre_process_time = p_time;
}
void ParticlesStorage::particles_request_process_time(RID p_particles, real_t p_request_process_time) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->request_process_time = p_request_process_time;
}
void ParticlesStorage::particles_set_seed(RID p_particles, uint32_t p_seed) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
particles->random_seed = p_seed;
}
void ParticlesStorage::particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
@ -287,13 +300,13 @@ void ParticlesStorage::particles_set_fractional_delta(RID p_particles, bool p_en
void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, double p_length) {
if (p_enable) {
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle trails.");
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle trails.");
}
}
void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
if (p_bind_poses.size() != 0) {
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle trails.");
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle trails.");
}
}
@ -357,12 +370,12 @@ void ParticlesStorage::particles_restart(RID p_particles) {
void ParticlesStorage::particles_set_subemitter(RID p_particles, RID p_subemitter_particles) {
if (p_subemitter_particles.is_valid()) {
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support particle sub-emitters.");
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support particle sub-emitters.");
}
}
void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_transform, const Vector3 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) {
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support manually emitting particles.");
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support manually emitting particles.");
}
void ParticlesStorage::particles_request_process(RID p_particles) {
@ -507,7 +520,6 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
if (p_particles->clear) {
p_particles->cycle_number = 0;
p_particles->random_seed = Math::rand();
} else if (new_phase < p_particles->phase) {
if (p_particles->one_shot) {
p_particles->emitting = false;
@ -645,7 +657,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
attr.extents[2] = extents.z;
} break;
case RS::PARTICLES_COLLISION_TYPE_VECTOR_FIELD_ATTRACT: {
WARN_PRINT_ONCE_ED("Vector field particle attractors are not available in the GL Compatibility rendering backend.");
WARN_PRINT_ONCE_ED("Vector field particle attractors are not available in the Compatibility renderer.");
} break;
default: {
}
@ -678,7 +690,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
col.extents[2] = extents.z;
} break;
case RS::PARTICLES_COLLISION_TYPE_SDF_COLLIDE: {
WARN_PRINT_ONCE_ED("SDF Particle Colliders are not available in the GL Compatibility rendering backend.");
WARN_PRINT_ONCE_ED("SDF Particle Colliders are not available in the Compatibility renderer.");
} break;
case RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE: {
if (collision_heightmap_texture != 0) { //already taken
@ -1136,6 +1148,24 @@ void ParticlesStorage::update_particles() {
}
}
if (particles->request_process_time > 0.0) {
double frame_time;
if (fixed_fps > 0) {
frame_time = 1.0 / fixed_fps;
} else {
frame_time = 1.0 / 30.0;
}
float tmp_scale = particles->speed_scale;
particles->speed_scale = 1.0;
double todo = particles->request_process_time;
while (todo >= 0) {
_particles_process(particles, frame_time);
todo -= frame_time;
}
particles->speed_scale = tmp_scale;
particles->request_process_time = 0.0;
}
// Copy particles to instance buffer and pack Color/Custom.
// We don't have camera information here, so don't copy here if we need camera information for view depth or align mode.
if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_VIEW_DEPTH && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD && particles->transform_align != RS::PARTICLES_TRANSFORM_ALIGN_Z_BILLBOARD_Y_TO_VELOCITY) {
@ -1341,7 +1371,7 @@ void ParticlesStorage::particles_collision_set_attractor_attenuation(RID p_parti
}
void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_collision, RID p_texture) {
WARN_PRINT_ONCE_ED("The GL Compatibility rendering backend does not support SDF collisions in 3D particle shaders");
WARN_PRINT_ONCE_ED("The Compatibility renderer does not support SDF collisions in 3D particle shaders");
}
void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
@ -1402,6 +1432,18 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
uint32_t ParticlesStorage::particles_collision_get_height_field_mask(RID p_particles_collision) const {
const ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_NULL_V(particles_collision, false);
return particles_collision->heightfield_mask;
}
void ParticlesStorage::particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) {
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_NULL(particles_collision);
particles_collision->heightfield_mask = p_heightfield_mask;
}
Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const {
ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_NULL_V(pc, nullptr);

View file

@ -33,7 +33,6 @@
#ifdef GLES3_ENABLED
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "drivers/gles3/shaders/particles_copy.glsl.gen.h"
@ -158,6 +157,7 @@ private:
int amount = 0;
double lifetime = 1.0;
double pre_process_time = 0.0;
real_t request_process_time = 0.0;
real_t explosiveness = 0.0;
real_t randomness = 0.0;
bool restart_request = false;
@ -247,6 +247,7 @@ private:
Particles() :
update_list(this) {
random_seed = Math::rand();
}
};
@ -286,6 +287,7 @@ private:
GLuint heightfield_texture = 0;
GLuint heightfield_fb = 0;
Size2i heightfield_fb_size;
uint32_t heightfield_mask = (1 << 20) - 1;
RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
@ -326,6 +328,7 @@ public:
virtual void particles_set_lifetime(RID p_particles, double p_lifetime) override;
virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) override;
virtual void particles_set_pre_process_time(RID p_particles, double p_time) override;
virtual void particles_request_process_time(RID p_particles, real_t p_request_process_time) override;
virtual void particles_set_explosiveness_ratio(RID p_particles, real_t p_ratio) override;
virtual void particles_set_randomness_ratio(RID p_particles, real_t p_ratio) override;
virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) override;
@ -341,6 +344,7 @@ public:
virtual void particles_set_collision_base_size(RID p_particles, real_t p_size) override;
virtual void particles_set_transform_align(RID p_particles, RS::ParticlesTransformAlign p_transform_align) override;
virtual void particles_set_seed(RID p_particles, uint32_t p_seed) override;
virtual void particles_set_trails(RID p_particles, bool p_enable, double p_length) override;
virtual void particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) override;
@ -396,7 +400,7 @@ public:
_FORCE_INLINE_ bool particles_has_collision(RID p_particles) {
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL_V(particles, 0);
ERR_FAIL_NULL_V(particles, false);
return particles->has_collision_cache;
}
@ -431,6 +435,8 @@ public:
Vector3 particles_collision_get_extents(RID p_particles_collision) const;
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
GLuint particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const;
virtual uint32_t particles_collision_get_height_field_mask(RID p_particles_collision) const override;
virtual void particles_collision_set_height_field_mask(RID p_particles_collision, uint32_t p_heightfield_mask) override;
_FORCE_INLINE_ Size2i particles_collision_get_heightfield_size(RID p_particles_collision) const {
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);

View file

@ -138,6 +138,7 @@ void RenderSceneBuffersGLES3::configure(const RenderSceneBuffersConfiguration *p
scaling_3d_mode = p_config->get_scaling_3d_mode();
//fsr_sharpness = p_config->get_fsr_sharpness();
//texture_mipmap_bias = p_config->get_texture_mipmap_bias();
//anisotropic_filtering_level = p_config->get_anisotropic_filtering_level();
render_target = p_config->get_render_target();
msaa3d.mode = p_config->get_msaa_3d();
//screen_space_aa = p_config->get_screen_space_aa();

View file

@ -103,9 +103,10 @@ public:
virtual void configure(const RenderSceneBuffersConfiguration *p_config) override;
void configure_for_probe(Size2i p_size);
virtual void set_fsr_sharpness(float p_fsr_sharpness) override{};
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override{};
virtual void set_use_debanding(bool p_use_debanding) override{};
virtual void set_anisotropic_filtering_level(RS::ViewportAnisotropicFiltering p_anisotropic_filtering_level) override {}
virtual void set_fsr_sharpness(float p_fsr_sharpness) override {}
virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override {}
virtual void set_use_debanding(bool p_use_debanding) override {}
void set_apply_color_adjustments_in_post(bool p_apply_in_post);
void free_render_buffer_data();

View file

@ -152,6 +152,11 @@ TextureStorage::TextureStorage() {
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
}
{
default_gl_textures[DEFAULT_GL_TEXTURE_EXT] = texture_allocate();
texture_external_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_EXT], 1, 1, 0);
}
{
unsigned char pixel_data[4 * 4 * 4];
for (int i = 0; i < 16; i++) {
@ -225,6 +230,32 @@ TextureStorage::TextureStorage() {
sdf_shader.shader_version = sdf_shader.shader.version_create();
}
// Initialize texture placeholder data for the `texture_*_placeholder_initialize()` methods.
constexpr int placeholder_size = 4;
texture_2d_placeholder = Image::create_empty(placeholder_size, placeholder_size, false, Image::FORMAT_RGBA8);
// Draw a magenta/black checkerboard pattern.
for (int i = 0; i < placeholder_size * placeholder_size; i++) {
const int x = i % placeholder_size;
const int y = i / placeholder_size;
texture_2d_placeholder->set_pixel(x, y, (x + y) % 2 == 0 ? Color(1, 0, 1) : Color(0, 0, 0));
}
texture_2d_array_placeholder.push_back(texture_2d_placeholder);
for (int i = 0; i < 6; i++) {
cubemap_placeholder.push_back(texture_2d_placeholder);
}
Ref<Image> texture_2d_placeholder_rotated;
texture_2d_placeholder_rotated.instantiate();
texture_2d_placeholder_rotated->copy_from(texture_2d_placeholder);
texture_2d_placeholder_rotated->rotate_90(CLOCKWISE);
for (int i = 0; i < 4; i++) {
// Alternate checkerboard pattern on odd layers (by using a copy that is rotated 90 degrees).
texture_3d_placeholder.push_back(i % 2 == 0 ? texture_2d_placeholder : texture_2d_placeholder_rotated);
}
#ifdef GL_API_ENABLED
if (RasterizerGLES3::is_gles_over_gl()) {
glEnable(GL_PROGRAM_POINT_SIZE);
@ -246,11 +277,6 @@ TextureStorage::~TextureStorage() {
sdf_shader.shader.version_free(sdf_shader.shader_version);
}
//TODO, move back to storage
bool TextureStorage::can_create_resources_async() const {
return false;
}
/* Canvas Texture API */
RID TextureStorage::canvas_texture_allocate() {
@ -308,15 +334,8 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS:
/* Texture API */
Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
static inline Error _get_gl_uncompressed_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type) {
Config *config = Config::get_singleton();
r_gl_format = 0;
Ref<Image> image = p_image;
r_compressed = false;
r_real_format = p_format;
bool need_decompress = false;
bool decompress_ra_to_rg = false;
switch (p_format) {
case Image::FORMAT_L8: {
@ -345,55 +364,95 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_internal_format = GL_R8;
r_gl_format = GL_RED;
r_gl_type = GL_UNSIGNED_BYTE;
} break;
case Image::FORMAT_RG8: {
r_gl_internal_format = GL_RG8;
r_gl_format = GL_RG;
r_gl_type = GL_UNSIGNED_BYTE;
} break;
case Image::FORMAT_RGB8: {
r_gl_internal_format = GL_RGB8;
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_BYTE;
} break;
case Image::FORMAT_RGBA8: {
r_gl_format = GL_RGBA;
r_gl_internal_format = GL_RGBA8;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
} break;
case Image::FORMAT_RGBA4444: {
r_gl_internal_format = GL_RGBA4;
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_SHORT_4_4_4_4;
} break;
case Image::FORMAT_RGB565: {
r_gl_internal_format = GL_RGB565;
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_SHORT_5_6_5;
} break;
case Image::FORMAT_RF: {
r_gl_internal_format = GL_R32F;
r_gl_format = GL_RED;
r_gl_type = GL_FLOAT;
if (config->float_texture_linear_supported) {
r_gl_internal_format = GL_R32F;
r_gl_format = GL_RED;
r_gl_type = GL_FLOAT;
} else {
ERR_PRINT("R32 float texture not supported, converting to R16.");
if (p_image.is_valid()) {
p_image->convert(Image::FORMAT_RH);
}
r_real_format = Image::FORMAT_RH;
r_gl_internal_format = GL_R16F;
r_gl_format = GL_RED;
r_gl_type = GL_HALF_FLOAT;
}
} break;
case Image::FORMAT_RGF: {
r_gl_internal_format = GL_RG32F;
r_gl_format = GL_RG;
r_gl_type = GL_FLOAT;
if (config->float_texture_linear_supported) {
r_gl_internal_format = GL_RG32F;
r_gl_format = GL_RG;
r_gl_type = GL_FLOAT;
} else {
ERR_PRINT("RG32 float texture not supported, converting to RG16.");
if (p_image.is_valid()) {
p_image->convert(Image::FORMAT_RGH);
}
r_real_format = Image::FORMAT_RGH;
r_gl_internal_format = GL_RG16F;
r_gl_format = GL_RG;
r_gl_type = GL_HALF_FLOAT;
}
} break;
case Image::FORMAT_RGBF: {
r_gl_internal_format = GL_RGB32F;
r_gl_format = GL_RGB;
r_gl_type = GL_FLOAT;
if (config->float_texture_linear_supported) {
r_gl_internal_format = GL_RGB32F;
r_gl_format = GL_RGB;
r_gl_type = GL_FLOAT;
} else {
ERR_PRINT("RGB32 float texture not supported, converting to RGB16.");
if (p_image.is_valid()) {
p_image->convert(Image::FORMAT_RGBH);
}
r_real_format = Image::FORMAT_RGBH;
r_gl_internal_format = GL_RGB16F;
r_gl_format = GL_RGB;
r_gl_type = GL_HALF_FLOAT;
}
} break;
case Image::FORMAT_RGBAF: {
r_gl_internal_format = GL_RGBA32F;
r_gl_format = GL_RGBA;
r_gl_type = GL_FLOAT;
if (config->float_texture_linear_supported) {
r_gl_internal_format = GL_RGBA32F;
r_gl_format = GL_RGBA;
r_gl_type = GL_FLOAT;
} else {
ERR_PRINT("RGBA32 float texture not supported, converting to RGBA16.");
if (p_image.is_valid()) {
p_image->convert(Image::FORMAT_RGBAH);
}
r_real_format = Image::FORMAT_RGBAH;
r_gl_internal_format = GL_RGBA16F;
r_gl_format = GL_RGBA;
r_gl_type = GL_HALF_FLOAT;
}
} break;
case Image::FORMAT_RH: {
r_gl_internal_format = GL_R16F;
@ -404,26 +463,48 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_internal_format = GL_RG16F;
r_gl_format = GL_RG;
r_gl_type = GL_HALF_FLOAT;
} break;
case Image::FORMAT_RGBH: {
r_gl_internal_format = GL_RGB16F;
r_gl_format = GL_RGB;
r_gl_type = GL_HALF_FLOAT;
} break;
case Image::FORMAT_RGBAH: {
r_gl_internal_format = GL_RGBA16F;
r_gl_format = GL_RGBA;
r_gl_type = GL_HALF_FLOAT;
} break;
case Image::FORMAT_RGBE9995: {
r_gl_internal_format = GL_RGB9_E5;
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_INT_5_9_9_9_REV;
} break;
default: {
return ERR_UNAVAILABLE;
}
}
return OK;
}
Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const {
Config *config = Config::get_singleton();
r_gl_format = 0;
Ref<Image> image = p_image;
r_compressed = false;
r_real_format = p_format;
if (!Image::is_format_compressed(p_format)) {
Error err = _get_gl_uncompressed_format(p_image, p_format, r_real_format, r_gl_format, r_gl_internal_format, r_gl_type);
ERR_FAIL_COND_V_MSG(err != OK, Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", p_format));
return p_image;
}
// For compressed images, some formats may not be supported by the current device and will require decompression.
bool need_decompress = false;
bool decompress_ra_to_rg = false;
switch (p_format) {
case Image::FORMAT_DXT1: {
if (config->s3tc_supported) {
r_gl_internal_format = _EXT_COMPRESSED_RGBA_S3TC_DXT1_EXT;
@ -510,7 +591,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RED;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -521,7 +601,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RED;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -532,7 +611,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RG;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -543,7 +621,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RG;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -555,7 +632,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGB;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -566,7 +642,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -577,7 +652,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -616,7 +690,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -627,7 +700,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -638,7 +710,6 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
@ -649,56 +720,31 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
r_gl_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_compressed = true;
} else {
need_decompress = true;
}
} break;
default: {
ERR_FAIL_V_MSG(Ref<Image>(), "The image format " + itos(p_format) + " is not supported by the GL Compatibility rendering backend.");
ERR_FAIL_V_MSG(Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", p_format));
}
}
if (need_decompress || p_force_decompress) {
if (!image.is_null()) {
if (image.is_valid()) {
image = image->duplicate();
image->decompress();
ERR_FAIL_COND_V(image->is_compressed(), image);
if (decompress_ra_to_rg) {
image->convert_ra_rgba8_to_rg();
image->convert(Image::FORMAT_RG8);
}
switch (image->get_format()) {
case Image::FORMAT_RG8: {
r_gl_format = GL_RG;
r_gl_internal_format = GL_RG8;
r_gl_type = GL_UNSIGNED_BYTE;
r_real_format = Image::FORMAT_RG8;
r_compressed = false;
} break;
case Image::FORMAT_RGB8: {
r_gl_format = GL_RGB;
r_gl_internal_format = GL_RGB;
r_gl_type = GL_UNSIGNED_BYTE;
r_real_format = Image::FORMAT_RGB8;
r_compressed = false;
} break;
case Image::FORMAT_RGBA8: {
r_gl_format = GL_RGBA;
r_gl_internal_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_real_format = Image::FORMAT_RGBA8;
r_compressed = false;
} break;
default: {
image->convert(Image::FORMAT_RGBA8);
r_gl_format = GL_RGBA;
r_gl_internal_format = GL_RGBA;
r_gl_type = GL_UNSIGNED_BYTE;
r_real_format = Image::FORMAT_RGBA8;
r_compressed = false;
} break;
}
Error err = _get_gl_uncompressed_format(image, image->get_format(), r_real_format, r_gl_format, r_gl_internal_format, r_gl_type);
ERR_FAIL_COND_V_MSG(err != OK, Ref<Image>(), vformat("The image format %d is not supported by the Compatibility renderer.", image->get_format()));
r_real_format = image->get_format();
r_compressed = false;
}
return image;
@ -729,7 +775,7 @@ void TextureStorage::texture_free(RID p_texture) {
}
}
} else {
must_free_data = t->tex_id != 0 && !t->is_external;
must_free_data = t->tex_id != 0 && !t->is_from_native_handle;
}
if (must_free_data) {
GLES3::Utilities::get_singleton()->texture_free_data(t->tex_id);
@ -769,11 +815,53 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
texture_set_data(p_texture, p_image);
}
void TextureStorage::texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
Texture texture;
texture.active = true;
texture.alloc_width = texture.width = p_width;
texture.alloc_height = texture.height = p_height;
texture.real_format = texture.format = Image::FORMAT_RGB8;
texture.type = Texture::TYPE_2D;
if (GLES3::Config::get_singleton()->external_texture_supported) {
texture.target = _GL_TEXTURE_EXTERNAL_OES;
} else {
texture.target = GL_TEXTURE_2D;
}
glGenTextures(1, &texture.tex_id);
glBindTexture(texture.target, texture.tex_id);
#ifdef ANDROID_ENABLED
if (texture.target == _GL_TEXTURE_EXTERNAL_OES) {
if (p_external_buffer) {
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
}
texture.total_data_size = 0;
} else
#endif
{
// If external textures aren't supported, allocate an empty 1x1 texture.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
texture.total_data_size = 3;
}
glTexParameteri(texture.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(texture.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(texture.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texture.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture External");
texture_owner.initialize_rid(p_texture, texture);
glBindTexture(texture.target, 0);
}
void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) {
ERR_FAIL_COND(p_layers.is_empty());
ERR_FAIL_COND(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP && p_layers.size() != 6);
ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the GL Compatibility backend.");
ERR_FAIL_COND_MSG(p_layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY, "Cubemap Arrays are not supported in the Compatibility renderer.");
const Ref<Image> &image = p_layers[0];
{
@ -874,26 +962,28 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
texture_owner.initialize_rid(p_texture, proxy_tex);
}
RID TextureStorage::texture_create_external(GLES3::Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
Texture texture;
texture.active = true;
texture.is_external = true;
texture.type = p_type;
texture.is_from_native_handle = true;
switch (p_type) {
case Texture::TYPE_2D: {
case RS::TEXTURE_TYPE_2D: {
texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
} break;
case Texture::TYPE_3D: {
case RS::TEXTURE_TYPE_3D: {
texture.type = Texture::TYPE_3D;
texture.target = GL_TEXTURE_3D;
} break;
case Texture::TYPE_LAYERED: {
case RS::TEXTURE_TYPE_LAYERED: {
texture.type = Texture::TYPE_LAYERED;
texture.target = GL_TEXTURE_2D_ARRAY;
} break;
}
texture.real_format = texture.format = p_format;
texture.tex_id = p_image;
texture.tex_id = p_native_handle;
texture.alloc_width = texture.width = p_width;
texture.alloc_height = texture.height = p_height;
texture.depth = p_depth;
@ -928,6 +1018,22 @@ void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &
GLES3::Utilities::get_singleton()->texture_resize_data(tex->tex_id, tex->total_data_size);
}
void TextureStorage::texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_NULL(tex);
tex->alloc_width = tex->width = p_width;
tex->alloc_height = tex->height = p_height;
#ifdef ANDROID_ENABLED
if (tex->target == _GL_TEXTURE_EXTERNAL_OES && p_external_buffer) {
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, tex->tex_id);
GLES3::Config::get_singleton()->eglEGLImageTargetTexture2DOES(_GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<void *>(p_external_buffer));
glBindTexture(_GL_TEXTURE_EXTERNAL_OES, 0);
}
#endif
}
void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_NULL(tex);
@ -954,46 +1060,19 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
}
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
texture_2d_initialize(p_texture, image);
texture_2d_initialize(p_texture, texture_2d_placeholder);
}
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
if (p_layered_type == RS::TEXTURE_LAYERED_2D_ARRAY) {
images.push_back(image);
texture_2d_layered_initialize(p_texture, texture_2d_array_placeholder, p_layered_type);
} else {
//cube
for (int i = 0; i < 6; i++) {
images.push_back(image);
}
texture_2d_layered_initialize(p_texture, cubemap_placeholder, p_layered_type);
}
texture_2d_layered_initialize(p_texture, images, p_layered_type);
}
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
//cube
for (int i = 0; i < 4; i++) {
images.push_back(image);
}
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, images);
texture_3d_initialize(p_texture, Image::FORMAT_RGBA8, 4, 4, 4, false, texture_3d_placeholder);
}
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
@ -1013,7 +1092,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
// It also allows for reading compressed textures, mipmaps, and more formats.
Vector<uint8_t> data;
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
int64_t 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();
@ -1025,7 +1104,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
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);
int64_t ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
if (texture->compressed) {
glPixelStorei(GL_PACK_ALIGNMENT, 4);
@ -1039,9 +1118,13 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
data.resize(data_size);
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
image = Image::create_from_data(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 = Image::create_from_data(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1, texture->real_format, data);
if (image->is_empty()) {
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
}
if (texture->format != texture->real_format && !Image::is_format_compressed(texture->real_format)) {
image->convert(texture->format);
}
}
@ -1051,7 +1134,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
Vector<uint8_t> data;
// On web and mobile we always read an RGBA8 image with no mipmaps.
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
int64_t data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
data.resize(data_size * 2); // Add some memory at the end, just in case for buggy drivers.
uint8_t *w = data.ptrw();
@ -1095,10 +1178,13 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
data.resize(data_size);
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
image = Image::create_from_data(texture->width, texture->height, false, Image::FORMAT_RGBA8, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
image = Image::create_from_data(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data);
if (image->is_empty()) {
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
}
if (texture->format != Image::FORMAT_RGBA8) {
if (texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(texture->format)) {
image->convert(texture->format);
}
@ -1123,7 +1209,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
Vector<uint8_t> data;
int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
int64_t data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false);
data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
uint8_t *w = data.ptrw();
@ -1168,9 +1254,12 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
ERR_FAIL_COND_V(data.is_empty(), Ref<Image>());
Ref<Image> image = Image::create_from_data(texture->width, texture->height, false, Image::FORMAT_RGBA8, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (image->is_empty()) {
const String &path_str = texture->path.is_empty() ? "with no path" : vformat("with path '%s'", texture->path);
ERR_FAIL_V_MSG(Ref<Image>(), vformat("Texture %s has no data.", path_str));
}
if (texture->format != Image::FORMAT_RGBA8) {
if (texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(texture->format)) {
image->convert(texture->format);
}
@ -1192,7 +1281,7 @@ Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(GLES3::Texture *
int depth = p_texture->depth;
for (int mipmap_level = 0; mipmap_level < p_texture->mipmaps; mipmap_level++) {
int data_size = Image::get_image_data_size(width, height, Image::FORMAT_RGBA8, false);
int64_t data_size = Image::get_image_data_size(width, height, Image::FORMAT_RGBA8, false);
glViewport(0, 0, width, height);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -1211,7 +1300,7 @@ Vector<Ref<Image>> TextureStorage::_texture_3d_read_framebuffer(GLES3::Texture *
Ref<Image> img = Image::create_from_data(width, height, false, Image::FORMAT_RGBA8, data);
ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
if (p_texture->format != Image::FORMAT_RGBA8) {
if (p_texture->format != Image::FORMAT_RGBA8 && !Image::is_format_compressed(p_texture->format)) {
img->convert(p_texture->format);
}
@ -1389,8 +1478,22 @@ void TextureStorage::texture_debug_usage(List<RS::TextureInfo> *r_info) {
tinfo.format = t->format;
tinfo.width = t->alloc_width;
tinfo.height = t->alloc_height;
tinfo.depth = t->depth;
tinfo.bytes = t->total_data_size;
switch (t->type) {
case Texture::TYPE_3D:
tinfo.depth = t->depth;
break;
case Texture::TYPE_LAYERED:
tinfo.depth = t->layers;
break;
default:
tinfo.depth = 0;
break;
}
r_info->push_back(tinfo);
}
}
@ -1452,8 +1555,17 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
GLenum internal_format;
bool compressed = false;
bool needs_decompress = texture->resize_to_po2;
// Support for RGTC-compressed Texture Arrays isn't mandated by GLES3/WebGL.
if (!RasterizerGLES3::is_gles_over_gl() && texture->target == GL_TEXTURE_2D_ARRAY) {
if (p_image->get_format() == Image::FORMAT_RGTC_R || p_image->get_format() == Image::FORMAT_RGTC_RG) {
needs_decompress = true;
}
}
Image::Format real_format;
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2);
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), real_format, format, internal_format, type, compressed, needs_decompress);
ERR_FAIL_COND(img.is_null());
if (texture->resize_to_po2) {
if (p_image->is_compressed()) {
@ -1497,11 +1609,9 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
if (texture->target == GL_TEXTURE_2D_ARRAY) {
if (p_initialize) {
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0,
size * texture->layers, &read[ofs]);
} else {
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]);
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, w, h, texture->layers, 0, size * texture->layers, nullptr);
}
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, i, 0, 0, p_layer, w, h, 1, internal_format, size, &read[ofs]);
} else {
glCompressedTexImage2D(blit_target, i, internal_format, w, h, 0, size, &read[ofs]);
}
@ -1523,7 +1633,11 @@ void TextureStorage::_texture_set_data(RID p_texture, const Ref<Image> &p_image,
h = MAX(1, h >> 1);
}
texture->total_data_size = tsize;
if (texture->target == GL_TEXTURE_CUBE_MAP || texture->target == GL_TEXTURE_2D_ARRAY) {
texture->total_data_size = tsize * texture->layers;
} else {
texture->total_data_size = tsize;
}
texture->stored_cube_sides |= (1 << p_layer);
@ -1548,7 +1662,7 @@ void TextureStorage::_texture_set_3d_data(RID p_texture, const Vector<Ref<Image>
Ref<Image> img = _get_gl_image_and_format(p_data[0], p_data[0]->get_format(), real_format, format, internal_format, type, compressed, texture->resize_to_po2);
ERR_FAIL_COND(img.is_null());
ERR_FAIL_COND_MSG(compressed, "Compressed 3D textures are not supported in the GL Compatibility backend.");
ERR_FAIL_COND_MSG(compressed, "Compressed 3D textures are not supported in the Compatibility renderer.");
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
@ -1680,6 +1794,14 @@ uint32_t TextureStorage::texture_get_texid(RID p_texture) const {
return texture->tex_id;
}
Vector3i TextureStorage::texture_get_size(RID p_texture) const {
Texture *texture = texture_owner.get_or_null(p_texture);
ERR_FAIL_NULL_V(texture, Vector3i(0, 0, 0));
return Vector3i(texture->width, texture->height, texture->depth);
}
uint32_t TextureStorage::texture_get_width(RID p_texture) const {
Texture *texture = texture_owner.get_or_null(p_texture);
@ -2369,7 +2491,7 @@ Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
ERR_FAIL_NULL_V(rt, Point2i());
return rt->position;
};
}
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
@ -2398,7 +2520,7 @@ Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
return rt->size;
}
void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
ERR_FAIL_COND(rt->direct_to_screen);
@ -2475,6 +2597,20 @@ RID TextureStorage::render_target_get_override_velocity(RID p_render_target) con
return rt->overridden.velocity;
}
void TextureStorage::render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL(rt);
rt->render_region = p_render_region;
}
Rect2i TextureStorage::render_target_get_render_region(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL_V(rt, Rect2i());
return rt->render_region;
}
RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_NULL_V(rt, RID());

View file

@ -36,6 +36,7 @@
#include "platform_gl.h"
#include "config.h"
#include "core/io/image.h"
#include "core/os/os.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
@ -126,6 +127,7 @@ enum DefaultGLTexture {
DEFAULT_GL_TEXTURE_3D_BLACK,
DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE,
DEFAULT_GL_TEXTURE_2D_UINT,
DEFAULT_GL_TEXTURE_EXT,
DEFAULT_GL_TEXTURE_MAX
};
@ -146,7 +148,7 @@ struct Texture {
RID self;
bool is_proxy = false;
bool is_external = false;
bool is_from_native_handle = false;
bool is_render_target = false;
RID proxy_to;
@ -209,7 +211,7 @@ struct Texture {
void copy_from(const Texture &o) {
proxy_to = o.proxy_to;
is_proxy = o.is_proxy;
is_external = o.is_external;
is_from_native_handle = o.is_from_native_handle;
width = o.width;
height = o.height;
alloc_width = o.alloc_width;
@ -370,6 +372,8 @@ struct RenderTarget {
RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
bool reattach_textures = false;
Rect2i render_region;
struct RTOverridden {
bool is_overridden = false;
RID color;
@ -476,8 +480,8 @@ public:
/* Canvas Texture API */
CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); }
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); }
virtual RID canvas_texture_allocate() override;
virtual void canvas_texture_initialize(RID p_rid) override;
@ -497,29 +501,34 @@ public:
return texture_owner.get_or_null(texture->proxy_to);
}
return texture;
};
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
}
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); }
void texture_2d_initialize_from_texture(RID p_texture, Texture &p_tex) {
texture_owner.initialize_rid(p_texture, p_tex);
}
virtual bool can_create_resources_async() const override;
virtual RID texture_allocate() override;
virtual void texture_free(RID p_rid) override;
virtual void texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) override;
virtual void texture_2d_layered_initialize(RID p_texture, const Vector<Ref<Image>> &p_layers, RS::TextureLayeredType p_layered_type) override;
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
RID texture_create_external(Texture::Type p_type, Image::Format p_format, unsigned int p_image, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY);
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
virtual void texture_2d_update(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) override;
virtual void texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) override;
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
Ref<Image> texture_2d_placeholder;
Vector<Ref<Image>> texture_2d_array_placeholder;
Vector<Ref<Image>> cubemap_placeholder;
Vector<Ref<Image>> texture_3d_placeholder;
//these two APIs can be used together or in combination with the others.
virtual void texture_2d_placeholder_initialize(RID p_texture) override;
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override;
@ -553,6 +562,7 @@ public:
void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
virtual Image::Format texture_get_format(RID p_texture) const override;
uint32_t texture_get_texid(RID p_texture) const;
Vector3i texture_get_size(RID p_texture) const;
uint32_t texture_get_width(RID p_texture) const;
uint32_t texture_get_height(RID p_texture) const;
uint32_t texture_get_depth(RID p_texture) const;
@ -581,7 +591,7 @@ public:
virtual RID decal_allocate() override;
virtual void decal_initialize(RID p_rid) override;
virtual void decal_free(RID p_rid) override{};
virtual void decal_free(RID p_rid) override {}
virtual void decal_set_size(RID p_decal, const Vector3 &p_size) override;
virtual void decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) override;
@ -610,8 +620,8 @@ public:
static GLuint system_fbo;
RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); }
bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); }
void check_backbuffer(RenderTarget *rt, const bool uses_screen_texture, const bool uses_depth_texture);
@ -677,13 +687,20 @@ public:
virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture, RID p_velocity_depth_texture) override;
virtual RID render_target_get_override_color(RID p_render_target) const override;
virtual RID render_target_get_override_depth(RID p_render_target) const override;
virtual RID render_target_get_override_velocity(RID p_render_target) const override;
virtual RID render_target_get_override_velocity_depth(RID p_render_target) const override { return RID(); }
virtual void render_target_set_render_region(RID p_render_target, const Rect2i &p_render_region) override;
virtual Rect2i render_target_get_render_region(RID p_render_target) const override;
virtual RID render_target_get_texture(RID p_render_target) override;
virtual void render_target_set_velocity_target_size(RID p_render_target, const Size2i &p_target_size) override {}
virtual Size2i render_target_get_velocity_target_size(RID p_render_target) const override { return Size2i(); }
void bind_framebuffer(GLuint framebuffer) {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

View file

@ -40,8 +40,6 @@
#include "particles_storage.h"
#include "texture_storage.h"
#include "servers/rendering/rendering_server_globals.h"
using namespace GLES3;
Utilities *Utilities::singleton = nullptr;
@ -467,4 +465,16 @@ Size2i Utilities::get_maximum_viewport_size() const {
return Size2i(config->max_viewport_size[0], config->max_viewport_size[1]);
}
uint32_t Utilities::get_maximum_shader_varyings() const {
Config *config = Config::get_singleton();
ERR_FAIL_NULL_V(config, 31);
return config->max_shader_varyings;
}
uint64_t Utilities::get_maximum_uniform_buffer_size() const {
Config *config = Config::get_singleton();
ERR_FAIL_NULL_V(config, 65536);
return uint64_t(config->max_uniform_buffer_size);
}
#endif // GLES3_ENABLED

View file

@ -165,8 +165,8 @@ public:
/* VISIBILITY NOTIFIER */
VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); };
bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); };
VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }
bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }
virtual RID visibility_notifier_allocate() override;
virtual void visibility_notifier_initialize(RID p_notifier) override;
@ -226,6 +226,8 @@ public:
virtual String get_video_adapter_api_version() const override;
virtual Size2i get_maximum_viewport_size() const override;
virtual uint32_t get_maximum_shader_varyings() const override;
virtual uint64_t get_maximum_uniform_buffer_size() const override;
};
} // namespace GLES3