BearishSun 8 лет назад
Родитель
Сommit
f130d85237

+ 162 - 0
Documentation/Manuals/Native/User/creatingMeshes.md

@@ -0,0 +1,162 @@
+Creating meshes				{#creatingMeshes}
+===============
+
+In a previous chapter we have shown how to import meshes from external files, and in this chapter we'll learn how to create meshes manually. 
+
+# Creating a mesh
+To create a mesh call @ref bs::Mesh::create "Mesh::create" or one if its overloads. You'll need to populate the @ref bs::MESH_DESC "MESH_DESC" structure and pass it as a parameter. At minimum the structure requires you to provide:
+ - @ref bs::MESH_DESC::numVertices "MESH_DESC::numVertices" - Number of vertices in the mesh
+ - @ref bs::MESH_DESC::numIndices "MESH_DESC::numIndices" - Number of indices in the mesh
+ - @ref bs::MESH_DESC::vertexDesc "MESH_DESC::vertexDesc" - Structure of type @ref bs::VertexDataDesc "VertexDataDesc" that describes what kind of data does each individual vertex contains, which we'll discuss in detail later.
+
+Optionally you can also provide:
+ - @ref bs::MESH_DESC::indexType "MESH_DESC::indexType" - Type of each index in the index buffer. They can be 32 or 16 bit, as specified by the @ref bs::IndexType "IndexType" enum.
+ - @ref bs::MESH_DESC::subMeshes "MESH_DESC::subMeshes" - A mesh can have multiple sub-meshes. Each sub-mesh is described by an offset and a range of indices that belong to it. Sub-meshes can be used for rendering sections of a mesh, instead of all of it (for example if a single mesh uses different materials). By default all indices are considered to be part of a single mesh.
+ - @ref bs::MESH_DESC::usage "MESH_DESC::usage" - Usage flag that specifies how the mesh is intended to be used, in a form of @ref bs::MeshUsage "MeshUsage" enum.
+ 
+Supported mesh usage flags are:
+ - @ref bs::MU_STATIC "MeshUsage::MU_STATIC" - Specify for normal meshes that are created once (or updated very rarely)
+ - @ref bs::MU_DYNAMIC "MeshUsage::MU_DYNAMIC" - Specify for meshes that are updated often (e.g. every frame)
+ - @ref bs::MU_CPUCACHED "MeshUsage::MU_CPUCACHED" - Specify that any data written to the mesh (from the CPU) will be cached internally, allowing it to be accessed through **Mesh::readCachedData()**. Uses extra memory as data needs to be stored in both normal and GPU memory.
+ 
+~~~~~~~~~~~~~{.cpp}
+// Creates an empty mesh with 36 indices and 8 vertices
+MESH_DESC meshDesc;
+meshDesc.numVertices = 8;
+meshDesc.numIndices = 36;
+
+SPtr<VertexDataDesc> vertexDesc = ...; // Vertex description creation is explained below
+meshDesc.vertexDesc = vertexDesc;
+
+HMesh mesh = Mesh::create(meshDesc);
+~~~~~~~~~~~~~
+
+## Vertex description
+To create a new vertex description object you call @ref bs::VertexDataDesc::create "VertexDataDesc::create()". After creation you need to specify a list of vertex elements by calling @ref bs::VertexDataDesc::addVertElem "VertexDataDesc::addVertElem()". Each vertex element is identified by:
+ - Type - Determines the size and format of that specific property (e.g. a 3D float for a position property). All supported types are provided in the @ref bs::VertexElementType "VertexElementType" enum.
+ - Semantic - Determines to which vertex GPU program input field will this property be mapped to. All supported semantic types are provided in the @ref bs::VertexElementSemantic "VertexElementSemantic" enum. Multiple types can be mapped to the same semantic by using the `semanticIdx` parameter.
+
+~~~~~~~~~~~~~{.cpp}
+// Create a vertex with a position, normal and UV coordinates
+SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
+vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
+vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
+vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD);
+~~~~~~~~~~~~~ 
+
+You may also specify these optional properties, primarily useful for low-level rendering:
+ - Stream index - Each vertex element can also be placed in a "stream". In the example above all the elements are in the 0th stream, but you can place different elements in different streams by providing a stream index. This can be useful if you are rendering the mesh with multiple GPU programs and not every GPU program requires all vertex elements, in which case you could only bind a subset of the vertex buffers and reduce the bandwidth costs by not sending the unnecessary data.
+ - Instance step rate - Values larger than 1 mean that data provided in the vertex buffer is not per vertex, but rather per instance. This is used for instanced rendering.
+
+Once the **VertexDataDesc** structure has been filled, you can use it for initializing a **Mesh** as shown above.
+
+# Writing mesh data
+After mesh has been created you need to write some vertex and index data to it by calling @ref bs::Mesh::writeData "Mesh::writeData". This method accepts a @ref bs::MeshData "MeshData" object.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<MeshData> meshData = ...; // Explained below
+// ... populate meshData
+
+mesh->writeData(meshData);
+~~~~~~~~~~~~~ 
+
+## Creating mesh data
+You can create @ref bs::MeshData "MeshData" by calling @ref bs::MeshData::create(UINT32, UINT32, const SPtr<VertexDataDesc>&, IndexType) "MeshData::create" and providing it with vertex description, index type and number of vertices and indices. You must ensure that the formats and sizes match the mesh this will be used on.
+
+~~~~~~~~~~~~~{.cpp}
+// Create mesh data able to contain 8 vertices of the format specified by vertexDesc, and 36 indices
+SPtr<MeshData> vertexDesc = MeshData::create(8, 36, vertexDesc);
+~~~~~~~~~~~~~ 
+
+You can also create **MeshData** using an existing mesh by calling @ref bs::Mesh::allocBuffer "Mesh::allocBuffer()". This will create an object of adequate size and vertex description for use on that mesh.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<MeshData> vertexDesc = mesh->allocBuffer();
+~~~~~~~~~~~~~ 
+
+## Populating mesh data
+Once **MeshData** has been created you need to populate it with vertices and indices. This can be done in a few ways.
+
+The most basic way is setting the data by using @ref bs::MeshData::setVertexData "MeshData::setVertexData" which set vertex data for a single vertex element all at once.
+
+~~~~~~~~~~~~~{.cpp}
+// Fill out the data for the 0th VES_POSITION element
+Vector3 myVertexPositions[8];
+for(UINT32 i = 0; i < 8; i++)
+	myVertexPositions = Vector3(i, i, 0); // Arbitrary
+
+// Write the vertices
+meshData->setVertexData(VES_POSITION, myVertexPositions, sizeof(myVertexPositions));
+~~~~~~~~~~~~~
+
+You can also use @ref bs::MeshData::getElementData "MeshData::getElementData" which will return a pointer to the starting point of the vertex data for a specific element. You can then iterate over the pointer to read/write values. Make sure to use @ref bs::VertexDataDesc::getVertexStride "VertexDataDesc::getVertexStride" to know how many bytes to advance between elements. This ensures you don't need to create an intermediate buffer like we did above.
+
+~~~~~~~~~~~~~{.cpp}
+// Fill out the data for the 0th VES_POSITION element
+UINT8* vertices = meshData->getElementData(VES_POSITION);
+UINT32 stride = meshData->getVertexDesc()->getVertexStride();
+
+for(UINT32 i = 0; i < 8; i++)
+{
+	Vector3 myPosition(i, i, 0); // Arbitrary
+	memcpy(vertices, &myPosition, sizeof(myPosition));
+	
+	vertices += stride;
+}
+~~~~~~~~~~~~~
+
+And finally you can use iterators: @ref bs::MeshData::getVec2DataIter "MeshData::getVec2DataIter", @ref bs::MeshData::getVec3DataIter "MeshData::getVec3DataIter", @ref bs::MeshData::getVec4DataIter "MeshData::getVec4DataIter", @ref bs::MeshData::getDWORDDataIter "MeshData::getDWORDDataIter". They are similar to the previous example but you don't need to manually worry about the vertex stride, or going outside of valid bounds.
+
+~~~~~~~~~~~~~{.cpp}
+// Fill out the data for the 0th VES_POSITION element
+auto iter = meshData->getVec3DataIter(VES_POSITION);
+
+Vector3 myPosition(0, 0, 0)
+do {
+	myPosition.x += 1.0f; // Arbitrary
+	myPosition.y += 1.0f; // Arbitrary
+} while(vecIter.addValue(myPosition)); // // Automatically advances the iterator, and returns false when there's no more room
+~~~~~~~~~~~~~
+
+Writing indices is simpler and is done through @ref bs::MeshData::getIndices32 "MeshData::getIndices32" or @ref bs::MeshData::getIndices16 "MeshData::getIndices16" depending if the indices are 32 or 16 bit. The returned value is a pointer to the index buffer you can use to read/write the indices directly.
+
+~~~~~~~~~~~~~{.cpp}
+// Write 6 32-bit indices
+UINT32* indices = meshData->getIndices32();
+indices[0] = 0;
+indices[1] = 1;
+indices[2] = 2;
+
+indices[3] = 2;
+indices[4] = 1;
+indices[5] = 3;
+~~~~~~~~~~~~~
+
+## Discard on write
+When you are sure you will overwrite all the contents of a mesh, make sure to set the last parameter of **Mesh::writeData()** to true. This ensures the system can more optimally execute the transfer, without requiring the GPU to finish its current action (which can be considerably slow if it is currently using that particular mesh).
+ 
+# Reading cached CPU data
+Reading cached CPU data allows you to read-back any data you have written to the mesh when calling **Mesh::writeData()**. It is particularily useful when importing meshes from external files and wish to access their vertex/index data. Note that mesh must be created with the **MeshUsage::MU_CPUCACHED** usage flag in order for CPU cached data to be available. When importing meshes this flag will automatically be set if the relevant property is enabled in **MeshImportOptions**.
+
+Cached CPU data can be read by calling @ref bs::Mesh::readCachedData "Mesh::readCachedData()". It accepts a **MeshData** parameter to which to output the index and vertex data.
+
+~~~~~~~~~~~~~{.cpp}
+SPtr<MeshData> meshData = mesh->allocBuffer();
+mesh->readCachedData(*meshData);
+~~~~~~~~~~~~~
+
+After reading the data you can access it through @ref bs::MeshData::getVertexData "PixelData::getVertexData()", @ref bs::MeshData::getElementData "PixelData::getElementData()" or through iterators.
+
+~~~~~~~~~~~~~{.cpp}
+// Read the data for the 0th VES_POSITION element, using iterators
+auto iter = meshData->getVec3DataIter(VES_POSITION);
+
+UINT32 numVertices = meshData->getNumVertices();
+Vector3* output = bs_newN<Vector>(numVertices);
+
+for(UINT32 i = 0; i < numVertices; i++)
+{
+	output[i] = iter.getValue(); // Returns current value
+	iter.moveNext(); // Move to next vertex
+}
+~~~~~~~~~~~~~

+ 85 - 0
Documentation/Manuals/Native/User/offscreenRendering.md

@@ -0,0 +1,85 @@
+Offscreen rendering				{#offscreenRendering}
+===============
+
+When we talked about how to set up a **Camera** component we have shown that we need to provide it with a render target onto which to output the rendered pixels. In that example we have used a **RenderWindow** as the target, but you may instead also use a @ref bs::RenderTexture "RenderTexture". Both render windows and render textures derive from a common @ref bs::RenderTarget "RenderTarget" base class, and can be used interchageably in most places. 
+
+We call rendering to a texture offscreen rendering. By rendering offscreen you can achieve advanced graphical effects by manipulating the contents of the rendered-to texture before presenting them to the user. 
+
+# Creation
+Render texture must contain at least one color surface, and may optionally also contain a depth-stencil surface. Both of those surfaces are **Texture** objects, created with either **TU_RENDERTARGET** or **TU_DEPTHSTENCIL** usage flags, respectively, as demonstrated in the texture manipulation chapter. 
+
+To create a render texture call @ref bs::RenderTexture::create(const RENDER_TEXTURE_DESC&) "RenderTexture::create" with a populated @ref bs::RENDER_TEXTURE_DESC "RENDER_TEXTURE_DESC" structure. This structure expects a reference to one or more color surface textures, and an optional depth-stencil surface texture. For each of those you must also specify the face and mip level onto which to render, in case your texture has multiple.
+
+~~~~~~~~~~~~~{.cpp}
+// Create a 1920x1080 texture with 32-bit RGBA format
+TEXTURE_DESC colorDesc;
+colorDesc.type = TEX_TYPE_2D;
+colorDesc.width = 1920;
+colorDesc.heigth = 1080;
+colorDesc.format = PF_R8G8B8A8;
+colorDesc.usage = TU_RENDERTARGET;
+
+HTexture color = Texture::create(colorDesc);
+
+// Create a 1920x1080 texture with a 32-bit depth-stencil format
+TEXTURE_DESC depthDesc;
+depthDesc.type = TEX_TYPE_2D;
+depthDesc.width = 1920;
+depthDesc.heigth = 1080;
+depthDesc.format = PF_R8G8B8A8;
+depthDesc.usage = TU_DEPTHSTENCIL;
+
+HTexture depthStencil = Texture::create(depthDesc);
+
+RENDER_TEXTURE_DESC desc;
+desc.colorSurfaces[0].texture = color;
+desc.colorSurfaces[0].face = 0;
+desc.colorSurfaces[0].mipLevel = 0;
+
+desc.depthStencilSurface.texture = depthStencil;
+desc.depthStencilSurface.face = 0;
+desc.depthStencilSurface.mipLevel = 0;
+
+SPtr<RenderTexture> renderTexture = RenderTexture::create(desc);
+~~~~~~~~~~~~~
+
+## Multiple surfaces
+Render textures can also contain multiple color surfaces (up to 8). Such targets allow you to write more data at once in your shader program. To create a texture with multiple color surfaces simply fill out other entries of @ref bs::RENDER_TEXTURE_DESC "RENDER_TEXTURE_DESC::colorSurfaces" array and proceed the same as in the above example.
+
+All color surfaces and the depth/stencil surface (if present) must have the same dimensions and sample count.
+
+## Multi-sampled surfaces
+Render textures can be created with support for multiple samples per pixel. This allows affects such as multi-sampled antialiasing and similar. To create a multi-sampled render texture simply create a **Texture** with its `multisampleCount` parameter larger than one, which you then use to initialize a render texture. Make sure that all surfaces (including depth-stencil) in a render texture have the same number of samples.
+
+Multisampled textures cannot be used directly by materials or sampled in shaders. This means that before you can use such a texture for normal rendering you must first resolve its multi-sampled contents into a non-multisampled texture. You may do this in two ways:
+ - Call @ref bs::ct::Texture::copy "ct::Texture::copy" with the source texture being your multisampled texture, and the destination being a texture of same dimensions and format, but with a single sample per pixel. Note this is a core-thread only method - we talk more about the core thread later.
+ - Write a custom shader that manually reads samples from the texture and outputs pixels (out of the scope of this manual)
+
+# Rendering to textures
+To render to a render texture you can simply pass it to a **Camera** component on construction, or you may use the low-level API to directly bind the texture for rendering (see the low level rendering manuals).
+
+~~~~~~~~~~~~~{.cpp}
+HSceneObject cameraSO = SceneObject::create("Camera");
+HCamera camera = cameraSO->addComponent<CCamera>(renderTexture);
+~~~~~~~~~~~~~
+
+# Using render textures as input
+Once you have performed some rendering into a render texture, you can access its underlying textures by calling @ref bs::RenderTexture::getColorTexture "RenderTexture::getColorTexture()" and @ref bs::RenderTexture::getDepthStencilTexture "RenderTexture::getDepthStencilTexture()". Once you have the underlying textures you can use them as you would normal textures, i.e. by binding them to a material for rendering, or reading their contents.
+
+~~~~~~~~~~~~~{.cpp}
+// Do some rendering to the render texture
+HTexture colorTexture = renderTexture->getColorTexture(0);
+
+// Bind the result as input to a material to render with
+HMaterial someMaterial = ...;
+someMaterial->setTexture("gInputTex", texture);
+~~~~~~~~~~~~~
+
+Please note that a render texture must not be bound for rendering at the same time you are trying to read from it (either from shader of from the CPU). This will result in undefined behaviour.
+
+# Priority
+All render targets have a priority that can be set by calling @ref bs::RenderTarget::setPriority "RenderTarget::setPriority". This priority can be used as a hint to the renderer in which order should the targets be rendered to. Targets with higher priority will be rendered to before targets with lower priority. This value is only used for render targets assigned to **Camera**%s, and this value is ignored if rendering using the low-level rendering API as in that case you have manual control over rendering order. This is useful if you are rendering to a texture which is used in a later stage as an input, in which case you can ensure the rendering to the texture happens first.
+
+~~~~~~~~~~~~~{.cpp}
+renderTexture->setPriority(50);
+~~~~~~~~~~~~~

+ 0 - 0
Documentation/Manuals/Native/playingAudio.md → Documentation/Manuals/Native/User/playingAudio.md


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

@@ -60,6 +60,8 @@ Manuals									{#manuals}
  - [Advanced animation](@ref advancedAnimation)
  - [Advanced animation](@ref advancedAnimation)
 - **Advanced**
 - **Advanced**
  - [Manipulating textures](@ref advancedTextures)
  - [Manipulating textures](@ref advancedTextures)
+ - [Offscreen rendering](@ref offscreenRendering)
+ - [Creating meshes](@ref creatingMeshes)
  - [Advanced RTTI](@ref advancedRtti) 
  - [Advanced RTTI](@ref advancedRtti) 
  
  
 # Developer guides
 # Developer guides