mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 03:02:30 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
289
src/gx/font/CGxStringBatch.cpp
Normal file
289
src/gx/font/CGxStringBatch.cpp
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
#include "gx/font/CGxStringBatch.hpp"
|
||||
#include "gx/font/CGxFont.hpp"
|
||||
#include "gx/Buffer.hpp"
|
||||
#include "gx/CGxBatch.hpp"
|
||||
#include "gx/Device.hpp"
|
||||
#include "gx/Draw.hpp"
|
||||
#include "gx/Font.hpp"
|
||||
#include "gx/Gx.hpp"
|
||||
#include "gx/RenderState.hpp"
|
||||
#include "gx/Shader.hpp"
|
||||
#include "gx/Texture.hpp"
|
||||
#include "gx/Transform.hpp"
|
||||
#include <cmath>
|
||||
#include <storm/Error.hpp>
|
||||
|
||||
bool BATCHEDRENDERFONTDESC::s_billboarded;
|
||||
CGxBuf* BATCHEDRENDERFONTDESC::s_indexBuf;
|
||||
CGxPool* BATCHEDRENDERFONTDESC::s_indexPool;
|
||||
|
||||
int32_t SetProjection() {
|
||||
float minX, maxX, minY, maxY, minZ, maxZ;
|
||||
GxXformViewport(minX, maxX, minY, maxY, minZ, maxZ);
|
||||
|
||||
float v14 = 0.0f;
|
||||
float v15 = 0.0f;
|
||||
|
||||
if (!GxCaps()->m_pixelCenterOnEdge) {
|
||||
v14 = -0.5f;
|
||||
v15 = 0.5f;
|
||||
}
|
||||
|
||||
C44Matrix proj;
|
||||
|
||||
uint32_t pixelWidth = GetScreenPixelWidth();
|
||||
float pixelMinX = floor(minX * pixelWidth);
|
||||
float pixelMaxX = floor(maxX * pixelWidth);
|
||||
|
||||
if (pixelMinX >= pixelMaxX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pixelHeight = GetScreenPixelHeight();
|
||||
float pixelMinY = floor(minY * pixelHeight);
|
||||
float pixelMaxY = floor(maxY * pixelHeight);
|
||||
|
||||
if (pixelMinY >= pixelMaxY) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pixelHeight > pixelMaxY) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
pixelMinX += v14;
|
||||
pixelMaxX += v14;
|
||||
pixelMinY += v15;
|
||||
pixelMaxY += v15;
|
||||
|
||||
GxuXformCreateOrthoDepth(pixelMinX, pixelMaxX, pixelMinY, pixelMaxY, -5000.0f, 5000.0f, proj);
|
||||
GxXformSetProjection(proj);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BATCHEDRENDERFONTDESC::Initialize() {
|
||||
CGxPool* indexPool = GxPoolCreate(
|
||||
GxPoolTarget_Index,
|
||||
GxPoolUsage_Static,
|
||||
6144,
|
||||
GxPoolHintBit_Unk0,
|
||||
"BATCHEDRENDERFONTDESC_idx"
|
||||
);
|
||||
|
||||
CGxBuf* indexBuf = GxBufCreate(
|
||||
indexPool,
|
||||
2,
|
||||
3072,
|
||||
0
|
||||
);
|
||||
|
||||
BATCHEDRENDERFONTDESC::s_indexPool = indexPool;
|
||||
BATCHEDRENDERFONTDESC::s_indexBuf = indexBuf;
|
||||
}
|
||||
|
||||
void BATCHEDRENDERFONTDESC::InitializeIndexBuff() {
|
||||
char* indexData = g_theGxDevicePtr->BufLock(BATCHEDRENDERFONTDESC::s_indexBuf);
|
||||
uint16_t* indexBuf = reinterpret_cast<uint16_t*>(indexData);
|
||||
|
||||
uint16_t index = 0;
|
||||
|
||||
for (int32_t i = 0; i < 512; i++) {
|
||||
indexBuf[i * 6 + 0] = index + 0;
|
||||
indexBuf[i * 6 + 1] = index + 2;
|
||||
indexBuf[i * 6 + 2] = index + 1;
|
||||
indexBuf[i * 6 + 3] = index + 2;
|
||||
indexBuf[i * 6 + 4] = index + 3;
|
||||
indexBuf[i * 6 + 5] = index + 1;
|
||||
|
||||
index += 4;
|
||||
}
|
||||
|
||||
GxBufUnlock(BATCHEDRENDERFONTDESC::s_indexBuf, 0);
|
||||
};
|
||||
|
||||
CGxVertexPCT* BATCHEDRENDERFONTDESC::UnlockVertexPtrAndRender(CGxBuf*& buf, int32_t count) {
|
||||
GxBufUnlock(buf, sizeof(CGxVertexPCT) * count);
|
||||
|
||||
if (!BATCHEDRENDERFONTDESC::s_indexBuf->unk1C || !BATCHEDRENDERFONTDESC::s_indexBuf->unk1D) {
|
||||
BATCHEDRENDERFONTDESC::InitializeIndexBuff();
|
||||
}
|
||||
|
||||
if (BATCHEDRENDERFONTDESC::s_indexBuf->unk1C && BATCHEDRENDERFONTDESC::s_indexBuf->unk1D) {
|
||||
GxPrimVertexPtr(buf, GxVBF_PCT);
|
||||
GxPrimIndexPtr(BATCHEDRENDERFONTDESC::s_indexBuf);
|
||||
|
||||
CGxBatch batch;
|
||||
batch.m_primType = GxPrim_Triangles;
|
||||
batch.m_start = 0;
|
||||
batch.m_count = 6 * (count / 4);
|
||||
batch.m_minIndex = 0;
|
||||
batch.m_maxIndex = count - 1;
|
||||
|
||||
GxDraw(&batch, 1);
|
||||
}
|
||||
|
||||
return reinterpret_cast<CGxVertexPCT*>(g_theGxDevicePtr->BufLock(buf));
|
||||
}
|
||||
|
||||
void BATCHEDRENDERFONTDESC::RenderBatch() {
|
||||
if (!BATCHEDRENDERFONTDESC::s_indexPool) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto string = this->m_strings.Head(); string; string = this->m_strings.Next(string)) {
|
||||
string->CheckGeometry();
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < 8; i++) {
|
||||
this->m_face->m_textureCache[i].UpdateDirty();
|
||||
}
|
||||
|
||||
int32_t maxBatchCapacity = 2048;
|
||||
|
||||
CGxBuf* vertexStream = g_theGxDevicePtr->BufStream(GxPoolTarget_Vertex, 0x18, maxBatchCapacity);
|
||||
char* vertexData = g_theGxDevicePtr->BufLock(vertexStream);
|
||||
CGxVertexPCT* vertexBuf = reinterpret_cast<CGxVertexPCT*>(vertexData);
|
||||
|
||||
for (int32_t i = 0; i < 8; i++) {
|
||||
auto& textureCache = this->m_face->m_textureCache[i];
|
||||
auto texture = textureCache.m_texture;
|
||||
|
||||
if (texture) {
|
||||
auto gxTex = TextureGetGxTex(reinterpret_cast<CTexture*>(texture), 1, nullptr);
|
||||
|
||||
if (gxTex) {
|
||||
GxRsSet(GxRs_Texture0, gxTex);
|
||||
|
||||
for (auto string = this->m_strings.Head(); string; string = this->m_strings.Next(string)) {
|
||||
auto line = string->m_textLines[i];
|
||||
|
||||
if (line) {
|
||||
int32_t vertsNeeded = string->CalculateVertsNeeded(i);
|
||||
int32_t batchOffset = 0;
|
||||
int32_t batchCapacity = maxBatchCapacity;
|
||||
|
||||
while (vertsNeeded) {
|
||||
int32_t batchCount = std::min(vertsNeeded, batchCapacity);
|
||||
|
||||
string->WriteGeometry(vertexBuf, i, batchOffset, batchCount);
|
||||
|
||||
vertsNeeded -= batchCount;
|
||||
batchOffset += batchCount;
|
||||
batchCapacity -= batchCount;
|
||||
vertexBuf += batchCount;
|
||||
|
||||
if (!batchCapacity) {
|
||||
vertexBuf = this->UnlockVertexPtrAndRender(vertexStream, maxBatchCapacity);
|
||||
batchCapacity = maxBatchCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
if (batchCapacity != maxBatchCapacity) {
|
||||
vertexBuf = this->UnlockVertexPtrAndRender(vertexStream, maxBatchCapacity - batchCapacity);
|
||||
batchCapacity = maxBatchCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_theGxDevicePtr->BufUnlock(vertexStream, 0);
|
||||
}
|
||||
|
||||
CGxStringBatch::~CGxStringBatch() {
|
||||
this->m_fontBatch.Clear();
|
||||
}
|
||||
|
||||
void CGxStringBatch::AddString(CGxString* string) {
|
||||
STORM_ASSERT(string);
|
||||
STORM_ASSERT(string->m_currentFace);
|
||||
|
||||
auto face = string->m_currentFace;
|
||||
uint32_t hashval = reinterpret_cast<uintptr_t>(face);
|
||||
HASHKEY_PTR key = { face };
|
||||
|
||||
auto batch = this->m_fontBatch.Ptr(hashval, key);
|
||||
|
||||
if (!batch) {
|
||||
batch = this->m_fontBatch.New(hashval, key, 0, 0);
|
||||
batch->m_face = face;
|
||||
}
|
||||
|
||||
batch->m_strings.LinkToTail(string);
|
||||
}
|
||||
|
||||
void CGxStringBatch::RenderBatch() {
|
||||
// TODO
|
||||
// if (!g_perf) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
C44Matrix oldProjection;
|
||||
C44Matrix oldView;
|
||||
|
||||
GxXformProjection(oldProjection);
|
||||
GxXformView(oldView);
|
||||
|
||||
GxRsPush();
|
||||
|
||||
GxRsSet(GxRs_Fog, 0);
|
||||
GxRsSet(GxRs_Culling, 0);
|
||||
GxRsSet(GxRs_BlendingMode, GxBlend_Alpha);
|
||||
GxRsSetAlphaRef();
|
||||
|
||||
int32_t setProjection;
|
||||
int32_t stereoEnabled;
|
||||
|
||||
if (this->m_flags & 0x1) {
|
||||
BATCHEDRENDERFONTDESC::s_billboarded = true;
|
||||
|
||||
GxRsSet(GxRs_DepthTest, 1);
|
||||
GxRsSet(GxRs_DepthWrite, 1);
|
||||
GxRsSet(GxRs_AlphaRef, 1);
|
||||
|
||||
setProjection = 1;
|
||||
stereoEnabled = 0;
|
||||
} else {
|
||||
C44Matrix view;
|
||||
GxXformSetView(view);
|
||||
|
||||
GxRsSet(GxRs_DepthTest, 0);
|
||||
GxRsSet(GxRs_DepthWrite, 0);
|
||||
|
||||
setProjection = SetProjection();
|
||||
stereoEnabled = g_theGxDevicePtr->StereoEnabled();
|
||||
}
|
||||
|
||||
CGxShader* vs = g_fontVertexShader[stereoEnabled ? 1 : 0];
|
||||
CGxShader* ps = g_fontPixelShader[0];
|
||||
|
||||
if (setProjection && vs->Valid() && ps->Valid()) {
|
||||
GxRsSet(GxRs_VertexShader, vs);
|
||||
GxRsSet(GxRs_PixelShader, ps);
|
||||
|
||||
C44Matrix viewProjMat;
|
||||
GxXformViewProjNativeTranspose(viewProjMat);
|
||||
GxShaderConstantsSet(GxSh_Vertex, 0, reinterpret_cast<float*>(&viewProjMat), 4);
|
||||
|
||||
for (auto fontBatch = this->m_fontBatch.Head(); fontBatch; fontBatch = this->m_fontBatch.Next(fontBatch)) {
|
||||
if (fontBatch->m_strings.Head()) {
|
||||
fontBatch->RenderBatch();
|
||||
|
||||
if (this->m_flags & 0x2) {
|
||||
// TODO
|
||||
}
|
||||
} else {
|
||||
this->m_fontBatch.Unlink(fontBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BATCHEDRENDERFONTDESC::s_billboarded = false;
|
||||
|
||||
GxRsPop();
|
||||
|
||||
GxXformSetView(oldView);
|
||||
GxXformSetProjection(oldProjection);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue