浏览代码

Add support for 3D textures to GLES2

clayjohn 5 年之前
父节点
当前提交
68915ce20d

+ 60 - 10
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -53,6 +53,11 @@
 #endif
 #endif
 #endif
 #endif
 
 
+#if !defined(GLES_OVER_GL)
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_3D 0x806F
+#endif
+
 static const GLenum _cube_side_enum[6] = {
 static const GLenum _cube_side_enum[6] = {
 
 
 	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
 	GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
@@ -1343,6 +1348,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 	const Pair<StringName, RID> *textures = p_material->textures.ptr();
 	const Pair<StringName, RID> *textures = p_material->textures.ptr();
 
 
 	const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr();
 	const ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptr();
+	const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr();
 
 
 	state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
 	state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
 
 
@@ -1356,22 +1362,66 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 
 
 		if (!t) {
 		if (!t) {
 
 
-			switch (texture_hints[i]) {
-				case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
-				case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
-					glBindTexture(GL_TEXTURE_2D, storage->resources.black_tex);
+			GLenum target = GL_TEXTURE_2D;
+			GLuint tex = 0;
+			switch (texture_types[i]) {
+				case ShaderLanguage::TYPE_ISAMPLER2D:
+				case ShaderLanguage::TYPE_USAMPLER2D:
+				case ShaderLanguage::TYPE_SAMPLER2D: {
+
+					switch (texture_hints[i]) {
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
+						case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
+							tex = storage->resources.black_tex;
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+							tex = storage->resources.aniso_tex;
+						} break;
+						case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
+							tex = storage->resources.normal_tex;
+						} break;
+						default: {
+							tex = storage->resources.white_tex;
+						} break;
+					}
+
+				} break;
+
+				case ShaderLanguage::TYPE_SAMPLERCUBE: {
+					// TODO
 				} break;
 				} break;
-				case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
-					glBindTexture(GL_TEXTURE_2D, storage->resources.aniso_tex);
+
+				case ShaderLanguage::TYPE_ISAMPLER3D:
+				case ShaderLanguage::TYPE_USAMPLER3D:
+				case ShaderLanguage::TYPE_SAMPLER3D: {
+
+					target = GL_TEXTURE_3D;
+					tex = storage->resources.white_tex_3d;
+
+					//switch (texture_hints[i]) {
+					// TODO
+					//}
+
 				} break;
 				} break;
-				case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
-					glBindTexture(GL_TEXTURE_2D, storage->resources.normal_tex);
+
+				case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+
+					target = GL_TEXTURE_2D_ARRAY;
+					tex = storage->resources.white_tex_array;
+
+					//switch (texture_hints[i]) {
+					// TODO
+					//}
+
 				} break;
 				} break;
+
 				default: {
 				default: {
-					glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
-				} break;
+				}
 			}
 			}
 
 
+			glBindTexture(target, tex);
 			continue;
 			continue;
 		}
 		}
 
 

+ 148 - 20
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -103,6 +103,13 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
 #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
 #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT
 #define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT
 #define glFramebufferTexture2DMultisample glFramebufferTexture2DMultisampleEXT
 
 
+PFNGLTEXIMAGE3DOESPROC glTexImage3DOES;
+PFNGLTEXSUBIMAGE3DOESPROC glTexSubImage3DOES;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glCompressedTexSubImage3DOES;
+#define glTexImage3D glTexImage3DOES
+#define glTexSubImage3D glTexSubImage3DOES
+#define glCompressedTexSubImage3D glCompressedTexSubImage3DOES
+
 #elif defined(UWP_ENABLED)
 #elif defined(UWP_ENABLED)
 #include <GLES2/gl2ext.h>
 #include <GLES2/gl2ext.h>
 #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE
 #define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleANGLE
@@ -113,6 +120,11 @@ PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT
 #define GL_MAX_SAMPLES 0x8D57
 #define GL_MAX_SAMPLES 0x8D57
 #endif //!GLES_OVER_GL
 #endif //!GLES_OVER_GL
 
 
+#if !defined(GLES_OVER_GL)
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_3D 0x806F
+#endif
+
 void RasterizerStorageGLES2::bind_quad_array() const {
 void RasterizerStorageGLES2::bind_quad_array() const {
 	glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
 	glBindBuffer(GL_ARRAY_BUFFER, resources.quadie);
 	glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
 	glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
@@ -566,11 +578,23 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
 			texture->target = GL_TEXTURE_CUBE_MAP;
 			texture->target = GL_TEXTURE_CUBE_MAP;
 			texture->images.resize(6);
 			texture->images.resize(6);
 		} break;
 		} break;
-		case VS::TEXTURE_TYPE_2D_ARRAY:
+		case VS::TEXTURE_TYPE_2D_ARRAY: {
+			if (config.texture_array_supported) {
+				texture->target = GL_TEXTURE_2D_ARRAY;
+				texture->images.resize(p_depth_3d);
+			} else {
+				WARN_PRINT_ONCE("Texture Arrays not supported on this hardware.");
+				return;
+			}
+		} break;
 		case VS::TEXTURE_TYPE_3D: {
 		case VS::TEXTURE_TYPE_3D: {
-			texture->target = GL_TEXTURE_3D;
-			ERR_PRINT("3D textures and Texture Arrays are not supported in GLES2. Please switch to the GLES3 backend.");
-			return;
+			if (config.texture_3d_supported) {
+				texture->target = GL_TEXTURE_3D;
+				texture->images.resize(p_depth_3d);
+			} else {
+				WARN_PRINT_ONCE("3D textures not supported on this hardware.");
+				return;
+			}
 		} break;
 		} break;
 		default: {
 		default: {
 			ERR_PRINT("Unknown texture type!");
 			ERR_PRINT("Unknown texture type!");
@@ -615,7 +639,42 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
 	glActiveTexture(GL_TEXTURE0);
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 	glBindTexture(texture->target, texture->tex_id);
 
 
-	if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
+#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
+	if ((p_type == VS::TEXTURE_TYPE_3D && config.texture_3d_supported) || (p_type == VS::TEXTURE_TYPE_2D_ARRAY && config.texture_array_supported)) {
+
+		int width = p_width;
+		int height = p_height;
+		int depth = p_depth_3d;
+
+		int mipmaps = 0;
+
+		while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) {
+			width = MAX(1, width);
+			height = MAX(1, height);
+			depth = MAX(1, depth);
+
+			glTexImage3D(texture->target, mipmaps, internal_format, width, height, depth, 0, format, type, NULL);
+
+			width /= 2;
+			height /= 2;
+
+			if (p_type == VS::TEXTURE_TYPE_3D) {
+				depth /= 2;
+			}
+
+			mipmaps++;
+
+			if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS))
+				break;
+		}
+#ifdef GLES_OVER_GL
+		glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
+#endif
+
+	} else
+#endif
+			if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
 		//prealloc if video
 		//prealloc if video
 		glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
 		glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
 	}
 	}
@@ -627,8 +686,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 	Texture *texture = texture_owner.getornull(p_texture);
 	Texture *texture = texture_owner.getornull(p_texture);
 
 
 	ERR_FAIL_COND(!texture);
 	ERR_FAIL_COND(!texture);
-	if (texture->target == GL_TEXTURE_3D) {
-		// Target is set to a 3D texture or array texture, exit early to avoid spamming errors
+	if ((texture->type == VS::TEXTURE_TYPE_2D_ARRAY && !config.texture_array_supported) || (texture->type == VS::TEXTURE_TYPE_3D && !config.texture_3d_supported)) {
 		return;
 		return;
 	}
 	}
 	ERR_FAIL_COND(!texture->active);
 	ERR_FAIL_COND(!texture->active);
@@ -673,7 +731,23 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 		}
 		}
 	}
 	}
 
 
-	GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
+	GLenum blit_target = GL_TEXTURE_2D;
+
+	switch (texture->type) {
+		case VS::TEXTURE_TYPE_2D: {
+			blit_target = GL_TEXTURE_2D;
+		} break;
+		case VS::TEXTURE_TYPE_CUBEMAP: {
+			ERR_FAIL_INDEX(p_layer, 6);
+			blit_target = _cube_side_enum[p_layer];
+		} break;
+		case VS::TEXTURE_TYPE_2D_ARRAY: {
+			blit_target = GL_TEXTURE_2D_ARRAY;
+		} break;
+		case VS::TEXTURE_TYPE_3D: {
+			blit_target = GL_TEXTURE_3D;
+		} break;
+	}
 
 
 	texture->data_size = img->get_data().size();
 	texture->data_size = img->get_data().size();
 	PoolVector<uint8_t>::Read read = img->get_data().read();
 	PoolVector<uint8_t>::Read read = img->get_data().read();
@@ -730,23 +804,41 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 
 
 		int size, ofs;
 		int size, ofs;
 		img->get_mipmap_offset_and_size(i, ofs, size);
 		img->get_mipmap_offset_and_size(i, ofs, size);
+		if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
 
 
-		if (compressed) {
-			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+			if (compressed) {
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
 
-			int bw = w;
-			int bh = h;
+				int bw = w;
+				int bh = h;
 
 
-			glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
-		} else {
+				glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]);
+			} else {
+
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+				if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
+					glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
+				} else {
+					glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+				}
+			}
+		}
+#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
+		else {
+			if (texture->compressed) {
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
 
-			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-			if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
-				glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]);
+				int bw = w;
+				int bh = h;
+
+				glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]);
 			} else {
 			} else {
-				glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+				glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]);
 			}
 			}
 		}
 		}
+#endif
 
 
 		tsize += size;
 		tsize += size;
 
 
@@ -1492,6 +1584,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
 
 
 	p_shader->texture_count = gen_code.texture_uniforms.size();
 	p_shader->texture_count = gen_code.texture_uniforms.size();
 	p_shader->texture_hints = gen_code.texture_hints;
 	p_shader->texture_hints = gen_code.texture_hints;
+	p_shader->texture_types = gen_code.texture_types;
 
 
 	p_shader->uses_vertex_time = gen_code.uses_vertex_time;
 	p_shader->uses_vertex_time = gen_code.uses_vertex_time;
 	p_shader->uses_fragment_time = gen_code.uses_fragment_time;
 	p_shader->uses_fragment_time = gen_code.uses_fragment_time;
@@ -1639,11 +1732,19 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
 
 
 			case ShaderLanguage::TYPE_SAMPLER2DARRAY:
 			case ShaderLanguage::TYPE_SAMPLER2DARRAY:
 			case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
 			case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
-			case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+			case ShaderLanguage::TYPE_USAMPLER2DARRAY: {
+
+				pi.type = Variant::OBJECT;
+				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+				pi.hint_string = "TextureArray";
+			} break;
+
 			case ShaderLanguage::TYPE_SAMPLER3D:
 			case ShaderLanguage::TYPE_SAMPLER3D:
 			case ShaderLanguage::TYPE_ISAMPLER3D:
 			case ShaderLanguage::TYPE_ISAMPLER3D:
 			case ShaderLanguage::TYPE_USAMPLER3D: {
 			case ShaderLanguage::TYPE_USAMPLER3D: {
-				// Not implemented in GLES2
+				pi.type = Variant::OBJECT;
+				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+				pi.hint_string = "Texture3D";
 			} break;
 			} break;
 		}
 		}
 
 
@@ -5795,6 +5896,8 @@ void RasterizerStorageGLES2::initialize() {
 	config.depth_type = GL_UNSIGNED_INT;
 	config.depth_type = GL_UNSIGNED_INT;
 
 
 #ifdef GLES_OVER_GL
 #ifdef GLES_OVER_GL
+	config.texture_3d_supported = true;
+	config.texture_array_supported = config.extensions.has("GL_EXT_texture_array");
 	config.float_texture_supported = true;
 	config.float_texture_supported = true;
 	config.s3tc_supported = true;
 	config.s3tc_supported = true;
 	config.pvrtc_supported = false;
 	config.pvrtc_supported = false;
@@ -5802,6 +5905,8 @@ void RasterizerStorageGLES2::initialize() {
 	config.support_npot_repeat_mipmap = true;
 	config.support_npot_repeat_mipmap = true;
 	config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
 	config.depth_buffer_internalformat = GL_DEPTH_COMPONENT24;
 #else
 #else
+	config.texture_3d_supported = config.extensions.has("GL_OES_texture_3D");
+	config.texture_array_supported = false;
 	config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
 	config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float");
 	config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
 	config.s3tc_supported = config.extensions.has("GL_EXT_texture_compression_s3tc") || config.extensions.has("WEBGL_compressed_texture_s3tc");
 	config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
 	config.etc1_supported = config.extensions.has("GL_OES_compressed_ETC1_RGB8_texture") || config.extensions.has("WEBGL_compressed_texture_etc1");
@@ -5840,6 +5945,9 @@ void RasterizerStorageGLES2::initialize() {
 	void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY);
 	void *gles2_lib = dlopen("libGLESv2.so", RTLD_LAZY);
 	glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT");
 	glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glRenderbufferStorageMultisampleEXT");
 	glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT");
 	glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)dlsym(gles2_lib, "glFramebufferTexture2DMultisampleEXT");
+	glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC)dlsym(gles2_lib, "glTexImage3DOES");
+	glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glTexSubImage3DOES");
+	glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)dlsym(gles2_lib, "glCompressedTexSubImage3DOES");
 #endif
 #endif
 #endif
 #endif
 
 
@@ -6062,6 +6170,26 @@ void RasterizerStorageGLES2::initialize() {
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
 		glGenerateMipmap(GL_TEXTURE_2D);
 		glBindTexture(GL_TEXTURE_2D, 0);
 		glBindTexture(GL_TEXTURE_2D, 0);
+
+#if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED)
+		glGenTextures(1, &resources.white_tex_3d);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_3D, resources.white_tex_3d);
+		glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB, 2, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
+
+#ifdef GLES_OVER_GL
+		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
+#endif
+
+		glGenTextures(1, &resources.white_tex_array);
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D_ARRAY, resources.white_tex_array);
+		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, 8, 8, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 8, 8, 1, GL_RGB, GL_UNSIGNED_BYTE, whitetexdata);
+		glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
+		glBindTexture(GL_TEXTURE_2D, 0);
+#endif
 	}
 	}
 
 
 	// skeleton buffer
 	// skeleton buffer

+ 5 - 0
drivers/gles2/rasterizer_storage_gles2.h

@@ -71,6 +71,8 @@ public:
 
 
 		Set<String> extensions;
 		Set<String> extensions;
 
 
+		bool texture_3d_supported;
+		bool texture_array_supported;
 		bool float_texture_supported;
 		bool float_texture_supported;
 		bool s3tc_supported;
 		bool s3tc_supported;
 		bool etc1_supported;
 		bool etc1_supported;
@@ -109,6 +111,8 @@ public:
 		GLuint black_tex;
 		GLuint black_tex;
 		GLuint normal_tex;
 		GLuint normal_tex;
 		GLuint aniso_tex;
 		GLuint aniso_tex;
+		GLuint white_tex_3d;
+		GLuint white_tex_array;
 
 
 		GLuint mipmap_blur_fbo;
 		GLuint mipmap_blur_fbo;
 		GLuint mipmap_blur_color;
 		GLuint mipmap_blur_color;
@@ -414,6 +418,7 @@ public:
 
 
 		Map<StringName, RID> default_textures;
 		Map<StringName, RID> default_textures;
 
 
+		Vector<ShaderLanguage::DataType> texture_types;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 
 
 		bool valid;
 		bool valid;

+ 11 - 0
drivers/gles2/shader_compiler_gles2.cpp

@@ -305,6 +305,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 
 
 			r_gen_code.texture_uniforms.resize(max_texture_uniforms);
 			r_gen_code.texture_uniforms.resize(max_texture_uniforms);
 			r_gen_code.texture_hints.resize(max_texture_uniforms);
 			r_gen_code.texture_hints.resize(max_texture_uniforms);
+			r_gen_code.texture_types.resize(max_texture_uniforms);
 
 
 			r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms);
 			r_gen_code.uniforms.resize(max_uniforms + max_texture_uniforms);
 
 
@@ -332,6 +333,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 				if (SL::is_sampler_type(E->get().type)) {
 				if (SL::is_sampler_type(E->get().type)) {
 					r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key();
 					r_gen_code.texture_uniforms.write[E->get().texture_order] = E->key();
 					r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
 					r_gen_code.texture_hints.write[E->get().texture_order] = E->get().hint;
+					r_gen_code.texture_types.write[E->get().texture_order] = E->get().type;
 				} else {
 				} else {
 					r_gen_code.uniforms.write[E->get().order] = E->key();
 					r_gen_code.uniforms.write[E->get().order] = E->key();
 				}
 				}
@@ -660,6 +662,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 								code += "texture2D";
 								code += "texture2D";
 							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
 							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
 								code += "textureCube";
 								code += "textureCube";
+							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) {
+								code += "texture3D";
+							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) {
+								code += "texture2DArray";
 							}
 							}
 
 
 						} else if (var_node->name == "textureLod") {
 						} else if (var_node->name == "textureLod") {
@@ -669,6 +675,10 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
 								code += "texture2DLod";
 								code += "texture2DLod";
 							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
 							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
 								code += "textureCubeLod";
 								code += "textureCubeLod";
+							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER3D) {
+								code += "texture3DLod";
+							} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2DARRAY) {
+								code += "texture2DArrayLod";
 							}
 							}
 
 
 						} else if (var_node->name == "mix") {
 						} else if (var_node->name == "mix") {
@@ -869,6 +879,7 @@ Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code,
 	r_gen_code.uniforms.clear();
 	r_gen_code.uniforms.clear();
 	r_gen_code.texture_uniforms.clear();
 	r_gen_code.texture_uniforms.clear();
 	r_gen_code.texture_hints.clear();
 	r_gen_code.texture_hints.clear();
+	r_gen_code.texture_types.clear();
 	r_gen_code.vertex = String();
 	r_gen_code.vertex = String();
 	r_gen_code.vertex_global = String();
 	r_gen_code.vertex_global = String();
 	r_gen_code.fragment = String();
 	r_gen_code.fragment = String();

+ 1 - 0
drivers/gles2/shader_compiler_gles2.h

@@ -54,6 +54,7 @@ public:
 		Vector<CharString> custom_defines;
 		Vector<CharString> custom_defines;
 		Vector<StringName> uniforms;
 		Vector<StringName> uniforms;
 		Vector<StringName> texture_uniforms;
 		Vector<StringName> texture_uniforms;
+		Vector<ShaderLanguage::DataType> texture_types;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 
 
 		String vertex_global;
 		String vertex_global;

+ 12 - 0
drivers/gles2/shaders/canvas.glsl

@@ -10,6 +10,12 @@ precision highp float;
 precision highp int;
 precision highp int;
 #endif
 #endif
 
 
+#ifndef USE_GLES_OVER_GL
+#extension GL_OES_texture_3D : enable
+#else
+#extension GL_EXT_texture_array : enable
+#endif
+
 uniform highp mat4 projection_matrix;
 uniform highp mat4 projection_matrix;
 /* clang-format on */
 /* clang-format on */
 
 
@@ -229,6 +235,12 @@ VERTEX_SHADER_CODE
 /* clang-format off */
 /* clang-format off */
 [fragment]
 [fragment]
 
 
+#ifndef USE_GLES_OVER_GL
+#extension GL_OES_texture_3D : enable
+#else
+#extension GL_EXT_texture_array : enable
+#endif
+
 // texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
 // texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
 // Do not copy these defines in the vertex section.
 // Do not copy these defines in the vertex section.
 #ifndef USE_GLES_OVER_GL
 #ifndef USE_GLES_OVER_GL

+ 12 - 0
drivers/gles2/shaders/scene.glsl

@@ -10,6 +10,12 @@ precision highp float;
 precision highp int;
 precision highp int;
 #endif
 #endif
 
 
+#ifndef USE_GLES_OVER_GL
+#extension GL_OES_texture_3D : enable
+#else
+#extension GL_EXT_texture_array : enable
+#endif
+
 /* clang-format on */
 /* clang-format on */
 #include "stdlib.glsl"
 #include "stdlib.glsl"
 /* clang-format off */
 /* clang-format off */
@@ -672,6 +678,12 @@ VERTEX_SHADER_CODE
 /* clang-format off */
 /* clang-format off */
 [fragment]
 [fragment]
 
 
+#ifndef USE_GLES_OVER_GL
+#extension GL_OES_texture_3D : enable
+#else
+#extension GL_EXT_texture_array : enable
+#endif
+
 // texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
 // texture2DLodEXT and textureCubeLodEXT are fragment shader specific.
 // Do not copy these defines in the vertex section.
 // Do not copy these defines in the vertex section.
 #ifndef USE_GLES_OVER_GL
 #ifndef USE_GLES_OVER_GL

+ 6 - 8
servers/visual/shader_language.cpp

@@ -1967,14 +1967,14 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
@@ -2004,10 +2004,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
+	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
-	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
+	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
@@ -4698,10 +4698,8 @@ Error ShaderLanguage::_validate_datatype(DataType p_type) {
 			case TYPE_UVEC4:
 			case TYPE_UVEC4:
 			case TYPE_ISAMPLER2D:
 			case TYPE_ISAMPLER2D:
 			case TYPE_USAMPLER2D:
 			case TYPE_USAMPLER2D:
-			case TYPE_SAMPLER3D:
 			case TYPE_ISAMPLER3D:
 			case TYPE_ISAMPLER3D:
 			case TYPE_USAMPLER3D:
 			case TYPE_USAMPLER3D:
-			case TYPE_SAMPLER2DARRAY:
 			case TYPE_USAMPLER2DARRAY:
 			case TYPE_USAMPLER2DARRAY:
 			case TYPE_ISAMPLER2DARRAY:
 			case TYPE_ISAMPLER2DARRAY:
 				invalid_type = true;
 				invalid_type = true;