Even more DolphinCGraphics

This commit is contained in:
2022-12-01 00:58:57 -05:00
parent 9fcf74b45b
commit dd8dd94f36
26 changed files with 413 additions and 65 deletions

View File

@@ -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();
}