⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mgcsoftrenderer.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#include "MgcSoftRenderer.h"

MgcImplementRTTI(MgcSoftRenderer,MgcGPRenderer);
MgcImplementStream(MgcSoftRenderer);

//---------------------------------------------------------------------------
MgcSoftRenderer::MgcSoftRenderer (HWND hWnd, int iWidth, int iHeight)
    :
    MgcGPRenderer(iWidth,iHeight)
{
    // memory is managed by a DIB section
    m_hWnd = hWnd;
    m_hWindowDC = GetDC(m_hWnd);
    m_hMemoryDC = CreateCompatibleDC(m_hWindowDC);

    // create the back buffer (16-bit RGB in format 1555)
    int iLength = sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD*);
    char* acBitMapInfo = new char[iLength];
    memset(acBitMapInfo,0,iLength);
    BITMAPINFOHEADER& bmih = *(BITMAPINFOHEADER*) acBitMapInfo;
    bmih.biSize = sizeof(BITMAPINFOHEADER);
    bmih.biWidth = m_iWidth;
    bmih.biHeight = -m_iHeight;
    bmih.biPlanes = 1;
    bmih.biBitCount = 16;
    bmih.biCompression = BI_RGB;
    bmih.biSizeImage = m_iQuantity;
    bmih.biXPelsPerMeter = 0;
    bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;

    m_hBufferBitmap = CreateDIBSection(m_hMemoryDC,
        (CONST BITMAPINFO *) acBitMapInfo, DIB_RGB_COLORS,
        (void**) &m_akBuffer, NULL, 0);

    delete[] acBitMapInfo;

    // conversion from MgcColor to MgcSoftColor
    m_kBackgroundSoftColor = m_kBackgroundColor;

    ClearBackBuffer();
    SelectObject(m_hMemoryDC,m_hBufferBitmap);

    // depth buffer
    m_ausZBuffer = new unsigned short[m_iQuantity];
    ClearZBuffer();
}
//---------------------------------------------------------------------------
MgcSoftRenderer::MgcSoftRenderer ()
{
}
//---------------------------------------------------------------------------
MgcSoftRenderer::~MgcSoftRenderer ()
{
    DeleteObject(m_hBufferBitmap);
    DeleteDC(m_hMemoryDC);
    ReleaseDC(m_hWnd,m_hWindowDC);
    delete[] m_ausZBuffer;
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::SetBackgroundColor (const MgcColor& rkColor)
{
    MgcGPRenderer::SetBackgroundColor(rkColor);
    m_kBackgroundSoftColor = rkColor;
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::ClearBackBuffer ()
{
    // TO DO.  Allow clear of only the viewport region.

    // Fast clear, about 1.5 times faster than the loop
    // for (int i = 0; i < m_iQuantity; i++)
    //     m_akBuffer[i] = m_kBackgroundSoftColor;

    int iQuantity = m_iQuantity;

    __asm
    {
        mov ebx, this
        xor eax, eax
        mov	ax,  [ebx]this.m_kBackgroundSoftColor
        mov cx,  ax
        shl ecx, 16
        or  eax, ecx
        mov ecx, iQuantity
        shr ecx, 1
        mov edi, [ebx]this.m_akBuffer
        rep stosd
    }
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::DisplayBackBuffer ()
{
    // blit bitmap from memory to screen
    BitBlt(m_hWindowDC,0,0,m_iWidth,m_iHeight,m_hMemoryDC,0,0,SRCCOPY);
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::ClearZBuffer ()
{
    // TO DO.  Allow clear of only the viewport region.

    memset(m_ausZBuffer,0xFF,m_iQuantity*sizeof(unsigned short));
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::ClearBuffers ()
{
    // TO DO.  Allow clear of only the viewport region.

    ClearBackBuffer();
    ClearZBuffer();
}
//---------------------------------------------------------------------------
int MgcSoftRenderer::GetRasterizerIndex ()
{
    // bit 0 = color
    // bit 1 = texture
    // bit 2 = perspective correction (bit 1 must be set)
    // bit 3 = depth buffer
    // bit 4 = 1-bit alpha blending
    int iIndex = 0;

    if ( m_kMesh.HasColors() )
        iIndex |= 1;

    if ( m_pkTextureState->GetQuantity() > 0 && m_kMesh.HasTextures() )
    {
        MgcTexture* pkTexture = m_pkTextureState->Get(0);
        assert( pkTexture );
        MgcImage* pkImage = pkTexture->GetImage();
        assert( pkImage && pkImage->GetType() == MgcImage::IT_RGBA5551 );

        iIndex |= 2;

        int iXSize = (int) pkImage->GetWidth();
        int iYSize = (int) pkImage->GetHeight();
        MgcSoftColor* akColor = (MgcSoftColor*) pkImage->GetData();
        bool bXClamp, bYClamp;
        switch ( pkTexture->Wrap() )
        {
            case MgcTexture::WM_CLAMP_S_CLAMP_T:
                bXClamp = true;
                bYClamp = true;
                break;
            case MgcTexture::WM_CLAMP_S_WRAP_T:
                bXClamp = true;
                bYClamp = false;
                break;
            case MgcTexture::WM_WRAP_S_CLAMP_T:
                bXClamp = false;
                bYClamp = true;
                break;
            case MgcTexture::WM_WRAP_S_WRAP_T:
                bXClamp = false;
                bYClamp = false;
                break;
        }

        m_kImage.Set(iXSize,iYSize,akColor,bXClamp,bYClamp);

        if ( pkTexture->Correction() == MgcTexture::CM_PERSPECTIVE )
            iIndex |= 4;
    }

    // TO DO.  The renderer ignores the members of the MgcAlphaState and the
    // MgcZBufferState objects.  The depth buffer is always tested and
    // written when necessary.  The comparison function is 'less than or
    // equal to'.  Alpha testing is ignored.

    if ( ZBufferActive() )
        iIndex |= 8;

    if ( AlphaBlendActive() )
        iIndex |= 16;

    return iIndex;
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::RasterizeEdges ()
{
    m_oERasterizer = ms_aoERasterizer[GetRasterizerIndex()];

    for (unsigned int uiE = 0; uiE < m_kMesh.GetEdgesUsed(); uiE++)
    {
        if ( m_kMesh.GetEdgeVisible(uiE) )
        {
            MgcGPTriMesh::EdgeRecord& rkEdge = m_kMesh.Edge(uiE);
            unsigned int uiV0 = rkEdge.Vertex(0);
            unsigned int uiV1 = rkEdge.Vertex(1);
            (this->*m_oERasterizer)(uiV0,uiV1);
        }
    }
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::RasterizeTriangles ()
{
    m_oTRasterizer = ms_aoTRasterizer[GetRasterizerIndex()];

    for (unsigned int uiT = 0; uiT < m_kMesh.GetTrianglesUsed(); uiT++)
    {
        if ( m_kMesh.GetTriangleVisible(uiT) )
        {
            MgcGPTriMesh::TriangleRecord& rkTri = m_kMesh.Triangle(uiT);
            unsigned int uiV0 = rkTri.Vertex(0);
            unsigned int uiV1 = rkTri.Vertex(1);
            unsigned int uiV2 = rkTri.Vertex(2);
            (this->*m_oTRasterizer)(uiV0,uiV1,uiV2);
        }
    }
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::DrawEdgeNULL (unsigned int, unsigned int)
{
    // Rasterizer not possible or not implemented.  This stub could also be
    // used for statistics gathering and profiling.
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::DrawTriNULL (unsigned int, unsigned int, unsigned int)
{
    // Rasterizer not possible or not implemented.  This stub could also be
    // used for statistics gathering and profiling.
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcSoftRenderer::Factory (MgcStream& rkStream)
{
    MgcSoftRenderer* pkObject = new MgcSoftRenderer;
    MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcGPRenderer::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcGPRenderer::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcSoftRenderer::Register (MgcStream& rkStream)
{
    return MgcGPRenderer::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcSoftRenderer::Save (MgcStream& rkStream)
{
    MgcGPRenderer::Save(rkStream);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -