add 3D textures

This commit is contained in:
Thomas Herzog 2018-06-26 13:59:26 +02:00 committed by karroffel
parent 5a5614e8ad
commit b4d3f541e7
23 changed files with 817 additions and 144 deletions

View file

@ -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);

View file

@ -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());

View file

@ -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);
}

View file

@ -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;

View file

@ -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());

View file

@ -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,12 +1199,39 @@ 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
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);
}
#endif
#ifdef TOOLS_ENABLED
if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
t->detect_normal(t->detect_normal_ud);
}
#endif
if (t->render_target)
t->render_target->used_in_frame = true;
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]) {
@ -1223,30 +1251,34 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material *p_m
} break;
}
} else {
} break;
if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
VisualServerRaster::redraw_request();
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;
}
t = t->get_ptr(); //resolve for proxies
} break;
#ifdef TOOLS_ENABLED
if (t->detect_3d) {
t->detect_3d(t->detect_3d_ud);
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
// TODO
} break;
}
#endif
#ifdef TOOLS_ENABLED
if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
t->detect_normal(t->detect_normal_ud);
}
#endif
if (t->render_target)
t->render_target->used_in_frame = true;
target = t->target;
tex = t->tex_id;
}
glBindTexture(target, tex);

View file

@ -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,6 +846,8 @@ 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->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) {
if (texture->compressed) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
@ -801,6 +864,20 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]);
}
}
} else {
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 {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage3D(blit_target, i, 0, 0, p_layer, w, h, 1, format, type, &read[ofs]);
}
}
tsize += size;
w = MAX(1, w >> 1);
@ -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,6 +965,7 @@ 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->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]);
@ -878,9 +975,28 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
// `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 {
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);

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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>();

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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; \
} \

View file

@ -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;

View file

@ -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) {

View file

@ -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,
};

View file

@ -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 *)

View file

@ -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 *)

View file

@ -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);

View file

@ -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