mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
fix: enable camera-plane clipping with native-wide projection correction
This commit is contained in:
+13
-9
@@ -1436,24 +1436,28 @@ native code and the dirty-RAM interpreter agree
|
||||
(`draw_distance_codegen_test`, `draw_distance_interp_test`). First user: R4's
|
||||
course renderers (RidgeRacerType4Recomp, Max Detail).
|
||||
|
||||
### Opt-in camera-plane clipping for native-wide textured worlds
|
||||
### Default camera-plane clipping for native-wide textured worlds
|
||||
|
||||
`psx_mod_set_native_wide_near_clip(1)` complements horizontal projection
|
||||
recovery. A large face can remain visible while a corner crosses the camera
|
||||
plane: unsigned SZ, the capped H/Z divider and saturated SXY cannot represent
|
||||
that face. PGXP now optionally carries the signed homogeneous projection from
|
||||
RTPS/RTPT through exact full-word copies. CPU arithmetic, partial writes,
|
||||
`psx_mod_set_native_wide_projection_correction(1)` automatically enables both
|
||||
horizontal projection recovery and camera-plane clipping. A large face can
|
||||
remain visible while a corner crosses the camera plane: unsigned SZ, the capped
|
||||
H/Z divider and saturated SXY cannot represent that face. PGXP carries the
|
||||
signed homogeneous projection from RTPS/RTPT through exact full-word copies. CPU arithmetic, partial writes,
|
||||
stale words and timeline invalidation discard the association; sandbox
|
||||
rollback restores it with the rest of the precision shadow.
|
||||
|
||||
Opted-in native-wide OpenGL sessions clip proven textured faces at depth 1
|
||||
and the visible bounds before perspective division. UV and color attributes
|
||||
Native-wide OpenGL sessions with projection correction clip proven textured
|
||||
faces at depth 1 and the visible bounds before perspective division. UV and color attributes
|
||||
follow each intersection, and ordinary GPU batches, painter order, masking,
|
||||
texture filtering and canonical/wide readback remain in use. The existing
|
||||
guest GTE registers, gameplay state and title culling branches do not change.
|
||||
Software/CPU-authoritative rendering, 4:3 and missing provenance use the
|
||||
original path. The larger PGXP value increases the full 8 MiB RAM shadow
|
||||
from 40 to 72 MiB; projection calculations are disabled unless a title opts in.
|
||||
from 40 to 72 MiB; projection calculations run only while projection correction
|
||||
is enabled. Session start resets that mode before the new plan's activation.
|
||||
The old `psx_mod_set_native_wide_near_clip` entry point remains for source/ABI
|
||||
compatibility, but its argument no longer changes clipping. The enhanced view
|
||||
is elective; clipping its proven geometry correctly needs no separate opt-in.
|
||||
|
||||
MediEvil II's title hallway provided the camera-crossing reproduction. The
|
||||
GL authority/order fixture passes 197 checks at 1x and 4x; provenance tests
|
||||
|
||||
@@ -238,15 +238,14 @@ int32_t psx_mod_widescreen_x_margin(void);
|
||||
* Use for screen-space layout, including the first frame of a new scene. */
|
||||
int32_t psx_mod_widescreen_view_x_margin(void);
|
||||
|
||||
/* Opt into render-only recovery of saturated horizontal GTE projections in
|
||||
* native-wide gameplay. Requires exact packet-address/word provenance and
|
||||
* depth; never changes guest SXY, vertical coordinates, or the 4:3 path. */
|
||||
/* Enable render-only recovery of saturated horizontal GTE projections and
|
||||
* camera-plane clipping in native-wide gameplay. Requires exact packet-address/
|
||||
* word provenance and depth; never changes guest SXY or the 4:3 path. */
|
||||
void psx_mod_set_native_wide_projection_correction(int enabled);
|
||||
/* Separately qualify near-camera world clipping for a title. The GL path
|
||||
* carries signed, unclamped projection through exact PGXP word transport,
|
||||
* clips at the camera/view planes, and preserves ordered GPU/VRAM writes.
|
||||
* Requires projection correction above; 4:3, software and untracked UI stay
|
||||
* on their existing paths. No architectural GTE or gameplay changes. */
|
||||
/* Deprecated compatibility entry point; enabled is ignored. Camera/view-plane
|
||||
* clipping is automatic with projection correction above. The GL path requires
|
||||
* signed projection through exact PGXP word transport; 4:3, software and
|
||||
* untracked UI stay on their existing paths. No guest GTE/gameplay changes. */
|
||||
void psx_mod_set_native_wide_near_clip(int enabled);
|
||||
/* Bind render-only NCLIP branch consumers to full instruction words. These
|
||||
* recover winding only when valid horizontal projections saturated; guest
|
||||
|
||||
+6
-1
@@ -4468,6 +4468,9 @@ void gpu_pgxp_rederive_enable(void) {
|
||||
void psx_mod_set_native_wide_projection_correction(int enabled) {
|
||||
s_native_wide_projection_correction = enabled ? 1 : 0;
|
||||
s_native_wide_projection_vertices = 0;
|
||||
/* Signed camera-space provenance is required for correct native-wide
|
||||
* faces, including corners behind the camera. Arm it with the mode. */
|
||||
pgxp_set_projection_tracking(s_native_wide_projection_correction);
|
||||
gpu_pgxp_rederive_enable();
|
||||
}
|
||||
|
||||
@@ -4482,7 +4485,9 @@ static int gpu_ws_projective_enabled(void) {
|
||||
gl_renderer_projective_supported();
|
||||
}
|
||||
void psx_mod_set_native_wide_near_clip(int enabled) {
|
||||
pgxp_set_projection_tracking(enabled);
|
||||
/* Compatibility entry point: clipping follows projection correction.
|
||||
* A separate toggle must not disable this mode's correctness fix. */
|
||||
(void)enabled;
|
||||
}
|
||||
|
||||
/* The PS1 clamps each projected X independently. At a wider FOV that can
|
||||
|
||||
@@ -1767,6 +1767,8 @@ static void reset_mod_owned_presentation(void) {
|
||||
gpu_ws_set_auto_ui_proportional(g_ws_auto_ui_proportional_cfg ? 1 : 0);
|
||||
psx_mod_set_world_scene_predicate(nullptr);
|
||||
gpu_ws_set_native_scene_predicate(nullptr);
|
||||
/* Projection recovery and its clipping belong to this session's mod. */
|
||||
psx_mod_set_native_wide_projection_correction(0);
|
||||
psx_mod_set_retained_scene_predicate(nullptr);
|
||||
psx_mod_set_adaptive_backdrop_preload(0);
|
||||
(void)psx_mod_set_draw_distance_clamp(0);
|
||||
|
||||
@@ -249,6 +249,13 @@ static void verify_stereo_transactions(void) {
|
||||
check(glGetError()==GL_NO_ERROR,"stereo transaction GL error");
|
||||
}
|
||||
|
||||
static void check_wide_green(uint32_t pixel,const char *label) {
|
||||
/* Accurate blending stores each 5-bit channel as k*8, so full green is
|
||||
* 248 in the raw wide surface. The legacy basis expands it to 255. */
|
||||
const uint32_t expected=gl_renderer_accurate_blending()?0xff00f800u:0xff00ff00u;
|
||||
if(pixel!=expected)fprintf(stderr,"%s: got %08x expected %08x\n",label,pixel,expected);
|
||||
check(pixel==expected,label);
|
||||
}
|
||||
static void verify_oversize_wide_geometry(int scale) {
|
||||
/* Captured hallway triangles exceed the PS1 height limit. Proven geometry
|
||||
* must use identical canonical/wide passes, including the center-copy edge. */
|
||||
@@ -288,11 +295,11 @@ static void verify_oversize_wide_geometry(int scale) {
|
||||
check(pixels!=NULL,"oversize wide pixels allocation");
|
||||
if(pixels) {
|
||||
check(glb_render_wide_display(pixels,848*scale*4,0,0,240)>0,"oversize wide readback");
|
||||
check(pixels[(100*scale)*(848*scale)+68*scale]==0xff00ff00u,"left oversize margin drawn in painter order");
|
||||
check(pixels[(100*scale)*(848*scale)+818*scale]==0xff00ff00u,"captured right hallway wall drawn");
|
||||
check(pixels[(100*scale)*(848*scale)+268*scale]==0xff00ff00u,"canonical center retains recovered faces");
|
||||
check(pixels[(100*scale)*(848*scale)+678*scale]==0xff00ff00u,"recovered wall before center-copy boundary");
|
||||
check(pixels[(100*scale)*(848*scale)+680*scale]==0xff00ff00u,"same recovered wall after center-copy boundary");
|
||||
check_wide_green(pixels[(100*scale)*(848*scale)+68*scale],"left oversize margin drawn in painter order");
|
||||
check_wide_green(pixels[(100*scale)*(848*scale)+818*scale],"captured right hallway wall drawn");
|
||||
check_wide_green(pixels[(100*scale)*(848*scale)+268*scale],"canonical center retains recovered faces");
|
||||
check_wide_green(pixels[(100*scale)*(848*scale)+678*scale],"recovered wall before center-copy boundary");
|
||||
check_wide_green(pixels[(100*scale)*(848*scale)+680*scale],"same recovered wall after center-copy boundary");
|
||||
free(pixels);
|
||||
}
|
||||
glb_wide_disable_target();
|
||||
@@ -326,8 +333,8 @@ static void verify_camera_plane_clip(int scale) {
|
||||
check(pixels!=NULL,"camera-plane wide allocation");
|
||||
if(pixels) {
|
||||
check(glb_render_wide_display(pixels,848*scale*4,0,0,240)>0,"camera-plane wide readback");
|
||||
check(pixels[100*scale*(848*scale)+68*scale]==0xff00ff00u,"crossing wall retained in wide margin");
|
||||
check(pixels[100*scale*(848*scale)+268*scale]==0xff00ff00u,"same crossing wall across center copy");
|
||||
check_wide_green(pixels[100*scale*(848*scale)+68*scale],"crossing wall retained in wide margin");
|
||||
check_wide_green(pixels[100*scale*(848*scale)+268*scale],"same crossing wall across center copy");
|
||||
free(pixels);
|
||||
}
|
||||
/* Perspective UVs must survive intersections without integer rounding.
|
||||
|
||||
@@ -39,7 +39,7 @@ int main(void) {
|
||||
prepare_precise_triangle(1,4,7,ax,ay);
|
||||
assert(!fixture_precise_triangle.enabled); /* default remains stock */
|
||||
psx_mod_set_native_wide_projection_correction(1);
|
||||
assert(fixture_pgxp_enabled);
|
||||
assert(fixture_pgxp_enabled && fixture_projection_tracking);
|
||||
prepare_precise_triangle(1,4,7,ax,ay);
|
||||
assert(fixture_precise_triangle.enabled && area(fixture_precise_triangle.xy)>0);
|
||||
assert(fixture_precise_triangle.xy[5]==152*65536); /* no Y fraction correction */
|
||||
@@ -128,12 +128,14 @@ int main(void) {
|
||||
gp0_cmd_source_addr=UINT32_MAX;
|
||||
assert(gpu_triangle_rejected(wall_x,wall_y,0,1,2));
|
||||
psx_mod_set_native_wide_projection_correction(0);
|
||||
assert(!fixture_pgxp_enabled);
|
||||
assert(!fixture_pgxp_enabled && !fixture_projection_tracking);
|
||||
psx_mod_set_native_wide_near_clip(1); /* legacy API cannot enable the mode */
|
||||
assert(!fixture_projection_tracking);
|
||||
prepare_precise_triangle(7,4,10,bx,by);
|
||||
assert(!fixture_triangle_recovered);
|
||||
assert(!fixture_precise_triangle.enabled);
|
||||
/* A camera-plane crossing needs intact homogeneous data for ALL corners.
|
||||
* The native-wide clip opt-in is independent of horizontal recovery. */
|
||||
* Enabling projection correction alone must also correct these faces. */
|
||||
psx_mod_set_native_wide_projection_correction(1);
|
||||
configure_native_wide_16_9();
|
||||
fixture_projective_supported=1;fixture_backend=GR_BACKEND_OPENGL;
|
||||
@@ -146,8 +148,8 @@ int main(void) {
|
||||
fixture_homogeneous[i].p=(PGXPProjection){40000,8000,i==1?-62:500,150};
|
||||
fixture_homogeneous[i].valid=1;
|
||||
}
|
||||
assert(!native_wide_projective_draw());
|
||||
psx_mod_set_native_wide_near_clip(1);
|
||||
psx_mod_set_native_wide_near_clip(0); /* legacy toggle cannot disable the fix */
|
||||
assert(fixture_projection_tracking);
|
||||
assert(native_wide_projective_draw() && fixture_projective_draws==2);
|
||||
assert(fixture_projective_vertices[1].z==-62); /* behind-camera depth retained */
|
||||
gp0_cmd_buf[4]^=1;
|
||||
|
||||
Reference in New Issue
Block a user