From add2537ecf4dbd6b752fdcd544dae4b2c3330166 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 6 Apr 2024 14:27:59 +1100 Subject: [PATCH] 3DS: Give real 3D support a try --- src/Game.c | 7 +++---- src/Graphics.h | 7 ++++++- src/Graphics_3DS.c | 44 +++++++++++++++++++++++++++++++--------- src/_GraphicsBase.h | 49 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 81 insertions(+), 26 deletions(-) diff --git a/src/Game.c b/src/Game.c index 63374513c..c8d193a6e 100644 --- a/src/Game.c +++ b/src/Game.c @@ -538,7 +538,7 @@ static void Render3D_Anaglyph(double delta, float t) { Matrix_Translate(&view_left, -0.10f, 0, 0); Matrix_Mul(&Gfx.View, &view, &view_left); - Gfx_SetColorWrite(false, true, true, false); + Gfx_Set3DLeft(); Render3DFrame(delta, t); Matrix_Translate(&proj_right, -0.07f, 0, 0); @@ -546,12 +546,11 @@ static void Render3D_Anaglyph(double delta, float t) { Matrix_Translate(&view_right, 0.10f, 0, 0); Matrix_Mul(&Gfx.View, &view, &view_right); - Gfx_ClearBuffers(GFX_BUFFER_DEPTH); - Gfx_SetColorWrite(true, false, false, false); + Gfx_Set3DRight(); Render3DFrame(delta, t); Gfx.Projection = proj; - Gfx_SetColorWrite(true, true, true, true); + Gfx_End3D(); } static void PerformScheduledTasks(double time) { diff --git a/src/Graphics.h b/src/Graphics.h index d7e9f7fa6..4d1f138d9 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -155,6 +155,11 @@ CC_API void Gfx_SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a); /* NOTE: Implicitly calls Gfx_SetColorWrite */ CC_API void Gfx_DepthOnlyRendering(cc_bool depthOnly); +/* Anaglyph 3D rendering support */ +void Gfx_Set3DLeft(void); +void Gfx_Set3DRight(void); +void Gfx_End3D(void); + /* Callback function to initialise/fill out the contents of an index buffer */ typedef void (*Gfx_FillIBFunc)(cc_uint16* indices, int count, void* obj); /* Creates a new index buffer and fills out its contents */ @@ -298,4 +303,4 @@ void Gfx_RestoreAlphaState(cc_uint8 draw); void Texture_Render(const struct Texture* tex); /* Binds then renders the given texture */ void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor); -#endif \ No newline at end of file +#endif diff --git a/src/Graphics_3DS.c b/src/Graphics_3DS.c index 11e6ebd75..34054cfe9 100644 --- a/src/Graphics_3DS.c +++ b/src/Graphics_3DS.c @@ -25,6 +25,8 @@ extern const u32 offset_shbin_size; static void GPUBuffers_DeleteUnreferenced(void); static void GPUTextures_DeleteUnreferenced(void); static cc_uint32 frameCounter; +static PackedCol clear_color; +static cc_bool rendering3D; /*########################################################################################################################* @@ -106,7 +108,8 @@ static void SwitchProgram(void) { /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* *#########################################################################################################################*/ -static C3D_RenderTarget* topTarget; +static C3D_RenderTarget* topTargetLeft; +static C3D_RenderTarget* topTargetRight; static C3D_RenderTarget* bottomTarget; static void AllocShaders(void) { @@ -131,8 +134,8 @@ static void SetDefaultState(void) { static void InitCitro3D(void) { C3D_Init(C3D_DEFAULT_CMDBUF_SIZE * 4); - topTarget = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); - C3D_RenderTargetSetOutput(topTarget, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); + topTargetLeft = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(topTargetLeft, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS); // Even though the bottom screen is 320 pixels wide, we use 400 here so that the same ortho matrix // can be used for both screens. The output is clipped to the actual screen width, anyway. @@ -186,9 +189,31 @@ void Gfx_FreeState(void) { } void Gfx_3DS_SetRenderScreen(enum Screen3DS screen) { - C3D_FrameDrawOn(screen == TOP_SCREEN ? topTarget : bottomTarget); + C3D_FrameDrawOn(screen == TOP_SCREEN ? topTargetLeft : bottomTarget); } + +/*########################################################################################################################* +*----------------------------------------------------Stereoscopic support-------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_Set3DLeft(void) { + rendering3D = true; +} + +void Gfx_Set3DRight(void) { + if (!topTargetRight) { + topTargetRight = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); + C3D_RenderTargetSetOutput(topTargetRight, GFX_TOP, GFX_RIGHT, DISPLAY_TRANSFER_FLAGS); + } + + C3D_RenderTargetClear(topTargetRight, C3D_CLEAR_ALL, clear_color, 0); + C3D_FrameDrawOn(topTargetRight); +} + +void Gfx_End3D(void) { +} + + /*########################################################################################################################* *--------------------------------------------------------GPU Textures-----------------------------------------------------* *#########################################################################################################################*/ @@ -368,7 +393,6 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) { enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); } -static PackedCol clear_color; void Gfx_ClearColor(PackedCol color) { // TODO find better way? clear_color = (PackedCol_R(color) << 24) | (PackedCol_G(color) << 16) | (PackedCol_B(color) << 8) | 0xFF; @@ -451,9 +475,10 @@ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { } void Gfx_BeginFrame(void) { - int flags = gfx_vsync ? C3D_FRAME_SYNCDRAW : 0; + rendering3D = false; + int flags = gfx_vsync ? C3D_FRAME_SYNCDRAW : 0; C3D_FrameBegin(flags); - C3D_FrameDrawOn(topTarget); + C3D_FrameDrawOn(topTargetLeft); } void Gfx_ClearBuffers(GfxBuffers buffers) { @@ -461,11 +486,12 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { if (buffers & GFX_BUFFER_COLOR) targets |= C3D_CLEAR_COLOR; if (buffers & GFX_BUFFER_DEPTH) targets |= C3D_CLEAR_DEPTH; - C3D_RenderTargetClear(topTarget, targets, clear_color, 0); - C3D_RenderTargetClear(bottomTarget, targets, 0, 0); + C3D_RenderTargetClear(topTargetLeft, targets, clear_color, 0); + C3D_RenderTargetClear(bottomTarget, targets, 0, 0); } void Gfx_EndFrame(void) { + gfxSet3D(rendering3D); C3D_FrameEnd(0); //gfxFlushBuffers(); //gfxSwapBuffers(); diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index 4662f5cb2..3c2314545 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -48,6 +48,21 @@ void Gfx_SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { void Gfx_SetTexturing(cc_bool enabled) { } /* useless */ +#ifndef CC_BUILD_3DS +void Gfx_Set3DLeft(void) { + Gfx_SetColorWrite(false, true, true, false); +} + +void Gfx_Set3DRight(void) { + Gfx_ClearBuffers(GFX_BUFFER_DEPTH); + Gfx_SetColorWrite(true, false, false, false); +} + +void Gfx_End3D(void) { + Gfx_SetColorWrite(true, true, true, true); +} +#endif + /*########################################################################################################################* *------------------------------------------------------Generic/Common-----------------------------------------------------* @@ -87,6 +102,10 @@ static void FreeDefaultResources(void) { Gfx_DeleteIb(&Gfx_defaultIb); } + +/*########################################################################################################################* +*------------------------------------------------------FPS and context----------------------------------------------------* +*#########################################################################################################################*/ #ifdef CC_BUILD_WEB static void LimitFPS(void) { /* Can't use Thread_Sleep on the web. (spinwaits instead of sleeping) */ @@ -152,17 +171,9 @@ static CC_INLINE void EndReducedPerformance(void) { } -void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { - Gfx_DeleteTexture(tex); - *tex = Gfx_CreateTexture(bmp, flags, mipmaps); -} - -void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count) { - Gfx_DeleteVb(vb); - *vb = Gfx_CreateVb(fmt, count); - return Gfx_LockVb(*vb, fmt, count); -} - +/*########################################################################################################################* +*--------------------------------------------------------2D drawing-------------------------------------------------------* +*#########################################################################################################################*/ #ifndef CC_BUILD_3DS void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol color) { struct VertexColoured* v; @@ -246,6 +257,10 @@ void Gfx_End2D(void) { if (gfx_hadFog) Gfx_SetFog(true); } + +/*########################################################################################################################* +*--------------------------------------------------------Misc/Utils-------------------------------------------------------* +*#########################################################################################################################*/ void Gfx_SetupAlphaState(cc_uint8 draw) { if (draw == DRAW_TRANSLUCENT) Gfx_SetAlphaBlending(true); if (draw == DRAW_TRANSPARENT) Gfx_SetAlphaTest(true); @@ -260,7 +275,6 @@ void Gfx_RestoreAlphaState(cc_uint8 draw) { if (draw == DRAW_SPRITE) Gfx_SetAlphaTest(false); } - static CC_INLINE float Reversed_CalcZNear(float fov, int depthbufferBits) { /* With reversed z depth, near Z plane can be much closer (with sufficient depth buffer precision) */ /* This reduces clipping with high FOV without sacrificing depth precision for faraway objects */ @@ -286,6 +300,11 @@ static void PrintMaxTextureInfo(cc_string* info) { /*########################################################################################################################* *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ +void Gfx_RecreateTexture(GfxResourceID* tex, struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { + Gfx_DeleteTexture(tex); + *tex = Gfx_CreateTexture(bmp, flags, mipmaps); +} + static void CopyTextureData(void* dst, int dstStride, const struct Bitmap* src, int srcStride) { /* We need to copy scanline by scanline, as generally srcStride != dstStride */ cc_uint8* src_ = (cc_uint8*)src->scan0; @@ -415,6 +434,12 @@ void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor) { /*########################################################################################################################* *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ +void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count) { + Gfx_DeleteVb(vb); + *vb = Gfx_CreateVb(fmt, count); + return Gfx_LockVb(*vb, fmt, count); +} + static GfxResourceID Gfx_AllocStaticVb( VertexFormat fmt, int count); static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices);