top of page

​​Chap 27/100: Terrain Following 3D Mini MAP​

​

What I will Learn here?:

​On this tutorial ​​we will learn how to render a following 3D Mini-Map

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​

​Note:

Try to move to different map zones and check the respective Map and Mini-Map updates.

​​

​Let's check our current main source tree, except the LIBs:

​

Added source on White:

​​

​│   Applicationclass.cpp
│   Applicationclass.h
│   counter.h
│   main.cpp
│   main.h
│
├───camera
│       cameraClass.cpp
│       cameraClass.h
│       frustumClass.cpp
│       frustumClass.h
​

│       lightClass.cpp
│       lightClass.h
│       positionClass.cpp
│       positionClass.h

│       RenderFrustumClass.cpp
│       RenderFrustumClass.h
│
├───game
│       playerClass.cpp
│       playerClass.h​
│
​

├───graphics

│       renderTextureClass.cpp
│       renderTextureClass.h
│       spriteClass.cpp
│       spriteClass.h
​

│       textClass.cpp
│       textClass.h
│       textFontClass.cpp
│       textFontClass.h
│
├───input
│       inputClass.cpp
│       inputClass.h
│
├───loader
│       objModelV2Class.cpp
│       objModelV2Class.h
│
├───shader
│       shaderClass.cpp
│       shaderClass.h
│

├───system
│       dx11Class.cpp
│       dx11class.h
│       SystemClass.cpp
│       SystemClass.h
│       xml_loader.cpp
│       xml_loader.h​

│​
​└───terrain
        bitmapclass.cpp
        bitmapclass.h
        Minimapclass.cpp
        Minimapclass.h
        quadtreeClass.cpp
        quadtreeClass.h
        terrainClass.cpp
        terrainClass.h
        terrainManagerClass.cpp
        terrainManagerClass.h

​

​​​(main.h) ​

- Set for Chapter 27

​

 

​

​​​​​

​​​​​​​​​


 

Actually this Chappter has a great visual effect and small changes.​

I am only rendering the Mini-Map 20x per second to allow more CPU to main Map​ Rendering.​

Here I have Average Render Main Map 1700 / Second and 20 /Second Mini-Map

​

////////////////////////////////////////////////////////////////////////////////
// Filename: minimapclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "../main.h"

#if TUTORIAL_CHAP >= 15
#pragma warning( disable : 4706 ) // Disable warning C4706: assignment within conditional expression
#include "../applicationClass.h"
#include <d3dx11tex.h>

#include "minimapclass.h"


extern ApplicationClass* g_applicationClass;

//Initialize the three bitmaps to null in the class constructor.
MiniMapClass::MiniMapClass()
{
    m_Point = 0;
    m_Border = 0;
    m_MiniMapBitmap = 0;
    m_MiniMapTexture = 0;
   
#if TUTORIAL_CHAP >= 26
    m_MapBitmap = 0;
    m_MapTexture = 0;
#endif//

    for (UINT i=0; i < MAX_CLIENTS; i++)
    {
        m_pointLocationX[i] = 0;
        m_pointLocationY[i] = 0;
        m_pointRotation[i] = 0;

    #if TUTORIAL_CHAP >= 26
        m_pointMapLocationX[i] = 0;
        m_pointMapLocationY[i] = 0;
    #endif//
    }
}

MiniMapClass::~MiniMapClass()
{
    Shutdown();
}

bool MiniMapClass::Initialize(DX11Class* directX11, TerrainClass* m_Terrain_, float terrainWidth, float terrainHeight)
{    bool result;

    m_DirectX11 = directX11;
    m_Terrain = m_Terrain_;

//The Initialize function starts by storing the location of the mini-map, its size, the base view matrix for rendering, and the actual size of the terrain mesh.

    // Initialize the location of the mini-map on the screen.
    m_mapLocationX = g_ScreenWidth - 200;
    m_mapLocationY = 75;

    // Set the size of the mini-map:
    m_mapSizeX = 150.0f;
    m_mapSizeY = 150.0f;

    #if TUTORIAL_CHAP >= 26
    // Set the size of the main-map:
    m_mainMapSizeX = 1000.0f;
    m_mainMapSizeY = 1000.0f;
    #endif

    // Store the terrain size.
    m_terrainWidth = terrainWidth;
    m_terrainHeight = terrainHeight;

//Next we create the mini-map from the color map .dds file. Even thought the color map is 256x256 we have shrunk it down to 150x150 so that displaying it does not take up too much of the screen.

    // Create the mini-map bitmap object.
    m_MiniMapBitmap = NEW BitmapClass;
    if(!m_MiniMapBitmap){return false;}

    // Initialize the "mini-map" bitmap object.
    result = m_MiniMapBitmap->Initialize(directX11->m_device, g_ScreenWidth, g_ScreenHeight, L"Engine/data/water_tex04.jpg", (int)m_mapSizeX, (int)m_mapSizeY, 1.0f);
    if(!result)
    {
        MessageBox(g_hwnd, L"Could not initialize the mini-map object.", L"Error", MB_OK);
        return false;
    }

    #if TUTORIAL_CHAP >= 26
    // Initialize the "MAP" bitmap object.
    m_MapBitmap = NEW BitmapClass;
    if(!m_MapBitmap){return false;}

    // Initialize the mini-map bitmap object.
    result = m_MapBitmap->Initialize(directX11->m_device, g_ScreenWidth, g_ScreenHeight, L"Engine/data/mapFramev3.bmp", (int)m_mainMapSizeX, (int)m_mainMapSizeY, 1.0f); // Main Map Size
    if(!result)
    {
        MessageBox(g_hwnd, L"Could not initialize the mini-map object.", L"Error", MB_OK);
        return false;
    }
    #endif//

    // Load the border which will surround the mini-map so the edges are clearly defined.
    m_Border = NEW BitmapClass;
    if(!m_Border){return false;}

    // Initialize the border bitmap object.
    result = m_Border->Initialize(directX11->m_device, g_ScreenWidth, g_ScreenHeight, L"Engine/data/015MiniMap.png", 161, 161, 1.0f);
    if(!result)
    {
        MessageBox(g_hwnd, L"Could not initialize the border object.", L"Error", MB_OK);
        return false;
    }

//And finally we load the point indicator. It is a 3x3 green pixel that we will use and constantly update to show where the user currently is located on the mini-map.

    // Create the point bitmap object.
    m_Point = NEW BitmapClass;
    if(!m_Point){return false;}

    // Initialize the point bitmap object.
    result = m_Point->Initialize(directX11->m_device, g_ScreenWidth, g_ScreenHeight, L"Engine/data/015arrowv2.png", 15, 19, 1.0f);//015arrow.png
    if(!result)
    {
        MessageBox(g_hwnd, L"Could not initialize the point object.", L"Error", MB_OK);
        return false;
    }

    // Initialize the shader object:
    result = miniMapShader.Initialize(MY_SHADER_TEXTURE, directX11, L"engine/005Texture.hlsl", false/*NOGS*/, true/*2D*/);
    if(!result)
    {
        MessageBox(g_hwnd, L"Could not initialize the MiniMap Shader object.", L"Error", MB_OK);
        return false;
    }

    renderFrustumClass.Init(m_DirectX11, m_Terrain->m_terrainWidth, m_Terrain->m_terrainHeight);

    MyOutputDebugString( L"Minimap Class: Initialized\n" );
    return true;
}

//The Shutdown function releases the three bitmap objects that were used for rendering the mini-map elements.
void MiniMapClass::Shutdown()
{
    //public:
    SAFE_SHUTDOWN(m_MiniMapTexture);
    #if TUTORIAL_CHAP >= 26
    SAFE_SHUTDOWN(m_MapTexture);
    #endif//

    //private:
    miniMapShader.Shutdown();
    renderFrustumClass.Shutdown();

    SAFE_SHUTDOWN(m_Point);            // Release the point bitmap object.
    SAFE_SHUTDOWN(m_Border);        // Release the border bitmap object.
    SAFE_SHUTDOWN(m_MiniMapBitmap);    // Release the mini-map bitmap object.
   
    #if TUTORIAL_CHAP >= 26
    SAFE_SHUTDOWN(m_MapBitmap);
    #endif//
}

bool MiniMapClass::Render(ID3D11DeviceContext* deviceContext)
{    bool result;

    if (m_DirectX11->RenderfirstTime)
    {
        // Create the refraction render to texture object.
        IF_NOT_RETURN_FALSE (m_MiniMapTexture = NEW RenderTextureClass);
        if(!m_MiniMapTexture->Initialize(m_DirectX11, g_ScreenWidth, g_ScreenHeight))
            {MyMessageBox(L"Could not initialize the MiniMapTexture object.");return false;}

    #if TUTORIAL_CHAP >= 26
        // Create the refraction render to texture object.
        IF_NOT_RETURN_FALSE (m_MapTexture = NEW RenderTextureClass);
        if(!m_MapTexture->Initialize(m_DirectX11, g_ScreenWidth, g_ScreenHeight))
            {MyMessageBox(L"Could not initialize the MiniMapTexture object.");return false;}

         m_DirectX11->TurnOffAlphaBlending();
         RenderMapToTexture(deviceContext);
    #endif
    }

    static bool last_g_GOD_MODE = g_GOD_MODE;
    #if TUTORIAL_CHAP <= 26
    // - On god Mode
    // - On first frame after disable god mode (to clean blue frustrum)
    // - On first frame
    if (g_GOD_MODE || last_g_GOD_MODE != g_GOD_MODE || m_DirectX11->RenderfirstTime)
        RenderMiniMapToTexture(deviceContext);  // Render: 1st shot to mini-map or alwways on "god mode"

    #else
    //#if TUTORIAL_CHAP >= 27
    static unsigned long m_pingTime = timeGetTime();
    if(timeGetTime() >= (m_pingTime + 50)) //1 Second = 1000 ms
    {
        m_pingTime = timeGetTime();
        RenderMiniMapToTexture(deviceContext);  // Render: 1st shot to mini-map or alwways on "god mode"
    }
    #endif//

    last_g_GOD_MODE = g_GOD_MODE;

    #if TUTORIAL_CHAP >= 26
    if (g_game_state == GAME_MAP)
    {
        // Map may Changed...
        m_DirectX11->TurnOffAlphaBlending();
        RenderMapToTexture(deviceContext);
        return true; // If we are on main map dont render mini-map
    }
    #endif
   
#if defined (SCENE_MINIMAP)
    if (g_MINIMAP_ENABLED)
    {
        deviceContext->RSSetState(m_DirectX11->m_rasterStateCullNone[FILL_SOLID]); // RESET
        m_DirectX11->TurnOffAlphaBlending();

        //[1] Render the pre-rendered "mini-map" bitmap
        result = m_MiniMapBitmap->Render(deviceContext, m_mapLocationX+4, m_mapLocationY+4);
        if(!result)return false;
        miniMapShader.texture = m_MiniMapTexture->GetShaderResourceView();
        miniMapShader.Render(deviceContext, m_MiniMapBitmap->GetIndexCount(), g_identMatrix, g_viewMatrix2D, g_orthoMatrix);

        //[2] Render the "border" bitmap
        result = m_Border->Render(deviceContext, (m_mapLocationX - 2), (m_mapLocationY - 2));
        if(!result)return false;
        miniMapShader.texture = m_Border->GetTexture();
        miniMapShader.Render(deviceContext, m_Border->GetIndexCount(), g_identMatrix, g_viewMatrix2D, g_orthoMatrix);

        //Render the "arrow" bitmap for all players:
        m_DirectX11->TurnZBufferOn();
        m_DirectX11->TurnOnAlphaBlending();
        RenderMiniMapPlayers(deviceContext);
    }
#endif
   
    return true;
}

bool MiniMapClass::RenderMiniMapPlayers(ID3D11DeviceContext* deviceContext)
{
bool result;

    //[3] Render the "arrow" bitmap for all players:
    for (UINT i=0; i < MAX_CLIENTS; i++)
    {
        if (m_pointLocationX[i] != 0 || m_pointLocationY[i] != 0)
        {
            result = m_Point->RenderRotY(deviceContext, m_pointLocationX[i], m_pointLocationY[i]);
            if(!result)return false;

            D3DXMATRIXA16 worldMatrix = g_identMatrix;;
            D3DXMATRIXA16 m;
            D3DXMatrixRotationZ( &m, -m_pointRotation[i] * 0.0174532925f );    //0.0174532925f (PI / 180.0f): Convert degrees to radians.
            worldMatrix *= m;

            worldMatrix._41 = (float) -g_ScreenWidth/2 + m_Point->m_bitmapWidth/2 + m_pointLocationX[i];
            worldMatrix._42 = (float) g_ScreenHeight/2 - m_Point->m_bitmapHeight/2 - m_pointLocationY[i];
            worldMatrix._43 = -0.1f; //Make sure that arrow is on top of map

            // Render the point bitmap using the: miniMapShader
            miniMapShader.texture = m_Point->GetTexture();
            miniMapShader.Render(deviceContext, m_Point->GetIndexCount(), worldMatrix, g_viewMatrix2D, g_orthoMatrix);
        }
    }

    return true;
}

#if TUTORIAL_CHAP >= 26
bool MiniMapClass::RenderMapPlayers(ID3D11DeviceContext* deviceContext)
{
bool result;

    //[3] Render the "arrow" bitmap for all players:
    for (UINT i=0; i < MAX_CLIENTS; i++)
    {
        if (m_pointMapLocationX[i] != 0 || m_pointMapLocationY[i] != 0)
        {
            result = m_Point->RenderRotY(deviceContext, m_pointMapLocationX[i], m_pointMapLocationY[i]);
            if(!result)return false;

            D3DXMATRIXA16 worldMatrix = g_identMatrix;;
            D3DXMATRIXA16 m;
            D3DXMatrixRotationZ( &m, -m_pointRotation[i] * 0.0174532925f );    //0.0174532925f (PI / 180.0f): Convert degrees to radians.
            worldMatrix *= m;

            worldMatrix._41 = (float) -g_ScreenWidth/2 + m_Point->m_bitmapWidth/2 + m_pointMapLocationX[i];
            worldMatrix._42 = (float) g_ScreenHeight/2 - m_Point->m_bitmapHeight/2 - m_pointMapLocationY[i];
            worldMatrix._43 = -0.1f; //Make sure that arrow is on top of map

            // Render the point bitmap using the: miniMapShader
            miniMapShader.texture = m_Point->GetTexture();
            miniMapShader.Render(deviceContext, m_Point->GetIndexCount(), worldMatrix, g_viewMatrix2D, g_orthoMatrix);
        }
    }

    return true;
}

bool MiniMapClass::RenderMap(ID3D11DeviceContext* deviceContext) {
    bool result;

    //[1] Put the "mini-map" bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing.
    result = m_MapBitmap->Render(deviceContext, (g_ScreenWidth - m_MapBitmap->m_bitmapWidth)/2, (g_ScreenHeight - m_MapBitmap->m_bitmapHeight)/2);
    if(!result)return false;

    static D3DXMATRIXA16 worldMatrix = g_identMatrix;
    miniMapShader.texture = m_MapTexture->GetShaderResourceView();

    float scaleX = g_ScreenWidth / 1920.0f;
    float scaleY = g_ScreenHeight / 1080.0f;
    worldMatrix._11 = scaleX;
    worldMatrix._22 = scaleY;
    worldMatrix._33 = scaleY;

    miniMapShader.Render(deviceContext, m_MapBitmap->GetIndexCount(), worldMatrix, g_viewMatrix2D, g_orthoMatrix);

    //Render the "arrow" bitmap for all players:
    m_DirectX11->TurnZBufferOn();
    m_DirectX11->TurnOnAlphaBlending();
    RenderMapPlayers(deviceContext);

    return true;
}
#endif//

//The PositionUpdate function is used for updating where the 3x3 green pixel point indicator should be located on the mini-map.
//It converts the 3D float position of the camera on the terrain into a 2D position on the bitmap.
//It also makes sure the indicator never goes past the borders of the mini-map.
void MiniMapClass::PositionUpdate(int playerId, float positionX, float positionZ)
{
    float percentX, percentY;
    float percentMapX, percentMapY;

    // Ensure the point does not leave the minimap borders even if the camera goes past the terrain borders.
    if(positionX <= 0) {
        positionX = 0;
        return;
    }

    if(positionZ <= 0) {
        positionZ = 0;
        return;
    }

    if(positionX > m_terrainWidth)
        positionX = m_terrainWidth;

    if(positionZ > m_terrainHeight)
        positionZ = m_terrainHeight;

    // Calculate the position of the camera on the minimap in terms of percentage.
    #if TUTORIAL_CHAP <= 25
    percentX = positionX / m_terrainWidth;
    percentY = 1.0f - (positionZ / m_terrainHeight);
    #endif
    #if TUTORIAL_CHAP == 26
    percentX = positionX / m_terrainWidth;
    percentY = 1.0f - (positionZ / m_terrainHeight);
    #else
    percentX = 0.5f;
    percentY = 0.5f;
    #endif

    #if TUTORIAL_CHAP >= 26
    // Check which Quadrant we are:
    Qx = (int) (g_applicationClass->m_Camera.m_positionX / ((m_terrainWidth+1)/2));
    Qz = (int) (g_applicationClass->m_Camera.m_positionZ / ((m_terrainHeight+1)/2));
    percentMapX = (positionX-Qx*m_terrainWidth/2) / m_terrainWidth*2;
    percentMapY = 1.0f - ((positionZ-Qz*(m_terrainHeight/2)) / m_terrainHeight*2); //Note: *2 couse we are viewing a 256 of a big 512 map
    #endif

    // Determine the pixel location of the point on the Mini-Map:
    m_pointLocationX[playerId] = m_mapLocationX + (int)(percentX * m_mapSizeX); // Dont need rescale. always 150x150
    m_pointLocationY[playerId] = m_mapLocationY + (int)(percentY * m_mapSizeY);

    // Determine the pixel location of the point on the Main-Map:
    float scaleX = g_ScreenWidth / 1920.0f;
    float scaleY = g_ScreenHeight / 1080.0f;

    #if TUTORIAL_CHAP >= 26
    m_pointMapLocationX[playerId] = (int)((g_ScreenWidth - scaleX*m_MapBitmap->m_bitmapWidth)/2 + (int)(percentMapX * scaleX*m_mainMapSizeX));   // Re-Scale Map.
    m_pointMapLocationY[playerId] = (int)((g_ScreenHeight - scaleY*m_MapBitmap->m_bitmapHeight)/2 + (int)(percentMapY * scaleY*m_mainMapSizeY));
    #endif

    // Subtract one from the location to center the point on the mini-map according to the 3x3 point pixel image size.
    m_pointLocationX[playerId] -= 1;
    m_pointLocationY[playerId] -= 1;
}

bool MiniMapClass::RenderMiniMapToTexture(ID3D11DeviceContext* pContext)
{
    // Setup a clipping plane based on the height of the water to clip everything above it.
    static D3DXVECTOR4 clipPlane = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);

    //"worldMatrix:"
    D3DXMATRIX    worldMatrix = g_identMatrix;

    //"viewMatrix": SET Camera Roration and Position to 2D Render: TEXT and SPRITES
    CameraClass    m_Camera;
    m_Camera.SetRotation(+89.999f, 0, 0);

    #if TUTORIAL_CHAP <= 26
        /*       /
               /     |
            /a       | m_Terrain->m_terrainHeight/2
            --- h--- |
        Note:
            angle a = 21.8f (half of our view frustrum)
        */
        float h = ((float)(m_Terrain->m_terrainHeight/2)) / tan(21.8f * 0.0174532925f);
        m_Camera.SetPosition((float)m_Terrain->m_terrainWidth/2, h, (float)m_Terrain->m_terrainHeight/2);

    #else
        m_Camera.SetPosition(g_applicationClass->m_Camera.m_positionX, 100, g_applicationClass->m_Camera.m_positionZ);
    #endif//

   
    m_Camera.Render();
    m_Camera.GetViewMatrix(g_viewMatrix);

    //"projectionMatrix" Change the projection Matrix to our MINIMAP projection
    D3DXMATRIX    g_projectionMatrixAux = g_projectionMatrix;
    g_projectionMatrix = g_projectionMiniMapMatrix;

    //[1] Set the render target to be the refraction render to "texture"
    pContext->OMSetRenderTargets(1, &m_MiniMapTexture->m_renderTargetView, m_DirectX11->m_depthStencilView);

    //[3] Clear the MiniMapTexture
    m_MiniMapTexture->ClearRenderTarget(pContext, m_DirectX11->m_depthStencilView, 0.0f, 0.0f, 0.0f, 1.0f);

    //[4] RENDER: terrain and water into mini map texture:
    // -----------------------------------------------------------------
    // Terrain:
    #if TUTORIAL_CHAP >= 16
    m_Terrain->m_ShaderFog.fogStart = 1024;     // No fog...
    m_Terrain->m_ShaderFog.fogEnd = 2048;      // No fog...
    m_Terrain->m_ShaderFog.m_hasLight = true;
    m_Terrain->m_ShaderFog.m_isDay = true;
    #endif

    m_Terrain->Render(pContext, &g_projectionMatrix);

    #if TUTORIAL_CHAP >= 16
    m_Terrain->m_ShaderFog.m_hasLight = false;
    #endif

    // Infinite Water
    g_applicationClass->InfiniteFixedTerraniWater(true);

    // MiniFrustum 2D:
#if defined(_DEBUG)
    if (g_GOD_MODE) {
        pContext->RSSetState(m_DirectX11->m_rasterStateCullNone[FILL_SOLID]); // RESET
        renderFrustumClass.Render(g_applicationClass->m_Camera.m_positionX,
                                  1+g_applicationClass->m_Camera.m_positionY,
                                  g_applicationClass->m_Camera.m_positionZ,
                                  g_applicationClass->m_Camera.m_rotationY,
                                  g_applicationClass->m_Frustum.m_screenDepth);
    }
#endif

    #if TUTORIAL_CHAP >= 40 && defined (SCENE_WATER)
    g_applicationClass->m_WaterModel->m_WaterShader->waterOn = 0; // Enable AlphaBlend on Water
    g_applicationClass->m_WaterModel->m_WaterShader->clipPlane = clipPlane;   
    #endif

    //[5] Reset the render target back to the original back buffer and not the render to texture anymore.
    pContext->OMSetRenderTargets(1, &m_DirectX11->m_renderTargetView, m_DirectX11->m_depthStencilView);

    //[6] restore normal projection Matrix
    g_projectionMatrix = g_projectionMatrixAux;

    return true;
}

#if TUTORIAL_CHAP >= 26
bool MiniMapClass::RenderMapToTexture(ID3D11DeviceContext* pContext)
{
    // Setup a clipping plane based on the height of the water to clip everything above it.
    static D3DXVECTOR4 clipPlane = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);

    //"worldMatrix:"
    D3DXMATRIX    worldMatrix = g_identMatrix;

    //"viewMatrix": SET Camera Roration and Position to 2D Render: TEXT and SPRITES
    CameraClass    m_Camera;
    m_Camera.SetRotation(+89.999f, 0, 0);       
    /*       /
           /     |
        /a       | m_Terrain->m_terrainHeight/2
        --- h--- |
    Note:
        angle a = 21.8f (half of our view frustrum)
    */
    float h = ((float)(m_Terrain->m_terrainHeight/4)) / tan(21.8f * 0.0174532925f);
    m_Camera.SetPosition((float)m_Terrain->m_terrainWidth/4 + Qx*m_Terrain->m_terrainWidth/2, h,
                         (float)m_Terrain->m_terrainHeight/4 + Qz*m_Terrain->m_terrainHeight/2);            //Note: Work with 512x512: 4 x 256x256
    //m_Camera.SetPosition((float)(m_Terrain->m_terrainWidth)/2, h, (float)(m_Terrain->m_terrainHeight)/2); //Note: Work for 256x256

    m_Camera.Render();
    m_Camera.GetViewMatrix(g_viewMatrix);

    //"projectionMatrix" Change the projection Matrix to our MINIMAP projection
    D3DXMATRIX    g_projectionMatrixAux = g_projectionMatrix;
    g_projectionMatrix = g_projectionMiniMapMatrix;

    //[1] Set the render target to be the refraction render to "texture"
    pContext->OMSetRenderTargets(1, &m_MapTexture->m_renderTargetView, m_DirectX11->m_depthStencilView);

    //[3] Clear the refraction render to texture.
    m_MapTexture->ClearRenderTarget(pContext, m_DirectX11->m_depthStencilView, 1.0f, 1.0f, 1.0f, 0.0f);

    //[4] RENDER: terrain and water into mini map texture:
    // -----------------------------------------------------------------
    // Terrain:
    m_Terrain->m_ShaderFog.fogStart = 1024;     // No fog...
    m_Terrain->m_ShaderFog.fogEnd = 2048;      // No fog...
    m_Terrain->m_ShaderFog.m_hasLight = true;   // hasLight = true to render mini-map
    m_Terrain->m_ShaderFog.m_isDay = true;      // Always day on Main Map
    m_Terrain->Render(pContext, &g_projectionMatrix);  
    m_Terrain->m_ShaderFog.m_hasLight = false;  // hasLight = false to render main terrain (back normal...)

    // Infinite Water
    g_applicationClass->InfiniteFixedTerraniWater(true);

    //[5] Reset the render target back to the original back buffer and not the render to texture anymore.
    pContext->OMSetRenderTargets(1, &m_DirectX11->m_renderTargetView, m_DirectX11->m_depthStencilView);

    //[6] restore normal projection Matrix
    g_projectionMatrix = g_projectionMatrixAux;

    return true;
}
#endif//

#endif//

​​

​​​​​

​​​​​​​​​


​Project Code:

​

woma.no-ip.org/woma/WoMA_PartII_Chap27.zip

​

​What's next?

This is for now the Last Terrain Chapter, on the next Tutorial Part III we will cover the Elements of Nature.

Including a real time Weather Service.

bottom of page