Instancing not working correctly

Started by
2 comments, last by Sobe118 9 years, 11 months ago
I am attempting to just draw a few thousand instanced basic spheres that will move around in the scene. Also I need to eventually use both DrawIndexed and DrawIndexedInstanced or DrawInstanced, and beable to change each instances rotation as well but don't need to worry about that atm.
The main question is just how to get the instanced spheres to draw? Currently the instancing version of my program is drawing one flat sphere at position (0,0,0)
There are no compile or run time errors in the code it just doesn't work correctly. Below is what I think is the relevant code. Thanks!
Vertex.cpp


const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::PosNormal[6] = 
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"NORMAL",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"WORLD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    {"WORLD", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
    {"WORLD", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
    {"WORLD", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
};

#pragma endregion

#pragma region InputLayouts

ID3D11InputLayout* InputLayouts::PosNormal = 0;

void InputLayouts::InitAll(ID3D11Device* device)
{
    //
    // PosNormal
    //

    D3DX11_PASS_DESC passDesc;
    Effects::BasicFX->Light1Tech->GetPassByIndex(0)->GetDesc(&passDesc);
    HR(device->CreateInputLayout(InputLayoutDesc::PosNormal, 6, passDesc.pIAInputSignature, 
        passDesc.IAInputSignatureSize, &PosNormal));
}

void InputLayouts::DestroyAll()
{
    ReleaseCOM(PosNormal);
}

From Basic.fx file


cbuffer cbPerFrame
{
    DirectionalLight gDirLights[3];
    float3 gEyePosW;

    float  gFogStart;
    float  gFogRange;
    float4 gFogColor;
};

cbuffer cbPerObject
{
    float4x4 gWorld;
    float4x4 gWorldInvTranspose;
    float4x4 gWorldViewProj;
    float4x4 gTexTransform;
    Material gMaterial;
}; 

// Nonnumeric values cannot be added to a cbuffer.
Texture2D gDiffuseMap;

SamplerState samAnisotropic
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 4;

    AddressU = WRAP;
    AddressV = WRAP;
};
struct VertexIn
{
    float3 PosL    : POSITION;
    float3 NormalL : NORMAL;
    row_major float4x4 World  : WORLD;
    uint InstanceId : SV_InstanceID;
};

struct VertexOut
{
    float4 PosH    : SV_POSITION;
    float3 PosW    : POSITION;
    float3 NormalW : NORMAL;
};

VertexOut VS(VertexIn vin)
{
    VertexOut vout;

    // Transform to world space space.
    vout.PosW    = mul(float4(vin.PosL, 1.0f), vin.World).xyz;
    vout.NormalW = mul(vin.NormalL, (float3x3)vin.World);
        
    // Transform to homogeneous clip space.
    vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
    
    return vout;
}

Creating buffer instanced object's locations


    D3D11_BUFFER_DESC instBuffDesc; 
    ZeroMemory( &instBuffDesc, sizeof(instBuffDesc) );
    instBuffDesc.Usage = D3D11_USAGE_DEFAULT;
    instBuffDesc.ByteWidth = sizeof(InstancedData) * OBJECTCOUNT;
    instBuffDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    instBuffDesc.CPUAccessFlags = 0;
    instBuffDesc.MiscFlags = 0;
    HR(md3dDevice->CreateBuffer( &instBuffDesc, NULL, &segmentInstanceBuffer));

Updating buffer in UpdateScene()


        //Copy Data to buffers
        for(int i = 0; i < OBJECTCOUNT; ++i)
        {
            //XMStoreFloat3(&objVector[i], XMVectorSet(segList[i].loc[0], segList[i].loc[1], segList[i].loc[2], 0.0f));
            XMMATRIX sphereOffset = XMMatrixTranslation(segList[i].loc[0], segList[i].loc[1], segList[i].loc[2]);
            XMStoreFloat4x4(&objVector[i].World, sphereOffset);
        }
        md3dImmediateContext->UpdateSubresource( segmentInstanceBuffer, 0, NULL, &objVector, 0, 0);

Relevant code from the Draw (I think)


   UINT strides[2] = {sizeof(Vertex::PosNormal), sizeof(InstancedData)};
    UINT offsets[2] = {0,0};

        md3dImmediateContext->IASetInputLayout(InputLayouts::PosNormal);
        ID3D11Buffer* vbs[2] = {mSphereVB, segmentInstanceBuffer};
        md3dImmediateContext->IASetVertexBuffers(0, 2, vbs, strides, offsets);
        md3dImmediateContext->IASetIndexBuffer(mSphereIB, DXGI_FORMAT_R32_UINT, 0);

        world = XMLoadFloat4x4(&mSphereWorld);
        worldInvTranspose = MathHelper::InverseTranspose(world);

        Effects::BasicFX->SetWorld(world);
        Effects::BasicFX->SetWorldInvTranspose(worldInvTranspose);
        Effects::BasicFX->SetWorldViewProj(worldViewProj);
        Effects::BasicFX->SetMaterial(mSphereMat);

        activeTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
        md3dImmediateContext->DrawIndexedInstanced(mSphereIndexCount, OBJECTCOUNT, 0, 0, 0);

Let me know if there is any more code that I should show, Thanks!

Advertisement

You forgot to use the instance world matrix here:


 // Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);

It should be more like this:


 // Transform to homogeneous clip space.
vout.PosH = mul(float4(vout.PosW, 1.0f), gViewProj);
When I changed it to :

 // Transform to homogeneous clip space.
vout.PosH = mul(float4(vout.PosW, 1.0f), gViewProj);

I had the shape drawn everywhere (not a sphere any more, covered screen)

When I changed it to this :

// Transform to homogeneous clip space.
vout.PosH = mul(float4(vin.PosL, 1.0f), gViewProj);

It is no longer a flat, and looks like a normal sphere, but there is only one stationary.

I know for sure the location data is being created. I, cant seem to verify the information going to the Buffer (no symbol for the dll, and cant seem to download) but I dont think that's the issue.

Im confused why I lost reputation, but I still have a problem...

So if this is correct why does is mess up all my visuals?


vout.PosH = mul(float4(vout.PosW, 1.0f), gViewProj);

I just re did the project a bit to fix the issue.

solved

This topic is closed to new replies.

Advertisement