Browse Source

More work on documentation

BearishSun 8 years ago
parent
commit
cc0766231d

+ 354 - 0
Documentation/Manuals/Native/customRenderer.md

@@ -0,0 +1,354 @@
+Creating a renderer plugin							{#customRenderer}
+===============
+[TOC]
+
+If your project requires a very specific form of rendering you might decide you want to write your own renderer from scratch. In Banshee renderers are built as plugins, and this manual will show you how to create one. This manual can also be useful if trying to understand how the renderer works, even if you are not implementing your own.
+
+# Components and the renderer {#renderer_a}
+We've already shown how to render scene objects. You create a **SceneObject** on which you then attach components such as **CCamera**, **CRenderable** or **CLight**. These components will then register themselves with the renderer, when takes care of everything else rendering-wise.
+
+Renderer isn't actually aware of scene objects and components, and instead operates on lower level objects owned by those components. For example **CCamera** component internally owns a @ref bs::Camera "Camera" object, and **CRenderable** component internally owns a @ref bs::Renderable "Renderable" object. As a general rule the non-component versions are named the same, without the "C" prefix. Their interface is very similar to their component versions.
+
+All such lower level objects used by the renderer are also **CoreObject**%s, meaning they have both a simulation and a core thread counterparts. 
+ 
+# Renderer plugin interface {#renderer_b}
+To create your own renderer you must implement the @ref bs::ct::Renderer "ct::Renderer" interface. Renderer executes on the core thread, although there are a few simulation thread methods we'll note specifically.
+
+## Scene state notifications {#renderer_b_a}
+Majority of the renderer interface consists of methods that notify the renderer when certain objects are added, updated or removed from the scene. The types of objects that the renderer cares about are:
+ - @ref bs::Camera "Camera"
+ - @ref bs::Renderable "Renderable"
+ - @ref bs::Light "Light"
+ - @ref bs::ReflectionProbe "ReflectionProbe"
+ - @ref bs::Skybox "Skybox"
+ 
+Whenever such objects are created, destroyed or some property on them is updated, one of the following methods is called:
+ - @ref bs::ct::Renderer::notifyCameraAdded "ct::Renderer::notifyCameraAdded()" - Called when a new **Camera** is created (e.g. when a **CCamera** component is added to the scene).
+ - @ref bs::ct::Renderer::notifyCameraUpdated "ct::Renderer::notifyCameraUpdated()" - Called when **Camera** position, rotation or scale changes.
+ - @ref bs::ct::Renderer::notifyCameraRemoved "ct::Renderer::notifyCameraRemoved()" - Called when a **Camera** is destroyed.
+ - @ref bs::ct::Renderer::notifyRenderableAdded "ct::Renderer::notifyRenderableAdded()" - Called when a new **Renderable** is created (e.g. when a **CRenderable** component is added to the scene).
+ - @ref bs::ct::Renderer::notifyRenderableUpdated "ct::Renderer::notifyRenderableUpdated()" - Called when **Renderable** position, rotation or scale changes.
+ - @ref bs::ct::Renderer::notifyRenderableRemoved "ct::Renderer::notifyRenderableRemoved()" - Called when a **Renderable** is destroyed.
+ - @ref bs::ct::Renderer::notifyLightAdded "ct::Renderer::notifyLightAdded()" - Called when a new **Light** is created (e.g. when a **CLight** component is added to the scene).
+ - @ref bs::ct::Renderer::notifyLightUpdated "ct::Renderer::notifyLightUpdated()" - Called when **Light** position, rotation or scale changes.
+ - @ref bs::ct::Renderer::notifyLightRemoved "ct::Renderer::notifyLightRemoved()" - Called when a **Light** is destroyed.
+ - @ref bs::ct::Renderer::notifyReflectionProbeAdded "ct::Renderer::notifyReflectionProbeAdded()" - Called when a new **ReflectionProbe** is created (e.g. when a **CReflectionProbe** component is added to the scene).
+ - @ref bs::ct::Renderer::notifyReflectionProbeUpdated "ct::Renderer::notifyReflectionProbeUpdated()" - Called when **ReflectionProbe** position, rotation or scale changes.
+ - @ref bs::ct::Renderer::notifyReflectionProbeRemoved "ct::Renderer::notifyReflectionProbeRemoved()" - Called when a **ReflectionProbe** is destroyed.
+ - @ref bs::ct::Renderer::notifySkyboxAdded "ct::Renderer::notifySkyboxAdded()" - Called when a new **Skybox** is created (e.g. when a **CSkybox** component is added to the scene).
+ - @ref bs::ct::Renderer::notifySkyboxTextureChanged "ct::Renderer::notifySkyboxTextureChanged()" - Called when the texture applied to **Skybox** changes.
+ - @ref bs::ct::Renderer::notifySkyboxRemoved "ct::Renderer::notifySkyboxRemoved()" - Called when a **Skybox** is destroyed. 
+ 
+Your renderer implementation can choose to implement some or all of those methods. By implementing these methods your renderer implementation is expected to keep track of the scene state, and then use that scene state for rendering. For example most renderers will at least need to keep track of all active cameras and renderable objects.
+ 
+Note that *Added/*Removed methods don't only get called on object creation/destruction. If some major property of the object changes (e.g. a mesh or a material on a **Renderable**), the system will call **ct::Renderer::notifyRenderableRemoved()** followed by a call to **ct::Renderer::notifyRenderableAdded()**.
+ 
+## Rendering {#renderer_b_b}
+Aside from keeping track of the state of the scene your renderer must also implement @ref bs::ct::Renderer::renderAll "ct::Renderer::renderAll()". This method will be called every frame and it is the starting point for all rendering. Note that this method gets called from the simulation thread, and you are expected to manually launch rendering on the core thread.
+
+~~~~~~~~~~~~~{.cpp}
+class MyRenderer : public Renderer
+{
+	// ... other renderer methods
+	
+	void renderAll() 
+	{
+		// ... do any sim thread operations if required ...
+		
+		// Queue rendering
+		gCoreThread().queueCommand(std::bind(&MyRenderer::renderAllCore, this));
+	}
+	
+	void renderAllCore()
+	{
+		// ... iterate over all cameras and renderables, call RenderAPI and other low-level rendering methods to actually render something ...
+	}
+};
+~~~~~~~~~~~~~
+
+The implementation of your rendering method should iterate over all renderable objects, cameras, lights or other provided objects (depending on what kind of rendering you wish to do). The rendering happens through the low-level rendering API as described in earlier manuals. At the end of rendering, every render target in every active camera should be filled with an image of the rendered scene. During rendering you should consider mesh and material set on renderable objects, and optionally apply lighting, special or post-processing effects as needed. 
+
+## Name {#renderer_b_c}
+You are required to give your renderer a name by overriding @ref bs::ct::Renderer::getName "ct::Renderer::getName()". 
+
+~~~~~~~~~~~~~{.cpp}
+class MyRenderer : public Renderer
+{
+	const StringID& MyRenderer::getName() const
+	{
+		static StringID name = "MyRenderer";
+		return name;
+	}
+
+	// ... other renderer methods
+};
+~~~~~~~~~~~~~
+
+At this point your renderer is ready for use, but there is still various optional functionality to cover.
+
+## Extensions {#renderer_b_d}
+We talked about how to implement renderer extensions in the previous chapter. But if you are implementing your own renderer you need to process those extensions during the rendering process. You may also choose to ignore extensions and not render them at all.
+
+All registered extensions are part of the **Renderer::mCallbacks** field. You can choose to iterate over them and execute them as needed.
+
+~~~~~~~~~~~~~{.cpp}
+class MyRenderer : public Renderer
+{
+	// ... other renderer methods
+
+	// Performs rendering for a single camera, on the core thread
+	void render(const SPtr<Camera>& camera)
+	{
+		// Render pre-base pass extensions
+		auto iter = mCallbacks.begin();
+		while (iter != mCallbacks.end())
+		{
+			RendererExtension* extension = *iter;
+			if (extension->getLocation() != RenderLocation::PreBasePass)
+				break;
+
+			if (extension->check(*camera))
+				extension->render(*camera);
+
+			++iter;
+		}
+		
+		// ... do normal rendering and optionally call extensions registered for other locations ...
+	}
+};
+~~~~~~~~~~~~~
+
+# Utilities {#renderer_c}
+While what we have shown so far is enough to create a custom renderer, there are also a variety of utilities that can help out in the process. These systems aren't critical for renderer creation, but instead provide an easier way to perform commonly required functions.
+
+## RendererUtility {#renderer_c_a}
+@ref bs::ct::RendererUtility "ct::RendererUtility" provides some commonly required functionality for rendering. For the most part it provides methods that are wrappers around various **RenderAPI** methods described previously. It can be accessed globally through @ref bs::ct::gRendererUtility() "ct::gRendererUtility()" and the relevant methods are:
+ - @ref bs::ct::RendererUtility::setPass "ct::RendererUtility::setPass()" - Binds a pass from a specific **Material** for rendering. Any further draw calls will be rendered using this pass.
+ - @ref bs::ct::RendererUtility::setPassParams "ct::RendererUtility::setPassParams()" - Binds parameters (textures, samplers, etc.) from a **Material**, in the form of **GpuParamsSet**. Any further draw calls will be rendered using these parameters.
+ - @ref bs::ct::RendererUtility::draw "ct::RendererUtility::draw()" - Draws a specific sub-mesh of the provided **ct::Mesh**, using the currently bound pass.
+ - @ref bs::ct::RendererUtility::blit "ct::RendererUtility::blit()" - Copies the contents of the provided texture into the currently bound render target.
+ - @ref bs::ct::RendererUtility::drawScreenQuad "ct::RendererUtility::drawScreenQuad()" - Draws a quad covering the screen using the currently bound pass.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<Material> material = ...;
+SPtr<Mesh> mesh = ...;
+SPtr<GpuParamsSet> paramsSet = material->createParamsSet();
+
+gRendererUtility().setPass(material);
+... set material parameters as normal ...
+gRendererUtility().setPassParams(paramsSet);
+gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+~~~~~~~~~~~~~
+
+## Render queue {#renderer_c_b}
+@ref bs::ct::RenderQueue "ct::RenderQueue" allows you to sort and group scene objects for rendering. For example transparent objects might need to be sorted back to front based on their distance from the camera. It is also often useful to group objects if they share the same material, to reduce state switching which can improve performance.
+
+Use @ref bs::ct::RenderQueue::add "ct::RenderQueue::add()" to add new objects to the queue. It expects a @ref bs::ct::RenderableElement "ct::RenderableElement" which you can create from information provided by **Renderable** when **ct::Renderer::notifyRenderableAdded()** is called. Normally you wish to have a single **ct::RenderableElement** for each sub-mesh present in the renderable object's mesh.
+
+Once all elements are in the queue, you can call @ref bs::ct::RenderQueue::setStateReduction "ct::RenderQueue::setStateReduction()" to select how to sort the objects:
+ - @ref bs::ct::StateReduction::None "ct::StateReduction::None" - Elements will be sorted by distance but no state reduction by material will occurr.
+ - @ref bs::ct::StateReduction::Material "ct::StateReduction::Material" - Elements will be sorted by material first, then by distance.
+ - @ref bs::ct::StateReduction::Distance "ct::StateReduction::Distance" - Elements will be sorted by distance first, then by material.
+ 
+Once the state reduction mode is set call @ref bs::ct::RenderQueue::sort "ct::RenderQueue::sort()", and then @ref bs::ct::RenderQueue::getSortedElements "ct::RenderQueue::getSortedElements()" to retrieve a sorted list of render elements. The returned list contains a list of @ref bs::ct::RenderQueueElement "ct::RenderQueueElement" which lets you know exactly which render element to render using which pass, and also tells you when a new pass needs to be applied.
+
+For example:
+~~~~~~~~~~~~~{.cpp}
+Vector<RenderableElement*> elements = ...; // Fill this up from a list of renderables
+
+SPtr<RenderQueue> queue = bs_shared_ptr_new<RenderQueue>(StateReduction::Distance);
+for(auto& element : elements)
+{
+	float distance = ...; // Calculate distance from element to camera, for sorting
+	queue->add(element, distance);
+}
+
+queue->sort();
+const Vector<RenderQueueElement>& sortedElements = queue->getSortedElements();
+... render sorted elements using the low level rendering API ...
+~~~~~~~~~~~~~
+
+## Renderer material {#renderer_c_c}
+Often the renderer needs to use special shaders for various effects (e.g. resolving lighting for a deferred renderer or post-processing effects like FXAA). Unlike shaders and materials used by renderable objects, these shaders are built into the engine. Since we know they'll always be there we can make it easier for the renderer to load and use them by implementing the @ref bs::ct::RendererMaterial "ct::RendererMaterial<T>" interface. 
+
+The template parameter must be name of your material implementation class. The class must contain a @ref RMAT_DEF macro which contains the filename of the shader the renderer material uses. The shader file should be present in the "Data/Raw/Engine/Shaders/" folder. 
+
+~~~~~~~~~~~~~{.cpp}
+// Set up a post-processing material that downsamples some texture
+class DownsampleMat : public RendererMaterial<DownsampleMat>
+{
+	// Required macro pointing to the shader file
+	RMAT_DEF("Downsample.bsl");
+};
+~~~~~~~~~~~~~
+
+After that you can simply instantiate your renderer material, and access the underlying material by calling @ref bs::ct::RendererMaterial::getMaterial() "ct::RendererMaterial::getMaterial()", and the material parameters by calling @ref bs::ct::RendererMaterial::getParamsSet() "ct::RendererMaterial::getParamsSet()". Then you can bind the material for rendering as normal (using **RendererUtility** or directly through **RenderAPI**).
+
+You will normally also want to add a constructor in which you look up any necessary parameters the material might require, so they can be set more easily when rendering.
+~~~~~~~~~~~~~{.cpp}
+class DownsampleMat : public RendererMaterial<DownsampleMat>
+{
+	RMAT_DEF("Downsample.bsl");
+
+public:
+	DownsampleMat()
+	{
+		// Retrieve material parameters, and optionally perform other set-up
+		mInputTexture = mMaterial->getParamTexture("gInputTex");
+		mInvTexSize = mMaterial->getParamVec2("gInvTexSize");
+	}
+
+	MaterialParamVec2 mInvTexSize;
+	MaterialParamTexture mInputTexture;
+};
+~~~~~~~~~~~~~
+
+Often you can also create a method that binds the parameters, binds the material and executes the material all in one. This way external code doesn't need to do anything but to call it.
+
+~~~~~~~~~~~~~{.cpp}
+class DownsampleMat : public RendererMaterial<DownsampleMat>
+{
+	// ... other DownsampleMat code ...
+	
+	// Set up parameters and render a full screen quad using the material
+	void execute(const SPtr<Texture>& input)
+	{
+		// Actually assign parameters before rendering
+		mInputTexture.set(input);
+		
+		const TextureProperties& props = input->getProperties();
+		Vector2 invTextureSize(1.0f / props.getWidth(), 1.0f / props.getHeight());
+
+		mInvTexSize.set(invTextureSize);
+		
+		mMaterial->updateParamsSet(mParamsSet);
+		
+		// Bind material, parameters and draw
+		gRendererUtility().setPass(mMaterial);
+		gRendererUtility().setPassParams(mParamsSet);
+		gRendererUtility().drawScreenQuad();
+	}
+
+	// ... other DownsampleMat code ...
+};
+~~~~~~~~~~~~~
+
+Renderer materials also support variations for cases where you might require slightly different versions of a shader for different use cases. The variations are handled by setting up preprocessor \#defines, which the shader code can then use to conditionally add or remove parts of code (via \#ifdef or similar). To determine which defines are set implement the _initDefines() method in your **RendererMaterial** implementation, and append your defines to the @ref bs::ShaderDefines "ShaderDefines" object. Note that this method must be present, even if not using any defines.
+
+~~~~~~~~~~~~~{.cpp}
+// Method defined in RMAT_DEF macro
+void DownsampleMat::_initDefines(ShaderDefines& defines)
+{
+	// Set up optional defines to control shader compilation
+	defines.set("BILINEAR_FILTERING", 1);
+}
+~~~~~~~~~~~~~
+
+> All builtin shaders are cached. The system will automatically pick up any changes to shaders in *Data/Raw/Engine* folder and rebuild the cache when needed. However if you are changing defines as above you must manually force the system to rebuild by deleting the *Timestamp.asset* file in *Data/Engine* folder.
+
+## Parameter blocks {#renderer_c_d}
+In the @ref gpuPrograms manual we talked about parameter block buffers, represented by **GpuParamBlockBuffer** class. These blocks are used for group data parameters (such as float, int or bool) into blocks that can then be efficiently bound to the pipeline. They are better known as uniform buffers in OpenGL/Vulkan, or constant buffers in DX11. 
+
+An example of such a buffer in HLSL looks like this:
+~~~~~~~~~~~~~{.cpp}
+// Contains various parameters specific to the current camera
+cbuffer PerCamera
+{
+	float3	 gViewDir;
+	float3 	 gViewOrigin;
+	float4x4 gMatViewProj;
+	float4x4 gMatView;
+	float4x4 gMatProj;
+	float4x4 gMatInvProj;
+	float4x4 gMatInvViewProj;			
+}
+~~~~~~~~~~~~~
+
+Such parameter block buffers are primarily useful when you need to share the same data between multiple materials. Instead of accessing parametes individually through **Material** or **GpuParams**, you would instead create a **GpuParamBlockBuffer** object, populate it, and then bind to **Material** or **GpuParams**.
+
+When we talked about them earlier we have shown how to manually create a **GpuParamBlockBuffer** object and write to it by reading the **GpuParamDesc** object of the **GpuProgram**. This is cumbersome and requires a lot of boilerplate code. A simpler way of creating and populating a parameter block is to use @ref BS_PARAM_BLOCK_BEGIN, @ref BS_PARAM_BLOCK_ENTRY and @ref BS_PARAM_BLOCK_END macros. You simply define the parameter block structure using these macros in C++, to match the structure in HLSL/GLSL code.
+
+~~~~~~~~~~~~~{.cpp}
+BS_PARAM_BLOCK_BEGIN(PerCameraParamBlockDef)
+	BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
+	BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
+	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
+	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
+	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
+	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
+	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
+BS_PARAM_BLOCK_END
+~~~~~~~~~~~~~
+
+Once your parameter block definition is created, you can instantiate a parameter block buffer, assign values to it, and assign the blocks to materials, like so:
+~~~~~~~~~~~~~{.cpp}
+PerCameraParamBlockDef def; // Normally you want to make this global so it's instantiated only once
+
+// Instantiates a new parameter block from the definition
+SPtr<GpuParamBlockBuffer> paramBlock = def.createBuffer(); 
+
+// Assign a value to the gViewDir parameter of the parameter block
+def.gViewDir.set(paramBlock, Vector3(0.707.0, 0.707f, 0.0f));
+... set other parameters in block ...
+
+// Assign the parameter block to the material (optionally, assign to GpuParams if using them directly)
+SPtr<Material> material = ...;
+material->setParamBlockBuffer("PerCamera", paramBlock);
+
+... render using the material ...
+~~~~~~~~~~~~~
+
+Blocks are often used with renderer materials we described in the previous section, although we didn't use one in that example.
+
+Note that by using this approach you lose all the error checking normally performed by **Material** or **GpuParams** when you are assigning parameters individually. You must make sure that the layout in C++ matches the layout in the GPU program. In case of GLSL you must also specify `layout(std140)` keyword to ensure its layout is compatible with C++ struct layout. You must also make sure that variable names match the names in the GPU program code.
+
+## Renderer semantics {#renderer_c_e}
+Renderer semantics allow user created shaders to request that certain parameters in a GPU program are populated by the renderer. They are specified in the shader code as we described in the BSL manual.
+
+For example the user might request a "VP" semantic, which could be recognized by the renderer that the shader requests a view-projection matrix. Such a matrix is not something that the user should have to assign to the material himself. The renderer can choose to parse material parameters looking for supported semantics, and assign their values. Ultimately whether the renderer chooses to parse the semantics or not is up to the renderer. 
+
+The semantics for each parameter can be accessed through the **Shader** object, which renderer needs to iterate through manually.
+
+~~~~~~~~~~~~~{.cpp}
+StringID RPS_ViewProjTfrm = "VP"; // Define semantic identifier
+
+SPtr<Material> material = ...;
+SPtr<Shader> shader = material->getShader();
+auto& dataParams = shader->getDataParams();
+for (auto& entry : texParams)
+{
+	if (entry.second.rendererSemantic == RPS_ViewProjTfrm)
+	{
+		// Found it, assign some value to the parameter
+		mMaterial->setMat4(entry.second.name, Matrix4::IDENTITY);
+		break;
+	}
+}
+~~~~~~~~~~~~~
+
+## GpuResourcePool {#renderer_c_f}
+Although you can create textures and buffers manually as described in the low level rendering API manual, @ref bs::ct::GpuResourcePool "ct::GpuResourcePool" provides a simpler and more efficient way of doing it. It will keep alive any referenced textures and buffers, so that other systems may re-use them if their size/formats match. This can improve performance when using many temporary/intermediary render textures (like in post-processing) or load-store buffers.
+
+To request a render texture, first populate the @ref bs::ct::POOLED_RENDER_TEXTURE_DESC "ct::POOLED_RENDER_TEXTURE_DESC" descriptor, by calling any of @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create2D "ct::POOLED_RENDER_TEXTURE_DESC::create2D()", @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create3D "ct::POOLED_RENDER_TEXTURE_DESC::create3D()" or @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::createCube "ct::POOLED_RENDER_TEXTURE_DESC::createCube()".
+
+To request a buffer, populate the @ref bs::ct::POOLED_STORAGE_BUFFER_DESC "ct::POOLED_STORAGE_BUFFER_DESC" descriptor by calling either @ref bs::ct::POOLED_STORAGE_BUFFER_DESC::createStandard "ct::POOLED_STORAGE_BUFFER_DESC::createStandard()" or @ref bs::ct::POOLED_STORAGE_BUFFER_DESC::createStructured "ct::POOLED_STORAGE_BUFFER_DESC::createStructured()".
+
+Then call @ref bs::ct::GpuResourcePool::get "ct::GpuResourcePool::get()" with the provided descriptor. This will either create a new render texture/buffer, or return one from the pool. The returned object is @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture" for textures and @ref bs::ct::PooledStorageBuffer  "ct::PooledStorageBuffer" for buffers.
+
+Once you are done using the texture or buffer, call @ref bs::ct::GpuResourcePool::release "ct::GpuResourcePool::release()" to return the object to the pool, and make it available for other systems. If you plan on using this object again, make sure to keep a reference to the **ct::PooledRenderTexture** / **ct::PooledStorageBuffer** object. This will prevent the pool from fully destroying the object so it may be reused.
+
+~~~~~~~~~~~~~{.cpp}
+// An example creating a pooled render texture
+POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8G8B8A8, 1024, 1024, TU_RENDERTARGET);
+SPtr<PooledRenderTexture> pooledRT = GpuResourcePool::instance().get(desc);
+
+RenderAPI::instance().setRenderTarget(pooledRT->renderTexture);
+... render to target ...
+GpuResourcePool::instance().release(pooledRT);
+// Keep a reference to pooledRT if we plan on re-using it, then next time just call get() using the same descriptor
+~~~~~~~~~~~~~
+
+## Renderer options {#renderer_c_g}
+You can customize your rendering at runtime by implementing the @ref bs::ct::RendererOptions "ct::RendererOptions" class. Your **ct::RendererOptions** implementation can then be assigned to the renderer by calling @ref bs::ct::Renderer::setOptions "ct::Renderer::setOptions()", and accessed within the renderer via the **Renderer::mOptions** field. No default options are provided and it's up to your renderer to decide what it requires.
+
+Be aware that options are set from the simulation thread, and if you want to use them on the core thread you need to either properly synchronize the access, or send a copy of the options to the core thread.

+ 3 - 2
Documentation/Manuals/Native/manuals.md

@@ -94,18 +94,19 @@ A set of manuals covering advanced functionality intented for those wanting to e
  - [Flags](@ref flags)
  - [Flags](@ref flags)
  - [Any](@ref any) 
  - [Any](@ref any) 
  - [Unit tests](@ref unitTests)
  - [Unit tests](@ref unitTests)
+- [Advanced material](@ref advMaterial)
 - [Threading](@ref threading)
 - [Threading](@ref threading)
 - [Plugins](@ref plugins)
 - [Plugins](@ref plugins)
 - **Renderer**
 - **Renderer**
  - [Renderer extensions](@ref rendererExtensions)
  - [Renderer extensions](@ref rendererExtensions)
- - [Creating a renderer manually](@ref customRenderer)
+ - [Creating a renderer plugin](@ref customRenderer)
+ 
  
  
 ## General guides
 ## General guides
 Name                                      | Description
 Name                                      | Description
 ------------------------------------------|-------------
 ------------------------------------------|-------------
 [Resources](@ref resources)  			  | Explains how resources work, including saving, loading and creating brand new resource types.
 [Resources](@ref resources)  			  | Explains how resources work, including saving, loading and creating brand new resource types.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
 [Scripting](@ref scripting)               | Shows you how to interact with the scripting system, and how to expose C++ objects to the scripting API.
-[Renderer](@ref renderer)    	  		  | Explains how the renderer works on the low level, and how to create a custom renderer so you may fully customize the look of your application.
 [BSLFX](@ref bsl)    	  		  		  | Provides a reference for the Banshee Shading Language syntax.
 [BSLFX](@ref bsl)    	  		  		  | Provides a reference for the Banshee Shading Language syntax.
 [Custom GUI elements](@ref customGUI)     | Shows you how to create custom GUI elements, manually render text or modify GUI system in a general way.
 [Custom GUI elements](@ref customGUI)     | Shows you how to create custom GUI elements, manually render text or modify GUI system in a general way.
 [Custom importers](@ref customImporters)  | Shows you how to create importers that handle conversion of third party resources into engine ready formats.
 [Custom importers](@ref customImporters)  | Shows you how to create importers that handle conversion of third party resources into engine ready formats.

+ 4 - 0
Documentation/Manuals/Native/materials.md

@@ -2,6 +2,10 @@ Materials									{#materials}
 ===============
 ===============
 [TOC]
 [TOC]
 
 
+TODO:
+ - GpuParamsSet
+ - MaterialParam%s
+
 A material controls how is an object rendered. In Banshee it is represented with @ref bs::Material "Material" and @ref bs::ct::Material "ct::Material" classes. Both of these provide almost equivalent functionality, but the former is for use on the simulation thread, and the latter is for use on the core thread. If you are confused by the dual nature of the objects, read the [core thread](@ref coreThread) manual. 
 A material controls how is an object rendered. In Banshee it is represented with @ref bs::Material "Material" and @ref bs::ct::Material "ct::Material" classes. Both of these provide almost equivalent functionality, but the former is for use on the simulation thread, and the latter is for use on the core thread. If you are confused by the dual nature of the objects, read the [core thread](@ref coreThread) manual. 
 
 
 We'll focus on the simulation thread @ref bs::Material "Material" throughout this manual, but aside from the `ct` namespace there are no major differences between the two interfaces.
 We'll focus on the simulation thread @ref bs::Material "Material" throughout this manual, but aside from the `ct` namespace there are no major differences between the two interfaces.

+ 0 - 327
Documentation/Manuals/Native/renderer.md

@@ -1,327 +0,0 @@
-Renderer								{#renderer}
-===============
-[TOC]
-
-Renderer is a system that processes all renderable objects in the scene, renders them, applies lighting and shadows, renders overlay like GUI and applies post processing effects. It is the system that determines how your game looks (together with custom materials you might specify). In Banshee the renderer is implemented as a plugin, so you may create your own and fully customize the look of your game. Banshee also comes with a default renderer called "RenderBeast".
-
-In this manual we'll explain how to use a renderer to render objects in the scene, as well as how to implement your own renderer.
-
-# Rendering scene objects {#renderer_a}
-To render objects in the scene create a @ref bs::SceneObject "SceneObject" onto which you then attach relevant @ref bs::Component "Components". These @ref bs::Component "Components" then register themselves with the renderer, which takes care of everything else. See the [game object](@ref gameObjects) manual for more information about scene objects and components.
-
-There are three primary types of components used for rendering:
- - @ref bs::CCamera "CCamera" - A camera used for viewing the scene.
- - @ref bs::CRenderable "CRenderable" - An object to render.
- - @ref bs::CLight "CLight" - A light to illuminate the objects with.
- 
-## Camera {#renderer_a_a}
-@ref bs::CCamera "Camera" component determines which portion of the scene is being rendered, onto which surface, and how. Before you create a camera you must first create a @ref bs::RenderTarget "RenderTarget" onto which the camera will output the rendered image. See the [render targets](@ref renderTargets) manual for information on how to create render targets.
-
-See the following example to create a camera:
-~~~~~~~~~~~~~{.cpp}
-SPtr<RenderTarget> rt = ...;
-
-HSceneObject cameraSO = SceneObject::create("Camera");
-HCamera camera = cameraSO->addComponent<CCamera>(rt);
-~~~~~~~~~~~~~
-
-The transform of the camera's parent scene object determines which portion of the scene does the camera see. You can position and rotate the camera using the standard @ref bs::SceneObject "SceneObject" transform methods:
-~~~~~~~~~~~~~{.cpp}
-cameraSO->setPosition(Vector3(0, 0, 50)); // Move camera to (0, 0, 50)
-cameraSO->lookAt(Vector3(0, 0, 0)); // Look towards origin
-~~~~~~~~~~~~~
-
-You may also adjust various other properties of the camera, including @ref bs::ProjectionType "projection type", field of view, aspect ratio and similar using methods like @ref bs::CCamera::setProjectionType "CCamera::setProjectionType", @ref bs::CCamera::setHorzFOV "CCamera::setHorzFOV" and @ref bs::CCamera::setAspectRatio "CCamera::setAspectRatio". See the @ref bs::CCamera "Camera" API documentation for a full list of methods.
-
-Each camera be assigned a priority via @ref bs::CCamera::setPriority "CCamera::setPriority". The priority determines in which order are multiple cameras rendered. Higher priority means the camera will be rendered sooner. Be aware that render targets also have priority, and their priority takes precedance over camera's priority. Camera priority only matters if multiple cameras are rendering to the same render target.
-
-Camera can also be assigned a layer via @ref bs::CCamera::setLayers "CCamera::setLayers". The layer is a bitmask that can be used for filtering which objects does the camera render. As we'll see later, each renderable object can also be assigned a layer. Any object whose layer ORed with the camera's layer bitmask is non-zero will be rendered to the camera.
-
-A variety of methods for converting between world, view, projection, clip and NDC spaces are also provided by the camera. For example see @ref bs::CCamera::screenPointToRay "CCamera::screenPointToRay".
-
-You may also retrieve the camera's projection and view matrices by calling @ref bs::CCamera::getProjectionMatrix "CCamera::getProjectionMatrix" and @ref bs::CCamera::getViewMatrix "CCamera::getViewMatrix" respectively.
-
-## Renderable {#renderer_a_b}
-Once the camera in the scene is set up, you can start adding object you wish to render. All such objects are represented with the @ref bs::CRenderable "CRenderable" component. This is a fairly simple components that expects only a @ref bs::Mesh "Mesh" and one or multiple @ref bs::Material "Material(s)". Read the [mesh](@ref meshes) and [material](@ref materials) manual for more information how to create them.
-
-See the following example to create a renderable object:
-~~~~~~~~~~~~~{.cpp}
-HMesh mesh = ...; // Create or import a mesh
-HMaterial material = ...; // Create or import a material
-
-HSceneObject renderableSO = SceneObject::create("Renderable");
-HRenderable renderable = renderableSO->addComponent<CRenderable>();
-renderable->setMesh(mesh);
-renderable->setMaterial(material);
-~~~~~~~~~~~~~
-
-You can also optionally set multiple materials in case your mesh has multiple sub-meshes. In such case each material will be used for rendering one sub-mesh.
-
-And as we have mentioned in the previous section, each renderable can also be assigned a layer by calling @ref bs::CRenderable::setLayer "CRenderable::setLayer", which in combination with camera's layer can be used for filtering on which camera(s) should the object be visible.
-
-## Light {#renderer_a_c}
-Finally we can choose to add a light to the scene. A light will influence the lighting and shadows of renderable objects in its radius. Use the @ref bs::CLight "CLight" component to set up a light. Light comes in three variants:
- - Point light that illuminates everything in a certain radius.
- - Spot light that illuminates everything within a certain angle and radius.
- - Directional light that illuminates everything at an infinite distance from a particular direction.
- 
-You can choose between light variants by calling @ref bs::CLight::setType "CLight::setType". You can also set parameters like light color, intensity, range and others. See the @ref bs::CLight "CLight" API documentation for a full list.
-
-An example creating a point light:
-~~~~~~~~~~~~~{.cpp}
-HSceneObject lightSO = SceneObject::create("Light");
-HLight light = lightSO->addComponent<CLight>();
-light->setType(LightType::Point);
-light->setRadius(100.0f);
-light->setIntensity(1000.0f);
-~~~~~~~~~~~~~
-
-# Creating your own renderer {#renderer_b}
-Renderer is the system that makes use of all the components we listed so far. Renderer isn't actually aware of scene objects and components, and instead operates on @ref bs::Camera "Camera", @ref bs::Renderable "Renderable" and @ref bs::Light "Light" types directly. These are the internal objects that are managed by @ref bs::CCamera "CCamera", @ref bs::CRenderable "CRenderable" and @ref bs::CLight "CLight", respectively. They provide the same interface as their component versions. They are also @ref bs::CoreObject "core objects", meaning they have both a simulation and a core thread counterparts.
-
-To create your own renderer you must implement the @ref bs::ct::Renderer "ct::Renderer" interface. The implementation should iterate over all renderable objects, cameras and lights and perform rendering according to your own rules. At the end of rendering, every render target in every active camera should be filled with an image of the rendered scene. During rendering you must consider mesh and material provided by the renderable objects, and apply lighting according to light objects. You should use the low level @ref bs::RenderAPI "RenderAPI" to render individual objects.
-
-The renderer is mostly a core-thread system as then it has a more direct access to the @ref bs::RenderAPI "RenderAPI", as well as various utility functionality we'll describe later. Read the [core thread](@ref coreThread) manual for more information about the core thread and core objects, and the [render API](@ref renderAPI) manual on how to use the low level rendering functionality.
-
-The @ref bs::ct::Renderer "ct::Renderer" interface requires you to implement the following methods:
- - @ref bs::ct::Renderer::getName "ct::Renderer::getName" - Returns a unique name of the renderer. This can be used by shader techniques to identify which renderer is active and when they should run, as described in the [material](@ref materials) manual.
- - @ref bs::ct::Renderer::renderAll "ct::Renderer::renderAll" - This is a method called from the simulation thread that executes the rendering. It is called once per frame. In this method you should queue your actual rendering method for execution on the core thread.
- - @ref bs::ct::Renderer::notifyCameraAdded "ct::Renderer::notifyCameraAdded" - Called on the core thread whenever a new @ref bs::Camera "Camera" is created (i.e. when a @ref bs::CCamera "CCamera" component is added to the scene). Also called when camera's properties change (camera is removed, then re-added).
- - @ref bs::ct::Renderer::notifyCameraUpdated "ct::Renderer::notifyCameraUpdated" - Called on the core thread whenever a @ref bs::Camera "Camera's" position or rotation changes.
- - @ref bs::ct::Renderer::notifyCameraRemoved "ct::Renderer::notifyCameraRemoved" - Called on the core thread whenever a @ref bs::Camera "Camera" is destroyed. Also called when camera's properties change (camera is removed, then re-added).
- - @ref bs::ct::Renderer::notifyRenderableAdded "ct::Renderer::notifyRenderableAdded" - Called on the core thread whenever a new @ref bs::Renderable "Renderable" is created (e.g. when a @ref bs::CRenderable "CRenderable" component is added to the scene).
- - @ref bs::ct::Renderer::notifyRenderableUpdated "ct::Renderer::notifyRenderableUpdated" - Called whenever @ref bs::Renderable "Renderable" properties change, e.g. when a scene object a renderable is attached to moves.
- - @ref bs::ct::Renderer::notifyRenderableRemoved "ct::Renderer::notifyRenderableRemoved" - Called whenever a @ref bs::Renderable "Renderable" is destroyed.
- - @ref bs::ct::Renderer::notifyLightAdded "ct::Renderer::notifyLightAdded" - Called whenever a new @ref bs::Light "Light" is created (e.g. when a @ref bs::CLight "CLight" component is added to the scene).
- - @ref bs::ct::Renderer::notifyLightUpdated "ct::Renderer::notifyLightUpdated" - Called whenever @ref bs::Light "Light" properties change, e.g. when a scene object a light is attached to moves.
- - @ref bs::ct::Renderer::notifyLightRemoved "ct::Renderer::notifyLightRemoved" - Called whenever @ref bs::Light "Light" is destroyed.
- 
-Implementing these methods should give you all the information you need to render your scene. You will have the required render target and projection/view matrices from the @ref bs::Camera "Camera", mesh/material/world transform from @ref bs::Renderable "Renderable" objects, and lighting information from @ref bs::Light "Light". Use the information provided in the [render API](@ref renderAPI) manual to learn how to render using those objects.
-
-Aside from rendering scene objects, the renderer should also take care of rendering everything else, like GUI, debug information and similar. This is handled in a general manner via callbacks. Every external system (like GUI) can register itself with the renderer by calling @ref bs::ct::CoreRenderer::registerRenderCallback "ct::Renderer::registerRenderCallback". This method accepts a few parameters:
- - Pointer to a @ref bs::Camera "Camera" for which the callback is valid. The renderer should call the callback when rendering onto that camera.
- - Index that indicated the priority. Callbacks with indices lower than zero should be executed before scene object rendering, and indices equal to or higher than zero should be executed after scene object rendering.
- - Callback to execute. Other systems will usually call @ref bs::RenderAPI "RenderAPI" methods in such callback to perform rendering manually.
- - Overlay toggle. Overlay elements are rendered after all other objects (and non-overlay callbacks). They don't require a depth buffer, nor a multi-sampled render target for rendering (e.g. like GUI), which makes them cheaper to render.
-
-Once a callback is registered, the renderer can access it via the `mRenderCallbacks` protected field.
- 
-While this is enough to create a custom renderer, a variety of useful utilities are provided to make rendering easier.
-
-## Utilities {#renderer_b_a}
-These systems aren't critical for renderer creation, but instead provide an easier way to perform commonly required functions.
-
-### Render queue {#renderer_b_a_a}
-@ref bs::ct::RenderQueue "ct::RenderQueue" allows you to sort and group scene objects for rendering. For example transparent objects might need to be sorted back to front based on their distance from the camera. It is also often useful to group objects if they share the same material, to reduce state switching which can improve performance.
-
-Use @ref bs::ct::RenderQueue::add "ct::RenderQueue::add" to add new objects to the queue. It expects a @ref bs::ct::RenderableElement "ct::RenderableElement" which you can create from information provided by @ref bs::Renderable "Renderable" when @ref bs::ct::Renderer::notifyRenderableAdded "ct::Renderer::notifyRenderableAdded" is called. Normally you wish to have a single @ref bs::ct::RenderableElement "ct::RenderableElement" for each sub-mesh present in the renderable object's mesh.
-
-Once all elements are in the queue, you can call @ref bs::ct::RenderQueue::setStateReduction "ct::RenderQueue::setStateReduction" to select how to sort the objects:
- - @ref bs::ct::StateReduction::None "ct::StateReduction::None" - There will be no sorting, based either by distance or material.
- - @ref bs::ct::StateReduction::Material "ct::StateReduction::Material" - Elements will be sorted by material first, then by distance.
- - @ref bs::ct::StateReduction::Distance "ct::StateReduction::Distance" - Elements will be sorted by distance first, then by material.
- 
-Once the state reduction mode is set call @ref bs::ct::RenderQueue::sort "ct::RenderQueue::sort", and then @ref bs::ct::RenderQueue::getSortedElements "ct::RenderQueue::getSortedElements" to retrieve a sorted list of render elements. The returned list contains a list of @ref bs::ct::RenderQueueElement "ct::RenderQueueElement" which lets you know exactly which render element to render using which pass, and also tells you when a new pass needs to be applied (if multiple elements in a row use the same pass, it doesn't need to be re-applied).
-
-For example:
-~~~~~~~~~~~~~{.cpp}
-Vector<RenderableElement*> elements = ...;
-
-SPtr<RenderQueue> queue = bs_shared_ptr_new<RenderQueue>(StateReduction::Distance);
-for(auto& element : elements)
-{
-	float distance = ...; // Calculate distance from element to camera, for sorting
-	queue->add(element, distance);
-}
-
-queue->sort();
-const Vector<RenderQueueElement>& sortedElements = queue->getSortedElements();
-... render sorted elements ...
-~~~~~~~~~~~~~
-
-### Renderer material {#renderer_b_a_b}
-Often the renderer needs to use special shaders for various effects (e.g. post-processing effects like FXAA). Unlike shaders and materials used by users, these shaders are built-in into the engine. Since we know they'll always be there we can make it easier for the renderer to load and use them by implementing the @ref bs::ct::RendererMaterial "ct::RendererMaterial" interface:
-~~~~~~~~~~~~~{.cpp}
-// Set up a post-processing material
-class DownsampleMat : public RendererMaterial<DownsampleMat>
-{
-	// Required macro pointing to the shader file
-	RMAT_DEF("Downsample.bsl");
-
-public:
-	DownsampleMat()
-	{
-		// Retrieve material parameters, and perform other set-up
-		mInputTexture = mMaterial->getParamTexture("gInputTex");
-		mInvTexSize = mMaterial->getParamVec2("gInvTexSize");
-	}
-
-	// Set up parameters and render a full screen quad using the material
-	void execute(const SPtr<Texture>& input)
-	{
-		// Actually assign parameters before rendering
-		mInputTexture.set(input);
-		
-		const RenderTextureProperties& rtProps = target->getProperties();
-		Vector2 invTextureSize(1.0f / rtProps.getWidth(), 1.0f / rtProps.getHeight());
-
-		mParams.gInvTexSize.set(invTextureSize);
-		
-		... set up the render target ...
-		... render using the material ...
-	}
-private:
-	MaterialParamVec2 mInvTexSize;
-	MaterialParamTexture mInputTexture;
-};
-
-// Method defined in RMAT_DEF
-void DirectionalLightMat::_initDefines(ShaderDefines& defines)
-{
-	// Set up optional defines to control shader compilation
-	defines.set("ENABLE_HIGH_QUALITY", 1);
-}
-
-~~~~~~~~~~~~~
-
-Renderer material implementation starts by deriving from @ref bs::ct::RendererMaterial<T> "ct::RendererMaterial<T>". This is followed by a declaration of the @ref RMAT_DEF macro, which contains a path to the shader file. The shader file should be located in "Data/Raw/Engine/Shaders/" folder.
-
-You must also implement `_initDefines` method, which allows you to modify the compilation environment. It can be empty if not required, but it is useful if your shader has different settings in the form of \#ifdef blocks, in which case different renderer materials can reference the same file, but yield different results depending on what is set in this method. Be aware that all built-in shaders are pre-processed by the @ref bs::BuiltinResources "BuiltinResources" manager. If you are changing define options you should delete the "Data/Engine/Timestamp.asset" file, which will force the manager to rebuild all shaders (and actually apply the new defines).
-
-Once these methods/macros are implemented, you can then instantiate your renderer material and access the @ref bs::Material "Material" using the `mMaterial` field. Normally your material will have some parameters, which you'll want to retrieve in the constructor, and then set before rendering. 
-
-@see @ref materials to learn how to work with materials in general.
-@see @ref renderTargets to learn how to create and render to a render target.
-
-### Parameter blocks {#renderer_b_a_c}
-If you shader has data parameters (like float, int, bool) it is efficient to group them into blocks of parameters. These blocks are better known as uniform buffers in OpenGL, or constant buffers in DX11. An example of such a buffer in HLSL looks like this:
-~~~~~~~~~~~~~{.cpp}
-// Contains various parameters specific to the current camera
-cbuffer PerCamera
-{
-	float3	 gViewDir;
-	float3 	 gViewOrigin;
-	float4x4 gMatViewProj;
-	float4x4 gMatView;
-	float4x4 gMatProj;
-	float4x4 gMatInvProj;
-	float4x4 gMatInvViewProj;			
-}
-~~~~~~~~~~~~~
-
-While you could assign these parameters using the standard way as described in the [material](@ref materials) manual:
-~~~~~~~~~~~~~{.cpp}
-MaterialParamVec3 viewDirParam = mMaterial->getParamVec3("gViewDir");
-viewDirParam.set(Vector3(0.707.0, 0.707f, 0.0f));
-// Or just simply:
-// mMaterial->setVec3("gViewDir", Vector3(0.707.0, 0.707f, 0.0f));
-
-... repeat for all other parameters
-~~~~~~~~~~~~~
-
-It is more efficient to assign them as a parameter block. Primarily because parameter blocks can be set once, and then shared between multiple materials. To set up a parameter block you must first set up its definition by using @ref BS_PARAM_BLOCK_BEGIN, @ref BS_PARAM_BLOCK_ENTRY and @ref BS_PARAM_BLOCK_END macros, like so:
-
-~~~~~~~~~~~~~{.cpp}
-BS_PARAM_BLOCK_BEGIN(PerCameraParamBlockDef)
-	BS_PARAM_BLOCK_ENTRY(Vector3, gViewDir)
-	BS_PARAM_BLOCK_ENTRY(Vector3, gViewOrigin)
-	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
-	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatView)
-	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatProj)
-	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvProj)
-	BS_PARAM_BLOCK_ENTRY(Matrix4, gMatInvViewProj)
-BS_PARAM_BLOCK_END
-~~~~~~~~~~~~~
-
-By using this approach you lose all the error checking normally performed by @ref bs::Material "Material". You must make sure that the layout in C++ matches the layout in the GPU program. In case of GLSL you must also specify `layout(std140)` keyword to ensure its layout is compatible with C++ struct layout. You must also make sure that variable names match the names in the GPU program.
-
-Once your parameter block definition is created, you can instantiate a parameter block buffer, assign values to it, and assign the blocks to materials, like so:
-~~~~~~~~~~~~~{.cpp}
-PerCameraParamBlockDef def; // Normally you want to make this global
-
-// Instantiates a new parameter block from the definition
-SPtr<GpuParamBlockBuffer> paramBlock = def.createBuffer(); 
-
-// Assign a value to the gViewDir parameter of the parameter block
-def.gViewDir.set(paramBlock, Vector3(0.707.0, 0.707f, 0.0f));
-... set other parameters in block ...
-
-SPtr<Material> material = ...;
-material->setParamBlockBuffer("PerCamera", paramBlock);
-
-... render using the material ...
-~~~~~~~~~~~~~
-
-Blocks are often used with renderer materials we described in the previous section, although we didn't use one in that example.
-
-### Renderer semantics {#renderer_b_a_d}
-Renderer semantics allow user created shaders to request that certain parameters in a GPU program are populated by the renderer. See the [materials](@ref materials) and [BSLFX](@ref bslfx) manuals on how to specify such semantics. 
-
-For example the user might request a "VP" semantic, which could be recognized by the renderer that the shader requests a view-projection matrix. Such a matrix is not something that the user should have to assign to the material himself. The renderer can choose to parse material parameters looking for supported semantics, and assign their values.
-
-For example:
-~~~~~~~~~~~~~{.cpp}
-StringID RPS_ViewProjTfrm = "VP"; // Define semantic identifier
-
-SPtr<Material> material = ...;
-SPtr<Shader> shader = material->getShader();
-auto& dataParams = shader->getDataParams();
-for (auto& entry : texParams)
-{
-	if (entry.second.rendererSemantic == RPS_ViewProjTfrm)
-	{
-		// Found it, assign some value to the parameter
-		mMaterial->setMat4(entry.second.name, Matrix4::IDENTITY);
-		break;
-	}
-}
-~~~~~~~~~~~~~
-
-You can choose to implement semantics in your renderer, but they aren't required. You can just as easily require the user to use specific parameter names, and then use those names directly (like we used in previous examples in this manual).
-
-### RendererUtility {#renderer_b_a_e}
-
-@ref bs::ct::RendererUtility "ct::RendererUtility" provides some commonly required functionality for rendering. For the most part these are just wrappers around @ref bs::RenderAPI "RenderAPI" methods, so you don't have to set things like vertex/index buffers manually, as described in [render API](@ref renderAPI) manual.
- - @ref bs::ct::RendererUtility::setPass "ct::RendererUtility::setPass" - Binds a pass from a specific @ref bs::Material "Material" for rendering. Any further draw calls will be rendered using this pass.
- - @ref bs::ct::RendererUtility::setPassParams "ct::RendererUtility::setPassParams" - Binds parameters (textures, samplers, etc.) from a @ref bs::Material "Material". Any further draw calls will be rendered using these parameters.
- - @ref bs::ct::RendererUtility::draw "ct::RendererUtility::draw" - Draws a specific sub-mesh of the provided @ref bs::ct::Mesh "ct::Mesh", using the currently bound pass.
- - @ref bs::ct::RendererUtility::blit "ct::RendererUtility::blit" - Copies the contents of the provided texture into the currently bound render target.
- - @ref bs::ct::RendererUtility::drawScreenQuad "ct::RendererUtility::drawScreenQuad" - Draws a quad using the currently bound pass.
- 
-Use @ref bs::ct::gRendererUtility() "ct::gRendererUtility()" to access the @ref bs::ct::RendererUtility "ct::RendererUtility" more easily.
- 
-Binding a material and rendering using @ref bs::ct::RendererUtility "ct::RendererUtility":
-~~~~~~~~~~~~~{.cpp}
-SPtr<Material> material = ...;
-SPtr<Mesh> mesh = ...;
-
-gRendererUtility().setPass(material);
-... set material parameters ...
-gRendererUtility().setPassParams(material);
-gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
-~~~~~~~~~~~~~
- 
-### RenderTexturePool {#renderer_b_a_f}
-Although you can create render textures manually as described in the [render target](@ref renderTargets) manual, @ref bs::ct::GpuResourcePool "ct::GpuResourcePool" provides a simpler and more efficient way of doing it. It will keep alive any referenced render textures, so that other systems may re-use them if their size/formats match. This can improve performance when using many temporary/intermediary render textures (like in post-processing).
-
-To request a render texture, first populate the @ref bs::ct::POOLED_RENDER_TEXTURE_DESC "ct::POOLED_RENDER_TEXTURE_DESC" descriptor, by calling either @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create2D "ct::POOLED_RENDER_TEXTURE_DESC::create2D", @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::create3D "ct::POOLED_RENDER_TEXTURE_DESC::create3D" or @ref bs::ct::POOLED_RENDER_TEXTURE_DESC::createCube "ct::POOLED_RENDER_TEXTURE_DESC::createCube".
-
-Then call @ref bs::ct::GpuResourcePool::get "ct::GpuResourcePool::get" which will either create a new render texture, or return one from the pool. The returned object is @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture" from which you can access the actual render texture.
-
-Once you are done using the texture, call @ref bs::ct::GpuResourcePool::release "ct::GpuResourcePool::release" to return the texture to the pool, and make it available for other systems. If you plan on using this texture again, make sure to keep a reference to the @ref bs::ct::PooledRenderTexture "ct::PooledRenderTexture". This will prevent the pool from fully destroying the texture so it may be reused.
-
-For example:
-~~~~~~~~~~~~~{.cpp}
-POOLED_RENDER_TEXTURE_DESC desc = POOLED_RENDER_TEXTURE_DESC::create2D(PF_R8G8B8A8, 1024, 1024);
-SPtr<PooledRenderTexture> pooledRT = GpuResourcePool::instance().get(desc);
-
-RenderAPI::instance().setRenderTarget(pooledRT->renderTexture);
-... render to target ...
-GpuResourcePool::instance().release(pooledRT);
-// Keep a reference to pooledRT if we plan on re-using it, then next time just call get() using the same descriptor
-~~~~~~~~~~~~~
-
-### Renderer options {#renderer_b_a_g}
-You can customize your rendering at runtime by implementing the @ref bs::ct::RendererOptions "ct::RendererOptions" class. Your @ref bs::ct::RendererOptions "ct::RendererOptions" implementation can then be assigned to the renderer by calling @ref bs::ct::Renderer::setOptions "ct::Renderer::setOptions", and accessed within the renderer via the `mOptions` field. No default options are provided and it's up to your renderer to decide what it requires.
-
-Be aware that options are set from the simulation thread, and if you want to use them on the core thread to either properly synchronize the access, or send a copy of the options to the core thread.