📄 mgcsoftrenderer.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 + -