Merge pull request #36342 from m4gr3d/external_texture_support_for_godot_3_2
Add support for opengl external textures
This commit is contained in:
commit
cc70b2fa0a
24 changed files with 401 additions and 57 deletions
25
doc/classes/ExternalTexture.xml
Normal file
25
doc/classes/ExternalTexture.xml
Normal 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>
|
|
@ -55,6 +55,10 @@
|
|||
<member name="code" type="String" setter="set_code" getter="get_code" default="""">
|
||||
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="""">
|
||||
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">
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue