shadows pretty close, something wrong with plane calc in jak2 keira, maybe flags

This commit is contained in:
water111
2025-06-18 22:10:22 -04:00
parent ca19e25b7f
commit cee354474c
9 changed files with 189 additions and 11 deletions
@@ -242,6 +242,10 @@ std::vector<ShadowData> extract_jak2_shadow_data(const LinkedObjectFile& file,
} else if (version == 1) {
u32 num_joints = read_plain_data_field<u32>(tr, "num-joints", dts);
uint32_t num_fragments = read_plain_data_field<u32>(tr, "num-fragments", dts);
if (num_fragments == 0) {
lg::error("Shadow geo {} with no fragments! Skipping\n", name);
return {};
}
// lg::info("{} {} fragments", name, num_fragments);
auto frags_ref =
TypedRef(get_field_ref(tr, "frags", dts), dts.ts.lookup_type("shadow-frag-ref"));
@@ -406,7 +410,8 @@ void extract_shadow(const ObjectFileData& ag_data,
auto geo_locations = find_objects_with_type(ag_data.linked_data, "shadow-geo");
for (auto loc : geo_locations) {
extract_jak2_shadow_data(ag_data.linked_data, dts, loc);
auto shadow_datas = extract_jak2_shadow_data(ag_data.linked_data, dts, loc);
add_data_to_level(sd, shadow_datas);
}
}
}
@@ -252,7 +252,7 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
BucketId::MERC_LCOM_SHRUB, m_merc2);
// 350
init_bucket_renderer<Shadow2>("shadow", BucketCategory::OTHER, BucketId::SHADOW);
init_bucket_renderer<Shadow2>("shadow", BucketCategory::OTHER, BucketId::SHADOW, m_shadow3);
// 351
for (int i = 0; i < LEVEL_MAX; i++) {
@@ -359,8 +359,8 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
BucketId::GENERIC_SPRITE_3, m_generic2,
Generic2::Mode::LIGHTNING);
init_bucket_renderer<Shadow2>("shadow2", BucketCategory::OTHER, BucketId::SHADOW2);
init_bucket_renderer<Shadow2>("shadow3", BucketCategory::OTHER, BucketId::SHADOW3);
init_bucket_renderer<Shadow2>("shadow2", BucketCategory::OTHER, BucketId::SHADOW2, m_shadow3);
init_bucket_renderer<Shadow2>("shadow3", BucketCategory::OTHER, BucketId::SHADOW3, m_shadow3);
// 575
init_bucket_renderer<TextureUploadHandler>("tex-warp", BucketCategory::TEX, BucketId::TEX_WARP,
m_texture_animator);
@@ -551,7 +551,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
init_bucket_renderer<Generic2BucketRenderer>("gmerc-lcom-tfrag", BucketCategory::GENERIC,
BucketId::GMERC_LCOM_TFRAG, m_generic2,
Generic2::Mode::NORMAL);
init_bucket_renderer<Shadow2>("shadow", BucketCategory::OTHER, BucketId::SHADOW);
init_bucket_renderer<Shadow2>("shadow", BucketCategory::OTHER, BucketId::SHADOW, m_shadow3);
// 220
init_bucket_renderer<TextureUploadHandler>("tex-lcom-pris", BucketCategory::TEX,
BucketId::TEX_LCOM_PRIS, m_texture_animator);
@@ -571,7 +571,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
init_bucket_renderer<TextureUploadHandler>("tex-all-sprite", BucketCategory::TEX,
BucketId::TEX_ALL_SPRITE, m_texture_animator);
init_bucket_renderer<Sprite3>("particles", BucketCategory::SPRITE, BucketId::PARTICLES);
init_bucket_renderer<Shadow2>("shadow2", BucketCategory::OTHER, BucketId::SHADOW2);
init_bucket_renderer<Shadow2>("shadow2", BucketCategory::OTHER, BucketId::SHADOW2, m_shadow3);
init_bucket_renderer<Generic2BucketRenderer>("effects", BucketCategory::OTHER, BucketId::EFFECTS,
m_generic2, Generic2::Mode::LIGHTNING);
init_bucket_renderer<TextureUploadHandler>("tex-all-warp", BucketCategory::TEX,
@@ -2,7 +2,8 @@
#include "third-party/imgui/imgui.h"
Shadow2::Shadow2(const std::string& name, int my_id) : BucketRenderer(name, my_id) {
Shadow2::Shadow2(const std::string& name, int my_id, std::shared_ptr<Shadow3> shadow3)
: BucketRenderer(name, my_id), m_shadow3(shadow3) {
m_vertex_buffer.resize(kMaxVerts);
m_front_index_buffer.resize(kMaxInds);
m_back_index_buffer.resize(kMaxInds);
@@ -53,7 +54,11 @@ void Shadow2::init_shaders(ShaderLibrary& shaders) {
}
void Shadow2::draw_debug_window() {
ImGui::Checkbox("volume", &m_debug_draw_volume);
if (m_using_shadow3) {
m_shadow3->draw_debug_window();
} else {
ImGui::Checkbox("volume", &m_debug_draw_volume);
}
}
void Shadow2::reset_buffers() {
@@ -71,6 +76,13 @@ void Shadow2::render(DmaFollower& dma, SharedRenderState* render_state, ScopedPr
return;
}
m_using_shadow3 = dma.current_tag_vifcode0().kind == VifCode::Kind::PC_PORT;
if (m_using_shadow3) {
m_shadow3->render_jak1(dma, render_state, prof);
return;
}
auto maybe_constants = dma.read_and_advance();
if (maybe_constants.size_bytes == 0 && maybe_constants.vif0() == 0 &&
maybe_constants.vif1() == 0) {
@@ -80,6 +92,7 @@ void Shadow2::render(DmaFollower& dma, SharedRenderState* render_state, ScopedPr
reset_buffers();
// shadow-vu1-constants
ASSERT(maybe_constants.size_bytes >= sizeof(ShadowVu1Constants));
FrameConstants frame_constants;
@@ -3,12 +3,13 @@
#include "common/math/Vector.h"
#include "game/graphics/opengl_renderer/BucketRenderer.h"
#include "game/graphics/opengl_renderer/foreground/Shadow3.h"
class Shadow2 : public BucketRenderer {
public:
static constexpr int kMaxVerts = 8192 * 3 * 2;
static constexpr int kMaxInds = kMaxVerts;
Shadow2(const std::string& name, int my_id);
Shadow2(const std::string& name, int my_id, std::shared_ptr<Shadow3> shadow3);
~Shadow2();
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void draw_debug_window() override;
@@ -94,4 +95,6 @@ class Shadow2 : public BucketRenderer {
ScopedProfilerNode& prof,
const FrameConstants& constants);
u8 m_color[4] = {0, 0, 0, 0};
std::shared_ptr<Shadow3> m_shadow3;
bool m_using_shadow3 = false;
};
@@ -107,8 +107,7 @@
;; new shadow queue for drawing PC shadows.
(declare-type pc-shadow-request structure)
(deftype pc-shadow-request (structure)
(
(dma-next dma-packet :inline)
((dma-next dma-packet :inline)
(settings shadow-settings :inline)
(color vector :inline)
(geo-name string) ;; name to send to PC renderer
+17
View File
@@ -1449,6 +1449,23 @@
)
)
)
;; og:preserve-this
(let ((v1-0 *pc-shadow-globals*))
(dotimes (a0-0 2)
(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) (if (zero? a0-0)
(new 'static 'rgba :r #xf0 :g #xf0 :b #xf0 :a #x80)
(the-as rgba (-> *setting-control* user-current spotlight-color))
)
)
(set! (-> a1-2 constants) (the-as shadow-vu1-constants 0))
)
)
)
(none)
)
@@ -13,6 +13,8 @@
(eye 3)
)
;; when set, use the rewritten PC shadow render (faster)
(define *use-pc-shadow* #t)
(def-mips2c foreground-draw-hud (function draw-control dma-buffer float none))
@@ -563,8 +565,102 @@
)
)
;; 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))
(format 0 "Setting first to #x~X~%" pse)
(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
)
)
;; ERROR: Unsupported inline assembly instruction kind - [lq ra, 32(v1)]
(defun foreground-shadow ((draw-ctrl draw-control) (arg1 (inline-array pris-mtx)) (arg2 pointer))
;; og:preserve-this
(when *use-pc-shadow*
(return (pc-draw-bones-shadow draw-ctrl (the pointer arg1) arg2))
)
(local-vars (shadow-settings shadow-settings))
(let ((shadow-geo (-> draw-ctrl shadow))
(dist (-> (scratchpad-object foreground-work) distance w))
@@ -137,6 +137,21 @@
(define *shadow-globals* (new 'global 'shadow-globals))
;; 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)
)
)
(deftype shadow-vertex (structure)
((x float :offset-assert 0)
(y float :offset-assert 4)
@@ -641,9 +641,39 @@
(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 shadow)))
(return #f)
)
(dotimes (i 2)
(when (nonzero? (-> *pc-shadow-globals* bucket i first))
(with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (if (zero? i) (bucket-id shadow) (bucket-id shadow2)))
(format 0 "dma bucket ~d from ~X~%" i (-> *pc-shadow-globals* bucket i first))
(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-24 18) 0) at op 58
;; ERROR: Failed store: (s.h! (+ v1-24 16) 0) at op 59
(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 'shadow)