Browse Source

Add shader decorator

Michael Ragazzon 2 years ago
parent
commit
5d52f71d76

+ 63 - 2
Backends/RmlUi_Renderer_GL3.cpp

@@ -33,6 +33,7 @@
 #include <RmlUi/Core/GeometryUtilities.h>
 #include <RmlUi/Core/Log.h>
 #include <RmlUi/Core/Platform.h>
+#include <RmlUi/Core/SystemInterface.h>
 #include <string.h>
 
 #if defined(RMLUI_PLATFORM_WIN32) && !defined(__MINGW32__)
@@ -181,6 +182,33 @@ void main() {
 }
 )";
 
+// "Creation" by Danilo Guanabara, based on: https://www.shadertoy.com/view/XsXXDn
+static const char* shader_frag_creation = RMLUI_SHADER_HEADER R"(
+uniform float _value;
+uniform vec2 _dimensions;
+
+in vec2 fragTexCoord;
+in vec4 fragColor;
+out vec4 finalColor;
+
+void main() {
+	float t = _value;
+	vec3 c;
+	float l;
+	for (int i = 0; i < 3; i++) {
+		vec2 p = fragTexCoord;
+		vec2 uv = p;
+		p -= .5;
+		p.x *= _dimensions.x / _dimensions.y;
+		float z = t + float(i) * .07;
+		l = length(p);
+		uv += p / l * (sin(z) + 1.) * abs(sin(l * 9. - z - z));
+		c[i] = .01 / length(mod(uv, 1.) - .5);
+	}
+	finalColor = vec4(c / l, fragColor.a);
+}
+)";
+
 static const char* shader_vert_passthrough = RMLUI_SHADER_HEADER R"(
 in vec2 inPosition;
 in vec2 inTexCoord0;
@@ -270,6 +298,7 @@ enum class ProgramId {
 	Color,
 	Texture,
 	Gradient,
+	Creation,
 	Passthrough,
 	ColorMatrix,
 	Blur,
@@ -286,6 +315,7 @@ enum class FragShaderId {
 	Color,
 	Texture,
 	Gradient,
+	Creation,
 	Passthrough,
 	ColorMatrix,
 	Blur,
@@ -308,13 +338,16 @@ enum class UniformId {
 	StopColors,
 	StopPositions,
 	NumStops,
+	Value,
+	Dimensions,
 	Count,
 };
 
 namespace Gfx {
 
 static const char* const program_uniform_names[(size_t)UniformId::Count] = {"_translate", "_transform", "_tex", "_color", "_color_matrix",
-	"_texelOffset", "_texCoordMin", "_texCoordMax", "_weights[0]", "_func", "_p", "_v", "_stop_colors[0]", "_stop_positions[0]", "_num_stops"};
+	"_texelOffset", "_texCoordMin", "_texCoordMax", "_weights[0]", "_func", "_p", "_v", "_stop_colors[0]", "_stop_positions[0]", "_num_stops",
+	"_value", "_dimensions"};
 
 enum class VertexAttribute { Position, Color0, TexCoord0, Count };
 static const char* const vertex_attribute_names[(size_t)VertexAttribute::Count] = {"inPosition", "inColor0", "inTexCoord0"};
@@ -346,6 +379,7 @@ static const FragShaderDefinition frag_shader_definitions[] = {
 	{FragShaderId::Color,       "color",        shader_frag_color},
 	{FragShaderId::Texture,     "texture",      shader_frag_texture},
 	{FragShaderId::Gradient,    "gradient",     shader_frag_gradient},
+	{FragShaderId::Creation,    "creation",     shader_frag_creation},
 	{FragShaderId::Passthrough, "passthrough",  shader_frag_passthrough},
 	{FragShaderId::ColorMatrix, "color_matrix", shader_frag_color_matrix},
 	{FragShaderId::Blur,        "blur",         shader_frag_blur},
@@ -355,6 +389,7 @@ static const ProgramDefinition program_definitions[] = {
 	{ProgramId::Color,       "color",        VertShaderId::Main,        FragShaderId::Color},
 	{ProgramId::Texture,     "texture",      VertShaderId::Main,        FragShaderId::Texture},
 	{ProgramId::Gradient,    "gradient",     VertShaderId::Main,        FragShaderId::Gradient},
+	{ProgramId::Creation,    "creation",     VertShaderId::Main,        FragShaderId::Creation},
 	{ProgramId::Passthrough, "passthrough",  VertShaderId::Passthrough, FragShaderId::Passthrough},
 	{ProgramId::ColorMatrix, "color_matrix", VertShaderId::Passthrough, FragShaderId::ColorMatrix},
 	{ProgramId::Blur,        "blur",         VertShaderId::Blur,        FragShaderId::Blur},
@@ -1578,7 +1613,7 @@ void RenderInterface_GL3::ReleaseCompiledFilter(Rml::CompiledFilterHandle filter
 	delete reinterpret_cast<CompiledFilter*>(filter);
 }
 
-enum class CompiledShaderType { Invalid = 0, Gradient };
+enum class CompiledShaderType { Invalid = 0, Gradient, Creation };
 struct CompiledShader {
 	CompiledShaderType type;
 
@@ -1588,6 +1623,9 @@ struct CompiledShader {
 	Rml::Vector2f v;
 	Rml::Vector<float> stop_positions;
 	Rml::Vector<Rml::Colourf> stop_colors;
+
+	// Shader
+	Rml::Vector2f dimensions;
 };
 
 Rml::CompiledShaderHandle RenderInterface_GL3::CompileShader(const Rml::String& name, const Rml::Dictionary& parameters)
@@ -1639,6 +1677,15 @@ Rml::CompiledShaderHandle RenderInterface_GL3::CompileShader(const Rml::String&
 		shader.v = {Rml::Math::Cos(angle), Rml::Math::Sin(angle)};
 		ApplyColorStopList(shader, parameters);
 	}
+	else if (name == "shader")
+	{
+		const Rml::String value = Rml::Get(parameters, "value", Rml::String());
+		if (value == "creation")
+		{
+			shader.type = CompiledShaderType::Creation;
+			shader.dimensions = Rml::Get(parameters, "dimensions", Rml::Vector2f(0.f));
+		}
+	}
 
 	if (shader.type != CompiledShaderType::Invalid)
 		return reinterpret_cast<Rml::CompiledShaderHandle>(new CompiledShader(std::move(shader)));
@@ -1676,6 +1723,20 @@ void RenderInterface_GL3::RenderShader(Rml::CompiledShaderHandle shader_handle,
 		glBindVertexArray(0);
 	}
 	break;
+	case CompiledShaderType::Creation:
+	{
+		const double time = Rml::GetSystemInterface()->GetElapsedTime();
+
+		UseProgram(ProgramId::Creation);
+		glUniform1f(GetUniformLocation(UniformId::Value), (float)time);
+		glUniform2f(GetUniformLocation(UniformId::Dimensions), shader.dimensions.x, shader.dimensions.y);
+
+		SubmitTransformUniform(translation);
+		glBindVertexArray(geometry.vao);
+		glDrawElements(GL_TRIANGLES, geometry.draw_count, GL_UNSIGNED_INT, (const GLvoid*)0);
+		glBindVertexArray(0);
+	}
+	break;
 	case CompiledShaderType::Invalid:
 	{
 		Rml::Log::Message(Rml::Log::LT_WARNING, "Unhandled render shader %d.", (int)type);

+ 2 - 0
CMake/FileList.cmake

@@ -12,6 +12,7 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/DataViewDefault.h
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorGradient.h
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorNinePatch.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorShader.h
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiled.h
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiledBox.h
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiledHorizontal.h
@@ -255,6 +256,7 @@ set(Core_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/Decorator.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorGradient.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorNinePatch.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorShader.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiled.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiledBox.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/DecoratorTiledHorizontal.cpp

+ 2 - 1
Samples/basic/effect/data/effect.rml

@@ -63,6 +63,7 @@
 
 .transform, .filter.transform_all > .box { transform: rotate3d(0.2, 0.4, 0.1, 15deg); }
 
+.shader { decorator: shader("creation"); }
 .gradient { decorator: linear-gradient(110deg, #fff3, #fff 10%, #c33 250dp, #3c3, #33c, #000 90%, #0003) border-box; }
 
 .brightness { filter: brightness(0.5); }
@@ -156,7 +157,7 @@
 <div class="box boxshadow_inset"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
 
 <div class="box"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
-<div class="box big"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
+<div class="box big shader"><div class="label">"Creation" (Danilo Guanabara)</div></div>
 <div class="box big gradient"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>
 
 <div class="box hue_rotate"><img sprite="icon-invader"/>Hello, do you feel the funk?</div>

+ 1 - 1
Samples/basic/effect/src/main.cpp

@@ -140,7 +140,7 @@ int main(int /*argc*/, char** /*argv*/)
 	bool running = true;
 	while (running)
 	{
-		running = Backend::ProcessEvents(context, &Shell::ProcessKeyDownShortcuts, true);
+		running = Backend::ProcessEvents(context, &Shell::ProcessKeyDownShortcuts, false);
 
 		context->Update();
 

+ 13 - 25
Source/Core/DecoratorGradient.cpp

@@ -35,22 +35,10 @@
 #include "../../Include/RmlUi/Core/Math.h"
 #include "../../Include/RmlUi/Core/PropertyDefinition.h"
 #include "ComputeProperty.h"
-#include "Pool.h"
+#include "DecoratorShader.h"
 
 namespace Rml {
 
-struct GradientElementData {
-	GradientElementData(Geometry&& geometry, CompiledShaderHandle shader) : geometry(std::move(geometry)), shader(shader) {}
-	Geometry geometry;
-	CompiledShaderHandle shader;
-};
-
-Pool<GradientElementData>& GetGradientElementDataPool()
-{
-	static Pool<GradientElementData> gradient_element_data_pool(20, true);
-	return gradient_element_data_pool;
-}
-
 // Returns the point along the input line ('line_point', 'line_vector') closest to the input 'point'.
 static Vector2f IntersectionPointToLineNormal(const Vector2f point, const Vector2f line_point, const Vector2f line_vector)
 {
@@ -342,21 +330,21 @@ DecoratorDataHandle DecoratorLinearGradient::GenerateElementData(Element* elemen
 	for (Vertex& vertex : geometry.GetVertices())
 		vertex.tex_coord = vertex.position - render_offset;
 
-	GradientElementData* element_data = GetGradientElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
+	ShaderElementData* element_data = GetShaderElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
 
 	return reinterpret_cast<DecoratorDataHandle>(element_data);
 }
 
 void DecoratorLinearGradient::ReleaseElementData(DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	GetRenderInterface()->ReleaseCompiledShader(element_data->shader);
-	GetGradientElementDataPool().DestroyAndDeallocate(element_data);
+	GetShaderElementDataPool().DestroyAndDeallocate(element_data);
 }
 
 void DecoratorLinearGradient::RenderElement(Element* element, DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	element_data->geometry.RenderWithShader(element_data->shader, element->GetAbsoluteOffset(BoxArea::Border));
 }
 
@@ -510,20 +498,20 @@ DecoratorDataHandle DecoratorRadialGradient::GenerateElementData(Element* elemen
 	for (Vertex& vertex : geometry.GetVertices())
 		vertex.tex_coord = vertex.position - render_offset;
 
-	GradientElementData* element_data = GetGradientElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
+	ShaderElementData* element_data = GetShaderElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
 	return reinterpret_cast<DecoratorDataHandle>(element_data);
 }
 
 void DecoratorRadialGradient::ReleaseElementData(DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	GetRenderInterface()->ReleaseCompiledShader(element_data->shader);
-	GetGradientElementDataPool().DestroyAndDeallocate(element_data);
+	GetShaderElementDataPool().DestroyAndDeallocate(element_data);
 }
 
 void DecoratorRadialGradient::RenderElement(Element* element, DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	element_data->geometry.RenderWithShader(element_data->shader, element->GetAbsoluteOffset(BoxArea::Border));
 }
 
@@ -706,21 +694,21 @@ DecoratorDataHandle DecoratorConicGradient::GenerateElementData(Element* element
 	for (Vertex& vertex : geometry.GetVertices())
 		vertex.tex_coord = vertex.position - render_offset;
 
-	GradientElementData* element_data = GetGradientElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
+	ShaderElementData* element_data = GetShaderElementDataPool().AllocateAndConstruct(std::move(geometry), shader_handle);
 	return reinterpret_cast<DecoratorDataHandle>(element_data);
 }
 
 void DecoratorConicGradient::ReleaseElementData(DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	GetRenderInterface()->ReleaseCompiledShader(element_data->shader);
 
-	GetGradientElementDataPool().DestroyAndDeallocate(element_data);
+	GetShaderElementDataPool().DestroyAndDeallocate(element_data);
 }
 
 void DecoratorConicGradient::RenderElement(Element* element, DecoratorDataHandle handle) const
 {
-	GradientElementData* element_data = reinterpret_cast<GradientElementData*>(handle);
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
 	element_data->geometry.RenderWithShader(element_data->shader, element->GetAbsoluteOffset(BoxArea::Border));
 }
 

+ 118 - 0
Source/Core/DecoratorShader.cpp

@@ -0,0 +1,118 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019-2023 The RmlUi Team, and contributors
+ *
+ * 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 "DecoratorShader.h"
+#include "../../Include/RmlUi/Core/ComputedValues.h"
+#include "../../Include/RmlUi/Core/Element.h"
+#include "../../Include/RmlUi/Core/Geometry.h"
+#include "../../Include/RmlUi/Core/GeometryUtilities.h"
+#include "../../Include/RmlUi/Core/PropertyDefinition.h"
+#include "../../Include/RmlUi/Core/RenderInterface.h"
+
+namespace Rml {
+
+Pool<ShaderElementData>& GetShaderElementDataPool()
+{
+	static Pool<ShaderElementData> gradient_element_data_pool(20, true);
+	return gradient_element_data_pool;
+}
+
+DecoratorShader::DecoratorShader() {}
+
+DecoratorShader::~DecoratorShader() {}
+
+bool DecoratorShader::Initialise(String&& in_value)
+{
+	value = std::move(in_value);
+	return true;
+}
+
+DecoratorDataHandle DecoratorShader::GenerateElementData(Element* element, BoxArea render_area) const
+{
+	RenderInterface* render_interface = GetRenderInterface();
+	if (!render_interface)
+		return INVALID_DECORATORDATAHANDLE;
+
+	const Box& box = element->GetBox();
+	const Vector2f dimensions = box.GetSize(render_area);
+	CompiledShaderHandle effect_handle =
+		render_interface->CompileShader("shader", Dictionary{{"value", Variant(value)}, {"dimensions", Variant(dimensions)}});
+
+	Geometry geometry;
+
+	const ComputedValues& computed = element->GetComputedValues();
+	const byte alpha = byte(computed.opacity() * 255.f);
+	GeometryUtilities::GenerateBackground(&geometry, box, Vector2f(), computed.border_radius(), Colourb(255, alpha), render_area);
+
+	const Vector2f offset = box.GetPosition(render_area);
+	for (Vertex& vertex : geometry.GetVertices())
+		vertex.tex_coord = (vertex.position - offset) / dimensions;
+
+	ShaderElementData* element_data = GetShaderElementDataPool().AllocateAndConstruct(std::move(geometry), effect_handle);
+
+	return reinterpret_cast<DecoratorDataHandle>(element_data);
+}
+
+void DecoratorShader::ReleaseElementData(DecoratorDataHandle handle) const
+{
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
+	GetRenderInterface()->ReleaseCompiledShader(element_data->shader);
+	GetShaderElementDataPool().DestroyAndDeallocate(element_data);
+}
+
+void DecoratorShader::RenderElement(Element* element, DecoratorDataHandle handle) const
+{
+	ShaderElementData* element_data = reinterpret_cast<ShaderElementData*>(handle);
+	element_data->geometry.RenderWithShader(element_data->shader, element->GetAbsoluteOffset(BoxArea::Border));
+}
+
+DecoratorShaderInstancer::DecoratorShaderInstancer()
+{
+	ids.value = RegisterProperty("value", String()).AddParser("string").GetId();
+	RegisterShorthand("decorator", "value", ShorthandType::FallThrough);
+}
+
+DecoratorShaderInstancer::~DecoratorShaderInstancer() {}
+
+SharedPtr<Decorator> DecoratorShaderInstancer::InstanceDecorator(const String& /*name*/, const PropertyDictionary& properties_,
+	const DecoratorInstancerInterface& /*interface_*/)
+{
+	const Property* p_value = properties_.GetProperty(ids.value);
+	if (!p_value)
+		return nullptr;
+
+	String value = p_value->Get<String>();
+
+	auto decorator = MakeShared<DecoratorShader>();
+	if (decorator->Initialise(std::move(value)))
+		return decorator;
+
+	return nullptr;
+}
+
+} // namespace Rml

+ 79 - 0
Source/Core/DecoratorShader.h

@@ -0,0 +1,79 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ * Copyright (c) 2019-2023 The RmlUi Team, and contributors
+ *
+ * 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.
+ *
+ */
+
+#ifndef RMLUI_CORE_DECORATORSHADER_H
+#define RMLUI_CORE_DECORATORSHADER_H
+
+#include "../../Include/RmlUi/Core/Decorator.h"
+#include "../../Include/RmlUi/Core/Geometry.h"
+#include "../../Include/RmlUi/Core/ID.h"
+#include "../../Include/RmlUi/Core/Spritesheet.h"
+#include "Pool.h"
+
+namespace Rml {
+
+class DecoratorShader : public Decorator {
+public:
+	DecoratorShader();
+	virtual ~DecoratorShader();
+
+	bool Initialise(String&& value);
+
+	DecoratorDataHandle GenerateElementData(Element* element, BoxArea paint_area) const override;
+	void ReleaseElementData(DecoratorDataHandle element_data) const override;
+
+	void RenderElement(Element* element, DecoratorDataHandle element_data) const override;
+
+private:
+	String value;
+};
+
+class DecoratorShaderInstancer : public DecoratorInstancer {
+public:
+	DecoratorShaderInstancer();
+	~DecoratorShaderInstancer();
+
+	SharedPtr<Decorator> InstanceDecorator(const String& name, const PropertyDictionary& properties,
+		const DecoratorInstancerInterface& instancer_interface) override;
+
+private:
+	struct PropertyIds {
+		PropertyId value;
+	};
+	PropertyIds ids;
+};
+
+struct ShaderElementData {
+	ShaderElementData(Geometry&& geometry, CompiledShaderHandle shader) : geometry(std::move(geometry)), shader(shader) {}
+	Geometry geometry;
+	CompiledShaderHandle shader;
+};
+Pool<ShaderElementData>& GetShaderElementDataPool();
+
+} // namespace Rml
+#endif

+ 3 - 0
Source/Core/Factory.cpp

@@ -50,6 +50,7 @@
 #include "DataViewDefault.h"
 #include "DecoratorGradient.h"
 #include "DecoratorNinePatch.h"
+#include "DecoratorShader.h"
 #include "DecoratorTiledBox.h"
 #include "DecoratorTiledHorizontal.h"
 #include "DecoratorTiledImage.h"
@@ -152,6 +153,7 @@ struct DefaultInstancers {
 	DecoratorTiledBoxInstancer decorator_tiled_box;
 	DecoratorTiledImageInstancer decorator_image;
 	DecoratorNinePatchInstancer decorator_ninepatch;
+	DecoratorShaderInstancer decorator_shader;
 	DecoratorStraightGradientInstancer decorator_straight_gradient;
 	DecoratorLinearGradientInstancer decorator_linear_gradient;
 	DecoratorRadialGradientInstancer decorator_radial_gradient;
@@ -244,6 +246,7 @@ bool Factory::Initialise()
 	RegisterDecoratorInstancer("tiled-box", &default_instancers->decorator_tiled_box);
 	RegisterDecoratorInstancer("image", &default_instancers->decorator_image);
 	RegisterDecoratorInstancer("ninepatch", &default_instancers->decorator_ninepatch);
+	RegisterDecoratorInstancer("shader", &default_instancers->decorator_shader);
 
 	RegisterDecoratorInstancer("gradient", &default_instancers->decorator_straight_gradient);
 	RegisterDecoratorInstancer("horizontal-gradient", &default_instancers->decorator_straight_gradient);