mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-12-21 07:39:11 +00:00
Even more DolphinCGraphics
This commit is contained in:
@@ -2,8 +2,11 @@
|
||||
|
||||
#include "Kyoto/Basics/COsContext.hpp"
|
||||
#include "Kyoto/Basics/CStopwatch.hpp"
|
||||
#include "Kyoto/CFrameDelayedKiller.hpp"
|
||||
#include "Kyoto/Graphics/CGX.hpp"
|
||||
#include "Kyoto/Graphics/CGraphicsSys.hpp"
|
||||
#include "Kyoto/Graphics/CTexture.hpp"
|
||||
#include "Kyoto/Math/CRelAngle.hpp"
|
||||
|
||||
#include "dolphin/vi.h"
|
||||
|
||||
@@ -250,7 +253,7 @@ bool CGraphics::mIsGXModelMatrixIdentity = true;
|
||||
bool CGraphics::mFirstFrame = true;
|
||||
bool CGraphics::mUseVideoFilter = true;
|
||||
float CGraphics::mBrightness = 1.f;
|
||||
Vec2 CGraphics::mBrightnessRange = {0.f, 2.f};
|
||||
// Vec2 CGraphics::mBrightnessRange = {0.f, 2.f};
|
||||
|
||||
bool CGraphics::Startup(const COsContext& osContext, uint fifoSize, void* fifoBase) {
|
||||
mpFifo = fifoBase;
|
||||
@@ -384,6 +387,7 @@ void CGraphics::EnableLight(ERglLight light) {
|
||||
|
||||
static inline GXLightID get_hw_light_index(ERglLight light) {
|
||||
#if NONMATCHING
|
||||
// one instruction, no branches
|
||||
return static_cast< GXLightID >((light << 1) & (GX_MAX_LIGHT - 1));
|
||||
#else
|
||||
if (light == kLight0) {
|
||||
@@ -527,19 +531,18 @@ void CGraphics::SetViewPointMatrix(const CTransform4f& xf) {
|
||||
void CGraphics::SetIdentityViewPointMatrix() {
|
||||
mViewMatrix = CTransform4f::Identity();
|
||||
MTXIdentity(mGXViewPointMatrix);
|
||||
mGXViewPointMatrix[2][2] = 0.0;
|
||||
mGXViewPointMatrix[1][1] = 0.0;
|
||||
mGXViewPointMatrix[1][2] = 1.0;
|
||||
mGXViewPointMatrix[2][1] = -1.0;
|
||||
mGXViewPointMatrix[2][2] = 0.f;
|
||||
mGXViewPointMatrix[1][1] = 0.f;
|
||||
mGXViewPointMatrix[1][2] = 1.f;
|
||||
mGXViewPointMatrix[2][1] = -1.f;
|
||||
mViewPoint = CVector3f::Zero();
|
||||
SetViewMatrix();
|
||||
}
|
||||
|
||||
// TODO: non-matching
|
||||
void CGraphics::SetModelMatrix(const CTransform4f& xf) {
|
||||
if (&xf == &CTransform4f::Identity()) {
|
||||
if (!mIsGXModelMatrixIdentity) {
|
||||
mModelMatrix = CTransform4f::Identity();
|
||||
mModelMatrix = xf;
|
||||
mIsGXModelMatrixIdentity = true;
|
||||
SetViewMatrix();
|
||||
}
|
||||
@@ -570,3 +573,294 @@ void CGraphics::SetIdentityModelMatrix() {
|
||||
SetViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::SetOrtho(float left, float right, float top, float bottom, float znear,
|
||||
float zfar) {
|
||||
mProj = CProjectionState(false, left, right, top, bottom, znear, zfar);
|
||||
FlushProjection();
|
||||
}
|
||||
|
||||
// TODO non-matching (regswaps)
|
||||
void CGraphics::SetPerspective(float fovy, float aspect, float znear, float zfar) {
|
||||
float t = tan(CRelAngle::FromDegrees(fovy).AsRadians() / 2.f);
|
||||
float top = znear * 2.f * t * 0.5f;
|
||||
float right = aspect * 2.f * znear * t * 0.5f;
|
||||
mProj = CProjectionState(true, -right, right, top, -top, znear, zfar);
|
||||
FlushProjection();
|
||||
}
|
||||
|
||||
CMatrix4f CGraphics::GetPerspectiveProjectionMatrix() {
|
||||
#if NONMATCHING
|
||||
// construct in place
|
||||
return CMatrix4f(
|
||||
#else
|
||||
CMatrix4f mtx(
|
||||
#endif
|
||||
// clang-format off
|
||||
(mProj.GetNear() * 2.f) / (mProj.GetRight() - mProj.GetLeft()),
|
||||
-(mProj.GetRight() + mProj.GetLeft()) / (mProj.GetRight() - mProj.GetLeft()),
|
||||
0.f,
|
||||
0.f,
|
||||
0.f,
|
||||
-(mProj.GetTop() + mProj.GetBottom()) / (mProj.GetTop() - mProj.GetBottom()),
|
||||
(mProj.GetNear() * 2.f) / (mProj.GetTop() - mProj.GetBottom()),
|
||||
0.f,
|
||||
0.f,
|
||||
(mProj.GetFar() + mProj.GetNear()) / (mProj.GetFar() - mProj.GetNear()),
|
||||
0.f,
|
||||
-(mProj.GetFar() * 2.f * mProj.GetNear()) / (mProj.GetFar() - mProj.GetNear()),
|
||||
0.f,
|
||||
1.f,
|
||||
0.f,
|
||||
0.f
|
||||
// clang-format on
|
||||
);
|
||||
#if !NONMATCHING
|
||||
return mtx;
|
||||
#endif
|
||||
}
|
||||
|
||||
CMatrix4f CGraphics::CalculatePerspectiveMatrix(float fovy, float aspect, float znear, float zfar) {
|
||||
float t = tan(CRelAngle::FromDegrees(fovy).AsRadians() / 2.f);
|
||||
float right = aspect * 2.f * znear * t * 0.5f;
|
||||
float left = -right;
|
||||
float top = znear * 2.f * t * 0.5f;
|
||||
float bottom = -top;
|
||||
#if NONMATCHING
|
||||
// construct in place
|
||||
return CMatrix4f(
|
||||
#else
|
||||
CMatrix4f mtx(
|
||||
#endif
|
||||
// clang-format off
|
||||
(2.f * znear) / (right - left),
|
||||
-(right + left) / (right - left),
|
||||
0.f,
|
||||
0.f,
|
||||
0.f,
|
||||
-(top + bottom) / (top - bottom),
|
||||
(2.f * znear) / (top - bottom),
|
||||
0.f,
|
||||
0.f,
|
||||
(zfar + znear) / (zfar - znear),
|
||||
0.f,
|
||||
-(2.f * zfar * znear) / (zfar - znear),
|
||||
0.f,
|
||||
1.f,
|
||||
0.f,
|
||||
0.f
|
||||
// clang-format on
|
||||
);
|
||||
#if !NONMATCHING
|
||||
return mtx;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGraphics::SetViewport(int left, int bottom, int width, int height) {
|
||||
mViewport.mLeft = left;
|
||||
mViewport.mTop = mRenderModeObj.efbHeight - (bottom + height);
|
||||
mViewport.mWidth = width;
|
||||
mViewport.mHeight = height;
|
||||
mViewport.mHalfWidth = static_cast< float >(width / 2);
|
||||
mViewport.mHalfHeight = static_cast< float >(height / 2);
|
||||
GXSetViewport(static_cast< float >(mViewport.mLeft), static_cast< float >(mViewport.mTop),
|
||||
static_cast< float >(mViewport.mWidth), static_cast< float >(mViewport.mHeight),
|
||||
mDepthNear, mDepthFar);
|
||||
}
|
||||
|
||||
void CGraphics::SetScissor(int left, int bottom, int width, int height) {
|
||||
GXSetScissor(left, mRenderModeObj.efbHeight - (bottom + height), width, height);
|
||||
}
|
||||
|
||||
void CGraphics::SetAmbientColor(const CColor& color) {
|
||||
CGX::SetChanAmbColor(CGX::Channel0, color.GetGXColor());
|
||||
CGX::SetChanAmbColor(CGX::Channel1, color.GetGXColor());
|
||||
}
|
||||
|
||||
void CGraphics::SetCopyClear(const CColor& color, float depth) {
|
||||
mClearColor = color;
|
||||
mClearDepthValue = static_cast< u32 >(depth * GX_MAX_Z24);
|
||||
GXSetCopyClear(color.GetGXColor(), mClearDepthValue);
|
||||
}
|
||||
|
||||
void CGraphics::SetClearColor(const CColor& color) {
|
||||
mClearColor = color;
|
||||
GXSetCopyClear(color.GetGXColor(), mClearDepthValue);
|
||||
}
|
||||
|
||||
void CGraphics::ClearBackAndDepthBuffers() {
|
||||
GXInvalidateTexAll();
|
||||
if (mRenderModeObj.field_rendering) {
|
||||
GXSetViewportJitter(0.f, 0.f, static_cast< float >(mRenderModeObj.fbWidth),
|
||||
static_cast< float >(mRenderModeObj.xfbHeight), 0.f, 1.f, VIGetNextField());
|
||||
} else {
|
||||
GXSetViewport(0.f, 0.f, static_cast< float >(mRenderModeObj.fbWidth),
|
||||
static_cast< float >(mRenderModeObj.xfbHeight), 0.f, 1.f);
|
||||
}
|
||||
GXInvalidateVtxCache();
|
||||
}
|
||||
|
||||
void CGraphics::BeginScene() { ClearBackAndDepthBuffers(); }
|
||||
|
||||
void CGraphics::SwapBuffers() {
|
||||
GXDisableBreakPt();
|
||||
mFlippingState = 1;
|
||||
}
|
||||
|
||||
void CGraphics::VideoPreCallback(u32 retraceCount) {
|
||||
if (mNumBreakpointsWaiting != 0 && mFlippingState == 1) {
|
||||
if (mFirstFrame) {
|
||||
VISetBlack(GX_FALSE);
|
||||
mFirstFrame = false;
|
||||
}
|
||||
VISetNextFrameBuffer(mpCurrenFrameBuf);
|
||||
VIFlush();
|
||||
void* frameBuf = mpCurrenFrameBuf == mpFrameBuf1 ? mpFrameBuf2 : mpFrameBuf1;
|
||||
mFlippingState = 2;
|
||||
mpCurrenFrameBuf = frameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::VideoPostCallback(u32 retraceCount) {
|
||||
if (mNumBreakpointsWaiting != 0) {
|
||||
if (mFlippingState == 2) {
|
||||
--mNumBreakpointsWaiting;
|
||||
mFlippingState = 0;
|
||||
CStopwatch& timer = sFPSTimer;
|
||||
float elapsed = timer.GetElapsedTime();
|
||||
mLastFramesPerSecond = mFramesPerSecond;
|
||||
mFramesPerSecond = 1.f / elapsed;
|
||||
timer.Reset();
|
||||
mInterruptLastFrameUsedAbove = VIGetNextField() == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGraphics::EndScene() {
|
||||
CGX::SetZMode(true, GX_LEQUAL, true);
|
||||
volatile int& numBreakPt = const_cast< volatile int& >(mNumBreakpointsWaiting);
|
||||
while (numBreakPt > 0) {
|
||||
OSYieldThread();
|
||||
}
|
||||
++mNumBreakpointsWaiting;
|
||||
void*& frameBuf = mpCurrenFrameBuf;
|
||||
float brightness = CMath::Clamp(0.f, mBrightness, 2.f);
|
||||
static const u8 copyFilter[7] = {0x00, 0x00, 0x15, 0x16, 0x15, 0x00, 0x00};
|
||||
const u8* inFilter = mUseVideoFilter ? mRenderModeObj.vfilter : copyFilter;
|
||||
u8 vfilter[7];
|
||||
for (int i = 0; i < 7; i++) {
|
||||
vfilter[i] = static_cast< u8 >(static_cast< float >(inFilter[i]) * brightness);
|
||||
}
|
||||
GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern, true, vfilter);
|
||||
GXCopyDisp(frameBuf, mIsBeginSceneClearFb ? GX_TRUE : GX_FALSE);
|
||||
GXSetCopyFilter(mRenderModeObj.aa, mRenderModeObj.sample_pattern,
|
||||
mUseVideoFilter ? GX_TRUE : GX_FALSE, mRenderModeObj.vfilter);
|
||||
GXSetBreakPtCallback(SwapBuffers);
|
||||
VISetPreRetraceCallback(VideoPreCallback);
|
||||
VISetPostRetraceCallback(VideoPostCallback);
|
||||
GXFlush();
|
||||
GXFifoObj* fifo = GXGetGPFifo();
|
||||
void* readPtr;
|
||||
void* writePtr;
|
||||
GXGetFifoPtrs(fifo, &readPtr, &writePtr);
|
||||
GXEnableBreakPt(writePtr);
|
||||
mLastFrameUsedAbove = mInterruptLastFrameUsedAbove;
|
||||
++mFrameCounter;
|
||||
CFrameDelayedKiller::sub_8036cb90();
|
||||
}
|
||||
|
||||
void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write) {
|
||||
mDepthFunc = comp;
|
||||
CGX::SetZMode(static_cast< uchar >(test), static_cast< GXCompare >(comp),
|
||||
static_cast< uchar >(write));
|
||||
}
|
||||
|
||||
void CGraphics::SetCullMode(ERglCullMode cullMode) {
|
||||
mCullMode = cullMode;
|
||||
GXSetCullMode(static_cast< GXCullMode >(cullMode));
|
||||
}
|
||||
|
||||
void CGraphics::SetBlendMode(ERglBlendMode mode, ERglBlendFactor src, ERglBlendFactor dst,
|
||||
ERglLogicOp op) {
|
||||
CGX::SetBlendMode(static_cast< GXBlendMode >(mode), static_cast< GXBlendFactor >(src),
|
||||
static_cast< GXBlendFactor >(dst), static_cast< GXLogicOp >(op));
|
||||
}
|
||||
|
||||
void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, uchar ref0, ERglAlphaOp op,
|
||||
ERglAlphaFunc comp1, uchar ref1) {
|
||||
CGX::SetAlphaCompare(static_cast< GXCompare >(comp0), static_cast< uchar >(ref0),
|
||||
static_cast< GXAlphaOp >(op), static_cast< GXCompare >(comp1),
|
||||
static_cast< uchar >(ref1));
|
||||
}
|
||||
|
||||
static const GXVtxDescList skPosColorTexDirect[] = {
|
||||
{GX_VA_POS, GX_DIRECT},
|
||||
{GX_VA_CLR0, GX_DIRECT},
|
||||
{GX_VA_TEX0, GX_DIRECT},
|
||||
{GX_VA_NULL, GX_DIRECT},
|
||||
};
|
||||
|
||||
// TODO non-matching (regswaps)
|
||||
void CGraphics::Render2D(const CTexture& tex, int x, int y, int w, int h, const CColor& col) {
|
||||
Mtx44 proj;
|
||||
MTXOrtho(proj, mViewport.mHeight / 2, -mViewport.mHeight / 2, -mViewport.mWidth / 2,
|
||||
mViewport.mWidth / 2, -1.f, -10.f);
|
||||
GXSetProjection(proj, GX_ORTHOGRAPHIC);
|
||||
uint c = col.GetColor_u32();
|
||||
|
||||
Mtx mtx;
|
||||
MTXIdentity(mtx);
|
||||
GXLoadPosMtxImm(mtx, GX_PNMTX0);
|
||||
|
||||
float x1 = x - mViewport.mWidth / 2;
|
||||
float y1 = y - mViewport.mHeight / 2;
|
||||
float x2 = x1 + w;
|
||||
float y2 = y1 + h;
|
||||
|
||||
// Save state + setup
|
||||
CGX::SetVtxDescv(skPosColorTexDirect);
|
||||
SetTevStates(6);
|
||||
mLightsWereOn = mLightActive;
|
||||
if (mLightActive != 0) {
|
||||
DisableAllLights();
|
||||
}
|
||||
ERglCullMode cullMode = mCullMode;
|
||||
SetCullMode(kCM_None);
|
||||
tex.Load(GX_TEXMAP0, CTexture::kCM_Repeat);
|
||||
|
||||
// Draw
|
||||
CGX::Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 4);
|
||||
GXPosition3f32(x1, y1, 1.f);
|
||||
GXColor1u32(c);
|
||||
GXTexCoord2f32(0.f, 0.f);
|
||||
GXPosition3f32(x2, y1, 1.f);
|
||||
GXColor1u32(c);
|
||||
GXTexCoord2f32(1.f, 0.f);
|
||||
GXPosition3f32(x1, y2, 1.f);
|
||||
GXColor1u32(c);
|
||||
GXTexCoord2f32(0.f, 1.f);
|
||||
GXPosition3f32(x2, y2, 1.f);
|
||||
GXColor1u32(c);
|
||||
GXTexCoord2f32(1.f, 1.f);
|
||||
CGX::End();
|
||||
|
||||
// Restore state
|
||||
if (mLightsWereOn != 0) {
|
||||
SetLightState(mLightsWereOn);
|
||||
}
|
||||
FlushProjection();
|
||||
mIsGXModelMatrixIdentity = false;
|
||||
SetModelMatrix(mModelMatrix);
|
||||
SetCullMode(cullMode);
|
||||
}
|
||||
|
||||
void CGraphics::DrawPrimitive(ERglPrimitive primitive, const float* pos, const CVector3f& normal,
|
||||
const CColor& col, int numVerts) {
|
||||
StreamBegin(primitive);
|
||||
StreamNormal(reinterpret_cast< const float* >(&normal));
|
||||
StreamColor(col);
|
||||
for (int i = 0; i < numVerts; ++i) {
|
||||
StreamVertex(pos + i * 3);
|
||||
}
|
||||
StreamEnd();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user