Browse Source

add 3D textures

Thomas Herzog 7 years ago
parent
commit
b4d3f541e7

+ 9 - 5
drivers/dummy/rasterizer_dummy.h

@@ -154,7 +154,8 @@ public:
 		ERR_FAIL_COND_V(!texture, RID());
 		return texture_owner.make_rid(texture);
 	}
-	void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) {
+
+	void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type = VS::TEXTURE_TYPE_2D, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) {
 		DummyTexture *t = texture_owner.getornull(p_texture);
 		ERR_FAIL_COND(!t);
 		t->width = p_width;
@@ -164,7 +165,7 @@ public:
 		t->image = Ref<Image>(memnew(Image));
 		t->image->create(p_width, p_height, false, p_format);
 	}
-	void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) {
+	void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_level) {
 		DummyTexture *t = texture_owner.getornull(p_texture);
 		ERR_FAIL_COND(!t);
 		t->width = p_image->get_width();
@@ -173,7 +174,7 @@ public:
 		t->image->create(t->width, t->height, false, t->format, p_image->get_data());
 	}
 
-	void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+	void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_level) {
 		DummyTexture *t = texture_owner.get(p_texture);
 
 		ERR_FAIL_COND(!t);
@@ -186,7 +187,7 @@ public:
 		t->image->blit_rect(p_image, Rect2(src_x, src_y, src_w, src_h), Vector2(dst_x, dst_y));
 	}
 
-	Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const {
+	Ref<Image> texture_get_data(RID p_texture, int p_level) const {
 		DummyTexture *t = texture_owner.getornull(p_texture);
 		ERR_FAIL_COND_V(!t, Ref<Image>());
 		return t->image;
@@ -206,10 +207,13 @@ public:
 		ERR_FAIL_COND_V(!t, Image::FORMAT_RGB8);
 		return t->format;
 	}
+
+	VisualServer::TextureType texture_get_type(RID p_texture) const { return VS::TEXTURE_TYPE_2D; }
 	uint32_t texture_get_texid(RID p_texture) const { return 0; }
 	uint32_t texture_get_width(RID p_texture) const { return 0; }
 	uint32_t texture_get_height(RID p_texture) const { return 0; }
-	void texture_set_size_override(RID p_texture, int p_width, int p_height) {}
+	uint32_t texture_get_depth(RID p_texture) const { return 0; }
+	void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) {}
 
 	void texture_set_path(RID p_texture, const String &p_path) {
 		DummyTexture *t = texture_owner.getornull(p_texture);

+ 1 - 1
drivers/gles2/rasterizer_gles2.cpp

@@ -317,7 +317,7 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 	canvas->canvas_begin();
 
 	RID texture = storage->texture_create();
-	storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), VS::TEXTURE_FLAG_FILTER);
+	storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER);
 	storage->texture_set_data(texture, p_image);
 
 	Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());

+ 44 - 16
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -346,7 +346,7 @@ RID RasterizerStorageGLES2::texture_create() {
 	return texture_owner.make_rid(texture);
 }
 
-void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
+void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type, uint32_t p_flags) {
 	GLenum format;
 	GLenum internal_format;
 	GLenum type;
@@ -365,7 +365,20 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
 	texture->format = p_format;
 	texture->flags = p_flags;
 	texture->stored_cube_sides = 0;
-	texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+	texture->type = p_type;
+
+	switch (p_type) {
+		case VS::TEXTURE_TYPE_2D: {
+			texture->target = GL_TEXTURE_2D;
+		} break;
+		case VS::TEXTURE_TYPE_CUBEMAP: {
+			texture->target = GL_TEXTURE_CUBE_MAP;
+		} break;
+		case VS::TEXTURE_TYPE_2D_ARRAY: {
+		} break;
+		case VS::TEXTURE_TYPE_3D: {
+		} break;
+	}
 
 	_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type, compressed);
 
@@ -391,7 +404,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
 	texture->active = true;
 }
 
-void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side) {
+void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
 	Texture *texture = texture_owner.getornull(p_texture);
 
 	ERR_FAIL_COND(!texture);
@@ -406,7 +419,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 	bool compressed = false;
 
 	if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
-		texture->images[p_cube_side] = p_image;
+		texture->images[p_layer] = p_image;
 	}
 
 	Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type, compressed);
@@ -425,7 +438,7 @@ 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_cube_side] : GL_TEXTURE_2D;
+	GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D;
 
 	texture->data_size = img->get_data().size();
 	PoolVector<uint8_t>::Read read = img->get_data().read();
@@ -527,9 +540,9 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 
 	// printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem);
 
-	texture->stored_cube_sides |= (1 << p_cube_side);
+	texture->stored_cube_sides |= (1 << p_layer);
 
-	if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (!(texture->flags & VS::TEXTURE_FLAG_CUBEMAP) || texture->stored_cube_sides == (1 << 6) - 1)) {
+	if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != VS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) {
 		//generate mipmaps if they were requested and the image does not contain them
 		glGenerateMipmap(texture->target);
 	}
@@ -537,12 +550,12 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
 	texture->mipmaps = mipmaps;
 }
 
-void RasterizerStorageGLES2::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+void RasterizerStorageGLES2::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
 	// TODO
 	ERR_PRINT("Not implemented (ask Karroffel to do it :p)");
 }
 
-Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const {
+Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) const {
 
 	Texture *texture = texture_owner.getornull(p_texture);
 
@@ -550,8 +563,8 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, VS::CubeMapSi
 	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
 	ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
 
-	if (!texture->images[p_cube_side].is_null()) {
-		return texture->images[p_cube_side];
+	if (!texture->images[p_layer].is_null()) {
+		return texture->images[p_layer];
 	}
 #ifdef GLES_OVER_GL
 
@@ -605,8 +618,6 @@ void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags)
 
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
-	uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP;
-	texture->flags = p_flags | cube; // can't remove a cube from being a cube
 
 	if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
 
@@ -663,6 +674,14 @@ Image::Format RasterizerStorageGLES2::texture_get_format(RID p_texture) const {
 	return texture->format;
 }
 
+VisualServer::TextureType RasterizerStorageGLES2::texture_get_type(RID p_texture) const {
+	Texture *texture = texture_owner.getornull(p_texture);
+
+	ERR_FAIL_COND_V(!texture, VS::TEXTURE_TYPE_2D);
+
+	return texture->type;
+}
+
 uint32_t RasterizerStorageGLES2::texture_get_texid(RID p_texture) const {
 	Texture *texture = texture_owner.getornull(p_texture);
 
@@ -687,7 +706,15 @@ uint32_t RasterizerStorageGLES2::texture_get_height(RID p_texture) const {
 	return texture->height;
 }
 
-void RasterizerStorageGLES2::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+uint32_t RasterizerStorageGLES2::texture_get_depth(RID p_texture) const {
+	Texture *texture = texture_owner.getornull(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->depth;
+}
+
+void RasterizerStorageGLES2::texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth) {
 	Texture *texture = texture_owner.getornull(p_texture);
 
 	ERR_FAIL_COND(!texture);
@@ -726,8 +753,9 @@ void RasterizerStorageGLES2::texture_debug_usage(List<VS::TextureInfo> *r_info)
 		VS::TextureInfo tinfo;
 		tinfo.path = t->path;
 		tinfo.format = t->format;
-		tinfo.size.x = t->alloc_width;
-		tinfo.size.y = t->alloc_height;
+		tinfo.width = t->alloc_width;
+		tinfo.height = t->alloc_height;
+		tinfo.depth = 0;
 		tinfo.bytes = t->total_data_size;
 		r_info->push_back(tinfo);
 	}

+ 9 - 6
drivers/gles2/rasterizer_storage_gles2.h

@@ -231,9 +231,10 @@ public:
 
 		String path;
 		uint32_t flags;
-		int width, height;
+		int width, height, depth;
 		int alloc_width, alloc_height;
 		Image::Format format;
+		VS::TextureType type;
 
 		GLenum target;
 		GLenum gl_format_cache;
@@ -327,17 +328,19 @@ public:
 	Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed);
 
 	virtual RID texture_create();
-	virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
-	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
-	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
-	virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const;
+	virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
+	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
+	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
+	virtual Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
 	virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
 	virtual uint32_t texture_get_flags(RID p_texture) const;
 	virtual Image::Format texture_get_format(RID p_texture) const;
+	virtual VS::TextureType texture_get_type(RID p_texture) const;
 	virtual uint32_t texture_get_texid(RID p_texture) const;
 	virtual uint32_t texture_get_width(RID p_texture) const;
 	virtual uint32_t texture_get_height(RID p_texture) const;
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height);
+	virtual uint32_t texture_get_depth(RID p_texture) const;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth);
 
 	virtual void texture_set_path(RID p_texture, const String &p_path);
 	virtual String texture_get_path(RID p_texture) const;

+ 1 - 1
drivers/gles3/rasterizer_gles3.cpp

@@ -290,7 +290,7 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
 	canvas->canvas_begin();
 
 	RID texture = storage->texture_create();
-	storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), VS::TEXTURE_FLAG_FILTER);
+	storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER);
 	storage->texture_set_data(texture, p_image);
 
 	Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height());

+ 57 - 25
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1190,6 +1190,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
 	int tc = p_material->textures.size();
 	RID *textures = p_material->textures.ptrw();
 	ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw();
+	const ShaderLanguage::DataType *texture_types = p_material->shader->texture_types.ptr();
 
 	state.current_main_tex = 0;
 
@@ -1198,39 +1199,17 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
 		glActiveTexture(GL_TEXTURE0 + i);
 
 		GLenum target;
-		GLuint tex;
+		GLuint tex = 0;
 
-		RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull(textures[i]);
+		RasterizerStorageGLES3::Texture *t = storage->texture_owner.getptr(textures[i]);
 
-		if (!t) {
-			//check hints
-			target = GL_TEXTURE_2D;
-
-			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;
-			}
-
-		} else {
+		if (t) {
 
 			if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
 				VisualServerRaster::redraw_request();
 			}
 
 			t = t->get_ptr(); //resolve for proxies
-
 #ifdef TOOLS_ENABLED
 			if (t->detect_3d) {
 				t->detect_3d(t->detect_3d_ud);
@@ -1247,6 +1226,59 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
 
 			target = t->target;
 			tex = t->tex_id;
+		} else {
+
+			switch (texture_types[i]) {
+				case ShaderLanguage::TYPE_ISAMPLER2D:
+				case ShaderLanguage::TYPE_USAMPLER2D:
+				case ShaderLanguage::TYPE_SAMPLER2D: {
+					target = GL_TEXTURE_2D;
+
+					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;
+
+				case ShaderLanguage::TYPE_ISAMPLER3D:
+				case ShaderLanguage::TYPE_USAMPLER3D:
+				case ShaderLanguage::TYPE_SAMPLER3D: {
+
+					target = GL_TEXTURE_3D;
+
+					switch (texture_hints[i]) {
+
+						// TODO
+						default: {
+							tex = storage->resources.white_tex_3d;
+						} break;
+					}
+
+				} break;
+
+				case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+				case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+					// TODO
+				} break;
+			}
 		}
 
 		glBindTexture(target, tex);

+ 200 - 35
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -595,7 +595,7 @@ RID RasterizerStorageGLES3::texture_create() {
 	return texture_owner.make_rid(texture);
 }
 
-void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
+void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type, uint32_t p_flags) {
 
 	GLenum format;
 	GLenum internal_format;
@@ -612,15 +612,33 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
 	ERR_FAIL_COND(!texture);
 	texture->width = p_width;
 	texture->height = p_height;
+	texture->depth = p_depth_3d;
 	texture->format = p_format;
 	texture->flags = p_flags;
 	texture->stored_cube_sides = 0;
-	texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
+
+	texture->type = p_type;
+
+	switch (p_type) {
+		case VS::TEXTURE_TYPE_2D: {
+			texture->target = GL_TEXTURE_2D;
+		} break;
+		case VS::TEXTURE_TYPE_CUBEMAP: {
+			texture->target = GL_TEXTURE_CUBE_MAP;
+		} break;
+		case VS::TEXTURE_TYPE_2D_ARRAY: {
+			texture->target = GL_TEXTURE_2D_ARRAY;
+		} break;
+		case VS::TEXTURE_TYPE_3D: {
+			texture->target = GL_TEXTURE_3D;
+		} break;
+	}
 
 	_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type, compressed, srgb);
 
 	texture->alloc_width = texture->width;
 	texture->alloc_height = texture->height;
+	texture->alloc_depth = texture->depth;
 
 	texture->gl_format_cache = format;
 	texture->gl_type_cache = type;
@@ -633,7 +651,34 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
 
-	if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
+	if (p_type == VS::TEXTURE_TYPE_3D || p_type == VS::TEXTURE_TYPE_2D_ARRAY) {
+
+		int width = p_width;
+		int height = p_height;
+		int depth = p_depth_3d;
+
+		int mipmaps = 0;
+
+		while (width != 1 && height != 1) {
+			glTexImage3D(texture->target, 0, internal_format, width, height, depth, 0, format, type, NULL);
+
+			width = MAX(1, width / 2);
+			height = MAX(1, height / 2);
+
+			if (p_type == VS::TEXTURE_TYPE_3D) {
+				depth = MAX(1, depth / 2);
+			}
+
+			mipmaps++;
+
+			if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS))
+				break;
+		}
+
+		glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
+
+	} else if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
 		//prealloc if video
 		glTexImage2D(texture->target, 0, internal_format, p_width, p_height, 0, format, type, NULL);
 	}
@@ -641,7 +686,7 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
 	texture->active = true;
 }
 
-void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side) {
+void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer) {
 
 	Texture *texture = texture_owner.get(p_texture);
 
@@ -658,7 +703,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 	bool srgb;
 
 	if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) {
-		texture->images[p_cube_side] = p_image;
+		texture->images[p_layer] = p_image;
 	}
 
 	Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type, compressed, srgb);
@@ -677,7 +722,23 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 		}
 	};
 
-	GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D;
+	GLenum blit_target;
+
+	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();
 	PoolVector<uint8_t>::Read read = img->get_data().read();
@@ -785,20 +846,36 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 
 		//print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h));
 
-		if (texture->compressed) {
-			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+		if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
+
+			if (texture->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]);
+				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]);
+				}
+			}
 		} 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]);
+			if (texture->compressed) {
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+				int bw = w;
+				int bh = h;
+
+				glCompressedTexSubImage3D(blit_target, i, 0, 0, p_layer, bw, bh, 1, internal_format, size, &read[ofs]);
 			} 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]);
 			}
 		}
 		tsize += size;
@@ -813,14 +890,17 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 
 	//printf("texture: %i x %i - size: %i - total: %i\n",texture->width,texture->height,tsize,_rinfo.texture_mem);
 
-	texture->stored_cube_sides |= (1 << p_cube_side);
+	texture->stored_cube_sides |= (1 << p_layer);
 
-	if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (!(texture->flags & VS::TEXTURE_FLAG_CUBEMAP) || texture->stored_cube_sides == (1 << 6) - 1)) {
+	if ((texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) && (texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != VS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) {
 		//generate mipmaps if they were requested and the image does not contain them
 		glGenerateMipmap(texture->target);
 	} else if (mipmaps > 1) {
 		glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
 		glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
+	} else {
+		glTexParameteri(texture->target, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(texture->target, GL_TEXTURE_MAX_LEVEL, 0);
 	}
 
 	texture->mipmaps = mipmaps;
@@ -831,7 +911,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
 // Uploads pixel data to a sub-region of a texture, for the specified mipmap.
 // The texture pixels must have been allocated before, because most features seen in texture_set_data() make no sense in a partial update.
 // TODO If we want this to be usable without pre-filling pixels with a full image, we have to call glTexImage2D() with null data.
-void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side) {
+void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer) {
 
 	Texture *texture = texture_owner.get(p_texture);
 
@@ -859,7 +939,23 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
 
 	Ref<Image> img = _get_gl_image_and_format(p_sub_img, p_sub_img->get_format(), texture->flags, format, internal_format, type, compressed, srgb);
 
-	GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D;
+	GLenum blit_target;
+
+	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;
+	}
 
 	PoolVector<uint8_t>::Read read = img->get_data().read();
 
@@ -869,18 +965,38 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
 	int src_data_size = img->get_data().size();
 	int src_ofs = 0;
 
-	if (texture->compressed) {
-		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-		glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]);
+	if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
+		if (texture->compressed) {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+			glCompressedTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, internal_format, src_data_size, &read[src_ofs]);
 
+		} else {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+			// `format` has to match the internal_format used when the texture was created
+			glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]);
+		}
 	} else {
-		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-		// `format` has to match the internal_format used when the texture was created
-		glTexSubImage2D(blit_target, p_dst_mip, dst_x, dst_y, src_w, src_h, format, type, &read[src_ofs]);
+		if (texture->compressed) {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+			glCompressedTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, src_data_size, &read[src_ofs]);
+		} else {
+			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+			// `format` has to match the internal_format used when the texture was created
+			glTexSubImage3D(blit_target, p_dst_mip, dst_x, dst_y, p_layer, src_w, src_h, 1, format, type, &read[src_ofs]);
+		}
+	}
+
+	if (texture->flags & VS::TEXTURE_FLAG_FILTER) {
+
+		glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering
+
+	} else {
+
+		glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering
 	}
 }
 
-Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const {
+Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) const {
 
 	Texture *texture = texture_owner.get(p_texture);
 
@@ -888,8 +1004,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSi
 	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
 	ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
 
-	if (!texture->images[p_cube_side].is_null()) {
-		return texture->images[p_cube_side];
+	if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && !texture->images[p_layer].is_null()) {
+		return texture->images[p_layer];
 	}
 
 #ifdef GLES_OVER_GL
@@ -977,10 +1093,10 @@ void RasterizerStorageGLES3::texture_set_flags(RID p_texture, uint32_t p_flags)
 
 	bool had_mipmaps = texture->flags & VS::TEXTURE_FLAG_MIPMAPS;
 
+	texture->flags = p_flags;
+
 	glActiveTexture(GL_TEXTURE0);
 	glBindTexture(texture->target, texture->tex_id);
-	uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP;
-	texture->flags = p_flags | cube; // can't remove a cube from being a cube
 
 	if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) {
 
@@ -1058,6 +1174,14 @@ Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const {
 
 	return texture->format;
 }
+
+VisualServer::TextureType RasterizerStorageGLES3::texture_get_type(RID p_texture) const {
+	Texture *texture = texture_owner.get(p_texture);
+
+	ERR_FAIL_COND_V(!texture, VS::TEXTURE_TYPE_2D);
+
+	return texture->type;
+}
 uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const {
 
 	Texture *texture = texture_owner.get(p_texture);
@@ -1083,7 +1207,16 @@ uint32_t RasterizerStorageGLES3::texture_get_height(RID p_texture) const {
 	return texture->height;
 }
 
-void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height) {
+uint32_t RasterizerStorageGLES3::texture_get_depth(RID p_texture) const {
+
+	Texture *texture = texture_owner.get(p_texture);
+
+	ERR_FAIL_COND_V(!texture, 0);
+
+	return texture->depth;
+}
+
+void RasterizerStorageGLES3::texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth) {
 
 	Texture *texture = texture_owner.get(p_texture);
 
@@ -1123,8 +1256,9 @@ void RasterizerStorageGLES3::texture_debug_usage(List<VS::TextureInfo> *r_info)
 		VS::TextureInfo tinfo;
 		tinfo.path = t->path;
 		tinfo.format = t->format;
-		tinfo.size.x = t->alloc_width;
-		tinfo.size.y = t->alloc_height;
+		tinfo.width = t->alloc_width;
+		tinfo.height = t->alloc_height;
+		tinfo.depth = 0;
 		tinfo.bytes = t->total_data_size;
 		r_info->push_back(tinfo);
 	}
@@ -1169,7 +1303,7 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_
 
 	Texture *texture = texture_owner.get(p_source);
 	ERR_FAIL_COND_V(!texture, RID());
-	ERR_FAIL_COND_V(!(texture->flags & VS::TEXTURE_FLAG_CUBEMAP), RID());
+	ERR_FAIL_COND_V(texture->type != VS::TEXTURE_TYPE_CUBEMAP, RID());
 
 	bool use_float = config.hdr_supported;
 
@@ -1285,7 +1419,8 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_
 
 	Texture *ctex = memnew(Texture);
 
-	ctex->flags = VS::TEXTURE_FLAG_CUBEMAP | VS::TEXTURE_FLAG_MIPMAPS | VS::TEXTURE_FLAG_FILTER;
+	ctex->type = VS::TEXTURE_TYPE_CUBEMAP;
+	ctex->flags = VS::TEXTURE_FLAG_MIPMAPS | VS::TEXTURE_FLAG_FILTER;
 	ctex->width = p_resolution;
 	ctex->height = p_resolution;
 	ctex->alloc_width = p_resolution;
@@ -1765,6 +1900,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
 	p_shader->ubo_offsets = gen_code.uniform_offsets;
 	p_shader->texture_count = gen_code.texture_uniforms.size();
 	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_fragment_time = gen_code.uses_fragment_time;
@@ -1875,6 +2011,13 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn
 				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
 				pi.hint_string = "Texture";
 			} break;
+			case ShaderLanguage::TYPE_SAMPLER3D:
+			case ShaderLanguage::TYPE_ISAMPLER3D:
+			case ShaderLanguage::TYPE_USAMPLER3D: {
+				pi.type = Variant::OBJECT;
+				pi.hint = PROPERTY_HINT_RESOURCE_TYPE;
+				pi.hint_string = "Texture3D";
+			} break;
 			case ShaderLanguage::TYPE_SAMPLERCUBE: {
 
 				pi.type = Variant::OBJECT;
@@ -2649,6 +2792,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
 	//set up the texture array, for easy access when it needs to be drawn
 	if (material->shader && material->shader->texture_count) {
 
+		material->texture_is_3d.resize(material->shader->texture_count);
 		material->textures.resize(material->shader->texture_count);
 
 		for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = material->shader->uniforms.front(); E; E = E->next()) {
@@ -2658,6 +2802,16 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
 
 			RID texture;
 
+			switch (E->get().type) {
+				case ShaderLanguage::TYPE_SAMPLER3D:
+				case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
+					material->texture_is_3d.write[E->get().texture_order] = true;
+				} break;
+				default: {
+					material->texture_is_3d.write[E->get().texture_order] = false;
+				} break;
+			}
+
 			Map<StringName, Variant>::Element *V = material->params.find(E->key());
 			if (V) {
 				texture = V->get();
@@ -2675,6 +2829,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
 
 	} else {
 		material->textures.clear();
+		material->texture_is_3d.clear();
 	}
 }
 
@@ -6999,6 +7154,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
 		info.texture_mem -= texture->total_data_size;
 		texture_owner.free(p_rid);
 		memdelete(texture);
+
 	} else if (sky_owner.owns(p_rid)) {
 		// delete the sky
 		Sky *sky = sky_owner.get(p_rid);
@@ -7408,6 +7564,15 @@ void RasterizerStorageGLES3::initialize() {
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, anisotexdata);
 		glGenerateMipmap(GL_TEXTURE_2D);
 		glBindTexture(GL_TEXTURE_2D, 0);
+
+		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);
+
+		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
 	}
 
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);

+ 14 - 7
drivers/gles3/rasterizer_storage_gles3.h

@@ -123,6 +123,8 @@ public:
 		GLuint normal_tex;
 		GLuint aniso_tex;
 
+		GLuint white_tex_3d;
+
 		GLuint quadie;
 		GLuint quadie_array;
 
@@ -248,9 +250,10 @@ public:
 
 		String path;
 		uint32_t flags;
-		int width, height;
-		int alloc_width, alloc_height;
+		int width, height, depth;
+		int alloc_width, alloc_height, alloc_depth;
 		Image::Format format;
+		VS::TextureType type;
 
 		GLenum target;
 		GLenum gl_format_cache;
@@ -340,17 +343,19 @@ public:
 	Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb);
 
 	virtual RID texture_create();
-	virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
-	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
-	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT);
-	virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const;
+	virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT);
+	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0);
+	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0);
+	virtual Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const;
 	virtual void texture_set_flags(RID p_texture, uint32_t p_flags);
 	virtual uint32_t texture_get_flags(RID p_texture) const;
 	virtual Image::Format texture_get_format(RID p_texture) const;
+	virtual VS::TextureType texture_get_type(RID p_texture) const;
 	virtual uint32_t texture_get_texid(RID p_texture) const;
 	virtual uint32_t texture_get_width(RID p_texture) const;
 	virtual uint32_t texture_get_height(RID p_texture) const;
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height);
+	virtual uint32_t texture_get_depth(RID p_texture) const;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth);
 
 	virtual void texture_set_path(RID p_texture, const String &p_path);
 	virtual String texture_get_path(RID p_texture) const;
@@ -410,6 +415,7 @@ public:
 
 		Map<StringName, RID> default_textures;
 
+		Vector<ShaderLanguage::DataType> texture_types;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 
 		bool valid;
@@ -532,6 +538,7 @@ public:
 		Map<StringName, Variant> params;
 		SelfList<Material> list;
 		SelfList<Material> dirty_list;
+		Vector<bool> texture_is_3d;
 		Vector<RID> textures;
 		float line_width;
 		int render_priority;

+ 2 - 0
drivers/gles3/shader_compiler_gles3.cpp

@@ -341,6 +341,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 
 			r_gen_code.texture_uniforms.resize(max_texture_uniforms);
 			r_gen_code.texture_hints.resize(max_texture_uniforms);
+			r_gen_code.texture_types.resize(max_texture_uniforms);
 
 			Vector<int> uniform_sizes;
 			Vector<int> uniform_alignments;
@@ -367,6 +368,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 					r_gen_code.fragment_global += ucode;
 					r_gen_code.texture_uniforms.write[E->get().texture_order] = _mkid(E->key());
 					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 {
 					if (!uses_uniforms) {
 

+ 1 - 0
drivers/gles3/shader_compiler_gles3.h

@@ -52,6 +52,7 @@ public:
 
 		Vector<CharString> defines;
 		Vector<StringName> texture_uniforms;
+		Vector<ShaderLanguage::DataType> texture_types;
 		Vector<ShaderLanguage::ShaderNode::Uniform::Hint> texture_hints;
 
 		Vector<uint32_t> uniform_offsets;

+ 1 - 0
scene/register_scene_types.cpp

@@ -613,6 +613,7 @@ void register_scene_types() {
 	ClassDB::register_class<ProxyTexture>();
 	ClassDB::register_class<AnimatedTexture>();
 	ClassDB::register_class<CubeMap>();
+	ClassDB::register_class<Texture3D>();
 	ClassDB::register_class<Animation>();
 	ClassDB::register_virtual_class<Font>();
 	ClassDB::register_class<BitmapFont>();

+ 2 - 2
scene/resources/sky_box.cpp

@@ -405,7 +405,7 @@ void ProceduralSky::_update_sky() {
 
 	} else {
 		Ref<Image> image = _generate_sky();
-		VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
+		VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
 		VS::get_singleton()->texture_set_data(texture, image);
 		_radiance_changed();
 	}
@@ -422,7 +422,7 @@ void ProceduralSky::_queue_update() {
 
 void ProceduralSky::_thread_done(const Ref<Image> &p_image) {
 
-	VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
+	VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
 	VS::get_singleton()->texture_set_data(texture, p_image);
 	_radiance_changed();
 	Thread::wait_to_finish(sky_thread);

+ 215 - 9
scene/resources/texture.cpp

@@ -124,7 +124,7 @@ bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) {
 		Size2 s = p_value;
 		w = s.width;
 		h = s.height;
-		VisualServer::get_singleton()->texture_set_size_override(texture, w, h);
+		VisualServer::get_singleton()->texture_set_size_override(texture, w, h, 0);
 	} else if (p_name == "_data") {
 		_set_data(p_value);
 	} else
@@ -183,7 +183,7 @@ void ImageTexture::_reload_hook(const RID &p_hook) {
 void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
 
 	flags = p_flags;
-	VisualServer::get_singleton()->texture_allocate(texture, p_width, p_height, p_format, p_flags);
+	VisualServer::get_singleton()->texture_allocate(texture, p_width, p_height, 0, p_format, VS::TEXTURE_TYPE_2D, p_flags);
 	format = p_format;
 	w = p_width;
 	h = p_height;
@@ -196,7 +196,7 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags
 	h = p_image->get_height();
 	format = p_image->get_format();
 
-	VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), p_flags);
+	VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags);
 	VisualServer::get_singleton()->texture_set_data(texture, p_image);
 	_change_notify();
 }
@@ -301,7 +301,7 @@ void ImageTexture::set_size_override(const Size2 &p_size) {
 		w = s.x;
 	if (s.y != 0)
 		h = s.y;
-	VisualServer::get_singleton()->texture_set_size_override(texture, w, h);
+	VisualServer::get_singleton()->texture_set_size_override(texture, w, h, 0);
 }
 
 void ImageTexture::set_path(const String &p_path, bool p_take_over) {
@@ -648,7 +648,7 @@ Error StreamTexture::load(const String &p_path) {
 	if (err)
 		return err;
 
-	VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), image->get_format(), lflags);
+	VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), 0, image->get_format(), VS::TEXTURE_TYPE_2D, lflags);
 	VS::get_singleton()->texture_set_data(texture, image);
 
 	w = lw;
@@ -1195,7 +1195,7 @@ void CubeMap::set_flags(uint32_t p_flags) {
 
 	flags = p_flags;
 	if (_is_valid())
-		VS::get_singleton()->texture_set_flags(cubemap, flags | VS::TEXTURE_FLAG_CUBEMAP);
+		VS::get_singleton()->texture_set_flags(cubemap, flags);
 }
 
 uint32_t CubeMap::get_flags() const {
@@ -1211,7 +1211,7 @@ void CubeMap::set_side(Side p_side, const Ref<Image> &p_image) {
 		format = p_image->get_format();
 		w = p_image->get_width();
 		h = p_image->get_height();
-		VS::get_singleton()->texture_allocate(cubemap, w, h, p_image->get_format(), flags | VS::TEXTURE_FLAG_CUBEMAP);
+		VS::get_singleton()->texture_allocate(cubemap, w, h, 0, p_image->get_format(), VS::TEXTURE_TYPE_CUBEMAP, flags);
 	}
 
 	VS::get_singleton()->texture_set_data(cubemap, p_image, VS::CubeMapSide(p_side));
@@ -1474,7 +1474,7 @@ void CurveTexture::_update() {
 
 	Ref<Image> image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data));
 
-	VS::get_singleton()->texture_allocate(_texture, _width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER);
+	VS::get_singleton()->texture_allocate(_texture, _width, 1, 0, Image::FORMAT_RF, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER);
 	VS::get_singleton()->texture_set_data(_texture, image);
 
 	emit_changed();
@@ -1583,7 +1583,7 @@ void GradientTexture::_update() {
 
 	Ref<Image> image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data));
 
-	VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RGBA8, VS::TEXTURE_FLAG_FILTER);
+	VS::get_singleton()->texture_allocate(texture, width, 1, 0, Image::FORMAT_RGBA8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER);
 	VS::get_singleton()->texture_set_data(texture, image);
 
 	emit_changed();
@@ -1876,3 +1876,209 @@ AnimatedTexture::AnimatedTexture() {
 AnimatedTexture::~AnimatedTexture() {
 	VS::get_singleton()->free(proxy);
 }
+
+bool Texture3D::get_split_single_image_enabled() const {
+	return split_single_image_enabled;
+}
+
+void Texture3D::set_split_single_image_enabled(bool p_split_enabled) {
+	split_single_image_enabled = p_split_enabled;
+
+	_change_notify();
+}
+
+uint32_t Texture3D::get_split_single_image_h_split() const {
+	return split_single_image_h_split;
+}
+
+void Texture3D::set_split_single_image_h_split(uint32_t p_h_split) {
+	split_single_image_h_split = p_h_split;
+
+	if (split_single_image_image.is_valid())
+		create_from_image(split_single_image_image, split_single_image_h_split, split_single_image_v_split, split_single_image_num_layers, flags);
+}
+
+uint32_t Texture3D::get_split_single_image_v_split() const {
+	return split_single_image_v_split;
+}
+
+void Texture3D::set_split_single_image_v_split(uint32_t p_v_split) {
+	split_single_image_v_split = p_v_split;
+
+	if (split_single_image_image.is_valid())
+		create_from_image(split_single_image_image, split_single_image_h_split, split_single_image_v_split, split_single_image_num_layers, flags);
+}
+
+uint32_t Texture3D::get_split_single_image_num_layers() const {
+	return split_single_image_num_layers;
+}
+
+void Texture3D::set_split_single_image_num_layers(uint32_t p_num_layers) {
+	split_single_image_num_layers = p_num_layers;
+
+	if (split_single_image_image.is_valid())
+		create_from_image(split_single_image_image, split_single_image_h_split, split_single_image_v_split, split_single_image_num_layers, flags);
+}
+
+Ref<Image> Texture3D::get_split_single_image_image() const {
+	return split_single_image_image;
+}
+
+void Texture3D::set_split_single_image_image(const Ref<Image> &p_image) {
+	split_single_image_image = p_image;
+
+	create_from_image(split_single_image_image, split_single_image_h_split, split_single_image_v_split, split_single_image_num_layers, flags);
+}
+
+void Texture3D::_validate_property(PropertyInfo &property) const {
+	if (property.name.begins_with("split_single_image_") && property.name != "split_single_image_enabled" && !split_single_image_enabled) {
+		property.usage = 0;
+	}
+}
+
+void Texture3D::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("set_flags", "flags"), &Texture3D::set_flags);
+	ClassDB::bind_method(D_METHOD("get_flags"), &Texture3D::get_flags);
+
+	ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format);
+
+	ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width);
+	ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height);
+	ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth);
+
+	ClassDB::bind_method(D_METHOD("set_split_single_image_enabled", "split_enabled"), &Texture3D::set_split_single_image_enabled);
+	ClassDB::bind_method(D_METHOD("get_split_single_image_enabled"), &Texture3D::get_split_single_image_enabled);
+
+	ClassDB::bind_method(D_METHOD("set_split_single_image_h_split", "h_split"), &Texture3D::set_split_single_image_h_split);
+	ClassDB::bind_method(D_METHOD("get_split_single_image_h_split"), &Texture3D::get_split_single_image_h_split);
+
+	ClassDB::bind_method(D_METHOD("set_split_single_image_v_split", "v_split"), &Texture3D::set_split_single_image_v_split);
+	ClassDB::bind_method(D_METHOD("get_split_single_image_v_split"), &Texture3D::get_split_single_image_v_split);
+
+	ClassDB::bind_method(D_METHOD("set_split_single_image_num_layers", "num_layers"), &Texture3D::set_split_single_image_num_layers);
+	ClassDB::bind_method(D_METHOD("get_split_single_image_num_layers"), &Texture3D::get_split_single_image_num_layers);
+
+	ClassDB::bind_method(D_METHOD("set_split_single_image_image", "image"), &Texture3D::set_split_single_image_image);
+	ClassDB::bind_method(D_METHOD("get_split_single_image_image"), &Texture3D::get_split_single_image_image);
+
+	ClassDB::bind_method(D_METHOD("create", "width", "height", "depth", "format", "flags"), &Texture3D::create, DEFVAL(FLAGS_DEFAULT));
+	ClassDB::bind_method(D_METHOD("create_from_image", "image", "h_split", "v_split", "num_layer", "flags"), &Texture3D::create_from_image, DEFVAL(FLAGS_DEFAULT));
+
+	ClassDB::bind_method(D_METHOD("set_data_partial", "image", "x_offset", "y_offset", "layer", "mipmap"), &Texture3D::set_data_partial, DEFVAL(0));
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter"), "set_flags", "get_flags");
+
+	BIND_ENUM_CONSTANT(FLAG_MIPMAPS);
+	BIND_ENUM_CONSTANT(FLAG_REPEAT);
+	BIND_ENUM_CONSTANT(FLAG_FILTER);
+	BIND_ENUM_CONSTANT(FLAGS_DEFAULT);
+
+	ADD_GROUP("Split single image", "split_single_image_");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "split_single_image_enabled"), "set_split_single_image_enabled", "get_split_single_image_enabled");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "split_single_image_h_split", PROPERTY_HINT_RANGE, "0,1000"), "set_split_single_image_h_split", "get_split_single_image_h_split");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "split_single_image_v_split", PROPERTY_HINT_RANGE, "0,1000"), "set_split_single_image_v_split", "get_split_single_image_v_split");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "split_single_image_num_layers"), "set_split_single_image_num_layers", "get_split_single_image_num_layers");
+	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "split_single_image_image", PROPERTY_HINT_RESOURCE_TYPE, "Image"), "set_split_single_image_image", "get_split_single_image_image");
+}
+
+void Texture3D::set_flags(uint32_t p_flags) {
+	flags = p_flags;
+
+	if (texture.is_valid()) {
+		VS::get_singleton()->texture_set_flags(texture, flags);
+	}
+}
+
+uint32_t Texture3D::get_flags() const {
+	return flags;
+}
+
+Image::Format Texture3D::get_format() const {
+	return format;
+}
+
+uint32_t Texture3D::get_width() const {
+	return width;
+}
+
+uint32_t Texture3D::get_height() const {
+	return height;
+}
+
+uint32_t Texture3D::get_depth() const {
+	return depth;
+}
+
+void Texture3D::create(uint32_t p_width, uint32_t p_height, uint32_t p_depth, Image::Format p_format, uint32_t p_flags) {
+	VS::get_singleton()->texture_allocate(texture, p_width, p_height, p_depth, p_format, VS::TEXTURE_TYPE_3D, p_flags);
+
+	width = p_width;
+	height = p_height;
+	depth = p_depth;
+
+	flags = p_flags;
+}
+
+void Texture3D::create_from_image(const Ref<Image> &p_image, uint32_t p_h_split, uint32_t p_v_split, uint32_t p_num_layer, uint32_t flags) {
+
+	ERR_FAIL_COND(p_image.is_null());
+	ERR_FAIL_COND((p_h_split + 1) * (p_v_split + 1) < p_num_layer);
+
+	uint32_t total_width = p_image->get_width();
+	uint32_t total_height = p_image->get_height();
+
+	uint32_t width = total_width / (p_h_split + 1);
+	uint32_t height = total_height / (p_v_split + 1);
+
+	create(width, height, p_num_layer, p_image->get_format(), flags);
+
+	for (uint32_t i = 0; i < p_num_layer; i++) {
+		uint32_t row = i / (p_v_split + 1);
+		uint32_t col = i % (p_v_split + 1);
+
+		uint32_t x_offset = col * width;
+		uint32_t y_offset = row * height;
+
+		VS::get_singleton()->texture_set_data_partial(texture, p_image, x_offset, y_offset, width, height, 0, 0, 0, i);
+	}
+}
+
+void Texture3D::set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_layer, int p_mipmap) {
+	ERR_FAIL_COND(!texture.is_valid());
+	VS::get_singleton()->texture_set_data_partial(texture, p_image, 0, 0, p_image->get_width(), p_image->get_height(), p_x_ofs, p_y_ofs, p_mipmap, p_layer);
+}
+
+RID Texture3D::get_rid() const {
+	return texture;
+}
+
+void Texture3D::set_path(const String &p_path, bool p_take_over) {
+	if (texture.is_valid()) {
+		VS::get_singleton()->texture_set_path(texture, p_path);
+	}
+
+	Resource::set_path(p_path, p_take_over);
+}
+
+Texture3D::Texture3D() {
+	format = Image::FORMAT_MAX;
+	flags = FLAGS_DEFAULT;
+
+	width = 0;
+	height = 0;
+	depth = 0;
+
+	split_single_image_enabled = false;
+	split_single_image_h_split = 0;
+	split_single_image_v_split = 0;
+	split_single_image_num_layers = 0;
+	split_single_image_image = Ref<Image>();
+
+	texture = VS::get_singleton()->texture_create();
+}
+
+Texture3D::~Texture3D() {
+	if (texture.is_valid()) {
+		VS::get_singleton()->free(texture);
+	}
+}

+ 71 - 0
scene/resources/texture.h

@@ -401,6 +401,77 @@ VARIANT_ENUM_CAST(CubeMap::Flags)
 VARIANT_ENUM_CAST(CubeMap::Side)
 VARIANT_ENUM_CAST(CubeMap::Storage)
 
+class Texture3D : public Resource {
+
+	GDCLASS(Texture3D, Resource)
+	RES_BASE_EXTENSION("tex3d")
+
+public:
+	enum Flags {
+		FLAG_MIPMAPS = VisualServer::TEXTURE_FLAG_MIPMAPS,
+		FLAG_REPEAT = VisualServer::TEXTURE_FLAG_REPEAT,
+		FLAG_FILTER = VisualServer::TEXTURE_FLAG_FILTER,
+		FLAGS_DEFAULT = FLAG_REPEAT | FLAG_FILTER,
+	};
+
+private:
+	RID texture;
+	Image::Format format;
+	uint32_t flags;
+
+	uint32_t width;
+	uint32_t height;
+	uint32_t depth;
+
+	// for setting an image as a property
+	bool split_single_image_enabled;
+
+	uint32_t split_single_image_h_split;
+	uint32_t split_single_image_v_split;
+	uint32_t split_single_image_num_layers;
+	Ref<Image> split_single_image_image;
+
+protected:
+	void _validate_property(PropertyInfo &property) const;
+
+	static void _bind_methods();
+
+public:
+	void set_flags(uint32_t p_flags);
+	uint32_t get_flags() const;
+
+	Image::Format get_format() const;
+	uint32_t get_width() const;
+	uint32_t get_height() const;
+	uint32_t get_depth() const;
+
+	void create(uint32_t p_width, uint32_t p_height, uint32_t p_depth, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT);
+	void create_from_image(const Ref<Image> &p_image, uint32_t p_h_split, uint32_t p_v_split, uint32_t p_num_layer, uint32_t flags = FLAGS_DEFAULT);
+
+	void set_data_partial(const Ref<Image> &p_image, int p_x_ofs, int p_y_ofs, int p_layer, int p_mipmap = 0);
+
+	virtual RID get_rid() const;
+
+	bool get_split_single_image_enabled() const;
+	void set_split_single_image_enabled(bool p_split_enabled);
+
+	uint32_t get_split_single_image_h_split() const;
+	void set_split_single_image_h_split(uint32_t p_h_split);
+	uint32_t get_split_single_image_v_split() const;
+	void set_split_single_image_v_split(uint32_t p_v_split);
+
+	uint32_t get_split_single_image_num_layers() const;
+	void set_split_single_image_num_layers(uint32_t p_num_layers);
+
+	Ref<Image> get_split_single_image_image() const;
+	void set_split_single_image_image(const Ref<Image> &p_image);
+
+	virtual void set_path(const String &p_path, bool p_take_over = false);
+
+	Texture3D();
+	~Texture3D();
+};
+
 class CurveTexture : public Texture {
 
 	GDCLASS(CurveTexture, Texture)

+ 1 - 1
servers/register_server_types.cpp

@@ -73,7 +73,7 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
 		usage.vram = E->get().bytes;
 		usage.id = E->get().texture;
 		usage.type = "Texture";
-		usage.format = itos(E->get().size.width) + "x" + itos(E->get().size.height) + " " + Image::get_format_name(E->get().format);
+		usage.format = itos(E->get().width) + "x" + itos(E->get().height) + " " + Image::get_format_name(E->get().format);
 		r_usage->push_back(usage);
 	}
 }

+ 4 - 3
servers/server_wrap_mt_common.h

@@ -197,9 +197,10 @@
 	}
 
 #define FUNC5RID(m_type, m_arg1, m_arg2, m_arg3, m_arg4, m_arg5)                                               \
-	int m_type##allocn() {                                                                                     \
-		for (int i = 0; i < m_type##_pool_max_size; i++) {                                                     \
-			m_type##_id_pool.push_back(server_name->m_type##_create());                                        \
+	List<RID> m_type##_id_pool;                                                                                \
+	int m_type##allocn(m_arg1 p1, m_arg2 p2, m_arg3 p3, m_arg4 p4, m_arg5 p5) {                                \
+		for (int i = 0; i < pool_max_size; i++) {                                                              \
+			m_type##_id_pool.push_back(server_name->m_type##_create(p1, p2, p3, p4, p5));                      \
 		}                                                                                                      \
 		return 0;                                                                                              \
 	}                                                                                                          \

+ 22 - 5
servers/visual/rasterizer.h

@@ -176,17 +176,34 @@ public:
 	/* TEXTURE API */
 
 	virtual RID texture_create() = 0;
-	virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) = 0;
-	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) = 0;
-	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) = 0;
-	virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const = 0;
+	virtual void texture_allocate(RID p_texture,
+			int p_width,
+			int p_height,
+			int p_depth_3d,
+			Image::Format p_format,
+			VS::TextureType p_type,
+			uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) = 0;
+
+	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_level = 0) = 0;
+
+	virtual void texture_set_data_partial(RID p_texture,
+			const Ref<Image> &p_image,
+			int src_x, int src_y,
+			int src_w, int src_h,
+			int dst_x, int dst_y,
+			int p_dst_mip,
+			int p_level = 0) = 0;
+
+	virtual Ref<Image> texture_get_data(RID p_texture, int p_level = 0) const = 0;
 	virtual void texture_set_flags(RID p_texture, uint32_t p_flags) = 0;
 	virtual uint32_t texture_get_flags(RID p_texture) const = 0;
 	virtual Image::Format texture_get_format(RID p_texture) const = 0;
+	virtual VS::TextureType texture_get_type(RID p_texture) const = 0;
 	virtual uint32_t texture_get_texid(RID p_texture) const = 0;
 	virtual uint32_t texture_get_width(RID p_texture) const = 0;
 	virtual uint32_t texture_get_height(RID p_texture) const = 0;
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
+	virtual uint32_t texture_get_depth(RID p_texture) const = 0;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
 
 	virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
 	virtual String texture_get_path(RID p_texture) const = 0;

+ 87 - 1
servers/visual/shader_language.cpp

@@ -123,6 +123,12 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
 	"TYPE_SAMPLER2D",
 	"TYPE_ISAMPLER2D",
 	"TYPE_USAMPLER2D",
+	"TYPE_SAMPLER2DARRAY",
+	"TYPE_ISAMPLER2DARRAY",
+	"TYPE_USAMPLER2DARRAY",
+	"TYPE_SAMPLER3D",
+	"TYPE_ISAMPLER3D",
+	"TYPE_USAMPLER3D",
 	"TYPE_SAMPLERCUBE",
 	"INTERPOLATION_FLAT",
 	"INTERPOLATION_NO_PERSPECTIVE",
@@ -257,6 +263,12 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
 	{ TK_TYPE_SAMPLER2D, "sampler2D" },
 	{ TK_TYPE_ISAMPLER2D, "isampler2D" },
 	{ TK_TYPE_USAMPLER2D, "usampler2D" },
+	{ TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" },
+	{ TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" },
+	{ TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" },
+	{ TK_TYPE_SAMPLER3D, "sampler3D" },
+	{ TK_TYPE_ISAMPLER3D, "isampler3D" },
+	{ TK_TYPE_USAMPLER3D, "usampler3D" },
 	{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
 	{ TK_INTERPOLATION_FLAT, "flat" },
 	{ TK_INTERPOLATION_NO_PERSPECTIVE, "noperspective" },
@@ -660,6 +672,12 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
 			p_type == TK_TYPE_SAMPLER2D ||
 			p_type == TK_TYPE_ISAMPLER2D ||
 			p_type == TK_TYPE_USAMPLER2D ||
+			p_type == TK_TYPE_SAMPLER2DARRAY ||
+			p_type == TK_TYPE_ISAMPLER2DARRAY ||
+			p_type == TK_TYPE_USAMPLER2DARRAY ||
+			p_type == TK_TYPE_SAMPLER3D ||
+			p_type == TK_TYPE_ISAMPLER3D ||
+			p_type == TK_TYPE_USAMPLER3D ||
 			p_type == TK_TYPE_SAMPLERCUBE);
 }
 
@@ -731,6 +749,12 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
 		case TYPE_SAMPLER2D: return "sampler2D";
 		case TYPE_ISAMPLER2D: return "isampler2D";
 		case TYPE_USAMPLER2D: return "usampler2D";
+		case TYPE_SAMPLER2DARRAY: return "sampler2DArray";
+		case TYPE_ISAMPLER2DARRAY: return "isampler2DArray";
+		case TYPE_USAMPLER2DARRAY: return "usampler2DArray";
+		case TYPE_SAMPLER3D: return "sampler3D";
+		case TYPE_ISAMPLER3D: return "isampler3D";
+		case TYPE_USAMPLER3D: return "usampler3D";
 		case TYPE_SAMPLERCUBE: return "samplerCube";
 	}
 
@@ -1802,6 +1826,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID } },
 	{ "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID } },
 	{ "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID } },
+	{ "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID } },
 	{ "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID } },
 
 	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID } },
@@ -1813,6 +1843,24 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID } },
 	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
 
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID } },
+	{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+
 	{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID } },
 	{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
 
@@ -1831,15 +1879,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
 	{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
 
+	{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+	{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+	{ "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
+	{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID } },
+	{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
+
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
 	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
 	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
+	{ "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
 	{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
 
 	{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
 	{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
 	{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID } },
 
+	{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+	{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+	{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+
+	{ "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+	{ "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+	{ "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID } },
+
 	{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID } },
 	{ "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID } },
 
@@ -1852,6 +1923,12 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
 	{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
 	{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
 	{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+	{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+	{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+	{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
+	{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+	{ "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
+	{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
 	{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
 
 	{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
@@ -2139,7 +2216,16 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) {
 
 bool ShaderLanguage::is_sampler_type(DataType p_type) {
 
-	return p_type == TYPE_SAMPLER2D || p_type == TYPE_ISAMPLER2D || p_type == TYPE_USAMPLER2D || p_type == TYPE_SAMPLERCUBE;
+	return p_type == TYPE_SAMPLER2D ||
+		   p_type == TYPE_ISAMPLER2D ||
+		   p_type == TYPE_USAMPLER2D ||
+		   p_type == TYPE_SAMPLER2DARRAY ||
+		   p_type == TYPE_ISAMPLER2DARRAY ||
+		   p_type == TYPE_USAMPLER2DARRAY ||
+		   p_type == TYPE_SAMPLER3D ||
+		   p_type == TYPE_ISAMPLER3D ||
+		   p_type == TYPE_USAMPLER3D ||
+		   p_type == TYPE_SAMPLERCUBE;
 }
 
 void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {

+ 12 - 0
servers/visual/shader_language.h

@@ -72,6 +72,12 @@ public:
 		TK_TYPE_SAMPLER2D,
 		TK_TYPE_ISAMPLER2D,
 		TK_TYPE_USAMPLER2D,
+		TK_TYPE_SAMPLER2DARRAY,
+		TK_TYPE_ISAMPLER2DARRAY,
+		TK_TYPE_USAMPLER2DARRAY,
+		TK_TYPE_SAMPLER3D,
+		TK_TYPE_ISAMPLER3D,
+		TK_TYPE_USAMPLER3D,
 		TK_TYPE_SAMPLERCUBE,
 		TK_INTERPOLATION_FLAT,
 		TK_INTERPOLATION_NO_PERSPECTIVE,
@@ -186,6 +192,12 @@ public:
 		TYPE_SAMPLER2D,
 		TYPE_ISAMPLER2D,
 		TYPE_USAMPLER2D,
+		TYPE_SAMPLER2DARRAY,
+		TYPE_ISAMPLER2DARRAY,
+		TYPE_USAMPLER2DARRAY,
+		TYPE_SAMPLER3D,
+		TYPE_ISAMPLER3D,
+		TYPE_USAMPLER3D,
 		TYPE_SAMPLERCUBE,
 	};
 

+ 7 - 5
servers/visual/visual_server_raster.h

@@ -148,17 +148,19 @@ public:
 	/* TEXTURE API */
 
 	BIND0R(RID, texture_create)
-	BIND5(texture_allocate, RID, int, int, Image::Format, uint32_t)
-	BIND3(texture_set_data, RID, const Ref<Image> &, CubeMapSide)
-	BIND10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, CubeMapSide)
-	BIND2RC(Ref<Image>, texture_get_data, RID, CubeMapSide)
+	BIND7(texture_allocate, RID, int, int, int, Image::Format, TextureType, uint32_t)
+	BIND3(texture_set_data, RID, const Ref<Image> &, int)
+	BIND10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, int)
+	BIND2RC(Ref<Image>, texture_get_data, RID, int)
 	BIND2(texture_set_flags, RID, uint32_t)
 	BIND1RC(uint32_t, texture_get_flags, RID)
 	BIND1RC(Image::Format, texture_get_format, RID)
+	BIND1RC(TextureType, texture_get_type, RID)
 	BIND1RC(uint32_t, texture_get_texid, RID)
 	BIND1RC(uint32_t, texture_get_width, RID)
 	BIND1RC(uint32_t, texture_get_height, RID)
-	BIND3(texture_set_size_override, RID, int, int)
+	BIND1RC(uint32_t, texture_get_depth, RID)
+	BIND4(texture_set_size_override, RID, int, int, int)
 
 	BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
 	BIND3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)

+ 7 - 5
servers/visual/visual_server_wrap_mt.h

@@ -82,17 +82,19 @@ public:
 
 	/* EVENT QUEUING */
 	FUNCRID(texture)
-	FUNC5(texture_allocate, RID, int, int, Image::Format, uint32_t)
-	FUNC3(texture_set_data, RID, const Ref<Image> &, CubeMapSide)
-	FUNC10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, CubeMapSide)
-	FUNC2RC(Ref<Image>, texture_get_data, RID, CubeMapSide)
+	FUNC7(texture_allocate, RID, int, int, int, Image::Format, TextureType, uint32_t)
+	FUNC3(texture_set_data, RID, const Ref<Image> &, int)
+	FUNC10(texture_set_data_partial, RID, const Ref<Image> &, int, int, int, int, int, int, int, int)
+	FUNC2RC(Ref<Image>, texture_get_data, RID, int)
 	FUNC2(texture_set_flags, RID, uint32_t)
 	FUNC1RC(uint32_t, texture_get_flags, RID)
 	FUNC1RC(Image::Format, texture_get_format, RID)
+	FUNC1RC(TextureType, texture_get_type, RID)
 	FUNC1RC(uint32_t, texture_get_texid, RID)
 	FUNC1RC(uint32_t, texture_get_width, RID)
 	FUNC1RC(uint32_t, texture_get_height, RID)
-	FUNC3(texture_set_size_override, RID, int, int)
+	FUNC1RC(uint32_t, texture_get_depth, RID)
+	FUNC4(texture_set_size_override, RID, int, int, int)
 
 	FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *)
 	FUNC3(texture_set_detect_srgb_callback, RID, TextureDetectCallback, void *)

+ 16 - 8
servers/visual_server.cpp

@@ -55,7 +55,7 @@ RID VisualServer::texture_create_from_image(const Ref<Image> &p_image, uint32_t
 
 	ERR_FAIL_COND_V(!p_image.is_valid(), RID());
 	RID texture = texture_create();
-	texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), p_flags); //if it has mipmaps, use, else generate
+	texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags); //if it has mipmaps, use, else generate
 	ERR_FAIL_COND_V(!texture.is_valid(), texture);
 
 	texture_set_data(texture, p_image);
@@ -72,7 +72,9 @@ Array VisualServer::_texture_debug_usage_bind() {
 
 		Dictionary dict;
 		dict["texture"] = E->get().texture;
-		dict["size"] = E->get().size;
+		dict["width"] = E->get().width;
+		dict["height"] = E->get().height;
+		dict["depth"] = E->get().depth;
 		dict["format"] = E->get().format;
 		dict["bytes"] = E->get().bytes;
 		dict["path"] = E->get().path;
@@ -333,7 +335,7 @@ RID VisualServer::get_white_texture() {
 	}
 	Ref<Image> white = memnew(Image(4, 4, 0, Image::FORMAT_RGB8, wt));
 	white_texture = texture_create();
-	texture_allocate(white_texture, 4, 4, Image::FORMAT_RGB8);
+	texture_allocate(white_texture, 4, 4, 0, Image::FORMAT_RGB8, TEXTURE_TYPE_2D);
 	texture_set_data(white_texture, white);
 	return white_texture;
 }
@@ -1658,17 +1660,19 @@ void VisualServer::_bind_methods() {
 
 	ClassDB::bind_method(D_METHOD("texture_create"), &VisualServer::texture_create);
 	ClassDB::bind_method(D_METHOD("texture_create_from_image", "image", "flags"), &VisualServer::texture_create_from_image, DEFVAL(TEXTURE_FLAGS_DEFAULT));
-	ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "format", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT));
-	ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "cube_side"), &VisualServer::texture_set_data, DEFVAL(CUBEMAP_LEFT));
-	ClassDB::bind_method(D_METHOD("texture_set_data_partial", "texture", "image", "src_x", "src_y", "src_w", "src_h", "dst_x", "dst_y", "dst_mip", "cube_side"), &VisualServer::texture_set_data_partial, DEFVAL(CUBEMAP_LEFT));
+	ClassDB::bind_method(D_METHOD("texture_allocate", "texture", "width", "height", "depth_3d", "format", "type", "flags"), &VisualServer::texture_allocate, DEFVAL(TEXTURE_FLAGS_DEFAULT));
+	ClassDB::bind_method(D_METHOD("texture_set_data", "texture", "image", "layer"), &VisualServer::texture_set_data, DEFVAL(0));
+	ClassDB::bind_method(D_METHOD("texture_set_data_partial", "texture", "image", "src_x", "src_y", "src_w", "src_h", "dst_x", "dst_y", "dst_mip", "layer"), &VisualServer::texture_set_data_partial, DEFVAL(0));
 	ClassDB::bind_method(D_METHOD("texture_get_data", "texture", "cube_side"), &VisualServer::texture_get_data, DEFVAL(CUBEMAP_LEFT));
 	ClassDB::bind_method(D_METHOD("texture_set_flags", "texture", "flags"), &VisualServer::texture_set_flags);
 	ClassDB::bind_method(D_METHOD("texture_get_flags", "texture"), &VisualServer::texture_get_flags);
 	ClassDB::bind_method(D_METHOD("texture_get_format", "texture"), &VisualServer::texture_get_format);
+	ClassDB::bind_method(D_METHOD("texture_get_type", "texture"), &VisualServer::texture_get_type);
 	ClassDB::bind_method(D_METHOD("texture_get_texid", "texture"), &VisualServer::texture_get_texid);
 	ClassDB::bind_method(D_METHOD("texture_get_width", "texture"), &VisualServer::texture_get_width);
 	ClassDB::bind_method(D_METHOD("texture_get_height", "texture"), &VisualServer::texture_get_height);
-	ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &VisualServer::texture_set_size_override);
+	ClassDB::bind_method(D_METHOD("texture_get_depth", "texture"), &VisualServer::texture_get_depth);
+	ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height", "depth"), &VisualServer::texture_set_size_override);
 	ClassDB::bind_method(D_METHOD("texture_set_path", "texture", "path"), &VisualServer::texture_set_path);
 	ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &VisualServer::texture_get_path);
 	ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data", "shrink"), &VisualServer::texture_set_shrink_all_x2_on_set_data);
@@ -2059,13 +2063,17 @@ void VisualServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(CUBEMAP_FRONT);
 	BIND_ENUM_CONSTANT(CUBEMAP_BACK);
 
+	BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D);
+	BIND_ENUM_CONSTANT(TEXTURE_TYPE_CUBEMAP);
+	BIND_ENUM_CONSTANT(TEXTURE_TYPE_2D_ARRAY);
+	BIND_ENUM_CONSTANT(TEXTURE_TYPE_3D);
+
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIPMAPS);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_REPEAT);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_FILTER);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_ANISOTROPIC_FILTER);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_CONVERT_TO_LINEAR);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_MIRRORED_REPEAT);
-	BIND_ENUM_CONSTANT(TEXTURE_FLAG_CUBEMAP);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAG_USED_FOR_STREAMING);
 	BIND_ENUM_CONSTANT(TEXTURE_FLAGS_DEFAULT);
 

+ 33 - 8
servers/visual_server.h

@@ -90,11 +90,17 @@ public:
 		TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
 		TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
 		TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
-		TEXTURE_FLAG_CUBEMAP = 2048,
-		TEXTURE_FLAG_USED_FOR_STREAMING = 4096,
+		TEXTURE_FLAG_USED_FOR_STREAMING = 2048,
 		TEXTURE_FLAGS_DEFAULT = TEXTURE_FLAG_REPEAT | TEXTURE_FLAG_MIPMAPS | TEXTURE_FLAG_FILTER
 	};
 
+	enum TextureType {
+		TEXTURE_TYPE_2D,
+		TEXTURE_TYPE_CUBEMAP,
+		TEXTURE_TYPE_2D_ARRAY,
+		TEXTURE_TYPE_3D,
+	};
+
 	enum CubeMapSide {
 
 		CUBEMAP_LEFT,
@@ -107,17 +113,33 @@ public:
 
 	virtual RID texture_create() = 0;
 	RID texture_create_from_image(const Ref<Image> &p_image, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT); // helper
-	virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = TEXTURE_FLAGS_DEFAULT) = 0;
-	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, CubeMapSide p_cube_side = CUBEMAP_LEFT) = 0;
-	virtual void texture_set_data_partial(RID p_texture, const Ref<Image> &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, CubeMapSide p_cube_side = CUBEMAP_LEFT) = 0;
-	virtual Ref<Image> texture_get_data(RID p_texture, CubeMapSide p_cube_side = CUBEMAP_LEFT) const = 0;
+	virtual void texture_allocate(RID p_texture,
+			int p_width,
+			int p_height,
+			int p_depth_3d,
+			Image::Format p_format,
+			TextureType p_type,
+			uint32_t p_flags = TEXTURE_FLAGS_DEFAULT) = 0;
+
+	virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, int p_layer = 0) = 0;
+	virtual void texture_set_data_partial(RID p_texture,
+			const Ref<Image> &p_image,
+			int src_x, int src_y,
+			int src_w, int src_h,
+			int dst_x, int dst_y,
+			int p_dst_mip,
+			int p_layer = 0) = 0;
+
+	virtual Ref<Image> texture_get_data(RID p_texture, int p_layer = 0) const = 0;
 	virtual void texture_set_flags(RID p_texture, uint32_t p_flags) = 0;
 	virtual uint32_t texture_get_flags(RID p_texture) const = 0;
 	virtual Image::Format texture_get_format(RID p_texture) const = 0;
+	virtual TextureType texture_get_type(RID p_texture) const = 0;
 	virtual uint32_t texture_get_texid(RID p_texture) const = 0;
 	virtual uint32_t texture_get_width(RID p_texture) const = 0;
 	virtual uint32_t texture_get_height(RID p_texture) const = 0;
-	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
+	virtual uint32_t texture_get_depth(RID p_texture) const = 0;
+	virtual void texture_set_size_override(RID p_texture, int p_width, int p_height, int p_depth_3d) = 0;
 
 	virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
 	virtual String texture_get_path(RID p_texture) const = 0;
@@ -132,7 +154,9 @@ public:
 
 	struct TextureInfo {
 		RID texture;
-		Size2 size;
+		uint32_t width;
+		uint32_t height;
+		uint32_t depth;
 		Image::Format format;
 		int bytes;
 		String path;
@@ -1054,6 +1078,7 @@ VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOQuality);
 VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOBlur);
 VARIANT_ENUM_CAST(VisualServer::InstanceFlags);
 VARIANT_ENUM_CAST(VisualServer::ShadowCastingSetting);
+VARIANT_ENUM_CAST(VisualServer::TextureType);
 
 //typedef VisualServer VS; // makes it easier to use
 #define VS VisualServer