AEngine uses a right-handed coordinate system where Y is up, and the negative Z is the depth.
In order to change to a left-handed coordinate system, you need to recompile AEEngine with the symbol _AE_RH_COORDINATE_SYSTEM
undefined (note that some other changes may be necessary, for instance : the order of the vertices must be inverted and the texture coordinates must be changed in order for the objects to be rendered properly. The view matrices for cube map rendering must be changed too (I was too lazy to do it).
In AEngine, a mesh consists in a buffer of vertices with an optional buffer of indices. The class AED3D11Renderable
stores this data. The structure of the vertex buffer (the vertex/input layout) can be different between meshes. For instance, a very basic mesh includes position coordinates only, while the meshes loaded from files often include texture mapping coordinates and normal data per vertex on top of the position information. These additional data are used for texturing and to render lighting, among other things.
Refer to the article Buffers to see how to create these buffers with Direct 3D.
An important thing to keep in mind is that to be rendered correctly, a mesh and the effect used to draw it must have matching vertex layouts. Moreover you need to tell Direct 3D where the vertex buffers are and what type of data they contain. This is (must be) done in AED3D11Effect::Update which binds the correct input layout.
We advise you to read this article Input-Assembler Stage to see how to code it with Direct 3D.
The effects you create should take care of choosing the right technique depending on the vertex layout of the mesh. In AEngine, when a mesh is created, a code to describe his vertex layout is stored in the attribute AERenderable::m_uiVertexSemanticCode
. The list of codes used in the vanilla version of AEngine can be found in enum VertexSemantics in AERenderable.h
enum VertexSemantics
{
Position,
PositionColor,
PositionTexture,
PositionNormal,
PositionColorTexture,
PositionNormalColor,
PositionNormalTexture,
PositionNormalColorTexture,
PositionNormalTextureTangentBinormal,
VertexSemanticsNumber
};
This code is used to retrieve a matching input layout and the correct technique from an effect.
Deprecated, no longer used and no longer existing (that was a good idea though ^^'). See the source code of shaders instead.
The helper class AED3D11VertexTypeMap can be used to retrieve an input layout description given a mesh vertex layout semantic code. Alternatively, the method AED3D11EffectFactory::CreateInputLayout creates the input layout from the vertex semantic code, and returns a pointer on an existing layout if a match was found, which you use as follows :
// ... D3DX11_PASS_DESC PassDesc; m_pTechnique->GetPassByIndex(0)->GetDesc(&PassDesc); m_pVertexLayout = AED3D11EffectFactory::GetSingleton()->CreateInputLayout(pEntity->GetRenderable()->GetVertexSemanticCode(), PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize );
Remember that if you re-use an input layout, the input signature of the shaders must be identical. Otherwise your meshes won't be rendered correctly. You have to create manually your input layouts if you do not want to rely on the methods above.
Here is the complete list of input signatures used in the shaders in AEngine (the order of the semantics is important) :
struct VertexPosition { float4 position : SV_Position; }; struct VertexPositionColor { float4 position : SV_Position; float4 color : COLOR; }; struct VertexPositionNormal { float4 position : SV_Position; float3 normal : NORMAL; }; struct VertexPositionTexture { float4 position : SV_Position; float2 tex : TEXCOORD0; }; struct VertexPositionColorTexture { float4 position : SV_Position; float4 color : COLOR; float2 tex : TEXCOORD0; }; struct VertexPositionNormalTexture { float4 position : SV_Position; float3 normal : NORMAL; float2 tex : TEXCOORD0; }; struct VertexPositionNormalTextureTangentBinormal { float4 position : SV_Position; float3 normal : NORMAL; float2 tex : TEXCOORD0; float3 tangent : TANGENT; float3 binormal : BINORMAL; };
The primitives provided are the following ones :
All AERenderable objects have their vertex buffer defined once and for all during their creation. You can't modify or read it directly after due to the way it is managed by Direct3D. Actually you can, but it is generally never needed. The process is costly and for an example, refer to ID3D11DeviceContext::Map
and ID3D11DeviceContext::UpdateSubresource
methods. An example of usage can be seen in AED3D11Renderable::GenerateTangentAndBinormal
.
AEPrimitiveBatch
objects are particular AERenderables which have their vertex buffer (and optionally their index buffer) filled in dynamically at each frame. We use them to render sets of lines for instance. The advantage is that you can easily tweak the method which fills in vertex buffer at each frame, but the rendering time is longer than if the vertex buffer was created one and for all. To use them, put in the code to fill in the vertex and/or index buffers between calls to Begin(ID3D11DeviceContext*)
and End(ID3D11DeviceContext*)
. Note that AEPrimitiveBatch
objects do not have a default effect applied (since they have the flag m_bEmbeddedEffect
set to true). Thus you need to provide and bind your own shaders to their Render function.
Limitation : for an easier memory management when using multithreaded rendering and the Map/Unmap methods, we chose to render AED3D11Primitivebatch objects in the main thread exclusively (the one on which the immediate context runs). This is done by assigning entities managing a primitive batch (whose m_bMappable
flag is set to true) to the rendering groups RenderOnImmediateContext
and TransparentRenderOnImmediateContext
.
The AEPrimitive batches provided are :
class AED3D11Grid
)class AED3D11Sphere
)class AEParallelepiped
)See AED3D113DText or AED3D11PrimitiveBatch.cpp for examples of usage.
All renderable objects may have a bounding box attached, used to compute faster whether they are in a frustrum or not. For now we only use 2 type of bounding boxes : spheres and parallelepiped. See AEFrustrum
and AEBoundingBox
and its derived classes. You can choose to display the bounding box for a renderable object via the class AEntity.