Преглед на файлове

More work on documentation

BearishSun преди 8 години
родител
ревизия
68c4fb3403

+ 0 - 23
Documentation/Manuals/Native/User/drawing.md

@@ -1,23 +0,0 @@
-Drawing									{#drawing}
-===============
-[TOC]
-
-With all the objects from the previous chapters bound to the pipeline we are almost ready to draw an object. When drawing you must ensure a pipeline state of **GraphicsPipelineState** type is bound, instead of **ComputePipelineState**.
-
-Next you need to specify what type of primitives you wish to draw by calling @ref bs::ct::RenderAPI::setDrawOperation "ct::RenderAPI::setDrawOperation()", which accepts any of the type defined in @ref bs::DrawOperationType "DrawOperationType". This determines how are contents of the index buffer interpreted (or vertex buffer if index isn't available). The available draw types are:
- - @ref bs::DOT_POINT_LIST "DOT_POINT_LIST" - Each vertex represents a point.
- - @ref bs::DOT_LINE_LIST "DOT_POINT_LIST" - Each sequential pair of vertices represent a line.
- - @ref bs::DOT_LINE_STRIP "DOT_LINE_STRIP" - Each vertex (except the first) forms a line with the previous vertex.
- - @ref bs::DOT_TRIANGLE_LIST "DOT_TRIANGLE_LIST" - Each sequential 3-tuple of vertices represent a triangle.
- - @ref bs::DOT_TRIANGLE_STRIP "DOT_TRIANGLE_STRIP" - Each vertex (except the first two) form a triangle with the previous two vertices.
- - @ref bs::DOT_TRIANGLE_FAN "DOT_TRIANGLE_FAN" - Each vertex (except the first two) form a triangle with the first vertex and previous vertex.
-
-~~~~~~~~~~~~~{.cpp}
-// We're drawing a triangle list
-RenderAPI& rapi = RenderAPI::instance();
-rapi.setDrawOperation(DOT_TRIANGLE_LIST);
-~~~~~~~~~~~~~
-
-Finally you can now draw the object by calling @ref bs::ct::RenderAPI::drawIndexed() "ct::RenderAPI::drawIndexed()".
-
-TODO

+ 21 - 13
Documentation/Manuals/Native/User/lights.md

@@ -14,16 +14,16 @@ HLight light = lightSO->addComponent<CLight>();
 Once created light can be positioned and oriented normally using its **SceneObject**.
 
 # Light types
-Lights have three variants that determine how light affects surrounding objects: point, spot and directional. You can change between light variants with @ref bs::CLight::setType "CLight::setType".
+Lights have three variants that determine how light affects surrounding objects: radial, spot and directional. You can change between light variants with @ref bs::CLight::setType "CLight::setType()".
 
 ~~~~~~~~~~~~~{.cpp}
-// Make a point light
-light->setType(LightType::Point);
+// Make a radial light
+light->setType(LightType::Radial);
 ~~~~~~~~~~~~~
 
-## Point light
+## Radial light
 
-Point light affects everything within a certain radius from the light (i.e. its sphere of influence). It is the most basic type of light.
+Radial light affects everything within a certain radius from the light (i.e. its sphere of influence). It is the most basic type of light.
 
 @ref TODO_IMAGE
 
@@ -35,7 +35,7 @@ Spot lights only illuminate a certain direction (i.e. like a flash-light). The u
 
 ## Directional light
 
-Directional lights are a special type of light primarily used for simulating sun-light, or otherwise far-away objects. Unlike point or spot lights they cannot be positioned. Only their orientation matters and they equally affect every object in the scene.
+Directional lights are a special type of light primarily used for simulating sun-light, or otherwise far-away objects. Unlike radial or spot lights they cannot be positioned. Only their orientation matters and they equally affect every object in the scene.
 
 @ref TODO_IMAGE
 
@@ -43,12 +43,12 @@ Directional lights are a special type of light primarily used for simulating sun
 Each light has a set of properties you can adjust (aside from position/orientation, which are handled by the **SceneObject**). Most of the properties are common for all light types but some are only relevant for specific types. We'll go over all of the properties below.
 
 ## Color
-As the name implies, this controls what color light is being emitted from the source. It can be set by calling @ref bs::CLight::setColor "CLight::setColor" and it is valid for all light types.
+As the name implies, this controls what color light is being emitted from the source. It can be set by calling @ref bs::CLight::setColor "CLight::setColor()" and it is valid for all light types.
 
-## Range
-Range determines how far away does the light's influence reach. For point lights this is the radius of the sphere of influence, and for spot lights this is the distance from the origin in the direction of the light. This property is not relevant for directional lights as their range is infinite. Use @ref bs::CLight::setRange "CLight::setRange" to set the range.
+## Attenuation radius
+Attenuation radius determines how far away does the light's influence reach. For radial lights this is the radius of the sphere of influence, and for spot lights this is the distance from the origin in the direction of the light. This property is not relevant for directional lights as their range is infinite. Use @ref bs::CLight::setAttenuationRadius "CLight::setAttenuationRadius()" to set the range.
 
-Note that the manually set range will only be used if physically based attenuation is disabled. You can toggle this by calling @ref bs::CLight::setPhysicallyBasedAttenuation "CLight::setPhysicallyBasedAttenuation". When physically based attenuation is enabled the maximum range is calculated automatically based on the light intensity (described below) and using a real-world light attenuation model. You might assume that this is always wanted, but sometimes the designer might want more control in which case setting the range manually might be preferable.
+Note that the manually set range will only be used if automatic attenuation is disabled. You can toggle this by calling @ref bs::CLight::setUseAutoAttenuation "CLight::setUseAutoAttenuation()". When automatic attenuation is enabled the maximum range is calculated automatically based on the light intensity (described below). This automatic attenuation will smoothly cut off the light influence when it reaches roughly 10% of its intensity. Sometimes this is not wanted in which case you can turn this off and increase the range manually. Reducing the range manually will result in a non-physically realistic light attenuation.
 
 ## Intensity
 This controls how strong is the light. Although you could technically control light intensity using the color property (by using a lighter or darker color), using the intensity allows the engine to simulate high-dynamic range. 
@@ -57,12 +57,20 @@ In nature the range of light intensities varies highly - standing outside at a s
 
 Banshee uses a HDR algorithm to try to approximate this adjustment, which results in more realistic and higher quality lighting. Therefore it can be important for realism to set up the light intensities similar to what they would be in nature. 
 
-Use @ref bs::CLight::setIntensity "CLight::setIntensity" to change the light intensity. 
+Use @ref bs::CLight::setIntensity "CLight::setIntensity()" to change the light intensity. 
 
-The specific units used for intensity (in case you want to look them up for actual light sources) are *luminous flux* for point/spot lights, and *radiance* for directional lights.
+The specific units used for intensity (in case you want to look them up for actual light sources) are *luminous flux* for radial/spot lights, and *luminance* for directional lights.
 
+## Source radius
+By default all lights are considered point (punctual) lights, meaning they have no area. In case you want to make an area light set the source radius of the light by calling @ref bs::CLight::setSourceRadius "CLight::setSourceRadius()". The value of this property is interpreted differently depending on light type:
+ - Radial - Light represents a spherical area light and source radius is the sphere's radius
+ - Spot - Light represents a disc area light (oriented toward spot direction) and the source radius in the disc radius
+ - Directional - Light represents a disc area light projected on the sky, and the source radius represents the angular radius (in degrees) of the light. For example, Sun's angular radius is roughly 0.5° (varies slighly).
+
+Area light types are particulary important for physically based rendering, as they can produce realistic looking specular reflections, which is not the case for point lights. 
+ 
 ## Shadows
-Lights may or may not cast shadows. For realism all lights should cast shadows, but that is not feasible due to the high performance costs of using shadows. Therefore you should enable shadows only for one, or a few important lights. Use @ref bs::CLight::setCastsShadow "CLight::setCastsShadow" to enable or disable shadow casting.
+Lights may or may not cast shadows. For realism all lights should cast shadows, but that is not feasible due to the high performance costs of using shadows. Therefore you should enable shadows only for one, or a few important lights. Use @ref bs::CLight::setCastsShadow "CLight::setCastsShadow()" to enable or disable shadow casting.
 
 ## Spot angles
 Spot light have a property that defines at how wide an angle do they cast light in. Narrower angle means a more focused light beam, while wider angle means a weaker light covering a larger area. 

+ 105 - 0
Documentation/Manuals/Native/drawing.md

@@ -0,0 +1,105 @@
+Drawing									{#drawing}
+===============
+[TOC]
+
+With all the objects from the previous chapters bound to the pipeline we are almost ready to draw an object. When drawing you must ensure a pipeline state of **GraphicsPipelineState** type is bound, instead of **ComputePipelineState**.
+
+Next you need to specify what type of primitives you wish to draw by calling @ref bs::ct::RenderAPI::setDrawOperation "ct::RenderAPI::setDrawOperation()", which accepts any of the types defined in @ref bs::DrawOperationType "DrawOperationType". This determines how are contents of the index buffer interpreted (or vertex buffer if index isn't available). The available draw types are:
+ - @ref bs::DOT_POINT_LIST "DOT_POINT_LIST" - Each vertex represents a point.
+ - @ref bs::DOT_LINE_LIST "DOT_POINT_LIST" - Each sequential pair of vertices represent a line.
+ - @ref bs::DOT_LINE_STRIP "DOT_LINE_STRIP" - Each vertex (except the first) forms a line with the previous vertex.
+ - @ref bs::DOT_TRIANGLE_LIST "DOT_TRIANGLE_LIST" - Each sequential 3-tuple of vertices represent a triangle.
+ - @ref bs::DOT_TRIANGLE_STRIP "DOT_TRIANGLE_STRIP" - Each vertex (except the first two) form a triangle with the previous two vertices.
+ - @ref bs::DOT_TRIANGLE_FAN "DOT_TRIANGLE_FAN" - Each vertex (except the first two) forms a triangle with the first vertex and previous vertex.
+
+~~~~~~~~~~~~~{.cpp}
+// We're drawing a triangle list
+RenderAPI& rapi = RenderAPI::instance();
+rapi.setDrawOperation(DOT_TRIANGLE_LIST);
+~~~~~~~~~~~~~
+
+# Indexed drawing
+Finally you can now draw the object by calling @ref bs::ct::RenderAPI::drawIndexed() "ct::RenderAPI::drawIndexed()". It requires the following parameters:
+ - @p startIndex - Offset into the bound index buffer to start drawing from. In most cases this will be zero.
+ - @p indexCount - Number of indices to draw. Specify total number of indices in the index buffer to draw them all (most common case).
+ - @p vertexOffset - Offset to append to each index in the index buffer. Allows you to draw different set of vertices using the same index buffer. In most cases this will be zero.
+ - @p vertexCount - Number of vertices to draw. Since the actual number of primitives drawn is determined by the index count, this value is internally used just for tracking purposes and wont affect your rendering. In most cases you can specify the number of vertices in the vertex buffer(s).
+ 
+~~~~~~~~~~~~~{.cpp}
+SPtr<IndexBuffer> ib = ...;
+SPtr<VertexBuffer> vb = ...;
+
+UINT32 numIndices = ib->getProperties()->getNumIndices();
+UINT32 numVertices = vb->getProperties()->getNumVertices();
+
+RenderAPI& rapi = RenderAPI::instance();
+rapi.drawIndexed(0, numIndices, 0, numVertices);
+~~~~~~~~~~~~~
+
+# Non-indexed drawing
+If drawing without an index buffer you can call @ref bs::ct::RenderAPI::draw() "ct::RenderAPI::draw()" instead. It requires only the @p vertexOffset and @p vertexCount parameters, with same meaning as above (except @p vertexCount in this case does affect the rendering).
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<VertexBuffer> vb = ...;
+UINT32 numVertices = vb->getProperties()->getNumVertices();
+
+RenderAPI& rapi = RenderAPI::instance();
+rapi.draw(0, numVertices);
+~~~~~~~~~~~~~
+
+# Instanced drawing
+Both **ct::RenderAPI::draw()** and **ct::RenderAPI::drawIndexed()** support drawing multiple instances of the same object using the @p instanceCount parameter. This can be used as an alternative for issuing multiple **draw** calls, as they may have a significant CPU overhead. Using instanced drawing you can draw the same geometry multiple times with almost no additional CPU overhead.
+
+~~~~~~~~~~~~~{.cpp}
+// Draw 5 instances of the currently bound geometry
+rapi.drawIndexed(0, numIndices, 0, numVertices, 5);
+~~~~~~~~~~~~~
+
+In order for instanced drawing to actually be useful, in most cases we need a way to differentiate the instances. At the very least we usually want to draw the instances at different positions in the world.
+
+This is done by creating a separate **VertexBuffer** that contains per-instance properties (like position). This buffer is created same as a normal vertex buffer, except it doesn't contain per-vertex data, and instead contains per-instance data.
+
+In order to use such a buffer we need to let the pipeline know by creating an appropriate **VertexDeclaration**. We need to define a **VertexDataDesc** that contains per-instance data. This is done by specifying the @p instanceStepRate parameter when calling **VertexDataDesc::addVertElem()**.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
+
+// Per vertex data (same as for non-instanced drawing)
+vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
+vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+
+// Per instance data
+vertexDesc->addVertElem(
+ VET_FLOAT3, // Each entry in the instance vertex buffer is a 3D float
+ VES_POSITION, // We map it to the position semantic as vertex shader input
+ 1, // We use the semantic index 1, as 0th index is taken by per-vertex VES_POSITION semantic
+ 1, // We use the second bound vertex buffer for instance data
+ 1  // Instance step rate of 1 means the new element will be fetched from the vertex buffer for each drawn instance
+ );
+
+// Create a vertex declaration
+SPtr<VertexDeclaration> vertexDecl = VertexDeclaration::create(vertexDesc);
+
+RenderAPI& rapi = RenderAPI::instance();
+
+// Bind vertex declaration
+rapi.setVertexDeclaration(vertexDecl);
+
+// Bind per-vertex and per-instance vertex buffers
+rapi.setVertexBuffers(0, { perVertexVB, perInstanceVB });
+
+// Draw ...
+~~~~~~~~~~~~~
+
+# Drawing helper
+As a way of making drawing easier you can also use @ref bs::ct::RendererUtility::draw "ct::RendererUtility::draw()" helper method, accessible globally through @ref bs::ct::gRendererUtility() "ct::gRendererUtility()". This method accepts a **ct::Mesh** as input and will automatically:
+ - Bind vertex & index buffer
+ - Bind vertex declaration
+ - Set draw operation type
+ - Execute a draw call
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<Mesh> mesh = ...;
+gRendererUtility().draw(mesh);
+~~~~~~~~~~~~~

+ 40 - 0
Documentation/Manuals/Native/loadStoreTextures.md

@@ -0,0 +1,40 @@
+Load-store textures			{#loadStoreTextures}
+===============
+[TOC]
+
+We discussed textures in detail previously, but we haven't yet mentioned load-store textures. These are a type of textures that can be used in a GPU program for arbitrary reads and writes. This makes them different from normal textures, which can only be used for reading or as render targets. They are particularily useful for compute programs as they are (together with load-store buffers) the only ways to output data from such programs.
+
+They are also known as unordered-access textures, storage textures or random write textures. In HLSL these textures have a *RW* prefix, e.g. *RWTexture2D*, and in GLSL they have an *image* prefix, e.g. *image2D*.
+
+Creation of a load-store texture is essentially the same as for normal textures, except for the addition of the @ref bs::TU_LOADSTORE "TU_LOADSTORE" usage flag.
+
+~~~~~~~~~~~~~{.cpp}
+// Creates a 2D load-store texture, 128x128 with a 4-component 32-bit floating point format
+TEXTURE_DESC desc;
+desc.type = TEX_TYPE_2D;
+desc.width = 128;
+desc.heigth = 128;
+desc.format = PF_FLOAT32_RGBA;
+desc.usage = TU_LOADSTORE;
+
+SPtr<Texture> texture = Texture::create(desc);
+~~~~~~~~~~~~~ 
+
+You can then bind a load-store texture to a GPU program by calling @ref bs::ct::GpuParams::setLoadStoreTexture(GpuProgramType, const String&, const TextureType&, const TextureSurface&) "ct::GpuParams::setLoadStoreTexture()" as was described in an earlier chapter.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<GpuParams> params = ...;
+params->setLoadStoreTexture(GPT_COMPUTE_PROGRAM, "myLoadStoreTex", texture);
+~~~~~~~~~~~~~ 
+
+Load-store textures do not support sampling using sampler states, you can only read-write their pixels directly. They also do not support mip-maps, and if your texture has multiple mip-maps you must provide a @ref bs::TextureSurface "TextureSurface" struct to **ct::GpuParams::setLoadStoreTexture()** in order to specify which mip-level to bind (by default it is the first).
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<GpuParams> params = ...;
+
+TextureSurface surface;
+surface.mipLevel = 5; // Bind 5th mip-level for load-store operations
+params->setLoadStoreTexture(GPT_COMPUTE_PROGRAM, "myLoadStoreTex", texture);
+~~~~~~~~~~~~~ 
+
+Load-store textures can also be bound as normal textures, for read-only operations like sampling. Note that they cannot be bound for both operations at once. Also note that load-store textures are not supported for 3D textures, and have limited support (depending on the rendering backend) for multisampled surfaces.

+ 2 - 0
Source/BansheeCore/Include/BsMaterialParams.h

@@ -387,6 +387,7 @@ namespace bs
 		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[out]	value		Output value of the parameter.
+		 * @param[out]	surface		Surface describing which part of the texture is being accessed.
 		 */
 		void getTexture(const String& name, TextureType& value, TextureSurface& surface) const;
 
@@ -396,6 +397,7 @@ namespace bs
 		 *
 		 * @param[in]	name		Name of the shader parameter.
 		 * @param[in]	value		New value of the parameter.
+		 * @param[in]	surface		Surface describing which part of the texture is being accessed.
 		 */
 		void setTexture(const String& name, const TextureType& value, 
 						const TextureSurface& surface = TextureSurface::COMPLETE);

+ 2 - 2
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -824,7 +824,7 @@ namespace bs { namespace ct
 		if (commandBuffer == nullptr)
 		{
 			executeRef(startIndex, indexCount, vertexOffset, vertexCount, instanceCount);
-			primCount = vertexCountToPrimCount(mActiveDrawOp, vertexCount);
+			primCount = vertexCountToPrimCount(mActiveDrawOp, indexCount);
 		}
 		else
 		{
@@ -833,7 +833,7 @@ namespace bs { namespace ct
 			SPtr<D3D11CommandBuffer> cb = std::static_pointer_cast<D3D11CommandBuffer>(commandBuffer);
 			cb->queueCommand(execute);
 
-			primCount = vertexCountToPrimCount(cb->mActiveDrawOp, vertexCount);
+			primCount = vertexCountToPrimCount(cb->mActiveDrawOp, indexCount);
 		}
 
 		BS_INC_RENDER_STAT(NumDrawCalls);

+ 11 - 5
Source/BansheeEngine/Include/BsRendererUtility.h

@@ -60,6 +60,16 @@ namespace bs { namespace ct
 		 */
 		void setPassParams(const SPtr<GpuParamsSet>& params, UINT32 passIdx = 0);
 
+		/**
+		 * Draws the specified mesh.
+		 *
+		 * @param[in]	mesh			Mesh to draw.
+		 * @param[in]	numInstances	Number of times to draw the mesh using instanced rendering.
+		 *
+		 * @note	Core thread.
+		 */
+		void draw(const SPtr<MeshBase>& mesh, UINT32 numInstances = 1);
+
 		/**
 		 * Draws the specified mesh.
 		 *
@@ -148,11 +158,7 @@ namespace bs { namespace ct
 		SPtr<BlitMat> mBlitMat;
 	};
 
-	/**
-	 * Provides easy access to RendererUtility.
-	 * 			
-	 * @note	Core thread only.
-	 */
+	/** Provides easy access to RendererUtility. */
 	BS_EXPORT RendererUtility& gRendererUtility();
 
 	/** Shader that resolves a MSAA surface into a non-MSAA render target. */

+ 5 - 0
Source/BansheeEngine/Source/BsRendererUtility.cpp

@@ -164,6 +164,11 @@ namespace bs { namespace ct
 		rapi.setGpuParams(gpuParams);
 	}
 
+	void RendererUtility::draw(const SPtr<MeshBase>& mesh, UINT32 numInstances)
+	{
+		draw(mesh, mesh->getProperties().getSubMesh(0), numInstances);
+	}
+
 	void RendererUtility::draw(const SPtr<MeshBase>& mesh, const SubMesh& subMesh, UINT32 numInstances)
 	{
 		RenderAPI& rapi = RenderAPI::instance();

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanRenderAPI.h

@@ -134,7 +134,7 @@ namespace bs { namespace ct
 	protected:
 		friend class VulkanRenderAPIFactory;
 
-		/** @copydoc RenderAPI::initializePrepare */
+		/** @copydoc RenderAPI::initialize */
 		void initialize() override;
 
 		/** @copydoc RenderAPI::destroyCore */

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanRenderStateManager.h

@@ -15,7 +15,7 @@ namespace bs { namespace ct
 	class VulkanRenderStateManager : public RenderStateManager
 	{
 	protected:
-		/** @copydoc RenderStateManager::createSamplerStateStateInternal */
+		/** @copydoc RenderStateManager::createSamplerStateInternal */
 		SPtr<SamplerState> createSamplerStateInternal(const SAMPLER_STATE_DESC& desc,
 			GpuDeviceFlags deviceMask) const override;
 

+ 1 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanTexture.h

@@ -210,7 +210,7 @@ namespace bs { namespace ct
 		void unlockImpl() override;
 
 		/** @copydoc Texture::copyImpl */
-		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel,
+		void copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 dstFace, UINT32 dstMipLevel,
 					  const SPtr<Texture>& target, UINT32 queueIdx = 0) override;
 
 		/** @copydoc Texture::readData */