diff --git a/decompiler/level_extractor/extract_shadow.cpp b/decompiler/level_extractor/extract_shadow.cpp index 3cb48c813e..9460c599c9 100644 --- a/decompiler/level_extractor/extract_shadow.cpp +++ b/decompiler/level_extractor/extract_shadow.cpp @@ -356,8 +356,8 @@ void add_data_to_level(tfrag3::ShadowModelGroup& sd, const std::vectorversion == GameVersion::Jak1) { glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0, 0xFF); diff --git a/game/graphics/opengl_renderer/foreground/Shadow3CPU.cpp b/game/graphics/opengl_renderer/foreground/Shadow3CPU.cpp index 223626eb83..1a6e443f53 100644 --- a/game/graphics/opengl_renderer/foreground/Shadow3CPU.cpp +++ b/game/graphics/opengl_renderer/foreground/Shadow3CPU.cpp @@ -191,7 +191,6 @@ void find_facing_double_tris(const ShadowCPUInput& input, ShadowCPUOutput* output, const std::vector& tris) { const int num_verts = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices; - const int flag_offset = 0; for (size_t i = 0; i < tris.size(); i++) { const auto& tri = tris[i]; @@ -200,7 +199,7 @@ void find_facing_double_tris(const ShadowCPUInput& input, math::Vector3f v2 = work->vertices[tri.verts[2]].xyz(); math::Vector3f n = (v1 - v0).cross(v2 - v0); if (n.dot(input.light_dir) < 0.f) { - work->tri_flags[i + flag_offset] = 1; + work->tri_flags[i] = 1; // treat this as a normal single-sided triangle that is facing. output->push_index(tri.verts[0], false); output->push_index(tri.verts[1], false); @@ -209,7 +208,7 @@ void find_facing_double_tris(const ShadowCPUInput& input, output->push_index(static_cast(tri.verts[2]) + num_verts, false); output->push_index(static_cast(tri.verts[1]) + num_verts, false); } else { - work->tri_flags[i + flag_offset] = 0; + work->tri_flags[i] = 0; // we need to flip vertices to face the light. output->push_index(tri.verts[0], false); output->push_index(tri.verts[2], false); diff --git a/goal_src/jak3/engine/draw/drawable.gc b/goal_src/jak3/engine/draw/drawable.gc index b3aa0b2849..df072aa454 100644 --- a/goal_src/jak3/engine/draw/drawable.gc +++ b/goal_src/jak3/engine/draw/drawable.gc @@ -1441,6 +1441,29 @@ ) ) ) + + ;; og:preserve-this + (let ((v1-0 *pc-shadow-globals*)) + (dotimes (a0-0 3) + (let ((a1-2 (-> v1-0 bucket a0-0))) + (set! (-> a1-2 first) (the-as pointer 0)) + (set! (-> a1-2 next) (the-as pointer 0)) + (set! (-> a1-2 shadow-color) (cond + ((zero? a0-0) + (new 'static 'rgba :r #xf0 :g #xf0 :b #xf0 :a #x80) + ) + ((= a0-0 1) + (the-as rgba (-> *setting-control* user-current spotlight-color)) + ) + (else + (the-as rgba (-> *setting-control* user-current highlight-color)) + ) + ) + ) + (set! (-> a1-2 constants) (the-as shadow-vu1-constants 0)) + ) + ) + ) (none) ) diff --git a/goal_src/jak3/engine/gfx/foreground/foreground.gc b/goal_src/jak3/engine/gfx/foreground/foreground.gc index 8dd1133d02..f527493038 100644 --- a/goal_src/jak3/engine/gfx/foreground/foreground.gc +++ b/goal_src/jak3/engine/gfx/foreground/foreground.gc @@ -19,6 +19,9 @@ ;; Note: merc mode 5 seems to be totally bogus - the buckets are somewhat random. +;; when set, use the rewritten PC shadow render (faster) +(define *use-pc-shadow* #t) + ;; DECOMP BEGINS (define foreground-vu0-block (new 'static 'vu-function #|:length 9 :qlength 5|#)) @@ -825,8 +828,101 @@ ) ) +;; og:preserve-this +(defun pc-draw-bones-shadow ((dc draw-control) (mtx pointer) (dma-ptr pointer)) + "Add shadows for this draw-control to the *pc-shadow-queue* to be drawn in pc-shadow-execute-all. + This places a pc-shadow-request in the DMA buffer and adds it to the linked list of requests + for the currently selected run in *pc-shadow-queue*" + + (when (-> dc shadow-ctrl) + ;; update the "center" position of the shadow control, I guess to let some other thing look at it? + (let ((center-pos (-> dc skeleton bones (-> dc shadow-joint-index) position)) + (settings (-> dc shadow-ctrl settings)) + ) + (set! (-> settings center x) (-> center-pos x)) + (set! (-> settings center y) (-> center-pos y)) + (set! (-> settings center z) (-> center-pos z)) + ) + ) + (let* ((pse (the pc-shadow-request dma-ptr)) + (sgeo (-> dc shadow)) + (settings (if (-> dc shadow-ctrl) (-> dc shadow-ctrl settings) *default-shadow-settings*)) + (flags (-> settings flags)) + ) + + ;; if fade is enabled, and we're all the way faded out, disable draw + (when (not (logtest? flags (shadow-flags disable-fade))) + (let ((dist (-> (scratchpad-object foreground-work) distance w))) + (#when PC_PORT + (if (not (-> *pc-settings* ps2-shadow?)) + (set! dist 0.0))) + (if (< (-> settings fade-dist) dist) + (logior! flags (shadow-flags disable-draw)) + ) + ) + ) + + ;; if disabled, early return + (if (logtest? flags (shadow-flags disable-draw)) + (return dma-ptr) + ) + + + ;; settings + (mem-copy! (the pointer (-> pse settings)) (the pointer settings) (size-of shadow-settings)) + + ;; update the "center" position. + (let ((center-pos (-> dc skeleton bones (-> dc shadow-joint-index) position))) + (set! (-> pse settings center x) (-> center-pos x)) + (set! (-> pse settings center y) (-> center-pos y)) + (set! (-> pse settings center z) (-> center-pos z)) + ) + + ;; set the other properties + (set! (-> pse geo-name) (-> sgeo name)) + (set! (-> pse mtx) mtx) + (set! (-> pse num-joints) (-> sgeo num-joints)) + ;; TODO: this is probably the wrong color!!! + (vector-copy! (-> pse color) (-> *time-of-day-context* current-shadow-color)) + + ;; set up linked list. + (let* ((run (-> *pc-shadow-globals* bucket (-> settings shadow-type))) + (next (-> run next)) + ) + + ;; if we're the first in the list, store in the run + (when (zero? (-> run first)) + (set! (-> run first) (the pointer pse))) + + ;; patch next pointer of previous + (if (nonzero? next) (set! (-> (the (pointer structure) next) 0) pse)) + + ;; remember where to patch for the next one + (set! (-> run next) (&-> pse next)) + + ;; clear our next pointer in case we're last + (set! (-> pse next) (the pc-shadow-request 0)) + + ;; set up next tag at the start, to skip over this data. + ;; this is a bit of a hack, this function gets called when building merc chains, + ;; and inserts a bit of shadow dma that will later be referenced by the shadow bucket. + ;; but the original game did the same thing! + (&+! dma-ptr (size-of pc-shadow-request)) + (set! (-> pse dma-next dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (the-as int dma-ptr))) + (set! (-> pse dma-next vif0) (new 'static 'vif-tag)) + (set! (-> pse dma-next vif1) (new 'static 'vif-tag)) + ) + + dma-ptr + ) + ) + (defun foreground-shadow ((arg0 draw-control) (arg1 (inline-array pris-mtx)) (arg2 pointer)) "Generate DMA for shadow drawing." + ;; og:preserve-this + (when *use-pc-shadow* + (return (pc-draw-bones-shadow arg0 (the pointer arg1) arg2)) + ) (local-vars (a3-3 shadow-settings)) (let ((v1-0 (-> arg0 shadow)) (t0-0 (-> (scratchpad-object foreground-work) distance w)) diff --git a/goal_src/jak3/engine/gfx/foreground/shadow-cpu-h.gc b/goal_src/jak3/engine/gfx/foreground/shadow-cpu-h.gc index 30f796b63e..fb7e8dec7c 100644 --- a/goal_src/jak3/engine/gfx/foreground/shadow-cpu-h.gc +++ b/goal_src/jak3/engine/gfx/foreground/shadow-cpu-h.gc @@ -120,13 +120,28 @@ (define *shadow-globals* (new 'global 'shadow-globals)) - (set! (-> *shadow-globals* bucket 0 bucket-id) (bucket-id shadow)) - (set! (-> *shadow-globals* bucket 1 bucket-id) (bucket-id shadow2)) - (set! (-> *shadow-globals* bucket 2 bucket-id) (bucket-id shadow3)) +;; og:preserve-this +;; separate copy of shadow-globals for storing only the PC format requests. +(define *pc-shadow-globals* (new 'global 'shadow-globals)) +(declare-type pc-shadow-request structure) +(deftype pc-shadow-request (structure) + ((dma-next dma-packet :inline) + (settings shadow-settings :inline) + (color vector :inline) + (geo-name string) ;; name to send to PC renderer + (mtx pointer) ;; pointer to DMA memory that will contain bones + (num-joints uint32) ;; number of joints needed for shadow + (next pc-shadow-request) + ) + ) +(set! (-> *pc-shadow-globals* bucket 0 bucket-id) (bucket-id shadow)) +(set! (-> *pc-shadow-globals* bucket 1 bucket-id) (bucket-id shadow2)) +(set! (-> *pc-shadow-globals* bucket 2 bucket-id) (bucket-id shadow3)) + (deftype shadow-vertex (structure) ((x float) (y float) diff --git a/goal_src/jak3/engine/gfx/foreground/shadow-cpu.gc b/goal_src/jak3/engine/gfx/foreground/shadow-cpu.gc index 42104b6265..64f9ed800e 100644 --- a/goal_src/jak3/engine/gfx/foreground/shadow-cpu.gc +++ b/goal_src/jak3/engine/gfx/foreground/shadow-cpu.gc @@ -659,9 +659,65 @@ (none) ) +;; og:preserve-this +(defun pc-shadow-execute-all () + "Send PC shadow queue to the PC shadow renderer." + + ;; bail if disabled + (if (not (logtest? (-> *display* vu1-enable-user) (vu1-renderer-mask rn32))) + (return #f) + ) + + (dotimes (i 3) + (when (nonzero? (-> *pc-shadow-globals* bucket i first)) + ;; patch the color of each request. + (let ((iter (the pc-shadow-request (-> *pc-shadow-globals* bucket i first))) + (color (new-stack-vector0)) + ) + + (cond + ((= i 0) + (vector-float*! color (-> *time-of-day-context* current-shadow-color) 128.0) + ) + (else + (let ((c (-> *pc-shadow-globals* bucket i shadow-color))) + (set! (-> color x) (the float (-> c r))) + (set! (-> color y) (the float (-> c g))) + (set! (-> color z) (the float (-> c b))) + ) + ) + ) + + (set! (-> color w) (the float (-> *pc-shadow-globals* bucket i shadow-color a))) + + (while (nonzero? iter) + ;(vector-copy! (-> iter color) color) + (set! (-> iter color quad) (-> color quad)) + (set! iter (-> iter next)) + ) + ) + + (with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (-> *pc-shadow-globals* bucket i bucket-id)) + (dma-buffer-add-ref-vif2 + dma-buf + 6 + (-> *pc-shadow-globals* bucket i first) + (new 'static 'vif-tag :cmd (vif-cmd pc-port)) + (new 'static 'vif-tag :cmd (vif-cmd pc-port)) + ) + ) + ) + ) + (none) + ) + ;; ERROR: Failed store: (s.h! (+ v1-25 18) 0) at op 61 ;; ERROR: Failed store: (s.h! (+ v1-25 16) 0) at op 62 (defun shadow-execute-all ((arg0 dma-buffer)) + (when *use-pc-shadow* + (pc-shadow-execute-all) + (return #f) + ) (when *debug-segment* (let ((gp-0 (-> *display* frames (-> *display* on-screen) profile-array data 0)) (v1-7 'other)