Merge pull request #105701 from ColinSORourke/DrawableTexture
Implement DrawableTextures
This commit is contained in:
commit
fd6e80d4e9
46 changed files with 2417 additions and 10 deletions
33
doc/classes/BlitMaterial.xml
Normal file
33
doc/classes/BlitMaterial.xml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="BlitMaterial" inherits="Material" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
A material that processes blit calls to a DrawableTexture.
|
||||
</brief_description>
|
||||
<description>
|
||||
A material resource that can be used by DrawableTextures when processing blit calls to draw.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="BlitMaterial.BlendMode" default="0">
|
||||
The manner in which the newly blitted texture is blended with the original DrawableTexture.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="BLEND_MODE_MIX" value="0" enum="BlendMode">
|
||||
Mix blending mode. Colors are assumed to be independent of the alpha (opacity) value.
|
||||
</constant>
|
||||
<constant name="BLEND_MODE_ADD" value="1" enum="BlendMode">
|
||||
Additive blending mode.
|
||||
</constant>
|
||||
<constant name="BLEND_MODE_SUB" value="2" enum="BlendMode">
|
||||
Subtractive blending mode.
|
||||
</constant>
|
||||
<constant name="BLEND_MODE_MUL" value="3" enum="BlendMode">
|
||||
Multiplicative blending mode.
|
||||
</constant>
|
||||
<constant name="BLEND_MODE_DISABLED" value="4" enum="BlendMode">
|
||||
No blending mode, direct color copy.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
71
doc/classes/DrawableTexture2D.xml
Normal file
71
doc/classes/DrawableTexture2D.xml
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="DrawableTexture2D" inherits="Texture2D" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
|
||||
<brief_description>
|
||||
A 2D texture that supports drawing to itself via Blit calls.
|
||||
</brief_description>
|
||||
<description>
|
||||
A 2D texture that can be modified via blit calls, copying from a target texture to itself. Primarily intended to be managed in code, a user must call [method setup] to initialize the state before drawing. Each [method blit_rect] call takes at least a rectangle, the area to draw to, and another texture, what to be drawn. The draw calls use a Texture_Blit Shader to process and calculate the result, pixel by pixel. Users can supply their own ShaderMaterial with custom Texture_Blit shaders for more complex behaviors.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="blit_rect" experimental="This function and its parameters are likely to change in the 4.7 Dev Cycle">
|
||||
<return type="void" />
|
||||
<param index="0" name="rect" type="Rect2i" />
|
||||
<param index="1" name="source" type="Texture2D" />
|
||||
<param index="2" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
|
||||
<param index="3" name="mipmap" type="int" default="0" />
|
||||
<param index="4" name="material" type="Material" default="null" />
|
||||
<description>
|
||||
Draws to given [param rect] on this texture by copying from the given [param source]. A [param modulate] color can be passed in for the shader to use, but defaults to White. The [param mipmap] value can specify a draw to a lower mipmap level. The [param material] parameter can take a ShaderMaterial with a TextureBlit Shader for custom drawing behavior.
|
||||
</description>
|
||||
</method>
|
||||
<method name="blit_rect_multi" experimental="This function and its parameters are likely to change in the 4.7 Dev Cycle">
|
||||
<return type="void" />
|
||||
<param index="0" name="rect" type="Rect2i" />
|
||||
<param index="1" name="sources" type="Texture2D[]" />
|
||||
<param index="2" name="extra_targets" type="DrawableTexture2D[]" />
|
||||
<param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" />
|
||||
<param index="4" name="mipmap" type="int" default="0" />
|
||||
<param index="5" name="material" type="Material" default="null" />
|
||||
<description>
|
||||
Draws to the given [param rect] on this texture, as well as on up to 3 DrawableTexture [param extra_targets]. All [param extra_targets] must be the same size and DrawableFormat as the original target, otherwise the Shader may fail. Expects up to 4 Texture [param sources], but will replace missing [param sources] with default Black Textures.
|
||||
</description>
|
||||
</method>
|
||||
<method name="generate_mipmaps">
|
||||
<return type="void" />
|
||||
<description>
|
||||
Re-calculates the mipmaps for this texture on demand.
|
||||
</description>
|
||||
</method>
|
||||
<method name="setup" experimental="This function and its parameters are likely to change in the 4.7 Dev Cycle">
|
||||
<return type="void" />
|
||||
<param index="0" name="width" type="int" />
|
||||
<param index="1" name="height" type="int" />
|
||||
<param index="2" name="format" type="int" enum="DrawableTexture2D.DrawableFormat" />
|
||||
<param index="3" name="color" type="Color" default="Color(1, 1, 1, 1)" />
|
||||
<param index="4" name="use_mipmaps" type="bool" default="false" />
|
||||
<description>
|
||||
Initializes the DrawableTexture to a White texture of the given [param width], [param height], and [param format].
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<members>
|
||||
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="DRAWABLE_FORMAT_RGBA8" value="0" enum="DrawableFormat">
|
||||
OpenGL texture format RGBA with four components, each with a bitdepth of 8.
|
||||
</constant>
|
||||
<constant name="DRAWABLE_FORMAT_RGBA8_SRGB" value="1" enum="DrawableFormat">
|
||||
OpenGL texture format RGBA with four components, each with a bitdepth of 8.
|
||||
When drawn to, an sRGB to linear color space conversion is performed.
|
||||
</constant>
|
||||
<constant name="DRAWABLE_FORMAT_RGBAH" value="2" enum="DrawableFormat">
|
||||
OpenGL texture format GL_RGBA16F where there are four components, each a 16-bit "half-precision" floating-point value.
|
||||
</constant>
|
||||
<constant name="DRAWABLE_FORMAT_RGBAF" value="3" enum="DrawableFormat">
|
||||
OpenGL texture format GL_RGBA32F where there are four components, each a 32-bit floating-point value.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
@ -3878,6 +3878,45 @@
|
|||
[b]Note:[/b] If using only the rendering device renderer, it's recommend to use [method RenderingDevice.texture_create_from_extension] together with [method RenderingServer.texture_rd_create], rather than this method. This way, the texture's format and usage can be controlled more effectively.
|
||||
</description>
|
||||
</method>
|
||||
<method name="texture_drawable_blit_rect">
|
||||
<return type="void" />
|
||||
<param index="0" name="textures" type="RID[]" />
|
||||
<param index="1" name="rect" type="Rect2i" />
|
||||
<param index="2" name="material" type="RID" />
|
||||
<param index="3" name="modulate" type="Color" />
|
||||
<param index="4" name="source_textures" type="RID[]" />
|
||||
<param index="5" name="to_mipmap" type="int" default="0" />
|
||||
<description>
|
||||
Draws to [param rect] on up to 4 given Drawable [param textures], using a TextureBlit Shader from [param material]. [param modulate] and up to 4 [param source_textures] are uniforms for the Shader to process with. [param to_mipmap] can specify to perform this draw to a lower mipmap level.
|
||||
[b]Note:[/b] All [param textures] must be the same size and format.
|
||||
</description>
|
||||
</method>
|
||||
<method name="texture_drawable_create">
|
||||
<return type="RID" />
|
||||
<param index="0" name="width" type="int" />
|
||||
<param index="1" name="height" type="int" />
|
||||
<param index="2" name="format" type="int" enum="RenderingServer.TextureDrawableFormat" />
|
||||
<param index="3" name="color" type="Color" default="Color(1, 1, 1, 1)" />
|
||||
<param index="4" name="with_mipmaps" type="bool" default="false" />
|
||||
<description>
|
||||
Creates a 2-dimensional texture and adds it to the RenderingServer. It can be accessed with the RID that is returned. This RID will be used in all [code]texture_drawable*[/code] RenderingServer functions.
|
||||
Once finished with your RID, you will want to free the RID using the RenderingServer's [method free_rid] method.
|
||||
[b]Note:[/b] The equivalent resource is [DrawableTexture2D].
|
||||
</description>
|
||||
</method>
|
||||
<method name="texture_drawable_generate_mipmaps">
|
||||
<return type="void" />
|
||||
<param index="0" name="texture" type="RID" />
|
||||
<description>
|
||||
Calculates new MipMaps for the given Drawable [param texture].
|
||||
</description>
|
||||
</method>
|
||||
<method name="texture_drawable_get_default_material" qualifiers="const">
|
||||
<return type="RID" />
|
||||
<description>
|
||||
Returns a ShaderMaterial with the default texture_blit Shader.
|
||||
</description>
|
||||
</method>
|
||||
<method name="texture_get_format" qualifiers="const">
|
||||
<return type="int" enum="Image.Format" />
|
||||
<param index="0" name="texture" type="RID" />
|
||||
|
|
@ -4677,6 +4716,19 @@
|
|||
<constant name="CUBEMAP_LAYER_BACK" value="5" enum="CubeMapLayer">
|
||||
Back face of a [Cubemap].
|
||||
</constant>
|
||||
<constant name="TEXTURE_DRAWABLE_FORMAT_RGBA8" value="0" enum="TextureDrawableFormat">
|
||||
OpenGL texture format RGBA with four components, each with a bitdepth of 8.
|
||||
</constant>
|
||||
<constant name="TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB" value="1" enum="TextureDrawableFormat">
|
||||
OpenGL texture format RGBA with four components, each with a bitdepth of 8.
|
||||
When drawn to, an sRGB to linear color space conversion is performed.
|
||||
</constant>
|
||||
<constant name="TEXTURE_DRAWABLE_FORMAT_RGBAH" value="2" enum="TextureDrawableFormat">
|
||||
OpenGL texture format GL_RGBA16F where there are four components, each a 16-bit "half-precision" floating-point value.
|
||||
</constant>
|
||||
<constant name="TEXTURE_DRAWABLE_FORMAT_RGBAF" value="3" enum="TextureDrawableFormat">
|
||||
OpenGL texture format GL_RGBA32F where there are four components, each a 32-bit floating-point value.
|
||||
</constant>
|
||||
<constant name="SHADER_SPATIAL" value="0" enum="ShaderMode">
|
||||
Shader is a 3D shader.
|
||||
</constant>
|
||||
|
|
@ -4692,7 +4744,10 @@
|
|||
<constant name="SHADER_FOG" value="4" enum="ShaderMode">
|
||||
Shader is a 3D fog shader.
|
||||
</constant>
|
||||
<constant name="SHADER_MAX" value="5" enum="ShaderMode">
|
||||
<constant name="SHADER_TEXTURE_BLIT" value="5" enum="ShaderMode">
|
||||
Shader is a texture_blit shader.
|
||||
</constant>
|
||||
<constant name="SHADER_MAX" value="6" enum="ShaderMode">
|
||||
Represents the size of the [enum ShaderMode] enum.
|
||||
</constant>
|
||||
<constant name="MATERIAL_RENDER_PRIORITY_MIN" value="-128">
|
||||
|
|
|
|||
|
|
@ -74,5 +74,8 @@
|
|||
<constant name="MODE_FOG" value="4" enum="Mode">
|
||||
Mode used for setting the color and density of volumetric fog effect.
|
||||
</constant>
|
||||
<constant name="MODE_TEXTURE_BLIT" value="5" enum="Mode">
|
||||
Mode used for drawing to DrawableTexture resources via blit calls.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
|||
|
|
@ -222,7 +222,10 @@
|
|||
<constant name="TYPE_FOG" value="9" enum="Type">
|
||||
A compute shader that runs for each froxel of the volumetric fog map.
|
||||
</constant>
|
||||
<constant name="TYPE_MAX" value="10" enum="Type">
|
||||
<constant name="TYPE_TEXTURE_BLIT" value="10" enum="Type">
|
||||
A shader used to process blit calls to a DrawableTexture.
|
||||
</constant>
|
||||
<constant name="TYPE_MAX" value="11" enum="Type">
|
||||
Represents the size of the [enum Type] enum.
|
||||
</constant>
|
||||
<constant name="VARYING_MODE_VERTEX_TO_FRAG_LIGHT" value="0" enum="VaryingMode">
|
||||
|
|
|
|||
|
|
@ -210,6 +210,8 @@ void RasterizerGLES3::initialize() {
|
|||
}
|
||||
|
||||
void RasterizerGLES3::finalize() {
|
||||
// Has to be a separate call due to TextureStorage & MaterialStorage needing to interact for TexBlit Shaders
|
||||
texture_storage->_tex_blit_shader_free();
|
||||
memdelete(scene);
|
||||
memdelete(canvas);
|
||||
memdelete(gi);
|
||||
|
|
@ -372,6 +374,8 @@ RasterizerGLES3::RasterizerGLES3() {
|
|||
fog = memnew(GLES3::Fog);
|
||||
canvas = memnew(RasterizerCanvasGLES3());
|
||||
scene = memnew(RasterizerSceneGLES3());
|
||||
// Has to be a separate call due to TextureStorage & MaterialStorage needing to interact for TexBlit Shaders
|
||||
texture_storage->_tex_blit_shader_initialize();
|
||||
|
||||
// Disable OpenGL linear to sRGB conversion, because Godot will always do this conversion itself.
|
||||
if (config->srgb_framebuffer_supported) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ if "GLES3_GLSL" in env["BUILDERS"]:
|
|||
env.GLES3_GLSL("particles.glsl")
|
||||
env.GLES3_GLSL("particles_copy.glsl")
|
||||
env.GLES3_GLSL("skeleton.glsl")
|
||||
env.GLES3_GLSL("tex_blit.glsl")
|
||||
|
||||
# once we finish conversion we can introduce this to cover all files:
|
||||
# for glsl_file in glsl_files:
|
||||
|
|
|
|||
121
drivers/gles3/shaders/tex_blit.glsl
Normal file
121
drivers/gles3/shaders/tex_blit.glsl
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* clang-format off */
|
||||
|
||||
#[modes]
|
||||
|
||||
mode_default =
|
||||
|
||||
#[specializations]
|
||||
|
||||
USE_OUTPUT1 = true
|
||||
USE_OUTPUT2 = true
|
||||
USE_OUTPUT3 = true
|
||||
|
||||
#[vertex]
|
||||
|
||||
layout(location = 0) in vec2 vertex_attrib;
|
||||
|
||||
uniform vec2 offset;
|
||||
uniform vec2 size;
|
||||
|
||||
out vec2 uv;
|
||||
|
||||
void main() {
|
||||
uv = vertex_attrib * 0.5 + 0.5;
|
||||
// This math scales the Vertex Attribute Quad to match the Rect the user passed in, based on Offset & Size
|
||||
gl_Position = vec4( (offset * 2.0 - 1.0) + (size * (vertex_attrib + 1.0)), 1.0, 1.0);
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
||||
uniform sampler2D source0; // texunit:0
|
||||
|
||||
uniform sampler2D source1; // texunit:-1
|
||||
|
||||
uniform sampler2D source2; // texunit:-2
|
||||
|
||||
uniform sampler2D source3; // texunit:-3
|
||||
|
||||
#define OUTPUT0_SRGB uint(1)
|
||||
#define OUTPUT1_SRGB uint(2)
|
||||
#define OUTPUT2_SRGB uint(4)
|
||||
#define OUTPUT3_SRGB uint(8)
|
||||
|
||||
uniform uint convert_to_srgb;
|
||||
uniform vec4 modulate;
|
||||
uniform float time;
|
||||
|
||||
in vec2 uv;
|
||||
|
||||
layout (location = 0) out vec4 out_color0;
|
||||
|
||||
#ifdef USE_OUTPUT1
|
||||
layout (location = 1) out vec4 out_color1;
|
||||
#endif
|
||||
|
||||
#ifdef USE_OUTPUT2
|
||||
layout (location = 2) out vec4 out_color2;
|
||||
#endif
|
||||
|
||||
#ifdef USE_OUTPUT3
|
||||
layout (location = 3) out vec4 out_color3;
|
||||
#endif
|
||||
|
||||
// This needs to be outside clang-format so the ubo comment is in the right place
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(std140) uniform MaterialUniforms{ //ubo:0
|
||||
|
||||
#MATERIAL_UNIFORMS
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
// If going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Handles the case where user code uses extra outputs, but extra output targets were not bound
|
||||
vec4 color0 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color1 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color2 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color3 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
#CODE : BLIT
|
||||
|
||||
// Discards extra outputs if extra output targets were not bound
|
||||
out_color0 = color0;
|
||||
|
||||
#ifdef USE_OUTPUT1
|
||||
out_color1 = color1;
|
||||
#endif
|
||||
#ifdef USE_OUTPUT2
|
||||
out_color2 = color2;
|
||||
#endif
|
||||
#ifdef USE_OUTPUT3
|
||||
out_color3 = color3;
|
||||
#endif
|
||||
|
||||
if (bool(convert_to_srgb & OUTPUT0_SRGB)) {
|
||||
out_color0.rgb = linear_to_srgb(out_color0.rgb); // Regular linear -> SRGB conversion.
|
||||
}
|
||||
#ifdef USE_OUTPUT1
|
||||
if (bool(convert_to_srgb & OUTPUT1_SRGB)) {
|
||||
out_color1.rgb = linear_to_srgb(out_color1.rgb);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OUTPUT2
|
||||
if (bool(convert_to_srgb & OUTPUT2_SRGB)) {
|
||||
out_color2.rgb = linear_to_srgb(out_color2.rgb);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OUTPUT3
|
||||
if (bool(convert_to_srgb & OUTPUT3_SRGB)) {
|
||||
out_color3.rgb = linear_to_srgb(out_color3.rgb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1137,12 +1137,14 @@ MaterialStorage::MaterialStorage() {
|
|||
shader_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_shader_func;
|
||||
shader_data_request_func[RS::SHADER_PARTICLES] = _create_particles_shader_func;
|
||||
shader_data_request_func[RS::SHADER_SKY] = _create_sky_shader_func;
|
||||
shader_data_request_func[RS::SHADER_TEXTURE_BLIT] = _create_tex_blit_shader_func;
|
||||
shader_data_request_func[RS::SHADER_FOG] = nullptr;
|
||||
|
||||
material_data_request_func[RS::SHADER_SPATIAL] = _create_scene_material_func;
|
||||
material_data_request_func[RS::SHADER_CANVAS_ITEM] = _create_canvas_material_func;
|
||||
material_data_request_func[RS::SHADER_PARTICLES] = _create_particles_material_func;
|
||||
material_data_request_func[RS::SHADER_SKY] = _create_sky_material_func;
|
||||
material_data_request_func[RS::SHADER_TEXTURE_BLIT] = _create_tex_blit_material_func;
|
||||
material_data_request_func[RS::SHADER_FOG] = nullptr;
|
||||
|
||||
static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
|
||||
|
|
@ -1549,6 +1551,28 @@ MaterialStorage::MaterialStorage() {
|
|||
|
||||
shaders.compiler_sky.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
// Setup TextureBlit compiler
|
||||
ShaderCompiler::DefaultIdentifierActions actions;
|
||||
|
||||
actions.renames["TIME"] = "time";
|
||||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
|
||||
actions.renames["UV"] = "uv";
|
||||
actions.renames["MODULATE"] = "modulate";
|
||||
|
||||
actions.renames["COLOR0"] = "color0";
|
||||
actions.renames["COLOR1"] = "color1";
|
||||
actions.renames["COLOR2"] = "color2";
|
||||
actions.renames["COLOR3"] = "color3";
|
||||
|
||||
shaders.compiler_tex_blit.initialize(actions);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialStorage::~MaterialStorage() {
|
||||
|
|
@ -2233,6 +2257,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
|
|||
new_mode = RS::SHADER_SKY;
|
||||
//} else if (mode_string == "fog") {
|
||||
// new_mode = RS::SHADER_FOG;
|
||||
} else if (mode_string == "texture_blit") {
|
||||
new_mode = RS::SHADER_TEXTURE_BLIT;
|
||||
} else {
|
||||
new_mode = RS::SHADER_MAX;
|
||||
ERR_PRINT("shader type " + mode_string + " not supported in OpenGL renderer");
|
||||
|
|
@ -3329,4 +3355,119 @@ void ParticleProcessMaterialData::bind_uniforms() {
|
|||
bind_uniforms_generic(texture_cache, shader_data->texture_uniforms, 1); // Start at GL_TEXTURE1 because texture slot 0 is reserved for the heightmap texture.
|
||||
}
|
||||
|
||||
/* TextureBlit SHADER */
|
||||
|
||||
void TexBlitShaderData::set_code(const String &p_code) {
|
||||
// Initialize and compile the shader.
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; // Just invalid, but no error.
|
||||
}
|
||||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
// Actual enum set further down after compilation.
|
||||
int blend_modei = BLEND_MODE_MIX;
|
||||
|
||||
ShaderCompiler::IdentifierActions actions;
|
||||
actions.entry_point_stages["blit"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||
|
||||
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD);
|
||||
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
|
||||
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
|
||||
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
|
||||
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_modei, BLEND_MODE_DISABLED);
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
Error err = MaterialStorage::get_singleton()->shaders.compiler_tex_blit.compile(RS::SHADER_TEXTURE_BLIT, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
|
||||
if (version.is_null()) {
|
||||
version = MaterialStorage::get_singleton()->shaders.tex_blit_shader.version_create();
|
||||
}
|
||||
|
||||
blend_mode = BlendMode(blend_modei);
|
||||
|
||||
#if 0
|
||||
print_line("**compiling shader:");
|
||||
print_line("**defines:\n");
|
||||
for (int i = 0; i < gen_code.defines.size(); i++) {
|
||||
print_line(gen_code.defines[i]);
|
||||
}
|
||||
|
||||
HashMap<String, String>::Iterator el = gen_code.code.begin();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key + ":\n" + el->value);
|
||||
++el;
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
LocalVector<ShaderGLES3::TextureUniformData> texture_uniform_data = get_texture_uniform_data(gen_code.texture_uniforms);
|
||||
|
||||
MaterialStorage::get_singleton()->shaders.tex_blit_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines, texture_uniform_data);
|
||||
ERR_FAIL_COND(!MaterialStorage::get_singleton()->shaders.tex_blit_shader.version_is_valid(version));
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
bool TexBlitShaderData::is_animated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TexBlitShaderData::casts_shadows() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode TexBlitShaderData::get_native_source_code() const {
|
||||
return MaterialStorage::get_singleton()->shaders.tex_blit_shader.version_get_native_source_code(version);
|
||||
}
|
||||
|
||||
TexBlitShaderData::TexBlitShaderData() {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
TexBlitShaderData::~TexBlitShaderData() {
|
||||
if (version.is_valid()) {
|
||||
MaterialStorage::get_singleton()->shaders.tex_blit_shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
GLES3::ShaderData *GLES3::_create_tex_blit_shader_func() {
|
||||
TexBlitShaderData *shader_data = memnew(TexBlitShaderData);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
void TexBlitMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
update_parameters_internal(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, false);
|
||||
}
|
||||
|
||||
void TexBlitMaterialData::bind_uniforms() {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniform_buffer);
|
||||
|
||||
bind_uniforms_generic(texture_cache, shader_data->texture_uniforms, 1);
|
||||
}
|
||||
|
||||
TexBlitMaterialData::~TexBlitMaterialData() {
|
||||
}
|
||||
|
||||
GLES3::MaterialData *GLES3::_create_tex_blit_material_func(ShaderData *p_shader) {
|
||||
TexBlitMaterialData *material_data = memnew(TexBlitMaterialData);
|
||||
material_data->shader_data = static_cast<TexBlitShaderData *>(p_shader);
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
#endif // !GLES3_ENABLED
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include "drivers/gles3/shaders/particles.glsl.gen.h"
|
||||
#include "drivers/gles3/shaders/scene.glsl.gen.h"
|
||||
#include "drivers/gles3/shaders/sky.glsl.gen.h"
|
||||
#include "drivers/gles3/shaders/tex_blit.glsl.gen.h"
|
||||
|
||||
namespace GLES3 {
|
||||
|
||||
|
|
@ -423,6 +424,52 @@ struct ParticleProcessMaterialData : public MaterialData {
|
|||
|
||||
MaterialData *_create_particles_material_func(ShaderData *p_shader);
|
||||
|
||||
/* Texture Blit Shader */
|
||||
|
||||
struct TexBlitShaderData : public ShaderData {
|
||||
enum BlendMode { // Used internally.
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_DISABLED,
|
||||
};
|
||||
|
||||
bool valid;
|
||||
RID version;
|
||||
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
|
||||
BlendMode blend_mode;
|
||||
|
||||
virtual void set_code(const String &p_code);
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
|
||||
TexBlitShaderData();
|
||||
virtual ~TexBlitShaderData();
|
||||
};
|
||||
|
||||
ShaderData *_create_tex_blit_shader_func();
|
||||
|
||||
struct TexBlitMaterialData : public MaterialData {
|
||||
TexBlitShaderData *shader_data = nullptr;
|
||||
|
||||
virtual void set_render_priority(int p_priority) {}
|
||||
virtual void set_next_pass(RID p_pass) {}
|
||||
virtual void update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual void bind_uniforms();
|
||||
virtual ~TexBlitMaterialData();
|
||||
};
|
||||
|
||||
MaterialData *_create_tex_blit_material_func(ShaderData *p_shader);
|
||||
|
||||
/* Global shader uniform structs */
|
||||
struct GlobalShaderUniforms {
|
||||
enum {
|
||||
|
|
@ -560,11 +607,13 @@ public:
|
|||
SkyShaderGLES3 sky_shader;
|
||||
SceneShaderGLES3 scene_shader;
|
||||
ParticlesShaderGLES3 particles_process_shader;
|
||||
TexBlitShaderGLES3 tex_blit_shader;
|
||||
|
||||
ShaderCompiler compiler_canvas;
|
||||
ShaderCompiler compiler_scene;
|
||||
ShaderCompiler compiler_particles;
|
||||
ShaderCompiler compiler_sky;
|
||||
ShaderCompiler compiler_tex_blit;
|
||||
} shaders;
|
||||
|
||||
/* GLOBAL SHADER UNIFORM API */
|
||||
|
|
|
|||
|
|
@ -303,6 +303,94 @@ TextureStorage::~TextureStorage() {
|
|||
sdf_shader.shader.version_free(sdf_shader.shader_version);
|
||||
}
|
||||
|
||||
// Has to be a separate call from TextureStorage initialization due to interacting with MaterialStorage
|
||||
void TextureStorage::_tex_blit_shader_initialize() {
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
|
||||
{
|
||||
String global_defines;
|
||||
global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
|
||||
material_storage->shaders.tex_blit_shader.initialize(global_defines, 1);
|
||||
}
|
||||
|
||||
{
|
||||
// default material and shader for Texture Blit shader
|
||||
tex_blit_shader.default_shader = material_storage->shader_allocate();
|
||||
material_storage->shader_initialize(tex_blit_shader.default_shader);
|
||||
material_storage->shader_set_code(tex_blit_shader.default_shader, R"(
|
||||
// Default Texture Blit shader.
|
||||
|
||||
shader_type texture_blit;
|
||||
render_mode blend_mix;
|
||||
|
||||
uniform sampler2D source_texture0 : hint_blit_source0;
|
||||
uniform sampler2D source_texture1 : hint_blit_source1;
|
||||
uniform sampler2D source_texture2 : hint_blit_source2;
|
||||
uniform sampler2D source_texture3 : hint_blit_source3;
|
||||
|
||||
void blit() {
|
||||
// Copies from each whole source texture to a rect on each output texture.
|
||||
COLOR0 = texture(source_texture0, UV) * MODULATE;
|
||||
COLOR1 = texture(source_texture1, UV) * MODULATE;
|
||||
COLOR2 = texture(source_texture2, UV) * MODULATE;
|
||||
COLOR3 = texture(source_texture3, UV) * MODULATE;
|
||||
}
|
||||
)");
|
||||
tex_blit_shader.default_material = material_storage->material_allocate();
|
||||
material_storage->material_initialize(tex_blit_shader.default_material);
|
||||
material_storage->material_set_shader(tex_blit_shader.default_material, tex_blit_shader.default_shader);
|
||||
}
|
||||
|
||||
{
|
||||
// Set up Frame & Vertex Buffers for TextureBlit Shaders
|
||||
// Just a 1x1 Quad to draw
|
||||
glGenFramebuffers(1, &tex_blit_fbo);
|
||||
|
||||
glGenBuffers(1, &tex_blit_quad);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tex_blit_quad);
|
||||
|
||||
const float qv[12] = {
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f,
|
||||
1.0f,
|
||||
};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12, qv, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
|
||||
glGenVertexArrays(1, &tex_blit_quad_array);
|
||||
glBindVertexArray(tex_blit_quad_array);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, tex_blit_quad);
|
||||
glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, nullptr);
|
||||
glEnableVertexAttribArray(RS::ARRAY_VERTEX);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
|
||||
}
|
||||
|
||||
tex_blit_shader.initialized = true;
|
||||
}
|
||||
|
||||
// Has to be a separate call from TextureStorage destruction due to interacting with Material Storage
|
||||
void TextureStorage::_tex_blit_shader_free() {
|
||||
if (tex_blit_shader.initialized) {
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
glDeleteFramebuffers(1, &tex_blit_fbo);
|
||||
glDeleteBuffers(1, &tex_blit_quad);
|
||||
glDeleteVertexArrays(1, &tex_blit_quad_array);
|
||||
material_storage->material_free(tex_blit_shader.default_material);
|
||||
material_storage->shader_free(tex_blit_shader.default_shader);
|
||||
}
|
||||
}
|
||||
|
||||
/* Canvas Texture API */
|
||||
|
||||
RID TextureStorage::canvas_texture_allocate() {
|
||||
|
|
@ -1113,6 +1201,51 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
|
|||
texture_owner.initialize_rid(p_texture, proxy_tex);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) {
|
||||
// Behaves identically to Texture_2D_Initialize by generating a white image based on parameters.
|
||||
|
||||
// GUARDRAIL: Bad Widths/Heights
|
||||
ERR_FAIL_COND_MSG(p_width <= 0 || p_height <= 0, "Drawable Texture Width or Height cannot be less than 1.");
|
||||
ERR_FAIL_COND_MSG(p_width >= 16384 || p_height >= 16384, "Drawable Texture Width or Height cannot be greater than 16383.");
|
||||
|
||||
Image::Format format;
|
||||
switch (p_format) {
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBA8:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBAH:
|
||||
format = Image::FORMAT_RGBAH;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBAF:
|
||||
format = Image::FORMAT_RGBAF;
|
||||
break;
|
||||
default:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
}
|
||||
|
||||
Ref<Image> image = Image::create_empty(p_width, p_height, p_with_mipmaps, format);
|
||||
image->fill(p_color);
|
||||
Texture texture;
|
||||
texture.width = image->get_width();
|
||||
texture.height = image->get_height();
|
||||
texture.alloc_width = texture.width;
|
||||
texture.alloc_height = texture.height;
|
||||
texture.mipmaps = image->get_mipmap_count() + 1;
|
||||
texture.format = image->get_format();
|
||||
texture.type = Texture::TYPE_2D;
|
||||
texture.target = GL_TEXTURE_2D;
|
||||
_get_gl_image_and_format(Ref<Image>(), texture.format, texture.real_format, texture.gl_format_cache, texture.gl_internal_format_cache, texture.gl_type_cache, texture.compressed, false);
|
||||
texture.total_data_size = image->get_image_data_size(texture.width, texture.height, texture.format, texture.mipmaps);
|
||||
texture.active = true;
|
||||
glGenTextures(1, &texture.tex_id);
|
||||
GLES3::Utilities::get_singleton()->texture_allocated_data(texture.tex_id, texture.total_data_size, "Texture 2D");
|
||||
texture_owner.initialize_rid(p_texture, texture);
|
||||
texture_set_data(p_texture, image);
|
||||
}
|
||||
|
||||
RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
|
||||
Texture texture;
|
||||
texture.active = true;
|
||||
|
|
@ -1231,6 +1364,135 @@ void TextureStorage::texture_remap_proxies(RID p_from_texture, RID p_to_texture)
|
|||
}
|
||||
}
|
||||
|
||||
// Output textures in p_textures must ALL BE THE SAME SIZE
|
||||
void TextureStorage::texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) {
|
||||
ERR_FAIL_COND_MSG(!tex_blit_shader.initialized, "Texture Blit shader & materials not yet initialized.");
|
||||
ERR_FAIL_COND_MSG(p_textures.size() == 0 || p_source_textures.size() == 0, "Blit Rect texture output and source arrays must contain at least 1 texture.");
|
||||
GLES3::MaterialStorage *material_storage = GLES3::MaterialStorage::get_singleton();
|
||||
|
||||
TexBlitMaterialData *m = static_cast<TexBlitMaterialData *>(material_storage->material_get_data(p_material, RS::SHADER_TEXTURE_BLIT));
|
||||
if (!m) {
|
||||
m = static_cast<TexBlitMaterialData *>(material_storage->material_get_data(tex_blit_shader.default_material, RS::SHADER_TEXTURE_BLIT));
|
||||
}
|
||||
// GUARDRAIL: p_material MUST BE ShaderType TextureBlit
|
||||
ERR_FAIL_NULL(m);
|
||||
|
||||
TexBlitShaderGLES3::ShaderVariant variant = TexBlitShaderGLES3::MODE_DEFAULT;
|
||||
RID version = tex_blit_shader.default_shader_version;
|
||||
if (m->shader_data->version.is_valid() && m->shader_data->valid) {
|
||||
// Must be called to force user ShaderMaterials to actually populate uniform buffer before binding
|
||||
// NOTE: Not an ideal work around, maybe in the future this can only update this MaterialData and remove it from the queue, instead of processing all queued updates
|
||||
material_storage->_update_queued_materials();
|
||||
// Bind material uniform buffer and textures.
|
||||
m->bind_uniforms();
|
||||
version = m->shader_data->version;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, tex_blit_fbo);
|
||||
TightLocalVector<GLenum> draw_buffers;
|
||||
|
||||
Texture *tar_textures[4];
|
||||
int convert_to_srgb_mask = 0;
|
||||
Texture *src_textures[4];
|
||||
|
||||
int i = 0;
|
||||
uint32_t specialization = 0;
|
||||
const int outputFlagArray[4] = { 0, TexBlitShaderGLES3::USE_OUTPUT1, TexBlitShaderGLES3::USE_OUTPUT2, TexBlitShaderGLES3::USE_OUTPUT3 };
|
||||
const int srgbMaskArray[4] = { 1, 2, 4, 8 };
|
||||
while (i < 4) {
|
||||
// Attach Targets to Framebuffer
|
||||
if (i < p_textures.size()) {
|
||||
tar_textures[i] = get_texture(p_textures[i]);
|
||||
ERR_FAIL_NULL_MSG(tar_textures[i], "Drawable Texture target cannot be null.");
|
||||
if (i > 0) {
|
||||
ERR_FAIL_COND_MSG(texture_get_size(p_textures[i - 1]) != texture_get_size(p_textures[i]), "All Blit_Rect output textures must be same size.");
|
||||
}
|
||||
specialization |= outputFlagArray[i];
|
||||
draw_buffers.push_back(GL_COLOR_ATTACHMENT0 + i);
|
||||
ERR_FAIL_COND_MSG(p_to_mipmap >= tar_textures[i]->mipmaps, vformat("Drawable Texture Target does not have mipmap level %d.", p_to_mipmap));
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, tar_textures[i]->tex_id, p_to_mipmap);
|
||||
convert_to_srgb_mask += tar_textures[i]->drawable_type == RS::TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB ? srgbMaskArray[i] : 0;
|
||||
}
|
||||
|
||||
// Bind Sources to buffer. Use placeholder Black Texture if source is bad.
|
||||
if (i < p_source_textures.size()) {
|
||||
src_textures[i] = get_texture(p_source_textures[i]);
|
||||
if (!src_textures[i]) {
|
||||
src_textures[i] = get_texture(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE]);
|
||||
}
|
||||
} else {
|
||||
src_textures[i] = get_texture(default_gl_textures[DEFAULT_GL_TEXTURE_WHITE]);
|
||||
}
|
||||
int shift = i == 0 ? 0 : GLES3::Config::get_singleton()->max_texture_image_units - i;
|
||||
glActiveTexture(GL_TEXTURE0 + shift);
|
||||
glBindTexture(GL_TEXTURE_2D, src_textures[i]->tex_id);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
bool success = material_storage->shaders.tex_blit_shader.version_bind_shader(version, variant, specialization);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculates the Rects Offset & Size in UV space for Shader to scale Vertex Quad correctly
|
||||
Vector3 size = texture_get_size(p_textures[0]);
|
||||
Vector2 offset = Vector2(p_rect.position.x / size.x, p_rect.position.y / size.y);
|
||||
Vector2 rect_size = Vector2(p_rect.size.x / size.x, p_rect.size.y / size.y);
|
||||
Vector2i vp_size = Vector2i(tar_textures[0]->alloc_width, tar_textures[0]->alloc_height);
|
||||
if (p_to_mipmap != 0) {
|
||||
vp_size.x >>= p_to_mipmap;
|
||||
vp_size.y >>= p_to_mipmap;
|
||||
}
|
||||
|
||||
glViewport(0, 0, vp_size.x, vp_size.y);
|
||||
|
||||
material_storage->shaders.tex_blit_shader.version_set_uniform(TexBlitShaderGLES3::CONVERT_TO_SRGB, convert_to_srgb_mask, version, variant, specialization);
|
||||
material_storage->shaders.tex_blit_shader.version_set_uniform(TexBlitShaderGLES3::SIZE, rect_size, version, variant, specialization);
|
||||
material_storage->shaders.tex_blit_shader.version_set_uniform(TexBlitShaderGLES3::OFFSET, offset, version, variant, specialization);
|
||||
material_storage->shaders.tex_blit_shader.version_set_uniform(TexBlitShaderGLES3::MODULATE, p_modulate, version, variant, specialization);
|
||||
material_storage->shaders.tex_blit_shader.version_set_uniform(TexBlitShaderGLES3::TIME, RasterizerGLES3::get_singleton()->get_total_time(), version, variant, specialization);
|
||||
|
||||
// Set Blend_Mode correctly
|
||||
GLES3::TexBlitShaderData::BlendMode blend_mode = m->shader_data->blend_mode;
|
||||
glEnable(GL_BLEND);
|
||||
switch (blend_mode) {
|
||||
case GLES3::TexBlitShaderData::BLEND_MODE_ADD:
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
|
||||
break;
|
||||
|
||||
case GLES3::TexBlitShaderData::BLEND_MODE_SUB:
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
|
||||
break;
|
||||
|
||||
case GLES3::TexBlitShaderData::BLEND_MODE_MIX:
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
|
||||
case GLES3::TexBlitShaderData::BLEND_MODE_MUL:
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_DST_ALPHA, GL_ZERO);
|
||||
break;
|
||||
|
||||
case GLES3::TexBlitShaderData::BLEND_MODE_DISABLED:
|
||||
glDisable(GL_BLEND);
|
||||
break;
|
||||
}
|
||||
|
||||
glDrawBuffers(draw_buffers.size(), draw_buffers.ptr());
|
||||
|
||||
// DRAW!!
|
||||
glBindVertexArray(tex_blit_quad_array);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Reset to system FBO
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
|
||||
texture_2d_initialize(p_texture, texture_2d_placeholder);
|
||||
}
|
||||
|
|
@ -1537,6 +1799,17 @@ Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void TextureStorage::texture_drawable_generate_mipmaps(RID p_texture) {
|
||||
Texture *texture = get_texture(p_texture);
|
||||
Vector3i size = texture_get_size(p_texture);
|
||||
CopyEffects::get_singleton()->bilinear_blur(texture->tex_id, texture->mipmaps, Rect2i(0, 0, size.x, size.y));
|
||||
}
|
||||
|
||||
RID TextureStorage::texture_drawable_get_default_material() const {
|
||||
// This should never be called before DrawableTexture stuff is initialized.
|
||||
return tex_blit_shader.default_material;
|
||||
}
|
||||
|
||||
void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
|
||||
Texture *tex_to = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL(tex_to);
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ struct Texture {
|
|||
|
||||
Type type = TYPE_2D;
|
||||
RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
|
||||
RS::TextureDrawableFormat drawable_type = RS::TEXTURE_DRAWABLE_FORMAT_RGBA8;
|
||||
|
||||
GLenum target = GL_TEXTURE_2D;
|
||||
GLenum gl_format_cache = 0;
|
||||
|
|
@ -487,9 +488,25 @@ private:
|
|||
RID shader_version;
|
||||
} sdf_shader;
|
||||
|
||||
/* Texture Blit Shader API */
|
||||
|
||||
struct TexBlitShader {
|
||||
bool initialized = false;
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
RID default_shader_version;
|
||||
} tex_blit_shader;
|
||||
|
||||
GLuint tex_blit_fbo;
|
||||
GLuint tex_blit_quad;
|
||||
GLuint tex_blit_quad_array;
|
||||
|
||||
public:
|
||||
static TextureStorage *get_singleton();
|
||||
|
||||
void _tex_blit_shader_initialize();
|
||||
void _tex_blit_shader_free();
|
||||
|
||||
TextureStorage();
|
||||
virtual ~TextureStorage();
|
||||
|
||||
|
|
@ -535,6 +552,7 @@ public:
|
|||
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
|
||||
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
|
||||
virtual void texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) override;
|
||||
|
||||
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
|
||||
|
||||
|
|
@ -544,6 +562,8 @@ public:
|
|||
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
|
||||
void texture_remap_proxies(RID p_from_texture, RID p_to_texture);
|
||||
|
||||
virtual void texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) override;
|
||||
|
||||
Ref<Image> texture_2d_placeholder;
|
||||
Vector<Ref<Image>> texture_2d_array_placeholder;
|
||||
Vector<Ref<Image>> cubemap_placeholder;
|
||||
|
|
@ -558,6 +578,9 @@ public:
|
|||
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
|
||||
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;
|
||||
|
||||
virtual void texture_drawable_generate_mipmaps(RID p_texture) override;
|
||||
virtual RID texture_drawable_get_default_material() const override;
|
||||
|
||||
virtual void texture_replace(RID p_texture, RID p_by_texture) override;
|
||||
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -9225,6 +9225,10 @@ EditorNode::EditorNode() {
|
|||
canvas_item_mat_convert.instantiate();
|
||||
resource_conversion_plugins.push_back(canvas_item_mat_convert);
|
||||
|
||||
Ref<BlitMaterialConversionPlugin> blit_mat_convert;
|
||||
blit_mat_convert.instantiate();
|
||||
resource_conversion_plugins.push_back(blit_mat_convert);
|
||||
|
||||
Ref<ParticleProcessMaterialConversionPlugin> particles_mat_convert;
|
||||
particles_mat_convert.instantiate();
|
||||
resource_conversion_plugins.push_back(particles_mat_convert);
|
||||
|
|
|
|||
1
editor/icons/BlitMaterial.svg
Normal file
1
editor/icons/BlitMaterial.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><defs><linearGradient xlink:href="#a" id="b" x1="15.347" x2="15.347" y1="3.168" y2="17.103" gradientTransform="matrix(1.00467 0 0 1.04022 -7.419 -2.544)" gradientUnits="userSpaceOnUse"/></defs><linearGradient id="a" x2="0" y2="16" gradientUnits="userSpaceOnUse"><stop offset=".188" stop-color="#ff4545"/><stop stop-color="#ffe345"/><stop offset=".313" stop-color="#ffe345"/><stop stop-color="#80ff45"/><stop offset=".438" stop-color="#80ff45"/><stop stop-color="#45ffa2"/><stop offset=".563" stop-color="#45ffa2"/><stop stop-color="#45d7ff"/><stop offset=".688" stop-color="#45d7ff"/><stop stop-color="#8045ff"/><stop offset=".813" stop-color="#8045ff"/><stop stop-color="#ff4596"/></linearGradient><path fill="url(#b)" d="m 2.9291085,10.340767 c -0.2642273,0.312066 -0.4219599,0.759362 -0.4219599,1.287796 0,1.693483 -3.15264355,-0.18516 -0.3385726,2.777396 0.8881251,0.936201 2.6663848,0.696949 3.55451,-0.237171 a 2.3408729,2.4237201 0 0 0 0,-3.386967 C 4.6179529,9.6178118 3.5128197,9.6542196 2.9301132,10.340767 Z M 5.2398414,8.6348009 7.651041,11.131336 14.482773,4.0578184 a 1.7228275,1.783801 0 0 0 -2.4112,-2.5485469 z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
editor/icons/DrawableTexture2D.svg
Normal file
1
editor/icons/DrawableTexture2D.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="#e0e0e0" d="M 2,1 C 1.4477153,1 1,1.4477153 1,2 v 12 c 0,0.552285 0.4477153,1 1,1 h 12 c 0.552285,0 1,-0.447715 1,-1 V 2 C 15,1.4477153 14.552285,1 14,1 Z m 1,2 h 10 v 8 H 3 Z"/><path fill="#e0e0e0" d="M5 5V4H6V5H7V6H6V7H5V6H4V5ZM10 8V7h1v1h1v1h-1v1H10V9H9V8Z"/></svg>
|
||||
|
After Width: | Height: | Size: 344 B |
|
|
@ -42,6 +42,7 @@
|
|||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/subviewport_container.h"
|
||||
#include "scene/main/viewport.h"
|
||||
#include "scene/resources/blit_material.h"
|
||||
#include "scene/resources/canvas_item_material.h"
|
||||
#include "scene/resources/particle_process_material.h"
|
||||
|
||||
|
|
@ -499,3 +500,42 @@ Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p
|
|||
ERR_FAIL_COND_V(!Object::cast_to<CanvasItemMaterial>(*p_resource) || !Object::cast_to<CanvasItemMaterial>(*p_resource)->_is_initialized(), Ref<CanvasItemMaterial>());
|
||||
return MaterialEditor::make_shader_material(p_resource);
|
||||
}
|
||||
|
||||
String BlitMaterialConversionPlugin::converts_to() const {
|
||||
return "ShaderMaterial";
|
||||
}
|
||||
|
||||
bool BlitMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
|
||||
Ref<BlitMaterial> mat = p_resource;
|
||||
return mat.is_valid();
|
||||
}
|
||||
|
||||
Ref<Resource> BlitMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
|
||||
Ref<BlitMaterial> mat = p_resource;
|
||||
ERR_FAIL_COND_V(mat.is_null(), Ref<Resource>());
|
||||
|
||||
Ref<ShaderMaterial> smat;
|
||||
smat.instantiate();
|
||||
|
||||
Ref<Shader> shader;
|
||||
shader.instantiate();
|
||||
|
||||
String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid());
|
||||
|
||||
shader->set_code(code);
|
||||
|
||||
smat->set_shader(shader);
|
||||
|
||||
List<PropertyInfo> params;
|
||||
RS::get_singleton()->get_shader_parameter_list(mat->get_shader_rid(), ¶ms);
|
||||
|
||||
for (const PropertyInfo &E : params) {
|
||||
Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E.name);
|
||||
smat->set_shader_parameter(E.name, value);
|
||||
}
|
||||
|
||||
smat->set_render_priority(mat->get_render_priority());
|
||||
smat->set_local_to_scene(mat->is_local_to_scene());
|
||||
smat->set_name(mat->get_name());
|
||||
return smat;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,3 +153,12 @@ public:
|
|||
virtual bool handles(const Ref<Resource> &p_resource) const override;
|
||||
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const override;
|
||||
};
|
||||
|
||||
class BlitMaterialConversionPlugin : public EditorResourceConversionPlugin {
|
||||
GDCLASS(BlitMaterialConversionPlugin, EditorResourceConversionPlugin);
|
||||
|
||||
public:
|
||||
virtual String converts_to() const override;
|
||||
virtual bool handles(const Ref<Resource> &p_resource) const override;
|
||||
virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -379,6 +379,8 @@ void ShaderTextEditor::_check_shader_mode() {
|
|||
mode = Shader::MODE_SKY;
|
||||
} else if (type == "fog") {
|
||||
mode = Shader::MODE_FOG;
|
||||
} else if (type == "texture_blit") {
|
||||
mode = Shader::MODE_TEXTURE_BLIT;
|
||||
} else {
|
||||
mode = Shader::MODE_SPATIAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,6 +125,13 @@ void fog() {
|
|||
// of the associated FogVolume. This means that froxels that just barely touch
|
||||
// a given FogVolume will still be used.
|
||||
}
|
||||
)";
|
||||
} break;
|
||||
case Shader::MODE_TEXTURE_BLIT: {
|
||||
code += R"(
|
||||
void blit() {
|
||||
// Called for each pixel inside the given rect on the DrawableTexture.
|
||||
}
|
||||
)";
|
||||
} break;
|
||||
case Shader::MODE_MAX: {
|
||||
|
|
|
|||
|
|
@ -1732,6 +1732,10 @@ void VisualShaderEditor::_get_current_mode_limits(int &r_begin_type, int &r_end_
|
|||
} break;
|
||||
case Shader::MODE_FOG: {
|
||||
r_begin_type = VisualShader::TYPE_FOG;
|
||||
r_end_type = VisualShader::TYPE_TEXTURE_BLIT;
|
||||
} break;
|
||||
case Shader::MODE_TEXTURE_BLIT: {
|
||||
r_begin_type = VisualShader::TYPE_TEXTURE_BLIT;
|
||||
r_end_type = VisualShader::TYPE_MAX;
|
||||
} break;
|
||||
default: {
|
||||
|
|
@ -2470,6 +2474,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
|
|||
edit_type_particles->set_visible(false);
|
||||
edit_type_sky->set_visible(true);
|
||||
edit_type_fog->set_visible(false);
|
||||
edit_type_texture_blit->set_visible(false);
|
||||
edit_type = edit_type_sky;
|
||||
custom_mode_box->set_visible(false);
|
||||
varying_button->hide();
|
||||
|
|
@ -2479,6 +2484,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
|
|||
edit_type_particles->set_visible(false);
|
||||
edit_type_sky->set_visible(false);
|
||||
edit_type_fog->set_visible(true);
|
||||
edit_type_texture_blit->set_visible(false);
|
||||
edit_type = edit_type_fog;
|
||||
custom_mode_box->set_visible(false);
|
||||
varying_button->hide();
|
||||
|
|
@ -2488,6 +2494,7 @@ void VisualShaderEditor::_set_mode(int p_which) {
|
|||
edit_type_particles->set_visible(true);
|
||||
edit_type_sky->set_visible(false);
|
||||
edit_type_fog->set_visible(false);
|
||||
edit_type_texture_blit->set_visible(false);
|
||||
edit_type = edit_type_particles;
|
||||
if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
|
||||
custom_mode_box->set_visible(false);
|
||||
|
|
@ -2496,11 +2503,26 @@ void VisualShaderEditor::_set_mode(int p_which) {
|
|||
}
|
||||
varying_button->hide();
|
||||
mode = MODE_FLAGS_PARTICLES;
|
||||
} else if (p_which == VisualShader::MODE_TEXTURE_BLIT) {
|
||||
edit_type_standard->set_visible(false);
|
||||
edit_type_particles->set_visible(false);
|
||||
edit_type_sky->set_visible(false);
|
||||
edit_type_fog->set_visible(false);
|
||||
edit_type_texture_blit->set_visible(true);
|
||||
edit_type = edit_type_texture_blit;
|
||||
if ((edit_type->get_selected() + 3) > VisualShader::TYPE_PROCESS) {
|
||||
custom_mode_box->set_visible(false);
|
||||
} else {
|
||||
custom_mode_box->set_visible(true);
|
||||
}
|
||||
varying_button->hide();
|
||||
mode = MODE_FLAGS_TEXTURE_BLIT;
|
||||
} else {
|
||||
edit_type_particles->set_visible(false);
|
||||
edit_type_standard->set_visible(true);
|
||||
edit_type_sky->set_visible(false);
|
||||
edit_type_fog->set_visible(false);
|
||||
edit_type_texture_blit->set_visible(false);
|
||||
edit_type = edit_type_standard;
|
||||
custom_mode_box->set_visible(false);
|
||||
varying_button->show();
|
||||
|
|
@ -2519,6 +2541,9 @@ void VisualShaderEditor::_set_mode(int p_which) {
|
|||
upper_type = VisualShader::TYPE_FOG;
|
||||
} else if (mode & MODE_FLAGS_FOG) {
|
||||
default_type = VisualShader::TYPE_FOG;
|
||||
upper_type = VisualShader::TYPE_TEXTURE_BLIT;
|
||||
} else if (mode & MODE_FLAGS_TEXTURE_BLIT) {
|
||||
default_type = VisualShader::TYPE_TEXTURE_BLIT;
|
||||
upper_type = VisualShader::TYPE_MAX;
|
||||
}
|
||||
|
||||
|
|
@ -5679,6 +5704,8 @@ void VisualShaderEditor::_type_selected(int p_id) {
|
|||
offset = VisualShader::TYPE_SKY;
|
||||
} else if (mode & MODE_FLAGS_FOG) {
|
||||
offset = VisualShader::TYPE_FOG;
|
||||
} else if (mode & MODE_FLAGS_TEXTURE_BLIT) {
|
||||
offset = VisualShader::TYPE_TEXTURE_BLIT;
|
||||
}
|
||||
|
||||
set_current_shader_type(VisualShader::Type(p_id + offset));
|
||||
|
|
@ -6686,6 +6713,11 @@ VisualShaderEditor::VisualShaderEditor() {
|
|||
edit_type_fog->select(0);
|
||||
edit_type_fog->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
|
||||
|
||||
edit_type_texture_blit = memnew(OptionButton);
|
||||
edit_type_texture_blit->add_item(TTR("Blit"));
|
||||
edit_type_texture_blit->select(0);
|
||||
edit_type_texture_blit->connect(SceneStringName(item_selected), callable_mp(this, &VisualShaderEditor::_type_selected));
|
||||
|
||||
edit_type = edit_type_standard;
|
||||
|
||||
toolbar_hflow->add_child(custom_mode_box);
|
||||
|
|
@ -6698,6 +6730,8 @@ VisualShaderEditor::VisualShaderEditor() {
|
|||
toolbar_hflow->move_child(edit_type_sky, 0);
|
||||
toolbar_hflow->add_child(edit_type_fog);
|
||||
toolbar_hflow->move_child(edit_type_fog, 0);
|
||||
toolbar_hflow->add_child(edit_type_texture_blit);
|
||||
toolbar_hflow->move_child(edit_type_texture_blit, 0);
|
||||
|
||||
add_node = memnew(Button);
|
||||
add_node->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
|
|
@ -7192,6 +7226,7 @@ VisualShaderEditor::VisualShaderEditor() {
|
|||
const String input_param_for_fragment_shader_mode = TTR("'%s' input parameter for fragment shader mode.") + translation_gdsl;
|
||||
const String input_param_for_sky_shader_mode = TTR("'%s' input parameter for sky shader mode.") + translation_gdsl;
|
||||
const String input_param_for_fog_shader_mode = TTR("'%s' input parameter for fog shader mode.") + translation_gdsl;
|
||||
const String input_param_for_texture_blit_shader_mode = TTR("'%s' input parameter for blit shader mode.") + translation_gdsl;
|
||||
const String input_param_for_light_shader_mode = TTR("'%s' input parameter for light shader mode.") + translation_gdsl;
|
||||
const String input_param_for_vertex_shader_mode = TTR("'%s' input parameter for vertex shader mode.") + translation_gdsl;
|
||||
const String input_param_for_start_shader_mode = TTR("'%s' input parameter for start shader mode.") + translation_gdsl;
|
||||
|
|
@ -7341,6 +7376,15 @@ VisualShaderEditor::VisualShaderEditor() {
|
|||
add_options.push_back(AddOption("UVW", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "uvw", "UVW"), { "uvw" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
|
||||
add_options.push_back(AddOption("WorldPosition", "Input/Fog", "VisualShaderNodeInput", vformat(input_param_for_fog_shader_mode, "world_position", "WORLD_POSITION"), { "world_position" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FOG, Shader::MODE_FOG));
|
||||
|
||||
// TEXTURE BLIT INPUTS
|
||||
add_options.push_back(AddOption("UV", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "uv", "UV"), { "uv" }, VisualShaderNode::PORT_TYPE_VECTOR_2D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Modulate", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Modulate", "MODULATE"), { "Modulate" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Fragcoord", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Fragcoord", "FRAGCOORD"), { "Fragcoord" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Source Texture", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture", "source_texture"), { "Source Texture" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Source Texture 2", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 2", "source_texture2"), { "Source Texture 2" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Source Texture 3", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 3", "source_texture3"), { "Source Texture 3" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
add_options.push_back(AddOption("Source Texture 4", "Input/Texture_blit", "VisualShaderNodeInput", vformat(input_param_for_texture_blit_shader_mode, "Source Texture 4", "source_texture4"), { "Source Texture 4" }, VisualShaderNode::PORT_TYPE_SAMPLER, TYPE_FLAGS_BLIT, Shader::MODE_TEXTURE_BLIT));
|
||||
|
||||
// PARTICLES INPUTS
|
||||
|
||||
add_options.push_back(AddOption("CollisionDepth", "Input/Collide", "VisualShaderNodeInput", vformat(input_param_for_collide_shader_mode, "collision_depth", "COLLISION_DEPTH"), { "collision_depth" }, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_COLLIDE, Shader::MODE_PARTICLES));
|
||||
|
|
@ -8288,7 +8332,7 @@ void EditorPropertyVisualShaderMode::_option_selected(int p_which) {
|
|||
}
|
||||
|
||||
//4. delete varyings (if needed)
|
||||
if (p_which == VisualShader::MODE_PARTICLES || p_which == VisualShader::MODE_SKY || p_which == VisualShader::MODE_FOG) {
|
||||
if (p_which == VisualShader::MODE_PARTICLES || p_which == VisualShader::MODE_SKY || p_which == VisualShader::MODE_FOG || p_which == VisualShader::MODE_TEXTURE_BLIT) {
|
||||
int var_count = visual_shader->get_varyings_count();
|
||||
|
||||
if (var_count > 0) {
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ class VisualShaderEditor : public ShaderEditor {
|
|||
OptionButton *edit_type_particles = nullptr;
|
||||
OptionButton *edit_type_sky = nullptr;
|
||||
OptionButton *edit_type_fog = nullptr;
|
||||
OptionButton *edit_type_texture_blit = nullptr;
|
||||
CheckBox *custom_mode_box = nullptr;
|
||||
bool custom_mode_enabled = false;
|
||||
|
||||
|
|
@ -297,6 +298,7 @@ class VisualShaderEditor : public ShaderEditor {
|
|||
MODE_FLAGS_SKY = 2,
|
||||
MODE_FLAGS_PARTICLES = 4,
|
||||
MODE_FLAGS_FOG = 8,
|
||||
MODE_FLAGS_TEXTURE_BLIT = 16,
|
||||
};
|
||||
|
||||
int mode = MODE_FLAGS_SPATIAL_CANVASITEM;
|
||||
|
|
@ -324,6 +326,10 @@ class VisualShaderEditor : public ShaderEditor {
|
|||
TYPE_FLAGS_FOG = 1,
|
||||
};
|
||||
|
||||
enum TextureBlitTypeFlags {
|
||||
TYPE_FLAGS_BLIT = 1,
|
||||
};
|
||||
|
||||
enum ToolsMenuOptions {
|
||||
EXPAND_ALL,
|
||||
COLLAPSE_ALL
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
#include "scene/resources/audio_stream_polyphonic.h"
|
||||
#include "scene/resources/audio_stream_wav.h"
|
||||
#include "scene/resources/bit_map.h"
|
||||
#include "scene/resources/blit_material.h"
|
||||
#include "scene/resources/bone_map.h"
|
||||
#include "scene/resources/camera_attributes.h"
|
||||
#include "scene/resources/camera_texture.h"
|
||||
|
|
@ -121,6 +122,7 @@
|
|||
#include "scene/resources/compositor.h"
|
||||
#include "scene/resources/compressed_texture.h"
|
||||
#include "scene/resources/curve_texture.h"
|
||||
#include "scene/resources/drawable_texture_2d.h"
|
||||
#include "scene/resources/environment.h"
|
||||
#include "scene/resources/external_texture.h"
|
||||
#include "scene/resources/font.h"
|
||||
|
|
@ -889,8 +891,10 @@ void register_scene_types() {
|
|||
GDREGISTER_CLASS(ShaderMaterial);
|
||||
GDREGISTER_CLASS(CanvasTexture);
|
||||
GDREGISTER_CLASS(CanvasItemMaterial);
|
||||
|
||||
SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes);
|
||||
CanvasItemMaterial::init_shaders();
|
||||
GDREGISTER_CLASS(BlitMaterial);
|
||||
|
||||
/* REGISTER 2D */
|
||||
|
||||
|
|
@ -1057,6 +1061,7 @@ void register_scene_types() {
|
|||
GDREGISTER_CLASS(GradientTexture2D);
|
||||
GDREGISTER_CLASS(CameraTexture);
|
||||
GDREGISTER_CLASS(ExternalTexture);
|
||||
GDREGISTER_CLASS(DrawableTexture2D);
|
||||
GDREGISTER_VIRTUAL_CLASS(TextureLayered);
|
||||
GDREGISTER_ABSTRACT_CLASS(ImageTextureLayered);
|
||||
GDREGISTER_VIRTUAL_CLASS(Texture3D);
|
||||
|
|
@ -1475,6 +1480,7 @@ void unregister_scene_types() {
|
|||
ParticleProcessMaterial::finish_shaders();
|
||||
CanvasItemMaterial::finish_shaders();
|
||||
ColorPickerShape::finish_shaders();
|
||||
BlitMaterial::cleanup_shader();
|
||||
GraphEdit::finish_shaders();
|
||||
SceneStringNames::free();
|
||||
|
||||
|
|
|
|||
140
scene/resources/blit_material.cpp
Normal file
140
scene/resources/blit_material.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/**************************************************************************/
|
||||
/* blit_material.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "blit_material.h"
|
||||
|
||||
#include "core/version.h"
|
||||
|
||||
void BlitMaterial::_update_shader(BlendMode p_blend) {
|
||||
MutexLock shader_lock(shader_mutex);
|
||||
int index = int(p_blend);
|
||||
if (shader_cache[p_blend].is_null()) {
|
||||
shader_cache[p_blend] = RS::get_singleton()->shader_create();
|
||||
String code = "// NOTE: Shader automatically converted from " GODOT_VERSION_NAME " " GODOT_VERSION_FULL_CONFIG "'s BlitMaterial.\n\n";
|
||||
|
||||
code += "shader_type texture_blit;\nrender_mode ";
|
||||
switch (p_blend) {
|
||||
case BLEND_MODE_MIX:
|
||||
code += "blend_mix";
|
||||
break;
|
||||
case BLEND_MODE_ADD:
|
||||
code += "blend_add";
|
||||
break;
|
||||
case BLEND_MODE_SUB:
|
||||
code += "blend_sub";
|
||||
break;
|
||||
case BLEND_MODE_MUL:
|
||||
code += "blend_mul";
|
||||
break;
|
||||
case BLEND_MODE_DISABLED:
|
||||
code += "blend_disabled";
|
||||
break;
|
||||
default:
|
||||
code += "blend_mix";
|
||||
break;
|
||||
}
|
||||
code += ";\n\n";
|
||||
|
||||
code += "uniform sampler2D source_texture0 : hint_blit_source0;\n";
|
||||
code += "uniform sampler2D source_texture1 : hint_blit_source1;\n";
|
||||
code += "uniform sampler2D source_texture2 : hint_blit_source2;\n";
|
||||
code += "uniform sampler2D source_texture3 : hint_blit_source3;\n\n";
|
||||
|
||||
code += "void blit() {\n";
|
||||
code += " // Copies from each whole source texture to a rect on each output texture.\n";
|
||||
code += " COLOR0 = texture(source_texture0, UV) * MODULATE;\n";
|
||||
code += " COLOR1 = texture(source_texture1, UV) * MODULATE;\n";
|
||||
code += " COLOR2 = texture(source_texture2, UV) * MODULATE;\n";
|
||||
code += " COLOR3 = texture(source_texture3, UV) * MODULATE;\n}";
|
||||
RS::get_singleton()->shader_set_code(shader_cache[index], code);
|
||||
}
|
||||
}
|
||||
|
||||
void BlitMaterial::set_blend_mode(BlendMode p_blend_mode) {
|
||||
blend_mode = p_blend_mode;
|
||||
_update_shader(blend_mode);
|
||||
if (shader_set) {
|
||||
RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(blend_mode)]);
|
||||
}
|
||||
}
|
||||
|
||||
BlitMaterial::BlendMode BlitMaterial::get_blend_mode() const {
|
||||
return blend_mode;
|
||||
}
|
||||
|
||||
RID BlitMaterial::get_shader_rid() const {
|
||||
_update_shader(blend_mode);
|
||||
return shader_cache[int(blend_mode)];
|
||||
}
|
||||
|
||||
Shader::Mode BlitMaterial::get_shader_mode() const {
|
||||
return Shader::MODE_TEXTURE_BLIT;
|
||||
}
|
||||
|
||||
RID BlitMaterial::get_rid() const {
|
||||
_update_shader(blend_mode);
|
||||
if (!shader_set) {
|
||||
RS::get_singleton()->material_set_shader(_get_material(), shader_cache[int(blend_mode)]);
|
||||
shader_set = true;
|
||||
}
|
||||
return _get_material();
|
||||
}
|
||||
|
||||
Mutex BlitMaterial::shader_mutex;
|
||||
RID BlitMaterial::shader_cache[5];
|
||||
|
||||
void BlitMaterial::cleanup_shader() {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (shader_cache[i].is_valid()) {
|
||||
RS::get_singleton()->free_rid(shader_cache[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlitMaterial::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &BlitMaterial::set_blend_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_mode"), &BlitMaterial::get_blend_mode);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Subtract,Multiply,Disabled"), "set_blend_mode", "get_blend_mode");
|
||||
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_MIX);
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_ADD);
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_SUB);
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_MUL);
|
||||
BIND_ENUM_CONSTANT(BLEND_MODE_DISABLED);
|
||||
}
|
||||
|
||||
BlitMaterial::BlitMaterial() {
|
||||
_set_material(RS::get_singleton()->material_create());
|
||||
set_blend_mode(BLEND_MODE_MIX);
|
||||
}
|
||||
|
||||
BlitMaterial::~BlitMaterial() {
|
||||
}
|
||||
72
scene/resources/blit_material.h
Normal file
72
scene/resources/blit_material.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/**************************************************************************/
|
||||
/* blit_material.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scene/resources/material.h"
|
||||
|
||||
class BlitMaterial : public Material {
|
||||
GDCLASS(BlitMaterial, Material);
|
||||
|
||||
public:
|
||||
enum BlendMode {
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_DISABLED
|
||||
};
|
||||
|
||||
private:
|
||||
static Mutex shader_mutex;
|
||||
static RID shader_cache[5];
|
||||
static void _update_shader(BlendMode p_blend);
|
||||
mutable bool shader_set = false;
|
||||
|
||||
BlendMode blend_mode = BLEND_MODE_MIX;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_blend_mode(BlendMode p_blend_mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
|
||||
virtual Shader::Mode get_shader_mode() const override;
|
||||
virtual RID get_shader_rid() const override;
|
||||
virtual RID get_rid() const override;
|
||||
|
||||
static void cleanup_shader();
|
||||
|
||||
BlitMaterial();
|
||||
virtual ~BlitMaterial();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(BlitMaterial::BlendMode);
|
||||
241
scene/resources/drawable_texture_2d.cpp
Normal file
241
scene/resources/drawable_texture_2d.cpp
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/**************************************************************************/
|
||||
/* drawable_texture_2d.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "drawable_texture_2d.h"
|
||||
|
||||
DrawableTexture2D::DrawableTexture2D() {
|
||||
default_material = RS::get_singleton()->texture_drawable_get_default_material();
|
||||
}
|
||||
|
||||
DrawableTexture2D::~DrawableTexture2D() {
|
||||
if (texture.is_valid()) {
|
||||
ERR_FAIL_NULL(RenderingServer::get_singleton());
|
||||
RenderingServer::get_singleton()->free_rid(texture);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Texture Resource with a call to rendering server. Overwrite existing.
|
||||
void DrawableTexture2D::_initialize() {
|
||||
if (texture.is_valid()) {
|
||||
RID new_texture = RS::get_singleton()->texture_drawable_create(width, height, (RS::TextureDrawableFormat)format, base_color, mipmaps);
|
||||
RS::get_singleton()->texture_replace(texture, new_texture);
|
||||
} else {
|
||||
texture = RS::get_singleton()->texture_drawable_create(width, height, (RS::TextureDrawableFormat)format, base_color, mipmaps);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup basic parameters on the Drawable Texture
|
||||
void DrawableTexture2D::setup(int p_width, int p_height, DrawableFormat p_format, const Color &p_color, bool p_use_mipmaps) {
|
||||
ERR_FAIL_COND_MSG(p_width <= 0 || p_width > 16384, "Texture dimensions have to be in the 1 to 16384 range.");
|
||||
ERR_FAIL_COND_MSG(p_height <= 0 || p_height > 16384, "Texture dimensions have to be in the 1 to 16384 range.");
|
||||
width = p_width;
|
||||
height = p_height;
|
||||
format = p_format;
|
||||
mipmaps = p_use_mipmaps;
|
||||
base_color = p_color;
|
||||
_initialize();
|
||||
notify_property_list_changed();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
void DrawableTexture2D::set_width(int p_width) {
|
||||
ERR_FAIL_COND_MSG(p_width <= 0 || p_width > 16384, "Texture dimensions have to be in the 1 to 16384 range.");
|
||||
if (width == p_width) {
|
||||
return;
|
||||
}
|
||||
width = p_width;
|
||||
notify_property_list_changed();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
int DrawableTexture2D::get_width() const {
|
||||
return width;
|
||||
}
|
||||
|
||||
void DrawableTexture2D::set_height(int p_height) {
|
||||
ERR_FAIL_COND_MSG(p_height <= 0 || p_height > 16384, "Texture dimensions have to be in the 1 to 16384 range.");
|
||||
if (height == p_height) {
|
||||
return;
|
||||
}
|
||||
height = p_height;
|
||||
notify_property_list_changed();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
int DrawableTexture2D::get_height() const {
|
||||
return height;
|
||||
}
|
||||
|
||||
void DrawableTexture2D::set_format(DrawableFormat p_format) {
|
||||
if (format == p_format) {
|
||||
return;
|
||||
}
|
||||
format = p_format;
|
||||
notify_property_list_changed();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
DrawableTexture2D::DrawableFormat DrawableTexture2D::get_format() const {
|
||||
return format;
|
||||
}
|
||||
|
||||
void DrawableTexture2D::set_use_mipmaps(bool p_mipmaps) {
|
||||
if (mipmaps == p_mipmaps) {
|
||||
return;
|
||||
}
|
||||
mipmaps = p_mipmaps;
|
||||
notify_property_list_changed();
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
bool DrawableTexture2D::get_use_mipmaps() const {
|
||||
return mipmaps;
|
||||
}
|
||||
|
||||
RID DrawableTexture2D::get_rid() const {
|
||||
if (texture.is_null()) {
|
||||
// We are in trouble, create something temporary.
|
||||
// 4, 4, false, Image::FORMAT_RGBA8
|
||||
texture = RenderingServer::get_singleton()->texture_2d_placeholder_create();
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
void DrawableTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
|
||||
if ((width | height) == 0) {
|
||||
return;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(width, height)), texture, false, p_modulate, p_transpose);
|
||||
}
|
||||
|
||||
void DrawableTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
|
||||
if ((width | height) == 0) {
|
||||
return;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose);
|
||||
}
|
||||
|
||||
void DrawableTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const {
|
||||
if ((width | height) == 0) {
|
||||
return;
|
||||
}
|
||||
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv);
|
||||
}
|
||||
|
||||
// Perform a blit operation from the given source to the given rect on self.
|
||||
void DrawableTexture2D::blit_rect(const Rect2i p_rect, const Ref<Texture2D> &p_source, const Color &p_modulate, int p_mipmap, const Ref<Material> &p_material) {
|
||||
// Use user Shader if exists.
|
||||
RID material = default_material;
|
||||
if (p_material.is_valid()) {
|
||||
material = p_material->get_rid();
|
||||
if (p_material->get_shader_mode() != Shader::MODE_TEXTURE_BLIT) {
|
||||
WARN_PRINT("ShaderMaterial passed to blit_rect() is not a texture_blit shader. Using default instead.");
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering server expects textureParameters as a TypedArray[RID]
|
||||
Array textures;
|
||||
textures.push_back(texture);
|
||||
|
||||
if (p_source.is_valid()) {
|
||||
ERR_FAIL_COND_MSG(texture == p_source->get_rid(), "Cannot use self as a source.");
|
||||
}
|
||||
Array src_textures;
|
||||
if (Ref<AtlasTexture>(p_source).is_valid()) {
|
||||
WARN_PRINT("AtlasTexture not supported as a source for blit_rect. Using default White.");
|
||||
src_textures.push_back(RID());
|
||||
} else {
|
||||
src_textures.push_back(p_source);
|
||||
}
|
||||
|
||||
RS::get_singleton()->texture_drawable_blit_rect(textures, p_rect, material, p_modulate, src_textures, p_mipmap);
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
// Perform a blit operation from the given sources to the given rect on self and extra targets
|
||||
void DrawableTexture2D::blit_rect_multi(const Rect2i p_rect, const TypedArray<Texture2D> &p_sources, const TypedArray<DrawableTexture2D> &p_extra_targets, const Color &p_modulate, int p_mipmap, const Ref<Material> &p_material) {
|
||||
RID material = default_material;
|
||||
if (p_material.is_valid()) {
|
||||
material = p_material->get_rid();
|
||||
if (p_material->get_shader_mode() != Shader::MODE_TEXTURE_BLIT) {
|
||||
WARN_PRINT("ShaderMaterial passed to blit_rect_multi() is not a texture_blit shader. Using default instead.");
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering server expects textureParameters as a TypedArray[RID]
|
||||
Array textures;
|
||||
textures.push_back(texture);
|
||||
int i = 0;
|
||||
while (i < p_extra_targets.size()) {
|
||||
textures.push_back(RID(p_extra_targets[i]));
|
||||
i += 1;
|
||||
}
|
||||
i = 0;
|
||||
Array src_textures;
|
||||
while (i < p_sources.size()) {
|
||||
if (Ref<AtlasTexture>(p_sources[i]).is_valid()) {
|
||||
WARN_PRINT("AtlasTexture not supported as a source for blit_rect. Using default White.");
|
||||
src_textures.push_back(RID());
|
||||
} else {
|
||||
src_textures.push_back(RID(p_sources[i]));
|
||||
}
|
||||
ERR_FAIL_COND_MSG(textures.has(RID(src_textures[i])), "Cannot use self as a source.");
|
||||
i += 1;
|
||||
}
|
||||
|
||||
RS::get_singleton()->texture_drawable_blit_rect(textures, p_rect, material, p_modulate, src_textures, p_mipmap);
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
Ref<Image> DrawableTexture2D::get_image() const {
|
||||
if (texture.is_valid()) {
|
||||
return RS::get_singleton()->texture_2d_get(texture);
|
||||
} else {
|
||||
return Ref<Image>();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableTexture2D::generate_mipmaps() {
|
||||
if (texture.is_valid()) {
|
||||
RS::get_singleton()->texture_drawable_generate_mipmaps(texture);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawableTexture2D::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("setup", "width", "height", "format", "color", "use_mipmaps"), &DrawableTexture2D::setup, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("blit_rect", "rect", "source", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref<Material>()));
|
||||
ClassDB::bind_method(D_METHOD("blit_rect_multi", "rect", "sources", "extra_targets", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect_multi, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref<Material>()));
|
||||
ClassDB::bind_method(D_METHOD("generate_mipmaps"), &DrawableTexture2D::generate_mipmaps);
|
||||
|
||||
BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBA8);
|
||||
BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBA8_SRGB);
|
||||
BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBAH);
|
||||
BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBAF);
|
||||
}
|
||||
95
scene/resources/drawable_texture_2d.h
Normal file
95
scene/resources/drawable_texture_2d.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/**************************************************************************/
|
||||
/* drawable_texture_2d.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "scene/resources/atlas_texture.h"
|
||||
#include "scene/resources/image_texture.h"
|
||||
#include "scene/resources/material.h"
|
||||
|
||||
class DrawableTexture2D : public Texture2D {
|
||||
GDCLASS(DrawableTexture2D, Texture2D);
|
||||
RES_BASE_EXTENSION("tex");
|
||||
|
||||
public:
|
||||
enum DrawableFormat {
|
||||
DRAWABLE_FORMAT_RGBA8,
|
||||
DRAWABLE_FORMAT_RGBA8_SRGB,
|
||||
DRAWABLE_FORMAT_RGBAH,
|
||||
DRAWABLE_FORMAT_RGBAF,
|
||||
};
|
||||
|
||||
private:
|
||||
mutable RID texture;
|
||||
int width = 64;
|
||||
int height = 64;
|
||||
bool mipmaps = false;
|
||||
DrawableFormat format = DRAWABLE_FORMAT_RGBA8;
|
||||
|
||||
Color base_color = Color(1, 1, 1, 1);
|
||||
|
||||
RID default_material;
|
||||
|
||||
void _initialize();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_width(int p_width);
|
||||
int get_width() const override;
|
||||
void set_height(int p_height);
|
||||
int get_height() const override;
|
||||
|
||||
void set_format(DrawableFormat p_format);
|
||||
DrawableFormat get_format() const;
|
||||
void set_use_mipmaps(bool p_mipmaps);
|
||||
bool get_use_mipmaps() const;
|
||||
|
||||
virtual RID get_rid() const override;
|
||||
|
||||
virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const override;
|
||||
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const override;
|
||||
virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = true) const override;
|
||||
|
||||
void setup(int p_width, int p_height, DrawableFormat p_format, const Color &p_modulate = Color(1, 1, 1, 1), bool p_use_mipmaps = false);
|
||||
|
||||
void blit_rect(const Rect2i p_rect, const Ref<Texture2D> &p_source, const Color &p_modulate = Color(1, 1, 1, 1), int p_mipmap = 0, const Ref<Material> &p_material = Ref<Material>());
|
||||
void blit_rect_multi(const Rect2i p_rect, const TypedArray<Texture2D> &p_sources, const TypedArray<DrawableTexture2D> &p_extra_targets, const Color &p_modulate = Color(1, 1, 1, 1), int p_mipmap = 0, const Ref<Material> &p_material = Ref<Material>());
|
||||
|
||||
virtual Ref<Image> get_image() const override;
|
||||
|
||||
void generate_mipmaps();
|
||||
|
||||
DrawableTexture2D();
|
||||
~DrawableTexture2D();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(DrawableTexture2D::DrawableFormat)
|
||||
|
|
@ -118,6 +118,8 @@ void Shader::set_code(const String &p_code) {
|
|||
mode = MODE_SKY;
|
||||
} else if (type == "fog") {
|
||||
mode = MODE_FOG;
|
||||
} else if (type == "texture_blit") {
|
||||
mode = MODE_TEXTURE_BLIT;
|
||||
} else {
|
||||
mode = MODE_SPATIAL;
|
||||
}
|
||||
|
|
@ -290,6 +292,7 @@ void Shader::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(MODE_PARTICLES);
|
||||
BIND_ENUM_CONSTANT(MODE_SKY);
|
||||
BIND_ENUM_CONSTANT(MODE_FOG);
|
||||
BIND_ENUM_CONSTANT(MODE_TEXTURE_BLIT);
|
||||
}
|
||||
|
||||
Shader::Shader() {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public:
|
|||
MODE_PARTICLES,
|
||||
MODE_SKY,
|
||||
MODE_FOG,
|
||||
MODE_TEXTURE_BLIT,
|
||||
MODE_MAX
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "visual_shader_particle_nodes.h"
|
||||
|
||||
String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) {
|
||||
static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
|
||||
static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog", "texture_blit" };
|
||||
return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id);
|
||||
}
|
||||
|
||||
|
|
@ -1718,6 +1718,7 @@ static const char *type_string[VisualShader::TYPE_MAX] = {
|
|||
"process_custom",
|
||||
"sky",
|
||||
"fog",
|
||||
"texture_blit",
|
||||
};
|
||||
|
||||
bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
|
||||
|
|
@ -1958,7 +1959,7 @@ void VisualShader::reset_state() {
|
|||
|
||||
void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
|
||||
//mode
|
||||
p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Spatial,CanvasItem,Particles,Sky,Fog"));
|
||||
p_list->push_back(PropertyInfo(Variant::INT, PNAME("mode"), PROPERTY_HINT_ENUM, "Spatial,CanvasItem,Particles,Sky,Fog,TextureBlit"));
|
||||
//render modes
|
||||
|
||||
HashMap<String, String> blend_mode_enums;
|
||||
|
|
@ -2683,7 +2684,7 @@ void VisualShader::_update_shader() const {
|
|||
Vector<VisualShader::DefaultTextureParam> default_tex_params;
|
||||
HashSet<StringName> classes;
|
||||
HashMap<int, int> insertion_pos;
|
||||
static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles", "sky", "fog" };
|
||||
static const char *shader_mode_str[Shader::MODE_MAX] = { "spatial", "canvas_item", "particles", "sky", "fog", "texture_blit" };
|
||||
|
||||
global_code += String() + "shader_type " + shader_mode_str[shader_mode] + ";\n";
|
||||
|
||||
|
|
@ -2786,7 +2787,7 @@ void VisualShader::_update_shader() const {
|
|||
global_code += "stencil_mode " + stencil_mode + ";\n\n";
|
||||
}
|
||||
|
||||
static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
|
||||
static const char *func_name[TYPE_MAX] = { "vertex", "fragment", "light", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog", "blit" };
|
||||
|
||||
String global_expressions;
|
||||
HashSet<String> used_parameter_names;
|
||||
|
|
@ -2794,6 +2795,13 @@ void VisualShader::_update_shader() const {
|
|||
HashMap<int, List<int>> emitters;
|
||||
HashMap<int, List<int>> varying_setters;
|
||||
|
||||
if (shader_mode == Shader::MODE_TEXTURE_BLIT) {
|
||||
global_code += "uniform sampler2D source_texture0 : hint_blit_source0;\n";
|
||||
global_code += "uniform sampler2D source_texture1 : hint_blit_source1;\n";
|
||||
global_code += "uniform sampler2D source_texture2 : hint_blit_source2;\n";
|
||||
global_code += "uniform sampler2D source_texture3 : hint_blit_source3;\n\n";
|
||||
}
|
||||
|
||||
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
|
||||
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
|
||||
continue;
|
||||
|
|
@ -2905,7 +2913,7 @@ void VisualShader::_update_shader() const {
|
|||
HashSet<int> processed;
|
||||
|
||||
bool is_empty_func = false;
|
||||
if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG) {
|
||||
if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG && shader_mode != Shader::MODE_TEXTURE_BLIT) {
|
||||
is_empty_func = true;
|
||||
}
|
||||
|
||||
|
|
@ -3221,6 +3229,7 @@ void VisualShader::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(TYPE_PROCESS_CUSTOM);
|
||||
BIND_ENUM_CONSTANT(TYPE_SKY);
|
||||
BIND_ENUM_CONSTANT(TYPE_FOG);
|
||||
BIND_ENUM_CONSTANT(TYPE_TEXTURE_BLIT);
|
||||
BIND_ENUM_CONSTANT(TYPE_MAX);
|
||||
|
||||
BIND_ENUM_CONSTANT(VARYING_MODE_VERTEX_TO_FRAG_LIGHT);
|
||||
|
|
@ -3550,6 +3559,15 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
|
|||
{ Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "uvw", "UVW" },
|
||||
{ Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "world_position", "WORLD_POSITION" },
|
||||
|
||||
// Blit, Blit
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "modulate", "MODULATE" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_SAMPLER, "source_texture", "source_texture" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_SAMPLER, "source_texture2", "source_texture2" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_SAMPLER, "source_texture3", "source_texture3" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_SAMPLER, "source_texture4", "source_texture4" },
|
||||
|
||||
{ Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
|
||||
};
|
||||
|
||||
|
|
@ -3630,6 +3648,11 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::preview_ports[] = {
|
|||
|
||||
{ Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
|
||||
|
||||
// Blit
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "modulate", "MODULATE" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "uv", "UV" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_SAMPLER, "source_texture", "source_texture" },
|
||||
|
||||
{ Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
|
||||
};
|
||||
|
||||
|
|
@ -4265,6 +4288,14 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
|
|||
{ Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Albedo", "ALBEDO" },
|
||||
{ Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR_3D, "Emission", "EMISSION" },
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Blit, Blit.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color0", "COLOR0" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color1", "COLOR1" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color2", "COLOR2" },
|
||||
{ Shader::MODE_TEXTURE_BLIT, VisualShader::TYPE_TEXTURE_BLIT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "Color3", "COLOR3" },
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
{ Shader::MODE_MAX, VisualShader::TYPE_MAX, VisualShaderNode::PORT_TYPE_TRANSFORM, nullptr, nullptr },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public:
|
|||
TYPE_PROCESS_CUSTOM,
|
||||
TYPE_SKY,
|
||||
TYPE_FOG,
|
||||
TYPE_TEXTURE_BLIT,
|
||||
TYPE_MAX
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
|
|||
new_mode = RS::SHADER_SKY;
|
||||
} else if (mode_string == "fog") {
|
||||
new_mode = RS::SHADER_FOG;
|
||||
} else if (mode_string == "texture_blit") {
|
||||
new_mode = RS::SHADER_TEXTURE_BLIT;
|
||||
} else {
|
||||
new_mode = RS::SHADER_MAX;
|
||||
ERR_FAIL_MSG("Shader type " + mode_string + " not supported in Dummy renderer.");
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public:
|
|||
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override {}
|
||||
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {}
|
||||
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override {} //all slices, then all the mipmaps, must be coherent
|
||||
virtual void texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) override {}
|
||||
|
||||
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override { return RID(); }
|
||||
|
||||
|
|
@ -96,6 +97,8 @@ public:
|
|||
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override {}
|
||||
virtual void texture_proxy_update(RID p_proxy, RID p_base) override {}
|
||||
|
||||
virtual void texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) override {}
|
||||
|
||||
//these two APIs can be used together or in combination with the others.
|
||||
virtual void texture_2d_placeholder_initialize(RID p_texture) override {}
|
||||
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) override {}
|
||||
|
|
@ -109,6 +112,9 @@ public:
|
|||
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override { return Ref<Image>(); }
|
||||
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override { return Vector<Ref<Image>>(); }
|
||||
|
||||
virtual void texture_drawable_generate_mipmaps(RID p_texture) override {}
|
||||
virtual RID texture_drawable_get_default_material() const override { return RID(); }
|
||||
|
||||
virtual void texture_replace(RID p_texture, RID p_by_texture) override { texture_free(p_by_texture); }
|
||||
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override {}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ void RendererCompositorRD::initialize() {
|
|||
uint64_t RendererCompositorRD::frame = 1;
|
||||
|
||||
void RendererCompositorRD::finalize() {
|
||||
texture_storage->_tex_blit_shader_free();
|
||||
memdelete(scene);
|
||||
memdelete(canvas);
|
||||
memdelete(fog);
|
||||
|
|
@ -318,6 +319,7 @@ RendererCompositorRD::RendererCompositorRD() {
|
|||
particles_storage = memnew(RendererRD::ParticlesStorage);
|
||||
fog = memnew(RendererRD::Fog);
|
||||
canvas = memnew(RendererCanvasRenderRD());
|
||||
texture_storage->_tex_blit_shader_initialize();
|
||||
|
||||
String rendering_method = OS::get_singleton()->get_current_rendering_method();
|
||||
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
|
||||
|
|
|
|||
128
servers/rendering/renderer_rd/shaders/tex_blit.glsl
Normal file
128
servers/rendering/renderer_rd/shaders/tex_blit.glsl
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
/* clang-format off */
|
||||
|
||||
#[vertex]
|
||||
|
||||
#version 450
|
||||
|
||||
// Has to be same push_constant for vertex & frag
|
||||
layout(push_constant, std430) uniform TexBlitData {
|
||||
vec2 offset;
|
||||
vec2 size;
|
||||
vec4 modulate;
|
||||
vec2 pad;
|
||||
int convert_to_srgb;
|
||||
float time;
|
||||
} data;
|
||||
|
||||
layout(location = 0) out vec2 uv;
|
||||
|
||||
void main() {
|
||||
vec2 base_arr[6] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(0.0), vec2(1.0, 0.0), vec2(1.0, 1.0));
|
||||
uv = base_arr[gl_VertexIndex];
|
||||
// gl_Position = vec4(uv * 2.0 - 1.0, 0.0, 1.0);
|
||||
|
||||
gl_Position = vec4( (data.offset + (uv * data.size)) * 2.0 - 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
#[fragment]
|
||||
|
||||
#version 450
|
||||
|
||||
#VERSION_DEFINES
|
||||
|
||||
#include "samplers_inc.glsl"
|
||||
|
||||
#define OUTPUT0_SRGB uint(1)
|
||||
#define OUTPUT1_SRGB uint(2)
|
||||
#define OUTPUT2_SRGB uint(4)
|
||||
#define OUTPUT3_SRGB uint(8)
|
||||
|
||||
layout(push_constant, std430) uniform TexBlitData {
|
||||
vec2 offset;
|
||||
vec2 size;
|
||||
vec4 modulate;
|
||||
vec2 pad;
|
||||
int convert_to_srgb;
|
||||
float time;
|
||||
} data;
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D source0;
|
||||
|
||||
layout(set = 0, binding = 1) uniform texture2D source1;
|
||||
|
||||
layout(set = 0, binding = 2) uniform texture2D source2;
|
||||
|
||||
layout(set = 0, binding = 3) uniform texture2D source3;
|
||||
|
||||
layout(location = 0) in vec2 uv;
|
||||
|
||||
layout (location = 0) out vec4 out_color0;
|
||||
|
||||
#ifdef USE_OUTPUT1
|
||||
layout (location = 1) out vec4 out_color1;
|
||||
#endif
|
||||
|
||||
#ifdef USE_OUTPUT2
|
||||
layout (location = 2) out vec4 out_color2;
|
||||
#endif
|
||||
|
||||
#ifdef USE_OUTPUT3
|
||||
layout (location = 3) out vec4 out_color3;
|
||||
#endif
|
||||
|
||||
#ifdef MATERIAL_UNIFORMS_USED
|
||||
layout(set = 1, binding = 0, std140) uniform MaterialUniforms {
|
||||
#MATERIAL_UNIFORMS
|
||||
} material;
|
||||
#endif
|
||||
|
||||
#GLOBALS
|
||||
|
||||
vec3 linear_to_srgb(vec3 color) {
|
||||
// If going to srgb, clamp from 0 to 1.
|
||||
color = clamp(color, vec3(0.0), vec3(1.0));
|
||||
const vec3 a = vec3(0.055f);
|
||||
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Handles the case where user code uses extra outputs, but extra output targets were not bound
|
||||
vec4 color0 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color1 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color2 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 color3 = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
#CODE : BLIT
|
||||
|
||||
// Discards extra outputs if extra output targets were not bound
|
||||
out_color0 = color0;
|
||||
|
||||
#ifdef USE_OUTPUT1
|
||||
out_color1 = color1;
|
||||
#endif
|
||||
#ifdef USE_OUTPUT2
|
||||
out_color2 = color2;
|
||||
#endif
|
||||
#ifdef USE_OUTPUT3
|
||||
out_color3 = color3;
|
||||
#endif
|
||||
|
||||
if (bool(data.convert_to_srgb & OUTPUT0_SRGB)) {
|
||||
out_color0.rgb = linear_to_srgb(out_color0.rgb); // Regular linear -> SRGB conversion.
|
||||
}
|
||||
#ifdef USE_OUTPUT1
|
||||
if (bool(data.convert_to_srgb & OUTPUT1_SRGB)) {
|
||||
out_color1.rgb = linear_to_srgb(out_color1.rgb);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OUTPUT2
|
||||
if (bool(data.convert_to_srgb & OUTPUT2_SRGB)) {
|
||||
out_color2.rgb = linear_to_srgb(out_color2.rgb);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_OUTPUT3
|
||||
if (bool(data.convert_to_srgb & OUTPUT3_SRGB)) {
|
||||
out_color3.rgb = linear_to_srgb(out_color3.rgb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1243,6 +1243,178 @@ void MaterialStorage::MaterialData::set_as_used() {
|
|||
}
|
||||
}
|
||||
|
||||
/* TextureBlit SHADER */
|
||||
|
||||
void MaterialStorage::TexBlitShaderData::set_code(const String &p_code) {
|
||||
TextureStorage *texture_storage = TextureStorage::get_singleton();
|
||||
// Initialize and compile the shader.
|
||||
|
||||
code = p_code;
|
||||
valid = false;
|
||||
ubo_size = 0;
|
||||
uniforms.clear();
|
||||
|
||||
if (code.is_empty()) {
|
||||
return; // Just invalid, but no error.
|
||||
}
|
||||
|
||||
ShaderCompiler::GeneratedCode gen_code;
|
||||
|
||||
// Actual enum set further down after compilation.
|
||||
int blend_modei = BLEND_MODE_DISABLED;
|
||||
|
||||
ShaderCompiler::IdentifierActions actions;
|
||||
actions.entry_point_stages["blit"] = ShaderCompiler::STAGE_FRAGMENT;
|
||||
|
||||
actions.render_mode_values["blend_add"] = Pair<int *, int>(&blend_modei, BLEND_MODE_ADD);
|
||||
actions.render_mode_values["blend_mix"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MIX);
|
||||
actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_modei, BLEND_MODE_SUB);
|
||||
actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_modei, BLEND_MODE_MUL);
|
||||
actions.render_mode_values["blend_disabled"] = Pair<int *, int>(&blend_modei, BLEND_MODE_DISABLED);
|
||||
|
||||
actions.uniforms = &uniforms;
|
||||
Error err = texture_storage->tex_blit_shader.compiler.compile(RS::SHADER_TEXTURE_BLIT, code, &actions, path, gen_code);
|
||||
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
|
||||
|
||||
if (version.is_null()) {
|
||||
version = texture_storage->tex_blit_shader.shader.version_create();
|
||||
}
|
||||
|
||||
blend_mode = BlendMode(blend_modei);
|
||||
|
||||
#if 0
|
||||
print_line("**compiling shader:");
|
||||
print_line("**defines:\n");
|
||||
for (int i = 0; i < gen_code.defines.size(); i++) {
|
||||
print_line(gen_code.defines[i]);
|
||||
}
|
||||
|
||||
HashMap<String, String>::Iterator el = gen_code.code.begin();
|
||||
while (el) {
|
||||
print_line("\n**code " + el->key + ":\n" + el->value);
|
||||
++el;
|
||||
}
|
||||
|
||||
print_line("\n**uniforms:\n" + gen_code.uniforms);
|
||||
print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
|
||||
print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
|
||||
#endif
|
||||
|
||||
texture_storage->tex_blit_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
|
||||
ERR_FAIL_COND(!texture_storage->tex_blit_shader.shader.version_is_valid(version));
|
||||
|
||||
ubo_size = gen_code.uniform_total_size;
|
||||
ubo_offsets = gen_code.uniform_offsets;
|
||||
texture_uniforms = gen_code.texture_uniforms;
|
||||
|
||||
RD::PipelineColorBlendState blend_state_color_blend;
|
||||
RD::PipelineColorBlendState::Attachment attachment;
|
||||
|
||||
// blend_mode_to_blend_attachment(blend_mode) does not work
|
||||
// Because we want BlendAdd and BlendSub to behave differently for Texture_Blit
|
||||
switch (blend_mode) {
|
||||
case BLEND_MODE_MIX: {
|
||||
attachment.enable_blend = true;
|
||||
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA;
|
||||
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
} break;
|
||||
case BLEND_MODE_ADD: {
|
||||
attachment.enable_blend = true;
|
||||
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
} break;
|
||||
case BLEND_MODE_SUB: {
|
||||
attachment.enable_blend = true;
|
||||
attachment.alpha_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
attachment.color_blend_op = RD::BLEND_OP_REVERSE_SUBTRACT;
|
||||
attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
|
||||
} break;
|
||||
case BLEND_MODE_MUL: {
|
||||
attachment.enable_blend = true;
|
||||
attachment.alpha_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.color_blend_op = RD::BLEND_OP_ADD;
|
||||
attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR;
|
||||
attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA;
|
||||
attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;
|
||||
} break;
|
||||
case BLEND_MODE_DISABLED:
|
||||
default: {
|
||||
// Use default attachment values.
|
||||
} break;
|
||||
}
|
||||
|
||||
blend_state_color_blend.attachments = { attachment, attachment, attachment, attachment };
|
||||
|
||||
// Update Pipelines
|
||||
for (int i = 0; i < 4; i++) {
|
||||
RID shader_variant = texture_storage->tex_blit_shader.shader.version_get_shader(version, i);
|
||||
|
||||
pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_color_blend, 0);
|
||||
}
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
bool MaterialStorage::TexBlitShaderData::is_animated() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialStorage::TexBlitShaderData::casts_shadows() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
RS::ShaderNativeSourceCode MaterialStorage::TexBlitShaderData::get_native_source_code() const {
|
||||
return TextureStorage::get_singleton()->tex_blit_shader.shader.version_get_native_source_code(version);
|
||||
}
|
||||
|
||||
Pair<ShaderRD *, RID> MaterialStorage::TexBlitShaderData::get_native_shader_and_version() const {
|
||||
return { &TextureStorage::get_singleton()->tex_blit_shader.shader, version };
|
||||
}
|
||||
|
||||
MaterialStorage::TexBlitShaderData::TexBlitShaderData() {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
MaterialStorage::TexBlitShaderData::~TexBlitShaderData() {
|
||||
if (version.is_valid()) {
|
||||
TextureStorage::get_singleton()->tex_blit_shader.shader.version_free(version);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialStorage::ShaderData *MaterialStorage::_create_tex_blit_shader_func() {
|
||||
MaterialStorage::TexBlitShaderData *shader_data = memnew(MaterialStorage::TexBlitShaderData);
|
||||
return shader_data;
|
||||
}
|
||||
|
||||
bool MaterialStorage::TexBlitMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
|
||||
uniform_set_updated = true;
|
||||
|
||||
return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, TextureStorage::get_singleton()->tex_blit_shader.shader.version_get_shader(shader_data->version, 0), 1, true, false);
|
||||
}
|
||||
|
||||
MaterialStorage::TexBlitMaterialData::~TexBlitMaterialData() {
|
||||
free_parameters_uniform_set(uniform_set);
|
||||
}
|
||||
|
||||
MaterialStorage::MaterialData *MaterialStorage::_create_tex_blit_material_func(MaterialStorage::ShaderData *p_shader) {
|
||||
MaterialStorage::TexBlitMaterialData *material_data = memnew(TexBlitMaterialData);
|
||||
material_data->shader_data = static_cast<TexBlitShaderData *>(p_shader);
|
||||
//update will happen later anyway so do nothing.
|
||||
return material_data;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MaterialStorage::Samplers
|
||||
|
||||
|
|
@ -2033,6 +2205,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
|
|||
new_type = SHADER_TYPE_SKY;
|
||||
} else if (mode_string == "fog") {
|
||||
new_type = SHADER_TYPE_FOG;
|
||||
} else if (mode_string == "texture_blit") {
|
||||
new_type = SHADER_TYPE_TEXTURE_BLIT;
|
||||
} else {
|
||||
new_type = SHADER_TYPE_MAX;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "core/templates/local_vector.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "core/templates/self_list.h"
|
||||
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
|
||||
#include "servers/rendering/shader_compiler.h"
|
||||
#include "servers/rendering/shader_language.h"
|
||||
#include "servers/rendering/storage/material_storage.h"
|
||||
|
|
@ -51,6 +52,7 @@ public:
|
|||
SHADER_TYPE_PARTICLES,
|
||||
SHADER_TYPE_SKY,
|
||||
SHADER_TYPE_FOG,
|
||||
SHADER_TYPE_TEXTURE_BLIT,
|
||||
SHADER_TYPE_MAX
|
||||
};
|
||||
|
||||
|
|
@ -134,6 +136,53 @@ public:
|
|||
bool is_null() const;
|
||||
};
|
||||
|
||||
/* Texture Blit Shader */
|
||||
|
||||
struct TexBlitShaderData : public ShaderData {
|
||||
bool valid;
|
||||
RID version;
|
||||
|
||||
PipelineCacheRD pipelines[4];
|
||||
Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
|
||||
|
||||
Vector<uint32_t> ubo_offsets;
|
||||
uint32_t ubo_size;
|
||||
|
||||
String code;
|
||||
|
||||
BlendMode blend_mode;
|
||||
|
||||
virtual void set_code(const String &p_Code);
|
||||
virtual bool is_animated() const;
|
||||
virtual bool casts_shadows() const;
|
||||
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
|
||||
virtual Pair<ShaderRD *, RID> get_native_shader_and_version() const;
|
||||
|
||||
TexBlitShaderData();
|
||||
virtual ~TexBlitShaderData();
|
||||
};
|
||||
|
||||
ShaderData *_create_tex_blit_shader_func();
|
||||
static MaterialStorage::ShaderData *_create_tex_blit_shader_funcs() {
|
||||
return get_singleton()->_create_tex_blit_shader_func();
|
||||
}
|
||||
|
||||
struct TexBlitMaterialData : public MaterialData {
|
||||
TexBlitShaderData *shader_data = nullptr;
|
||||
RID uniform_set;
|
||||
bool uniform_set_updated;
|
||||
|
||||
virtual void set_render_priority(int p_priority) {}
|
||||
virtual void set_next_pass(RID p_pass) {}
|
||||
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
|
||||
virtual ~TexBlitMaterialData();
|
||||
};
|
||||
|
||||
MaterialData *_create_tex_blit_material_func(ShaderData *p_shader);
|
||||
static MaterialStorage::MaterialData *_create_tex_blit_material_funcs(MaterialStorage::ShaderData *p_shader) {
|
||||
return get_singleton()->_create_tex_blit_material_func(static_cast<TexBlitShaderData *>(p_shader));
|
||||
}
|
||||
|
||||
private:
|
||||
static MaterialStorage *singleton;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@
|
|||
|
||||
#include "../effects/copy_effects.h"
|
||||
#include "../framebuffer_cache_rd.h"
|
||||
#include "../uniform_set_cache_rd.h"
|
||||
#include "material_storage.h"
|
||||
#include "render_scene_buffers_rd.h"
|
||||
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
|
||||
|
||||
using namespace RendererRD;
|
||||
|
|
@ -633,6 +635,92 @@ TextureStorage::~TextureStorage() {
|
|||
singleton = nullptr;
|
||||
}
|
||||
|
||||
// Has to be a separate call from TextureStorage initialization due to interacting with Material Storage
|
||||
void TextureStorage::_tex_blit_shader_initialize() {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
{
|
||||
Vector<String> tex_blit_modes;
|
||||
tex_blit_modes.push_back(""); // Only 1 Output
|
||||
tex_blit_modes.push_back("\n#define USE_OUTPUT1\n"); // 2 Outputs
|
||||
tex_blit_modes.push_back("\n#define USE_OUTPUT1\n#define USE_OUTPUT2\n"); // 3 Outputs
|
||||
tex_blit_modes.push_back("\n#define USE_OUTPUT1\n#define USE_OUTPUT2\n#define USE_OUTPUT3\n"); // 4 Outputs
|
||||
String global_defines;
|
||||
global_defines += "\n#define SAMPLERS_BINDING_FIRST_INDEX " + itos(SAMPLERS_BINDING_FIRST_INDEX) + "\n";
|
||||
global_defines += "#define MAX_GLOBAL_SHADER_UNIFORMS 256\n"; // TODO: this is arbitrary for now
|
||||
tex_blit_shader.shader.initialize(tex_blit_modes, global_defines);
|
||||
}
|
||||
material_storage->shader_set_data_request_function(MaterialStorage::SHADER_TYPE_TEXTURE_BLIT, MaterialStorage::_create_tex_blit_shader_funcs);
|
||||
material_storage->material_set_data_request_function(MaterialStorage::SHADER_TYPE_TEXTURE_BLIT, MaterialStorage::_create_tex_blit_material_funcs);
|
||||
|
||||
{
|
||||
// Setup TextureBlit compiler
|
||||
ShaderCompiler::DefaultIdentifierActions actions;
|
||||
|
||||
actions.renames["TIME"] = "data.time";
|
||||
actions.renames["PI"] = _MKSTR(Math_PI);
|
||||
actions.renames["TAU"] = _MKSTR(Math_TAU);
|
||||
actions.renames["E"] = _MKSTR(Math_E);
|
||||
|
||||
actions.renames["FRAGCOORD"] = "gl_FragCoord";
|
||||
|
||||
actions.renames["UV"] = "uv";
|
||||
actions.renames["MODULATE"] = "data.modulate";
|
||||
|
||||
actions.renames["COLOR0"] = "color0";
|
||||
actions.renames["COLOR1"] = "color1";
|
||||
actions.renames["COLOR2"] = "color2";
|
||||
actions.renames["COLOR3"] = "color3";
|
||||
|
||||
actions.base_uniform_string = "material.";
|
||||
actions.base_texture_binding_index = 1;
|
||||
actions.texture_layout_set = 1;
|
||||
|
||||
tex_blit_shader.compiler.initialize(actions);
|
||||
}
|
||||
|
||||
{
|
||||
// default material and shader for Texture Blit shader
|
||||
tex_blit_shader.default_shader = material_storage->shader_allocate();
|
||||
material_storage->shader_initialize(tex_blit_shader.default_shader);
|
||||
material_storage->shader_set_code(tex_blit_shader.default_shader, R"(
|
||||
// Default Texture Blit shader.
|
||||
|
||||
shader_type texture_blit;
|
||||
render_mode blend_mix;
|
||||
|
||||
uniform sampler2D source_texture0 : hint_blit_source0;
|
||||
uniform sampler2D source_texture1 : hint_blit_source1;
|
||||
uniform sampler2D source_texture2 : hint_blit_source2;
|
||||
uniform sampler2D source_texture3 : hint_blit_source3;
|
||||
|
||||
void blit() {
|
||||
// Copies from each whole source texture to a rect on each output texture.
|
||||
COLOR0 = texture(source_texture0, UV) * MODULATE;
|
||||
COLOR1 = texture(source_texture1, UV) * MODULATE;
|
||||
COLOR2 = texture(source_texture2, UV) * MODULATE;
|
||||
COLOR3 = texture(source_texture3, UV) * MODULATE;
|
||||
}
|
||||
)");
|
||||
tex_blit_shader.default_material = material_storage->material_allocate();
|
||||
material_storage->material_initialize(tex_blit_shader.default_material);
|
||||
material_storage->material_set_shader(tex_blit_shader.default_material, tex_blit_shader.default_shader);
|
||||
}
|
||||
|
||||
tex_blit_shader.initialized = true;
|
||||
}
|
||||
|
||||
// Has to be a separate call from TextureStorage destruction due to interacting with Material Storage
|
||||
void TextureStorage::_tex_blit_shader_free() {
|
||||
if (tex_blit_shader.initialized) {
|
||||
MaterialStorage *material_storage = MaterialStorage::get_singleton();
|
||||
|
||||
print_verbose("Freeing Default Tex_Blit Shader");
|
||||
material_storage->material_free(tex_blit_shader.default_material);
|
||||
material_storage->shader_free(tex_blit_shader.default_shader);
|
||||
}
|
||||
}
|
||||
|
||||
bool TextureStorage::free(RID p_rid) {
|
||||
if (owns_texture(p_rid)) {
|
||||
texture_free(p_rid);
|
||||
|
|
@ -1164,6 +1252,106 @@ void TextureStorage::texture_proxy_initialize(RID p_texture, RID p_base) {
|
|||
tex->proxies.push_back(p_texture);
|
||||
}
|
||||
|
||||
void TextureStorage::texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) {
|
||||
// Near identical to Texture_2D_initialize, Generates an empty white image based on parameters
|
||||
|
||||
// GUARDRAIL: Bad Widths/Heights
|
||||
ERR_FAIL_COND_MSG(p_width <= 0 || p_height <= 0, "Drawable Texture Width or Height cannot be less than 1.");
|
||||
ERR_FAIL_COND_MSG(p_width >= 16384 || p_height >= 16384, "Drawable Texture Width or Height cannot be greater than 16383.");
|
||||
|
||||
Image::Format format;
|
||||
switch (p_format) {
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBA8:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBAH:
|
||||
format = Image::FORMAT_RGBAH;
|
||||
break;
|
||||
case RS::TEXTURE_DRAWABLE_FORMAT_RGBAF:
|
||||
format = Image::FORMAT_RGBAF;
|
||||
break;
|
||||
default:
|
||||
format = Image::FORMAT_RGBA8;
|
||||
}
|
||||
|
||||
Ref<Image> image = Image::create_empty(p_width, p_height, p_with_mipmaps, format);
|
||||
image->fill(p_color);
|
||||
TextureToRDFormat ret_format;
|
||||
|
||||
Ref<Image> valid_image = _validate_texture_format(image, ret_format);
|
||||
Texture texture;
|
||||
|
||||
texture.type = TextureStorage::TYPE_2D;
|
||||
|
||||
texture.width = p_width;
|
||||
texture.height = p_height;
|
||||
texture.layers = 1;
|
||||
texture.mipmaps = image->get_mipmap_count() + 1;
|
||||
texture.depth = 1;
|
||||
texture.format = image->get_format();
|
||||
texture.validated_format = image->get_format();
|
||||
|
||||
texture.rd_type = RD::TEXTURE_TYPE_2D;
|
||||
texture.rd_format = ret_format.format;
|
||||
texture.rd_format_srgb = ret_format.format_srgb;
|
||||
|
||||
RD::TextureFormat rd_format;
|
||||
RD::TextureView rd_view;
|
||||
{ //attempt register
|
||||
rd_format.format = texture.rd_format;
|
||||
rd_format.width = texture.width;
|
||||
rd_format.height = texture.height;
|
||||
rd_format.depth = 1;
|
||||
rd_format.array_layers = 1;
|
||||
rd_format.mipmaps = texture.mipmaps;
|
||||
rd_format.texture_type = texture.rd_type;
|
||||
rd_format.samples = RD::TEXTURE_SAMPLES_1;
|
||||
// The Color Attachment Usage bit here is what differentiates a DrawableTexture from a regular Texture2D
|
||||
rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
|
||||
rd_format.shareable_formats.push_back(texture.rd_format);
|
||||
rd_format.shareable_formats.push_back(texture.rd_format_srgb);
|
||||
}
|
||||
}
|
||||
{
|
||||
rd_view.swizzle_r = ret_format.swizzle_r;
|
||||
rd_view.swizzle_g = ret_format.swizzle_g;
|
||||
rd_view.swizzle_b = ret_format.swizzle_b;
|
||||
rd_view.swizzle_a = ret_format.swizzle_a;
|
||||
}
|
||||
|
||||
Vector<uint8_t> data = image->get_data(); //use image data
|
||||
Vector<Vector<uint8_t>> data_slices;
|
||||
data_slices.push_back(data);
|
||||
texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices);
|
||||
ERR_FAIL_COND(texture.rd_texture.is_null());
|
||||
if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) {
|
||||
rd_view.format_override = texture.rd_format_srgb;
|
||||
texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture);
|
||||
if (texture.rd_texture_srgb.is_null()) {
|
||||
RD::get_singleton()->free_rid(texture.rd_texture);
|
||||
ERR_FAIL_COND(texture.rd_texture_srgb.is_null());
|
||||
}
|
||||
}
|
||||
|
||||
// Used for Drawable Textures.
|
||||
for (int i = 0; i < texture.mipmaps; i++) {
|
||||
texture.cached_rd_slices.append(RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), texture.rd_texture, 0, i));
|
||||
}
|
||||
|
||||
//used for 2D, overridable
|
||||
texture.width_2d = texture.width;
|
||||
texture.height_2d = texture.height;
|
||||
texture.is_render_target = false;
|
||||
texture.rd_view = rd_view;
|
||||
texture.is_proxy = false;
|
||||
|
||||
texture_owner.initialize_rid(p_texture, texture);
|
||||
}
|
||||
|
||||
// Note: We make some big assumptions about format and usage. If developers need more control,
|
||||
// they should use RD::texture_create_from_extension() instead.
|
||||
RID TextureStorage::texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers, RS::TextureLayeredType p_layered_type) {
|
||||
|
|
@ -1474,6 +1662,145 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
|||
}
|
||||
}
|
||||
|
||||
// Output textures in p_textures must ALL BE THE SAME SIZE
|
||||
void TextureStorage::texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) {
|
||||
ERR_FAIL_COND_MSG(!tex_blit_shader.initialized, "Texture Blit shader & materials not yet initialized.");
|
||||
ERR_FAIL_COND_MSG(p_textures.is_empty() || p_source_textures.is_empty(), "Blit Rect texture output and source arrays must contain at least 1 texture.");
|
||||
const RID default_tex_rid = texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
|
||||
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
|
||||
|
||||
RendererRD::MaterialStorage::TexBlitMaterialData *m = static_cast<RendererRD::MaterialStorage::TexBlitMaterialData *>(material_storage->material_get_data(p_material, RendererRD::MaterialStorage::SHADER_TYPE_TEXTURE_BLIT));
|
||||
if (!m) {
|
||||
m = static_cast<RendererRD::MaterialStorage::TexBlitMaterialData *>(material_storage->material_get_data(tex_blit_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_TEXTURE_BLIT));
|
||||
}
|
||||
// GUARDRAIL:: p_material MUST BE ShaderType TextureBlit
|
||||
ERR_FAIL_NULL(m);
|
||||
|
||||
RendererRD::MaterialStorage::TexBlitShaderData *shader_data = m->shader_data;
|
||||
ERR_FAIL_NULL(shader_data);
|
||||
material_storage->_update_queued_materials();
|
||||
RID shaderRD = tex_blit_shader.shader.version_get_shader(shader_data->version, p_source_textures.size() - 1);
|
||||
|
||||
RID tar_textures[4];
|
||||
Texture *src_textures[4];
|
||||
|
||||
RID uniform_texture_set;
|
||||
int TEX_BLIT_MATERIAL_SET = 1;
|
||||
int TEX_BLIT_TEXTURE_SET = 0;
|
||||
int srgb_mask = 0;
|
||||
const int srgbMaskArray[4] = { 1, 2, 4, 8 };
|
||||
LocalVector<RD::Uniform> texture_uniforms;
|
||||
|
||||
int i = 0;
|
||||
while (i < 4) {
|
||||
// Load Target Textures
|
||||
if (i < p_textures.size()) {
|
||||
Texture *tex = get_texture(p_textures[i]);
|
||||
srgb_mask += get_texture(p_textures[i])->drawable_type == RS::TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB ? srgbMaskArray[i] : 0;
|
||||
ERR_FAIL_NULL_MSG(tex, "Drawable Texture target cannot be null.");
|
||||
ERR_FAIL_COND_MSG(p_to_mipmap >= tex->mipmaps || p_to_mipmap >= tex->cached_rd_slices.size(), vformat("Drawable Texture Target does not have mipmap level %d.", p_to_mipmap));
|
||||
if (i > 0) {
|
||||
ERR_FAIL_COND_MSG(texture_2d_get_size(p_textures[i - 1]) != texture_2d_get_size(p_textures[i]), "All Blit_Rect output textures must be same size.");
|
||||
}
|
||||
tar_textures[i] = tex->cached_rd_slices[p_to_mipmap];
|
||||
}
|
||||
|
||||
// Load and bind source textures, load default Black if source is bad.
|
||||
RD::Uniform u;
|
||||
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
|
||||
u.binding = i;
|
||||
if (i < p_source_textures.size()) {
|
||||
src_textures[i] = get_texture(p_source_textures[i]);
|
||||
if (!src_textures[i]) {
|
||||
u.append_id(default_tex_rid);
|
||||
} else {
|
||||
u.append_id(src_textures[i]->rd_texture);
|
||||
}
|
||||
} else {
|
||||
u.append_id(default_tex_rid);
|
||||
}
|
||||
texture_uniforms.push_back(u);
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Calculates the Rects Offset & Size in UV space for Shader to scale Vertex Quad correctly
|
||||
Vector2i size = texture_2d_get_size(p_textures[0]);
|
||||
Vector2 offset = Vector2(float(p_rect.position.x) / size.x, float(p_rect.position.y) / size.y);
|
||||
Vector2 rect_size = Vector2(float(p_rect.size.x) / size.x, float(p_rect.size.y) / size.y);
|
||||
|
||||
// Select Pipeline based on # of targets.
|
||||
RID tex_blit_fb;
|
||||
PipelineCacheRD *pipeline;
|
||||
switch (p_textures.size()) {
|
||||
case 1:
|
||||
tex_blit_fb = FramebufferCacheRD::get_singleton()->get_cache(tar_textures[0]);
|
||||
pipeline = &shader_data->pipelines[0];
|
||||
break;
|
||||
case 2:
|
||||
tex_blit_fb = FramebufferCacheRD::get_singleton()->get_cache(tar_textures[0], tar_textures[1]);
|
||||
pipeline = &shader_data->pipelines[1];
|
||||
break;
|
||||
case 3:
|
||||
tex_blit_fb = FramebufferCacheRD::get_singleton()->get_cache(tar_textures[0], tar_textures[1], tar_textures[2]);
|
||||
pipeline = &shader_data->pipelines[2];
|
||||
break;
|
||||
case 4:
|
||||
tex_blit_fb = FramebufferCacheRD::get_singleton()->get_cache(tar_textures[0], tar_textures[1], tar_textures[2], tar_textures[3]);
|
||||
pipeline = &shader_data->pipelines[3];
|
||||
break;
|
||||
default:
|
||||
tex_blit_fb = FramebufferCacheRD::get_singleton()->get_cache(tar_textures[0], tar_textures[1], tar_textures[2], tar_textures[3]);
|
||||
pipeline = &shader_data->pipelines[3];
|
||||
}
|
||||
|
||||
// Bind uniforms via push_constant
|
||||
TexBlitPushConstant push_constant;
|
||||
memset(&push_constant, 0, sizeof(TexBlitPushConstant));
|
||||
|
||||
push_constant.offset[0] = offset.x;
|
||||
push_constant.offset[1] = offset.y;
|
||||
push_constant.size[0] = rect_size.x;
|
||||
push_constant.size[1] = rect_size.y;
|
||||
push_constant.modulate[0] = p_modulate.r;
|
||||
push_constant.modulate[1] = p_modulate.g;
|
||||
push_constant.modulate[2] = p_modulate.b;
|
||||
push_constant.modulate[3] = p_modulate.a;
|
||||
push_constant.convert_to_srgb = srgb_mask;
|
||||
push_constant.time = RSG::rasterizer->get_total_time();
|
||||
|
||||
Rect2i tex_blit_rr;
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Blit Rect");
|
||||
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(tex_blit_fb, RD::DRAW_DEFAULT_ALL, Vector<Color>(), 1.0f, 0u, tex_blit_rr);
|
||||
|
||||
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(tex_blit_fb);
|
||||
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline->get_render_pipeline(RD::INVALID_ID, fb_format, false, 0));
|
||||
|
||||
material_storage->samplers_rd_get_default().append_uniforms(texture_uniforms, 4);
|
||||
|
||||
uniform_texture_set = UniformSetCacheRD::get_singleton()->get_cache_vec(shaderRD, TEX_BLIT_TEXTURE_SET, texture_uniforms);
|
||||
|
||||
{
|
||||
// Push Constants
|
||||
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(TexBlitPushConstant));
|
||||
|
||||
// Material Uniforms
|
||||
if (m->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(m->uniform_set)) { // Material may not have a uniform set.
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, m->uniform_set, TEX_BLIT_MATERIAL_SET);
|
||||
}
|
||||
|
||||
// Texture Uniforms
|
||||
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_texture_set, TEX_BLIT_TEXTURE_SET);
|
||||
}
|
||||
|
||||
// DRAW!!
|
||||
RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 6u);
|
||||
|
||||
RD::get_singleton()->draw_list_end();
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
//these two APIs can be used together or in combination with the others.
|
||||
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
|
||||
texture_2d_initialize(p_texture, texture_2d_placeholder);
|
||||
|
|
@ -1599,6 +1926,38 @@ Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void TextureStorage::texture_drawable_generate_mipmaps(RID p_texture) {
|
||||
Texture *tex = get_texture(p_texture);
|
||||
CopyEffects *copy_effects = CopyEffects::get_singleton();
|
||||
ERR_FAIL_NULL(copy_effects);
|
||||
|
||||
uint32_t mipmaps = tex->mipmaps;
|
||||
int width = tex->width;
|
||||
int height = tex->height;
|
||||
|
||||
RID source = tex->rd_texture;
|
||||
RID dest = tex->cached_rd_slices[0];
|
||||
|
||||
for (uint32_t m = 1; m < mipmaps; m++) {
|
||||
width = MAX(1, width >> 1);
|
||||
height = MAX(1, height >> 1);
|
||||
|
||||
source = dest;
|
||||
dest = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), source, 0, m, 1, RD::TEXTURE_SLICE_2D);
|
||||
|
||||
if (copy_effects->get_raster_effects().has_flag(CopyEffects::RASTER_EFFECT_COPY)) {
|
||||
copy_effects->make_mipmap_raster(source, dest, Size2i(width, height));
|
||||
} else {
|
||||
copy_effects->make_mipmap(source, dest, Size2i(width, height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RID TextureStorage::texture_drawable_get_default_material() const {
|
||||
// Return a material with a default Texture_Blit shader for DrawableTexture2D to use
|
||||
return tex_blit_shader.default_material;
|
||||
}
|
||||
|
||||
void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
|
||||
Texture *tex = texture_owner.get_or_null(p_texture);
|
||||
ERR_FAIL_NULL(tex);
|
||||
|
|
|
|||
|
|
@ -33,8 +33,10 @@
|
|||
#include "core/templates/paged_array.h"
|
||||
#include "core/templates/rid_owner.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/shaders/tex_blit.glsl.gen.h"
|
||||
#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
|
||||
#include "servers/rendering/rendering_server_default.h"
|
||||
#include "servers/rendering/shader_compiler.h"
|
||||
#include "servers/rendering/storage/texture_storage.h"
|
||||
#include "servers/rendering/storage/utilities.h"
|
||||
|
||||
|
|
@ -45,6 +47,8 @@ class MaterialStorage;
|
|||
|
||||
class TextureStorage : public RendererTextureStorage {
|
||||
public:
|
||||
const int SAMPLERS_BINDING_FIRST_INDEX = 4;
|
||||
|
||||
enum DefaultRDTexture {
|
||||
DEFAULT_RD_TEXTURE_WHITE,
|
||||
DEFAULT_RD_TEXTURE_BLACK,
|
||||
|
|
@ -144,12 +148,14 @@ private:
|
|||
public:
|
||||
TextureType type;
|
||||
RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
|
||||
RS::TextureDrawableFormat drawable_type = RS::TEXTURE_DRAWABLE_FORMAT_RGBA8;
|
||||
|
||||
RenderingDevice::TextureType rd_type;
|
||||
RID rd_texture;
|
||||
RID rd_texture_srgb;
|
||||
RenderingDevice::DataFormat rd_format;
|
||||
RenderingDevice::DataFormat rd_format_srgb;
|
||||
Vector<RID> cached_rd_slices;
|
||||
|
||||
RD::TextureView rd_view;
|
||||
|
||||
|
|
@ -482,9 +488,32 @@ private:
|
|||
RID pipelines[SHADER_MAX];
|
||||
} rt_sdf;
|
||||
|
||||
struct TextureBlitShader {
|
||||
TexBlitShaderRD shader;
|
||||
ShaderCompiler compiler;
|
||||
|
||||
bool initialized = false;
|
||||
RID default_shader;
|
||||
RID default_material;
|
||||
RID default_shader_version;
|
||||
} tex_blit_shader;
|
||||
|
||||
struct TexBlitPushConstant {
|
||||
float offset[2]; // 8 - 8
|
||||
float size[2]; // 8 - 16
|
||||
float modulate[4]; // 16 - 32
|
||||
float pad[2]; // 8 - 40
|
||||
uint32_t convert_to_srgb; // 4 - 44
|
||||
float time; // 4 - 48
|
||||
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
|
||||
};
|
||||
|
||||
public:
|
||||
static TextureStorage *get_singleton();
|
||||
|
||||
void _tex_blit_shader_initialize();
|
||||
void _tex_blit_shader_free();
|
||||
|
||||
_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
|
||||
return default_rd_textures[p_texture];
|
||||
}
|
||||
|
|
@ -523,6 +552,7 @@ public:
|
|||
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) override;
|
||||
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_initialize(RID p_texture, RID p_base) override; //all slices, then all the mipmaps, must be coherent
|
||||
virtual void texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) override;
|
||||
|
||||
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) override;
|
||||
|
||||
|
|
@ -531,6 +561,8 @@ public:
|
|||
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) override;
|
||||
virtual void texture_proxy_update(RID p_proxy, RID p_base) override;
|
||||
|
||||
virtual void texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) override;
|
||||
|
||||
Ref<Image> texture_2d_placeholder;
|
||||
Vector<Ref<Image>> texture_2d_array_placeholder;
|
||||
Vector<Ref<Image>> cubemap_placeholder;
|
||||
|
|
@ -545,6 +577,9 @@ public:
|
|||
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const override;
|
||||
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const override;
|
||||
|
||||
virtual void texture_drawable_generate_mipmaps(RID p_texture) override;
|
||||
virtual RID texture_drawable_get_default_material() const override;
|
||||
|
||||
virtual void texture_replace(RID p_texture, RID p_by_texture) override;
|
||||
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -2329,11 +2329,14 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("texture_3d_create", "format", "width", "height", "depth", "mipmaps", "data"), &RenderingServer::_texture_3d_create);
|
||||
ClassDB::bind_method(D_METHOD("texture_proxy_create", "base"), &RenderingServer::texture_proxy_create);
|
||||
ClassDB::bind_method(D_METHOD("texture_create_from_native_handle", "type", "format", "native_handle", "width", "height", "depth", "layers", "layered_type"), &RenderingServer::texture_create_from_native_handle, DEFVAL(1), DEFVAL(TEXTURE_LAYERED_2D_ARRAY));
|
||||
ClassDB::bind_method(D_METHOD("texture_drawable_create", "width", "height", "format", "color", "with_mipmaps"), &RenderingServer::texture_drawable_create, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("texture_2d_update", "texture", "image", "layer"), &RenderingServer::texture_2d_update);
|
||||
ClassDB::bind_method(D_METHOD("texture_3d_update", "texture", "data"), &RenderingServer::_texture_3d_update);
|
||||
ClassDB::bind_method(D_METHOD("texture_proxy_update", "texture", "proxy_to"), &RenderingServer::texture_proxy_update);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("texture_drawable_blit_rect", "textures", "rect", "material", "modulate", "source_textures", "to_mipmap"), &RenderingServer::texture_drawable_blit_rect, DEFVAL(0));
|
||||
|
||||
ClassDB::bind_method(D_METHOD("texture_2d_placeholder_create"), &RenderingServer::texture_2d_placeholder_create);
|
||||
ClassDB::bind_method(D_METHOD("texture_2d_layered_placeholder_create", "layered_type"), &RenderingServer::texture_2d_layered_placeholder_create);
|
||||
ClassDB::bind_method(D_METHOD("texture_3d_placeholder_create"), &RenderingServer::texture_3d_placeholder_create);
|
||||
|
|
@ -2342,6 +2345,9 @@ void RenderingServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("texture_2d_layer_get", "texture", "layer"), &RenderingServer::texture_2d_layer_get);
|
||||
ClassDB::bind_method(D_METHOD("texture_3d_get", "texture"), &RenderingServer::_texture_3d_get);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("texture_drawable_generate_mipmaps", "texture"), &RenderingServer::texture_drawable_generate_mipmaps);
|
||||
ClassDB::bind_method(D_METHOD("texture_drawable_get_default_material"), &RenderingServer::texture_drawable_get_default_material);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("texture_replace", "texture", "by_texture"), &RenderingServer::texture_replace);
|
||||
ClassDB::bind_method(D_METHOD("texture_set_size_override", "texture", "width", "height"), &RenderingServer::texture_set_size_override);
|
||||
|
||||
|
|
@ -2370,6 +2376,11 @@ void RenderingServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(CUBEMAP_LAYER_FRONT);
|
||||
BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BACK);
|
||||
|
||||
BIND_ENUM_CONSTANT(TEXTURE_DRAWABLE_FORMAT_RGBA8);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_DRAWABLE_FORMAT_RGBAH);
|
||||
BIND_ENUM_CONSTANT(TEXTURE_DRAWABLE_FORMAT_RGBAF);
|
||||
|
||||
/* SHADER */
|
||||
|
||||
ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create);
|
||||
|
|
@ -2387,6 +2398,7 @@ void RenderingServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(SHADER_PARTICLES);
|
||||
BIND_ENUM_CONSTANT(SHADER_SKY);
|
||||
BIND_ENUM_CONSTANT(SHADER_FOG);
|
||||
BIND_ENUM_CONSTANT(SHADER_TEXTURE_BLIT);
|
||||
BIND_ENUM_CONSTANT(SHADER_MAX);
|
||||
|
||||
/* MATERIAL */
|
||||
|
|
|
|||
|
|
@ -136,11 +136,19 @@ public:
|
|||
CUBEMAP_LAYER_BACK
|
||||
};
|
||||
|
||||
enum TextureDrawableFormat {
|
||||
TEXTURE_DRAWABLE_FORMAT_RGBA8,
|
||||
TEXTURE_DRAWABLE_FORMAT_RGBA8_SRGB, // Use this if you want to read the result from both 2D (non-hdr) and 3D.
|
||||
TEXTURE_DRAWABLE_FORMAT_RGBAH,
|
||||
TEXTURE_DRAWABLE_FORMAT_RGBAF,
|
||||
};
|
||||
|
||||
virtual RID texture_2d_create(const Ref<Image> &p_image) = 0;
|
||||
virtual RID texture_2d_layered_create(const Vector<Ref<Image>> &p_layers, TextureLayeredType p_layered_type) = 0;
|
||||
virtual RID texture_3d_create(Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0; //all slices, then all the mipmaps, must be coherent
|
||||
virtual RID texture_external_create(int p_width, int p_height, uint64_t p_external_buffer = 0) = 0;
|
||||
virtual RID texture_proxy_create(RID p_base) = 0;
|
||||
virtual RID texture_drawable_create(int p_width, int p_height, TextureDrawableFormat p_format, const Color &p_color = Color(1, 1, 1, 1), bool p_with_mipmaps = false) = 0;
|
||||
|
||||
virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) = 0;
|
||||
|
||||
|
|
@ -149,6 +157,8 @@ public:
|
|||
virtual void texture_external_update(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer = 0) = 0;
|
||||
virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0;
|
||||
|
||||
virtual void texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap = 0) = 0;
|
||||
|
||||
// These two APIs can be used together or in combination with the others.
|
||||
virtual RID texture_2d_placeholder_create() = 0;
|
||||
virtual RID texture_2d_layered_placeholder_create(TextureLayeredType p_layered_type) = 0;
|
||||
|
|
@ -164,6 +174,9 @@ public:
|
|||
virtual void texture_set_path(RID p_texture, const String &p_path) = 0;
|
||||
virtual String texture_get_path(RID p_texture) const = 0;
|
||||
|
||||
virtual void texture_drawable_generate_mipmaps(RID p_texture) = 0; // Update mipmaps if modified
|
||||
virtual RID texture_drawable_get_default_material() const = 0; // To use with simplified functions in DrawableTexture2D
|
||||
|
||||
virtual Image::Format texture_get_format(RID p_texture) const = 0;
|
||||
|
||||
typedef void (*TextureDetectCallback)(void *);
|
||||
|
|
@ -221,6 +234,7 @@ public:
|
|||
SHADER_PARTICLES,
|
||||
SHADER_SKY,
|
||||
SHADER_FOG,
|
||||
SHADER_TEXTURE_BLIT,
|
||||
SHADER_MAX
|
||||
};
|
||||
|
||||
|
|
@ -1947,6 +1961,7 @@ private:
|
|||
VARIANT_ENUM_CAST(RenderingServer::TextureType);
|
||||
VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType);
|
||||
VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer);
|
||||
VARIANT_ENUM_CAST(RenderingServer::TextureDrawableFormat);
|
||||
VARIANT_ENUM_CAST(RenderingServer::PipelineSource);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ShaderMode);
|
||||
VARIANT_ENUM_CAST(RenderingServer::ArrayType);
|
||||
|
|
|
|||
|
|
@ -174,6 +174,28 @@ public:
|
|||
return ret; \
|
||||
}
|
||||
|
||||
#define FUNCRIDTEX4(m_type, m_type1, m_type2, m_type3, m_type4) \
|
||||
virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4) override { \
|
||||
RID ret = RSG::texture_storage->texture_allocate(); \
|
||||
if (Thread::get_caller_id() == server_thread || RSG::rasterizer->can_create_resources_async()) { \
|
||||
RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4); \
|
||||
} else { \
|
||||
command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define FUNCRIDTEX5(m_type, m_type1, m_type2, m_type3, m_type4, m_type5) \
|
||||
virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5) override { \
|
||||
RID ret = RSG::texture_storage->texture_allocate(); \
|
||||
if (Thread::get_caller_id() == server_thread || RSG::rasterizer->can_create_resources_async()) { \
|
||||
RSG::texture_storage->m_type##_initialize(ret, p1, p2, p3, p4, p5); \
|
||||
} else { \
|
||||
command_queue.push(RSG::texture_storage, &RendererTextureStorage::m_type##_initialize, ret, p1, p2, p3, p4, p5); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define FUNCRIDTEX6(m_type, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \
|
||||
virtual RID m_type##_create(m_type1 p1, m_type2 p2, m_type3 p3, m_type4 p4, m_type5 p5, m_type6 p6) override { \
|
||||
RID ret = RSG::texture_storage->texture_allocate(); \
|
||||
|
|
@ -191,6 +213,7 @@ public:
|
|||
FUNCRIDTEX6(texture_3d, Image::Format, int, int, int, bool, const Vector<Ref<Image>> &)
|
||||
FUNCRIDTEX3(texture_external, int, int, uint64_t)
|
||||
FUNCRIDTEX1(texture_proxy, RID)
|
||||
FUNCRIDTEX5(texture_drawable, int, int, TextureDrawableFormat, const Color &, bool)
|
||||
|
||||
// Called directly, not through the command queue.
|
||||
virtual RID texture_create_from_native_handle(TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, TextureLayeredType p_layered_type = TEXTURE_LAYERED_2D_ARRAY) override {
|
||||
|
|
@ -203,6 +226,8 @@ public:
|
|||
FUNC4(texture_external_update, RID, int, int, uint64_t)
|
||||
FUNC2(texture_proxy_update, RID, RID)
|
||||
|
||||
FUNC6(texture_drawable_blit_rect, const TypedArray<RID> &, const Rect2i &, RID, const Color &, const TypedArray<RID> &, int)
|
||||
|
||||
//these also go pass-through
|
||||
FUNCRIDTEX0(texture_2d_placeholder)
|
||||
FUNCRIDTEX1(texture_2d_layered_placeholder, TextureLayeredType)
|
||||
|
|
@ -212,6 +237,9 @@ public:
|
|||
FUNC2RC(Ref<Image>, texture_2d_layer_get, RID, int)
|
||||
FUNC1RC(Vector<Ref<Image>>, texture_3d_get, RID)
|
||||
|
||||
FUNC1(texture_drawable_generate_mipmaps, RID)
|
||||
FUNC0RC(RID, texture_drawable_get_default_material)
|
||||
|
||||
FUNC2(texture_replace, RID, RID)
|
||||
|
||||
FUNC3(texture_set_size_override, RID, int, int)
|
||||
|
|
|
|||
|
|
@ -527,7 +527,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
|||
if (SL::is_sampler_type(E.value.type)) {
|
||||
if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE0 ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE1 ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE2 ||
|
||||
E.value.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
|
||||
continue; // Don't create uniforms in the generated code for these.
|
||||
}
|
||||
max_texture_uniforms++;
|
||||
|
|
@ -572,7 +576,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
|||
|
||||
if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE0 ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE1 ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE2 ||
|
||||
uniform.hint == SL::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
|
||||
continue; // Don't create uniforms in the generated code for these.
|
||||
}
|
||||
|
||||
|
|
@ -937,6 +945,14 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
|
|||
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
|
||||
name = "depth_buffer";
|
||||
r_gen_code.uses_depth_texture = true;
|
||||
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE0) {
|
||||
name = "source0";
|
||||
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE1) {
|
||||
name = "source1";
|
||||
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE2) {
|
||||
name = "source2";
|
||||
} else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLIT_SOURCE3) {
|
||||
name = "source3";
|
||||
} else {
|
||||
name = _mkid(vnode->name); //texture, use as is
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,6 +220,10 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
|
|||
"HINT_SCREEN_TEXTURE",
|
||||
"HINT_NORMAL_ROUGHNESS_TEXTURE",
|
||||
"HINT_DEPTH_TEXTURE",
|
||||
"HINT_BLIT_SOURCE0",
|
||||
"HINT_BLIT_SOURCE1",
|
||||
"HINT_BLIT_SOURCE2",
|
||||
"HINT_BLIT_SOURCE3",
|
||||
"FILTER_NEAREST",
|
||||
"FILTER_LINEAR",
|
||||
"FILTER_NEAREST_MIPMAP",
|
||||
|
|
@ -392,6 +396,11 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
|
|||
{ TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} },
|
||||
|
||||
{ TK_HINT_BLIT_SOURCE0, "hint_blit_source0", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_HINT_BLIT_SOURCE1, "hint_blit_source1", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_HINT_BLIT_SOURCE2, "hint_blit_source2", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_HINT_BLIT_SOURCE3, "hint_blit_source3", CF_UNSPECIFIED, {}, {} },
|
||||
|
||||
{ TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
|
||||
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
|
||||
|
|
@ -1236,6 +1245,18 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
|
|||
case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: {
|
||||
result = "hint_depth_texture";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_BLIT_SOURCE0: {
|
||||
result = "hint_blit_source0";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_BLIT_SOURCE1: {
|
||||
result = "hint_blit_source1";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_BLIT_SOURCE2: {
|
||||
result = "hint_blit_source2";
|
||||
} break;
|
||||
case ShaderNode::Uniform::HINT_BLIT_SOURCE3: {
|
||||
result = "hint_blit_source3";
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -10029,6 +10050,42 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
|
|||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} break;
|
||||
case TK_HINT_BLIT_SOURCE0: {
|
||||
new_hint = ShaderNode::Uniform::HINT_BLIT_SOURCE0;
|
||||
--texture_uniforms;
|
||||
--texture_binding;
|
||||
if (shader_type_identifier != StringName() && String(shader_type_identifier) != "texture_blit") {
|
||||
_set_error(vformat(RTR("'hint_blit_source' is not supported in '%s' shaders."), shader_type_identifier));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} break;
|
||||
case TK_HINT_BLIT_SOURCE1: {
|
||||
new_hint = ShaderNode::Uniform::HINT_BLIT_SOURCE1;
|
||||
--texture_uniforms;
|
||||
--texture_binding;
|
||||
if (shader_type_identifier != StringName() && String(shader_type_identifier) != "texture_blit") {
|
||||
_set_error(vformat(RTR("'hint_blit_source' is not supported in '%s' shaders."), shader_type_identifier));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} break;
|
||||
case TK_HINT_BLIT_SOURCE2: {
|
||||
new_hint = ShaderNode::Uniform::HINT_BLIT_SOURCE2;
|
||||
--texture_uniforms;
|
||||
--texture_binding;
|
||||
if (shader_type_identifier != StringName() && String(shader_type_identifier) != "texture_blit") {
|
||||
_set_error(vformat(RTR("'hint_blit_source' is not supported in '%s' shaders."), shader_type_identifier));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} break;
|
||||
case TK_HINT_BLIT_SOURCE3: {
|
||||
new_hint = ShaderNode::Uniform::HINT_BLIT_SOURCE3;
|
||||
--texture_uniforms;
|
||||
--texture_binding;
|
||||
if (shader_type_identifier != StringName() && String(shader_type_identifier) != "texture_blit") {
|
||||
_set_error(vformat(RTR("'hint_blit_source' is not supported in '%s' shaders."), shader_type_identifier));
|
||||
return ERR_PARSE_ERROR;
|
||||
}
|
||||
} break;
|
||||
case TK_FILTER_NEAREST: {
|
||||
new_filter = FILTER_NEAREST;
|
||||
} break;
|
||||
|
|
@ -12072,6 +12129,10 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
|
|||
options.push_back("hint_screen_texture");
|
||||
options.push_back("hint_normal_roughness_texture");
|
||||
options.push_back("hint_depth_texture");
|
||||
options.push_back("hint_blit_source0");
|
||||
options.push_back("hint_blit_source1");
|
||||
options.push_back("hint_blit_source2");
|
||||
options.push_back("hint_blit_source3");
|
||||
options.push_back("source_color");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,6 +184,10 @@ public:
|
|||
TK_HINT_SCREEN_TEXTURE,
|
||||
TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
|
||||
TK_HINT_DEPTH_TEXTURE,
|
||||
TK_HINT_BLIT_SOURCE0,
|
||||
TK_HINT_BLIT_SOURCE1,
|
||||
TK_HINT_BLIT_SOURCE2,
|
||||
TK_HINT_BLIT_SOURCE3,
|
||||
TK_FILTER_NEAREST,
|
||||
TK_FILTER_LINEAR,
|
||||
TK_FILTER_NEAREST_MIPMAP,
|
||||
|
|
@ -676,6 +680,10 @@ public:
|
|||
HINT_DEFAULT_TRANSPARENT,
|
||||
HINT_ANISOTROPY,
|
||||
HINT_SCREEN_TEXTURE,
|
||||
HINT_BLIT_SOURCE0,
|
||||
HINT_BLIT_SOURCE1,
|
||||
HINT_BLIT_SOURCE2,
|
||||
HINT_BLIT_SOURCE3,
|
||||
HINT_NORMAL_ROUGHNESS_TEXTURE,
|
||||
HINT_DEPTH_TEXTURE,
|
||||
HINT_MAX
|
||||
|
|
|
|||
|
|
@ -519,12 +519,37 @@ ShaderTypes::ShaderTypes() {
|
|||
shader_modes[RS::SHADER_FOG].functions["fog"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
|
||||
shader_modes[RS::SHADER_FOG].functions["fog"].main_function = true;
|
||||
|
||||
/************ TEXTURE_BLIT **************************/
|
||||
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["constants"].built_ins["PI"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["constants"].built_ins["TAU"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["constants"].built_ins["E"] = constt(ShaderLanguage::TYPE_FLOAT);
|
||||
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2);
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["MODULATE"] = constt(ShaderLanguage::TYPE_VEC4);
|
||||
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["COLOR0"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["COLOR1"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["COLOR2"] = ShaderLanguage::TYPE_VEC4;
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].built_ins["COLOR3"] = ShaderLanguage::TYPE_VEC4;
|
||||
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].functions["blit"].main_function = true;
|
||||
|
||||
// Texture Blit Modes
|
||||
{
|
||||
shader_modes[RS::SHADER_TEXTURE_BLIT].modes.push_back({ PNAME("blend"), "mix", "add", "sub", "mul", "disabled" });
|
||||
}
|
||||
|
||||
// Must be kept in sync with the Shader::Mode enum.
|
||||
shader_types_list.push_back("spatial");
|
||||
shader_types_list.push_back("canvas_item");
|
||||
shader_types_list.push_back("particles");
|
||||
shader_types_list.push_back("sky");
|
||||
shader_types_list.push_back("fog");
|
||||
shader_types_list.push_back("texture_blit");
|
||||
DEV_ASSERT(shader_types_list.size() == Shader::MODE_MAX);
|
||||
|
||||
for (const String &type : shader_types_list) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public:
|
|||
virtual void texture_3d_initialize(RID p_texture, Image::Format, int p_width, int p_height, int p_depth, bool p_mipmaps, const Vector<Ref<Image>> &p_data) = 0;
|
||||
virtual void texture_external_initialize(RID p_texture, int p_width, int p_height, uint64_t p_external_buffer) = 0;
|
||||
virtual void texture_proxy_initialize(RID p_texture, RID p_base) = 0; //all slices, then all the mipmaps, must be coherent
|
||||
virtual void texture_drawable_initialize(RID p_texture, int p_width, int p_height, RS::TextureDrawableFormat p_format, const Color &p_color, bool p_with_mipmaps) = 0;
|
||||
|
||||
virtual RID texture_create_from_native_handle(RS::TextureType p_type, Image::Format p_format, uint64_t p_native_handle, int p_width, int p_height, int p_depth, int p_layers = 1, RS::TextureLayeredType p_layered_type = RS::TEXTURE_LAYERED_2D_ARRAY) = 0;
|
||||
|
||||
|
|
@ -77,6 +78,8 @@ public:
|
|||
virtual void texture_external_update(RID p_proxy, int p_width, int p_height, uint64_t p_external_buffer) = 0;
|
||||
virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0;
|
||||
|
||||
virtual void texture_drawable_blit_rect(const TypedArray<RID> &p_textures, const Rect2i &p_rect, RID p_material, const Color &p_modulate, const TypedArray<RID> &p_source_textures, int p_to_mipmap) = 0;
|
||||
|
||||
//these two APIs can be used together or in combination with the others.
|
||||
virtual void texture_2d_placeholder_initialize(RID p_texture) = 0;
|
||||
virtual void texture_2d_layered_placeholder_initialize(RID p_texture, RenderingServer::TextureLayeredType p_layered_type) = 0;
|
||||
|
|
@ -86,6 +89,9 @@ public:
|
|||
virtual Ref<Image> texture_2d_layer_get(RID p_texture, int p_layer) const = 0;
|
||||
virtual Vector<Ref<Image>> texture_3d_get(RID p_texture) const = 0;
|
||||
|
||||
virtual void texture_drawable_generate_mipmaps(RID p_texture) = 0;
|
||||
virtual RID texture_drawable_get_default_material() const = 0;
|
||||
|
||||
virtual void texture_replace(RID p_texture, RID p_by_texture) = 0;
|
||||
virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue