How to use Scene class?

Dec 23, 2014 at 8:12 PM
I'm trying to use Scene class as well as Actor, Camera etc. to setup the virtual scene. I get sample projects running correctly, but failed to do it on my own. The code I wrote is to render a green triangle with just vertex and pixel shader, here is the code:
////////////////////////
// header
////////////////////////
#pragma once
#include "Application.h"
#include "Win32RenderWindow.h"
#include "RendererDX11.h"

#include "Actor.h"
#include "ViewPerspective.h"

#include "GeometryActor.h"

#include "Camera.h"
#include "Scene.h"

using namespace Glyph3;

class base_scene : public Application
{
public:
    base_scene();

public:
    virtual void Initialize();
    virtual void Update();
    virtual void Shutdown();

    virtual bool ConfigureEngineComponents();
    virtual void ShutdownEngineComponents();
    virtual void TakeScreenShot();

    virtual std::wstring GetName();

    RendererDX11*           m_pRenderer11;
    Win32RenderWindow *     m_pWindow;

    int                     m_iSwapChain;
    ResourcePtr             m_RenderTarget;
    ResourcePtr             m_DepthTarget;

    ResourcePtr             m_pVertexBuffer;
    int                     m_VertexLayout;
    ResourcePtr             m_pIndexBuffer;
    RenderEffectDX11        m_Effect;

    int                     m_iViewPort;

    ViewPerspective*        m_pRenderView;
    Actor*                  m_pActor;
    Entity3D*               m_pEntity;

    MaterialPtr             m_pMaterial;
    Vector4f                m_TessParams;

    GeometryPtr             m_pGeometry;
    Camera*                 m_pCamera;

    GeometryActor*          m_pGeometryActor;
};

////////////////////////
// implementation
////////////////////////
#include "baseScene.h"
#include "Log.h"

#include <sstream>
#include <DirectXMath.h>

#include "EventManager.h"
#include "EvtFrameStart.h"
#include "EvtErrorMessage.h"

#include "PipelineManagerDX11.h"

#include "BufferConfigDX11.h"
#include "DepthStencilStateConfigDX11.h"
#include "RasterizerStateConfigDX11.h"
#include "BlendStateConfigDX11.h"
#include "SwapChainConfigDX11.h"
#include "Texture2dConfigDX11.h"

#include "GeometryLoaderDX11.h"
#include "MaterialGeneratorDX11.h"

using namespace Glyph3;

base_scene AppInstance;

base_scene::base_scene()
{}

bool base_scene::ConfigureEngineComponents()
{
    // window size
    int width = 640;
    int height = 480;

    // initialize render window
    m_pWindow = new Win32RenderWindow();
    m_pWindow->SetPosition(100, 100);
    m_pWindow->SetSize(width, height);
    m_pWindow->SetCaption(GetName());
    m_pWindow->Initialize(this);

    // initialize renderer
    m_pRenderer11 = new RendererDX11();

    // create renderer and initialize with only hardware level
    if (!m_pRenderer11->Initialize(D3D_DRIVER_TYPE_HARDWARE, D3D_FEATURE_LEVEL_11_0)) {
        Log::Get().Write(L"Failed to create hardware device");
        return false;
    }

    // create a swap chain
    SwapChainConfigDX11 Config;
    Config.SetWidth(m_pWindow->GetWidth());
    Config.SetHeight(m_pWindow->GetHeight());
    Config.SetOutputWindow(m_pWindow->GetHandle());
    m_iSwapChain = m_pRenderer11->CreateSwapChain(&Config);
    m_pWindow->SetSwapChain(m_iSwapChain);

    // keep a copy of the render target
    m_RenderTarget = m_pRenderer11->GetSwapChainResource(m_iSwapChain);

    // create a depth buffer
    Texture2dConfigDX11 depthConfig;
    depthConfig.SetDepthBuffer(width, height);
    m_DepthTarget = m_pRenderer11->CreateTexture2D(&depthConfig, 0);

    // bind the swap chain, render target and the depth buffer
    //PipelineManagerDX11 *pipelineMgr = m_pRenderer11->pImmPipeline;
    m_pRenderer11->pImmPipeline->ClearRenderTargets();
    m_pRenderer11->pImmPipeline->OutputMergerStage.DesiredState.RenderTargetViews.SetState(
        0, m_RenderTarget->m_iResourceRTV);
    m_pRenderer11->pImmPipeline->OutputMergerStage.DesiredState.DepthTargetViews.SetState(
        m_DepthTarget->m_iResourceDSV);
    m_pRenderer11->pImmPipeline->ApplyRenderTargets();

    // initialize shaders
    m_Effect.SetVertexShader(m_pRenderer11->LoadShader(VERTEX_SHADER,
        std::wstring(L"Tutorial04.hlsl"),
        std::wstring(L"VSMain"),
        std::wstring(L"vs_4_0"),
        true));

    m_Effect.SetPixelShader(m_pRenderer11->LoadShader(PIXEL_SHADER,
        std::wstring(L"Tutorial04.hlsl"),
        std::wstring(L"PSMain"),
        std::wstring(L"ps_4_0"),
        true));

    DepthStencilStateConfigDX11 dsConfig;
    int iDepthStencilState = m_pRenderer11->CreateDepthStencilState(&dsConfig);
    if (iDepthStencilState == -1) {
        Log::Get().Write(L"Failed to create light depth stencil state");
        assert(false);
    }

    BlendStateConfigDX11 blendConfig;
    int iBlendState = m_pRenderer11->CreateBlendState(&blendConfig);
    if (iBlendState == -1) {
        Log::Get().Write(L"Failed to create light blend state");
        assert(false);
    }

    RasterizerStateConfigDX11 rsConfig;
    rsConfig.CullMode = D3D11_CULL_BACK;
    int iRasterizerState = m_pRenderer11->CreateRasterizerState(&rsConfig);
    if (iRasterizerState == -1) {
        Log::Get().Write(L"Failed to create rasterizer state");
        assert(false);
    }

    m_Effect.m_iBlendState = iBlendState;
    m_Effect.m_iDepthStencilState = iDepthStencilState;
    m_Effect.m_iRasterizerState = iRasterizerState;
    m_Effect.m_uStencilRef = iDepthStencilState;

    // create viewport
    D3D11_VIEWPORT viewport;
    viewport.Width = static_cast<float>(width);
    viewport.Height = static_cast<float>(height);
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;

    m_iViewPort = m_pRenderer11->CreateViewPort(viewport);
    m_pRenderer11->pImmPipeline->RasterizerStage.DesiredState.ViewportCount.SetState(1);
    m_pRenderer11->pImmPipeline->RasterizerStage.DesiredState.Viewports.SetState(0, m_iViewPort);

    //bool bCurrentState = m_pRenderer11->MultiThreadingConfig.GetConfiguration();
    m_pRenderer11->MultiThreadingConfig.SetConfiguration(false);
    return true;
}

void base_scene::ShutdownEngineComponents()
{
    if (m_pRenderer11)
    {
        m_pRenderer11->Shutdown();
        delete m_pRenderer11;
    }

    if (m_pWindow)
    {
        m_pWindow->Shutdown();
        delete m_pWindow;
    }
}

void base_scene::Initialize()
{
    // create the geometry (one triangle)
    m_pGeometry = GeometryPtr(new GeometryDX11());
    if (m_pGeometry == NULL) {
        EventManager::Get()->ProcessEvent(EvtErrorMessagePtr(new EvtErrorMessage(std::wstring(
            L"Attempted to generate a full-screen quad on null geometry object!"))));
        return;
    }

    VertexElementDX11* vPos = new VertexElementDX11(3, 3);      // three-components and three vertex
    vPos->m_SemanticName = "POSITION";
    vPos->m_uiSemanticIndex = 0;
    vPos->m_Format = DXGI_FORMAT_R32G32B32_FLOAT;
    vPos->m_uiInputSlot = 0;
    vPos->m_uiAlignedByteOffset = 0;
    vPos->m_InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    vPos->m_uiInstanceDataStepRate = 0;

    VertexElementDX11* vCol = new VertexElementDX11(4, 3);
    vCol->m_SemanticName = "COLOR";
    vCol->m_uiSemanticIndex = 0;
    vCol->m_Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
    vCol->m_uiInputSlot = 0;
    vCol->m_uiAlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
    vCol->m_InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    vCol->m_uiInstanceDataStepRate = 0;

    Vector3f* pPos = vPos->Get3f(0);
    Vector4f* pCol = vCol->Get4f(0);

    pPos[0] = Vector3f(-1.0f, -1.0f, 0.0f);
    pPos[1] = Vector3f(0.0f, 1.0f, 0.0f);
    pPos[2] = Vector3f(1.0f, -1.0f, 0.0f);

    Vector4f col_green = Vector4f(0.0f, 1.0f, 0.0f, 1.0f);
    pCol[0] = pCol[1] = pCol[2] = col_green;

    TriangleIndices face;
    m_pGeometry->AddElement(vPos);
    m_pGeometry->AddElement(vCol);
    face = TriangleIndices(0, 1, 2);
    m_pGeometry->AddFace(face);

    m_pGeometry->GenerateInputLayout(m_Effect.GetVertexShader());
    m_pGeometry->LoadToBuffers();

    // create the camera
    m_pCamera = new Camera();
    m_pCamera->Spatial().SetTranslation(Vector3f(0.0f, 0.0f, -5.0f));
    m_pRenderView = new ViewPerspective(*m_pRenderer11, m_RenderTarget, m_DepthTarget);
    m_pRenderView->SetBackColor(Vector4f(0.2f, 0.2f, 0.2f, 1.0f));
    m_pCamera->SetCameraView(m_pRenderView);
    m_pCamera->SetProjectionParams(0.1f, 100.0f, 640.0f / 320.0f, static_cast<float>(GLYPH_PI) / 2.0f);

    m_pEntity = new Entity3D();
    m_pEntity->Visual.SetGeometry(m_pGeometry);
    m_pEntity->Visual.SetMaterial(m_pMaterial);
    m_pEntity->Transform.Position() = Vector3f(0.0f, 0.0f, 0.0f);

    m_pActor = new Actor();
    m_pActor->GetNode()->AttachChild(m_pEntity);

    m_pScene->AddActor(m_pActor);
    m_pScene->AddCamera(m_pCamera);
    
}

void base_scene::Update()
{
    m_pTimer->Update();

    EvtManager.ProcessEvent(EvtFrameStartPtr(new EvtFrameStart(m_pTimer->Elapsed())));

    // Update the scene, and then render all cameras within the scene.
    m_pScene->Update(m_pTimer->Elapsed());
    m_pScene->Render(m_pRenderer11);

    // Present the results of the rendering to the output window.

    m_pRenderer11->Present(m_pWindow->GetHandle(), m_pWindow->GetSwapChain());
}

void base_scene::Shutdown()
{
    SAFE_DELETE(m_pEntity);

    std::wstringstream out;
    out << L"Max FPS: " << m_pTimer->MaxFramerate();
    Log::Get().Write(out.str());
}

void base_scene::TakeScreenShot()
{
    if (m_bSaveScreenshot)
    {
        m_bSaveScreenshot = false;
        m_pRenderer11->pImmPipeline->SaveTextureScreenShot(0, GetName());
    }
}

std::wstring base_scene::GetName()
{
    return(std::wstring(L"camera and scene"));
}
It compiles and runs (the shader works too), but all I can see is the gray background. What's the problem? Thanks !
Coordinator
Dec 30, 2014 at 12:31 PM
This looks more like an application subclass than a scene subclass - are you mixing the two ideas perhaps?

In general, there are tons of different things that can be happening in a graphical application that might make the rendering not work properly. There is the setup side, which is what you are suspecting here. But then there is also the pipeline configuration (i.e. if your triangles are backwards, they will be culled!), it could be that your actor is situated at (0,0,0) and so is your camera, etc... There can be lots of things going on.

Can you please take a look at the Graphics Debugger in Visual Studio? That will help you to dissect all of the actions that are being taken in a frame, and you can work backwards from there to diagnose what is going on.
Marked as answer by wxz on 12/30/2014 at 11:37 AM
Dec 30, 2014 at 5:21 PM
ok, the problem was that the triangle is backwards due to incorrect index order. I didn't intend to subclass Scene, just want to use it as is. The main problem for me is how to add geometries into the scene so that it will be rendered properly by just calling something like:
m_pScene->Update(m_pTimer->Elapsed());
The part of the code that create the GeometryDX11 object was mimicking GeometryGeneratorDX11::GenerateFullScreenQuad(). Thanks for bringing up Graphics Debugger, looks like a great tool !
Marked as answer by wxz on 12/30/2014 at 11:37 AM
Coordinator
Dec 30, 2014 at 7:49 PM
I see better what you are looking for now. The basic way is to create individual Actor instances, and add them to the scene with the AddActor method. If you look at the sample applications, they show the general usage (check out Application and RenderApplication as the primary base classes). Note that the AddActor method will take ownership of the pointer, and will delete the actors on exit. This works with manually configured Actor instances, as well as the many other subclasses of Actor (i.e. GeometryActor, SkyboxActor, etc...). Similar methods can be used for cameras, but in general you only should have one camera per scene.

Does that help out?
Dec 30, 2014 at 9:07 PM
I get the idea about how it works in general. The sample projects show how to use those various Actor subclasses. However, as soon as I want to do something even slightly different from the sample (e.g., the rotating box example in my other post), it's hard to get it right.
Coordinator
Dec 30, 2014 at 10:34 PM
Ok - I'll take a look in the other post and see if I can see what is wrong.