diff --git a/examples/99_testscene/main_test_depth b/examples/99_testscene/main_test_depth new file mode 100644 index 0000000..5d032b5 --- /dev/null +++ b/examples/99_testscene/main_test_depth @@ -0,0 +1,298 @@ +#include +#include + +#include +#include +#include + +#include "debug_overlay.h" + +#define FB_COUNT 3 + +/** + * Simple example with a spinning quad. + * This shows how to manually generate geometry and draw it, + * although most o the time you should use the builtin model format. + */ +int main() +{ + profile_data.frame_count = 0; + + // @TODO: game random slows down under different code. + // investigate what part of the shifting code/data is causing this + //#if RSPQ_PROFILE == 1 + debug_init_isviewer(); + debug_init_usblog(); + //#endif + + asset_init_compression(2); + + dfs_init(DFS_DEFAULT_LOCATION); + + display_init(RESOLUTION_320x240, DEPTH_16_BPP, FB_COUNT, GAMMA_NONE, FILTERS_RESAMPLE_ANTIALIAS); + + rdpq_init(); + rspq_profile_start(); + //rdpq_debug_start(); + //rdpq_debug_log(true); + + bool testClip = false; + + joypad_init(); + t3d_init((T3DInitParams){}); + T3DViewport viewport = t3d_viewport_create_buffered(FB_COUNT); + if(testClip) { + viewport.guardBandScale = 1; + } + + t3d_debug_print_init(); + sprite_t *spriteLogo = sprite_load("rom:/logo.ia8.sprite"); + T3DModel *model = t3d_model_load("rom://scene.t3dm"); + + T3DMat4 modelMat; // matrix for our model, this is a "normal" float matrix + t3d_mat4_identity(&modelMat); + // Now allocate a fixed-point matrix, this is what t3d uses internally. + T3DMat4FP* modelMatFP = malloc_uncached(sizeof(T3DMat4FP) * 3); + T3DMetrics* metrics = malloc_uncached(sizeof(T3DMetrics)); + + T3DVec3 camPos = {{2.9232f, 67.6248f, 61.1093f}}; + if(testClip)camPos = (T3DVec3){{2.9232f, 37.6248f, 31.1093f}}; + T3DVec3 camTarget = {{0,0,0}}; + T3DVec3 camDir = {{0,0,1}}; + + float camRotX = 1.544792654048f; + float camRotY = 4.05f; + + uint8_t colorAmbient[4] = {190, 190, 150, 0xFF}; + //uint8_t colorAmbient[4] = {40, 40, 40, 0xFF}; + uint8_t colorDir[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + + T3DVec3 lightDirVec = {{0.0f, 1.0f, 1.0f}}; + t3d_vec3_norm(&lightDirVec); + + float rotAngle = 0.0f; + T3DVec3 rotAxis = {{1.0f, 2.5f, 0.25f}}; + t3d_vec3_norm(&rotAxis); + + double lastTimeMs = 0; + float time = 0.0f; + + bool requestDisplayMetrics = false; + bool displayMetrics = false; + float last3dFPS = 0.0f; + float nearFarScale = 1.0f; + + float FAR_VAL = 50.0f; + + float vertFxTime = 0; + int vertFxFunc = T3D_VERTEX_FX_NONE; + float colorExposure = 1.0f; + int16_t uvOffset[2] = {0,0}; + + for(uint64_t frame = 0;; ++frame) + { + joypad_poll(); + joypad_inputs_t joypad = joypad_get_inputs(JOYPAD_PORT_1); + joypad_buttons_t btn = joypad_get_buttons_pressed(JOYPAD_PORT_1); + if(joypad.stick_x < 10 && joypad.stick_x > -10)joypad.stick_x = 0; + if(joypad.stick_y < 10 && joypad.stick_y > -10)joypad.stick_y = 0; + + double nowMs = (double)get_ticks_us() / 1000.0; + float deltaTime = (float)(nowMs - lastTimeMs); + lastTimeMs = nowMs; + time += deltaTime; + + vertFxTime = fmaxf(vertFxTime - deltaTime, 0.0f); + + + if(joypad.btn.d_up || joypad.btn.d_down || joypad.btn.d_left || joypad.btn.d_right) { + fm_vec3_t oldCamPos; + fm_vec3_scale(&oldCamPos, &camPos, 1.0f / nearFarScale); + + if(joypad.btn.d_up)nearFarScale += 0.5f; + if(joypad.btn.d_down)nearFarScale -= 0.5f; + if(nearFarScale < 1)nearFarScale = 1; + + fm_vec3_scale(&camPos, &oldCamPos, nearFarScale); + } + + { + float camSpeed = deltaTime * nearFarScale * 0.001f; + float camRotSpeed = deltaTime * 0.00001f; + + camDir.v[0] = fm_cosf(camRotX) * fm_cosf(camRotY); + camDir.v[1] = fm_sinf(camRotY); + camDir.v[2] = fm_sinf(camRotX) * fm_cosf(camRotY); + t3d_vec3_norm(&camDir); + + if(joypad.btn.z) { + camRotX += (float)joypad.stick_x * camRotSpeed; + camRotY += (float)joypad.stick_y * camRotSpeed; + + if(joypad.btn.c_up)uvOffset[1] += 11; + if(joypad.btn.c_down)uvOffset[1] -= 11; + if(joypad.btn.c_left)uvOffset[0] += 11; + if(joypad.btn.c_right)uvOffset[0] -= 11; + + } else { + camPos.v[0] += camDir.v[0] * (float)joypad.stick_y * camSpeed; + camPos.v[1] += camDir.v[1] * (float)joypad.stick_y * camSpeed; + camPos.v[2] += camDir.v[2] * (float)joypad.stick_y * camSpeed; + + camPos.v[0] += camDir.v[2] * (float)joypad.stick_x * -camSpeed; + camPos.v[2] -= camDir.v[0] * (float)joypad.stick_x * -camSpeed; + + if(joypad.btn.c_up)camPos.v[1] += camSpeed * 15.0f; + if(joypad.btn.c_down)camPos.v[1] -= camSpeed * 15.0f; + } + + camTarget.v[0] = camPos.v[0] + camDir.v[0]; + camTarget.v[1] = camPos.v[1] + camDir.v[1]; + camTarget.v[2] = camPos.v[2] + camDir.v[2]; + } + + color_t fogColor = (color_t){0xFF, 0xFF, 0xFF, 0xFF}; + + if(joypad.btn.b) + { + requestDisplayMetrics = true; + colorAmbient[2] = colorAmbient[1] = colorAmbient[0] = 40; + colorDir[2] = colorDir[1] = colorDir[0] = 40; + fogColor = (color_t){0x00, 0x00, 0x00, 0xFF}; + } else { + requestDisplayMetrics = false; + displayMetrics = false; + + colorAmbient[2] = colorAmbient[1] = colorAmbient[0] = 100; + colorDir[2] = colorDir[1] = colorDir[0] = 0xFF; + + // roate light around axis + lightDirVec.v[0] = fm_cosf(time * 0.002f); + lightDirVec.v[1] = 0.0f;//fm_sinf(time * 0.002f); + lightDirVec.v[2] = fm_sinf(time * 0.002f); + t3d_vec3_norm(&lightDirVec); + } + + if(btn.l) { + vertFxTime = 500.0f; + vertFxFunc++; + if(vertFxFunc > T3D_VERTEX_FX_UV_OFFSET)vertFxFunc = T3D_VERTEX_FX_NONE; + + t3d_state_set_vertex_fx(vertFxFunc, 32, 32); + } + + if(vertFxFunc == T3D_VERTEX_FX_UV_OFFSET) { + t3d_state_set_vertex_fx(T3D_VERTEX_FX_UV_OFFSET, uvOffset[0], uvOffset[1]); + } + + rotAngle += 0.03f; + + float modelScale = 0.12f * nearFarScale; + t3d_mat4_identity(&modelMat); + //t3d_mat4_rotate(&modelMat, &rotAxis, rotAngle); + t3d_mat4_scale(&modelMat, modelScale, modelScale, modelScale); + t3d_mat4fp_from_srt_euler(&modelMatFP[frame%3], + (float[]){modelScale,modelScale,modelScale}, + (float[]){0,0,0}, + (float[]){0,0, 20 * nearFarScale } + ); + + t3d_viewport_set_projection(&viewport, T3D_DEG_TO_RAD(85.0f), nearFarScale * 5.0f, nearFarScale * FAR_VAL); + t3d_viewport_look_at(&viewport, &camPos, &camTarget, &(T3DVec3){{0,1,0}}); + + // ----------- DRAW ------------ // + rdpq_attach(display_get(), display_get_zbuf()); + + t3d_frame_start(); + t3d_viewport_attach(&viewport); + + rdpq_set_prim_color((color_t){0xFF, 0xFF, 0xFF, 0xFF}); + rdpq_mode_fog(RDPQ_FOG_STANDARD); + rdpq_set_fog_color(fogColor); + + t3d_screen_clear_color(RGBA32(0, 0, 0, 0xFF)); + t3d_screen_clear_depth(); + + //t3d_fog_set_range(17.0f, 100.0f); + t3d_fog_set_enabled(false); + + t3d_light_set_ambient(colorAmbient); // one global ambient light, always active + t3d_light_set_directional(0, colorDir, &lightDirVec); // optional directional light, can be disabled + t3d_light_set_count(1); + + /*t3d_light_set_point(0, colorDir, &(T3DVec3){{-10.0f, 10.0f, 0.0f}}, 0.3f, false); // optional point light, can be disabled + t3d_light_set_point(1, colorDir, &(T3DVec3){{10.0f, 10.0f, 0.0f}}, 0.3f, false); // optional point light, can be disabled + t3d_light_set_count(2);*/ + + // t3d functions can be recorded into a display list: + if(!model->userBlock) { + rspq_block_begin(); + t3d_model_draw(model); + model->userBlock = rspq_block_end(); + } + + t3d_matrix_push(&modelMatFP[frame%3]); + rspq_block_run(model->userBlock); + + t3d_matrix_pop(1); + t3d_metrics_fetch(metrics); + + + t3d_debug_print_start(); + t3d_debug_printf(16, 16, "Near/Far: %.2f %.2f", nearFarScale*5, nearFarScale*FAR_VAL); + t3d_debug_printf(16, 16+8, "W-norm: %04X", (int16_t)(int32_t)(viewport._normScaleW * 0xFFFF)); + + + + if(vertFxFunc == T3D_VERTEX_FX_UV_OFFSET) { + t3d_debug_print_start(); + t3d_debug_printf(16, 48, "UV Offset: %d %d", uvOffset[0], uvOffset[1]); + } + + //t3d_debug_print_start(); + //t3d_debug_printf(20, 20, "%.2f FPS", last3dFPS); + //t3d_debug_printf(20, 28, "Tris: %d / %d", metrics->trisPostCull, metrics->trisPreCull); + + if(displayMetrics) + { + t3d_debug_print_start(); + + // show pos / rot + //debug_printf_screen(24, 190, "Pos: %.4f %.4f %.4f", camPos.v[0], camPos.v[1], camPos.v[2]); + //t3d_debug_printf(24, 200, "Rot: %.4f %.4f", camRotX, camRotY); + + if(profile_data.frame_count == 0) { + t3d_debug_printf(140, 206, "FPS (3D) : %.4f", last3dFPS); + t3d_debug_printf(140, 218, "FPS (3D+UI): %.4f", display_get_fps()); + } + + debug_draw_perf_overlay(last3dFPS); + + rdpq_set_mode_standard(); + rdpq_mode_combiner(RDPQ_COMBINER_TEX); + rdpq_mode_blender(RDPQ_BLENDER_MULTIPLY); + rdpq_sprite_blit(spriteLogo, 22.0f, 164.0f, NULL); + rspq_wait(); + } + + rdpq_detach_show(); + rspq_profile_next_frame(); + rspq_wait(); + + if(frame == 30) + { + if(!displayMetrics){ + last3dFPS = display_get_fps(); + rspq_wait(); + rspq_profile_get_data(&profile_data); + if(requestDisplayMetrics)displayMetrics = true; + } + + frame = 0; + rspq_profile_reset(); + } + } + + t3d_destroy(); + return 0; +} diff --git a/src/t3d/rsp/clipping.rspl b/src/t3d/rsp/clipping.rspl index 077544c..294191e 100644 --- a/src/t3d/rsp/clipping.rspl +++ b/src/t3d/rsp/clipping.rspl @@ -299,7 +299,7 @@ function triToScreenSpace(u32<$s6> ptr) // Note: these values need to be loaded each time, as RDPQ_Triangle wipes most regs vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzw; screenSize:sfract = 0; - screenSize >>= 4; + screenSize >>= 8; vec16 vecOne = 1; diff --git a/src/t3d/rsp/rsp_tiny3d.S b/src/t3d/rsp/rsp_tiny3d.S index 7677afd..40ff0e5 100644 --- a/src/t3d/rsp/rsp_tiny3d.S +++ b/src/t3d/rsp/rsp_tiny3d.S @@ -241,10 +241,10 @@ T3DCmd_VertLoad: ori $at, $zero, %lo(FOG_SCALE_OFFSET) ## L:358 | 35 | vec16 fogScaleOffset = load(FOG_SCALE_OFFSET).xyzw; vor $v15, $v00, $v15.e1 ## L:351 | ^ | guardBandScale = guardBandScale.y; ldv $v11, 0, 0, $at ## L:358 | 36 | vec16 fogScaleOffset = load(FOG_SCALE_OFFSET).xyzw; - vmudl $v14, $v00, $v31.e3 ## L:355 | ^ | screenSize >>= 4; + vmudl $v14, $v00, $v31.e7 ## L:355 | ^ | screenSize >>= 4; lbu $k0, %lo(TRI_COMMAND + 0) ## L:384 | 37 | u8 isUnlit = load(TRI_COMMAND); lbu $s0, %lo(CLIP_CODE_ORG_ADDR + 0) ## L:388 | 38 | u8<$s0> baseTileMask = load(CLIP_CODE_ORG_ADDR); - vmadm $v13, $v13, $v31.e3 ## L:355 | ^ | screenSize >>= 4; + vmadm $v13, $v13, $v31.e7 ## L:355 | ^ | screenSize >>= 4; ori $at, $zero, %lo(NORM_SCALE_W) ## L:361 | 39 | vec16 normScaleW = load(NORM_SCALE_W).xyzwxyzw; vmadn $v14, $v00, $v00 ## L:355 | ^ | screenSize >>= 4; ldv $v10, 0, 0, $at ## L:361 | 40 | vec16 normScaleW = load(NORM_SCALE_W).xyzwxyzw; diff --git a/src/t3d/rsp/rsp_tiny3d.rspl b/src/t3d/rsp/rsp_tiny3d.rspl index 712dab4..53fce01 100644 --- a/src/t3d/rsp/rsp_tiny3d.rspl +++ b/src/t3d/rsp/rsp_tiny3d.rspl @@ -315,7 +315,7 @@ command<4> T3DCmd_VertLoad(u32 bufferSize, u32 rdramVerts, u32 addressInOut) vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzwxyzw; screenSize:sfract = 0; - screenSize >>= 4; + screenSize >>= 8; vec16 screenOffset = load(SCREEN_SCALE_OFFSET, 0x08).xyzwxyzw; vec16 fogScaleOffset = load(FOG_SCALE_OFFSET).xyzw; diff --git a/src/t3d/rsp/rsp_tiny3d_clipping.S b/src/t3d/rsp/rsp_tiny3d_clipping.S index 13b0d93..0bbba35 100644 --- a/src/t3d/rsp/rsp_tiny3d_clipping.S +++ b/src/t3d/rsp/rsp_tiny3d_clipping.S @@ -418,11 +418,11 @@ triToScreenSpace: ori $at, $zero, %lo(SCREEN_SCALE_OFFSET) ## L:574 | ^ | vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzw; ldv $v01, 0, 0, $at ## L:574 | 2 | vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzw; ldv $v07, 0, 16, $s6 ## L:589 | 3 | vec32 posClip = load(ptr, 0x10).xyzw; - vmudl $v02, $v00, $v31.e3 ## L:576 | ^ | screenSize >>= 4; + vmudl $v02, $v00, $v31.e7 ## L:576 | ^ | screenSize >>= 4; ldv $v08, 0, 24, $s6 ## L:589 | 4 | vec32 posClip = load(ptr, 0x10).xyzw; lhu $t0, %lo(RSPQ_SCRATCH_MEM + 20) ## L:582 | 5 | u16<$t0> oldClipFlag = load(RSPQ_SCRATCH_MEM, 20); ldv $v04, 0, 8, $at ## L:586 | 6 | vec16 screenOffset = load(SCREEN_SCALE_OFFSET, 0x08).xyzw; - vmadm $v01, $v01, $v31.e3 ## L:576 | ^ | screenSize >>= 4; + vmadm $v01, $v01, $v31.e7 ## L:576 | ^ | screenSize >>= 4; vmadn $v02, $v00, $v00 ## L:576 | 7 | screenSize >>= 4; vrcph $v05.e3, $v07.e3 ## L:590 | 8 | invW.w = invert_half(posClip).w; vrcpl $v06.e3, $v08.e3 ## L:590 | 9 | invW.w = invert_half(posClip).w; diff --git a/src/t3d/rsp/rsp_tinypx.S b/src/t3d/rsp/rsp_tinypx.S index 051016d..5a016a6 100644 --- a/src/t3d/rsp/rsp_tinypx.S +++ b/src/t3d/rsp/rsp_tinypx.S @@ -159,7 +159,7 @@ TPXCmd_DrawColor: addiu $t0, $t0, -1 ## L:850 | 5 | dma_in_async(dmaDmem, rdramAddr, dmaSize); jal DMAExec ## L:850 | 6 | dma_in_async(dmaDmem, rdramAddr, dmaSize); ## Args: $t0, $t1, $s0, $s4, $t2 or $t2, $zero, $zero ## L:850 | *8 | dma_in_async(dmaDmem, rdramAddr, dmaSize); - vmudl $v20, $v00, $v31.e3 ## L:865 | 9 | screenSize >>= 4; + vmudl $v20, $v00, $v31.e7 ## L:865 | 9 | screenSize >>= 4; lw $s2, %lo(RDPQ_SCISSOR_RECT + 4) ## L:1213 | ^ | u32 extMax = load(RDPQ_SCISSOR_RECT, 4); lw $s1, %lo(RDPQ_SCISSOR_RECT + 0) ## L:1214 | 10 | u32 extMin = load(RDPQ_SCISSOR_RECT, 0); ori $at, $zero, %lo(MATRIX_MVP) ## L:858 | 11 | vec32 mat0 = load(MATRIX_MVP, 0x00).xyzwxyzw; @@ -203,7 +203,7 @@ TPXCmd_DrawColor: ori $at, $zero, %lo(PARTICLE_SCALE) ## L:875 | 49 | globalPartSize.xy = load(PARTICLE_SCALE).xy; addiu $a0, $zero, 46 ## L:884 | 50 | cmdRdpDepth = 0x2E; srl $t4, $s1, 12 ## L:1220 | 51 | temp1 = extMin >> 12; - vmadm $v19, $v19, $v31.e3 ## L:865 | ^ | screenSize >>= 4; + vmadm $v19, $v19, $v31.e7 ## L:865 | ^ | screenSize >>= 4; vmadn $v20, $v00, $v00 ## L:865 | 52 | screenSize >>= 4; mtc2 $t4, $v16.e0 ## L:1221 | ^ | screenMin.x = temp1; screenMin.X = temp1; mtc2 $t4, $v16.e4 ## L:1221 | 53 | screenMin.x = temp1; screenMin.X = temp1; @@ -576,7 +576,7 @@ TPXCmd_DrawTextured: addu $s7, $s4, $t0 ## L:1096 | 5 | u32 ptrInEnd = dmaDmem + dmaSize; jal DMAExec ## L:1097 | 6 | dma_in_async(dmaDmem, rdramAddr, dmaSize); ## Args: $t0, $t1, $s0, $s4, $t2 addiu $t0, $t0, -1 ## L:1097 | *8 | dma_in_async(dmaDmem, rdramAddr, dmaSize); - vmudl $v20, $v00, $v31.e3 ## L:1112 | 9 | screenSize >>= 4; + vmudl $v20, $v00, $v31.e7 ## L:1112 | 9 | screenSize >>= 4; ori $at, $zero, %lo(MATRIX_MVP) ## L:1105 | ^ | vec32 mat0 = load(MATRIX_MVP, 0x00).xyzwxyzw; ldv $v22, 0, 56, $at ## L:1108 | 10 | vec32 mat3 = load(MATRIX_MVP, 0x30).xyzwxyzw; lw $s2, %lo(RDPQ_SCISSOR_RECT + 4) ## L:1212 | 11 | u32 extMax = load(RDPQ_SCISSOR_RECT, 4); @@ -621,7 +621,7 @@ TPXCmd_DrawTextured: mtc2 $at, $v15.e3 ## L:1211 | 50 | screenMax.w = 0b1111'1111'1111; mtc2 $t4, $v16.e4 ## L:1220 | 51 | screenMin.x = temp1; screenMin.X = temp1; ori $at, $zero, %lo(PARTICLE_SCALE) ## L:1122 | 52 | globalPartSize.xy = load(PARTICLE_SCALE).xy; - vmadm $v19, $v19, $v31.e3 ## L:1112 | ^ | screenSize >>= 4; + vmadm $v19, $v19, $v31.e7 ## L:1112 | ^ | screenSize >>= 4; addiu $s1, $s5, 32 ## L:1129 | 53 | u16 buffRdpEnd = dmaDmemFlush + 32; vmadn $v20, $v00, $v00 ## L:1112 | ^ | screenSize >>= 4; vand $v15, $v15, $v15.e3 ## L:1223 | 54 | screenMax &= screenMax.w; diff --git a/src/t3d/rsp/rsp_tinypx.rspl b/src/t3d/rsp/rsp_tinypx.rspl index af3b732..0e8f787 100644 --- a/src/t3d/rsp/rsp_tinypx.rspl +++ b/src/t3d/rsp/rsp_tinypx.rspl @@ -128,7 +128,7 @@ command<1> TPXCmd_DrawColor(s16 dataSize, s32 rdramAddr) vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzwxyzw; screenSize:sfract = 0; - screenSize >>= 4; + screenSize >>= 8; vec16 screenOffset = load(SCREEN_SCALE_OFFSET, 0x08).xyzwxyzw; vec16 normScaleW = load(NORM_SCALE_W).xyzwxyzw; @@ -225,7 +225,7 @@ command<4> TPXCmd_DrawTextured(s16 dataSize, s32 rdramAddr) vec32 screenSize:sint = load(SCREEN_SCALE_OFFSET).xyzwxyzw; screenSize:sfract = 0; - screenSize >>= 4; + screenSize >>= 8; vec16 screenOffset = load(SCREEN_SCALE_OFFSET, 0x08).xyzwxyzw; vec16 normScaleW = load(NORM_SCALE_W).xyzwxyzw; diff --git a/src/t3d/rsp/rspq_triangle.inc b/src/t3d/rsp/rspq_triangle.inc index c6bfa8d..976180f 100644 --- a/src/t3d/rsp/rspq_triangle.inc +++ b/src/t3d/rsp/rspq_triangle.inc @@ -1,3 +1,5 @@ +#define T3D_METRICS__ 1 + ######################################################################### # # RDPQ_Triangle: assemble a RDP triangle command @@ -230,6 +232,13 @@ RDPQ_Triangle_Send_Async: mtc2 vtx1, vall1.e3 mtc2 vtx2, vall2.e3 + + #ifdef T3D_METRICS + lw t0, %lo(SEGMENT_TABLE) + (8) + addiu t0, 1 + sw t0, %lo(SEGMENT_TABLE) + (8) + #endif + llv vall1, VTX_ATTR_XY,vtx1 llv vall2, VTX_ATTR_XY,vtx2 llv vall3, VTX_ATTR_XY,vtx3; # Create a vector for negative pow2 constants @@ -614,6 +623,12 @@ rdpq_triangle_change_buffer_done: addiu prim_size, -1 sdv vzout1.e0, 0x00,z_dmem +#ifdef T3D_METRICS + lw t0, %lo(SEGMENT_TABLE) + (8+4) + addiu t0, 1 + sw t0, %lo(SEGMENT_TABLE) + (8+4) +#endif + jr ra mtc0 prim_size, COP0_DMA_WRITE diff --git a/src/t3d/t3d.c b/src/t3d/t3d.c index 398ee30..5154de5 100644 --- a/src/t3d/t3d.c +++ b/src/t3d/t3d.c @@ -100,6 +100,14 @@ inline static void t3d_dmem_set_u16(uint32_t addr, uint32_t value) { rspq_write(T3D_RSP_ID, T3D_CMD_SET_WORD, addr | 0x8000, value); } +void t3d_metrics_fetch(T3DMetrics* data) +{ + t3d_dmem_set_u32((RSP_T3D_SEGMENT_TABLE & 0xFFF) + 0, 0); // force ucode switch + rspq_dma_to_rdram(data, (RSP_T3D_SEGMENT_TABLE & 0xFFFF) + 8, sizeof(T3DMetrics), false); + t3d_dmem_set_u32((RSP_T3D_SEGMENT_TABLE & 0xFFF) + 8, 0); // reset counter + t3d_dmem_set_u32((RSP_T3D_SEGMENT_TABLE & 0xFFF) + 8+4, 0); // reset counter +} + void t3d_matrix_set(const T3DMat4FP *mat, bool doMultiply) { t3d_matrix_stack((void*)mat, 0, doMultiply, false); } @@ -452,12 +460,15 @@ void t3d_viewport_attach(T3DViewport *viewport) { viewport->offset[1] + viewport->size[1] ); - float screenShiftFactor = 16.0f; // compensates the shift in the ucode - float screenFactorX = (float)viewport->size[0] * currentViewport->_normScaleW * 4.0f * screenShiftFactor; - float screenFactorY = (float)viewport->size[1] * currentViewport->_normScaleW * 4.0f * -screenShiftFactor; + uint16_t normWScale = (uint16_t)roundf(0xFFFF * currentViewport->_normScaleW); + float normWScaleFloat = (float)normWScale * (1.0f / 0xFFFF); + + float screenShiftFactor = 256.0f; // compensates the shift in the ucode + float screenFactorX = (float)viewport->size[0] * normWScaleFloat * 4.0f * screenShiftFactor; + float screenFactorY = (float)viewport->size[1] * normWScaleFloat * 4.0f * -screenShiftFactor; - int32_t screenScaleX = (int32_t)roundf(screenFactorX); - int32_t screenScaleY = (int32_t)roundf(screenFactorY); + int32_t screenScaleX = (int32_t)ceilf(screenFactorX); + int32_t screenScaleY = (int32_t)ceilf(screenFactorY); // Set screen size, internally the 3D-scene renders to the correct size, but at [0,0] // calc. both scale and offset to move/scale it into our scissor region @@ -467,9 +478,15 @@ void t3d_viewport_attach(T3DViewport *viewport) { int32_t screenOffset = (screenOffsetX << 17) | (screenOffsetY << 1); int32_t screenScale = (screenScaleX << 16) | ((uint16_t)(screenScaleY) & 0xFFFF); - uint16_t normWScale = (uint16_t)roundf(0xFFFF * currentViewport->_normScaleW); - uint16_t depthScale = (uint16_t)roundf(0xFFFF * currentViewport->_normScaleW * screenShiftFactor * 0.5f); - uint32_t depthAndWScale = ((uint32_t)depthScale << 16) | normWScale; + uint32_t depthScale = (uint32_t)roundf(0xFFFF * normWScaleFloat * screenShiftFactor * 0.5f); + if(depthScale > 0x7FFF)depthScale = 0x7FFF; + + uint32_t depthAndWScale = (depthScale << 16) | normWScale; + + /*debugf("Screen: %04X %04X | Depth: %08X W-scale: %04X\n", + (screenScaleX & 0xFFFF), (screenScaleY & 0xFFFF), + depthScale, normWScale + );*/ int32_t guardBandScale = viewport->guardBandScale & 0xF; diff --git a/src/t3d/t3d.h b/src/t3d/t3d.h index c2ddbde..d9f2e79 100644 --- a/src/t3d/t3d.h +++ b/src/t3d/t3d.h @@ -120,6 +120,15 @@ typedef struct { int matrixStackSize; } T3DInitParams; +/** + * Struct containing rendering metrics. + * Retrieved via `t3d_metrics_fetch`. + */ +typedef struct { + uint32_t trisPreCull; + uint32_t trisPostCull; +} T3DMetrics; + /** * @brief Initializes the tiny3d library * @param params settings to configure the library @@ -143,6 +152,15 @@ void t3d_screen_clear_color(color_t color); /// @brief Clears the entire depth buffer with a fixed value (0xFFFC) void t3d_screen_clear_depth(); +/** + * NOTE: This function is a stub and does nothing for now! + * + * Fetches rendering metrics into the given struct. + * @param data pointer to struct to fill + * @deprecated DO NOT USE + */ +void t3d_metrics_fetch(T3DMetrics* data); + /** * Creates a viewport struct, this only creates a struct and doesn't change any setting. * Most likely you want to update the camera and projection matrix over time,