summaryrefslogtreecommitdiff
path: root/drivers/gles3/storage
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/storage')
-rw-r--r--drivers/gles3/storage/config.cpp33
-rw-r--r--drivers/gles3/storage/config.h10
-rw-r--r--drivers/gles3/storage/material_storage.cpp760
-rw-r--r--drivers/gles3/storage/material_storage.h208
-rw-r--r--drivers/gles3/storage/mesh_storage.cpp118
-rw-r--r--drivers/gles3/storage/mesh_storage.h21
-rw-r--r--drivers/gles3/storage/texture_storage.cpp114
-rw-r--r--drivers/gles3/storage/texture_storage.h17
8 files changed, 1053 insertions, 228 deletions
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 369e523cc4..49a2a79cb2 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -44,7 +44,7 @@ Config::Config() {
singleton = this;
{
- int max_extensions = 0;
+ GLint max_extensions = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &max_extensions);
for (int i = 0; i < max_extensions; i++) {
const GLubyte *s = glGetStringi(GL_EXTENSIONS, i);
@@ -120,16 +120,6 @@ Config::Config() {
support_write_depth = extensions.has("GL_EXT_frag_depth");
#endif
- support_half_float_vertices = true;
-//every platform should support this except web, iOS has issues with their support, so add option to disable
-#ifdef JAVASCRIPT_ENABLED
- support_half_float_vertices = false;
-#endif
- bool disable_half_float = false; //GLOBAL_GET("rendering/opengl/compatibility/disable_half_float");
- if (disable_half_float) {
- support_half_float_vertices = false;
- }
-
//picky requirements for these
support_shadow_cubemaps = support_write_depth && support_depth_cubemaps;
// the use skeleton software path should be used if either float texture is not supported,
@@ -149,6 +139,27 @@ Config::Config() {
force_vertex_shading = false; //GLOBAL_GET("rendering/quality/shading/force_vertex_shading");
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
+
+ use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));
+ if (use_depth_prepass) {
+ String vendors = GLOBAL_GET("rendering/driver/depth_prepass/disable_for_vendors");
+ Vector<String> vendor_match = vendors.split(",");
+ String renderer = (const char *)glGetString(GL_RENDERER);
+ for (int i = 0; i < vendor_match.size(); i++) {
+ String v = vendor_match[i].strip_edges();
+ if (v == String()) {
+ continue;
+ }
+
+ if (renderer.findn(v) != -1) {
+ use_depth_prepass = false;
+ }
+ }
+ }
+
+ max_renderable_elements = GLOBAL_GET("rendering/limits/opengl/max_renderable_elements");
+ max_renderable_lights = GLOBAL_GET("rendering/limits/opengl/max_renderable_lights");
+ max_lights_per_object = GLOBAL_GET("rendering/limits/opengl/max_lights_per_object");
}
Config::~Config() {
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index 0646881b72..975508b555 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -34,7 +34,7 @@
#ifdef GLES3_ENABLED
#include "core/string/ustring.h"
-#include "core/templates/set.h"
+#include "core/templates/rb_set.h"
// This must come first to avoid windows.h mess
#include "platform_config.h"
@@ -58,11 +58,14 @@ public:
int max_texture_image_units = 0;
int max_texture_size = 0;
int max_uniform_buffer_size = 0;
+ int max_renderable_elements = 0;
+ int max_renderable_lights = 0;
+ int max_lights_per_object = 0;
// TODO implement wireframe in OpenGL
// bool generate_wireframes;
- Set<String> extensions;
+ RBSet<String> extensions;
bool float_texture_supported = false;
bool s3tc_supported = false;
@@ -82,7 +85,6 @@ public:
bool support_32_bits_indices = false;
bool support_write_depth = false;
- bool support_half_float_vertices = false;
bool support_npot_repeat_mipmap = false;
bool support_depth_cubemaps = false;
bool support_shadow_cubemaps = false;
@@ -97,6 +99,8 @@ public:
// so the user can switch orphaning off for them.
bool should_orphan = true;
+ bool use_depth_prepass = true;
+
static Config *get_singleton() { return singleton; };
Config();
diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp
index d14d26346c..e93c503396 100644
--- a/drivers/gles3/storage/material_storage.cpp
+++ b/drivers/gles3/storage/material_storage.cpp
@@ -43,7 +43,7 @@ using namespace GLES3;
///////////////////////////////////////////////////////////////////////////
// UBI helper functions
-_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data, bool p_linear_color) {
+_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, int p_array_size, const Variant &value, uint8_t *data) {
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
uint32_t *gui = (uint32_t *)data;
@@ -399,9 +399,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
if (i < s) {
Color color = a[i];
- if (p_linear_color) {
- color = color.srgb_to_linear();
- }
gui[j] = color.r;
gui[j + 1] = color.g;
gui[j + 2] = color.b;
@@ -433,10 +430,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
if (value.get_type() == Variant::COLOR) {
Color v = value;
- if (p_linear_color) {
- v = v.srgb_to_linear();
- }
-
gui[0] = v.r;
gui[1] = v.g;
gui[2] = v.b;
@@ -459,9 +452,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
for (int i = 0, j = 0; i < p_array_size; i++, j += 4) {
if (i < s) {
Color color = a[i];
- if (p_linear_color) {
- color = color.srgb_to_linear();
- }
gui[j] = color.r;
gui[j + 1] = color.g;
gui[j + 2] = color.b;
@@ -496,10 +486,6 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
if (value.get_type() == Variant::COLOR) {
Color v = value;
- if (p_linear_color) {
- v = v.srgb_to_linear();
- }
-
gui[0] = v.r;
gui[1] = v.g;
gui[2] = v.b;
@@ -900,7 +886,43 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
///////////////////////////////////////////////////////////////////////////
// MaterialData
-void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
+static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
+ GL_TEXTURE_2D, // TYPE_VOID,
+ GL_TEXTURE_2D, // TYPE_BOOL,
+ GL_TEXTURE_2D, // TYPE_BVEC2,
+ GL_TEXTURE_2D, // TYPE_BVEC3,
+ GL_TEXTURE_2D, // TYPE_BVEC4,
+ GL_TEXTURE_2D, // TYPE_INT,
+ GL_TEXTURE_2D, // TYPE_IVEC2,
+ GL_TEXTURE_2D, // TYPE_IVEC3,
+ GL_TEXTURE_2D, // TYPE_IVEC4,
+ GL_TEXTURE_2D, // TYPE_UINT,
+ GL_TEXTURE_2D, // TYPE_UVEC2,
+ GL_TEXTURE_2D, // TYPE_UVEC3,
+ GL_TEXTURE_2D, // TYPE_UVEC4,
+ GL_TEXTURE_2D, // TYPE_FLOAT,
+ GL_TEXTURE_2D, // TYPE_VEC2,
+ GL_TEXTURE_2D, // TYPE_VEC3,
+ GL_TEXTURE_2D, // TYPE_VEC4,
+ GL_TEXTURE_2D, // TYPE_MAT2,
+ GL_TEXTURE_2D, // TYPE_MAT3,
+ GL_TEXTURE_2D, // TYPE_MAT4,
+ GL_TEXTURE_2D, // TYPE_SAMPLER2D,
+ GL_TEXTURE_2D, // TYPE_ISAMPLER2D,
+ GL_TEXTURE_2D, // TYPE_USAMPLER2D,
+ GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY,
+ GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY,
+ GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY,
+ GL_TEXTURE_3D, // TYPE_SAMPLER3D,
+ GL_TEXTURE_3D, // TYPE_ISAMPLER3D,
+ GL_TEXTURE_3D, // TYPE_USAMPLER3D,
+ GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
+ GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
+ GL_TEXTURE_2D, // TYPE_STRUCT
+};
+
+void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
bool uses_global_buffer = false;
@@ -947,11 +969,11 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
ERR_CONTINUE(offset + size > p_buffer_size);
#endif
uint8_t *data = &p_buffer[offset];
- const Map<StringName, Variant>::Element *V = p_parameters.find(E.key);
+ HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key);
if (V) {
//user provided
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data);
} else if (E.value.default_value.size()) {
//default value
@@ -961,7 +983,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S
//zero because it was not provided
if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) {
//colors must be set as black, with alpha as 1.0
- _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color);
+ _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data);
} else {
//else just zero it out
_fill_std140_ubo_empty(E.value.type, E.value.array_size, data);
@@ -1002,10 +1024,11 @@ MaterialData::~MaterialData() {
if (uniform_buffer) {
glDeleteBuffers(1, &uniform_buffer);
+ uniform_buffer = 0;
}
}
-void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -1033,12 +1056,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters,
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
} else {
- Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name);
+ HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name);
if (!E) {
E = used_global_textures.insert(uniform_name, global_textures_pass);
v->texture_materials.insert(self);
} else {
- E->get() = global_textures_pass;
+ E->value = global_textures_pass;
}
textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value);
@@ -1048,10 +1071,10 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters,
WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
}
} else {
- const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name);
+ HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name);
if (V) {
- if (V->get().is_array()) {
- Array array = (Array)V->get();
+ if (V->value.is_array()) {
+ Array array = (Array)V->value;
if (uniform_array_size > 0) {
for (int j = 0; j < array.size(); j++) {
textures.push_back(array[j]);
@@ -1062,25 +1085,25 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters,
}
}
} else {
- textures.push_back(V->get());
+ textures.push_back(V->value);
}
}
if (uniform_array_size > 0) {
if (textures.size() < uniform_array_size) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
+ HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
for (int j = textures.size(); j < uniform_array_size; j++) {
- if (W && W->get().has(j)) {
- textures.push_back(W->get()[j]);
+ if (W && W->value.has(j)) {
+ textures.push_back(W->value[j]);
} else {
textures.push_back(RID());
}
}
}
} else if (textures.is_empty()) {
- const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name);
- if (W && W->get().has(0)) {
- textures.push_back(W->get()[0]);
+ HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name);
+ if (W && W->value.has(0)) {
+ textures.push_back(W->value[0]);
}
}
}
@@ -1199,12 +1222,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters,
}
{
//for textures no longer used, unregister them
- List<Map<StringName, uint64_t>::Element *> to_delete;
- for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) {
- if (E->get() != global_textures_pass) {
- to_delete.push_back(E);
+ List<StringName> to_delete;
+ for (KeyValue<StringName, uint64_t> &E : used_global_textures) {
+ if (E.value != global_textures_pass) {
+ to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key());
+ GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1227,7 +1250,7 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters,
}
}
-void MaterialData::update_parameters_internal(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size) {
+void MaterialData::update_parameters_internal(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (!uniform_buffer) {
@@ -1275,16 +1298,16 @@ MaterialStorage *MaterialStorage::get_singleton() {
MaterialStorage::MaterialStorage() {
singleton = this;
- shader_data_request_func[RS::SHADER_SPATIAL] = nullptr;
+ shader_data_request_func[RS::SHADER_SPATIAL] = _create_scene_shader_func;
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
shader_data_request_func[RS::SHADER_PARTICLES] = nullptr;
- shader_data_request_func[RS::SHADER_SKY] = nullptr;
+ shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
shader_data_request_func[RS::SHADER_FOG] = nullptr;
- material_data_request_func[RS::SHADER_SPATIAL] = nullptr;
+ material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
material_data_request_func[RS::SHADER_PARTICLES] = nullptr;
- material_data_request_func[RS::SHADER_SKY] = nullptr;
+ material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
material_data_request_func[RS::SHADER_FOG] = nullptr;
static_assert(sizeof(GlobalVariables::Value) == 16);
@@ -1365,16 +1388,12 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
actions.render_mode_defines["light_only"] = "#define MODE_LIGHT_ONLY\n";
- actions.base_texture_binding_index = 1;
- actions.base_uniform_string = "";
- actions.global_buffer_array_variable = "";
-
shaders.compiler_canvas.initialize(actions);
}
{
// Setup Scene compiler
- /*
+
//shader compiler
ShaderCompiler::DefaultIdentifierActions actions;
@@ -1529,11 +1548,6 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["sss_mode_skin"] = "#define SSS_MODE_SKIN\n";
actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n";
-
- actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps
- actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]";
- actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter
-
actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n";
actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n";
actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n";
@@ -1541,19 +1555,10 @@ MaterialStorage::MaterialStorage() {
actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
- actions.instance_uniform_index_variable = "instances.data[instance_index].instance_uniforms_ofs";
- compiler.initialize(actions);
- */
+ shaders.compiler_scene.initialize(actions);
}
{
@@ -1626,10 +1631,10 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["COLOR"] = "color";
actions.renames["ALPHA"] = "alpha";
actions.renames["EYEDIR"] = "cube_normal";
- actions.renames["POSITION"] = "params.position_multiplier.xyz";
+ actions.renames["POSITION"] = "position";
actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv";
- actions.renames["TIME"] = "params.time";
+ actions.renames["TIME"] = "time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -1660,20 +1665,12 @@ ShaderCompiler::DefaultIdentifierActions actions;
actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS";
actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS";
actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS";
- actions.custom_samplers["RADIANCE"] = "material_samplers[3]";
actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = 1;
- actions.base_uniform_string = "material.";
- actions.base_varying_index = 10;
-
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables";
shaders.compiler_sky.initialize(actions);
}
@@ -1681,9 +1678,6 @@ ShaderCompiler::DefaultIdentifierActions actions;
//shaders.copy.initialize();
//shaders.copy_version = shaders.copy.version_create(); //TODO
//shaders.copy.version_bind_shader(shaders.copy_version, CopyShaderGLES3::MODE_COPY_SECTION);
- //shaders.cubemap_filter.init();
- //bool ggx_hq = GLOBAL_GET("rendering/quality/reflections/high_quality_ggx");
- //shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::LOW_QUALITY, !ggx_hq);
}
MaterialStorage::~MaterialStorage() {
@@ -1873,7 +1867,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.a;
GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
- v = v.srgb_to_linear();
+ //v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
bv_linear.z = v.b;
@@ -2077,10 +2071,9 @@ Vector<StringName> MaterialStorage::global_variable_get_list() const {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
- const StringName *K = nullptr;
Vector<StringName> names;
- while ((K = global_variables.variables.next(K))) {
- names.push_back(*K);
+ for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
@@ -2098,7 +2091,7 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
Material *material = material_storage->get_material(E->get());
ERR_CONTINUE(!material);
material_storage->_material_queue_update(material, false, true);
@@ -2130,7 +2123,7 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
+ for (RBSet<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) {
Material *material = material_storage->get_material(E->get());
ERR_CONTINUE(!material);
material_storage->_material_queue_update(material, false, true);
@@ -2312,7 +2305,7 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos]);
_global_variable_mark_buffer_dirty(pos, 1);
}
@@ -2428,7 +2421,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
shader->data = nullptr;
}
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
material->shader_mode = new_mode;
if (material->data) {
@@ -2445,7 +2438,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
shader->mode = RS::SHADER_MAX; //invalid
}
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
if (shader->data) {
material->data = material_data_request_func[new_mode](shader->data);
@@ -2457,7 +2450,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
}
if (shader->data) {
- for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) {
+ for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) {
for (const KeyValue<int, RID> &E2 : E.value) {
shader->data->set_default_texture_param(E.key, E2.value, E2.key);
}
@@ -2469,7 +2462,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
shader->data->set_code(p_code);
}
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
@@ -2496,7 +2489,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin
if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) {
if (!shader->default_texture_parameter.has(p_name)) {
- shader->default_texture_parameter[p_name] = Map<int, RID>();
+ shader->default_texture_parameter[p_name] = HashMap<int, RID>();
}
shader->default_texture_parameter[p_name][p_index] = p_texture;
} else {
@@ -2511,7 +2504,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin
if (shader->data) {
shader->data->set_default_texture_param(p_name, p_texture, p_index);
}
- for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
+ for (RBSet<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {
Material *material = E->get();
_material_queue_update(material, false, true);
}
@@ -2547,7 +2540,7 @@ RS::ShaderNativeSourceCode MaterialStorage::shader_get_native_source_code(RID p_
/* MATERIAL API */
-void MaterialStorage::_material_queue_update(Material *material, bool p_uniform, bool p_texture) {
+void MaterialStorage::_material_queue_update(GLES3::Material *material, bool p_uniform, bool p_texture) {
material->uniform_dirty = material->uniform_dirty || p_uniform;
material->texture_dirty = material->texture_dirty || p_texture;
@@ -2739,7 +2732,8 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage
}
}
-// Canvas Shader Data
+/* Canvas Shader Data */
+
void CanvasShaderData::set_code(const String &p_code) {
// compile the shader
@@ -2824,14 +2818,14 @@ void CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p
}
} else {
if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = Map<int, RID>();
+ default_texture_params[p_name] = HashMap<int, RID>();
}
default_texture_params[p_name][p_index] = p_texture;
}
}
void CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- Map<int, StringName> order;
+ HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
@@ -2912,55 +2906,19 @@ GLES3::ShaderData *GLES3::_create_canvas_shader_func() {
return shader_data;
}
-void CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+void CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
}
-// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
-static const GLenum target_from_type[ShaderLanguage::TYPE_MAX] = {
- GL_TEXTURE_2D, // TYPE_VOID,
- GL_TEXTURE_2D, // TYPE_BOOL,
- GL_TEXTURE_2D, // TYPE_BVEC2,
- GL_TEXTURE_2D, // TYPE_BVEC3,
- GL_TEXTURE_2D, // TYPE_BVEC4,
- GL_TEXTURE_2D, // TYPE_INT,
- GL_TEXTURE_2D, // TYPE_IVEC2,
- GL_TEXTURE_2D, // TYPE_IVEC3,
- GL_TEXTURE_2D, // TYPE_IVEC4,
- GL_TEXTURE_2D, // TYPE_UINT,
- GL_TEXTURE_2D, // TYPE_UVEC2,
- GL_TEXTURE_2D, // TYPE_UVEC3,
- GL_TEXTURE_2D, // TYPE_UVEC4,
- GL_TEXTURE_2D, // TYPE_FLOAT,
- GL_TEXTURE_2D, // TYPE_VEC2,
- GL_TEXTURE_2D, // TYPE_VEC3,
- GL_TEXTURE_2D, // TYPE_VEC4,
- GL_TEXTURE_2D, // TYPE_MAT2,
- GL_TEXTURE_2D, // TYPE_MAT3,
- GL_TEXTURE_2D, // TYPE_MAT4,
- GL_TEXTURE_2D, // TYPE_SAMPLER2D,
- GL_TEXTURE_2D, // TYPE_ISAMPLER2D,
- GL_TEXTURE_2D, // TYPE_USAMPLER2D,
- GL_TEXTURE_2D_ARRAY, // TYPE_SAMPLER2DARRAY,
- GL_TEXTURE_2D_ARRAY, // TYPE_ISAMPLER2DARRAY,
- GL_TEXTURE_2D_ARRAY, // TYPE_USAMPLER2DARRAY,
- GL_TEXTURE_3D, // TYPE_SAMPLER3D,
- GL_TEXTURE_3D, // TYPE_ISAMPLER3D,
- GL_TEXTURE_3D, // TYPE_USAMPLER3D,
- GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBE,
- GL_TEXTURE_CUBE_MAP, // TYPE_SAMPLERCUBEARRAY,
- GL_TEXTURE_2D, // TYPE_STRUCT
-};
-
void CanvasMaterialData::bind_uniforms() {
// Bind Material Uniforms
- glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_BUFFER_OBJECT, uniform_buffer);
+ glBindBufferBase(GL_UNIFORM_BUFFER, RasterizerCanvasGLES3::MATERIAL_UNIFORM_LOCATION, uniform_buffer);
RID *textures = texture_cache.ptrw();
ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
for (int ti = 0; ti < texture_cache.size(); ti++) {
Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
- glActiveTexture(GL_TEXTURE1 + ti);
+ glActiveTexture(GL_TEXTURE1 + ti); // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
// Set sampler state here as the same texture can be used in multiple places with different flags
@@ -2982,4 +2940,544 @@ GLES3::MaterialData *GLES3::_create_canvas_material_func(ShaderData *p_shader) {
return material_data;
}
+////////////////////////////////////////////////////////////////////////////////
+// SKY SHADER
+
+void SkyShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["sky"] = ShaderCompiler::STAGE_FRAGMENT;
+
+ uses_time = false;
+ uses_half_res = false;
+ uses_quarter_res = false;
+ uses_position = false;
+ uses_light = false;
+
+ actions.render_mode_flags["use_half_res_pass"] = &uses_half_res;
+ actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+ actions.usage_flag_pointers["POSITION"] = &uses_position;
+ actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT0_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT1_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT2_SIZE"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light;
+ actions.usage_flag_pointers["LIGHT3_SIZE"] = &uses_light;
+
+ actions.uniforms = &uniforms;
+
+ Error err = MaterialStorage::get_singleton()->shaders.compiler_sky.compile(RS::SHADER_SKY, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = MaterialStorage::get_singleton()->shaders.sky_shader.version_create();
+ }
+
+#if 0
+ print_line("**compiling shader:");
+ print_line("**defines:\n");
+ for (int i = 0; i < gen_code.defines.size(); i++) {
+ print_line(gen_code.defines[i]);
+ }
+ print_line("\n**uniforms:\n" + gen_code.uniforms);
+ // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
+ // print_line("\n**vertex_code:\n" + gen_code.vertex);
+ print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
+ print_line("\n**fragment_code:\n" + gen_code.fragment);
+ print_line("\n**light_code:\n" + gen_code.light);
+#endif
+
+ Vector<StringName> texture_uniform_names;
+ for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+ texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+ }
+
+ MaterialStorage::get_singleton()->shaders.sky_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.sky_shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ valid = true;
+}
+
+void SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ RBMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool SkyShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool SkyShaderData::is_animated() const {
+ return false;
+}
+
+bool SkyShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode SkyShaderData::get_native_source_code() const {
+ return MaterialStorage::get_singleton()->shaders.sky_shader.version_get_native_source_code(version);
+}
+
+SkyShaderData::SkyShaderData() {
+ valid = false;
+}
+
+SkyShaderData::~SkyShaderData() {
+ if (version.is_valid()) {
+ MaterialStorage::get_singleton()->shaders.sky_shader.version_free(version);
+ }
+}
+
+GLES3::ShaderData *GLES3::_create_sky_shader_func() {
+ SkyShaderData *shader_data = memnew(SkyShaderData);
+ return shader_data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sky material
+
+void SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ uniform_set_updated = true;
+ return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+}
+
+SkyMaterialData::~SkyMaterialData() {
+}
+GLES3::MaterialData *GLES3::_create_sky_material_func(ShaderData *p_shader) {
+ SkyMaterialData *material_data = memnew(SkyMaterialData);
+ material_data->shader_data = static_cast<SkyShaderData *>(p_shader);
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+void SkyMaterialData::bind_uniforms() {
+ // Bind Material Uniforms
+ glBindBufferBase(GL_UNIFORM_BUFFER, SKY_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
+
+ RID *textures = texture_cache.ptrw();
+ ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
+ for (int ti = 0; ti < texture_cache.size(); ti++) {
+ Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
+ glActiveTexture(GL_TEXTURE0 + ti);
+ glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+
+ // Set sampler state here as the same texture can be used in multiple places with different flags
+ // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
+ RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
+ RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Scene SHADER
+
+void SceneShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+ uses_screen_texture = false;
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+
+ int blend_modei = BLEND_MODE_MIX;
+ int depth_testi = DEPTH_TEST_ENABLED;
+ int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF;
+ int cull_modei = CULL_BACK;
+ int depth_drawi = DEPTH_DRAW_OPAQUE;
+
+ uses_point_size = false;
+ uses_alpha = false;
+ uses_alpha_clip = false;
+ uses_blend_alpha = false;
+ uses_depth_pre_pass = false;
+ uses_discard = false;
+ uses_roughness = false;
+ uses_normal = false;
+ wireframe = false;
+
+ unshaded = false;
+ uses_vertex = false;
+ uses_position = false;
+ uses_sss = false;
+ uses_transmittance = false;
+ uses_screen_texture = false;
+ uses_depth_texture = false;
+ uses_normal_texture = false;
+ uses_time = false;
+ writes_modelview_or_projection = false;
+ uses_world_coordinates = false;
+ uses_particle_trails = false;
+
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
+ actions.entry_point_stages["fragment"] = ShaderCompiler::STAGE_FRAGMENT;
+ actions.entry_point_stages["light"] = ShaderCompiler::STAGE_FRAGMENT;
+
+ actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD);
+ actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
+ actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
+ actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
+
+ actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE);
+ actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_modei, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE);
+
+ actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED);
+ actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE);
+ actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS);
+
+ actions.render_mode_values["depth_test_disabled"] = Pair<int *, int>(&depth_testi, DEPTH_TEST_DISABLED);
+
+ actions.render_mode_values["cull_disabled"] = Pair<int *, int>(&cull_modei, CULL_DISABLED);
+ actions.render_mode_values["cull_front"] = Pair<int *, int>(&cull_modei, CULL_FRONT);
+ actions.render_mode_values["cull_back"] = Pair<int *, int>(&cull_modei, CULL_BACK);
+
+ actions.render_mode_flags["unshaded"] = &unshaded;
+ actions.render_mode_flags["wireframe"] = &wireframe;
+ actions.render_mode_flags["particle_trails"] = &uses_particle_trails;
+
+ actions.usage_flag_pointers["ALPHA"] = &uses_alpha;
+ actions.usage_flag_pointers["ALPHA_SCISSOR_THRESHOLD"] = &uses_alpha_clip;
+ actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass;
+
+ actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss;
+ actions.usage_flag_pointers["SSS_TRANSMITTANCE_DEPTH"] = &uses_transmittance;
+
+ actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture;
+ actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture;
+ actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture;
+ actions.usage_flag_pointers["DISCARD"] = &uses_discard;
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+ actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness;
+ actions.usage_flag_pointers["NORMAL"] = &uses_normal;
+ actions.usage_flag_pointers["NORMAL_MAP"] = &uses_normal;
+
+ actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size;
+ actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size;
+
+ actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection;
+ actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection;
+ actions.write_flag_pointers["VERTEX"] = &uses_vertex;
+ actions.write_flag_pointers["POSITION"] = &uses_position;
+
+ actions.usage_flag_pointers["TANGENT"] = &uses_tangent;
+ actions.usage_flag_pointers["BINORMAL"] = &uses_tangent;
+ actions.usage_flag_pointers["COLOR"] = &uses_color;
+ actions.usage_flag_pointers["UV"] = &uses_uv;
+ actions.usage_flag_pointers["UV2"] = &uses_uv2;
+ actions.usage_flag_pointers["CUSTOM0"] = &uses_custom0;
+ actions.usage_flag_pointers["CUSTOM1"] = &uses_custom1;
+ actions.usage_flag_pointers["CUSTOM2"] = &uses_custom2;
+ actions.usage_flag_pointers["CUSTOM3"] = &uses_custom3;
+ actions.usage_flag_pointers["BONE_INDICES"] = &uses_bones;
+ actions.usage_flag_pointers["BONE_WEIGHTS"] = &uses_weights;
+
+ actions.uniforms = &uniforms;
+
+ Error err = MaterialStorage::get_singleton()->shaders.compiler_scene.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+
+ if (version.is_null()) {
+ version = MaterialStorage::get_singleton()->shaders.scene_shader.version_create();
+ }
+
+ depth_draw = DepthDraw(depth_drawi);
+ depth_test = DepthTest(depth_testi);
+ cull_mode = Cull(cull_modei);
+ blend_mode = BlendMode(blend_modei);
+ alpha_antialiasing_mode = AlphaAntiAliasing(alpha_antialiasing_modei);
+ vertex_input_mask = uint32_t(uses_normal);
+ vertex_input_mask |= uses_tangent << 1;
+ vertex_input_mask |= uses_color << 2;
+ vertex_input_mask |= uses_uv << 3;
+ vertex_input_mask |= uses_uv2 << 4;
+ vertex_input_mask |= uses_custom0 << 5;
+ vertex_input_mask |= uses_custom1 << 6;
+ vertex_input_mask |= uses_custom2 << 7;
+ vertex_input_mask |= uses_custom3 << 8;
+ vertex_input_mask |= uses_bones << 9;
+ vertex_input_mask |= uses_weights << 10;
+
+#if 0
+ print_line("**compiling shader:");
+ print_line("**defines:\n");
+ for (int i = 0; i < gen_code.defines.size(); i++) {
+ print_line(gen_code.defines[i]);
+ }
+
+ Map<String, String>::Element *el = gen_code.code.front();
+ while (el) {
+ print_line("\n**code " + el->key() + ":\n" + el->value());
+
+ el = el->next();
+ }
+
+ print_line("\n**uniforms:\n" + gen_code.uniforms);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
+#endif
+
+ Vector<StringName> texture_uniform_names;
+ for (int i = 0; i < gen_code.texture_uniforms.size(); i++) {
+ texture_uniform_names.push_back(gen_code.texture_uniforms[i].name);
+ }
+
+ MaterialStorage::get_singleton()->shaders.scene_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_names);
+ ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.scene_shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage
+ if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) {
+ blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE;
+ }
+
+ valid = true;
+}
+
+void SceneShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void SceneShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+ RBMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ for (const KeyValue<int, StringName> &E : order) {
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void SceneShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool SceneShaderData::is_param_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool SceneShaderData::is_animated() const {
+ return false;
+}
+
+bool SceneShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant SceneShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode SceneShaderData::get_native_source_code() const {
+ return MaterialStorage::get_singleton()->shaders.scene_shader.version_get_native_source_code(version);
+}
+
+SceneShaderData::SceneShaderData() {
+ valid = false;
+ uses_screen_texture = false;
+}
+
+SceneShaderData::~SceneShaderData() {
+ if (version.is_valid()) {
+ MaterialStorage::get_singleton()->shaders.scene_shader.version_free(version);
+ }
+}
+
+GLES3::ShaderData *GLES3::_create_scene_shader_func() {
+ SceneShaderData *shader_data = memnew(SceneShaderData);
+ return shader_data;
+}
+
+void SceneMaterialData::set_render_priority(int p_priority) {
+ priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits
+}
+
+void SceneMaterialData::set_next_pass(RID p_pass) {
+ next_pass = p_pass;
+}
+
+void SceneMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ return update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size);
+}
+
+SceneMaterialData::~SceneMaterialData() {
+}
+
+GLES3::MaterialData *GLES3::_create_scene_material_func(ShaderData *p_shader) {
+ SceneMaterialData *material_data = memnew(SceneMaterialData);
+ material_data->shader_data = static_cast<SceneShaderData *>(p_shader);
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+void SceneMaterialData::bind_uniforms() {
+ // Bind Material Uniforms
+ glBindBufferBase(GL_UNIFORM_BUFFER, SCENE_MATERIAL_UNIFORM_LOCATION, uniform_buffer);
+
+ RID *textures = texture_cache.ptrw();
+ ShaderCompiler::GeneratedCode::Texture *texture_uniforms = shader_data->texture_uniforms.ptrw();
+ for (int ti = 0; ti < texture_cache.size(); ti++) {
+ Texture *texture = TextureStorage::get_singleton()->get_texture(textures[ti]);
+ glActiveTexture(GL_TEXTURE0 + ti);
+ glBindTexture(target_from_type[texture_uniforms[ti].type], texture->tex_id);
+
+ // Set sampler state here as the same texture can be used in multiple places with different flags
+ // Need to convert sampler state from ShaderLanguage::Texture* to RS::CanvasItemTexture*
+ RS::CanvasItemTextureFilter filter = RS::CanvasItemTextureFilter((int(texture_uniforms[ti].filter) + 1) % RS::CANVAS_ITEM_TEXTURE_FILTER_MAX);
+ RS::CanvasItemTextureRepeat repeat = RS::CanvasItemTextureRepeat((int(texture_uniforms[ti].repeat) + 1) % RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR);
+ texture->gl_set_filter(filter);
+ texture->gl_set_repeat(repeat);
+ }
+}
+
#endif // !GLES3_ENABLED
diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h
index cc6cbdc152..6a11a10d76 100644
--- a/drivers/gles3/storage/material_storage.h
+++ b/drivers/gles3/storage/material_storage.h
@@ -45,15 +45,19 @@
#include "drivers/gles3/shaders/copy.glsl.gen.h"
#include "../shaders/canvas.glsl.gen.h"
+#include "../shaders/cubemap_filter.glsl.gen.h"
+#include "../shaders/scene.glsl.gen.h"
#include "../shaders/sky.glsl.gen.h"
namespace GLES3 {
-/* SHADER Structs */
+/* Shader Structs */
struct Shaders {
CanvasShaderGLES3 canvas_shader;
SkyShaderGLES3 sky_shader;
+ SceneShaderGLES3 scene_shader;
+ CubemapFilterShaderGLES3 cubemap_filter_shader;
ShaderCompiler compiler_canvas;
ShaderCompiler compiler_scene;
@@ -84,24 +88,24 @@ struct Shader {
ShaderData *data = nullptr;
String code;
RS::ShaderMode mode;
- Map<StringName, Map<int, RID>> default_texture_parameter;
- Set<Material *> owners;
+ HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
+ RBSet<Material *> owners;
};
/* Material structs */
struct MaterialData {
- void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
+ void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
virtual void set_render_priority(int p_priority) = 0;
virtual void set_next_pass(RID p_pass) = 0;
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
virtual void bind_uniforms() = 0;
virtual ~MaterialData();
// Used internally by all Materials
- void update_parameters_internal(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size);
+ void update_parameters_internal(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size);
protected:
Vector<uint8_t> ubo_data;
@@ -114,7 +118,7 @@ private:
List<RID>::Element *global_buffer_E = nullptr;
List<RID>::Element *global_texture_E = nullptr;
uint64_t global_textures_pass = 0;
- Map<StringName, uint64_t> used_global_textures;
+ HashMap<StringName, uint64_t> used_global_textures;
//internally by update_parameters_internal
};
@@ -130,7 +134,7 @@ struct Material {
uint32_t shader_id = 0;
bool uniform_dirty = false;
bool texture_dirty = false;
- Map<StringName, Variant> params;
+ HashMap<StringName, Variant> params;
int32_t priority = 0;
RID next_pass;
SelfList<Material> update_element;
@@ -141,7 +145,7 @@ struct Material {
update_element(this) {}
};
-// CanvasItem Materials
+/* CanvasItem Materials */
struct CanvasShaderData : public ShaderData {
enum BlendMode { //used internally
@@ -158,14 +162,14 @@ struct CanvasShaderData : public ShaderData {
//PipelineVariants pipeline_variants;
String path;
- Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
Vector<uint32_t> ubo_offsets;
uint32_t ubo_size;
String code;
- Map<StringName, Map<int, RID>> default_texture_params;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
bool uses_sdf = false;
@@ -193,20 +197,194 @@ struct CanvasMaterialData : public MaterialData {
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
- virtual void update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
virtual void bind_uniforms();
virtual ~CanvasMaterialData();
};
MaterialData *_create_canvas_material_func(ShaderData *p_shader);
+/* Sky Materials */
+
+struct SkyShaderData : public ShaderData {
+ bool valid;
+ RID version;
+
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ bool uses_time;
+ bool uses_position;
+ bool uses_half_res;
+ bool uses_quarter_res;
+ bool uses_light;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+ SkyShaderData();
+ virtual ~SkyShaderData();
+};
+
+ShaderData *_create_sky_shader_func();
+
+struct SkyMaterialData : public MaterialData {
+ SkyShaderData *shader_data = nullptr;
+ bool uniform_set_updated = false;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual void bind_uniforms();
+ virtual ~SkyMaterialData();
+};
+
+MaterialData *_create_sky_material_func(ShaderData *p_shader);
+
+/* Scene Materials */
+
+struct SceneShaderData : public ShaderData {
+ enum BlendMode { //used internally
+ BLEND_MODE_MIX,
+ BLEND_MODE_ADD,
+ BLEND_MODE_SUB,
+ BLEND_MODE_MUL,
+ BLEND_MODE_ALPHA_TO_COVERAGE
+ };
+
+ enum DepthDraw {
+ DEPTH_DRAW_DISABLED,
+ DEPTH_DRAW_OPAQUE,
+ DEPTH_DRAW_ALWAYS
+ };
+
+ enum DepthTest {
+ DEPTH_TEST_DISABLED,
+ DEPTH_TEST_ENABLED
+ };
+
+ enum Cull {
+ CULL_DISABLED,
+ CULL_FRONT,
+ CULL_BACK
+ };
+
+ enum AlphaAntiAliasing {
+ ALPHA_ANTIALIASING_OFF,
+ ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE,
+ ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE
+ };
+
+ bool valid;
+ RID version;
+
+ String path;
+
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size;
+
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ BlendMode blend_mode;
+ AlphaAntiAliasing alpha_antialiasing_mode;
+ DepthDraw depth_draw;
+ DepthTest depth_test;
+ Cull cull_mode;
+
+ bool uses_point_size;
+ bool uses_alpha;
+ bool uses_blend_alpha;
+ bool uses_alpha_clip;
+ bool uses_depth_pre_pass;
+ bool uses_discard;
+ bool uses_roughness;
+ bool uses_normal;
+ bool uses_particle_trails;
+ bool wireframe;
+
+ bool unshaded;
+ bool uses_vertex;
+ bool uses_position;
+ bool uses_sss;
+ bool uses_transmittance;
+ bool uses_screen_texture;
+ bool uses_depth_texture;
+ bool uses_normal_texture;
+ bool uses_time;
+ bool writes_modelview_or_projection;
+ bool uses_world_coordinates;
+ bool uses_tangent;
+ bool uses_color;
+ bool uses_uv;
+ bool uses_uv2;
+ bool uses_custom0;
+ bool uses_custom1;
+ bool uses_custom2;
+ bool uses_custom3;
+ bool uses_bones;
+ bool uses_weights;
+
+ uint32_t vertex_input_mask = 0;
+
+ uint64_t last_pass = 0;
+ uint32_t index = 0;
+
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+
+ virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ SceneShaderData();
+ virtual ~SceneShaderData();
+};
+
+ShaderData *_create_scene_shader_func();
+
+struct SceneMaterialData : public MaterialData {
+ SceneShaderData *shader_data = nullptr;
+ uint64_t last_pass = 0;
+ uint32_t index = 0;
+ RID next_pass;
+ uint8_t priority = 0;
+ virtual void set_render_priority(int p_priority);
+ virtual void set_next_pass(RID p_pass);
+ virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual void bind_uniforms();
+ virtual ~SceneMaterialData();
+};
+
+MaterialData *_create_scene_material_func(ShaderData *p_shader);
+
/* Global variable structs */
struct GlobalVariables {
enum {
BUFFER_DIRTY_REGION_SIZE = 1024
};
struct Variable {
- Set<RID> texture_materials; // materials using this
+ RBSet<RID> texture_materials; // materials using this
RS::GlobalVariableType type;
Variant value;
@@ -283,8 +461,6 @@ private:
SelfList<Material>::List material_update_list;
- //static void _material_uniform_set_erased(void *p_material);
-
public:
static MaterialStorage *get_singleton();
diff --git a/drivers/gles3/storage/mesh_storage.cpp b/drivers/gles3/storage/mesh_storage.cpp
index 41b5107b6c..5739a63cac 100644
--- a/drivers/gles3/storage/mesh_storage.cpp
+++ b/drivers/gles3/storage/mesh_storage.cpp
@@ -68,7 +68,7 @@ void MeshStorage::mesh_free(RID p_rid) {
ERR_PRINT("deleting mesh with active instances");
}
if (mesh->shadow_owners.size()) {
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
Mesh *shadow_owner = E->get();
shadow_owner->shadow_mesh = RID();
shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
@@ -194,6 +194,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
glBufferData(GL_ARRAY_BUFFER, p_surface.attribute_data.size(), p_surface.attribute_data.ptr(), (s->format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ s->attribute_buffer_size = p_surface.attribute_data.size();
}
if (p_surface.skin_data.size()) {
glGenBuffers(1, &s->skin_buffer);
@@ -216,6 +217,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, p_surface.index_data.size(), p_surface.index_data.ptr(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //unbind
s->index_count = p_surface.index_count;
+ s->index_buffer_size = p_surface.index_data.size();
if (p_surface.lods.size()) {
s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size());
@@ -266,7 +268,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
Mesh *shadow_owner = E->get();
shadow_owner->shadow_mesh = RID();
shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
@@ -323,7 +325,97 @@ RID MeshStorage::mesh_surface_get_material(RID p_mesh, int p_surface) const {
}
RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
- return RS::SurfaceData();
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, RS::SurfaceData());
+ ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData());
+
+ Mesh::Surface &s = *mesh->surfaces[p_surface];
+
+ RS::SurfaceData sd;
+ sd.format = s.format;
+ {
+ Vector<uint8_t> ret;
+ ret.resize(s.vertex_buffer_size);
+ glBindBuffer(GL_ARRAY_BUFFER, s.vertex_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.vertex_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.vertex_buffer_size);
+ }
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
+ sd.vertex_data = ret;
+ }
+
+ if (s.attribute_buffer != 0) {
+ Vector<uint8_t> ret;
+ ret.resize(s.attribute_buffer_size);
+ glBindBuffer(GL_ARRAY_BUFFER, s.attribute_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ARRAY_BUFFER, 0, s.attribute_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.attribute_buffer_size);
+ }
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+#endif
+ sd.attribute_data = ret;
+ }
+
+ sd.vertex_count = s.vertex_count;
+ sd.index_count = s.index_count;
+ sd.primitive = s.primitive;
+
+ if (sd.index_count) {
+ Vector<uint8_t> ret;
+ ret.resize(s.index_buffer_size);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s.index_buffer);
+
+#if defined(__EMSCRIPTEN__)
+ {
+ uint8_t *w = ret.ptrw();
+ glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, w);
+ }
+#else
+ void *data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, s.index_buffer_size, GL_MAP_READ_BIT);
+ ERR_FAIL_NULL_V(data, RS::SurfaceData());
+ {
+ uint8_t *w = ret.ptrw();
+ memcpy(w, data, s.index_buffer_size);
+ }
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+#endif
+ sd.index_data = ret;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ sd.aabb = s.aabb;
+ for (uint32_t i = 0; i < s.lod_count; i++) {
+ RS::SurfaceData::LOD lod;
+ lod.edge_length = s.lods[i].edge_length;
+ //lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer);
+ sd.lods.push_back(lod);
+ }
+
+ sd.bone_aabbs = s.bone_aabbs;
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ return sd;
}
int MeshStorage::mesh_get_surface_count(RID p_mesh) const {
@@ -478,25 +570,29 @@ void MeshStorage::mesh_clear(RID p_mesh) {
if (s.vertex_buffer != 0) {
glDeleteBuffers(1, &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) {
glDeleteBuffers(1, &s.attribute_buffer);
+ s.attribute_buffer = 0;
}
if (s.skin_buffer != 0) {
glDeleteBuffers(1, &s.skin_buffer);
+ s.skin_buffer = 0;
}
if (s.index_buffer != 0) {
glDeleteBuffers(1, &s.index_buffer);
- glDeleteVertexArrays(1, &s.index_array);
+ s.index_buffer = 0;
}
memdelete(mesh->surfaces[i]);
}
@@ -514,7 +610,7 @@ void MeshStorage::mesh_clear(RID p_mesh) {
mesh->has_bone_weights = false;
mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
- for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
+ for (RBSet<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) {
Mesh *shadow_owner = E->get();
shadow_owner->shadow_mesh = RID();
shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
@@ -553,14 +649,14 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
case RS::ARRAY_NORMAL: {
attribs[i].offset = vertex_stride;
// Will need to change to accommodate octahedral compression
- attribs[i].size = 1;
+ attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
vertex_stride += sizeof(float);
attribs[i].normalized = GL_TRUE;
} break;
case RS::ARRAY_TANGENT: {
attribs[i].offset = vertex_stride;
- attribs[i].size = 1;
+ attribs[i].size = 4;
attribs[i].type = GL_UNSIGNED_INT_2_10_10_10_REV;
vertex_stride += sizeof(float);
attribs[i].normalized = GL_TRUE;
@@ -629,14 +725,17 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
continue;
}
if (i <= RS::ARRAY_TANGENT) {
+ attribs[i].stride = vertex_stride;
if (mis) {
glBindBuffer(GL_ARRAY_BUFFER, mis->vertex_buffer);
} else {
glBindBuffer(GL_ARRAY_BUFFER, s->vertex_buffer);
}
} else if (i <= RS::ARRAY_CUSTOM3) {
+ attribs[i].stride = attributes_stride;
glBindBuffer(GL_ARRAY_BUFFER, s->attribute_buffer);
} else {
+ attribs[i].stride = skin_stride;
glBindBuffer(GL_ARRAY_BUFFER, s->skin_buffer);
}
@@ -645,7 +744,7 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} else {
glVertexAttribPointer(i, attribs[i].size, attribs[i].type, attribs[i].normalized, attribs[i].stride, CAST_INT_TO_UCHAR_PTR(attribs[i].offset));
}
- glEnableVertexAttribArray(attribs[i].index);
+ glEnableVertexAttribArray(i);
}
// Do not bind index here as we want to switch between index buffers for LOD
@@ -710,17 +809,20 @@ void MeshStorage::_mesh_instance_clear(MeshInstance *mi) {
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_buffer != 0) {
glDeleteBuffers(1, &mi->surfaces[i].vertex_buffer);
+ mi->surfaces[i].vertex_buffer = 0;
}
}
mi->surfaces.clear();
if (mi->blend_weights_buffer != 0) {
glDeleteBuffers(1, &mi->blend_weights_buffer);
+ mi->blend_weights_buffer = 0;
}
mi->blend_weights.clear();
mi->weights_dirty = false;
diff --git a/drivers/gles3/storage/mesh_storage.h b/drivers/gles3/storage/mesh_storage.h
index f51ec6edbe..856463d45e 100644
--- a/drivers/gles3/storage/mesh_storage.h
+++ b/drivers/gles3/storage/mesh_storage.h
@@ -54,7 +54,6 @@ struct Mesh {
struct Attrib {
bool enabled;
bool integer;
- GLuint index;
GLint size;
GLenum type;
GLboolean normalized;
@@ -69,6 +68,7 @@ struct Mesh {
GLuint skin_buffer = 0;
uint32_t vertex_count = 0;
uint32_t vertex_buffer_size = 0;
+ uint32_t attribute_buffer_size = 0;
uint32_t skin_buffer_size = 0;
// Cache vertex arrays so they can be created
@@ -84,8 +84,8 @@ struct Mesh {
uint32_t version_count = 0;
GLuint index_buffer = 0;
- GLuint index_array = 0;
uint32_t index_count = 0;
+ uint32_t index_buffer_size = 0;
struct LOD {
float edge_length = 0.0;
@@ -123,7 +123,7 @@ struct Mesh {
List<MeshInstance *> instances;
RID shadow_mesh;
- Set<Mesh *> shadow_owners;
+ RBSet<Mesh *> shadow_owners;
RendererStorage::Dependency dependency;
};
@@ -357,6 +357,12 @@ public:
}
}
+ _FORCE_INLINE_ GLenum mesh_surface_get_index_type(void *p_surface) const {
+ Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
+
+ return s->vertex_count <= 65536 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
+ }
+
// Use this to cache Vertex Array Objects so they are only generated once
_FORCE_INLINE_ void mesh_surface_get_vertex_arrays_and_format(void *p_surface, uint32_t p_input_mask, GLuint &r_vertex_array_gl) {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
@@ -388,6 +394,9 @@ public:
/* MESH INSTANCE API */
+ MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
+ bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+
virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override;
virtual void mesh_instance_set_skeleton(RID p_mesh_instance, RID p_skeleton) override;
@@ -431,6 +440,9 @@ public:
/* MULTIMESH API */
+ MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
+ bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
+
virtual RID multimesh_allocate() override;
virtual void multimesh_initialize(RID p_rid) override;
virtual void multimesh_free(RID p_rid) override;
@@ -483,6 +495,9 @@ public:
/* SKELETON API */
+ Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
+ bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+
virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_rid) override;
virtual void skeleton_free(RID p_rid) override;
diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp
index 6f2dc391d8..f932fa8bad 100644
--- a/drivers/gles3/storage/texture_storage.cpp
+++ b/drivers/gles3/storage/texture_storage.cpp
@@ -62,8 +62,9 @@ TextureStorage::TextureStorage() {
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(1, 1, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_WHITE] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE], image);
@@ -92,8 +93,9 @@ TextureStorage::TextureStorage() {
{ // black
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(0, 0, 0, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_BLACK] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_BLACK], image);
@@ -117,8 +119,9 @@ TextureStorage::TextureStorage() {
{
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(0.5, 0.5, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_NORMAL], image);
@@ -127,8 +130,9 @@ TextureStorage::TextureStorage() {
{
Ref<Image> image;
image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ image->create(4, 4, true, Image::FORMAT_RGBA8);
image->fill(Color(1.0, 0.5, 1, 1));
+ image->generate_mipmaps();
default_gl_textures[DEFAULT_GL_TEXTURE_ANISO] = texture_allocate();
texture_2d_initialize(default_gl_textures[DEFAULT_GL_TEXTURE_ANISO], image);
@@ -189,18 +193,7 @@ TextureStorage::~TextureStorage() {
}
}
-void TextureStorage::set_main_thread_id(Thread::ID p_id) {
- _main_thread_id = p_id;
-}
-
-bool TextureStorage::_is_main_thread() {
- //#if defined DEBUG_ENABLED && defined TOOLS_ENABLED
- // must be called from main thread in OpenGL
- bool is_main_thread = _main_thread_id == Thread::get_caller_id();
- //#endif
- return is_main_thread;
-}
-
+//TODO, move back to storage
bool TextureStorage::can_create_resources_async() const {
return false;
}
@@ -561,7 +554,7 @@ Ref<Image> TextureStorage::_get_gl_image_and_format(const Ref<Image> &p_image, I
} break;
*/
default: {
- ERR_FAIL_V(Ref<Image>());
+ ERR_FAIL_V_MSG(Ref<Image>(), "Image Format: " + itos(p_format) + " is not supported by the OpenGL3 Renderer");
}
}
@@ -644,10 +637,14 @@ void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_im
Texture texture;
texture.width = p_image->get_width();
texture.height = p_image->get_height();
+ texture.alloc_width = texture.width;
+ texture.alloc_height = texture.height;
+ texture.mipmaps = p_image->get_mipmap_count();
texture.format = p_image->get_format();
texture.type = Texture::TYPE_2D;
texture.target = GL_TEXTURE_2D;
- texture.image_cache_2d = p_image; //TODO, remove this once texture_2d_get is implemented
+ _get_gl_image_and_format(Ref<Image>(), texture.format, 0, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false);
+ //texture.total_data_size = p_image->get_image_data_size(); // verify that this returns size in bytes
texture.active = true;
glGenTextures(1, &texture.tex_id);
texture_owner.initialize_rid(p_texture, texture);
@@ -740,49 +737,66 @@ void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
}
Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
- Texture *tex = texture_owner.get_or_null(p_texture);
- ERR_FAIL_COND_V(!tex, Ref<Image>());
+ Texture *texture = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!texture, Ref<Image>());
#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid() && !tex->is_render_target) {
- return tex->image_cache_2d;
+ if (texture->image_cache_2d.is_valid() && !texture->is_render_target) {
+ return texture->image_cache_2d;
}
#endif
- /*
-#ifdef TOOLS_ENABLED
- if (tex->image_cache_2d.is_valid()) {
- return tex->image_cache_2d;
+#ifdef GLES_OVER_GL
+ // OpenGL 3.3 supports glGetTexImage which is faster and simpler than glReadPixels.
+ Vector<uint8_t> data;
+
+ int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->real_format, texture->mipmaps > 1);
+
+ data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers
+ uint8_t *w = data.ptrw();
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glBindTexture(texture->target, texture->tex_id);
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+ for (int i = 0; i < texture->mipmaps; i++) {
+ int ofs = Image::get_image_mipmap_offset(texture->alloc_width, texture->alloc_height, texture->real_format, i);
+
+ if (texture->compressed) {
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+ glGetCompressedTexImage(texture->target, i, &w[ofs]);
+
+ } else {
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+ glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &w[ofs]);
+ }
}
-#endif
- Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
+
+ data.resize(data_size);
+
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
Ref<Image> image;
- image.instance();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
- ERR_FAIL_COND_V(image->empty(), Ref<Image>());
- if (tex->format != tex->validated_format) {
- image->convert(tex->format);
+ image.instantiate();
+ image->create(texture->width, texture->height, texture->mipmaps > 1, texture->real_format, data);
+ ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
+ if (texture->format != texture->real_format) {
+ image->convert(texture->format);
}
+#else
+ // Support for Web and Mobile will come later.
+ Ref<Image> image;
+#endif
#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint()) {
- tex->image_cache_2d = image;
+ if (Engine::get_singleton()->is_editor_hint() && !texture->is_render_target) {
+ texture->image_cache_2d = image;
}
#endif
-*/
- /*
- #ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && !tex->is_render_target) {
- tex->image_cache_2d = image;
- }
- #endif
- */
-
- // return image;
-
- return Ref<Image>();
+ return image;
}
void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
@@ -954,7 +968,7 @@ void TextureStorage::texture_set_data(RID p_texture, const Ref<Image> &p_image,
Image::Format real_format;
Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), 0, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
-
+ ERR_FAIL_COND(img.is_null());
if (texture->resize_to_po2) {
if (p_image->is_compressed()) {
ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage.");
@@ -1311,6 +1325,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->color_internal_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_RGBA8 : GL_RGB10_A2;
rt->color_format = GL_RGBA;
+ rt->color_type = rt->flags[RENDER_TARGET_TRANSPARENT] ? GL_BYTE : GL_UNSIGNED_INT_2_10_10_10_REV;
rt->image_format = Image::FORMAT_RGBA8;
glDisable(GL_SCISSOR_TEST);
@@ -1357,6 +1372,9 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
}
texture->format = rt->image_format;
+ texture->real_format = rt->image_format;
+ texture->type = Texture::TYPE_2D;
+ texture->target = GL_TEXTURE_2D;
texture->gl_format_cache = rt->color_format;
texture->gl_type_cache = GL_UNSIGNED_BYTE;
texture->gl_internal_format_cache = rt->color_internal_format;
diff --git a/drivers/gles3/storage/texture_storage.h b/drivers/gles3/storage/texture_storage.h
index a841ff8f46..b092a009c1 100644
--- a/drivers/gles3/storage/texture_storage.h
+++ b/drivers/gles3/storage/texture_storage.h
@@ -141,6 +141,7 @@ struct Texture {
int alloc_width = 0;
int alloc_height = 0;
Image::Format format = Image::FORMAT_R8;
+ Image::Format real_format = Image::FORMAT_R8;
enum Type {
TYPE_2D,
@@ -248,7 +249,10 @@ struct Texture {
[[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: {
pmag = GL_NEAREST;
- if (config->use_nearest_mip_filter) {
+ if (mipmaps <= 1) {
+ pmin = GL_NEAREST;
+ max_lod = 0;
+ } else if (config->use_nearest_mip_filter) {
pmin = GL_NEAREST_MIPMAP_NEAREST;
} else {
pmin = GL_NEAREST_MIPMAP_LINEAR;
@@ -260,9 +264,11 @@ struct Texture {
[[fallthrough]];
case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: {
pmag = GL_LINEAR;
- if (config->use_nearest_mip_filter) {
+ if (mipmaps <= 1) {
+ pmin = GL_LINEAR;
+ max_lod = 0;
+ } else if (config->use_nearest_mip_filter) {
pmin = GL_LINEAR_MIPMAP_NEAREST;
-
} else {
pmin = GL_LINEAR_MIPMAP_LINEAR;
}
@@ -370,9 +376,6 @@ private:
RID default_gl_textures[DEFAULT_GL_TEXTURE_MAX];
- Thread::ID _main_thread_id = 0;
- bool _is_main_thread();
-
/* Canvas Texture API */
RID_Owner<CanvasTexture, true> canvas_texture_owner;
@@ -440,8 +443,6 @@ public:
};
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
- void set_main_thread_id(Thread::ID p_id);
-
virtual bool can_create_resources_async() const override;
RID texture_create();