Procházet zdrojové kódy

Added tags to material techniques

BearishSun před 9 roky
rodič
revize
e4637da406

binární
Data/Engine/GUISkin.asset


binární
Data/Engine/ResourceManifest.asset


binární
Data/Engine/Timestamp.asset


binární
Data/Engine/arial.ttf.asset


+ 4 - 3
Data/Raw/Engine/Shaders/TestFX.bsl

@@ -72,11 +72,11 @@ Parameters =
 	Sampler2DMS samp4;
 	Sampler2DMS samp4;
 	ByteBuffer buffer1;
 	ByteBuffer buffer1;
 	StructBuffer buffer2;
 	StructBuffer buffer2;
-	ByteBufferRW buffer3;
-	StructBufferRW buffer4;
+	RWByteBuffer buffer3;
+	RWStructBuffer buffer4;
 	AppendBuffer buffer5;
 	AppendBuffer buffer5;
 	ConsumeBuffer buffer6;
 	ConsumeBuffer buffer6;
-	TypedBufferRW buffer7;			  
+	RWTypedBuffer buffer7;			  
 };
 };
 
 
 Blocks = 
 Blocks = 
@@ -89,6 +89,7 @@ Technique =
 {
 {
 	Renderer = "Any";
 	Renderer = "Any";
 	Language = "HLSL11";
 	Language = "HLSL11";
+	Tags = { "Animated", "OtherTag" };
 
 
 	Pass =
 	Pass =
 	{
 	{

+ 16 - 3
Documentation/Manuals/Native/bslfx.md

@@ -174,24 +174,37 @@ Blocks all begin with the Block keyword, followed by a name. The name must match
 
 
 # Technique {#bslfx_c}
 # Technique {#bslfx_c}
 
 
-This is the meat of your shader. A technique contains code for your vertex/fragment/geometry/hull/domain/compute programs, as well as blend/rasterizer/depth-stencil states. A shader can contain multiple techniques but only a single technique is ever used at once. Different techniques can be specified for each shading language (e.g. HLSL, GLSL) and different renderer (in case you're using something other than the default).
+This is the meat of your shader. A technique contains code for your vertex/fragment/geometry/hull/domain/compute programs, as well as blend/rasterizer/depth-stencil states. A shader can contain multiple techniques but only a single technique is ever used at once. Different techniques can be specified for:
+ - Shading language (e.g. HLSL, GLSL) 
+ - Renderer (in case you're using something other than the default)
+ - Per-object properties (e.g. different technique for an animated object vs. a static object)
 
 
 ## Properties {#bslfx_c_a}
 ## Properties {#bslfx_c_a}
 
 
-Technique block should therefore always contain a "Language" property like so:
+Technique block should therefore always contain a "Language" property. This will ensure the proper technique is used depending on the render API the engine is set to use.
 ~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~
 	Language = "HLSL"
 	Language = "HLSL"
 ~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~
 
 
 Supported values are "HLSL" (DirectX 11 HLSL), "HLSL9" (DirectX 9 HLSL), and "GLSL".
 Supported values are "HLSL" (DirectX 11 HLSL), "HLSL9" (DirectX 9 HLSL), and "GLSL".
 
 
-You can also specify a renderer using the "Renderer" property:
+In case you are using a non-standard render, you can also specify a renderer using the "Renderer" property. This will ensure the propert technique is used as you switch between renderers.
 ~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~
 	Renderer = "Default"
 	Renderer = "Default"
 ~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~
 
 
 Supported values are "Any", or "Default". More values could be available if you are using a custom renderer, but otherwise you don't need to set this property.
 Supported values are "Any", or "Default". More values could be available if you are using a custom renderer, but otherwise you don't need to set this property.
 
 
+And finally you may specify an optional set of tags that serve as hints to the renderer when rendering a specific object. You may specify zero or multiple tags:
+~~~~~~~~~~~~~~
+	Tags = { "Animated", "OtherTag" }
+~~~~~~~~~~~~~~
+
+Currently recognized tags by the default renderer are:
+ - Animated - When renderer detects it is rendering a mesh that supports skeletal or blend shape animation, it will prefer to pick a technique with this tag, rather than one without it.
+
+Unrecognized tags will just be ignored. Renderer can be extended so it supports custom tags.
+ 
 Once the base properties are defined you can start defining code blocks and states.
 Once the base properties are defined you can start defining code blocks and states.
 
 
 ## Code blocks {#bslfx_c_b}
 ## Code blocks {#bslfx_c_b}

+ 1 - 1
Documentation/Manuals/Native/index.md

@@ -8,7 +8,7 @@ Welcome to the documentation for the native (C++) API of the Banshee Engine.
 This documentation contains a set of [manuals](@ref manuals) and an API reference for all native types.
 This documentation contains a set of [manuals](@ref manuals) and an API reference for all native types.
 
 
 # Manuals # {#mainpage_a}
 # Manuals # {#mainpage_a}
-Manuals should be your primary entry point into learning about Banshee. They will provide you with a view of the general architecture of the engine, as well as the architecture of the more important systems. They will also teach you have to extend/modify various parts of the engine, including adding custom GUI types, script objects, resources, importers, renderers and many more.
+Manuals should be your primary entry point into learning about Banshee. They will provide you with a view of the general architecture of the engine, as well as the architecture of the more important systems. They will also teach you how to extend/modify various parts of the engine, including adding custom GUI types, script objects, resources, importers, renderers and many more.
  
  
 The manuals generally do not cover user-facing functionality, and focus more on explaining the engine internals. To learn about user-facing functionality read the [scripting documentation](@ref TODO_LINK), the C++ interfaces are very similar and are usually just a direct reflection of their script counterparts.
 The manuals generally do not cover user-facing functionality, and focus more on explaining the engine internals. To learn about user-facing functionality read the [scripting documentation](@ref TODO_LINK), the C++ interfaces are very similar and are usually just a direct reflection of their script counterparts.
  
  

+ 7 - 2
Documentation/Manuals/Native/materials.md

@@ -42,12 +42,13 @@ SPtr<Pass> pass = Pass::create(desc);
 [GPU program](@ref gpuPrograms) and [render API](@ref renderAPI) manuals teach you how to create GPU programs and render states. 
 [GPU program](@ref gpuPrograms) and [render API](@ref renderAPI) manuals teach you how to create GPU programs and render states. 
 
 
 ## Technique {#materials_a_b}
 ## Technique {#materials_a_b}
-Now that we know how to create a pass, we can use one or multiple passes to initialize a @ref BansheeEngine::Technique "Technique". A technique is just a container for passes, with names of the supported render API and renderer.
+Now that we know how to create a pass, we can use one or multiple passes to initialize a @ref BansheeEngine::Technique "Technique". A technique is just a container for passes for a specific render API and renderer.
 
 
 To create a technique call @ref BansheeEngine::Technique::create "Technique::create" and provide it with:
 To create a technique call @ref BansheeEngine::Technique::create "Technique::create" and provide it with:
  - One or multiple passes
  - One or multiple passes
  - Supported render API name: Use built-in `RenderAPIAny` to signal that the technique works on any API, or use the render API identifier to signal that it only works on a specific one. By default supported identifiers are: `"D3D11RenderAPI"`, `"D3D9RenderAPI"`, `"GLRenderAPI"`, but more can be added via plugins. In general those identifiers are returned from @ref BansheeEngine::RenderAPICore::getName "RenderAPICore::getName". Most users should be okay by providing `RenderAPIAny`.
  - Supported render API name: Use built-in `RenderAPIAny` to signal that the technique works on any API, or use the render API identifier to signal that it only works on a specific one. By default supported identifiers are: `"D3D11RenderAPI"`, `"D3D9RenderAPI"`, `"GLRenderAPI"`, but more can be added via plugins. In general those identifiers are returned from @ref BansheeEngine::RenderAPICore::getName "RenderAPICore::getName". Most users should be okay by providing `RenderAPIAny`.
  - Supported renderer name: Use built-in `RendererAny` to signal that the technique works on any renderer, or use the renderer identifier to signal that it only works on a specific one. By default the only supported identifier is `"RenderBeast"`, but more can be added via plugins. In general those identifiers are returned from @ref BansheeEngine::Renderer::getName "Renderer::getName". Most users should be okay by providing `RendererAny`.
  - Supported renderer name: Use built-in `RendererAny` to signal that the technique works on any renderer, or use the renderer identifier to signal that it only works on a specific one. By default the only supported identifier is `"RenderBeast"`, but more can be added via plugins. In general those identifiers are returned from @ref BansheeEngine::Renderer::getName "Renderer::getName". Most users should be okay by providing `RendererAny`.
+ - An optional list of tags that allows renderer to pick which technique to use when rendering objects. Can be left empty in most cases.
 
 
 For example:
 For example:
 ~~~~~~~~~~~~~{.cpp}
 ~~~~~~~~~~~~~{.cpp}
@@ -184,7 +185,11 @@ albedoParam.set(Texture::White);
 # Rendering with material {#materials_d}
 # Rendering with material {#materials_d}
 From the simulation thread you cannot use material to render manually (you must instead use GPU programs and states manually as described by the [render API](@ref renderAPI) manual). You are instead expected to set the material on a @ref BansheeEngine::Renderable "Renderable" object which will then be used for rendering automatically. Read the [renderer](@ref renderer) manual for more information.
 From the simulation thread you cannot use material to render manually (you must instead use GPU programs and states manually as described by the [render API](@ref renderAPI) manual). You are instead expected to set the material on a @ref BansheeEngine::Renderable "Renderable" object which will then be used for rendering automatically. Read the [renderer](@ref renderer) manual for more information.
 
 
-Core thread gives you more flexibility and you can use @ref BansheeEngine::RendererUtility::setPass "RendererUtility::setPass" to bind a specific pass from a material to the pipeline, and @ref BansheeEngine::RendererUtility::setPassParams "RendererUtility::setPassParams" to bind material parameters for a specific pass. You can follow these calls with draw calls as described in the [render API](@ref renderAPI) manual to render objects manually. 
+Core thread gives you more flexibility and you can use @ref BansheeEngine::RendererUtility::setPass "RendererUtility::setPass" to bind a specific pass from a material to the pipeline, and @ref BansheeEngine::RendererUtility::setPassParams "RendererUtility::setPassParams" to bind material parameters for a specific pass. 
+
+In order to retrieve a set of per-program @ref BansheeEngine::RendererUtility::GpuParams "GpuParams" that can be used for binding directly to the pipeline, call @ref BansheeEngine::Material::createParamsSet "Material::createParamsSet", followed by @ref BansheeEngine::Material::updateParamsSet "Material::updateParamsSet". You are required to call @ref BansheeEngine::Material::updateParamsSet "Material::updateParamsSet" whenever material parameters change, in order to transfer the new data to @ref BansheeEngine::RendererUtility::GpuParams "GpuParams".
+
+After pass and pass parameters are bound you can follow them with draw calls as described in the [render API](@ref renderAPI) manual to render objects manually. 
 
 
 # Saving/loading {#materials_e}
 # Saving/loading {#materials_e}
 A material is a @ref BansheeEngine::Resource "Resource" and can be saved/loaded like any other. See the [resource](@ref resources) manual.
 A material is a @ref BansheeEngine::Resource "Resource" and can be saved/loaded like any other. See the [resource](@ref resources) manual.

+ 51 - 29
Source/BansheeCore/Include/BsTechnique.h

@@ -12,19 +12,11 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/**
-	 * Technique represents a specific implementation of a shader. Contains a number of passes that will be executed when 
-	 * rendering objects using this technique.
-	 *
-	 * @note	
-	 * Normally you want to have a separate technique for every render system and renderer your application supports. 
-	 * For example, if you are supporting DirectX11 and OpenGL you will want to have two techniques, one using HLSL based 
-	 * GPU programs, other using GLSL. Those techniques should try to mirror each others end results.
-	 */
+	/** Base class that is used for implementing both sim and core versions of Technique. */
 	class BS_CORE_EXPORT TechniqueBase
 	class BS_CORE_EXPORT TechniqueBase
 	{
 	{
 	public:
 	public:
-		TechniqueBase(const StringID& renderAPI, const StringID& renderer);
+		TechniqueBase(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags);
 		virtual ~TechniqueBase() { }
 		virtual ~TechniqueBase() { }
 
 
 		/**	Checks if this technique is supported based on current render and other systems. */
 		/**	Checks if this technique is supported based on current render and other systems. */
@@ -36,6 +28,7 @@ namespace BansheeEngine
 	protected:
 	protected:
 		StringID mRenderAPI;
 		StringID mRenderAPI;
 		StringID mRenderer;
 		StringID mRenderer;
+		Vector<StringID> mTags;
 	};
 	};
 
 
 	template<bool Core> struct TPassType { };
 	template<bool Core> struct TPassType { };
@@ -46,11 +39,7 @@ namespace BansheeEngine
 	template<> struct TTechniqueType < false > { typedef Technique Type; };
 	template<> struct TTechniqueType < false > { typedef Technique Type; };
 	template<> struct TTechniqueType < true > { typedef TechniqueCore Type; };
 	template<> struct TTechniqueType < true > { typedef TechniqueCore Type; };
 
 
-	/**
-	 * @copydoc	TechniqueBase
-	 *
-	 * @note	Templated version that is used for implementing both sim and core versions of Technique.
-	 */
+	/** Templated class that is used for implementing both sim and core versions of Technique. */
 	template<bool Core>
 	template<bool Core>
 	class BS_CORE_EXPORT TTechnique : public TechniqueBase
 	class BS_CORE_EXPORT TTechnique : public TechniqueBase
 	{
 	{
@@ -58,7 +47,8 @@ namespace BansheeEngine
 		typedef typename TPassType<Core>::Type PassType;
 		typedef typename TPassType<Core>::Type PassType;
 		
 		
 		TTechnique();
 		TTechnique();
-		TTechnique(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassType>>& passes);
+		TTechnique(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+			const Vector<SPtr<PassType>>& passes);
 		virtual ~TTechnique() { }
 		virtual ~TTechnique() { }
 
 
 		/**	Returns a pass with the specified index. */
 		/**	Returns a pass with the specified index. */
@@ -77,18 +67,20 @@ namespace BansheeEngine
 	 *  @{
 	 *  @{
 	 */
 	 */
 
 
-	/**
-	 * @copydoc	TechniqueBase
-	 *
-	 * @note	Core thread.
-	 */
+	/** Core thread version of Technique. */
 	class BS_CORE_EXPORT TechniqueCore : public CoreObjectCore, public TTechnique<true>
 	class BS_CORE_EXPORT TechniqueCore : public CoreObjectCore, public TTechnique<true>
 	{
 	{
 	public:
 	public:
-		TechniqueCore(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassCore>>& passes);
+		TechniqueCore(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+			const Vector<SPtr<PassCore>>& passes);
+
+		/** @copydoc Technique::create(const StringID&, const StringID&, const Vector<SPtr<Pass>>&) */
+		static SPtr<TechniqueCore> create(const StringID& renderAPI, const StringID& renderer, 
+			const Vector<SPtr<PassCore>>& passes);
 
 
-		/** Creates a new technique. */
-		static SPtr<TechniqueCore> create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassCore>>& passes);
+		/** @copydoc Technique::create(const StringID&, const StringID&, const Vector<StringID>&, const Vector<SPtr<Pass>>&) */
+		static SPtr<TechniqueCore> create(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags,
+			const Vector<SPtr<PassCore>>& passes);
 	};
 	};
 
 
 	/** @} */
 	/** @} */
@@ -97,21 +89,51 @@ namespace BansheeEngine
 	 */
 	 */
 
 
 	/**
 	/**
-	 * @copydoc	TechniqueBase
+	 * Technique is a set of shading passes bindable to the GPU pipeline. Each technique can also have a set of properties
+	 * that help the engine to determine which technique should be used under which circumstances (if more than one
+	 * technique is available).
 	 *
 	 *
-	 * @note	Sim thread.
+	 * @note	
+	 * Normally you want to have a separate technique for every render system and renderer your application supports. 
+	 * For example, if you are supporting DirectX11 and OpenGL you will want to have two techniques, one using HLSL based 
+	 * GPU programs, other using GLSL. Those techniques should try to mirror each other's end results.
 	 */
 	 */
 	class BS_CORE_EXPORT Technique : public IReflectable, public CoreObject, public TTechnique<false>
 	class BS_CORE_EXPORT Technique : public IReflectable, public CoreObject, public TTechnique<false>
 	{
 	{
 	public:
 	public:
-		Technique(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes);
+		Technique(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+			const Vector<SPtr<Pass>>& passes);
 
 
 		/** Retrieves an implementation of a technique usable only from the core thread. */
 		/** Retrieves an implementation of a technique usable only from the core thread. */
 		SPtr<TechniqueCore> getCore() const;
 		SPtr<TechniqueCore> getCore() const;
 
 
-		/** Creates a new technique. */
+		/** 
+		 * Creates a new technique. 
+		 *
+		 * @param[in]	renderAPI	Render API the technique supports. Under normal circumstances the engine will not use
+		 *							this technique unless this API is enabled.
+		 * @param[in]	renderer	Renderer the technique supports. Under normal circumstances the engine will not use
+		 *							this technique unless this renderer is enabled.
+		 * @param[in]	passes		A set of passes that define the technique.
+		 * @return					Newly creted technique.
+		 */
 		static SPtr<Technique> create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes);
 		static SPtr<Technique> create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes);
 
 
+		/** 
+		 * Creates a new technique. 
+		 *
+		 * @param[in]	renderAPI	Render API the technique supports. Under normal circumstances the engine will not use
+		 *							this technique unless this API is enabled.
+		 * @param[in]	renderer	Renderer the technique supports. Under normal circumstances the engine will not use
+		 *							this technique unless this renderer is enabled.
+		 * @param[in]	tags		An optional set of tags that can be used for further identifying under which 
+		 *							circumstances should a technique be used.
+		 * @param[in]	passes		A set of passes that define the technique.
+		 * @return					Newly creted technique.
+		 */
+		static SPtr<Technique> create(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+			const Vector<SPtr<Pass>>& passes);
+
 	protected:
 	protected:
 		/** @copydoc CoreObject::createCore */
 		/** @copydoc CoreObject::createCore */
 		SPtr<CoreObjectCore> createCore() const override;
 		SPtr<CoreObjectCore> createCore() const override;
@@ -133,7 +155,7 @@ namespace BansheeEngine
 	public:
 	public:
 		friend class TechniqueRTTI;
 		friend class TechniqueRTTI;
 		static RTTITypeBase* getRTTIStatic();
 		static RTTITypeBase* getRTTIStatic();
-		virtual RTTITypeBase* getRTTI() const override;	
+		RTTITypeBase* getRTTI() const override;	
 	};
 	};
 
 
 	/** @} */
 	/** @} */

+ 8 - 17
Source/BansheeCore/Include/BsTechniqueRTTI.h

@@ -16,26 +16,17 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT TechniqueRTTI : public RTTIType<Technique, IReflectable, TechniqueRTTI>
 	class BS_CORE_EXPORT TechniqueRTTI : public RTTIType<Technique, IReflectable, TechniqueRTTI>
 	{
 	{
 	private:
 	private:
-		StringID& getRenderAPI(Technique* obj) { return obj->mRenderAPI; }
-		void setRenderAPI(Technique* obj, StringID& val) { obj->mRenderAPI = val; }
-
-		StringID& getRenderer(Technique* obj) { return obj->mRenderer; }
-		void setRenderer(Technique* obj, StringID& val) { obj->mRenderer = val; }
-
-		SPtr<Pass> getPass(Technique* obj, UINT32 idx) { return obj->mPasses[idx]; }
-		void setPass(Technique* obj, UINT32 idx, SPtr<Pass> val) { obj->mPasses[idx] = val; }
-
-		UINT32 getPassArraySize(Technique* obj) { return (UINT32)obj->mPasses.size(); }
-		void setPassArraySize(Technique* obj, UINT32 size) { obj->mPasses.resize(size); }
+		BS_BEGIN_RTTI_MEMBERS
+			BS_RTTI_MEMBER_PLAIN(mRenderAPI, 0)
+			BS_RTTI_MEMBER_PLAIN(mRenderer, 1)
+			BS_RTTI_MEMBER_REFLPTR_ARRAY(mPasses, 2)
+			BS_RTTI_MEMBER_PLAIN_ARRAY(mTags, 3)
+		BS_END_RTTI_MEMBERS
 
 
 	public:
 	public:
 		TechniqueRTTI()
 		TechniqueRTTI()
-		{
-			addPlainField("mRenderAPI", 0, &TechniqueRTTI::getRenderAPI, &TechniqueRTTI::setRenderAPI);
-			addPlainField("mRenderer", 1, &TechniqueRTTI::getRenderer, &TechniqueRTTI::setRenderer);
-
-			addReflectablePtrArrayField("mPasses", 2, &TechniqueRTTI::getPass, &TechniqueRTTI::getPassArraySize, &TechniqueRTTI::setPass, &TechniqueRTTI::setPassArraySize);
-		}
+			:mInitMembers(this)
+		{ }
 
 
 		void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
 		void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
 		{
 		{

+ 45 - 14
Source/BansheeCore/Source/BsTechnique.cpp

@@ -11,8 +11,8 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	TechniqueBase::TechniqueBase(const StringID& renderAPI, const StringID& renderer)
-		:mRenderAPI(renderAPI), mRenderer(renderer)
+	TechniqueBase::TechniqueBase(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags)
+		:mRenderAPI(renderAPI), mRenderer(renderer), mTags(tags)
 	{
 	{
 
 
 	}
 	}
@@ -32,18 +32,24 @@ namespace BansheeEngine
 
 
 	bool TechniqueBase::hasTag(const StringID& tag)
 	bool TechniqueBase::hasTag(const StringID& tag)
 	{
 	{
-		// TODO - Not implemented
+		for(auto& entry : mTags)
+		{
+			if (entry == tag)
+				return true;
+		}
+
 		return false;
 		return false;
 	}
 	}
 
 
 	template<bool Core>
 	template<bool Core>
-	TTechnique<Core>::TTechnique(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassType>>& passes)
-		: TechniqueBase(renderAPI, renderer), mPasses(passes)
+	TTechnique<Core>::TTechnique(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+		const Vector<SPtr<PassType>>& passes)
+		: TechniqueBase(renderAPI, renderer, tags), mPasses(passes)
 	{ }
 	{ }
 
 
 	template<bool Core>
 	template<bool Core>
 	TTechnique<Core>::TTechnique()
 	TTechnique<Core>::TTechnique()
-		: TechniqueBase("", "")
+		: TechniqueBase("", "", {})
 	{ }
 	{ }
 
 
 	template<bool Core>
 	template<bool Core>
@@ -58,13 +64,15 @@ namespace BansheeEngine
 	template class TTechnique < false > ;
 	template class TTechnique < false > ;
 	template class TTechnique < true >;
 	template class TTechnique < true >;
 
 
-	TechniqueCore::TechniqueCore(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassCore>>& passes)
-		:TTechnique(renderAPI, renderer, passes)
+	TechniqueCore::TechniqueCore(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+		const Vector<SPtr<PassCore>>& passes)
+		:TTechnique(renderAPI, renderer, tags, passes)
 	{ }
 	{ }
 
 
-	SPtr<TechniqueCore> TechniqueCore::create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<PassCore>>& passes)
+	SPtr<TechniqueCore> TechniqueCore::create(const StringID& renderAPI, const StringID& renderer, 
+		const Vector<SPtr<PassCore>>& passes)
 	{
 	{
-		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderAPI, renderer, passes);
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderAPI, renderer, {}, passes);
 		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore>(technique);
 		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore>(technique);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->initialize();
 		techniquePtr->initialize();
@@ -72,8 +80,20 @@ namespace BansheeEngine
 		return techniquePtr;
 		return techniquePtr;
 	}
 	}
 
 
-	Technique::Technique(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes)
-		:TTechnique(renderAPI, renderer, passes)
+	SPtr<TechniqueCore> TechniqueCore::create(const StringID& renderAPI, const StringID& renderer, 
+		const Vector<StringID>& tags, const Vector<SPtr<PassCore>>& passes)
+	{
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(renderAPI, renderer, tags, passes);
+		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+		techniquePtr->initialize();
+
+		return techniquePtr;
+	}
+
+	Technique::Technique(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+		const Vector<SPtr<Pass>>& passes)
+		:TTechnique(renderAPI, renderer, tags, passes)
 	{ }
 	{ }
 
 
 	Technique::Technique()
 	Technique::Technique()
@@ -91,7 +111,7 @@ namespace BansheeEngine
 		for (auto& pass : mPasses)
 		for (auto& pass : mPasses)
 			passes.push_back(pass->getCore());
 			passes.push_back(pass->getCore());
 
 
-		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(mRenderAPI, mRenderer, passes);
+		TechniqueCore* technique = new (bs_alloc<TechniqueCore>()) TechniqueCore(mRenderAPI, mRenderer, mTags, passes);
 		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore>(technique);
 		SPtr<TechniqueCore> techniquePtr = bs_shared_ptr<TechniqueCore>(technique);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->_setThisPtr(techniquePtr);
 
 
@@ -106,7 +126,18 @@ namespace BansheeEngine
 
 
 	SPtr<Technique> Technique::create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes)
 	SPtr<Technique> Technique::create(const StringID& renderAPI, const StringID& renderer, const Vector<SPtr<Pass>>& passes)
 	{
 	{
-		Technique* technique = new (bs_alloc<Technique>()) Technique(renderAPI, renderer, passes);
+		Technique* technique = new (bs_alloc<Technique>()) Technique(renderAPI, renderer, {}, passes);
+		SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
+		techniquePtr->_setThisPtr(techniquePtr);
+		techniquePtr->initialize();
+
+		return techniquePtr;
+	}
+
+	SPtr<Technique> Technique::create(const StringID& renderAPI, const StringID& renderer, const Vector<StringID>& tags, 
+		const Vector<SPtr<Pass>>& passes)
+	{
+		Technique* technique = new (bs_alloc<Technique>()) Technique(renderAPI, renderer, tags, passes);
 		SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
 		SPtr<Technique> techniquePtr = bs_core_ptr<Technique>(technique);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->_setThisPtr(techniquePtr);
 		techniquePtr->initialize();
 		techniquePtr->initialize();

+ 1 - 0
Source/BansheeSL/BsLexerFX.l

@@ -110,6 +110,7 @@ Blocks			{ return TOKEN_BLOCKS; }
 	/* Technique keywords */
 	/* Technique keywords */
 Renderer		{ return TOKEN_RENDERER; }
 Renderer		{ return TOKEN_RENDERER; }
 Language		{ return TOKEN_LANGUAGE; }
 Language		{ return TOKEN_LANGUAGE; }
+Tags			{ return TOKEN_TAGS; }
 Pass			{ return TOKEN_PASS; }
 Pass			{ return TOKEN_PASS; }
 
 
 	/* Pass keywords */
 	/* Pass keywords */

+ 30 - 1
Source/BansheeSL/BsParserFX.y

@@ -155,7 +155,7 @@ typedef struct YYLTYPE {
 %token TOKEN_PARAMETERS TOKEN_BLOCKS TOKEN_TECHNIQUE
 %token TOKEN_PARAMETERS TOKEN_BLOCKS TOKEN_TECHNIQUE
 
 
 	/* Technique keywords */
 	/* Technique keywords */
-%token	TOKEN_RENDERER TOKEN_LANGUAGE TOKEN_PASS
+%token	TOKEN_RENDERER TOKEN_LANGUAGE TOKEN_PASS TOKEN_TAGS
 
 
 	/* Pass keywords */
 	/* Pass keywords */
 %token	TOKEN_VERTEX TOKEN_FRAGMENT TOKEN_GEOMETRY TOKEN_HULL TOKEN_DOMAIN TOKEN_COMPUTE TOKEN_COMMON
 %token	TOKEN_VERTEX TOKEN_FRAGMENT TOKEN_GEOMETRY TOKEN_HULL TOKEN_DOMAIN TOKEN_COMPUTE TOKEN_COMMON
@@ -185,6 +185,8 @@ typedef struct YYLTYPE {
 %type <nodePtr>		technique_header;
 %type <nodePtr>		technique_header;
 %type <nodeOption>	technique_statement;
 %type <nodeOption>	technique_statement;
 %type <nodeOption>	technique_option;
 %type <nodeOption>	technique_option;
+%type <nodePtr>		tags;
+%type <nodePtr>		tags_header;
 
 
 %type <nodePtr>		pass;
 %type <nodePtr>		pass;
 %type <nodePtr>		pass_header;
 %type <nodePtr>		pass_header;
@@ -327,6 +329,33 @@ technique_statement
 technique_option
 technique_option
 	: TOKEN_RENDERER '=' TOKEN_STRING ';'	{ $$.type = OT_Renderer; $$.value.strValue = $3; }
 	: TOKEN_RENDERER '=' TOKEN_STRING ';'	{ $$.type = OT_Renderer; $$.value.strValue = $3; }
 	| TOKEN_LANGUAGE '=' TOKEN_STRING ';'	{ $$.type = OT_Language; $$.value.strValue = $3; }
 	| TOKEN_LANGUAGE '=' TOKEN_STRING ';'	{ $$.type = OT_Language; $$.value.strValue = $3; }
+	| tags									{ $$.type = OT_Tags; $$.value.nodePtr = $1; }
+	;
+	
+tags
+	: tags_header '{' tags_body '}' ';'	{ nodePop(parse_state); $$ = $1; }
+	;
+	
+tags_header
+	: TOKEN_TAGS '='
+		{ 
+			$$ = nodeCreate(parse_state->memContext, NT_Tags); 
+			nodePush(parse_state, $$);
+		}
+	;
+	
+tags_body
+	: /* empty */
+	| TOKEN_STRING
+		{ 
+			NodeOption entry; entry.type = OT_TagValue; entry.value.strValue = $1;
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry); 
+		}		
+	| TOKEN_STRING ',' tags_body		
+		{ 
+			NodeOption entry; entry.type = OT_TagValue; entry.value.strValue = $1;
+			nodeOptionsAdd(parse_state->memContext, parse_state->topNode->options, &entry); 
+		}	
 	;
 	;
 
 
 	/* Pass */
 	/* Pass */

+ 3 - 0
Source/BansheeSL/Include/BsASTFX.h

@@ -20,6 +20,7 @@ enum tagNodeType
 	NT_AddrMode,
 	NT_AddrMode,
 	NT_Parameter,
 	NT_Parameter,
 	NT_Block,
 	NT_Block,
+	NT_Tags,
 	NT_CodeVertex,
 	NT_CodeVertex,
 	NT_CodeFragment,
 	NT_CodeFragment,
 	NT_CodeGeometry,
 	NT_CodeGeometry,
@@ -97,6 +98,8 @@ enum tagOptionType
 	OT_SamplerState,
 	OT_SamplerState,
 	OT_Code,
 	OT_Code,
 	OT_StencilRef,
 	OT_StencilRef,
+	OT_Tags,
+	OT_TagValue,
 	OT_Count
 	OT_Count
 };
 };
 
 

+ 1 - 1
Source/BansheeSL/Include/BsLexerFX.h

@@ -349,7 +349,7 @@ extern int yylex \
 #undef YY_DECL
 #undef YY_DECL
 #endif
 #endif
 
 
-#line 395 "C:/Projects/BansheeEngineDev/BansheeEngine/Source/BansheeSL/BsLexerFX.l"
+#line 396 "C:/Projects/BansheeEngineDev/BansheeEngine/Source/BansheeSL/BsLexerFX.l"
 
 
 
 
 #line 356 "BsLexerFX.h"
 #line 356 "BsLexerFX.h"

+ 51 - 50
Source/BansheeSL/Include/BsParserFX.h

@@ -174,55 +174,56 @@ typedef struct YYLTYPE {
      TOKEN_RENDERER = 324,
      TOKEN_RENDERER = 324,
      TOKEN_LANGUAGE = 325,
      TOKEN_LANGUAGE = 325,
      TOKEN_PASS = 326,
      TOKEN_PASS = 326,
-     TOKEN_VERTEX = 327,
-     TOKEN_FRAGMENT = 328,
-     TOKEN_GEOMETRY = 329,
-     TOKEN_HULL = 330,
-     TOKEN_DOMAIN = 331,
-     TOKEN_COMPUTE = 332,
-     TOKEN_COMMON = 333,
-     TOKEN_STENCILREF = 334,
-     TOKEN_FILLMODE = 335,
-     TOKEN_CULLMODE = 336,
-     TOKEN_DEPTHBIAS = 337,
-     TOKEN_SDEPTHBIAS = 338,
-     TOKEN_DEPTHCLIP = 339,
-     TOKEN_SCISSOR = 340,
-     TOKEN_MULTISAMPLE = 341,
-     TOKEN_AALINE = 342,
-     TOKEN_DEPTHREAD = 343,
-     TOKEN_DEPTHWRITE = 344,
-     TOKEN_COMPAREFUNC = 345,
-     TOKEN_STENCIL = 346,
-     TOKEN_STENCILREADMASK = 347,
-     TOKEN_STENCILWRITEMASK = 348,
-     TOKEN_STENCILOPFRONT = 349,
-     TOKEN_STENCILOPBACK = 350,
-     TOKEN_FAIL = 351,
-     TOKEN_ZFAIL = 352,
-     TOKEN_ALPHATOCOVERAGE = 353,
-     TOKEN_INDEPENDANTBLEND = 354,
-     TOKEN_TARGET = 355,
-     TOKEN_INDEX = 356,
-     TOKEN_BLEND = 357,
-     TOKEN_COLOR = 358,
-     TOKEN_ALPHA = 359,
-     TOKEN_WRITEMASK = 360,
-     TOKEN_SOURCE = 361,
-     TOKEN_DEST = 362,
-     TOKEN_OP = 363,
-     TOKEN_ADDRMODE = 364,
-     TOKEN_MINFILTER = 365,
-     TOKEN_MAGFILTER = 366,
-     TOKEN_MIPFILTER = 367,
-     TOKEN_MAXANISO = 368,
-     TOKEN_MIPBIAS = 369,
-     TOKEN_MIPMIN = 370,
-     TOKEN_MIPMAX = 371,
-     TOKEN_BORDERCOLOR = 372,
-     TOKEN_U = 373,
-     TOKEN_V = 374,
-     TOKEN_W = 375
+     TOKEN_TAGS = 327,
+     TOKEN_VERTEX = 328,
+     TOKEN_FRAGMENT = 329,
+     TOKEN_GEOMETRY = 330,
+     TOKEN_HULL = 331,
+     TOKEN_DOMAIN = 332,
+     TOKEN_COMPUTE = 333,
+     TOKEN_COMMON = 334,
+     TOKEN_STENCILREF = 335,
+     TOKEN_FILLMODE = 336,
+     TOKEN_CULLMODE = 337,
+     TOKEN_DEPTHBIAS = 338,
+     TOKEN_SDEPTHBIAS = 339,
+     TOKEN_DEPTHCLIP = 340,
+     TOKEN_SCISSOR = 341,
+     TOKEN_MULTISAMPLE = 342,
+     TOKEN_AALINE = 343,
+     TOKEN_DEPTHREAD = 344,
+     TOKEN_DEPTHWRITE = 345,
+     TOKEN_COMPAREFUNC = 346,
+     TOKEN_STENCIL = 347,
+     TOKEN_STENCILREADMASK = 348,
+     TOKEN_STENCILWRITEMASK = 349,
+     TOKEN_STENCILOPFRONT = 350,
+     TOKEN_STENCILOPBACK = 351,
+     TOKEN_FAIL = 352,
+     TOKEN_ZFAIL = 353,
+     TOKEN_ALPHATOCOVERAGE = 354,
+     TOKEN_INDEPENDANTBLEND = 355,
+     TOKEN_TARGET = 356,
+     TOKEN_INDEX = 357,
+     TOKEN_BLEND = 358,
+     TOKEN_COLOR = 359,
+     TOKEN_ALPHA = 360,
+     TOKEN_WRITEMASK = 361,
+     TOKEN_SOURCE = 362,
+     TOKEN_DEST = 363,
+     TOKEN_OP = 364,
+     TOKEN_ADDRMODE = 365,
+     TOKEN_MINFILTER = 366,
+     TOKEN_MAGFILTER = 367,
+     TOKEN_MIPFILTER = 368,
+     TOKEN_MAXANISO = 369,
+     TOKEN_MIPBIAS = 370,
+     TOKEN_MIPMIN = 371,
+     TOKEN_MIPMAX = 372,
+     TOKEN_BORDERCOLOR = 373,
+     TOKEN_U = 374,
+     TOKEN_V = 375,
+     TOKEN_W = 376
    };
    };
 #endif
 #endif
 
 
@@ -242,7 +243,7 @@ typedef union YYSTYPE
 
 
 
 
 /* Line 2579 of glr.c  */
 /* Line 2579 of glr.c  */
-#line 246 "BsParserFX.h"
+#line 247 "BsParserFX.h"
 } YYSTYPE;
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */

+ 3 - 1
Source/BansheeSL/Include/BsSLFXCompiler.h

@@ -65,6 +65,7 @@ namespace BansheeEngine
 		{
 		{
 			StringID renderer = RendererAny;
 			StringID renderer = RendererAny;
 			StringID renderAPI = RenderAPIAny;
 			StringID renderAPI = RenderAPIAny;
+			Vector<StringID> tags;
 			String language;
 			String language;
 
 
 			PassData commonPassData;
 			PassData commonPassData;
@@ -83,7 +84,8 @@ namespace BansheeEngine
 		 * Retrieves the renderer and language specified for the technique. These two values are considered a unique 
 		 * Retrieves the renderer and language specified for the technique. These two values are considered a unique 
 		 * identifier for a technique.
 		 * identifier for a technique.
 		 */
 		 */
-		static void getTechniqueIdentifier(ASTFXNode* technique, StringID& renderer, String& language);
+		static void getTechniqueIdentifier(ASTFXNode* technique, StringID& renderer, String& language, 
+			Vector<StringID>& tags);
 
 
 		/** Checks if two techniques can be matched based on the options specified in their child nodes. */
 		/** Checks if two techniques can be matched based on the options specified in their child nodes. */
 		static bool doTechniquesMatch(ASTFXNode* into, ASTFXNode* from);
 		static bool doTechniquesMatch(ASTFXNode* into, ASTFXNode* from);

+ 3 - 1
Source/BansheeSL/Source/BsASTFX.c

@@ -71,7 +71,9 @@ OptionInfo OPTION_LOOKUP[] =
 	{ OT_Block, ODT_Complex },
 	{ OT_Block, ODT_Complex },
 	{ OT_SamplerState, ODT_Complex },
 	{ OT_SamplerState, ODT_Complex },
 	{ OT_Code, ODT_Complex },
 	{ OT_Code, ODT_Complex },
-	{ OT_StencilRef, ODT_Int }
+	{ OT_StencilRef, ODT_Int },
+	{ OT_Tags, ODT_Complex },
+	{ OT_TagValue, ODT_String }
 };
 };
 
 
 NodeOptions* nodeOptionsCreate(void* context)
 NodeOptions* nodeOptionsCreate(void* context)

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 500 - 500
Source/BansheeSL/Source/BsLexerFX.c


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 456 - 445
Source/BansheeSL/Source/BsParserFX.c


+ 60 - 5
Source/BansheeSL/Source/BsSLFXCompiler.cpp

@@ -190,7 +190,8 @@ namespace BansheeEngine
 		yylex_destroy(scanner);
 		yylex_destroy(scanner);
 	}
 	}
 
 
-	void BSLFXCompiler::getTechniqueIdentifier(ASTFXNode* technique, StringID& renderer, String& language)
+	void BSLFXCompiler::getTechniqueIdentifier(ASTFXNode* technique, StringID& renderer, String& language, 
+		Vector<StringID>& tags)
 	{
 	{
 		renderer = RendererAny;
 		renderer = RendererAny;
 		language = "Any";
 		language = "Any";
@@ -207,6 +208,18 @@ namespace BansheeEngine
 			case OT_Language:
 			case OT_Language:
 				language = removeQuotes(option->value.strValue);
 				language = removeQuotes(option->value.strValue);
 				break;
 				break;
+			case OT_Tags:
+			{
+				ASTFXNode* tagsNode = option->value.nodePtr;
+				for (int j = 0; j < tagsNode->options->count; j++)
+				{
+					NodeOption* tagOption = &tagsNode->options->entries[j];
+
+					if (tagOption->type == OT_TagValue)
+						tags.push_back(removeQuotes(tagOption->value.strValue));
+				}
+			}
+			break;
 			default:
 			default:
 				break;
 				break;
 			}
 			}
@@ -217,14 +230,43 @@ namespace BansheeEngine
 	{
 	{
 		StringID intoRenderer = RendererAny;
 		StringID intoRenderer = RendererAny;
 		String intoLanguage = "Any";
 		String intoLanguage = "Any";
+		Vector<StringID> intoTags;
 
 
 		StringID fromRenderer = RendererAny;
 		StringID fromRenderer = RendererAny;
 		String fromLanguage = "Any";
 		String fromLanguage = "Any";
+		Vector<StringID> fromTags;
+
+		getTechniqueIdentifier(into, intoRenderer, intoLanguage, intoTags);
+		getTechniqueIdentifier(from, fromRenderer, fromLanguage, fromTags);
+
+		bool matches = (intoRenderer == fromRenderer || fromRenderer == RendererAny) && (intoLanguage == fromLanguage || fromLanguage == "Any");
+		if(matches)
+		{
+			for (auto& intoTag : intoTags)
+			{
+				auto iterFind = std::find(fromTags.begin(), fromTags.end(), intoTag);
+				if(iterFind == fromTags.end())
+				{
+					matches = false;
+					break;
+				}
+			}
+		}
 
 
-		getTechniqueIdentifier(into, intoRenderer, intoLanguage);
-		getTechniqueIdentifier(from, fromRenderer, fromLanguage);
+		if (matches)
+		{
+			for (auto& fromTag : fromTags)
+			{
+				auto iterFind = std::find(intoTags.begin(), intoTags.end(), fromTag);
+				if (iterFind == intoTags.end())
+				{
+					matches = false;
+					break;
+				}
+			}
+		}
 
 
-		return (intoRenderer == fromRenderer || fromRenderer == RendererAny) && (intoLanguage == fromLanguage || fromLanguage == "Any");
+		return matches;
 	}
 	}
 
 
 	StringID BSLFXCompiler::parseRenderer(const String& name)
 	StringID BSLFXCompiler::parseRenderer(const String& name)
@@ -1051,6 +1093,18 @@ namespace BansheeEngine
 			case OT_Language:
 			case OT_Language:
 				parseLanguage(removeQuotes(option->value.strValue), techniqueData.renderAPI, techniqueData.language);
 				parseLanguage(removeQuotes(option->value.strValue), techniqueData.renderAPI, techniqueData.language);
 				break;
 				break;
+			case OT_Tags:
+			{
+				ASTFXNode* tagsNode = option->value.nodePtr;
+				for (int j = 0; j < tagsNode->options->count; j++)
+				{
+					NodeOption* tagOption = &tagsNode->options->entries[j];
+
+					if(tagOption->type == OT_TagValue)
+						techniqueData.tags.push_back(removeQuotes(tagOption->value.strValue));
+				}
+			}
+			break;
 			case OT_Code:
 			case OT_Code:
 				parseCodeBlock(option->value.nodePtr, codeBlocks, techniqueData.commonPassData);
 				parseCodeBlock(option->value.nodePtr, codeBlocks, techniqueData.commonPassData);
 				break;
 				break;
@@ -1343,7 +1397,8 @@ namespace BansheeEngine
 
 
 			if (orderedPasses.size() > 0)
 			if (orderedPasses.size() > 0)
 			{
 			{
-				SPtr<Technique> technique = Technique::create(techniqueData.renderAPI, techniqueData.renderer, orderedPasses);
+				SPtr<Technique> technique = Technique::create(techniqueData.renderAPI, techniqueData.renderer, 
+					techniqueData.tags, orderedPasses);
 				techniques.push_back(technique);
 				techniques.push_back(technique);
 			}
 			}
 		}
 		}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů