DirectX rendering procedure

Started by
16 comments, last by Ubermeowmix 10 years, 3 months ago

I'm having trouble understanding how directX deals with the objects being called and when it renders each one.

In a nutshell is it like this?:

1. set render states

2. set vertex format

3. load vertex buffers

3.1. create vertex buffer (lock buffer)

3.2. fill the buffer with array data

3.3. Copy array data and then unlock buffer.

4. Draw to scene

5. Present data

So do I create classes to load multiple models at step 3 before step 4?

Or does each model have to go through the process up to draw before present is called at step 5?

Help would be greatly appreciated!

If you get near a point, make it!
Advertisement

Not quite. You can think of DX11 application has having 3 distinct stages:

  • Load - in this stage you create all your state objects. Shaders, render states, resources, resource-views, vertex buffers, index buffers, constant buffers, etc.
    • This is stage where you load all you models and materials.
  • Rendering - the main rendering loop. this is the stage where you use the objects created in the load stage. In this stage you usually:
    • Set render states(depth state, rasterizer state, blend state).
    • Set viewport
    • Set and clear the render-target-view and depth-stencil-view.
    • Set shaders and shaders state
      • Samplers
      • Shader resource views
      • Constant buffer. In most cases, you map the CBs, fill them with data, unmap and bind them.
    • Set vertex and index buffer, input element layout, topology. Note that there's usually no reason to change the content of your VB/IB.
    • Draw.
  • Cleanup stage - release all the objects you created during load.

As you can see, the main rendering loop doesn't create anything, and besides the CBs doesn't use any dynamic buffers (there are exceptions, of course). This reduces API overhead and allows the driver to be more clever about optimizations it makes.

And unless I forgot something, this is DX11 in a nutshell.

Is short, you setup rendering states: render targets, render states, textures, buffers, other things, and then draw. After that you need to change only what changed.

So lets say if you have 100 different models that use same textures/everything your loop would look like (pseudocode):


context->SetShader()
context->SetIndexBuffer() // assuming index buffer is identical
context->SetVertexFormat()
context->SetRenderTarget()
for(...) {
    context->SetVertexBuffer()
    context->Draw()
}

nice one, thanks for clearing that up.

If you get near a point, make it!

Okay one more lol, getting lost in how to implement what I need using derived classes.

So I can lay it out like this then:

WinMain -> calls AssetsClass;

during windows message check:

calls AssetsClass->Update();

AssetsClass->Render();

DirectxBaseInitialization (class)

virtual Render();

virtual Update();

AssetsClass : public DirectxBaseInitialization

virtual Update();

Then I can wrap all my code in the following classes Sprites, Font's & 3Dmodels. All 'public DirectxBaseInitialization'.

Then it all waterfalls back down the pipeline to the render call that is called by AssetsClass.

Or is that barking up the wrong tree?

If you get near a point, make it!

would I have to make DirectxBaseInitialization & AssetsClass's Render() function a pure virtual one to avoid it calling wrong?

If you get near a point, make it!

Okay I've gone away and RTFM a bit more,

I'm to the point where:

  • I've tied object creation down to the Vertex buffer & Index buffer in initialization
  • Declaration of the objects world Scale * rotation * translation in updating your scene
  • And drawing the object using the loaded textures, texture samplers & the vertex shader buffer in the DrawScene stage

I'm currently trying to encapsulate object creation (cubes) into a vector, problem is it's failing at runtime due to the CubesClass containing XMMATRIX variables.

How do I get round this? and why wont Vector allow a class containing them?

If you get near a point, make it!

problem is it's failing at runtime due to the CubesClass containing XMMATRIX variables.

No it’s not.

why wont Vector allow a class containing them?

It does.

How do I get round this?

Better show some code and provide more information.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

#ifndef _C_MY_OBJECT_H_
#define _C_MY_OBJECT_H_

#include <xnamath.h>

class cMyObject
{
public:
    cMyObject() :    posX(0.0f),
                    posY(0.0f),
                    posZ(0.0f),
                    rot(0.0f),
                    scaleMod(0.3f),
                    scaleFull(false) {};
    ~cMyObject() {};

    //void DeclareMyObject(float rotPassed, float posXnew, float posYnew, float posZnew)
    void DeclareMyObject(    float newScale,
                            float rotIn,
                            float posXnew,
                            float posYnew,
                            float posZnew )
    {
        currCubeWorldMat = XMMatrixIdentity();                                            //Reset current cubes coords

        Scale = XMMatrixScaling( newScale, newScale, newScale );

        XMVECTOR rotaxis = XMVectorSet( 0.0f, 0.0f, 1.0f, 0.0f );                    //Define objects world space matrix
        Rotation = XMMatrixRotationAxis( rotaxis, rotIn );
        Translation = XMMatrixTranslation( posXnew, posYnew, posZnew );

        //SRT scale, rot, translation
        currCubeWorldMat = Scale * Rotation * Translation;                                //Set cube1's world space using the transformations
    }

    XMMATRIX ReturnWorldMatrix() { return currCubeWorldMat; }

    /*
    void DrawMyObject(    ID3D11DeviceContext* d3d11DevCon,
                            XMMATRIX& WVP,
                            cbPerObject& cbPerObjectBuffer,
                            cbPerObject& cbPerObj,
                            ID3D11ShaderResourceView* TextureRef,
                            ID3D11SamplerState* TexSamplerRef,
                            XMMATRIX& camView,
                            XMMATRIX& camProjection)
    {
        WVP = currCubeWorldMat * camView * camProjection;
        cbPerObj.WVP = XMMatrixTranspose(WVP);
        d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0 );
        d3d11DevCon->VSSetConstantBuffers( 0, 1, &cbPerObjectBuffer );
        d3d11DevCon->PSSetShaderResources( 0, 1, &TextureRef );
        d3d11DevCon->PSSetSamplers( 0, 1, &TexSamplerRef );
    
        //Draw the cube
        d3d11DevCon->DrawIndexed( 36, 0, 0 );
    }
    */

private:
    XMMATRIX    currCubeWorldMat;

    XMMATRIX    Scale,
                Rotation,
                Translation;

    float        posX,
                posY,
                posZ,
                rot,
                scaleMod;

    bool        scaleFull;
};

#endif

//declarations at the top of main.cpp

std::vector<cMyObject> vCubes;

in the main update function

void UpdateScene()
{
    float newX = 0.0f;

    for(int i = 0; i < 3; i++)
    {
        vCubes.push_back( cMyObject( ) );
        vCubes[i].DeclareMyObject( newX, 0.0f, 0.0f );
        newX += 0.3f;
    }
}

in the drawscene function when I swap to this function i get the following error:

1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(870): error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
1> main.cpp(103) : see reference to class template instantiation 'std::vector<_Ty>' being compiled

for(int i = 0; i < 3; i++)
    {
        WVP = vCubes[i].ReturnWorldMatrix() * camView * camProjection;
        cbPerObj.WVP = XMMatrixTranspose(WVP);
        d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0 );
        d3d11DevCon->VSSetConstantBuffers( 0, 1, &cbPerObjectBuffer );
        d3d11DevCon->PSSetShaderResources( 0, 1, &CubesTexture );
        d3d11DevCon->PSSetSamplers( 0, 1, &CubesTexSamplerState );

        //Draw the cube
        d3d11DevCon->DrawIndexed( 36, 0, 0 );
    }

The code works fine if I split up the variables into seperate calls eg:

//initial declarations
cMyObject object1;
cMyObject object2;
cMyObject object3;
 
//in the update scene
object1.DeclareMyObject( scaleMod, rot, -2.0f, 0.0f, 0.0f );
object2.DeclareMyObject( scaleMod, rot, 0.0f, 3.0f, 2.0f );
object3.DeclareMyObject( scaleMod, rot, 4.0f, 1.0f, 0.0f );
 
//in the draw call
WVP = object1.ReturnWorldMatrix() * camView * camProjection;
    cbPerObj.WVP = XMMatrixTranspose(WVP);
    d3d11DevCon->UpdateSubresource( cbPerObjectBuffer, 0, NULL, &cbPerObj, 0, 0 );
    d3d11DevCon->VSSetConstantBuffers( 0, 1, &cbPerObjectBuffer );
    d3d11DevCon->PSSetShaderResources( 0, 1, &CubesTexture2 );
    d3d11DevCon->PSSetSamplers( 0, 1, &CubesTexSamplerState2 );
   
    //Draw the cube
    d3d11DevCon->DrawIndexed( 36, 0, 0 );
//code repeated with 2/3 etc
If you get near a point, make it!

I was trying to implement:

object1.DrawMyObject( d3d11DevCon, WVP, cbPerObjectBuffer, cbPerObj, CubesTexture2, CubesTexSamplerState2, camView, camProjection );

But that does the same so I seperated it from the class to try identify where the error was.

If you get near a point, make it!

This topic is closed to new replies.

Advertisement