feat: complete native client rendering parity updates
This commit is contained in:
@@ -5,10 +5,15 @@
|
||||
#include "EterLib/StdAfx.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
inline std::atomic<std::uint64_t> mt_next_cpu_buffer_id{1};
|
||||
|
||||
struct MtCpuVertexBuffer : IDirect3DVertexBuffer8
|
||||
{
|
||||
const std::uint64_t id = mt_next_cpu_buffer_id.fetch_add(1, std::memory_order_relaxed);
|
||||
std::uint64_t revision = 0;
|
||||
std::vector<uint8_t> bytes;
|
||||
DWORD fvf = 0;
|
||||
|
||||
@@ -19,11 +24,13 @@ struct MtCpuVertexBuffer : IDirect3DVertexBuffer8
|
||||
*data = bytes.data() + offset;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT Unlock() override { return S_OK; }
|
||||
HRESULT Unlock() override { ++revision; return S_OK; }
|
||||
};
|
||||
|
||||
struct MtCpuIndexBuffer : IDirect3DIndexBuffer8
|
||||
{
|
||||
const std::uint64_t id = mt_next_cpu_buffer_id.fetch_add(1, std::memory_order_relaxed);
|
||||
std::uint64_t revision = 0;
|
||||
std::vector<uint8_t> bytes;
|
||||
D3DFORMAT format = D3DFMT_INDEX16;
|
||||
|
||||
@@ -34,7 +41,7 @@ struct MtCpuIndexBuffer : IDirect3DIndexBuffer8
|
||||
*data = bytes.data() + offset;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT Unlock() override { return S_OK; }
|
||||
HRESULT Unlock() override { ++revision; return S_OK; }
|
||||
};
|
||||
|
||||
// D3DXGetFVFVertexSize.
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
// Platform skeleton for EterLib/CullingManager.h (40250 EterLib/CullingManager.cpp), generated by platform_stub.py.
|
||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
||||
#include "EterLib/StdAfx.h"
|
||||
#include "EterLib/CullingManager.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
|
||||
CCullingManager::CCullingManager()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CCullingManager::~CCullingManager()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::RayTraceCallback(const Vector3d &, const Vector3d &, float, const Vector3d &, SpherePack *) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::VisibilityCallback(const Frustum &, SpherePack *, ViewState) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::RangeTestCallback(const Vector3d &, float, SpherePack *, ViewState) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::Reset() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::Update() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
// 40250 CullingManager.cpp:105. RenderGame calls it after SetPerspective; it hands the camera's view and
|
||||
// the projection to CStateManager for the scene.
|
||||
// PORT: BuildViewFrustum and m_Factory->FrustumTest follow in 40250; the sphere-pack culling (SphereLib)
|
||||
// is not ported, so every registered object stays visible.
|
||||
void CCullingManager::Process()
|
||||
{
|
||||
//DWORD time = ELTimer_GetMSec();
|
||||
//Frustum f;
|
||||
UpdateViewMatrix();
|
||||
UpdateProjMatrix();
|
||||
}
|
||||
|
||||
auto CCullingManager::FindRange(const Vector3d &, float) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::FindRay(const Vector3d &, const Vector3d &) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::FindRayDistance(const Vector3d &, const Vector3d &, float) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CCullingManager::Register(CGraphicObjectInstance *) -> CullingHandle
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<CullingHandle>();
|
||||
}
|
||||
|
||||
auto CCullingManager::Unregister(CullingHandle) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
@@ -98,6 +98,8 @@ int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int /
|
||||
D3DXMatrixIdentity(&ms_matProj);
|
||||
D3DXMatrixIdentity(&ms_matInverseView);
|
||||
D3DXMatrixIdentity(&ms_matInverseViewYAxis);
|
||||
D3DXMatrixIdentity(&ms_matWorld);
|
||||
D3DXMatrixIdentity(&ms_matWorldView);
|
||||
D3DXMatrixIdentity(&ms_matScreen0);
|
||||
D3DXMatrixIdentity(&ms_matScreen1);
|
||||
D3DXMatrixIdentity(&ms_matScreen2);
|
||||
|
||||
@@ -137,16 +137,22 @@ std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle)
|
||||
{
|
||||
if (!handle) return {};
|
||||
const auto* texture = static_cast<const IDirect3DTexture8*>(handle);
|
||||
std::lock_guard<std::mutex> lock(g_memory_mutex);
|
||||
if (const MemoryTexture* memory = live_memory_texture(texture))
|
||||
return "mem:" + std::to_string(memory->id) + "@" + std::to_string(memory->revision);
|
||||
const auto* file = static_cast<const FileTexture*>(texture);
|
||||
return g_file_textures.count(file) ? file->name : std::string();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_memory_mutex);
|
||||
if (const MemoryTexture* memory = live_memory_texture(texture))
|
||||
return "mem:" + std::to_string(memory->id) + "@" + std::to_string(memory->revision);
|
||||
const auto* file = static_cast<const FileTexture*>(texture);
|
||||
if (g_file_textures.count(file))
|
||||
return file->name;
|
||||
}
|
||||
return MtCpuTextureNameFromHandle(handle);
|
||||
}
|
||||
|
||||
bool UIRenderMemoryTexture(const std::string& name, UIMemoryTexture* out)
|
||||
{
|
||||
if (name.compare(0, 4, "mem:") != 0 || !out) return false;
|
||||
if (name.compare(0, 8, "mem:cpu_") == 0)
|
||||
return MtCpuMemoryTexture(name, out);
|
||||
const unsigned id = unsigned(std::strtoul(name.c_str() + 4, nullptr, 10));
|
||||
std::lock_guard<std::mutex> lock(g_memory_mutex);
|
||||
auto it = g_memory.find(id);
|
||||
|
||||
@@ -34,6 +34,7 @@ bool CGraphicIndexBuffer::Lock(void** pretIndices) const
|
||||
void CGraphicIndexBuffer::Unlock() const
|
||||
{
|
||||
assert(m_lpd3dIdxBuf!=NULL);
|
||||
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
|
||||
}
|
||||
|
||||
bool CGraphicIndexBuffer::Lock(void** pretIndices)
|
||||
@@ -47,6 +48,7 @@ bool CGraphicIndexBuffer::Lock(void** pretIndices)
|
||||
void CGraphicIndexBuffer::Unlock()
|
||||
{
|
||||
assert(m_lpd3dIdxBuf!=NULL);
|
||||
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
|
||||
}
|
||||
|
||||
bool CGraphicIndexBuffer::Copy(int bufSize, const void* srcIndices)
|
||||
@@ -54,6 +56,7 @@ bool CGraphicIndexBuffer::Copy(int bufSize, const void* srcIndices)
|
||||
assert(m_lpd3dIdxBuf!=NULL);
|
||||
|
||||
memcpy(index_bytes(m_lpd3dIdxBuf), srcIndices, bufSize);
|
||||
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -73,6 +76,7 @@ bool CGraphicIndexBuffer::Create(int faceCount, TFace* faces)
|
||||
dstIndices[1]=curFace->indices[1];
|
||||
dstIndices[2]=curFace->indices[2];
|
||||
}
|
||||
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "EterLib/StdAfx.h"
|
||||
#include "EterLib/GrpScreen.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
#include "EterLib/Camera.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
#include "UIRenderCommands.h"
|
||||
@@ -285,27 +286,75 @@ void CScreen::SetCursorPosition(int x, int y, int hres, int vres)
|
||||
ms_Ray.SetDirection(-ms_vtPickRayDir, 51200.0f);
|
||||
}
|
||||
|
||||
auto CScreen::GetCursorPosition(float *, float *, float *) -> bool
|
||||
auto CScreen::GetCursorPosition(float * px, float * py, float * pz) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
if (!GetCursorXYPosition(px, py)) return false;
|
||||
if (!GetCursorZPosition(pz)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto CScreen::GetCursorXYPosition(float *, float *) -> bool
|
||||
auto CScreen::GetCursorXYPosition(float * px, float * py) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye();
|
||||
|
||||
TPosition posVertices[4];
|
||||
posVertices[0] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y + 90000000.0f, 0.0f);
|
||||
posVertices[1] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y - 90000000.0f, 0.0f);
|
||||
posVertices[2] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y + 90000000.0f, 0.0f);
|
||||
posVertices[3] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y - 90000000.0f, 0.0f);
|
||||
|
||||
static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
|
||||
|
||||
float u, v, t;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir,
|
||||
posVertices[sc_awFillRectIndices[i * 3]],
|
||||
posVertices[sc_awFillRectIndices[i * 3 + 1]],
|
||||
posVertices[sc_awFillRectIndices[i * 3 + 2]],
|
||||
&u, &v, &t))
|
||||
{
|
||||
*px = u;
|
||||
*py = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto CScreen::GetCursorZPosition(float *) -> bool
|
||||
auto CScreen::GetCursorZPosition(float * pz) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye();
|
||||
|
||||
TPosition posVertices[4];
|
||||
posVertices[0] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z + 90000000.0f);
|
||||
posVertices[1] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z - 90000000.0f);
|
||||
posVertices[2] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z + 90000000.0f);
|
||||
posVertices[3] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z - 90000000.0f);
|
||||
|
||||
static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
|
||||
|
||||
float u, v, t;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir,
|
||||
posVertices[sc_awFillRectIndices[i * 3]],
|
||||
posVertices[sc_awFillRectIndices[i * 3 + 1]],
|
||||
posVertices[sc_awFillRectIndices[i * 3 + 2]],
|
||||
&u, &v, &t))
|
||||
{
|
||||
*pz = t;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto CScreen::GetPickingPosition(float, float *, float *, float *) -> void
|
||||
auto CScreen::GetPickingPosition(float t, float * x, float * y, float * z) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
*x = ms_vtPickRayOrig.x + ms_vtPickRayDir.x * t;
|
||||
*y = ms_vtPickRayOrig.y + ms_vtPickRayDir.y * t;
|
||||
*z = ms_vtPickRayOrig.z + ms_vtPickRayDir.z * t;
|
||||
}
|
||||
|
||||
// 40250 GrpScreen.cpp:749-779.
|
||||
@@ -313,7 +362,7 @@ void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pf
|
||||
{
|
||||
D3DXVECTOR3 Input(x, y, z);
|
||||
D3DXVECTOR3 Output;
|
||||
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld);
|
||||
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
|
||||
|
||||
*pfX = Output.x;
|
||||
*pfY = Output.y;
|
||||
@@ -323,7 +372,7 @@ void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pf
|
||||
{
|
||||
D3DXVECTOR3 Input(x, y, z);
|
||||
D3DXVECTOR3 Output;
|
||||
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld);
|
||||
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
|
||||
|
||||
*pfX = Output.x;
|
||||
*pfY = Output.y;
|
||||
@@ -334,7 +383,7 @@ void CScreen::UnprojectPosition(float x, float y, float z, float * pfX, float *
|
||||
{
|
||||
D3DXVECTOR3 Input(x, y, z);
|
||||
D3DXVECTOR3 Output;
|
||||
D3DXVec3Unproject(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matWorld);
|
||||
D3DXVec3Unproject(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
|
||||
|
||||
*pfX = Output.x;
|
||||
*pfY = Output.y;
|
||||
@@ -355,12 +404,24 @@ auto CScreen::RestoreDevice() -> BOOL
|
||||
|
||||
auto CScreen::BuildViewFrustum() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
CCamera* pkCamera = CCameraManager::Instance().GetCurrentCamera();
|
||||
if (!pkCamera)
|
||||
return;
|
||||
const D3DXVECTOR3& c_rv3Eye = pkCamera->GetEye();
|
||||
const D3DXVECTOR3& c_rv3View = pkCamera->GetView();
|
||||
auto vv = ms_matView * ms_matProj;
|
||||
ms_frustum.BuildViewFrustum2(
|
||||
vv,
|
||||
ms_fNearY,
|
||||
ms_fFarY,
|
||||
ms_fFieldOfView,
|
||||
ms_fAspect,
|
||||
c_rv3Eye, c_rv3View);
|
||||
}
|
||||
|
||||
auto CScreen::Identity() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity);
|
||||
}
|
||||
|
||||
decltype(CScreen::ms_diffuseColor) CScreen::ms_diffuseColor{};
|
||||
|
||||
@@ -49,6 +49,7 @@ bool CGraphicVertexBuffer::Unlock() const
|
||||
{
|
||||
if (!m_lpd3dVB)
|
||||
return false;
|
||||
static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->revision++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -83,6 +84,7 @@ bool CGraphicVertexBuffer::Unlock()
|
||||
{
|
||||
if (!m_lpd3dVB)
|
||||
return false;
|
||||
static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->revision++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,34 +35,43 @@ CInputKeyboard::~CInputKeyboard()
|
||||
|
||||
auto CInputKeyboard::InitializeKeyboard(HWND) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
ResetKeyboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
auto CInputKeyboard::UpdateKeyboard() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CInputKeyboard::ResetKeyboard() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
memset(ms_bPressedKey, 0, sizeof(ms_bPressedKey));
|
||||
memset(ms_diks, 0, sizeof(ms_diks));
|
||||
}
|
||||
|
||||
auto CInputKeyboard::IsPressed(int) -> bool
|
||||
auto CInputKeyboard::IsPressed(int iIndex) -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
if (iIndex >= 0 && iIndex < 256)
|
||||
return (ms_diks[iIndex] & 0x80) != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto CInputKeyboard::KeyDown(int) -> void
|
||||
auto CInputKeyboard::KeyDown(int iIndex) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (iIndex >= 0 && iIndex < 256)
|
||||
{
|
||||
ms_bPressedKey[iIndex] = true;
|
||||
ms_diks[iIndex] = (char)0x80;
|
||||
}
|
||||
}
|
||||
|
||||
auto CInputKeyboard::KeyUp(int) -> void
|
||||
auto CInputKeyboard::KeyUp(int iIndex) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (iIndex >= 0 && iIndex < 256)
|
||||
{
|
||||
ms_bPressedKey[iIndex] = false;
|
||||
ms_diks[iIndex] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
decltype(CInputKeyboard::ms_lpKeyboard) CInputKeyboard::ms_lpKeyboard{};
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace {
|
||||
std::mutex g_draws_mutex;
|
||||
std::vector<Render3DDraw> g_draws;
|
||||
int g_native_terrain_override = -1;
|
||||
|
||||
|
||||
struct VertexLayout {
|
||||
unsigned stride = 0;
|
||||
@@ -69,9 +74,8 @@ int format_bytes(D3DFORMAT format)
|
||||
}
|
||||
|
||||
// PORT: device-created resources live in CPU memory with D3D reference counting. Textures made by
|
||||
// CreateTexture (CTerrain's splat alpha maps and attribute marks, CSnowEnvironment's blur targets)
|
||||
// keep their mip levels as bytes; nothing samples them because terrain and offscreen passes are
|
||||
// drawn by the Godot side.
|
||||
// CreateTexture resources keep their mip levels as bytes. Terrain alpha maps and the character
|
||||
// shadow render target are sampled by the native renderer through MtCpuMemoryTexture.
|
||||
struct CpuTexture;
|
||||
|
||||
struct CpuSurface final : IDirect3DSurface8
|
||||
@@ -89,13 +93,32 @@ struct CpuSurface final : IDirect3DSurface8
|
||||
HRESULT UnlockRect() override { return S_OK; }
|
||||
};
|
||||
|
||||
struct CpuTexture;
|
||||
std::mutex g_cpu_tex_mutex;
|
||||
std::unordered_map<unsigned, CpuTexture*> g_cpu_textures;
|
||||
unsigned g_next_cpu_tex_id = 1;
|
||||
|
||||
struct CpuTexture final : IDirect3DTexture8
|
||||
{
|
||||
struct Level { D3DSURFACE_DESC desc; std::vector<uint8_t> bytes; };
|
||||
|
||||
unsigned id = 0;
|
||||
std::uint32_t revision = 1;
|
||||
ULONG refs = 1;
|
||||
std::vector<Level> levels;
|
||||
|
||||
CpuTexture()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_cpu_tex_mutex);
|
||||
id = g_next_cpu_tex_id++;
|
||||
g_cpu_textures[id] = this;
|
||||
}
|
||||
~CpuTexture()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_cpu_tex_mutex);
|
||||
g_cpu_textures.erase(id);
|
||||
}
|
||||
|
||||
ULONG AddRef() override { return ++refs; }
|
||||
ULONG Release() override
|
||||
{
|
||||
@@ -132,7 +155,14 @@ struct CpuTexture final : IDirect3DTexture8
|
||||
locked->pBits = levels[level].bytes.data();
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT UnlockRect(UINT level) override { return level < levels.size() ? S_OK : E_FAIL; }
|
||||
HRESULT UnlockRect(UINT level) override
|
||||
{
|
||||
if (level >= levels.size())
|
||||
return E_FAIL;
|
||||
if (level == 0)
|
||||
++revision;
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
ULONG CpuSurface::Release()
|
||||
@@ -217,6 +247,22 @@ public:
|
||||
m_renderTarget->AddRef();
|
||||
m_depthStencil = m_depthBuffer;
|
||||
m_depthStencil->AddRef();
|
||||
m_viewport = { 0, 0, (DWORD)width, (DWORD)height, 0.0f, 1.0f };
|
||||
m_renderStates[D3DRS_TEXTUREFACTOR] = 0xFFFFFFFF;
|
||||
m_renderStates[D3DRS_ZENABLE] = TRUE;
|
||||
m_renderStates[D3DRS_ZWRITEENABLE] = TRUE;
|
||||
m_renderStates[D3DRS_CULLMODE] = D3DCULL_CCW;
|
||||
m_renderStates[D3DRS_LIGHTING] = TRUE;
|
||||
m_renderStates[D3DRS_SRCBLEND] = D3DBLEND_ONE;
|
||||
m_renderStates[D3DRS_DESTBLEND] = D3DBLEND_ZERO;
|
||||
m_renderStates[D3DRS_ALPHAFUNC] = D3DCMP_ALWAYS;
|
||||
m_stageStates[0][D3DTSS_COLOROP] = D3DTOP_MODULATE;
|
||||
m_stageStates[0][D3DTSS_COLORARG1] = D3DTA_TEXTURE;
|
||||
m_stageStates[0][D3DTSS_COLORARG2] = D3DTA_CURRENT;
|
||||
m_stageStates[0][D3DTSS_ALPHAOP] = D3DTOP_SELECTARG1;
|
||||
m_stageStates[0][D3DTSS_ALPHAARG1] = D3DTA_TEXTURE;
|
||||
m_stageStates[1][D3DTSS_COLOROP] = D3DTOP_DISABLE;
|
||||
m_stageStates[1][D3DTSS_ALPHAOP] = D3DTOP_DISABLE;
|
||||
}
|
||||
~RecordingDevice() override
|
||||
{
|
||||
@@ -254,7 +300,14 @@ public:
|
||||
}
|
||||
HRESULT GetViewport(D3DVIEWPORT8* viewport) override
|
||||
{
|
||||
*viewport = { 0, 0, DWORD(m_width), DWORD(m_height), 0.0f, 1.0f };
|
||||
if (viewport)
|
||||
*viewport = m_viewport;
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT SetViewport(const D3DVIEWPORT8* viewport) override
|
||||
{
|
||||
if (viewport)
|
||||
m_viewport = *viewport;
|
||||
return S_OK;
|
||||
}
|
||||
// PORT: CPU memory has no texture budget; report the 64MB of a mid-range 2004 card.
|
||||
@@ -340,8 +393,8 @@ public:
|
||||
*out = m_depthStencil;
|
||||
return S_OK;
|
||||
}
|
||||
// PORT: an offscreen target (CSnowEnvironment's blur pass) swallows its draws; only the back
|
||||
// buffer's draws are recorded for the Godot renderer.
|
||||
// Character shadow targets are rasterized below; other offscreen targets still need a
|
||||
// separate effect-specific implementation (snow blur is disabled by default).
|
||||
HRESULT SetRenderTarget(IDirect3DSurface8* target, IDirect3DSurface8* depth) override
|
||||
{
|
||||
if (target)
|
||||
@@ -358,7 +411,28 @@ public:
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT Clear(DWORD, const D3DRECT*, DWORD, D3DCOLOR, float, DWORD) override { return S_OK; }
|
||||
HRESULT Clear(DWORD, const D3DRECT*, DWORD flags, D3DCOLOR color, float depth, DWORD) override
|
||||
{
|
||||
if (m_renderTarget == m_backBuffer)
|
||||
return S_OK;
|
||||
auto* surface = static_cast<CpuSurface*>(m_renderTarget);
|
||||
if (!surface->parent || surface->level != 0 || surface->desc.Format != D3DFMT_R5G6B5)
|
||||
return S_OK;
|
||||
const size_t pixels = size_t(surface->desc.Width) * surface->desc.Height;
|
||||
if (flags & D3DCLEAR_TARGET)
|
||||
{
|
||||
const std::uint16_t rgb565 = std::uint16_t((((color >> 16) & 255u) >> 3) << 11 |
|
||||
(((color >> 8) & 255u) >> 2) << 5 | ((color & 255u) >> 3));
|
||||
auto& bytes = surface->parent->levels[0].bytes;
|
||||
bytes.resize(pixels * 2);
|
||||
for (size_t i = 0; i < pixels; ++i)
|
||||
std::memcpy(bytes.data() + i * 2, &rgb565, 2);
|
||||
++surface->parent->revision;
|
||||
}
|
||||
if (flags & D3DCLEAR_ZBUFFER)
|
||||
m_offscreenDepth.assign(pixels, depth);
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT SetRenderState(D3DRENDERSTATETYPE state, DWORD value) override
|
||||
{
|
||||
if (unsigned(state) < kRenderStates)
|
||||
@@ -406,7 +480,8 @@ public:
|
||||
std::vector<std::uint32_t> indices(count);
|
||||
for (UINT i = 0; i < count; ++i)
|
||||
indices[i] = startVertex + i;
|
||||
record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices);
|
||||
record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices,
|
||||
m_stream, nullptr, startVertex);
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT DrawIndexedPrimitive(D3DPRIMITIVETYPE type, UINT, UINT, UINT startIndex, UINT primitiveCount) override
|
||||
@@ -417,7 +492,8 @@ public:
|
||||
if (!read_indices(m_indices->bytes.data(), m_indices->bytes.size(), m_indices->format, startIndex,
|
||||
index_count(type, primitiveCount), m_baseVertex, &indices))
|
||||
return E_FAIL;
|
||||
record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices);
|
||||
record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices,
|
||||
m_stream, m_indices, startIndex);
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT DrawPrimitiveUP(D3DPRIMITIVETYPE type, UINT primitiveCount, const void* vertices, UINT stride) override
|
||||
@@ -488,6 +564,92 @@ private:
|
||||
transform_point(&a[r * 4], b, &out[r * 4]);
|
||||
}
|
||||
|
||||
// The 40250 shadow pass renders a flat grey silhouette into an R5G6B5 target.
|
||||
// Rasterizing that small target here keeps the D3D render-target sequence and lets
|
||||
// the normal memory-texture path upload the result for terrain/object projection.
|
||||
void rasterize_shadow(const Render3DDraw& draw)
|
||||
{
|
||||
auto* surface = static_cast<CpuSurface*>(m_renderTarget);
|
||||
if (!surface->parent || surface->level != 0 || surface->desc.Format != D3DFMT_R5G6B5 || draw.lines)
|
||||
return;
|
||||
const int width = int(surface->desc.Width), height = int(surface->desc.Height);
|
||||
if (width <= 0 || height <= 0 || draw.indices.size() < 3)
|
||||
return;
|
||||
auto& bytes = surface->parent->levels[0].bytes;
|
||||
if (bytes.size() < size_t(width) * height * 2)
|
||||
return;
|
||||
if (m_offscreenDepth.size() != size_t(width) * height)
|
||||
m_offscreenDepth.assign(size_t(width) * height, 1.0f);
|
||||
float worldView[16], mvp[16];
|
||||
multiply(draw.world, draw.view, worldView);
|
||||
multiply(worldView, draw.proj, mvp);
|
||||
struct Point { float x, y, z; bool valid; };
|
||||
std::vector<Point> points(draw.positions.size() / 3);
|
||||
for (size_t i = 0; i < points.size(); ++i)
|
||||
{
|
||||
float p[4] = { draw.positions[i * 3], draw.positions[i * 3 + 1], draw.positions[i * 3 + 2], 1.0f };
|
||||
if (!draw.bone_matrices.empty() && draw.bone_weights.size() >= (i + 1) * 4 &&
|
||||
draw.bone_indices.size() >= (i + 1) * 4)
|
||||
{
|
||||
float skinned[4] = {};
|
||||
float total = 0.0f;
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
const float weight = draw.bone_weights[i * 4 + b];
|
||||
const size_t bone = draw.bone_indices[i * 4 + b];
|
||||
if (weight <= 0.0f || (bone + 1) * 16 > draw.bone_matrices.size()) continue;
|
||||
float transformed[4];
|
||||
transform_point(p, draw.bone_matrices.data() + bone * 16, transformed);
|
||||
for (int c = 0; c < 4; ++c) skinned[c] += transformed[c] * weight;
|
||||
total += weight;
|
||||
}
|
||||
if (total > 0.0f) { p[0] = skinned[0]; p[1] = skinned[1]; p[2] = skinned[2]; }
|
||||
}
|
||||
float clip[4];
|
||||
transform_point(p, mvp, clip);
|
||||
const bool valid = clip[3] > 0.00001f;
|
||||
const float invW = valid ? 1.0f / clip[3] : 0.0f;
|
||||
points[i] = { draw.viewport[0] + (clip[0] * invW * 0.5f + 0.5f) * draw.viewport[2],
|
||||
draw.viewport[1] + (0.5f - clip[1] * invW * 0.5f) * draw.viewport[3],
|
||||
clip[2] * invW, valid };
|
||||
}
|
||||
const std::uint32_t color = m_renderStates[D3DRS_TEXTUREFACTOR];
|
||||
const std::uint16_t rgb565 = std::uint16_t((((color >> 16) & 255u) >> 3) << 11 |
|
||||
(((color >> 8) & 255u) >> 2) << 5 | ((color & 255u) >> 3));
|
||||
auto edge = [](const Point& a, const Point& b, float x, float y) {
|
||||
return (x - a.x) * (b.y - a.y) - (y - a.y) * (b.x - a.x);
|
||||
};
|
||||
for (size_t i = 0; i + 2 < draw.indices.size(); i += 3)
|
||||
{
|
||||
if (draw.indices[i] >= points.size() || draw.indices[i + 1] >= points.size() ||
|
||||
draw.indices[i + 2] >= points.size()) continue;
|
||||
const Point& a = points[draw.indices[i]];
|
||||
const Point& b = points[draw.indices[i + 1]];
|
||||
const Point& c = points[draw.indices[i + 2]];
|
||||
if (!a.valid || !b.valid || !c.valid) continue;
|
||||
const float area = edge(a, b, c.x, c.y);
|
||||
if (std::fabs(area) < 0.00001f) continue;
|
||||
const int x0 = std::max(0, int(std::floor(std::min({a.x, b.x, c.x}))));
|
||||
const int y0 = std::max(0, int(std::floor(std::min({a.y, b.y, c.y}))));
|
||||
const int x1 = std::min(width - 1, int(std::ceil(std::max({a.x, b.x, c.x}))));
|
||||
const int y1 = std::min(height - 1, int(std::ceil(std::max({a.y, b.y, c.y}))));
|
||||
for (int y = y0; y <= y1; ++y)
|
||||
for (int x = x0; x <= x1; ++x)
|
||||
{
|
||||
const float px = float(x) + 0.5f, py = float(y) + 0.5f;
|
||||
const float wa = edge(b, c, px, py) / area;
|
||||
const float wb = edge(c, a, px, py) / area;
|
||||
const float wc = 1.0f - wa - wb;
|
||||
if (wa < 0.0f || wb < 0.0f || wc < 0.0f) continue;
|
||||
const float z = wa * a.z + wb * b.z + wc * c.z;
|
||||
const size_t pixel = size_t(y) * width + x;
|
||||
if (z < 0.0f || z > 1.0f || z > m_offscreenDepth[pixel]) continue;
|
||||
m_offscreenDepth[pixel] = z;
|
||||
std::memcpy(bytes.data() + pixel * 2, &rgb565, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Each two-triangle quad of a UI-space draw becomes an image command: its screen corners through
|
||||
// world * view * projection, its stage-0 texture (or D3DTA_TFACTOR colour when stage 0 selects it)
|
||||
// and, when stage 1 generates coordinates from the camera-space position through D3DTS_TEXTURE1
|
||||
@@ -585,9 +747,10 @@ private:
|
||||
}
|
||||
|
||||
void record(D3DPRIMITIVETYPE type, UINT primitives, const uint8_t* vertices, size_t vertexBytes, UINT stride,
|
||||
const std::vector<std::uint32_t>& indices)
|
||||
const std::vector<std::uint32_t>& indices, const MtCpuVertexBuffer* source_vertex = nullptr,
|
||||
const MtCpuIndexBuffer* source_index = nullptr, UINT source_first_index = 0)
|
||||
{
|
||||
if (type == D3DPT_POINTLIST || indices.empty() || !vertices || m_renderTarget != m_backBuffer)
|
||||
if (type == D3DPT_POINTLIST || indices.empty() || !vertices)
|
||||
return;
|
||||
VertexLayout layout = fvf_layout(m_fvf);
|
||||
if (!stride)
|
||||
@@ -602,7 +765,7 @@ private:
|
||||
|
||||
// An orthographic projection over untransformed vertices is a UI-space draw (CPythonMiniMap's
|
||||
// terrain tiles under CPythonGraphic::SetOrtho2D): it joins the UI command stream in order.
|
||||
if (!layout.rhw && m_transforms[D3DTS_PROJECTION][11] == 0.0f)
|
||||
if (m_renderTarget == m_backBuffer && !layout.rhw && m_transforms[D3DTS_PROJECTION][11] == 0.0f)
|
||||
{
|
||||
record_ui_quads(type, vertices, vertexBytes, stride, layout, indices);
|
||||
return;
|
||||
@@ -614,6 +777,10 @@ private:
|
||||
std::memcpy(draw.proj, m_transforms[D3DTS_PROJECTION], sizeof(draw.proj));
|
||||
draw.texture0 = UIRenderTextureNameFromHandle(m_textures[0]);
|
||||
draw.texture1 = UIRenderTextureNameFromHandle(m_textures[1]);
|
||||
draw.viewport[0] = float(m_viewport.X);
|
||||
draw.viewport[1] = float(m_viewport.Y);
|
||||
draw.viewport[2] = float(m_viewport.Width);
|
||||
draw.viewport[3] = float(m_viewport.Height);
|
||||
draw.pretransformed = layout.rhw;
|
||||
draw.lines = type == D3DPT_LINELIST || type == D3DPT_LINESTRIP;
|
||||
|
||||
@@ -627,47 +794,221 @@ private:
|
||||
if ((size_t(hi) + 1) * stride > vertexBytes)
|
||||
return;
|
||||
const size_t count = size_t(hi - lo) + 1;
|
||||
draw.positions.resize(count * 3);
|
||||
if (layout.rhw) draw.rhw.resize(count);
|
||||
if (layout.normal >= 0) draw.normals.resize(count * 3);
|
||||
if (layout.uv0 >= 0) draw.uv0.resize(count * 2);
|
||||
if (layout.uv1 >= 0) draw.uv1.resize(count * 2);
|
||||
if (layout.diffuse >= 0) draw.diffuse.resize(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
const bool texgen_cam_pos0 = layout.uv0 < 0 && m_textures[0] != nullptr &&
|
||||
(m_stageStates[0][D3DTSS_TEXCOORDINDEX] & 0xFFFF0000u) == D3DTSS_TCI_CAMERASPACEPOSITION &&
|
||||
m_stageStates[0][D3DTSS_TEXTURETRANSFORMFLAGS] == D3DTTFF_COUNT2;
|
||||
const bool texgen_cam_pos1 = layout.uv1 < 0 && m_textures[1] != nullptr &&
|
||||
(m_stageStates[1][D3DTSS_TEXCOORDINDEX] & 0xFFFF0000u) == D3DTSS_TCI_CAMERASPACEPOSITION &&
|
||||
m_stageStates[1][D3DTSS_TEXTURETRANSFORMFLAGS] == D3DTTFF_COUNT2;
|
||||
const bool tex_xform0 = layout.uv0 >= 0 && m_textures[0] != nullptr &&
|
||||
(m_stageStates[0][D3DTSS_TEXCOORDINDEX] & 0xFFFF0000u) == 0 &&
|
||||
m_stageStates[0][D3DTSS_TEXTURETRANSFORMFLAGS] == D3DTTFF_COUNT2;
|
||||
GpuSkinSubrangeView skin_view;
|
||||
const bool gpu_skinned = source_vertex != nullptr &&
|
||||
LookupGpuSkinSubrange(vertices, stride, lo, hi, &skin_view);
|
||||
if (source_vertex)
|
||||
{
|
||||
const uint8_t* v = vertices + (lo + i) * stride;
|
||||
std::memcpy(&draw.positions[i * 3], v, 12);
|
||||
if (layout.rhw) std::memcpy(&draw.rhw[i], v + 12, 4);
|
||||
if (layout.normal >= 0) std::memcpy(&draw.normals[i * 3], v + layout.normal, 12);
|
||||
if (layout.uv0 >= 0) std::memcpy(&draw.uv0[i * 2], v + layout.uv0, 8);
|
||||
if (layout.uv1 >= 0) std::memcpy(&draw.uv1[i * 2], v + layout.uv1, 8);
|
||||
if (layout.diffuse >= 0) std::memcpy(&draw.diffuse[i], v + layout.diffuse, 4);
|
||||
// The original buffers outlive individual draw calls. Keep their identity separate from
|
||||
// Unlock revisions so a static surface can keep its Godot mesh across frames.
|
||||
auto mix = [](std::uint64_t hash, std::uint64_t value) {
|
||||
return (hash ^ value) * 1099511628211ull;
|
||||
};
|
||||
std::uint64_t key = 14695981039346656037ull;
|
||||
if (gpu_skinned)
|
||||
{
|
||||
key = mix(key, skin_view.source_mesh_key);
|
||||
key = mix(key, source_index ? source_index->id : 0);
|
||||
key = mix(key, source_first_index);
|
||||
key = mix(key, lo - skin_view.mesh_base_vertex);
|
||||
key = mix(key, hi - skin_view.mesh_base_vertex);
|
||||
key = mix(key, primitives);
|
||||
key = mix(key, type);
|
||||
key = mix(key, stride);
|
||||
key = mix(key, m_fvf);
|
||||
draw.geometry_key = (key & 0x7FFFFFFFFFFFFFFFull) | 1ull;
|
||||
draw.geometry_revision = 1ull;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = mix(key, source_vertex->id);
|
||||
key = mix(key, source_index ? source_index->id : 0);
|
||||
key = mix(key, source_first_index);
|
||||
key = mix(key, lo);
|
||||
key = mix(key, hi);
|
||||
key = mix(key, primitives);
|
||||
key = mix(key, type);
|
||||
key = mix(key, stride);
|
||||
key = mix(key, m_fvf);
|
||||
if (texgen_cam_pos0)
|
||||
key = mix(key, static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(m_textures[0])));
|
||||
if (texgen_cam_pos1)
|
||||
key = mix(key, static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(m_textures[1])));
|
||||
draw.geometry_key = (key & 0x7FFFFFFFFFFFFFFFull) | 1ull;
|
||||
std::uint64_t revision = mix(14695981039346656037ull, source_vertex->revision);
|
||||
revision = mix(revision, source_index ? source_index->revision : 0);
|
||||
if (tex_xform0)
|
||||
{
|
||||
const float* m = m_transforms[D3DTS_TEXTURE0];
|
||||
for (int mi : { 0, 1, 4, 5, 8, 9, 12, 13 })
|
||||
{
|
||||
std::uint32_t bits = 0;
|
||||
std::memcpy(&bits, &m[mi], sizeof(bits));
|
||||
revision = mix(revision, bits);
|
||||
}
|
||||
}
|
||||
// Camera-space texture coordinates are baked into the captured geometry.
|
||||
// The terrain splat and character-shadow matrices can change while the
|
||||
// vertex/index buffers remain unchanged, so they are part of its revision.
|
||||
for (int stage = 0; stage < 2; ++stage)
|
||||
{
|
||||
if ((stage == 0 && !texgen_cam_pos0) || (stage == 1 && !texgen_cam_pos1))
|
||||
continue;
|
||||
float worldView[16], worldTexture[16];
|
||||
multiply(m_transforms[256], m_transforms[D3DTS_VIEW], worldView);
|
||||
multiply(worldView, m_transforms[stage == 0 ? D3DTS_TEXTURE0 : D3DTS_TEXTURE1], worldTexture);
|
||||
for (int mi : { 0, 1, 4, 5, 8, 9, 12, 13 })
|
||||
{
|
||||
std::uint32_t bits = 0;
|
||||
std::memcpy(&bits, &worldTexture[mi], sizeof(bits));
|
||||
revision = mix(revision, bits);
|
||||
}
|
||||
}
|
||||
draw.geometry_revision = revision & 0x7FFFFFFFFFFFFFFFull;
|
||||
}
|
||||
}
|
||||
const std::uint64_t frame_id = UIRenderFrameId();
|
||||
auto cached = draw.geometry_key ? m_geometry_cache.find(draw.geometry_key) : m_geometry_cache.end();
|
||||
const bool reuse = cached != m_geometry_cache.end() && !cached->second.changing &&
|
||||
cached->second.revision == draw.geometry_revision;
|
||||
if (reuse)
|
||||
{
|
||||
cached->second.last_used = frame_id;
|
||||
const Render3DDraw& prior = cached->second.geometry;
|
||||
draw.positions = prior.positions;
|
||||
draw.rhw = prior.rhw;
|
||||
draw.normals = prior.normals;
|
||||
draw.uv0 = prior.uv0;
|
||||
draw.uv1 = prior.uv1;
|
||||
draw.diffuse = prior.diffuse;
|
||||
draw.indices = prior.indices;
|
||||
draw.bone_indices = prior.bone_indices;
|
||||
draw.bone_weights = prior.bone_weights;
|
||||
}
|
||||
else
|
||||
{
|
||||
draw.positions.resize(count * 3);
|
||||
if (layout.rhw) draw.rhw.resize(count);
|
||||
if (layout.normal >= 0) draw.normals.resize(count * 3);
|
||||
if (layout.uv0 >= 0) draw.uv0.resize(count * 2);
|
||||
if (layout.uv1 >= 0) draw.uv1.resize(count * 2);
|
||||
if (layout.diffuse >= 0) draw.diffuse.resize(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const uint8_t* v = vertices + (lo + i) * stride;
|
||||
std::memcpy(&draw.positions[i * 3], v, 12);
|
||||
if (layout.rhw) std::memcpy(&draw.rhw[i], v + 12, 4);
|
||||
if (layout.normal >= 0) std::memcpy(&draw.normals[i * 3], v + layout.normal, 12);
|
||||
if (layout.uv0 >= 0) std::memcpy(&draw.uv0[i * 2], v + layout.uv0, 8);
|
||||
if (layout.uv1 >= 0) std::memcpy(&draw.uv1[i * 2], v + layout.uv1, 8);
|
||||
if (layout.diffuse >= 0) std::memcpy(&draw.diffuse[i], v + layout.diffuse, 4);
|
||||
}
|
||||
if (texgen_cam_pos0)
|
||||
{
|
||||
float worldView[16], worldTex0[16];
|
||||
multiply(m_transforms[256], m_transforms[D3DTS_VIEW], worldView);
|
||||
multiply(worldView, m_transforms[D3DTS_TEXTURE0], worldTex0);
|
||||
draw.uv0.resize(count * 2);
|
||||
const bool clamp0_u = m_stageStates[0][D3DTSS_ADDRESSU] == D3DTADDRESS_CLAMP;
|
||||
const bool clamp0_v = m_stageStates[0][D3DTSS_ADDRESSV] == D3DTADDRESS_CLAMP;
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const float pos[4] = { draw.positions[i * 3 + 0], draw.positions[i * 3 + 1], draw.positions[i * 3 + 2], 1.0f };
|
||||
float tc[4];
|
||||
transform_point(pos, worldTex0, tc);
|
||||
draw.uv0[i * 2 + 0] = clamp0_u ? std::clamp(tc[0], 0.5f / 256.0f, 255.5f / 256.0f) : tc[0];
|
||||
draw.uv0[i * 2 + 1] = clamp0_v ? std::clamp(tc[1], 0.5f / 256.0f, 255.5f / 256.0f) : tc[1];
|
||||
}
|
||||
}
|
||||
else if (tex_xform0)
|
||||
{
|
||||
const float* m = m_transforms[D3DTS_TEXTURE0];
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const float u = draw.uv0[i * 2 + 0];
|
||||
const float v = draw.uv0[i * 2 + 1];
|
||||
draw.uv0[i * 2 + 0] = u * m[0] + v * m[4] + m[8] + m[12];
|
||||
draw.uv0[i * 2 + 1] = u * m[1] + v * m[5] + m[9] + m[13];
|
||||
}
|
||||
}
|
||||
if (texgen_cam_pos1)
|
||||
{
|
||||
float worldView[16], worldTex1[16];
|
||||
multiply(m_transforms[256], m_transforms[D3DTS_VIEW], worldView);
|
||||
multiply(worldView, m_transforms[D3DTS_TEXTURE1], worldTex1);
|
||||
draw.uv1.resize(count * 2);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
const float pos[4] = { draw.positions[i * 3 + 0], draw.positions[i * 3 + 1], draw.positions[i * 3 + 2], 1.0f };
|
||||
float tc[4];
|
||||
transform_point(pos, worldTex1, tc);
|
||||
draw.uv1[i * 2 + 0] = tc[0];
|
||||
draw.uv1[i * 2 + 1] = tc[1];
|
||||
}
|
||||
}
|
||||
if (gpu_skinned)
|
||||
{
|
||||
const std::size_t rel_lo = std::size_t(lo - skin_view.mesh_base_vertex);
|
||||
draw.bone_indices.resize(count * 4);
|
||||
draw.bone_weights.resize(count * 4);
|
||||
std::memcpy(draw.bone_indices.data(), skin_view.bone_indices + rel_lo * 4, count * 4 * sizeof(std::uint8_t));
|
||||
std::memcpy(draw.bone_weights.data(), skin_view.bone_weights + rel_lo * 4, count * 4 * sizeof(float));
|
||||
}
|
||||
|
||||
// Strips and fans become lists; D3D flips the winding of every odd strip triangle.
|
||||
switch (type)
|
||||
{
|
||||
case D3DPT_TRIANGLESTRIP:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
{
|
||||
const std::uint32_t a = indices[i] - lo, b = indices[i + 1] - lo, c = indices[i + 2] - lo;
|
||||
if (i & 1) draw.indices.insert(draw.indices.end(), { b, a, c });
|
||||
else draw.indices.insert(draw.indices.end(), { a, b, c });
|
||||
}
|
||||
break;
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
draw.indices.insert(draw.indices.end(), { indices[0] - lo, indices[i + 1] - lo, indices[i + 2] - lo });
|
||||
break;
|
||||
case D3DPT_LINESTRIP:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
draw.indices.insert(draw.indices.end(), { indices[i] - lo, indices[i + 1] - lo });
|
||||
break;
|
||||
default:
|
||||
for (std::uint32_t index : indices)
|
||||
draw.indices.push_back(index - lo);
|
||||
break;
|
||||
}
|
||||
if (cached != m_geometry_cache.end())
|
||||
{
|
||||
cached->second.last_used = frame_id;
|
||||
if (!cached->second.changing && cached->second.revision != draw.geometry_revision)
|
||||
{
|
||||
cached->second.changing = true;
|
||||
cached->second.geometry = Render3DDraw();
|
||||
}
|
||||
}
|
||||
else if (draw.geometry_key && cached == m_geometry_cache.end())
|
||||
m_geometry_cache.emplace(draw.geometry_key, GeometryCacheEntry{draw.geometry_revision, frame_id, false, draw});
|
||||
}
|
||||
if (gpu_skinned && skin_view.bone_matrices && skin_view.bone_count > 0)
|
||||
draw.bone_matrices.assign(skin_view.bone_matrices, skin_view.bone_matrices + std::size_t(skin_view.bone_count) * 16);
|
||||
if (frame_id >= m_cache_pruned_frame + 120)
|
||||
{
|
||||
m_cache_pruned_frame = frame_id;
|
||||
for (auto it = m_geometry_cache.begin(); it != m_geometry_cache.end();)
|
||||
it = frame_id - it->second.last_used > 120 ? m_geometry_cache.erase(it) : std::next(it);
|
||||
}
|
||||
|
||||
// Strips and fans become lists; D3D flips the winding of every odd strip triangle.
|
||||
switch (type)
|
||||
{
|
||||
case D3DPT_TRIANGLESTRIP:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
{
|
||||
const std::uint32_t a = indices[i] - lo, b = indices[i + 1] - lo, c = indices[i + 2] - lo;
|
||||
if (i & 1) draw.indices.insert(draw.indices.end(), { b, a, c });
|
||||
else draw.indices.insert(draw.indices.end(), { a, b, c });
|
||||
}
|
||||
break;
|
||||
case D3DPT_TRIANGLEFAN:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
draw.indices.insert(draw.indices.end(), { indices[0] - lo, indices[i + 1] - lo, indices[i + 2] - lo });
|
||||
break;
|
||||
case D3DPT_LINESTRIP:
|
||||
for (UINT i = 0; i < primitives; ++i)
|
||||
draw.indices.insert(draw.indices.end(), { indices[i] - lo, indices[i + 1] - lo });
|
||||
break;
|
||||
default:
|
||||
for (std::uint32_t index : indices)
|
||||
draw.indices.push_back(index - lo);
|
||||
break;
|
||||
}
|
||||
|
||||
draw.alpha_blend = m_renderStates[D3DRS_ALPHABLENDENABLE];
|
||||
draw.src_blend = m_renderStates[D3DRS_SRCBLEND];
|
||||
@@ -682,7 +1023,17 @@ private:
|
||||
draw.lighting = m_renderStates[D3DRS_LIGHTING];
|
||||
draw.texture_factor = m_renderStates[D3DRS_TEXTUREFACTOR];
|
||||
draw.fog_enable = m_renderStates[D3DRS_FOGENABLE];
|
||||
draw.fog_color = m_renderStates[D3DRS_FOGCOLOR];
|
||||
draw.fog_vertex_mode = m_renderStates[D3DRS_FOGVERTEXMODE];
|
||||
draw.fog_table_mode = m_renderStates[D3DRS_FOGTABLEMODE];
|
||||
draw.fog_range_enable = m_renderStates[D3DRS_RANGEFOGENABLE];
|
||||
std::memcpy(&draw.fog_start, &m_renderStates[D3DRS_FOGSTART], sizeof(float));
|
||||
std::memcpy(&draw.fog_end, &m_renderStates[D3DRS_FOGEND], sizeof(float));
|
||||
std::memcpy(&draw.fog_density, &m_renderStates[D3DRS_FOGDENSITY], sizeof(float));
|
||||
draw.ambient = m_renderStates[D3DRS_AMBIENT];
|
||||
draw.diffuse_material_source = m_renderStates[D3DRS_DIFFUSEMATERIALSOURCE];
|
||||
draw.ambient_material_source = m_renderStates[D3DRS_AMBIENTMATERIALSOURCE];
|
||||
draw.color_vertex = m_renderStates[D3DRS_COLORVERTEX];
|
||||
for (int stage = 0; stage < 2; ++stage)
|
||||
{
|
||||
draw.color_op[stage] = m_stageStates[stage][D3DTSS_COLOROP];
|
||||
@@ -691,11 +1042,16 @@ private:
|
||||
draw.alpha_op[stage] = m_stageStates[stage][D3DTSS_ALPHAOP];
|
||||
draw.alpha_arg1[stage] = m_stageStates[stage][D3DTSS_ALPHAARG1];
|
||||
draw.alpha_arg2[stage] = m_stageStates[stage][D3DTSS_ALPHAARG2];
|
||||
draw.address_u[stage] = m_stageStates[stage][D3DTSS_ADDRESSU];
|
||||
draw.address_v[stage] = m_stageStates[stage][D3DTSS_ADDRESSV];
|
||||
draw.min_filter[stage] = m_stageStates[stage][D3DTSS_MINFILTER];
|
||||
draw.mag_filter[stage] = m_stageStates[stage][D3DTSS_MAGFILTER];
|
||||
draw.mip_filter[stage] = m_stageStates[stage][D3DTSS_MIPFILTER];
|
||||
}
|
||||
copy_color(draw.material_diffuse, m_material.Diffuse);
|
||||
copy_color(draw.material_ambient, m_material.Ambient);
|
||||
copy_color(draw.material_emissive, m_material.Emissive);
|
||||
if (m_lightEnabled[0] && m_lights[0].Type == D3DLIGHT_DIRECTIONAL)
|
||||
if (m_lightEnabled[0] && (m_lights[0].Type == D3DLIGHT_DIRECTIONAL || m_lights[0].Type == D3DLIGHT_SPOT))
|
||||
{
|
||||
draw.light0 = true;
|
||||
draw.light0_direction[0] = m_lights[0].Direction.x;
|
||||
@@ -704,11 +1060,37 @@ private:
|
||||
copy_color(draw.light0_diffuse, m_lights[0].Diffuse);
|
||||
copy_color(draw.light0_ambient, m_lights[0].Ambient);
|
||||
}
|
||||
Render3DAdd(std::move(draw));
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (!m_lightEnabled[i]) continue;
|
||||
const D3DLIGHT8& source = m_lights[i];
|
||||
auto& light = draw.lights[i];
|
||||
light.type = source.Type;
|
||||
light.position[0] = source.Position.x;
|
||||
light.position[1] = source.Position.y;
|
||||
light.position[2] = source.Position.z;
|
||||
light.direction[0] = source.Direction.x;
|
||||
light.direction[1] = source.Direction.y;
|
||||
light.direction[2] = source.Direction.z;
|
||||
copy_color(light.diffuse, source.Diffuse);
|
||||
copy_color(light.ambient, source.Ambient);
|
||||
light.attenuation[0] = source.Attenuation0;
|
||||
light.attenuation[1] = source.Attenuation1;
|
||||
light.attenuation[2] = source.Attenuation2;
|
||||
light.range = source.Range;
|
||||
light.theta = source.Theta;
|
||||
light.phi = source.Phi;
|
||||
light.falloff = source.Falloff;
|
||||
}
|
||||
if (m_renderTarget == m_backBuffer)
|
||||
Render3DAdd(std::move(draw));
|
||||
else
|
||||
rasterize_shadow(draw);
|
||||
}
|
||||
|
||||
ULONG m_refs = 1;
|
||||
int m_width, m_height;
|
||||
D3DVIEWPORT8 m_viewport = {};
|
||||
float m_transforms[kTransforms][16];
|
||||
DWORD m_renderStates[kRenderStates] = {};
|
||||
DWORD m_stageStates[kStages][kStageStates] = {};
|
||||
@@ -725,11 +1107,103 @@ private:
|
||||
UINT m_streamStride = 0;
|
||||
MtCpuIndexBuffer* m_indices = nullptr;
|
||||
UINT m_baseVertex = 0;
|
||||
struct GeometryCacheEntry {
|
||||
std::uint64_t revision;
|
||||
std::uint64_t last_used;
|
||||
bool changing;
|
||||
Render3DDraw geometry;
|
||||
};
|
||||
std::unordered_map<std::uint64_t, GeometryCacheEntry> m_geometry_cache;
|
||||
std::uint64_t m_cache_pruned_frame = 0;
|
||||
std::vector<float> m_offscreenDepth;
|
||||
};
|
||||
}
|
||||
|
||||
std::string MtCpuTextureNameFromHandle(const IDirect3DBaseTexture8* handle)
|
||||
{
|
||||
if (!handle) return {};
|
||||
std::lock_guard<std::mutex> lock(g_cpu_tex_mutex);
|
||||
for (const auto& entry : g_cpu_textures)
|
||||
{
|
||||
if (entry.second == handle && !entry.second->levels.empty())
|
||||
return "mem:cpu_" + std::to_string(entry.first) + "@" + std::to_string(entry.second->revision);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool MtCpuMemoryTexture(const std::string& name, UIMemoryTexture* out)
|
||||
{
|
||||
if (name.compare(0, 8, "mem:cpu_") != 0 || !out) return false;
|
||||
const unsigned id = unsigned(std::strtoul(name.c_str() + 8, nullptr, 10));
|
||||
std::lock_guard<std::mutex> lock(g_cpu_tex_mutex);
|
||||
auto it = g_cpu_textures.find(id);
|
||||
if (it == g_cpu_textures.end() || it->second->levels.empty()) return false;
|
||||
const auto& lv0 = it->second->levels[0];
|
||||
const UINT w = lv0.desc.Width;
|
||||
const UINT h = lv0.desc.Height;
|
||||
if (!w || !h) return false;
|
||||
out->width = static_cast<int>(w);
|
||||
out->height = static_cast<int>(h);
|
||||
out->revision = it->second->revision;
|
||||
out->argb.resize(std::size_t(w) * std::size_t(h));
|
||||
const uint8_t* bytes = lv0.bytes.data();
|
||||
const int bpp = format_bytes(lv0.desc.Format);
|
||||
for (std::size_t i = 0; i < out->argb.size(); ++i)
|
||||
{
|
||||
if (bpp == 4)
|
||||
{
|
||||
std::uint32_t px = 0;
|
||||
std::memcpy(&px, bytes + i * 4, 4);
|
||||
// CTerrain::PutImage32 packs alpha into bits 31..24 with RGB == 0.
|
||||
// Set RGB to white so stage-1 modulation preserves the base texture's RGB.
|
||||
if ((px & 0x00FFFFFFu) == 0)
|
||||
px |= 0x00FFFFFFu;
|
||||
out->argb[i] = px;
|
||||
}
|
||||
else if (lv0.desc.Format == D3DFMT_R5G6B5)
|
||||
{
|
||||
std::uint16_t word = 0;
|
||||
std::memcpy(&word, bytes + i * 2, 2);
|
||||
const std::uint32_t r = ((word >> 11) & 31u) * 255u / 31u;
|
||||
const std::uint32_t g = ((word >> 5) & 63u) * 255u / 63u;
|
||||
const std::uint32_t b = (word & 31u) * 255u / 31u;
|
||||
out->argb[i] = 0xFF000000u | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
else if (bpp == 2)
|
||||
{
|
||||
std::uint16_t word = 0;
|
||||
std::memcpy(&word, bytes + i * 2, 2);
|
||||
// CTerrain::PutImage16 writes `src[x] << 8`, storing the full 8-bit alpha in the high byte.
|
||||
const std::uint32_t a = (word >> 8) & 0xFFu;
|
||||
out->argb[i] = (a << 24) | 0x00FFFFFFu;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::uint32_t a = bytes[i];
|
||||
out->argb[i] = (a << 24) | 0x00FFFFFFu;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
IDirect3DDevice8* MtCreateRecordingDevice(int width, int height) { return new RecordingDevice(width, height); }
|
||||
|
||||
void SetNativeTerrainRenderEnabled(bool enabled)
|
||||
{
|
||||
g_native_terrain_override = enabled ? 1 : 0;
|
||||
}
|
||||
|
||||
bool IsNativeTerrainRenderEnabled()
|
||||
{
|
||||
if (g_native_terrain_override >= 0)
|
||||
return g_native_terrain_override != 0;
|
||||
static const bool env_on = [] {
|
||||
const char* v = std::getenv("MT_NATIVE_TERRAIN");
|
||||
return v && (*v == '1' || *v == 't' || *v == 'T' || *v == 'y' || *v == 'Y');
|
||||
}();
|
||||
return env_on;
|
||||
}
|
||||
|
||||
void Render3DBeginFrame()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_draws_mutex);
|
||||
|
||||
@@ -10,9 +10,14 @@
|
||||
//
|
||||
// Matrices are D3D8's row-vector layout (translation in elements 12..14), exactly as 40250 set them.
|
||||
struct Render3DDraw {
|
||||
// Stable source-buffer identity and content version. Zero key means an immediate-mode draw
|
||||
// without a reusable D3D buffer. Geometry may be reused only while both values match.
|
||||
std::uint64_t geometry_key = 0;
|
||||
std::uint64_t geometry_revision = 0;
|
||||
float world[16];
|
||||
float view[16];
|
||||
float proj[16];
|
||||
float viewport[4] = {}; // x, y, width, height
|
||||
|
||||
// Stage 0/1 textures, named like UIRenderTextureName: the pack path of a file texture or
|
||||
// "mem:<id>@<revision>"; empty when the stage has no texture.
|
||||
@@ -30,6 +35,9 @@ struct Render3DDraw {
|
||||
std::vector<float> uv1; // u, v
|
||||
std::vector<std::uint32_t> diffuse; // 0xAARRGGBB
|
||||
std::vector<std::uint32_t> indices; // triangle list (strips and fans are expanded), or line list
|
||||
std::vector<std::uint8_t> bone_indices; // 4 uint8 per vertex (mesh-local bone palette index)
|
||||
std::vector<float> bone_weights; // 4 floats per vertex
|
||||
std::vector<float> bone_matrices; // 16 floats per bone in the mesh's palette (D3D row-vector layout)
|
||||
bool lines = false;
|
||||
|
||||
// D3DRS_* / D3DTSS_* values in effect for the draw.
|
||||
@@ -37,8 +45,12 @@ struct Render3DDraw {
|
||||
std::uint32_t alpha_test = 0, alpha_ref = 0, alpha_func = 0;
|
||||
std::uint32_t cull_mode = 0, z_enable = 0, z_write = 0, z_func = 0;
|
||||
std::uint32_t lighting = 0, texture_factor = 0, fog_enable = 0;
|
||||
std::uint32_t fog_color = 0, fog_vertex_mode = 0, fog_table_mode = 0, fog_range_enable = 0;
|
||||
float fog_start = 0, fog_end = 0, fog_density = 0;
|
||||
std::uint32_t color_op[2] = {}, color_arg1[2] = {}, color_arg2[2] = {};
|
||||
std::uint32_t alpha_op[2] = {}, alpha_arg1[2] = {}, alpha_arg2[2] = {};
|
||||
std::uint32_t address_u[2] = {}, address_v[2] = {};
|
||||
std::uint32_t min_filter[2] = {}, mag_filter[2] = {}, mip_filter[2] = {};
|
||||
// D3DMATERIAL8 diffuse/ambient/emissive (r, g, b, a) and light 0 when enabled.
|
||||
float material_diffuse[4] = {1, 1, 1, 1};
|
||||
float material_ambient[4] = {};
|
||||
@@ -48,8 +60,40 @@ struct Render3DDraw {
|
||||
float light0_diffuse[4] = {};
|
||||
float light0_ambient[4] = {};
|
||||
std::uint32_t ambient = 0; // D3DRS_AMBIENT
|
||||
struct Light {
|
||||
std::uint32_t type = 0; // zero when disabled; D3DLIGHT_POINT/SPOT/DIRECTIONAL otherwise
|
||||
float position[3] = {};
|
||||
float direction[3] = {};
|
||||
float diffuse[4] = {};
|
||||
float ambient[4] = {};
|
||||
float attenuation[3] = {};
|
||||
float range = 0;
|
||||
float theta = 0, phi = 0, falloff = 0;
|
||||
} lights[2];
|
||||
std::uint32_t diffuse_material_source = 0;
|
||||
std::uint32_t ambient_material_source = 0;
|
||||
std::uint32_t color_vertex = 0;
|
||||
};
|
||||
|
||||
struct GpuSkinSubrangeView {
|
||||
std::uint64_t source_mesh_key = 0;
|
||||
std::uint32_t mesh_base_vertex = 0;
|
||||
std::uint32_t mesh_vertex_count = 0;
|
||||
const std::uint8_t* bone_indices = nullptr; // mesh_vertex_count * 4
|
||||
const float* bone_weights = nullptr; // mesh_vertex_count * 4
|
||||
const float* bone_matrices = nullptr; // bone_count * 16
|
||||
std::uint32_t bone_count = 0;
|
||||
};
|
||||
|
||||
void SetNativeTerrainRenderEnabled(bool enabled);
|
||||
bool IsNativeTerrainRenderEnabled();
|
||||
|
||||
void SetGpuSkinningEnabled(bool enabled);
|
||||
bool IsGpuSkinningEnabled();
|
||||
bool LookupGpuSkinSubrange(const void* vertex_buffer_base, std::uint32_t stride,
|
||||
std::uint32_t lo_vertex, std::uint32_t hi_vertex,
|
||||
GpuSkinSubrangeView* out_view);
|
||||
|
||||
void Render3DBeginFrame();
|
||||
void Render3DAdd(Render3DDraw draw);
|
||||
const std::vector<Render3DDraw>& Render3DDraws();
|
||||
|
||||
@@ -1,199 +1,787 @@
|
||||
// Platform skeleton for EterLib/SkyBox.h (40250 EterLib/SkyBox.cpp), generated by platform_stub.py.
|
||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
||||
// Platform implementation of EterLib/SkyBox.cpp (40250 EterLib/SkyBox.cpp).
|
||||
#include "EterLib/StdAfx.h"
|
||||
#include "EterLib/SkyBox.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
#include "EterLib/Camera.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
#include "EterLib/ResourceManager.h"
|
||||
#include "EterBase/Timer.h"
|
||||
#include "RenderCommands3D.h"
|
||||
|
||||
CSkyObjectQuad::CSkyObjectQuad()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_Indices[0] = 0;
|
||||
m_Indices[1] = 2;
|
||||
m_Indices[2] = 1;
|
||||
m_Indices[3] = 3;
|
||||
|
||||
for (unsigned char uci = 0; uci < 4; ++uci)
|
||||
{
|
||||
memset(&m_Vertex[uci], 0, sizeof(TPDTVertex));
|
||||
}
|
||||
}
|
||||
|
||||
CSkyObjectQuad::~CSkyObjectQuad()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::Clear(const unsigned char &, const float &, const float &, const float &, const float &) -> void
|
||||
void CSkyObjectQuad::Clear(const unsigned char & c_rucNumVertex,
|
||||
const float & c_rfRed,
|
||||
const float & c_rfGreen,
|
||||
const float & c_rfBlue,
|
||||
const float & c_rfAlpha)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (c_rucNumVertex > 3)
|
||||
return;
|
||||
m_Helper[c_rucNumVertex].Clear(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha);
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::SetSrcColor(const unsigned char &, const float &, const float &, const float &, const float &) -> void
|
||||
void CSkyObjectQuad::SetSrcColor(const unsigned char & c_rucNumVertex,
|
||||
const float & c_rfRed,
|
||||
const float & c_rfGreen,
|
||||
const float & c_rfBlue,
|
||||
const float & c_rfAlpha)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (c_rucNumVertex > 3)
|
||||
return;
|
||||
m_Helper[c_rucNumVertex].SetSrcColor(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha);
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::SetTransition(const unsigned char &, const float &, const float &, const float &, const float &, DWORD) -> void
|
||||
void CSkyObjectQuad::SetTransition(const unsigned char & c_rucNumVertex,
|
||||
const float & c_rfRed,
|
||||
const float & c_rfGreen,
|
||||
const float & c_rfBlue,
|
||||
const float & c_rfAlpha,
|
||||
DWORD dwDuration)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (c_rucNumVertex > 3)
|
||||
return;
|
||||
m_Helper[c_rucNumVertex].SetTransition(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha, dwDuration);
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::SetVertex(const unsigned char &, const TPDTVertex &) -> void
|
||||
void CSkyObjectQuad::SetVertex(const unsigned char & c_rucNumVertex, const TPDTVertex & c_rPDTVertex)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (c_rucNumVertex > 3)
|
||||
return;
|
||||
memcpy(&m_Vertex[m_Indices[c_rucNumVertex]], &c_rPDTVertex, sizeof(TPDTVertex));
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::StartTransition() -> void
|
||||
void CSkyObjectQuad::StartTransition()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
for (unsigned char uci = 0; uci < 4; ++uci)
|
||||
{
|
||||
m_Helper[uci].StartTransition();
|
||||
}
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::Update() -> bool
|
||||
bool CSkyObjectQuad::Update()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
bool bResult = false;
|
||||
for (unsigned char uci = 0; uci < 4; ++uci)
|
||||
{
|
||||
bResult = m_Helper[uci].Update() || bResult;
|
||||
m_Vertex[m_Indices[uci]].diffuse = m_Helper[uci].GetCurColor();
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
auto CSkyObjectQuad::Render() -> void
|
||||
void CSkyObjectQuad::Render()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (CGraphicBase::SetPDTStream(m_Vertex, 4))
|
||||
STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
}
|
||||
|
||||
CSkyObject::CSkyObject()
|
||||
CSkyObject::CSkyObject() :
|
||||
m_v3Position(0.0f, 0.0f, 0.0f),
|
||||
m_fScaleX(1.0f),
|
||||
m_fScaleY(1.0f),
|
||||
m_fScaleZ(1.0f)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
D3DXMatrixIdentity(&m_matWorld);
|
||||
D3DXMatrixIdentity(&m_matTranslation);
|
||||
D3DXMatrixIdentity(&m_matWorldCloud);
|
||||
D3DXMatrixIdentity(&m_matTranslationCloud);
|
||||
D3DXMatrixIdentity(&m_matTextureCloud);
|
||||
|
||||
m_dwlastTime = CTimer::Instance().GetCurrentMillisecond();
|
||||
|
||||
m_fCloudPositionU = 0.0f;
|
||||
m_fCloudPositionV = 0.0f;
|
||||
m_fCloudScaleX = 1.0f;
|
||||
m_fCloudScaleY = 1.0f;
|
||||
m_fCloudHeight = 0.0f;
|
||||
m_fCloudTextureScaleX = 1.0f;
|
||||
m_fCloudTextureScaleY = 1.0f;
|
||||
m_fCloudScrollSpeedU = 0.0f;
|
||||
m_fCloudScrollSpeedV = 0.0f;
|
||||
m_ucRenderMode = SKY_RENDER_MODE_DEFAULT;
|
||||
|
||||
m_bTransitionStarted = false;
|
||||
m_bSkyMatrixUpdated = false;
|
||||
}
|
||||
|
||||
CSkyObject::~CSkyObject()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CSkyObject::StartTransition() -> void
|
||||
void CSkyObject::Destroy()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CSkyObject::GenerateTexture(const char *) -> CGraphicImageInstance *
|
||||
void CSkyObject::Update()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<CGraphicImageInstance *>();
|
||||
CCamera* pCamera = CCameraManager::Instance().GetCurrentCamera();
|
||||
if (!pCamera)
|
||||
return;
|
||||
D3DXVECTOR3 v3Eye = pCamera->GetEye();
|
||||
|
||||
if (m_v3Position == v3Eye)
|
||||
if (m_bSkyMatrixUpdated == false)
|
||||
return;
|
||||
|
||||
m_v3Position = v3Eye;
|
||||
|
||||
m_matWorld._41 = m_v3Position.x;
|
||||
m_matWorld._42 = m_v3Position.y;
|
||||
m_matWorld._43 = m_v3Position.z;
|
||||
|
||||
m_matWorldCloud._41 = m_v3Position.x;
|
||||
m_matWorldCloud._42 = m_v3Position.y;
|
||||
m_matWorldCloud._43 = m_v3Position.z + m_fCloudHeight;
|
||||
|
||||
if (m_bSkyMatrixUpdated)
|
||||
m_bSkyMatrixUpdated = false;
|
||||
}
|
||||
|
||||
auto CSkyObject::DeleteTexture(CGraphicImageInstance *) -> void
|
||||
void CSkyObject::Render()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CSkyObject::CSkyBox::StartTransition() -> void
|
||||
void CSkyObject::StartTransition()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CSkyObject::CSkyBox::Update() -> bool
|
||||
CGraphicImageInstance * CSkyObject::GenerateTexture(const char * szfilename)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
if (!szfilename || !*szfilename)
|
||||
return NULL;
|
||||
|
||||
CResource * pResource = CResourceManager::Instance().GetResourcePointer(szfilename);
|
||||
if (!pResource || !pResource->IsType(CGraphicImage::Type()))
|
||||
return NULL;
|
||||
|
||||
CGraphicImageInstance * pImageInstance = CGraphicImageInstance::New();
|
||||
pImageInstance->SetImagePointer(static_cast<CGraphicImage *>(pResource));
|
||||
return pImageInstance;
|
||||
}
|
||||
|
||||
auto CSkyObject::CSkyBox::Render() -> void
|
||||
void CSkyObject::DeleteTexture(CGraphicImageInstance * pImageInstance)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (pImageInstance)
|
||||
CGraphicImageInstance::Delete(pImageInstance);
|
||||
}
|
||||
|
||||
void CSkyObject::TSkyObjectFace::StartTransition()
|
||||
{
|
||||
for (unsigned char uci = 0; uci < m_SkyObjectQuadVector.size(); ++uci)
|
||||
{
|
||||
m_SkyObjectQuadVector[uci].StartTransition();
|
||||
}
|
||||
}
|
||||
|
||||
bool CSkyObject::TSkyObjectFace::Update()
|
||||
{
|
||||
bool bResult = false;
|
||||
for (DWORD dwi = 0; dwi < m_SkyObjectQuadVector.size(); ++dwi)
|
||||
bResult = m_SkyObjectQuadVector[dwi].Update() || bResult;
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void CSkyObject::TSkyObjectFace::Render()
|
||||
{
|
||||
for (unsigned char uci = 0; uci < m_SkyObjectQuadVector.size(); ++uci)
|
||||
{
|
||||
m_SkyObjectQuadVector[uci].Render();
|
||||
}
|
||||
}
|
||||
|
||||
CSkyBox::CSkyBox()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_ucVirticalGradientLevelUpper = 0;
|
||||
m_ucVirticalGradientLevelLower = 0;
|
||||
}
|
||||
|
||||
CSkyBox::~CSkyBox()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
auto CSkyBox::Update() -> void
|
||||
void CSkyBox::Destroy()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
Unload();
|
||||
}
|
||||
|
||||
auto CSkyBox::Render() -> void
|
||||
void CSkyBox::Unload()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.begin();
|
||||
|
||||
while (itor != m_GraphicImageInstanceMap.end())
|
||||
{
|
||||
DeleteTexture(itor->second);
|
||||
++itor;
|
||||
}
|
||||
|
||||
m_GraphicImageInstanceMap.clear();
|
||||
}
|
||||
|
||||
auto CSkyBox::RenderCloud() -> void
|
||||
void CSkyBox::SetSkyBoxScale(const D3DXVECTOR3 & c_rv3Scale)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_fScaleX = c_rv3Scale.x;
|
||||
m_fScaleY = c_rv3Scale.y;
|
||||
m_fScaleZ = c_rv3Scale.z;
|
||||
|
||||
m_bSkyMatrixUpdated = true;
|
||||
D3DXMatrixScaling(&m_matWorld, m_fScaleX, m_fScaleY, m_fScaleZ);
|
||||
}
|
||||
|
||||
auto CSkyBox::Destroy() -> void
|
||||
void CSkyBox::SetGradientLevel(BYTE byUpper, BYTE byLower)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_ucVirticalGradientLevelUpper = byUpper;
|
||||
m_ucVirticalGradientLevelLower = byLower;
|
||||
}
|
||||
|
||||
auto CSkyBox::Unload() -> void
|
||||
void CSkyBox::SetFaceTexture(const char* c_szFileName, int iFaceIndex)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (iFaceIndex < 0 || iFaceIndex > 5 || !c_szFileName || !*c_szFileName)
|
||||
return;
|
||||
|
||||
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.find(c_szFileName);
|
||||
if (m_GraphicImageInstanceMap.end() != itor)
|
||||
return;
|
||||
|
||||
m_Faces[iFaceIndex].m_strFaceTextureFileName = c_szFileName;
|
||||
|
||||
CGraphicImageInstance * pGraphicImageInstance = GenerateTexture(c_szFileName);
|
||||
m_GraphicImageInstanceMap.insert(TGraphicImageInstanceMap::value_type(c_szFileName, pGraphicImageInstance));
|
||||
}
|
||||
|
||||
auto CSkyBox::SetSkyBoxScale(const D3DXVECTOR3 &) -> void
|
||||
void CSkyBox::SetCloudTexture(const char * c_szFileName)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (!c_szFileName || !*c_szFileName)
|
||||
return;
|
||||
|
||||
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.find(c_szFileName);
|
||||
if (m_GraphicImageInstanceMap.end() != itor)
|
||||
return;
|
||||
|
||||
m_FaceCloud.m_strfacename = c_szFileName;
|
||||
CGraphicImageInstance * pGraphicImageInstance = GenerateTexture(c_szFileName);
|
||||
m_GraphicImageInstanceMap.insert(TGraphicImageInstanceMap::value_type(m_FaceCloud.m_strfacename, pGraphicImageInstance));
|
||||
}
|
||||
|
||||
auto CSkyBox::SetGradientLevel(BYTE, BYTE) -> void
|
||||
void CSkyBox::SetCloudScale(const D3DXVECTOR2 & c_rv2CloudScale)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_fCloudScaleX = c_rv2CloudScale.x;
|
||||
m_fCloudScaleY = c_rv2CloudScale.y;
|
||||
|
||||
D3DXMatrixScaling(&m_matWorldCloud, m_fCloudScaleX, m_fCloudScaleY, 1.0f);
|
||||
}
|
||||
|
||||
auto CSkyBox::SetFaceTexture(const char *, int) -> void
|
||||
void CSkyBox::SetCloudHeight(float fHeight)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_fCloudHeight = fHeight;
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudTexture(const char *) -> void
|
||||
void CSkyBox::SetCloudTextureScale(const D3DXVECTOR2 & c_rv2CloudTextureScale)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_fCloudTextureScaleX = c_rv2CloudTextureScale.x;
|
||||
m_fCloudTextureScaleY = c_rv2CloudTextureScale.y;
|
||||
|
||||
m_matTextureCloud._11 = m_fCloudTextureScaleX;
|
||||
m_matTextureCloud._22 = m_fCloudTextureScaleY;
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudScale(const D3DXVECTOR2 &) -> void
|
||||
void CSkyBox::SetCloudScrollSpeed(const D3DXVECTOR2 & c_rv2CloudScrollSpeed)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_fCloudScrollSpeedU = c_rv2CloudScrollSpeed.x;
|
||||
m_fCloudScrollSpeedV = c_rv2CloudScrollSpeed.y;
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudHeight(float) -> void
|
||||
void CSkyBox::SetSkyObjectQuadVertical(TSkyObjectQuadVector * pSkyObjectQuadVector, const D3DXVECTOR2 * c_pv2QuadPoints)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
TPDTVertex aPDTVertex;
|
||||
|
||||
DWORD dwIndex = 0;
|
||||
|
||||
pSkyObjectQuadVector->clear();
|
||||
pSkyObjectQuadVector->resize(m_ucVirticalGradientLevelUpper + m_ucVirticalGradientLevelLower);
|
||||
|
||||
unsigned char ucY;
|
||||
for (ucY = 0; ucY < m_ucVirticalGradientLevelUpper; ++ucY)
|
||||
{
|
||||
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(dwIndex++);
|
||||
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
|
||||
aPDTVertex.position.z = 1.0f - (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper);
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(0, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
|
||||
aPDTVertex.position.z = 1.0f - (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper);
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(1, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
|
||||
aPDTVertex.position.z = 1.0f - (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper);
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(2, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
|
||||
aPDTVertex.position.z = 1.0f - (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper);
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(3, aPDTVertex);
|
||||
}
|
||||
for (ucY = 0; ucY < m_ucVirticalGradientLevelLower; ++ucY)
|
||||
{
|
||||
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(dwIndex++);
|
||||
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
|
||||
aPDTVertex.position.z = -(float)(ucY + 1) / (float)(m_ucVirticalGradientLevelLower);
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = 0.5f + (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(0, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
|
||||
aPDTVertex.position.z = -(float)(ucY) / (float)(m_ucVirticalGradientLevelLower);
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = 0.5f + (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(1, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
|
||||
aPDTVertex.position.z = -(float)(ucY + 1) / (float)(m_ucVirticalGradientLevelLower);
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = 0.5f + (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(2, aPDTVertex);
|
||||
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
|
||||
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
|
||||
aPDTVertex.position.z = -(float)(ucY) / (float)(m_ucVirticalGradientLevelLower);
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = 0.5f + (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
|
||||
rSkyObjectQuad.SetVertex(3, aPDTVertex);
|
||||
}
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudTextureScale(const D3DXVECTOR2 &) -> void
|
||||
void CSkyBox::SetSkyObjectQuadHorizon(TSkyObjectQuadVector * pSkyObjectQuadVector, const D3DXVECTOR3 * c_pv3QuadPoints)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
pSkyObjectQuadVector->clear();
|
||||
pSkyObjectQuadVector->resize(1);
|
||||
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(0);
|
||||
|
||||
TPDTVertex aPDTVertex{};
|
||||
aPDTVertex.position = c_pv3QuadPoints[0];
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = 1.0f;
|
||||
rSkyObjectQuad.SetVertex(0, aPDTVertex);
|
||||
|
||||
aPDTVertex.position = c_pv3QuadPoints[1];
|
||||
aPDTVertex.texCoord.x = 0.0f;
|
||||
aPDTVertex.texCoord.y = 0.0f;
|
||||
rSkyObjectQuad.SetVertex(1, aPDTVertex);
|
||||
|
||||
aPDTVertex.position = c_pv3QuadPoints[2];
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = 1.0f;
|
||||
rSkyObjectQuad.SetVertex(2, aPDTVertex);
|
||||
|
||||
aPDTVertex.position = c_pv3QuadPoints[3];
|
||||
aPDTVertex.texCoord.x = 1.0f;
|
||||
aPDTVertex.texCoord.y = 0.0f;
|
||||
rSkyObjectQuad.SetVertex(3, aPDTVertex);
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudScrollSpeed(const D3DXVECTOR2 &) -> void
|
||||
void CSkyBox::Refresh()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
D3DXVECTOR3 v3QuadPoints[4];
|
||||
|
||||
if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_DEFAULT || m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_DIFFUSE)
|
||||
{
|
||||
if (m_ucVirticalGradientLevelUpper + m_ucVirticalGradientLevelLower <= 0)
|
||||
return;
|
||||
|
||||
D3DXVECTOR2 v2QuadPoints[2];
|
||||
|
||||
v2QuadPoints[0] = D3DXVECTOR2(1.0f, -1.0f);
|
||||
v2QuadPoints[1] = D3DXVECTOR2(-1.0f, -1.0f);
|
||||
SetSkyObjectQuadVertical(&m_Faces[0].m_SkyObjectQuadVector, v2QuadPoints);
|
||||
m_Faces[0].m_strfacename = "front";
|
||||
|
||||
v2QuadPoints[0] = D3DXVECTOR2(-1.0f, 1.0f);
|
||||
v2QuadPoints[1] = D3DXVECTOR2(1.0f, 1.0f);
|
||||
SetSkyObjectQuadVertical(&m_Faces[1].m_SkyObjectQuadVector, v2QuadPoints);
|
||||
m_Faces[1].m_strfacename = "back";
|
||||
|
||||
v2QuadPoints[0] = D3DXVECTOR2(-1.0f, -1.0f);
|
||||
v2QuadPoints[1] = D3DXVECTOR2(-1.0f, 1.0f);
|
||||
SetSkyObjectQuadVertical(&m_Faces[2].m_SkyObjectQuadVector, v2QuadPoints);
|
||||
m_Faces[2].m_strfacename = "left";
|
||||
|
||||
v2QuadPoints[0] = D3DXVECTOR2(1.0f, 1.0f);
|
||||
v2QuadPoints[1] = D3DXVECTOR2(1.0f, -1.0f);
|
||||
SetSkyObjectQuadVertical(&m_Faces[3].m_SkyObjectQuadVector, v2QuadPoints);
|
||||
m_Faces[3].m_strfacename = "right";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[4].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[4].m_strfacename = "top";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[5].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[5].m_strfacename = "bottom";
|
||||
}
|
||||
else if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_TEXTURE)
|
||||
{
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[0].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[0].m_strfacename = "front";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[1].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[1].m_strfacename = "back";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[2].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[2].m_strfacename = "left";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[3].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[3].m_strfacename = "right";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[4].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[4].m_strfacename = "top";
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
|
||||
SetSkyObjectQuadHorizon(&m_Faces[5].m_SkyObjectQuadVector, v3QuadPoints);
|
||||
m_Faces[5].m_strfacename = "bottom";
|
||||
}
|
||||
|
||||
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, 0.0f);
|
||||
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 0.0f);
|
||||
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
|
||||
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
|
||||
SetSkyObjectQuadHorizon(&m_FaceCloud.m_SkyObjectQuadVector, v3QuadPoints);
|
||||
}
|
||||
|
||||
auto CSkyBox::SetCloudColor(const TGradientColor &, const TGradientColor &, const DWORD &) -> void
|
||||
void CSkyBox::SetCloudColor(const TGradientColor & c_rColor, const TGradientColor & c_rNextColor, const DWORD & dwTransitionTime)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
TSkyObjectFace & aFaceCloud = m_FaceCloud;
|
||||
for (DWORD dwk = 0; dwk < aFaceCloud.m_SkyObjectQuadVector.size(); ++dwk)
|
||||
{
|
||||
CSkyObjectQuad & aSkyObjectQuad = aFaceCloud.m_SkyObjectQuadVector[dwk];
|
||||
for (unsigned char v = 0; v < 4; ++v)
|
||||
{
|
||||
aSkyObjectQuad.SetSrcColor(v,
|
||||
c_rColor.m_FirstColor.r,
|
||||
c_rColor.m_FirstColor.g,
|
||||
c_rColor.m_FirstColor.b,
|
||||
c_rColor.m_FirstColor.a);
|
||||
aSkyObjectQuad.SetTransition(v,
|
||||
c_rNextColor.m_FirstColor.r,
|
||||
c_rNextColor.m_FirstColor.g,
|
||||
c_rNextColor.m_FirstColor.b,
|
||||
c_rNextColor.m_FirstColor.a,
|
||||
dwTransitionTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto CSkyBox::Refresh() -> void
|
||||
void CSkyBox::SetSkyColor(const TVectorGradientColor & c_rColorVector, const TVectorGradientColor & c_rNextColorVector, long lTransitionTime)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (c_rColorVector.empty() || c_rNextColorVector.empty())
|
||||
return;
|
||||
|
||||
unsigned long ulVectorGradientColornum = 0;
|
||||
unsigned long uck;
|
||||
for (unsigned char ucj = 0; ucj < 4; ++ucj)
|
||||
{
|
||||
TSkyObjectFace & aFace = m_Faces[ucj];
|
||||
ulVectorGradientColornum = 0;
|
||||
for (uck = 0; uck < aFace.m_SkyObjectQuadVector.size(); ++uck)
|
||||
{
|
||||
if (ulVectorGradientColornum >= c_rColorVector.size() || ulVectorGradientColornum >= c_rNextColorVector.size())
|
||||
break;
|
||||
CSkyObjectQuad & aSkyObjectQuad = aFace.m_SkyObjectQuadVector[uck];
|
||||
|
||||
aSkyObjectQuad.SetSrcColor(0,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
|
||||
aSkyObjectQuad.SetTransition(0,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
|
||||
lTransitionTime);
|
||||
aSkyObjectQuad.SetSrcColor(1,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
|
||||
aSkyObjectQuad.SetTransition(1,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
|
||||
lTransitionTime);
|
||||
aSkyObjectQuad.SetSrcColor(2,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
|
||||
aSkyObjectQuad.SetTransition(2,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
|
||||
lTransitionTime);
|
||||
aSkyObjectQuad.SetSrcColor(3,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
|
||||
aSkyObjectQuad.SetTransition(3,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
|
||||
lTransitionTime);
|
||||
|
||||
ulVectorGradientColornum++;
|
||||
}
|
||||
}
|
||||
|
||||
TSkyObjectFace & aFaceTop = m_Faces[4];
|
||||
ulVectorGradientColornum = 0;
|
||||
for (uck = 0; uck < aFaceTop.m_SkyObjectQuadVector.size(); ++uck)
|
||||
{
|
||||
CSkyObjectQuad & aSkyObjectQuad = aFaceTop.m_SkyObjectQuadVector[uck];
|
||||
for (unsigned char v = 0; v < 4; ++v)
|
||||
{
|
||||
aSkyObjectQuad.SetSrcColor(v,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
|
||||
aSkyObjectQuad.SetTransition(v,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
|
||||
lTransitionTime);
|
||||
}
|
||||
}
|
||||
|
||||
TSkyObjectFace & aFaceBottom = m_Faces[5];
|
||||
ulVectorGradientColornum = c_rColorVector.size() - 1;
|
||||
for (uck = 0; uck < aFaceBottom.m_SkyObjectQuadVector.size(); ++uck)
|
||||
{
|
||||
CSkyObjectQuad & aSkyObjectQuad = aFaceBottom.m_SkyObjectQuadVector[uck];
|
||||
for (unsigned char v = 0; v < 4; ++v)
|
||||
{
|
||||
aSkyObjectQuad.SetSrcColor(v,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
|
||||
aSkyObjectQuad.SetTransition(v,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
|
||||
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
|
||||
lTransitionTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto CSkyBox::SetSkyColor(const TVectorGradientColor &, const TVectorGradientColor &, long) -> void
|
||||
void CSkyBox::StartTransition()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
m_bTransitionStarted = true;
|
||||
for (unsigned char ucj = 0; ucj < 6; ++ucj)
|
||||
m_Faces[ucj].StartTransition();
|
||||
m_FaceCloud.StartTransition();
|
||||
}
|
||||
|
||||
auto CSkyBox::StartTransition() -> void
|
||||
void CSkyBox::Update()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
CSkyObject::Update();
|
||||
|
||||
if (!m_bTransitionStarted)
|
||||
return;
|
||||
|
||||
bool bResult = false;
|
||||
for (unsigned char uci = 0; uci < 6; ++uci)
|
||||
bResult = m_Faces[uci].Update() || bResult;
|
||||
bResult = m_FaceCloud.Update() || bResult;
|
||||
|
||||
m_bTransitionStarted = bResult;
|
||||
}
|
||||
|
||||
auto CSkyBox::SetSkyObjectQuadVertical(TSkyObjectQuadVector *, const D3DXVECTOR2 *) -> void
|
||||
void CSkyBox::Render()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (!IsNativeTerrainRenderEnabled())
|
||||
return;
|
||||
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, TRUE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
|
||||
STATEMANAGER.SetTexture(1, NULL);
|
||||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||||
|
||||
STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
|
||||
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorld);
|
||||
|
||||
if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_TEXTURE)
|
||||
{
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
{
|
||||
CGraphicImageInstance * pFaceImageInstance = m_GraphicImageInstanceMap[m_Faces[i].m_strFaceTextureFileName];
|
||||
if (!pFaceImageInstance)
|
||||
break;
|
||||
|
||||
STATEMANAGER.SetTexture(0, pFaceImageInstance->GetTextureReference().GetD3DTexture());
|
||||
m_Faces[i].Render();
|
||||
}
|
||||
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
|
||||
}
|
||||
else
|
||||
{
|
||||
STATEMANAGER.SetTexture(0, NULL);
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
{
|
||||
m_Faces[i].Render();
|
||||
}
|
||||
}
|
||||
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2);
|
||||
}
|
||||
|
||||
auto CSkyBox::SetSkyObjectQuadHorizon(TSkyObjectQuadVector *, const D3DXVECTOR3 *) -> void
|
||||
void CSkyBox::RenderCloud()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
if (!IsNativeTerrainRenderEnabled())
|
||||
return;
|
||||
|
||||
CGraphicImageInstance * pCloudGraphicImageInstance = m_GraphicImageInstanceMap[m_FaceCloud.m_strfacename];
|
||||
if (!pCloudGraphicImageInstance || pCloudGraphicImageInstance->IsEmpty() || !pCloudGraphicImageInstance->GetTexturePointer())
|
||||
return;
|
||||
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, TRUE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
|
||||
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
|
||||
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
|
||||
|
||||
m_matTextureCloud._31 = m_fCloudPositionU;
|
||||
m_matTextureCloud._32 = m_fCloudPositionV;
|
||||
|
||||
DWORD dwCurTime = CTimer::Instance().GetCurrentMillisecond();
|
||||
|
||||
m_fCloudPositionU += m_fCloudScrollSpeedU * (float)(dwCurTime - m_dwlastTime) * 0.001f;
|
||||
if (m_fCloudPositionU >= 1.0f)
|
||||
m_fCloudPositionU = 0.0f;
|
||||
|
||||
m_fCloudPositionV += m_fCloudScrollSpeedV * (float)(dwCurTime - m_dwlastTime) * 0.001f;
|
||||
if (m_fCloudPositionV >= 1.0f)
|
||||
m_fCloudPositionV = 0.0f;
|
||||
|
||||
m_dwlastTime = dwCurTime;
|
||||
|
||||
STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &m_matTextureCloud);
|
||||
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATEINVALPHA_ADDCOLOR);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||||
|
||||
D3DXMATRIX matProjCloud;
|
||||
D3DXMatrixPerspectiveFovRH(&matProjCloud, D3DX_PI * 0.25f, 1.33333f, 50.0f, 999999.0f);
|
||||
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldCloud);
|
||||
STATEMANAGER.SaveTransform(D3DTS_PROJECTION, &matProjCloud);
|
||||
STATEMANAGER.SetTexture(0, pCloudGraphicImageInstance->GetTexturePointer()->GetD3DTexture());
|
||||
m_FaceCloud.Render();
|
||||
STATEMANAGER.RestoreTransform(D3DTS_PROJECTION);
|
||||
|
||||
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
|
||||
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
|
||||
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
|
||||
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#include "EterLib/StdAfx.h"
|
||||
#include "UIRenderCommands.h"
|
||||
#include "RenderCommands3D.h"
|
||||
#include "EterLib/StateManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
std::vector<UIRenderCommand> commands;
|
||||
std::uint64_t frame_id = 0;
|
||||
int canvas_width = 0;
|
||||
int canvas_height = 0;
|
||||
float clip_x1 = 0, clip_y1 = 0, clip_x2 = 0, clip_y2 = 0;
|
||||
@@ -18,14 +20,17 @@ void UIRenderGetSize(unsigned* width, unsigned* height) {
|
||||
if (height) *height = canvas_height;
|
||||
}
|
||||
void UIRenderBeginFrame() {
|
||||
++frame_id;
|
||||
commands.clear();
|
||||
clip_x1 = clip_y1 = 0;
|
||||
clip_x2 = canvas_width;
|
||||
clip_y2 = canvas_height;
|
||||
}
|
||||
std::uint64_t UIRenderFrameId() { return frame_id; }
|
||||
void UIRenderAdd(UIRenderCommand command) {
|
||||
command.clip_x1 = clip_x1; command.clip_y1 = clip_y1;
|
||||
command.clip_x2 = clip_x2; command.clip_y2 = clip_y2;
|
||||
command.behind_3d = Render3DDraws().empty();
|
||||
commands.push_back(command);
|
||||
}
|
||||
const std::vector<UIRenderCommand>& UIRenderCommands() { return commands; }
|
||||
|
||||
@@ -23,6 +23,7 @@ struct UIRenderCommand {
|
||||
// circular minimap_image_filter): the mask's texture coordinates at the quad's four corners.
|
||||
std::string mask;
|
||||
float mu[4] = {}, mv[4] = {};
|
||||
bool behind_3d = false;
|
||||
};
|
||||
|
||||
// D3DXCOLOR (0..1 floats) -> the 0xAARRGGBB the commands carry.
|
||||
@@ -54,6 +55,8 @@ struct IDirect3DBaseTexture8;
|
||||
void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture);
|
||||
// The name (as UIRenderTextureName) of the texture a D3D handle belongs to; "" for null or unknown.
|
||||
std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle);
|
||||
std::string MtCpuTextureNameFromHandle(const IDirect3DBaseTexture8* handle);
|
||||
bool MtCpuMemoryTexture(const std::string& name, UIMemoryTexture* out);
|
||||
|
||||
// A textured quad from 40250's TPDTVertex[4] (TL, TR, BL, BR) positions and texture coordinates.
|
||||
// PORT: D3D8 puts pixel centres on integers, which is why 40250 subtracts 0.5 from every vertex; the
|
||||
@@ -64,6 +67,7 @@ void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const fl
|
||||
void UIRenderSetSize(int width, int height);
|
||||
void UIRenderGetSize(unsigned* width, unsigned* height);
|
||||
void UIRenderBeginFrame();
|
||||
std::uint64_t UIRenderFrameId();
|
||||
void UIRenderAdd(UIRenderCommand command);
|
||||
const std::vector<UIRenderCommand>& UIRenderCommands();
|
||||
void UIRenderSetClip(float x, float y, float width, float height);
|
||||
|
||||
Reference in New Issue
Block a user