Merge pull request #36342 from m4gr3d/external_texture_support_for_godot_3_2

Add support for opengl external textures
This commit is contained in:
Rémi Verschelde 2020-03-17 16:29:14 +01:00 committed by GitHub
commit cc70b2fa0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 401 additions and 57 deletions

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ExternalTexture" inherits="Texture" category="Core" version="3.2">
<brief_description>
Adds support for external textures as defined by https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
<method name="get_external_texture_id" qualifiers="const">
<return type="int"/>
<description>
Returns the external texture name.
</description>
</method>
</methods>
<members>
<member name="size" type="Vector2" setter="set_size" getter="get_size" default="Vector2( 1, 1 )">
External texture size.
</member>
</members>
<constants>
</constants>
</class>

View file

@ -55,6 +55,10 @@
<member name="code" type="String" setter="set_code" getter="get_code" default="&quot;&quot;">
Returns the shader's code as the user has written it, not the full generated code used internally.
</member>
<member name="custom_defines" type="String" setter="set_custom_defines" getter="get_custom_defines" default="&quot;&quot;">
Returns the shader's custom defines. Custom defines can be used in Godot to add GLSL preprocessor directives (e.g: extensions) required for the shader logic.
[b]Note:[/b] Custom defines are not validated by the Godot shader parser, so care should be taken when using them.
</member>
</members>
<constants>
<constant name="MODE_SPATIAL" value="0" enum="Mode">

View file

@ -262,6 +262,10 @@ public:
void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) {}
RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { return RID(); }
void shader_add_custom_define(RID p_shader, const String &p_define) {}
void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const {}
void shader_clear_custom_defines(RID p_shader) {}
/* COMMON MATERIAL API */
RID material_create() { return RID(); }

View file

@ -69,6 +69,8 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
#ifdef GLES_OVER_GL
#define _GL_HALF_FLOAT_OES 0x140B
#else
@ -562,6 +564,10 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_2D;
texture->images.resize(1);
} break;
case VS::TEXTURE_TYPE_EXTERNAL: {
texture->target = _GL_TEXTURE_EXTERNAL_OES;
texture->images.resize(0);
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6);
@ -578,44 +584,59 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
}
}
texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
texture->resize_to_po2 = false;
if (!config.support_npot_repeat_mipmap) {
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);
if (p_type != VS::TEXTURE_TYPE_EXTERNAL) {
texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
texture->resize_to_po2 = false;
if (!config.support_npot_repeat_mipmap) {
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);
bool is_po2 = p_width == po2_width && p_height == po2_height;
bool is_po2 = p_width == po2_width && p_height == po2_height;
if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//not supported
ERR_PRINTS("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS);
} else {
texture->alloc_height = po2_height;
texture->alloc_width = po2_width;
texture->resize_to_po2 = true;
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//not supported
ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled.");
texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS);
} else {
texture->alloc_height = po2_height;
texture->alloc_width = po2_width;
texture->resize_to_po2 = true;
}
}
}
Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(),
texture->format,
texture->flags,
real_format,
format,
internal_format,
type,
compressed,
texture->resize_to_po2);
texture->gl_format_cache = format;
texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format;
texture->data_size = 0;
texture->mipmaps = 1;
texture->compressed = compressed;
}
Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2);
texture->gl_format_cache = format;
texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format;
texture->data_size = 0;
texture->mipmaps = 1;
texture->compressed = compressed;
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
if (p_type == VS::TEXTURE_TYPE_EXTERNAL) {
glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//prealloc if video
glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
}
@ -635,6 +656,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &p
ERR_FAIL_COND(texture->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format());
ERR_FAIL_COND(p_image.is_null());
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type;
GLenum format;
@ -1624,6 +1646,7 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
} break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_SAMPLEREXT:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
pi.type = Variant::OBJECT;
@ -1680,6 +1703,34 @@ RID RasterizerStorageGLES2::shader_get_default_texture_param(RID p_shader, const
return E->get();
}
void RasterizerStorageGLES2::shader_add_custom_define(RID p_shader, const String &p_define) {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->add_custom_define(p_define);
_shader_make_dirty(shader);
}
void RasterizerStorageGLES2::shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->get_custom_defines(p_defines);
}
void RasterizerStorageGLES2::shader_clear_custom_defines(RID p_shader) {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->clear_custom_defines();
_shader_make_dirty(shader);
}
/* COMMON MATERIAL API */
void RasterizerStorageGLES2::_material_make_dirty(Material *p_material) const {

View file

@ -525,6 +525,10 @@ public:
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
virtual void shader_add_custom_define(RID p_shader, const String &p_define);
virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const;
virtual void shader_clear_custom_defines(RID p_shader);
void _update_shader(Shader *p_shader) const;
void update_dirty_shaders();

View file

@ -656,7 +656,8 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener
if (var_node->name == "texture") {
// emit texture call
if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D) {
if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLER2D ||
op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLEREXT) {
code += "texture2D";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCube";

View file

@ -182,6 +182,16 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
#endif
#ifdef ANDROID_ENABLED
strings.push_back("#define ANDROID_ENABLED\n");
#endif
for (int i = 0; i < custom_defines.size(); i++) {
strings.push_back(custom_defines[i].get_data());
strings.push_back("\n");
}
for (int j = 0; j < conditional_count; j++) {
bool enable = (conditional_version.version & (1 << j)) > 0;
@ -941,6 +951,10 @@ void ShaderGLES2::use_material(void *p_material) {
} break;
case ShaderLanguage::TYPE_SAMPLEREXT: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: {
} break;
@ -1060,6 +1074,10 @@ void ShaderGLES2::use_material(void *p_material) {
} break;
case ShaderLanguage::TYPE_SAMPLEREXT: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: {
} break;

View file

@ -246,6 +246,16 @@ public:
custom_defines.push_back(p_define.utf8());
}
void get_custom_defines(Vector<String> *p_defines) {
for (int i = 0; i < custom_defines.size(); i++) {
p_defines->push_back(custom_defines[i].get_data());
}
}
void clear_custom_defines() {
custom_defines.clear();
}
virtual ~ShaderGLES2();
};

View file

@ -101,6 +101,8 @@
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
#ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf
#endif
@ -663,6 +665,10 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_2D;
texture->images.resize(1);
} break;
case VS::TEXTURE_TYPE_EXTERNAL: {
texture->target = _GL_TEXTURE_EXTERNAL_OES;
texture->images.resize(0);
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6);
@ -677,39 +683,55 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
} break;
}
texture->is_npot_repeat_mipmap = false;
if (p_type != VS::TEXTURE_TYPE_EXTERNAL) {
texture->is_npot_repeat_mipmap = false;
#ifdef JAVASCRIPT_ENABLED
// WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT)
// textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec.
// Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058).
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);
bool is_po2 = p_width == po2_width && p_height == po2_height;
// WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT)
// textures with repeat/mipmaps, even though NPOT textures should be supported as per the spec.
// Force decompressing them to work it around on WebGL 2.0 at a performance cost (GH-33058).
int po2_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height);
bool is_po2 = p_width == po2_width && p_height == po2_height;
if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
texture->is_npot_repeat_mipmap = true;
}
if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) {
texture->is_npot_repeat_mipmap = true;
}
#endif // JAVASCRIPT_ENABLED
Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, real_format, format, internal_format, type, compressed, srgb, texture->is_npot_repeat_mipmap);
Image::Format real_format;
_get_gl_image_and_format(Ref<Image>(),
texture->format,
texture->flags,
real_format,
format,
internal_format,
type,
compressed,
srgb,
texture->is_npot_repeat_mipmap);
texture->alloc_width = texture->width;
texture->alloc_height = texture->height;
texture->alloc_depth = texture->depth;
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;
texture->gl_internal_format_cache = internal_format;
texture->compressed = compressed;
texture->srgb = srgb;
texture->data_size = 0;
texture->mipmaps = 1;
texture->gl_format_cache = format;
texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format;
texture->compressed = compressed;
texture->srgb = srgb;
texture->data_size = 0;
texture->mipmaps = 1;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id);
if (p_type == VS::TEXTURE_TYPE_3D || p_type == VS::TEXTURE_TYPE_2D_ARRAY) {
if (p_type == VS::TEXTURE_TYPE_EXTERNAL) {
glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else if (p_type == VS::TEXTURE_TYPE_3D || p_type == VS::TEXTURE_TYPE_2D_ARRAY) {
int width = p_width;
int height = p_height;
@ -757,6 +779,7 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
ERR_FAIL_COND(texture->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format());
ERR_FAIL_COND(p_image.is_null());
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type;
GLenum format;
@ -788,7 +811,8 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
GLenum blit_target = GL_TEXTURE_2D;
switch (texture->type) {
case VS::TEXTURE_TYPE_2D: {
case VS::TEXTURE_TYPE_2D:
case VS::TEXTURE_TYPE_EXTERNAL: {
blit_target = GL_TEXTURE_2D;
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
@ -989,6 +1013,7 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
ERR_FAIL_COND(src_x < 0 || src_y < 0 || src_x + src_w > p_image->get_width() || src_y + src_h > p_image->get_height());
ERR_FAIL_COND(dst_x < 0 || dst_y < 0 || dst_x + src_w > texture->alloc_width || dst_y + src_h > texture->alloc_height);
ERR_FAIL_COND(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps);
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type;
GLenum format;
@ -1008,7 +1033,8 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
GLenum blit_target = GL_TEXTURE_2D;
switch (texture->type) {
case VS::TEXTURE_TYPE_2D: {
case VS::TEXTURE_TYPE_2D:
case VS::TEXTURE_TYPE_EXTERNAL: {
blit_target = GL_TEXTURE_2D;
} break;
case VS::TEXTURE_TYPE_CUBEMAP: {
@ -2466,6 +2492,7 @@ void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyIn
case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break;
case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break;
case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_SAMPLEREXT:
case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: {
@ -2524,6 +2551,34 @@ RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const
return E->get();
}
void RasterizerStorageGLES3::shader_add_custom_define(RID p_shader, const String &p_define) {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->add_custom_define(p_define);
_shader_make_dirty(shader);
}
void RasterizerStorageGLES3::shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->get_custom_defines(p_defines);
}
void RasterizerStorageGLES3::shader_clear_custom_defines(RID p_shader) {
Shader *shader = shader_owner.get(p_shader);
ERR_FAIL_COND(!shader);
shader->shader->clear_custom_defines();
_shader_make_dirty(shader);
}
/* COMMON MATERIAL API */
void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const {

View file

@ -533,6 +533,10 @@ public:
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture);
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const;
virtual void shader_add_custom_define(RID p_shader, const String &p_define);
virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const;
virtual void shader_clear_custom_defines(RID p_shader);
void _update_shader(Shader *p_shader) const;
void update_dirty_shaders();

View file

@ -86,6 +86,7 @@ static int _get_datatype_size(SL::DataType p_type) {
case SL::TYPE_ISAMPLER3D: return 16;
case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16;
case SL::TYPE_SAMPLEREXT: return 16;
}
ERR_FAIL_V(0);
@ -125,6 +126,7 @@ static int _get_datatype_alignment(SL::DataType p_type) {
case SL::TYPE_ISAMPLER3D: return 16;
case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16;
case SL::TYPE_SAMPLEREXT: return 16;
}
ERR_FAIL_V(0);

View file

@ -210,9 +210,14 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() {
strings.push_back("#version 300 es\n");
#endif
#ifdef ANDROID_ENABLED
strings.push_back("#define ANDROID_ENABLED\n");
#endif
for (int i = 0; i < custom_defines.size(); i++) {
strings.push_back(custom_defines[i].get_data());
strings.push_back("\n");
}
for (int j = 0; j < conditional_count; j++) {

View file

@ -368,6 +368,16 @@ public:
custom_defines.push_back(p_define.utf8());
}
void get_custom_defines(Vector<String> *p_defines) {
for (int i = 0; i < custom_defines.size(); i++) {
p_defines->push_back(custom_defines[i].get_data());
}
}
void clear_custom_defines() {
custom_defines.clear();
}
virtual ~ShaderGLES3();
};

View file

@ -658,6 +658,7 @@ void register_scene_types() {
ClassDB::register_class<ProxyTexture>();
ClassDB::register_class<AnimatedTexture>();
ClassDB::register_class<CameraTexture>();
ClassDB::register_class<ExternalTexture>();
ClassDB::register_class<CubeMap>();
ClassDB::register_virtual_class<TextureLayered>();
ClassDB::register_class<Texture3D>();

View file

@ -127,6 +127,27 @@ void Shader::get_default_texture_param_list(List<StringName> *r_textures) const
}
}
void Shader::set_custom_defines(const String &p_defines) {
VS::get_singleton()->shader_clear_custom_defines(shader);
VS::get_singleton()->shader_add_custom_define(shader, p_defines);
}
String Shader::get_custom_defines() {
Vector<String> custom_defines;
VS::get_singleton()->shader_get_custom_defines(shader, &custom_defines);
String concatenated_defines;
for (int i = 0; i < custom_defines.size(); i++) {
if (i != 0) {
concatenated_defines += "\n";
}
concatenated_defines += custom_defines[i];
}
return concatenated_defines;
}
bool Shader::is_text_shader() const {
return true;
}
@ -149,11 +170,15 @@ void Shader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_texture_param", "param", "texture"), &Shader::set_default_texture_param);
ClassDB::bind_method(D_METHOD("get_default_texture_param", "param"), &Shader::get_default_texture_param);
ClassDB::bind_method(D_METHOD("set_custom_defines", "custom_defines"), &Shader::set_custom_defines);
ClassDB::bind_method(D_METHOD("get_custom_defines"), &Shader::get_custom_defines);
ClassDB::bind_method(D_METHOD("has_param", "name"), &Shader::has_param);
//ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_code", "get_code");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "custom_defines", PROPERTY_HINT_MULTILINE_TEXT), "set_custom_defines", "get_custom_defines");
BIND_ENUM_CONSTANT(MODE_SPATIAL);
BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM);

View file

@ -79,6 +79,9 @@ public:
Ref<Texture> get_default_texture_param(const StringName &p_param) const;
void get_default_texture_param_list(List<StringName> *r_textures) const;
void set_custom_defines(const String &p_defines);
String get_custom_defines();
virtual bool is_text_shader() const;
_FORCE_INLINE_ StringName remap_param(const StringName &p_param) const {

View file

@ -2621,3 +2621,64 @@ CameraTexture::CameraTexture() {
CameraTexture::~CameraTexture() {
// nothing to do here yet
}
void ExternalTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_size", "size"), &ExternalTexture::set_size);
ClassDB::bind_method(D_METHOD("get_external_texture_id"), &ExternalTexture::get_external_texture_id);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
}
uint32_t ExternalTexture::get_external_texture_id() {
return VisualServer::get_singleton()->texture_get_texid(texture);
}
void ExternalTexture::set_size(const Size2 &p_size) {
if (p_size.width > 0 && p_size.height > 0) {
size = p_size;
VisualServer::get_singleton()->texture_set_size_override(texture, size.width, size.height, 0);
}
}
int ExternalTexture::get_width() const {
return size.width;
}
int ExternalTexture::get_height() const {
return size.height;
}
Size2 ExternalTexture::get_size() const {
return size;
}
RID ExternalTexture::get_rid() const {
return texture;
}
bool ExternalTexture::has_alpha() const {
return true;
}
void ExternalTexture::set_flags(uint32_t p_flags) {
// not supported
}
uint32_t ExternalTexture::get_flags() const {
// not supported
return 0;
}
ExternalTexture::ExternalTexture() {
size = Size2(1.0, 1.0);
texture = VisualServer::get_singleton()->texture_create();
VisualServer::get_singleton()->texture_allocate(texture, size.width, size.height, 0, Image::FORMAT_RGBA8, VS::TEXTURE_TYPE_EXTERNAL, 0);
_change_notify();
emit_changed();
}
ExternalTexture::~ExternalTexture() {
VisualServer::get_singleton()->free(texture);
}

View file

@ -772,4 +772,34 @@ public:
~CameraTexture();
};
// External textures as defined by https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
class ExternalTexture : public Texture {
GDCLASS(ExternalTexture, Texture);
private:
RID texture;
Size2 size;
protected:
static void _bind_methods();
public:
uint32_t get_external_texture_id();
virtual Size2 get_size() const;
void set_size(const Size2 &p_size);
virtual int get_width() const;
virtual int get_height() const;
virtual RID get_rid() const;
virtual bool has_alpha() const;
virtual void set_flags(uint32_t p_flags);
virtual uint32_t get_flags() const;
ExternalTexture();
~ExternalTexture();
};
#endif

View file

@ -242,6 +242,10 @@ public:
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
virtual void shader_add_custom_define(RID p_shader, const String &p_define) = 0;
virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const = 0;
virtual void shader_clear_custom_defines(RID p_shader) = 0;
/* COMMON MATERIAL API */
virtual RID material_create() = 0;

View file

@ -132,6 +132,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_ISAMPLER3D",
"TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE",
"TYPE_SAMPLEREXT",
"INTERPOLATION_FLAT",
"INTERPOLATION_SMOOTH",
"CONST",
@ -272,6 +273,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_ISAMPLER3D, "isampler3D" },
{ TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_TYPE_SAMPLEREXT, "samplerExternalOES" },
{ TK_INTERPOLATION_FLAT, "flat" },
{ TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_CONST, "const" },
@ -755,7 +757,8 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
p_type == TK_TYPE_SAMPLER3D ||
p_type == TK_TYPE_ISAMPLER3D ||
p_type == TK_TYPE_USAMPLER3D ||
p_type == TK_TYPE_SAMPLERCUBE);
p_type == TK_TYPE_SAMPLERCUBE ||
p_type == TK_TYPE_SAMPLEREXT);
}
ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) {
@ -841,6 +844,7 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
case TYPE_ISAMPLER3D: return "isampler3D";
case TYPE_USAMPLER3D: return "usampler3D";
case TYPE_SAMPLERCUBE: return "samplerCube";
case TYPE_SAMPLEREXT: return "samplerExternalOES";
}
return "";
@ -1983,6 +1987,8 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
@ -2002,6 +2008,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLEREXT, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
@ -2452,7 +2462,8 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLER3D ||
p_type == TYPE_ISAMPLER3D ||
p_type == TYPE_USAMPLER3D ||
p_type == TYPE_SAMPLERCUBE;
p_type == TYPE_SAMPLERCUBE ||
p_type == TYPE_SAMPLEREXT;
}
Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) {
@ -2546,7 +2557,8 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER3D:
case ShaderLanguage::TYPE_SAMPLERCUBE: {
case ShaderLanguage::TYPE_SAMPLERCUBE:
case ShaderLanguage::TYPE_SAMPLEREXT: {
// Texture types, likely not relevant here.
break;
}

View file

@ -79,6 +79,7 @@ public:
TK_TYPE_ISAMPLER3D,
TK_TYPE_USAMPLER3D,
TK_TYPE_SAMPLERCUBE,
TK_TYPE_SAMPLEREXT,
TK_INTERPOLATION_FLAT,
TK_INTERPOLATION_SMOOTH,
TK_CONST,
@ -200,6 +201,7 @@ public:
TYPE_ISAMPLER3D,
TYPE_USAMPLER3D,
TYPE_SAMPLERCUBE,
TYPE_SAMPLEREXT,
};
enum DataPrecision {

View file

@ -190,6 +190,10 @@ public:
BIND3(shader_set_default_texture_param, RID, const StringName &, RID)
BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
BIND2(shader_add_custom_define, RID, const String &)
BIND2C(shader_get_custom_defines, RID, Vector<String> *)
BIND1(shader_clear_custom_defines, RID)
/* COMMON MATERIAL API */
BIND0R(RID, material_create)

View file

@ -126,6 +126,10 @@ public:
FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
FUNC2(shader_add_custom_define, RID, const String &)
FUNC2SC(shader_get_custom_defines, RID, Vector<String> *)
FUNC1(shader_clear_custom_defines, RID)
/* COMMON MATERIAL API */
FUNCRID(material)

View file

@ -93,6 +93,7 @@ public:
enum TextureType {
TEXTURE_TYPE_2D,
TEXTURE_TYPE_EXTERNAL,
TEXTURE_TYPE_CUBEMAP,
TEXTURE_TYPE_2D_ARRAY,
TEXTURE_TYPE_3D,
@ -193,6 +194,10 @@ public:
virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
virtual void shader_add_custom_define(RID p_shader, const String &p_define) = 0;
virtual void shader_get_custom_defines(RID p_shader, Vector<String> *p_defines) const = 0;
virtual void shader_clear_custom_defines(RID p_shader) = 0;
/* COMMON MATERIAL API */
enum {