This commit is contained in:
fhuya 2020-01-18 23:14:10 -08:00
parent ea2e976cdd
commit 30d738eda7
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;"> <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. Returns the shader's code as the user has written it, not the full generated code used internally.
</member> </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> </members>
<constants> <constants>
<constant name="MODE_SPATIAL" value="0" enum="Mode"> <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) {} 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(); } 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 */ /* COMMON MATERIAL API */
RID material_create() { return RID(); } 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_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
#ifdef GLES_OVER_GL #ifdef GLES_OVER_GL
#define _GL_HALF_FLOAT_OES 0x140B #define _GL_HALF_FLOAT_OES 0x140B
#else #else
@ -562,6 +564,10 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_2D; texture->target = GL_TEXTURE_2D;
texture->images.resize(1); texture->images.resize(1);
} break; } break;
case VS::TEXTURE_TYPE_EXTERNAL: {
texture->target = _GL_TEXTURE_EXTERNAL_OES;
texture->images.resize(0);
} break;
case VS::TEXTURE_TYPE_CUBEMAP: { case VS::TEXTURE_TYPE_CUBEMAP: {
texture->target = GL_TEXTURE_CUBE_MAP; texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6); 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; if (p_type != VS::TEXTURE_TYPE_EXTERNAL) {
texture->alloc_height = texture->height; texture->alloc_width = texture->width;
texture->resize_to_po2 = false; texture->alloc_height = texture->height;
if (!config.support_npot_repeat_mipmap) { texture->resize_to_po2 = false;
int po2_width = next_power_of_2(p_width); if (!config.support_npot_repeat_mipmap) {
int po2_height = next_power_of_2(p_height); 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) { if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) {
//not supported //not supported
ERR_PRINTS("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); 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); texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS);
} else { } else {
texture->alloc_height = po2_height; texture->alloc_height = po2_height;
texture->alloc_width = po2_width; texture->alloc_width = po2_width;
texture->resize_to_po2 = true; 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); glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id); glBindTexture(texture->target, texture->tex_id);
if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { if (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 //prealloc if video
glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL);
} }
@ -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->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format()); ERR_FAIL_COND(texture->format != p_image->get_format());
ERR_FAIL_COND(p_image.is_null()); ERR_FAIL_COND(p_image.is_null());
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type; GLenum type;
GLenum format; GLenum format;
@ -1624,6 +1646,7 @@ void RasterizerStorageGLES2::shader_get_param_list(RID p_shader, List<PropertyIn
} break; } break;
case ShaderLanguage::TYPE_SAMPLER2D: case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_SAMPLEREXT:
case ShaderLanguage::TYPE_ISAMPLER2D: case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: { case ShaderLanguage::TYPE_USAMPLER2D: {
pi.type = Variant::OBJECT; pi.type = Variant::OBJECT;
@ -1680,6 +1703,34 @@ RID RasterizerStorageGLES2::shader_get_default_texture_param(RID p_shader, const
return E->get(); 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 */ /* COMMON MATERIAL API */
void RasterizerStorageGLES2::_material_make_dirty(Material *p_material) const { 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 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 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_shader(Shader *p_shader) const;
void update_dirty_shaders(); 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") { if (var_node->name == "texture") {
// emit texture call // 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"; code += "texture2D";
} else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) { } else if (op_node->arguments[1]->get_datatype() == SL::TYPE_SAMPLERCUBE) {
code += "textureCube"; code += "textureCube";

View file

@ -182,6 +182,16 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
#endif #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++) { for (int j = 0; j < conditional_count; j++) {
bool enable = (conditional_version.version & (1 << j)) > 0; bool enable = (conditional_version.version & (1 << j)) > 0;
@ -941,6 +951,10 @@ void ShaderGLES2::use_material(void *p_material) {
} break; } break;
case ShaderLanguage::TYPE_SAMPLEREXT: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: { case ShaderLanguage::TYPE_ISAMPLER2D: {
} break; } break;
@ -1060,6 +1074,10 @@ void ShaderGLES2::use_material(void *p_material) {
} break; } break;
case ShaderLanguage::TYPE_SAMPLEREXT: {
} break;
case ShaderLanguage::TYPE_ISAMPLER2D: { case ShaderLanguage::TYPE_ISAMPLER2D: {
} break; } break;

View file

@ -246,6 +246,16 @@ public:
custom_defines.push_back(p_define.utf8()); 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(); virtual ~ShaderGLES2();
}; };

View file

@ -101,6 +101,8 @@
#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E #define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F #define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define _GL_TEXTURE_EXTERNAL_OES 0x8D65
#ifndef GLES_OVER_GL #ifndef GLES_OVER_GL
#define glClearDepth glClearDepthf #define glClearDepth glClearDepthf
#endif #endif
@ -663,6 +665,10 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
texture->target = GL_TEXTURE_2D; texture->target = GL_TEXTURE_2D;
texture->images.resize(1); texture->images.resize(1);
} break; } break;
case VS::TEXTURE_TYPE_EXTERNAL: {
texture->target = _GL_TEXTURE_EXTERNAL_OES;
texture->images.resize(0);
} break;
case VS::TEXTURE_TYPE_CUBEMAP: { case VS::TEXTURE_TYPE_CUBEMAP: {
texture->target = GL_TEXTURE_CUBE_MAP; texture->target = GL_TEXTURE_CUBE_MAP;
texture->images.resize(6); texture->images.resize(6);
@ -677,39 +683,55 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_
} break; } break;
} }
texture->is_npot_repeat_mipmap = false; if (p_type != VS::TEXTURE_TYPE_EXTERNAL) {
texture->is_npot_repeat_mipmap = false;
#ifdef JAVASCRIPT_ENABLED #ifdef JAVASCRIPT_ENABLED
// WebGL 2.0 on browsers does not seem to properly support compressed non power-of-two (NPOT) // 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. // 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). // 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_width = next_power_of_2(p_width);
int po2_height = next_power_of_2(p_height); 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)) {
texture->is_npot_repeat_mipmap = true; texture->is_npot_repeat_mipmap = true;
} }
#endif // JAVASCRIPT_ENABLED #endif // JAVASCRIPT_ENABLED
Image::Format real_format; 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); _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_width = texture->width;
texture->alloc_height = texture->height; texture->alloc_height = texture->height;
texture->alloc_depth = texture->depth; texture->alloc_depth = texture->depth;
texture->gl_format_cache = format; texture->gl_format_cache = format;
texture->gl_type_cache = type; texture->gl_type_cache = type;
texture->gl_internal_format_cache = internal_format; texture->gl_internal_format_cache = internal_format;
texture->compressed = compressed; texture->compressed = compressed;
texture->srgb = srgb; texture->srgb = srgb;
texture->data_size = 0; texture->data_size = 0;
texture->mipmaps = 1; texture->mipmaps = 1;
}
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(texture->target, texture->tex_id); 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 width = p_width;
int height = p_height; 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->render_target);
ERR_FAIL_COND(texture->format != p_image->get_format()); ERR_FAIL_COND(texture->format != p_image->get_format());
ERR_FAIL_COND(p_image.is_null()); ERR_FAIL_COND(p_image.is_null());
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type; GLenum type;
GLenum format; GLenum format;
@ -788,7 +811,8 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p
GLenum blit_target = GL_TEXTURE_2D; GLenum blit_target = GL_TEXTURE_2D;
switch (texture->type) { switch (texture->type) {
case VS::TEXTURE_TYPE_2D: { case VS::TEXTURE_TYPE_2D:
case VS::TEXTURE_TYPE_EXTERNAL: {
blit_target = GL_TEXTURE_2D; blit_target = GL_TEXTURE_2D;
} break; } break;
case VS::TEXTURE_TYPE_CUBEMAP: { 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(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(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(p_dst_mip < 0 || p_dst_mip >= texture->mipmaps);
ERR_FAIL_COND(texture->type == VS::TEXTURE_TYPE_EXTERNAL);
GLenum type; GLenum type;
GLenum format; GLenum format;
@ -1008,7 +1033,8 @@ void RasterizerStorageGLES3::texture_set_data_partial(RID p_texture, const Ref<I
GLenum blit_target = GL_TEXTURE_2D; GLenum blit_target = GL_TEXTURE_2D;
switch (texture->type) { switch (texture->type) {
case VS::TEXTURE_TYPE_2D: { case VS::TEXTURE_TYPE_2D:
case VS::TEXTURE_TYPE_EXTERNAL: {
blit_target = GL_TEXTURE_2D; blit_target = GL_TEXTURE_2D;
} break; } break;
case VS::TEXTURE_TYPE_CUBEMAP: { 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_MAT3: pi.type = Variant::BASIS; break;
case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break; case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break;
case ShaderLanguage::TYPE_SAMPLER2D: case ShaderLanguage::TYPE_SAMPLER2D:
case ShaderLanguage::TYPE_SAMPLEREXT:
case ShaderLanguage::TYPE_ISAMPLER2D: case ShaderLanguage::TYPE_ISAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER2D: { case ShaderLanguage::TYPE_USAMPLER2D: {
@ -2524,6 +2551,34 @@ RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const
return E->get(); 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 */ /* COMMON MATERIAL API */
void RasterizerStorageGLES3::_material_make_dirty(Material *p_material) const { 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 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 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_shader(Shader *p_shader) const;
void update_dirty_shaders(); 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_ISAMPLER3D: return 16;
case SL::TYPE_USAMPLER3D: return 16; case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16; case SL::TYPE_SAMPLERCUBE: return 16;
case SL::TYPE_SAMPLEREXT: return 16;
} }
ERR_FAIL_V(0); 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_ISAMPLER3D: return 16;
case SL::TYPE_USAMPLER3D: return 16; case SL::TYPE_USAMPLER3D: return 16;
case SL::TYPE_SAMPLERCUBE: return 16; case SL::TYPE_SAMPLERCUBE: return 16;
case SL::TYPE_SAMPLEREXT: return 16;
} }
ERR_FAIL_V(0); ERR_FAIL_V(0);

View file

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

View file

@ -368,6 +368,16 @@ public:
custom_defines.push_back(p_define.utf8()); 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(); virtual ~ShaderGLES3();
}; };

View file

@ -658,6 +658,7 @@ void register_scene_types() {
ClassDB::register_class<ProxyTexture>(); ClassDB::register_class<ProxyTexture>();
ClassDB::register_class<AnimatedTexture>(); ClassDB::register_class<AnimatedTexture>();
ClassDB::register_class<CameraTexture>(); ClassDB::register_class<CameraTexture>();
ClassDB::register_class<ExternalTexture>();
ClassDB::register_class<CubeMap>(); ClassDB::register_class<CubeMap>();
ClassDB::register_virtual_class<TextureLayered>(); ClassDB::register_virtual_class<TextureLayered>();
ClassDB::register_class<Texture3D>(); 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 { bool Shader::is_text_shader() const {
return true; 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("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("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("has_param", "name"), &Shader::has_param);
//ClassDB::bind_method(D_METHOD("get_param_list"),&Shader::get_fragment_code); //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, "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_SPATIAL);
BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM); BIND_ENUM_CONSTANT(MODE_CANVAS_ITEM);

View file

@ -79,6 +79,9 @@ public:
Ref<Texture> get_default_texture_param(const StringName &p_param) const; Ref<Texture> get_default_texture_param(const StringName &p_param) const;
void get_default_texture_param_list(List<StringName> *r_textures) 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; virtual bool is_text_shader() const;
_FORCE_INLINE_ StringName remap_param(const StringName &p_param) const { _FORCE_INLINE_ StringName remap_param(const StringName &p_param) const {

View file

@ -2621,3 +2621,64 @@ CameraTexture::CameraTexture() {
CameraTexture::~CameraTexture() { CameraTexture::~CameraTexture() {
// nothing to do here yet // 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(); ~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 #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 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 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 */ /* COMMON MATERIAL API */
virtual RID material_create() = 0; virtual RID material_create() = 0;

View file

@ -132,6 +132,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"TYPE_ISAMPLER3D", "TYPE_ISAMPLER3D",
"TYPE_USAMPLER3D", "TYPE_USAMPLER3D",
"TYPE_SAMPLERCUBE", "TYPE_SAMPLERCUBE",
"TYPE_SAMPLEREXT",
"INTERPOLATION_FLAT", "INTERPOLATION_FLAT",
"INTERPOLATION_SMOOTH", "INTERPOLATION_SMOOTH",
"CONST", "CONST",
@ -272,6 +273,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_TYPE_ISAMPLER3D, "isampler3D" }, { TK_TYPE_ISAMPLER3D, "isampler3D" },
{ TK_TYPE_USAMPLER3D, "usampler3D" }, { TK_TYPE_USAMPLER3D, "usampler3D" },
{ TK_TYPE_SAMPLERCUBE, "samplerCube" }, { TK_TYPE_SAMPLERCUBE, "samplerCube" },
{ TK_TYPE_SAMPLEREXT, "samplerExternalOES" },
{ TK_INTERPOLATION_FLAT, "flat" }, { TK_INTERPOLATION_FLAT, "flat" },
{ TK_INTERPOLATION_SMOOTH, "smooth" }, { TK_INTERPOLATION_SMOOTH, "smooth" },
{ TK_CONST, "const" }, { TK_CONST, "const" },
@ -755,7 +757,8 @@ bool ShaderLanguage::is_token_datatype(TokenType p_type) {
p_type == TK_TYPE_SAMPLER3D || p_type == TK_TYPE_SAMPLER3D ||
p_type == TK_TYPE_ISAMPLER3D || p_type == TK_TYPE_ISAMPLER3D ||
p_type == TK_TYPE_USAMPLER3D || 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) { 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_ISAMPLER3D: return "isampler3D";
case TYPE_USAMPLER3D: return "usampler3D"; case TYPE_USAMPLER3D: return "usampler3D";
case TYPE_SAMPLERCUBE: return "samplerCube"; case TYPE_SAMPLERCUBE: return "samplerCube";
case TYPE_SAMPLEREXT: return "samplerExternalOES";
} }
return ""; 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_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_VOID }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, 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_VEC3, TYPE_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, 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_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_VOID }, TAG_GLOBAL, true },
{ "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, 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_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false },
{ "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true },
@ -2452,7 +2462,8 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) {
p_type == TYPE_SAMPLER3D || p_type == TYPE_SAMPLER3D ||
p_type == TYPE_ISAMPLER3D || p_type == TYPE_ISAMPLER3D ||
p_type == TYPE_USAMPLER3D || 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) { 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_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2D: case ShaderLanguage::TYPE_USAMPLER2D:
case ShaderLanguage::TYPE_USAMPLER3D: case ShaderLanguage::TYPE_USAMPLER3D:
case ShaderLanguage::TYPE_SAMPLERCUBE: { case ShaderLanguage::TYPE_SAMPLERCUBE:
case ShaderLanguage::TYPE_SAMPLEREXT: {
// Texture types, likely not relevant here. // Texture types, likely not relevant here.
break; break;
} }

View file

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

View file

@ -190,6 +190,10 @@ public:
BIND3(shader_set_default_texture_param, RID, const StringName &, RID) BIND3(shader_set_default_texture_param, RID, const StringName &, RID)
BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &) 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 */ /* COMMON MATERIAL API */
BIND0R(RID, material_create) BIND0R(RID, material_create)

View file

@ -126,6 +126,10 @@ public:
FUNC3(shader_set_default_texture_param, RID, const StringName &, RID) FUNC3(shader_set_default_texture_param, RID, const StringName &, RID)
FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) 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 */ /* COMMON MATERIAL API */
FUNCRID(material) FUNCRID(material)

View file

@ -93,6 +93,7 @@ public:
enum TextureType { enum TextureType {
TEXTURE_TYPE_2D, TEXTURE_TYPE_2D,
TEXTURE_TYPE_EXTERNAL,
TEXTURE_TYPE_CUBEMAP, TEXTURE_TYPE_CUBEMAP,
TEXTURE_TYPE_2D_ARRAY, TEXTURE_TYPE_2D_ARRAY,
TEXTURE_TYPE_3D, 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 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 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 */ /* COMMON MATERIAL API */
enum { enum {