mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 06:09:57 +00:00
[jak2] add sprite glow renderer (#2232)
Adds the "sprite glow" renderer, which is responsible for the glowing lights.
This commit is contained in:
parent
f388898d7b
commit
08ce65fd9b
@ -128,6 +128,13 @@ class Vector {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<T, Size>& operator+=(const T& other) {
|
||||
for (int i = 0; i < Size; i++) {
|
||||
m_data[i] += other;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector<T, Size> elementwise_multiply(const Vector<T, Size>& other) const {
|
||||
Vector<T, Size> result;
|
||||
for (int i = 0; i < Size; i++) {
|
||||
|
@ -3662,6 +3662,7 @@
|
||||
(signal 96)
|
||||
(finish 97)
|
||||
(label 98)
|
||||
(hack 127)
|
||||
)
|
||||
|
||||
(defenum gs-reg64
|
||||
@ -4047,10 +4048,10 @@
|
||||
)
|
||||
|
||||
(deftype gs-adcmd (structure)
|
||||
((word uint32 4 :offset-assert 0)
|
||||
(quad uint128 :offset 0)
|
||||
(data uint64 :offset 0)
|
||||
(cmds gs-reg64 :offset 8)
|
||||
((word uint32 4 :offset-assert 0 :score -10)
|
||||
(quad uint128 :offset 0 :score -10)
|
||||
(data uint64 :offset 0 :score -10)
|
||||
(cmds gs-reg64 :offset 8 :score 10)
|
||||
(cmd uint8 :offset 8)
|
||||
(x uint32 :offset 0)
|
||||
(y uint32 :offset 4)
|
||||
@ -4356,10 +4357,10 @@
|
||||
)
|
||||
|
||||
(deftype gs-packed-xyzw (vector)
|
||||
((ix int32 :offset 0)
|
||||
(iy int32 :offset 4)
|
||||
(iz int32 :offset 8)
|
||||
(iw int32 :offset 12)
|
||||
((ix int32 :offset 0 :score 10)
|
||||
(iy int32 :offset 4 :score 10)
|
||||
(iz int32 :offset 8 :score 10)
|
||||
(iw int32 :offset 12 :score 10)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x10
|
||||
@ -20356,6 +20357,7 @@
|
||||
(fade-b float :offset-assert 52)
|
||||
(tex-id texture-id :offset-assert 56)
|
||||
(dummy uint32 :offset-assert 60)
|
||||
(quads vector 4 :inline :offset 0)
|
||||
)
|
||||
:method-count-assert 10
|
||||
:size-assert #x40
|
||||
@ -20368,14 +20370,14 @@
|
||||
(deftype simple-sprite-system (structure)
|
||||
((count int16 :offset-assert 0)
|
||||
(max-count int16 :offset-assert 2)
|
||||
(data sprite-glow-data :offset-assert 4)
|
||||
(data (inline-array sprite-glow-data) :offset-assert 4)
|
||||
)
|
||||
:method-count-assert 12
|
||||
:size-assert #x8
|
||||
:flag-assert #xc00000008
|
||||
(:methods
|
||||
(add! (_type_ dma-buffer) none 9)
|
||||
(simple-sprite-system-method-10 (_type_ dma-buffer) none 10)
|
||||
(add! (_type_ sprite-glow-data) none 9)
|
||||
(draw-all-sprites! (_type_ dma-buffer) none 10)
|
||||
(clear! (_type_) none 11)
|
||||
)
|
||||
)
|
||||
@ -23852,14 +23854,14 @@
|
||||
|
||||
(deftype sprite-glow-template (structure)
|
||||
((clear-init-giftag gs-gif-tag :inline :offset-assert 0)
|
||||
(clear-init-adcmds vector4w 5 :inline :offset-assert 16) ;; gs-adcmd?
|
||||
(clear-init-adcmds gs-adcmd 5 :inline :offset-assert 16) ;; gs-adcmd?
|
||||
(clear-draw-giftag gs-gif-tag :inline :offset-assert 96)
|
||||
(clear-draw-clr-0 gs-packed-rgba :inline :offset-assert 112)
|
||||
(clear-draw-xyz-0 vector 2 :inline :offset-assert 128)
|
||||
(clear-draw-xyz-0 gs-packed-xyzw 2 :inline :offset-assert 128)
|
||||
(clear-draw-clr-1 gs-packed-rgba :inline :offset-assert 160)
|
||||
(clear-draw-xyz-1 vector 2 :inline :offset-assert 176)
|
||||
(offscr-setup-giftag gs-gif-tag :inline :offset-assert 208)
|
||||
(offscr-setup-adcmds vector4w 8 :inline :offset-assert 224) ;; gs-adcmd?
|
||||
(offscr-setup-adcmds gs-adcmd 8 :inline :offset-assert 224) ;; gs-adcmd?
|
||||
(offscr-first-giftag gs-gif-tag :inline :offset-assert 352)
|
||||
(offscr-first-clr gs-packed-rgba :inline :offset-assert 368)
|
||||
(offscr-first-uv-0 gs-packed-uv :inline :offset-assert 384)
|
||||
@ -23867,7 +23869,7 @@
|
||||
(offscr-first-uv-1 gs-packed-uv :inline :offset-assert 416)
|
||||
(offscr-first-xyzw-1 gs-packed-xyzw :inline :offset-assert 432)
|
||||
(repeat-draw-giftag gs-gif-tag :inline :offset-assert 448)
|
||||
(repeat-draw-adcmds vector4w 29 :inline :offset-assert 464) ;; gs-adcmd?
|
||||
(repeat-draw-adcmds gs-adcmd 29 :inline :offset-assert 464) ;; gs-adcmd?
|
||||
(flare-alpha-giftag gs-gif-tag :inline :offset-assert 928)
|
||||
(flare-alpha-clr gs-packed-rgba :inline :offset-assert 944)
|
||||
(flare-alpha-uv gs-packed-uv :inline :offset-assert 960)
|
||||
@ -23876,7 +23878,7 @@
|
||||
(flare-alpha-xyzw-2 gs-packed-xyzw :inline :offset-assert 1008)
|
||||
(flare-alpha-xyzw-3 gs-packed-xyzw :inline :offset-assert 1024)
|
||||
(flare-init-giftag gs-gif-tag :inline :offset-assert 1040)
|
||||
(flare-init-adcmds vector4w 8 :inline :offset-assert 1056) ;; gs-adcmd?
|
||||
(flare-init-adcmds gs-adcmd 8 :inline :offset-assert 1056) ;; gs-adcmd?
|
||||
(flare-draw-giftag gs-gif-tag :inline :offset-assert 1184)
|
||||
(flare-draw-clr gs-packed-rgba :inline :offset-assert 1200)
|
||||
(flare-draw-stq-0 gs-packed-stq :inline :offset-assert 1216)
|
||||
@ -23894,11 +23896,11 @@
|
||||
)
|
||||
|
||||
(deftype sprite-glow-consts (structure)
|
||||
((camera matrix :inline :offset-assert 0)
|
||||
(perspective matrix :inline :offset-assert 64)
|
||||
(hvdf-offset vector :inline :offset-assert 128)
|
||||
(hmge-scale vector :inline :offset-assert 144)
|
||||
(consts vector :inline :offset-assert 160 :score -1)
|
||||
((camera matrix :inline :offset-assert 0) ;; 0
|
||||
(perspective matrix :inline :offset-assert 64) ;; 4
|
||||
(hvdf-offset vector :inline :offset-assert 128);; 8
|
||||
(hmge-scale vector :inline :offset-assert 144) ;; 9
|
||||
(consts vector :inline :offset-assert 160 :score -1) ;; 10
|
||||
(pfog0 float :offset 160)
|
||||
(deg-to-rad float :offset 164)
|
||||
(min-scale float :offset 168)
|
||||
@ -23935,6 +23937,7 @@
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
@ -23950,9 +23953,11 @@
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
(shader-packet-ptr pointer :offset 116) ;; pointer to adgif shader to upload.
|
||||
(mscal-packet dma-packet :inline :offset-assert 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@ -23966,9 +23971,9 @@
|
||||
(define-extern sprite-glow-init-engine (function dma-buffer none))
|
||||
(define-extern *sprite-glow-dma-packet-data* sprite-glow-dma-packet-data)
|
||||
(define-extern sprite-glow-add-sprite (function dma-buffer sprite-vec-data-2d float float float adgif-shader none))
|
||||
(define-extern sprite-glow-add-simple-sprite (function dma-buffer sprite-glow-dma-packet-data sprite-glow-data pointer))
|
||||
(define-extern sprite-glow-add-simple-sprite (function dma-buffer sprite-glow-dma-packet-data sprite-glow-data pointer none))
|
||||
(define-extern sprite-glow-draw (function dma-buffer none))
|
||||
(define-extern add-shader-to-dma (function dma-buffer pointer))
|
||||
(define-extern add-shader-to-dma (function dma-buffer adgif-shader))
|
||||
(define-extern *simple-sprite-system* simple-sprite-system)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -495,7 +495,7 @@
|
||||
"(method 181 gator)": [
|
||||
2, 3, 7, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 30
|
||||
],
|
||||
"(method 10 simple-sprite-system)": [0, 1, 3, 4, 5, 6, 9, 11],
|
||||
"(method 10 simple-sprite-system)": [0],
|
||||
"target-pilot-post": [0, 2, 4, 13, 16, 22, 27, 41],
|
||||
"(anon-function 0 ruins-obs)": [
|
||||
0, 5, 7, 12, 13, 15, 17, 23, 24, 33, 42, 45, 46, 53, 58
|
||||
|
@ -66,7 +66,7 @@
|
||||
"sprite-distort": [["L27", "vu-function"]],
|
||||
"sprite-glow": [
|
||||
["L29", "vu-function"],
|
||||
["L27", "vector"]
|
||||
["L27", "dma-packet"]
|
||||
],
|
||||
"debug": [
|
||||
["L250", "(inline-array vector)", 32],
|
||||
|
@ -1591,7 +1591,7 @@
|
||||
[48, "vector4w"]
|
||||
],
|
||||
"(method 22 traffic-tracker)": [[16, "mystery-traffic-object-spawn-params"]],
|
||||
"(method 10 simple-sprite-system)": [[16, ["array", "texture-id", 4]]],
|
||||
"(method 10 simple-sprite-system)": [[16, ["array", "texture-id", 128]]],
|
||||
"(anon-function 3 ruins-obs)": [[16, "event-message-block"]],
|
||||
"(event unbroken ruins-breakable-wall)": [[16, "attack-info"]],
|
||||
"(method 21 spider-eyes)": [[32, "vector"]],
|
||||
|
@ -10525,5 +10525,21 @@
|
||||
[8, "a3", "pal-electric-fan"],
|
||||
[15, "a3", "pal-electric-fan"],
|
||||
[22, "t0", "pal-electric-fan"]
|
||||
],
|
||||
"sprite-glow-init-engine": [
|
||||
[[8, 22], "a0", "dma-packet"],
|
||||
[[32, 50], "a1", "dma-packet"],
|
||||
[[52, 74], "a1", "dma-packet"],
|
||||
[[76, 84], "a0", "dma-packet"],
|
||||
[[85, 92], "v1", "dma-packet"]
|
||||
],
|
||||
"sprite-glow-add-sprite": [
|
||||
[[0, 33], "v1", "sprite-glow-cnt-template"]
|
||||
],
|
||||
"sprite-glow-add-simple-sprite": [
|
||||
[[0, 33], "v1", "sprite-glow-ref-template"]
|
||||
],
|
||||
"add-shader-to-dma": [
|
||||
[[6, 8], "v1", "(pointer uint32)"]
|
||||
]
|
||||
}
|
||||
|
@ -749,6 +749,8 @@ const std::unordered_map<
|
||||
{
|
||||
{"ocean-near-indices",
|
||||
{{"data", ArrayFieldDecompMeta(TypeSpec("ocean-near-index"), 32)}}},
|
||||
{"simple-sprite-system",
|
||||
{{"data", ArrayFieldDecompMeta(TypeSpec("sprite-glow-data"), 64)}}},
|
||||
{"ocean-mid-masks", {{"data", ArrayFieldDecompMeta(TypeSpec("ocean-mid-mask"), 8)}}},
|
||||
{"sparticle-launcher",
|
||||
{{"init-specs", ArrayFieldDecompMeta(TypeSpec("sp-field-init-spec"), 16)}}},
|
||||
|
298
docs/progress-notes/jak2/sprite_glow.md
Normal file
298
docs/progress-notes/jak2/sprite_glow.md
Normal file
@ -0,0 +1,298 @@
|
||||
# Sprite Glow: EE side
|
||||
It's pretty simple, no asm.
|
||||
|
||||
# VU Memory Map
|
||||
Offset is 400 (0-400 -> 400-800 as input buffers)
|
||||
```
|
||||
|
||||
400 - 800 (input second buffer)
|
||||
800 - template copy 1
|
||||
884 - template copy 2
|
||||
980 - constants
|
||||
```
|
||||
# DMA init
|
||||
```
|
||||
@ 0x500930 tag: TAG: 0x00000000 cnt qwc 0x0018
|
||||
vif0: STCYCL cl: 4 wl: 4
|
||||
vif1: UNPACK-V4-32: 24 addr: 980 us: false tops: false
|
||||
|
||||
@ 0x500ac0 tag: TAG: 0x00777650 ref qwc 0x0054
|
||||
vif0: STCYCL cl: 4 wl: 4
|
||||
vif1: UNPACK-V4-32: 84 addr: 800 us: false tops: false
|
||||
|
||||
@ 0x500ad0 tag: TAG: 0x00777650 ref qwc 0x0054
|
||||
vif0: MSCAL 0x0
|
||||
vif1: UNPACK-V4-32: 84 addr: 884 us: false tops: false
|
||||
|
||||
@ 0x500ae0 tag: TAG: 0x00000000 cnt qwc 0x0000
|
||||
vif0: BASE 0x0
|
||||
vif1: OFFSET 0x190
|
||||
|
||||
@ 0x500af0 tag: TAG: 0x00000000 cnt qwc 0x0000
|
||||
vif0: NOP
|
||||
vif1: FLUSHE
|
||||
```
|
||||
|
||||
First tag is uploading the constants.
|
||||
|
||||
Next two are uploading two copies of the templates and run init. Output is double buffered, so this makes sense.
|
||||
|
||||
Next tag sets up input double buffer.
|
||||
|
||||
Final tag is just sync before starting the draws
|
||||
|
||||
# Template system
|
||||
The VU program is (as usual) double buffered.
|
||||
There are two input buffers, containing data uploaded through VIF.
|
||||
There are two output buffers, each containing the `sprite-glow-template`.
|
||||
While the program runs, it transform vertices, putting the results in the template.
|
||||
Once done, it `xgkick`s, which waits for the previous run's draw to finish if needed,
|
||||
then begins the drawing process.
|
||||
|
||||
# What is drawn?
|
||||
|
||||
Annoyingly, there are 6 draws this time:
|
||||
- Probe Clear alpha
|
||||
- Probe Draw alpha
|
||||
- Offscreen sample
|
||||
- Offscreen repeat
|
||||
- Draw Alpha
|
||||
- Draw Final
|
||||
|
||||
In summary:
|
||||
- Probe Clear alpha: draw a `alpha = 0` square. Always drawn.
|
||||
- Probe Draw alpha: draw an `alpha = 1` square. 1 px smaller than first draw. Uses normal z test.
|
||||
|
||||
## Draw 1 and 2: "Probe Clear alpha" and "Probe Draw alpha"
|
||||
First is the `clear`. The first tag is 5 regs of adgif:
|
||||
- `texflush`
|
||||
- `(new 'static 'gs-alpha :a 2 :b 2 :c 2 :d 1)`
|
||||
- `(new 'static 'gs-test :ate 1 :afail 1 :zte 1 :ztst 2)`
|
||||
- `(new 'static 'gs-zbuf :zbp 304 :psm 1 :zmsk 1)`
|
||||
- `(new 'static 'gs-frame :fbp 408 :fbw 8 :fbmsk #xffffff)`
|
||||
|
||||
The alpha is:
|
||||
```
|
||||
Cv = (0 - 0) * 0 + Cd
|
||||
```
|
||||
which means to not write any color.
|
||||
|
||||
The test is:
|
||||
- alpha test always fails, means only rgba is written always
|
||||
- ztest is usual GEQUAL
|
||||
|
||||
When combined with the alpha settings, this only writes alpha, no rgb or depth.
|
||||
|
||||
The zbuf looks at the normal zbuf, but z writing is masked again. Just in case.
|
||||
|
||||
The gs-frame yet again masks away rgb writes. Just in case.
|
||||
|
||||
There are two draws. Both are sprites. The first draw sets alpha to 0 and uses z = #xffffff, so it always passes.
|
||||
|
||||
The second draw is similar but:
|
||||
- z comes from the transformed vertex. So it has normal depth test behavior
|
||||
- alpha is 1
|
||||
- it's 1 pixel smaller than the first draw.
|
||||
|
||||
So the end result is:
|
||||
- a `alpha = 0` square always
|
||||
- an `alpha = 1` square, offset in by 1 pixel on all sides, but only where depth passes.
|
||||
|
||||
## Draw 3: Offscreen Sample
|
||||
Switches to GS context 2. Samples from framebuffer and writes to a temporary texture (64 px width, uses only 32).
|
||||
- only writes alpha
|
||||
- mmag/mmin on
|
||||
- tcc = 1, tfx = 1 (rgba, decal) - RGBA all come from texture, nothing fancy
|
||||
- rgb writes masked (only write alpha)
|
||||
- clamp clamps
|
||||
- alpha test thing disables z buffer writing.
|
||||
|
||||
This basically just copies the inner square from draw 2 to a separate texture.
|
||||
|
||||
## Draw 4: Repeat draw
|
||||
This appears to draw over itself again and again. I think it effectively blends using texture filtering. So the 0, 0 px will have the average value of alpha.
|
||||
|
||||
## Draw 5: flare alpha
|
||||
This is set up in the `repeat-draw-adcmds`. Drawing to the framebuffer again.
|
||||
|
||||
|
||||
|
||||
|
||||
# VU1 program
|
||||
```
|
||||
out memory map:
|
||||
|
||||
68: adgif0
|
||||
69: adgif1
|
||||
70: adgif2
|
||||
71: adgif3
|
||||
72: adgif4
|
||||
```
|
||||
```
|
||||
;; math:
|
||||
|
||||
first, input position is multiplied by camera matrix (including adding part). Only xyz is computed here. (p0, vf01)
|
||||
|
||||
color: rgb *= a
|
||||
|
||||
fade = clamp(0, 1, p0.z * fade_a + fade_b)
|
||||
|
||||
|
||||
|
||||
|
||||
INIT program
|
||||
iaddiu vi05, vi00, 0x320 | nop ;; vi05 = 800 (template)
|
||||
lq.xyzw vf25, 988(vi00) | nop
|
||||
lq.xyzw vf26, 989(vi00) | nop
|
||||
lq.xyzw vf27, 990(vi00) | nop
|
||||
lq.xyzw vf30, 996(vi00) | nop
|
||||
lq.xyzw vf31, 997(vi00) | nop
|
||||
lq.xyzw vf28, 1002(vi00) | nop
|
||||
lq.xyzw vf29, 1003(vi00) | nop
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
|
||||
regs:
|
||||
|
||||
vi02 = input ptr
|
||||
vi03 = num_sprites
|
||||
vi04 = adgif ptr
|
||||
vi05 = output buffer (double buffered, so toggles)
|
||||
|
||||
vf25 = hvdf
|
||||
vf26 = hmge
|
||||
vf27 = consts
|
||||
vf30 = basis_x
|
||||
vf31 = basis_y
|
||||
vf28 = clamp_min
|
||||
vf29 = clamp_max
|
||||
|
||||
DRAW program
|
||||
xtop vi02 | nop ;; vi02 = input buffer's control
|
||||
nop | nop
|
||||
ilwr.x vi03, vi02 | nop ;; vi03 = num_sprites (1 always?)
|
||||
iaddi vi02, vi02, 0x1 | nop ;; vi02 = sprite data
|
||||
iaddiu vi04, vi02, 0x90 | nop ;; vi04 = adgif data
|
||||
L1:
|
||||
lq.xyzw vf03, 2(vi02) | nop ;; vf03 = color
|
||||
lq.xyzw vf02, 1(vi02) | nop ;; vf02 = [size_probe, z_offset, rot-angle, size-y]
|
||||
lq.xyzw vf01, 0(vi02) | nop ;; vf01 = [position.xyz, size-x]
|
||||
lq.xyzw vf24, 983(vi00) | nop ;; vf24 = [camera_mat[3]]
|
||||
lq.xyzw vf21, 980(vi00) | nop ;; vf21 = [camera_mat[0]]
|
||||
lq.xyzw vf22, 981(vi00) | nop ;; vf22 = [camera_mat[1]]
|
||||
lq.xyzw vf23, 982(vi00) | nop ;; vf23 = [camera_mat[2]]
|
||||
lq.xyzw vf04, 3(vi02) | mulaw.xyz ACC, vf24, vf00 ;; vf04 = [fade_a, fade_b, X, X] | multiply
|
||||
lq.xyzw vf24, 987(vi00) | maddax.xyz ACC, vf21, vf01 ;; vf24 = [perspective[3]] | multiply
|
||||
lq.xyzw vf21, 984(vi00) | madday.xyz ACC, vf22, vf01 ;; vf21 = [perspective[0]] | multiply
|
||||
lq.xyzw vf22, 985(vi00) | maddz.xyz vf01, vf23, vf01 ;; vf22 = [perspective[1]] | multiply
|
||||
lq.xyzw vf23, 986(vi00) | nop ;; vf23 = [perspective[2]]
|
||||
lq.xyzw vf09, 0(vi04) | nop ;; vf09 = adgif[0]
|
||||
lq.xyzw vf10, 1(vi04) | mulw.xyz vf03, vf03, vf03 ;; vf10 = adgif[1] | color multiply by alpha
|
||||
div Q, vf02.y, vf01.z | mulz.x vf04, vf04, vf01 ;; Q = (z_offset / p0.z) | fade_a *= p0.z
|
||||
lq.xyzw vf11, 2(vi04) | nop ;; vf11 = adgif[2]
|
||||
0.0078125 | nop :i ;; I = 0.0078125 (= 1/128)
|
||||
lq.xyzw vf12, 3(vi04) | nop ;; vf12 = adgif[3]
|
||||
lq.xyzw vf13, 4(vi04) | addy.x vf04, vf04, vf04 ;; vf13 = adgif[4] | fade_a += fade_b
|
||||
sq.xyzw vf09, 68(vi05) | muly.z vf05, vf02, vf27 ;; adgif0 store | vf05.z = rot-angle * deg_to_rad
|
||||
move.w vf05, vf00 | addw.z vf02, vf00, vf01 ;; vf05.w = 1 | vf02.z = size-x
|
||||
sq.xyzw vf10, 69(vi05) | mul.w vf09, vf00, Q ;; agdif1 store | vf09.w = (z_offset / p0.z)
|
||||
sq.xyzw vf11, 70(vi05) | nop ;; adgif2 store
|
||||
sq.xyzw vf12, 71(vi05) | miniw.x vf04, vf04, vf00 ;; adgif3 store | clamp fade 1
|
||||
sq.xyzw vf13, 72(vi05) | nop ;; adgif4 store
|
||||
nop | subw.w vf09, vf00, vf09 ;; vf09.w = 1 - (z_offset / p0.z);
|
||||
nop | maxx.x vf04, vf04, vf00 ;; clamp fade 2
|
||||
nop | mulw.xyz vf01, vf01, vf09 ;; multiply by pscale
|
||||
nop | mulx.xyz vf03, vf03, vf04 ;; multiply color by fade
|
||||
nop | mulaw.xyzw ACC, vf24, vf00 ;; multiply by perspective matrix
|
||||
nop | maddax.xyzw ACC, vf21, vf01
|
||||
nop | madday.xyzw ACC, vf22, vf01
|
||||
nop | muli.xyz vf03, vf03, I ;; color scaling.
|
||||
nop | maddz.xyzw vf01, vf23, vf01 ;; perspective matrix.
|
||||
nop | nop
|
||||
iaddi vi03, vi03, -0x1 | mulz.z vf06, vf05, vf05 ;; dec sprite count | vf06 = rot^2
|
||||
lq.xyzw vf15, 991(vi00) | nop ;; vf15 = sincos01
|
||||
iaddi vi02, vi02, 0x3 | nop ;; inc input pointer... by the wrong amount lol
|
||||
fcset 0x0 | mul.xyzw vf07, vf01, vf26 ;; hmge mult
|
||||
nop | mulz.zw vf09, vf05, vf06 ;; vf09 = rot^3
|
||||
lq.xyzw vf15, 992(vi00) | mula.zw ACC, vf05, vf15 ;; vf15 = sincos23 | acc working on sincos.
|
||||
nop | nop
|
||||
div Q, vf00.w, vf07.w | clipw.xyz vf07, vf07 ;; Q = 1 / p_hmged.w | clip!!!
|
||||
nop | mulz.zw vf10, vf09, vf06 ;; vf10 is rot thing
|
||||
lq.xyzw vf15, 993(vi00) | madda.zw ACC, vf09, vf15 ;; vf15 is rot coeff, working on sincos
|
||||
nop | nop
|
||||
fcand vi01, 0x3f | nop ;; check clipping result
|
||||
ibne vi00, vi01, L2 | mulz.zw vf09, vf10, vf06 ;; skip if clipped | working on rot
|
||||
lq.xyzw vf15, 994(vi00) | madda.zw ACC, vf10, vf15 ;; rot | rot
|
||||
nop | mul.xyz vf01, vf01, Q ;; perspective multiply
|
||||
nop | mul.xyzw vf02, vf02, Q ;; vf02 *= q
|
||||
nop | mulz.zw vf10, vf09, vf06 ;; rot
|
||||
lq.xyzw vf15, 995(vi00) | madda.zw ACC, vf09, vf15 ;; rot89 | rot
|
||||
nop | add.xyzw vf01, vf01, vf25 ;; hvdf offset
|
||||
nop | maxw.x vf02, vf02, vf00 ;; clip size_probe to 1
|
||||
nop | miniw.x vf02, vf02, vf29 ;; min size_probe against clamp max.w
|
||||
nop | miniz.zw vf02, vf02, vf29 ;; min zw against clamp max.z
|
||||
nop | madd.zw vf05, vf10, vf15 ;; vf05 = sincos output
|
||||
nop | ftoi0.xyzw vf03, vf03 ;; colors to ints or whatever
|
||||
nop | addx.xy vf09, vf28, vf02 ;; vf09 = [cmin.x + probe_size, cmin.y + probe_size]
|
||||
nop | subx.xy vf11, vf01, vf02 ;; vf11 = probe lower corner = [p0.xy - probe_size]
|
||||
nop | addx.xy vf12, vf01, vf02 ;; vf12 = probe upper corner = [po.xy + probe_size]
|
||||
nop | subx.xy vf10, vf29, vf02 ;; vf10 = [cmax.x - probe_size, cmax.y - probe_size]
|
||||
nop | mulaz.xyzw ACC, vf30, vf05
|
||||
nop | msubw.xyzw vf15, vf31, vf05 ;; rotate the basis
|
||||
|
||||
nop | max.xy vf20, vf01, vf09 ;; vf20 is some clamped position.
|
||||
nop | addx.zw vf11, vf01, vf00 ;; vf11.zw = vf01.zw
|
||||
nop | addx.zw vf12, vf01, vf00 ;; vf12.zw = vf01.zw
|
||||
nop | subw.xy vf17, vf28, vf00 ;; vf17 = [clamp_min.x - 1, clamp_min.y - 1]
|
||||
nop | mulz.xyzw vf15, vf15, vf02 ;; rot_basis *= vf02.z (x-scale)
|
||||
nop | addw.xy vf18, vf28, vf00 ;; vf18 = [calm_min.x + 1, clamp_min.y + 1]
|
||||
nop | ftoi4.xyzw vf11, vf11 ;; usual ftoi4 of clear positions
|
||||
nop | ftoi4.xyzw vf12, vf12
|
||||
nop | mini.xy vf20, vf20, vf10 ;; vf20 clamp again.
|
||||
nop | mulaw.xyzw ACC, vf30, vf05
|
||||
sq.xyzw vf03, 75(vi05) | maddz.xyzw vf16, vf31, vf05 ;; store color of flare | second row of rotation matrix
|
||||
sq.xyz vf11, 11(vi05) | sub.xy vf17, vf20, vf17 ;; store clear pos | offset vf17
|
||||
sq.xyz vf12, 12(vi05) | sub.xy vf18, vf20, vf18 ;; store clear pos | offset vf18
|
||||
lq.xyzw vf11, 998(vi00) | subx.xy vf19, vf20, vf02 ;; compute first clear pos,
|
||||
lq.xyzw vf12, 999(vi00) | mulw.xyzw vf16, vf16, vf02 ;; y scale
|
||||
lq.xyzw vf13, 1000(vi00) | addx.xy vf20, vf20, vf02 ;; first clear pos, upper corner.
|
||||
lq.xyzw vf14, 1001(vi00) | mulaw.xyzw ACC, vf01, vf00
|
||||
nop | maddax.xyzw ACC, vf15, vf11
|
||||
nop | maddy.xyzw vf11, vf16, vf11
|
||||
nop | mulaw.xyzw ACC, vf01, vf00
|
||||
nop | maddax.xyzw ACC, vf15, vf12
|
||||
nop | maddy.xyzw vf12, vf16, vf12
|
||||
nop | mulaw.xyzw ACC, vf01, vf00
|
||||
nop | maddax.xyzw ACC, vf15, vf13
|
||||
nop | maddy.xyzw vf13, vf16, vf13
|
||||
nop | mulaw.xyzw ACC, vf01, vf00
|
||||
nop | maddax.xyzw ACC, vf15, vf14
|
||||
nop | maddy.xyzw vf14, vf16, vf14
|
||||
nop | subx.xy vf17, vf17, vf02
|
||||
nop | addx.xy vf18, vf18, vf02
|
||||
iaddiu vi04, vi04, 0x50 | subw.xy vf19, vf19, vf00 ;; offset first clear pos lower
|
||||
nop | addw.xy vf20, vf20, vf00 ;; offset first clear pos upper
|
||||
nop | ftoi4.xyzw vf11, vf11
|
||||
nop | ftoi4.xyzw vf12, vf12
|
||||
nop | ftoi4.xyzw vf13, vf13
|
||||
nop | ftoi4.xyzw vf14, vf14
|
||||
sq.xy vf11, 61(vi05) | ftoi4.xyzw vf17, vf17
|
||||
sq.xy vf12, 62(vi05) | ftoi4.xyzw vf18, vf18
|
||||
sq.xy vf13, 63(vi05) | ftoi4.xyzw vf19, vf19
|
||||
sq.xy vf14, 64(vi05) | ftoi4.xyzw vf20, vf20
|
||||
sq.xy vf17, 24(vi05) | nop
|
||||
sq.xy vf18, 26(vi05) | nop
|
||||
sq.xy vf19, 8(vi05) | nop
|
||||
sq.xy vf20, 9(vi05) | nop
|
||||
sq.xy vf11, 77(vi05) | nop
|
||||
sq.xy vf12, 79(vi05) | nop
|
||||
sq.xy vf13, 81(vi05) | nop
|
||||
sq.xy vf14, 83(vi05) | nop
|
||||
xgkick vi05 | nop
|
||||
L2:
|
||||
iaddiu vi01, vi00, 0x694 | nop
|
||||
ibne vi00, vi03, L1 | nop
|
||||
isub vi05, vi01, vi05 | nop
|
||||
nop | nop :e
|
||||
nop | nop
|
||||
```
|
@ -132,6 +132,11 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/foreground/Generic2_DMA.cpp
|
||||
graphics/opengl_renderer/foreground/Generic2_Build.cpp
|
||||
graphics/opengl_renderer/foreground/Generic2_OpenGL.cpp
|
||||
graphics/opengl_renderer/sprite/GlowRenderer.cpp
|
||||
graphics/opengl_renderer/sprite/Sprite3.cpp
|
||||
graphics/opengl_renderer/sprite/Sprite3_Distort.cpp
|
||||
graphics/opengl_renderer/sprite/Sprite3_Glow.cpp
|
||||
graphics/opengl_renderer/sprite/SpriteRenderer.cpp
|
||||
graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMid.cpp
|
||||
graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
|
||||
@ -159,8 +164,6 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/SkyBlendCPU.cpp
|
||||
graphics/opengl_renderer/SkyBlendGPU.cpp
|
||||
graphics/opengl_renderer/SkyRenderer.cpp
|
||||
graphics/opengl_renderer/Sprite3.cpp
|
||||
graphics/opengl_renderer/SpriteRenderer.cpp
|
||||
graphics/opengl_renderer/TextureUploadHandler.cpp
|
||||
graphics/opengl_renderer/VisDataHandler.cpp
|
||||
graphics/opengl_renderer/DepthCue.cpp
|
||||
|
@ -9,8 +9,6 @@
|
||||
#include "game/graphics/opengl_renderer/LightningRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/ShadowRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/SkyRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/Sprite3.h"
|
||||
#include "game/graphics/opengl_renderer/SpriteRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/TextureUploadHandler.h"
|
||||
#include "game/graphics/opengl_renderer/VisDataHandler.h"
|
||||
#include "game/graphics/opengl_renderer/background/Shrub.h"
|
||||
@ -20,6 +18,8 @@
|
||||
#include "game/graphics/opengl_renderer/foreground/Merc2.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/OceanMidAndFar.h"
|
||||
#include "game/graphics/opengl_renderer/ocean/OceanNear.h"
|
||||
#include "game/graphics/opengl_renderer/sprite/Sprite3.h"
|
||||
#include "game/graphics/opengl_renderer/sprite/SpriteRenderer.h"
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
@ -95,6 +95,11 @@ ShaderLibrary::ShaderLibrary(GameVersion version) {
|
||||
at(ShaderId::POST_PROCESSING) = {"post_processing", version};
|
||||
at(ShaderId::DEPTH_CUE) = {"depth_cue", version};
|
||||
at(ShaderId::EMERC) = {"emerc", version};
|
||||
at(ShaderId::GLOW_PROBE) = {"glow_probe", version};
|
||||
at(ShaderId::GLOW_PROBE_READ) = {"glow_probe_read", version};
|
||||
at(ShaderId::GLOW_PROBE_READ_DEBUG) = {"glow_probe_read_debug", version};
|
||||
at(ShaderId::GLOW_PROBE_DOWNSAMPLE) = {"glow_probe_downsample", version};
|
||||
at(ShaderId::GLOW_DRAW) = {"glow_draw", version};
|
||||
|
||||
for (auto& shader : m_shaders) {
|
||||
ASSERT_MSG(shader.okay(), "error compiling shader");
|
||||
|
@ -48,6 +48,11 @@ enum class ShaderId {
|
||||
POST_PROCESSING = 22,
|
||||
DEPTH_CUE = 23,
|
||||
EMERC = 24,
|
||||
GLOW_PROBE = 25,
|
||||
GLOW_PROBE_READ = 26,
|
||||
GLOW_PROBE_READ_DEBUG = 27,
|
||||
GLOW_PROBE_DOWNSAMPLE = 28,
|
||||
GLOW_DRAW = 29,
|
||||
MAX_SHADERS
|
||||
};
|
||||
|
||||
|
16
game/graphics/opengl_renderer/shaders/glow_draw.frag
Normal file
16
game/graphics/opengl_renderer/shaders/glow_draw.frag
Normal file
@ -0,0 +1,16 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
in float discard_flag;
|
||||
in vec2 uv_texture;
|
||||
|
||||
layout (binding = 0) uniform sampler2D tex;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 texture_color = texture(tex, uv_texture);
|
||||
color.xyz = texture_color.xyz * fragment_color.xyz * 2.f * discard_flag / 128.f;
|
||||
color.w = fragment_color.w * texture_color.w;
|
||||
}
|
31
game/graphics/opengl_renderer/shaders/glow_draw.vert
Normal file
31
game/graphics/opengl_renderer/shaders/glow_draw.vert
Normal file
@ -0,0 +1,31 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec2 uv_texture_in;
|
||||
layout (location = 3) in vec2 uv_probe_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec2 uv_texture;
|
||||
out float discard_flag;
|
||||
|
||||
const float SCISSOR_ADJUST = HEIGHT_SCALE * 512.0/448.0;
|
||||
|
||||
layout (binding = 1) uniform sampler2D probe_tex;
|
||||
|
||||
|
||||
void main() {
|
||||
vec4 transformed = position_in;
|
||||
transformed.xy -= (2048.);
|
||||
transformed.z /= (8388608);
|
||||
transformed.z -= 1;
|
||||
transformed.x /= (256);
|
||||
transformed.y /= -(128);
|
||||
transformed.xyz *= transformed.w;
|
||||
// scissoring area adjust
|
||||
transformed.y *= SCISSOR_ADJUST;
|
||||
gl_Position = transformed;
|
||||
fragment_color = rgba_in;
|
||||
uv_texture = uv_texture_in;
|
||||
discard_flag = texture(probe_tex, uv_probe_in).a;
|
||||
}
|
10
game/graphics/opengl_renderer/shaders/glow_probe.frag
Normal file
10
game/graphics/opengl_renderer/shaders/glow_probe.frag
Normal file
@ -0,0 +1,10 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
|
||||
|
||||
void main() {
|
||||
color = fragment_color;
|
||||
}
|
23
game/graphics/opengl_renderer/shaders/glow_probe.vert
Normal file
23
game/graphics/opengl_renderer/shaders/glow_probe.vert
Normal file
@ -0,0 +1,23 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
|
||||
const float SCISSOR_ADJUST = HEIGHT_SCALE * 512.0/448.0;
|
||||
|
||||
void main() {
|
||||
vec4 transformed = position_in;
|
||||
transformed.xy -= (2048.);
|
||||
transformed.z /= (8388608);
|
||||
transformed.z -= 1;
|
||||
transformed.x /= (256);
|
||||
transformed.y /= -(128);
|
||||
transformed.xyz *= transformed.w;
|
||||
// scissoring area adjust
|
||||
transformed.y *= SCISSOR_ADJUST;
|
||||
gl_Position = transformed;
|
||||
|
||||
fragment_color = rgba_in;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 out_color;
|
||||
uniform sampler2D tex;
|
||||
in flat vec4 fragment_color;
|
||||
in vec2 tex_coord;
|
||||
|
||||
void main() {
|
||||
vec2 texture_coords = vec2(tex_coord.x, tex_coord.y);
|
||||
|
||||
// sample framebuffer texture
|
||||
out_color = texture(tex, texture_coords);
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 position_in;
|
||||
|
||||
out vec2 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.xy * 2) - 1.f, 0.f, 1.f);
|
||||
tex_coord = position_in.xy;
|
||||
}
|
14
game/graphics/opengl_renderer/shaders/glow_probe_read.frag
Normal file
14
game/graphics/opengl_renderer/shaders/glow_probe_read.frag
Normal file
@ -0,0 +1,14 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 tex_coord;
|
||||
|
||||
void main() {
|
||||
vec2 texture_coords = vec2(tex_coord.x, tex_coord.y);
|
||||
|
||||
// sample framebuffer texture
|
||||
out_color = texture(tex, texture_coords);
|
||||
}
|
13
game/graphics/opengl_renderer/shaders/glow_probe_read.vert
Normal file
13
game/graphics/opengl_renderer/shaders/glow_probe_read.vert
Normal file
@ -0,0 +1,13 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec2 uv;
|
||||
|
||||
out vec2 tex_coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.xy * 2) - 1.f, 0.f, 1.f);
|
||||
tex_coord.x = uv.x / 512;
|
||||
tex_coord.y = 1.f - ((uv.y + 16) / 448);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
#version 430 core
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
out_color = vec4(0, 0.5, 1, 1);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec4 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec2 uv;
|
||||
|
||||
void main() {
|
||||
float x = (uv.x / 512) * 2 - 1;
|
||||
float y = -(((uv.y + 16) / 448) * 2 - 1);
|
||||
gl_Position = vec4(x, y, 0, 1.f);
|
||||
}
|
737
game/graphics/opengl_renderer/sprite/GlowRenderer.cpp
Normal file
737
game/graphics/opengl_renderer/sprite/GlowRenderer.cpp
Normal file
@ -0,0 +1,737 @@
|
||||
#include "GlowRenderer.h"
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
/*
|
||||
* The glow renderer draws a sprite, but only if the center of the sprite is "visible".
|
||||
* To determine visibility, we draw a test "probe" at the center of the sprite and see how many
|
||||
* pixels of the probe were visible.
|
||||
*
|
||||
* The inputs to this renderer are the transformed vertices that would be computed on VU1.
|
||||
* The convention is that float -> int conversions and scalings are dropped.
|
||||
*
|
||||
* To detect if this is visible, we do something a little different from the original game:
|
||||
* - first copy the depth buffer to a separate texture. It seems like we could eliminate this copy
|
||||
* eventually and always render to a texture.
|
||||
*
|
||||
* - For each sprite draw a "test probe" using this depth buffer. Write to a separate texture.
|
||||
* This test probe is pretty small. First clear alpha to 0, then draw a test image with alpha = 1
|
||||
* and depth testing on.
|
||||
*
|
||||
* - Repeatedly sample the result of the probe as a texture and draw it to another texture with half
|
||||
* the size. This effectively averages the alpha values with texture filtering.
|
||||
*
|
||||
* - Stop once we've reached 2x2. At this point we can sample the center of this "texture" and the
|
||||
* alpha will indicate the fraction of pixels in the original probe that passed depth. Use this
|
||||
* to scale the intensity of the actual sprite draw.
|
||||
*
|
||||
* There are a number of optimizations made at this point:
|
||||
* - Probe clear/drawing are batched.
|
||||
* - Instead of doing the "downsampling" one-at-a-time, all probes are copied to a big grid and
|
||||
* the downsampling happens in batches.
|
||||
* - The sampling of the final downsampled texture happens inside the vertex shader. On PS2, it's
|
||||
* used as a texture, drawn as alpha-only over the entire region, then blended with the final
|
||||
* draw. But the alpha of the entire first draw is constant, and we can figure it out in the
|
||||
* vertex shader, so there's no need to do this approach.
|
||||
*
|
||||
* there are a few remaining improvements that could be made:
|
||||
* - The final draws could be bucketed, this would reduce draw calls by a lot.
|
||||
* - The depth buffer copy could likely be eliminated.
|
||||
* - There's a possibility that overlapping probes do the "wrong" thing. This could be solved by
|
||||
* copying from the depth buffer to the grid, then drawing probes on the grid. Currently the
|
||||
* probes are drawn aligned with the framebuffer, then copied back to the grid. This approach
|
||||
* would also lower the vram needed.
|
||||
*/
|
||||
|
||||
GlowRenderer::GlowRenderer() {
|
||||
m_vertex_buffer.resize(kMaxVertices);
|
||||
m_sprite_data_buffer.resize(kMaxSprites);
|
||||
m_index_buffer.resize(kMaxIndices);
|
||||
|
||||
// dynamic buffer: this will hold vertices that are generated by the game and updated each frame.
|
||||
// the most important optimization here is to have as few uploads as possible. The size of the
|
||||
// upload isn't too important - we only have at most 256 sprites so the overhead of uploading
|
||||
// anything dominates. So we use a single vertex format for all of our draws.
|
||||
{
|
||||
glGenBuffers(1, &m_ogl.vertex_buffer);
|
||||
glGenVertexArrays(1, &m_ogl.vao);
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
|
||||
auto bytes = kMaxVertices * sizeof(Vertex);
|
||||
glBufferData(GL_ARRAY_BUFFER, bytes, nullptr, GL_STREAM_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, x) // offset in array
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
4, // 4 color components
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, r) // offset in array
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, // location 2 in the shader
|
||||
2, // 2 uv
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, u) // offset in array (why is this a pointer...)
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, // location 2 in the shader
|
||||
2, // 2 uv
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, uu) // offset in array (why is this a pointer...)
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glGenBuffers(1, &m_ogl.index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxIndices * sizeof(u32), nullptr, GL_STREAM_DRAW);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// static buffer: this will hold draws for downsampling. Because everything is normalized, we can
|
||||
// reuse the same vertices for all downsampling!
|
||||
// Note that we can't do a single giant square - otherwise it would "bleed" over the edges.
|
||||
// the boundary between cells needs to be preserved.
|
||||
{
|
||||
glGenBuffers(1, &m_ogl_downsampler.vertex_buffer);
|
||||
glGenVertexArrays(1, &m_ogl_downsampler.vao);
|
||||
glBindVertexArray(m_ogl_downsampler.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl_downsampler.vertex_buffer);
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<u32> indices;
|
||||
vertices.resize(kMaxSprites * 4);
|
||||
indices.resize(kMaxSprites * 5);
|
||||
for (int i = 0; i < kMaxSprites; i++) {
|
||||
int x = i / kDownsampleBatchWidth;
|
||||
int y = i % kDownsampleBatchWidth;
|
||||
float step = 1.f / kDownsampleBatchWidth;
|
||||
Vertex* vtx = &vertices.at(i * 4);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
vtx[j].r = 0.f; // debug
|
||||
vtx[j].g = 0.f;
|
||||
vtx[j].b = 0.f;
|
||||
vtx[j].a = 0.f;
|
||||
vtx[j].x = x * step;
|
||||
vtx[j].y = y * step;
|
||||
vtx[j].z = 0;
|
||||
vtx[j].w = 0;
|
||||
}
|
||||
vtx[1].x += step;
|
||||
vtx[2].y += step;
|
||||
vtx[3].x += step;
|
||||
vtx[3].y += step;
|
||||
indices.at(i * 5 + 0) = i * 4;
|
||||
indices.at(i * 5 + 1) = i * 4 + 1;
|
||||
indices.at(i * 5 + 2) = i * 4 + 2;
|
||||
indices.at(i * 5 + 3) = i * 4 + 3;
|
||||
indices.at(i * 5 + 4) = UINT32_MAX;
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(),
|
||||
GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, x) // offset in array
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
4, // 4 color components
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, r) // offset in array
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, // location 2 in the shader
|
||||
3, // 4 color components
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, u) // offset in array (why is this a pointer...)
|
||||
);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glGenBuffers(1, &m_ogl_downsampler.index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl_downsampler.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(u32), indices.data(),
|
||||
GL_STATIC_DRAW);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// probe fbo setup: this fbo will hold the result of drawing probes.
|
||||
glGenFramebuffers(1, &m_ogl.probe_fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.probe_fbo);
|
||||
glGenTextures(1, &m_ogl.probe_fbo_rgba_tex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glGenRenderbuffers(1, &m_ogl.probe_fbo_zbuf_rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_ogl.probe_fbo_w,
|
||||
m_ogl.probe_fbo_h);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
|
||||
m_ogl.probe_fbo_zbuf_rb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
m_ogl.probe_fbo_rgba_tex, 0);
|
||||
GLenum render_targets[1] = {GL_COLOR_ATTACHMENT0};
|
||||
glDrawBuffers(1, render_targets);
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
ASSERT(status == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
// downsample fbo setup: each will hold a grid of probes.
|
||||
// there's one fbo for each size.
|
||||
int ds_size = kFirstDownsampleSize;
|
||||
for (int i = 0; i < kDownsampleIterations; i++) {
|
||||
m_ogl.downsample_fbos[i].size = ds_size * kDownsampleBatchWidth;
|
||||
glGenFramebuffers(1, &m_ogl.downsample_fbos[i].fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.downsample_fbos[i].fbo);
|
||||
glGenTextures(1, &m_ogl.downsample_fbos[i].tex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, m_ogl.downsample_fbos[i].tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ds_size * kDownsampleBatchWidth,
|
||||
ds_size * kDownsampleBatchWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
m_ogl.downsample_fbos[i].tex, 0);
|
||||
glDrawBuffers(1, render_targets);
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
ASSERT(status == GL_FRAMEBUFFER_COMPLETE);
|
||||
ds_size /= 2;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// set up a default draw mode for sprites. If they don't set values, they will get this
|
||||
// from the giftag
|
||||
m_default_draw_mode.set_ab(true);
|
||||
|
||||
// ;; (new 'static 'gs-test :ate 1 :afail 1 :zte 1 :ztst 2)
|
||||
// (new 'static 'gs-adcmd :cmds (gs-reg64 test-1) :x #x51001)
|
||||
m_default_draw_mode.set_at(true);
|
||||
m_default_draw_mode.set_alpha_fail(GsTest::AlphaFail::FB_ONLY);
|
||||
m_default_draw_mode.set_zt(true);
|
||||
m_default_draw_mode.set_depth_test(GsTest::ZTest::GEQUAL);
|
||||
m_default_draw_mode.set_alpha_test(DrawMode::AlphaTest::NEVER);
|
||||
|
||||
// ;; (new 'static 'gs-zbuf :zbp 304 :psm 1 :zmsk 1)
|
||||
// (new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-1) :x #x1000130 :y #x1)
|
||||
m_default_draw_mode.disable_depth_write();
|
||||
}
|
||||
|
||||
namespace {
|
||||
void copy_to_vertex(GlowRenderer::Vertex* vtx, const Vector4f& xyzw) {
|
||||
vtx->x = xyzw.x();
|
||||
vtx->y = xyzw.y();
|
||||
vtx->z = xyzw.z();
|
||||
vtx->w = xyzw.w();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
SpriteGlowOutput* GlowRenderer::alloc_sprite() {
|
||||
ASSERT(m_next_sprite < m_sprite_data_buffer.size());
|
||||
return &m_sprite_data_buffer[m_next_sprite++];
|
||||
}
|
||||
|
||||
void GlowRenderer::cancel_sprite() {
|
||||
ASSERT(m_next_sprite);
|
||||
m_next_sprite--;
|
||||
}
|
||||
|
||||
// vertex addition is done in passes, so the "pass1" for all sprites is before any "pass2" vertices.
|
||||
// But, we still do a single big upload for all passes.
|
||||
// this way pass1 can be a single giant draw.
|
||||
|
||||
/*!
|
||||
* Add pass 1 vertices, for drawing the probe.
|
||||
*/
|
||||
void GlowRenderer::add_sprite_pass_1(const SpriteGlowOutput& data) {
|
||||
{ // first draw is a GS sprite to clear the alpha. This is faster than glClear, and the game
|
||||
// computes these for us and gives it a large z that always passes.
|
||||
// We need to convert to triangle strip.
|
||||
u32 idx_start = m_next_vertex;
|
||||
Vertex* vtx = alloc_vtx(4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vtx[i].r = 1.f; // red for debug
|
||||
vtx[i].g = 0.f;
|
||||
vtx[i].b = 0.f;
|
||||
vtx[i].a = 0.f; // clearing alpha
|
||||
}
|
||||
copy_to_vertex(vtx, data.first_clear_pos[0]);
|
||||
copy_to_vertex(vtx + 1, data.first_clear_pos[0]);
|
||||
vtx[1].x = data.first_clear_pos[1].x();
|
||||
copy_to_vertex(vtx + 2, data.first_clear_pos[0]);
|
||||
vtx[2].y = data.first_clear_pos[1].y();
|
||||
copy_to_vertex(vtx + 3, data.first_clear_pos[1]);
|
||||
|
||||
u32* idx = alloc_index(5);
|
||||
idx[0] = idx_start;
|
||||
idx[1] = idx_start + 1;
|
||||
idx[2] = idx_start + 2;
|
||||
idx[3] = idx_start + 3;
|
||||
idx[4] = UINT32_MAX;
|
||||
}
|
||||
|
||||
{ // second draw is the actual probe, using the real Z, and setting alpha to 1.
|
||||
u32 idx_start = m_next_vertex;
|
||||
Vertex* vtx = alloc_vtx(4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vtx[i].r = 0.f;
|
||||
vtx[i].g = 1.f; // green for debug
|
||||
vtx[i].b = 0.f;
|
||||
vtx[i].a = 1.f; // setting alpha
|
||||
}
|
||||
copy_to_vertex(vtx, data.second_clear_pos[0]);
|
||||
copy_to_vertex(vtx + 1, data.second_clear_pos[0]);
|
||||
vtx[1].x = data.second_clear_pos[1].x();
|
||||
copy_to_vertex(vtx + 2, data.second_clear_pos[0]);
|
||||
vtx[2].y = data.second_clear_pos[1].y();
|
||||
copy_to_vertex(vtx + 3, data.second_clear_pos[1]);
|
||||
|
||||
u32* idx = alloc_index(5);
|
||||
idx[0] = idx_start;
|
||||
idx[1] = idx_start + 1;
|
||||
idx[2] = idx_start + 2;
|
||||
idx[3] = idx_start + 3;
|
||||
idx[4] = UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add pass 2 vertices, for copying from the probe fbo to the biggest grid.
|
||||
*/
|
||||
void GlowRenderer::add_sprite_pass_2(const SpriteGlowOutput& data, int sprite_idx) {
|
||||
// output is a grid of kBatchWidth * kBatchWidth.
|
||||
// for simplicity, we'll map to (0, 1) here, and the shader will convert to (-1, 1) for opengl.
|
||||
int x = sprite_idx / kDownsampleBatchWidth;
|
||||
int y = sprite_idx % kDownsampleBatchWidth;
|
||||
float step = 1.f / kDownsampleBatchWidth;
|
||||
|
||||
u32 idx_start = m_next_vertex;
|
||||
Vertex* vtx = alloc_vtx(4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vtx[i].r = 1.f; // debug
|
||||
vtx[i].g = 0.f;
|
||||
vtx[i].b = 0.f;
|
||||
vtx[i].a = 0.f;
|
||||
vtx[i].x = x * step; // start of our cell
|
||||
vtx[i].y = y * step;
|
||||
vtx[i].z = 0;
|
||||
vtx[i].w = 0;
|
||||
}
|
||||
vtx[1].x += step;
|
||||
vtx[2].y += step;
|
||||
vtx[3].x += step;
|
||||
vtx[3].y += step;
|
||||
|
||||
// transformation code gives us these coordinates for where to sample probe fbo
|
||||
vtx[0].u = data.offscreen_uv[0][0];
|
||||
vtx[0].v = data.offscreen_uv[0][1];
|
||||
vtx[1].u = data.offscreen_uv[1][0];
|
||||
vtx[1].v = data.offscreen_uv[0][1];
|
||||
vtx[2].u = data.offscreen_uv[0][0];
|
||||
vtx[2].v = data.offscreen_uv[1][1];
|
||||
vtx[3].u = data.offscreen_uv[1][0];
|
||||
vtx[3].v = data.offscreen_uv[1][1];
|
||||
|
||||
u32* idx = alloc_index(5);
|
||||
idx[0] = idx_start;
|
||||
idx[1] = idx_start + 1;
|
||||
idx[2] = idx_start + 2;
|
||||
idx[3] = idx_start + 3;
|
||||
idx[4] = UINT32_MAX;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add pass 3 vertices and update sprite records. This is the final draw.
|
||||
*/
|
||||
void GlowRenderer::add_sprite_pass_3(const SpriteGlowOutput& data, int sprite_idx) {
|
||||
// figure out our cell, we'll need to read from this to see if we're visible or not.
|
||||
int x = sprite_idx / kDownsampleBatchWidth;
|
||||
int y = sprite_idx % kDownsampleBatchWidth;
|
||||
float step = 1.f / kDownsampleBatchWidth;
|
||||
|
||||
u32 idx_start = m_next_vertex;
|
||||
Vertex* vtx = alloc_vtx(4);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// include the color, used by the shader
|
||||
vtx[i].r = data.flare_draw_color[0];
|
||||
vtx[i].g = data.flare_draw_color[1];
|
||||
vtx[i].b = data.flare_draw_color[2];
|
||||
vtx[i].a = data.flare_draw_color[3];
|
||||
copy_to_vertex(&vtx[i], data.flare_xyzw[i]);
|
||||
vtx[i].u = 0;
|
||||
vtx[i].v = 0;
|
||||
// where to sample from to see probe result
|
||||
// offset by step/2 to sample the middle.
|
||||
// we use 2x2 for the final resolution and sample the middle - should be the same as
|
||||
// going to a 1x1, but saves a draw.
|
||||
vtx[i].uu = x * step + step / 2;
|
||||
vtx[i].vv = y * step + step / 2;
|
||||
}
|
||||
// texture uv's hardcoded to corners
|
||||
vtx[1].u = 1;
|
||||
vtx[3].v = 1;
|
||||
vtx[2].u = 1;
|
||||
vtx[2].v = 1;
|
||||
|
||||
// get a record
|
||||
auto& record = m_sprite_records[sprite_idx];
|
||||
record.draw_mode = m_default_draw_mode;
|
||||
record.tbp = 0;
|
||||
record.idx = m_next_index;
|
||||
|
||||
u32* idx = alloc_index(5);
|
||||
// flip first two - fan -> strip
|
||||
idx[0] = idx_start + 1;
|
||||
idx[1] = idx_start + 0;
|
||||
idx[2] = idx_start + 2;
|
||||
idx[3] = idx_start + 3;
|
||||
idx[4] = UINT32_MAX;
|
||||
|
||||
// handle adgif stuff
|
||||
{
|
||||
ASSERT(data.adgif.tex0_addr == (u32)GsRegisterAddress::TEX0_1);
|
||||
GsTex0 reg(data.adgif.tex0_data);
|
||||
record.tbp = reg.tbp0();
|
||||
record.draw_mode.set_tcc(reg.tcc());
|
||||
// shader is hardcoded for this right now.
|
||||
ASSERT(reg.tcc() == 1);
|
||||
ASSERT(reg.tfx() == GsTex0::TextureFunction::MODULATE);
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT((u8)data.adgif.tex1_addr == (u8)GsRegisterAddress::TEX1_1);
|
||||
GsTex1 reg(data.adgif.tex1_data);
|
||||
record.draw_mode.set_filt_enable(reg.mmag());
|
||||
}
|
||||
|
||||
{
|
||||
ASSERT(data.adgif.mip_addr == (u32)GsRegisterAddress::MIPTBP1_1);
|
||||
// ignore
|
||||
}
|
||||
|
||||
// clamp or zbuf
|
||||
if (GsRegisterAddress(data.adgif.clamp_addr) == GsRegisterAddress::ZBUF_1) {
|
||||
GsZbuf x(data.adgif.clamp_data);
|
||||
record.draw_mode.set_depth_write_enable(!x.zmsk());
|
||||
} else if (GsRegisterAddress(data.adgif.clamp_addr) == GsRegisterAddress::CLAMP_1) {
|
||||
u32 val = data.adgif.clamp_data;
|
||||
if (!(val == 0b101 || val == 0 || val == 1 || val == 0b100)) {
|
||||
ASSERT_MSG(false, fmt::format("clamp: 0x{:x}", val));
|
||||
}
|
||||
record.draw_mode.set_clamp_s_enable(val & 0b001);
|
||||
record.draw_mode.set_clamp_t_enable(val & 0b100);
|
||||
} else {
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
// alpha
|
||||
ASSERT(data.adgif.alpha_addr == (u32)GsRegisterAddress::ALPHA_1); // ??
|
||||
|
||||
// ;; a = 0, b = 2, c = 1, d = 1
|
||||
// Cv = (Cs - 0) * Ad + D
|
||||
// leaving out the multiply by Ad.
|
||||
record.draw_mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_0_FIX_DST);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Blit the depth buffer from the default rendering buffer to the depth buffer of the probe fbo.
|
||||
*/
|
||||
void GlowRenderer::blit_depth(SharedRenderState* render_state) {
|
||||
if (m_ogl.probe_fbo_w != render_state->render_fb_w ||
|
||||
m_ogl.probe_fbo_h != render_state->render_fb_h) {
|
||||
m_ogl.probe_fbo_w = render_state->render_fb_w;
|
||||
m_ogl.probe_fbo_h = render_state->render_fb_h;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_ogl.probe_fbo_w,
|
||||
m_ogl.probe_fbo_h);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_ogl.probe_fbo);
|
||||
|
||||
glBlitFramebuffer(render_state->render_fb_x, // srcX0
|
||||
render_state->render_fb_y, // srcY0
|
||||
render_state->render_fb_x + render_state->render_fb_w, // srcX1
|
||||
render_state->render_fb_y + render_state->render_fb_h, // srcY1
|
||||
0, // dstX0
|
||||
0, // dstY0
|
||||
m_ogl.probe_fbo_w, // dstX1
|
||||
m_ogl.probe_fbo_h, // dstY1
|
||||
GL_DEPTH_BUFFER_BIT, // mask
|
||||
GL_NEAREST // filter
|
||||
);
|
||||
}
|
||||
|
||||
void GlowRenderer::draw_debug_window() {
|
||||
ImGui::Checkbox("Show Probes", &m_debug.show_probes);
|
||||
ImGui::Checkbox("Show Copy", &m_debug.show_probe_copies);
|
||||
ImGui::Text("Count: %d", m_debug.num_sprites);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Do all downsample draws to make 2x2 textures.
|
||||
*/
|
||||
void GlowRenderer::downsample_chain(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 num_sprites) {
|
||||
glBindVertexArray(m_ogl_downsampler.vao);
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
render_state->shaders[ShaderId::GLOW_PROBE_DOWNSAMPLE].activate();
|
||||
for (int i = 0; i < kDownsampleIterations - 1; i++) {
|
||||
auto* source = &m_ogl.downsample_fbos[i];
|
||||
auto* dest = &m_ogl.downsample_fbos[i + 1];
|
||||
glBindTexture(GL_TEXTURE_2D, source->tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, dest->fbo);
|
||||
glViewport(0, 0, dest->size, dest->size);
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(num_sprites * 4);
|
||||
// the grid fill order is the same as the downsample order, so we don't need to do all cells
|
||||
// if we aren't using all sprites.
|
||||
glDrawElements(GL_TRIANGLE_STRIP, num_sprites * 5, GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
glViewport(render_state->draw_offset_x, render_state->draw_offset_y, render_state->draw_region_w,
|
||||
render_state->draw_region_h);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draw probes (including the clear) to the probe fbo. Also copies vertex/index buffer.
|
||||
*/
|
||||
void GlowRenderer::draw_probes(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.probe_fbo);
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_next_vertex * sizeof(Vertex), m_vertex_buffer.data(),
|
||||
GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_index * sizeof(u32), m_index_buffer.data(),
|
||||
GL_STREAM_DRAW);
|
||||
|
||||
// do probes
|
||||
render_state->shaders[ShaderId::GLOW_PROBE].activate();
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_next_sprite * 4);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT,
|
||||
(void*)(idx_start * sizeof(u32)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draw red/green probes to the framebuffer for debugging.
|
||||
*/
|
||||
void GlowRenderer::debug_draw_probes(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end) {
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_next_sprite * 4);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT,
|
||||
(void*)(idx_start * sizeof(u32)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Copy probes from probe fbo to grid.
|
||||
*/
|
||||
void GlowRenderer::draw_probe_copies(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end) {
|
||||
// read probe from probe fbo, write it to the first downsample fbo
|
||||
render_state->shaders[ShaderId::GLOW_PROBE_READ].activate();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_ogl.downsample_fbos[0].fbo);
|
||||
glBindTexture(GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glViewport(0, 0, m_ogl.downsample_fbos[0].size, m_ogl.downsample_fbos[0].size);
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_next_sprite * 2);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT,
|
||||
(void*)(idx_start * sizeof(u32)));
|
||||
glViewport(render_state->draw_offset_x, render_state->draw_offset_y, render_state->draw_region_w,
|
||||
render_state->draw_region_h);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draw blue squares to show where probes and being copied from, to help debug texture offsets.
|
||||
*/
|
||||
void GlowRenderer::debug_draw_probe_copies(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end) {
|
||||
render_state->shaders[ShaderId::GLOW_PROBE_READ_DEBUG].activate();
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_next_sprite * 2);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, idx_end - idx_start, GL_UNSIGNED_INT,
|
||||
(void*)(idx_start * sizeof(u32)));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draw all pending sprites.
|
||||
*/
|
||||
void GlowRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
m_debug.num_sprites = m_next_sprite;
|
||||
if (!m_next_sprite) {
|
||||
// no sprites submitted.
|
||||
return;
|
||||
}
|
||||
|
||||
// copy depth from framebuffer to a temporary buffer
|
||||
// (this is a bit wasteful)
|
||||
blit_depth(render_state);
|
||||
|
||||
// generate vertex/index data for probes
|
||||
u32 probe_idx_start = m_next_index;
|
||||
for (u32 sidx = 0; sidx < m_next_sprite; sidx++) {
|
||||
add_sprite_pass_1(m_sprite_data_buffer[sidx]);
|
||||
}
|
||||
|
||||
// generate vertex/index data for copy to downsample buffer
|
||||
u32 copy_idx_start = m_next_index;
|
||||
for (u32 sidx = 0; sidx < m_next_sprite; sidx++) {
|
||||
add_sprite_pass_2(m_sprite_data_buffer[sidx], sidx);
|
||||
}
|
||||
u32 copy_idx_end = m_next_index;
|
||||
|
||||
// generate vertex/index data for framebuffer draws
|
||||
for (u32 sidx = 0; sidx < m_next_sprite; sidx++) {
|
||||
add_sprite_pass_3(m_sprite_data_buffer[sidx], sidx);
|
||||
}
|
||||
|
||||
// draw probes
|
||||
draw_probes(render_state, prof, probe_idx_start, copy_idx_start);
|
||||
if (m_debug.show_probes) {
|
||||
debug_draw_probes(render_state, prof, probe_idx_start, copy_idx_start);
|
||||
}
|
||||
|
||||
// copy probes
|
||||
draw_probe_copies(render_state, prof, copy_idx_start, copy_idx_end);
|
||||
if (m_debug.show_probe_copies) {
|
||||
debug_draw_probe_copies(render_state, prof, copy_idx_start, copy_idx_end);
|
||||
}
|
||||
|
||||
// downsample probes.
|
||||
downsample_chain(render_state, prof, m_next_sprite);
|
||||
|
||||
draw_sprites(render_state, prof);
|
||||
|
||||
m_next_vertex = 0;
|
||||
m_next_index = 0;
|
||||
m_next_sprite = 0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Final drawing of sprites.
|
||||
*/
|
||||
void GlowRenderer::draw_sprites(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, m_ogl.downsample_fbos[kDownsampleIterations - 1].tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
render_state->shaders[ShaderId::GLOW_DRAW].activate();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glEnable(GL_BLEND);
|
||||
// Cv = (Cs - 0) * Ad + D
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for (u32 i = 0; i < m_next_sprite; i++) {
|
||||
const auto& record = m_sprite_records[i];
|
||||
auto tex = render_state->texture_pool->lookup(record.tbp);
|
||||
if (!tex) {
|
||||
fmt::print("Failed to find texture at {}, using random", record.tbp);
|
||||
tex = render_state->texture_pool->get_placeholder_texture();
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, *tex);
|
||||
if (record.draw_mode.get_clamp_s_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (record.draw_mode.get_clamp_t_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
|
||||
if (record.draw_mode.get_filt_enable()) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(2);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_INT, (void*)(record.idx * sizeof(u32)));
|
||||
}
|
||||
}
|
||||
|
||||
GlowRenderer::Vertex* GlowRenderer::alloc_vtx(int num) {
|
||||
ASSERT(m_next_vertex + num <= m_vertex_buffer.size());
|
||||
auto* result = &m_vertex_buffer[m_next_vertex];
|
||||
m_next_vertex += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
u32* GlowRenderer::alloc_index(int num) {
|
||||
ASSERT(m_next_index + num <= m_index_buffer.size());
|
||||
auto* result = &m_index_buffer[m_next_index];
|
||||
m_next_index += num;
|
||||
return result;
|
||||
}
|
112
game/graphics/opengl_renderer/sprite/GlowRenderer.h
Normal file
112
game/graphics/opengl_renderer/sprite/GlowRenderer.h
Normal file
@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/graphics/opengl_renderer/sprite/sprite_common.h"
|
||||
|
||||
class GlowRenderer {
|
||||
public:
|
||||
GlowRenderer();
|
||||
SpriteGlowOutput* alloc_sprite();
|
||||
void cancel_sprite();
|
||||
|
||||
void flush(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void draw_debug_window();
|
||||
|
||||
// Vertex can hold all possible values for all passes. The total number of vertices is very small
|
||||
// so it ends up a lot faster to do a single upload, even if the size is like 50% larger than it
|
||||
// could be.
|
||||
struct Vertex {
|
||||
float x, y, z, w;
|
||||
float r, g, b, a;
|
||||
float u, v;
|
||||
float uu, vv;
|
||||
};
|
||||
|
||||
private:
|
||||
struct {
|
||||
bool show_probes = false;
|
||||
bool show_probe_copies = false;
|
||||
int num_sprites = 0;
|
||||
} m_debug;
|
||||
void add_sprite_pass_1(const SpriteGlowOutput& data);
|
||||
void add_sprite_pass_2(const SpriteGlowOutput& data, int sprite_idx);
|
||||
void add_sprite_pass_3(const SpriteGlowOutput& data, int sprite_idx);
|
||||
|
||||
void blit_depth(SharedRenderState* render_state);
|
||||
|
||||
void draw_probes(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end);
|
||||
|
||||
void debug_draw_probes(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end);
|
||||
|
||||
void draw_probe_copies(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end);
|
||||
|
||||
void debug_draw_probe_copies(SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
u32 idx_start,
|
||||
u32 idx_end);
|
||||
void downsample_chain(SharedRenderState* render_state, ScopedProfilerNode& prof, u32 num_sprites);
|
||||
|
||||
void draw_sprites(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
std::vector<Vertex> m_vertex_buffer;
|
||||
std::vector<SpriteGlowOutput> m_sprite_data_buffer;
|
||||
u32 m_next_sprite = 0;
|
||||
|
||||
u32 m_next_vertex = 0;
|
||||
Vertex* alloc_vtx(int num);
|
||||
|
||||
std::vector<u32> m_index_buffer;
|
||||
u32 m_next_index = 0;
|
||||
u32* alloc_index(int num);
|
||||
|
||||
struct DsFbo {
|
||||
int size = -1;
|
||||
GLuint fbo;
|
||||
GLuint tex;
|
||||
};
|
||||
|
||||
static constexpr int kDownsampleBatchWidth = 16;
|
||||
static constexpr int kMaxSprites = kDownsampleBatchWidth * kDownsampleBatchWidth;
|
||||
static constexpr int kMaxVertices = kMaxSprites * 32; // check.
|
||||
static constexpr int kMaxIndices = kMaxSprites * 32; // check.
|
||||
static constexpr int kDownsampleIterations = 5;
|
||||
static constexpr int kFirstDownsampleSize = 32; // should be power of 2.
|
||||
|
||||
struct {
|
||||
GLuint vertex_buffer;
|
||||
GLuint vao;
|
||||
GLuint index_buffer;
|
||||
|
||||
GLuint probe_fbo;
|
||||
GLuint probe_fbo_rgba_tex;
|
||||
GLuint probe_fbo_zbuf_rb;
|
||||
int probe_fbo_w = 640;
|
||||
int probe_fbo_h = 480;
|
||||
|
||||
DsFbo downsample_fbos[kDownsampleIterations];
|
||||
} m_ogl;
|
||||
|
||||
struct {
|
||||
GLuint vao;
|
||||
GLuint index_buffer;
|
||||
GLuint vertex_buffer;
|
||||
} m_ogl_downsampler;
|
||||
|
||||
DrawMode m_default_draw_mode;
|
||||
|
||||
struct SpriteRecord {
|
||||
u32 tbp;
|
||||
DrawMode draw_mode;
|
||||
u32 idx;
|
||||
};
|
||||
|
||||
std::array<SpriteRecord, kMaxSprites> m_sprite_records;
|
||||
};
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
#include "Sprite3.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
@ -36,19 +34,8 @@ u32 process_sprite_chunk_header(DmaFollower& dma) {
|
||||
return header[0];
|
||||
}
|
||||
|
||||
/*!
|
||||
* Does the next DMA transfer look like the frame data for sprite distort?
|
||||
*/
|
||||
bool looks_like_distort_frame_data(const DmaFollower& dma) {
|
||||
return dma.current_tag().kind == DmaTag::Kind::CNT &&
|
||||
dma.current_tag_vifcode0().kind == VifCode::Kind::NOP &&
|
||||
dma.current_tag_vifcode1().kind == VifCode::Kind::UNPACK_V4_32;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
constexpr int SPRITE_RENDERER_MAX_SPRITES = 1920 * 10;
|
||||
constexpr int SPRITE_RENDERER_MAX_DISTORT_SPRITES =
|
||||
256 * 10; // size of sprite-aux-list in GOAL code * SPRITE_MAX_AMOUNT_MULT
|
||||
} // namespace
|
||||
|
||||
Sprite3::Sprite3(const std::string& name, int my_id)
|
||||
: BucketRenderer(name, my_id), m_direct(name, my_id, 1024) {
|
||||
@ -143,620 +130,6 @@ void Sprite3::opengl_setup_normal() {
|
||||
m_current_mode = m_default_mode;
|
||||
}
|
||||
|
||||
void Sprite3::opengl_setup_distort() {
|
||||
// Create framebuffer to snapshot current render to a texture that can be bound for the distort
|
||||
// shader This will represent tex0 from the original GS data
|
||||
glGenFramebuffers(1, &m_distort_ogl.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_distort_ogl.fbo);
|
||||
|
||||
glGenTextures(1, &m_distort_ogl.fbo_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_distort_ogl.fbo_width, m_distort_ogl.fbo_height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
// Texture clamping here matches the GS init data for distort
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
m_distort_ogl.fbo_texture, 0);
|
||||
|
||||
ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// Non-instancing
|
||||
// ----------------------
|
||||
glGenBuffers(1, &m_distort_ogl.vertex_buffer);
|
||||
glGenVertexArrays(1, &m_distort_ogl.vao);
|
||||
glBindVertexArray(m_distort_ogl.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_ogl.vertex_buffer);
|
||||
// note: each sprite shares a single vertex per slice, account for that here
|
||||
int distort_vert_buffer_len =
|
||||
SPRITE_RENDERER_MAX_DISTORT_SPRITES *
|
||||
((5 - 1) * 11 + 1); // max * ((verts_per_slice - 1) * max_slices + 1)
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_vert_buffer_len * sizeof(SpriteDistortVertex), nullptr,
|
||||
GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, xyz) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
2, // 2 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, st) // offset in array
|
||||
);
|
||||
|
||||
// note: add one extra element per sprite that marks the end of a triangle strip
|
||||
int distort_idx_buffer_len = SPRITE_RENDERER_MAX_DISTORT_SPRITES *
|
||||
((5 * 11) + 1); // max * ((verts_per_slice * max_slices) + 1)
|
||||
glGenBuffers(1, &m_distort_ogl.index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_distort_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, distort_idx_buffer_len * sizeof(u32), nullptr,
|
||||
GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_sprite_distorter_vertices.resize(distort_vert_buffer_len);
|
||||
m_sprite_distorter_indices.resize(distort_idx_buffer_len);
|
||||
m_sprite_distorter_frame_data.resize(SPRITE_RENDERER_MAX_DISTORT_SPRITES);
|
||||
|
||||
// Instancing
|
||||
// ----------------------
|
||||
glGenVertexArrays(1, &m_distort_instanced_ogl.vao);
|
||||
glBindVertexArray(m_distort_instanced_ogl.vao);
|
||||
|
||||
int distort_max_sprite_slices = 0;
|
||||
for (int i = 3; i < 12; i++) {
|
||||
// For each 'resolution', there can be that many slices
|
||||
distort_max_sprite_slices += i;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &m_distort_instanced_ogl.vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.vertex_buffer);
|
||||
|
||||
int distort_instanced_vert_buffer_len = distort_max_sprite_slices * 5; // 5 vertices per slice
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_instanced_vert_buffer_len * sizeof(SpriteDistortVertex),
|
||||
nullptr, GL_STREAM_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, xyz) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
2, // 2 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, st) // offset in array
|
||||
);
|
||||
|
||||
glGenBuffers(1, &m_distort_instanced_ogl.instance_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.instance_buffer);
|
||||
|
||||
int distort_instance_buffer_len = SPRITE_RENDERER_MAX_DISTORT_SPRITES;
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_instance_buffer_len * sizeof(SpriteDistortInstanceData),
|
||||
nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, // location 2 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored,
|
||||
sizeof(SpriteDistortInstanceData), //
|
||||
(void*)offsetof(SpriteDistortInstanceData, x_y_z_s) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, // location 3 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored,
|
||||
sizeof(SpriteDistortInstanceData), //
|
||||
(void*)offsetof(SpriteDistortInstanceData, sx_sy_sz_t) // offset in array
|
||||
);
|
||||
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_sprite_distorter_vertices_instanced.resize(distort_instanced_vert_buffer_len);
|
||||
|
||||
for (int i = 3; i < 12; i++) {
|
||||
auto vec = std::vector<SpriteDistortInstanceData>();
|
||||
vec.resize(distort_instance_buffer_len);
|
||||
|
||||
m_sprite_distorter_instances_by_res[i] = vec;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Run the sprite distorter.
|
||||
*/
|
||||
void Sprite3::render_distorter(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// Skip to distorter DMA
|
||||
m_direct.reset_state();
|
||||
while (dma.current_tag().qwc != 7) {
|
||||
auto direct_data = dma.read_and_advance();
|
||||
m_direct.render_vif(direct_data.vif0(), direct_data.vif1(), direct_data.data,
|
||||
direct_data.size_bytes, render_state, prof);
|
||||
}
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
|
||||
// Read DMA
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("dma");
|
||||
distort_dma(dma, prof_node);
|
||||
}
|
||||
|
||||
if (!m_enabled || !m_distort_enable) {
|
||||
// Distort disabled, we can stop here since all the DMA has been read
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up vertex data
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("setup");
|
||||
if (m_enable_distort_instancing) {
|
||||
distort_setup_instanced(prof_node);
|
||||
} else {
|
||||
distort_setup(prof_node);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("drawing");
|
||||
if (m_enable_distort_instancing) {
|
||||
distort_draw_instanced(render_state, prof_node);
|
||||
} else {
|
||||
distort_draw(render_state, prof_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reads all sprite distort related DMA packets.
|
||||
*/
|
||||
void Sprite3::distort_dma(DmaFollower& dma, ScopedProfilerNode& /*prof*/) {
|
||||
// First should be the GS setup
|
||||
auto sprite_distorter_direct_setup = dma.read_and_advance();
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode1().immediate == 7);
|
||||
memcpy(&m_sprite_distorter_setup, sprite_distorter_direct_setup.data, 7 * 16);
|
||||
|
||||
auto gif_tag = m_sprite_distorter_setup.gif_tag;
|
||||
ASSERT(gif_tag.nloop() == 1);
|
||||
ASSERT(gif_tag.eop() == 1);
|
||||
ASSERT(gif_tag.nreg() == 6);
|
||||
ASSERT(gif_tag.reg(0) == GifTag::RegisterDescriptor::AD);
|
||||
|
||||
auto zbuf1 = m_sprite_distorter_setup.zbuf;
|
||||
ASSERT(zbuf1.zbp() == 0x1c0);
|
||||
ASSERT(zbuf1.zmsk() == true);
|
||||
ASSERT(zbuf1.psm() == TextureFormat::PSMZ24);
|
||||
|
||||
auto tex0 = m_sprite_distorter_setup.tex0;
|
||||
ASSERT(tex0.tbw() == 8);
|
||||
ASSERT(tex0.tw() == 9);
|
||||
ASSERT(tex0.th() == 8);
|
||||
|
||||
auto tex1 = m_sprite_distorter_setup.tex1;
|
||||
ASSERT(tex1.mmag() == true);
|
||||
ASSERT(tex1.mmin() == 1);
|
||||
|
||||
auto alpha = m_sprite_distorter_setup.alpha;
|
||||
ASSERT(alpha.a_mode() == GsAlpha::BlendMode::SOURCE);
|
||||
ASSERT(alpha.b_mode() == GsAlpha::BlendMode::DEST);
|
||||
ASSERT(alpha.c_mode() == GsAlpha::BlendMode::SOURCE);
|
||||
ASSERT(alpha.d_mode() == GsAlpha::BlendMode::DEST);
|
||||
|
||||
// Next is the aspect used by the sine tables (PC only)
|
||||
//
|
||||
// This was added to let the renderer reliably detect when the sine tables changed,
|
||||
// which is whenever the aspect ratio changed. However, the tables aren't always
|
||||
// updated on the same frame that the aspect changed, so this just lets the game
|
||||
// easily notify the renderer when it finally does get updated.
|
||||
auto sprite_distort_tables_aspect = dma.read_and_advance();
|
||||
ASSERT(sprite_distort_tables_aspect.size_bytes == 16);
|
||||
ASSERT(sprite_distort_tables_aspect.vifcode1().kind == VifCode::Kind::PC_PORT);
|
||||
memcpy(&m_sprite_distorter_sine_tables_aspect, sprite_distort_tables_aspect.data,
|
||||
sizeof(math::Vector4f));
|
||||
|
||||
// Next thing should be the sine tables
|
||||
auto sprite_distorter_tables = dma.read_and_advance();
|
||||
unpack_to_stcycl(&m_sprite_distorter_sine_tables, sprite_distorter_tables,
|
||||
VifCode::Kind::UNPACK_V4_32, 4, 4, 0x8b * 16, 0x160, false, false);
|
||||
|
||||
ASSERT(GsPrim(m_sprite_distorter_sine_tables.gs_gif_tag.prim()).kind() ==
|
||||
GsPrim::Kind::TRI_STRIP);
|
||||
|
||||
// Finally, should be frame data packets (containing sprites)
|
||||
// Up to 170 sprites will be DMA'd at a time followed by a mscalf,
|
||||
// and this process can happen twice up to a maximum of 256 sprites DMA'd
|
||||
// (256 is the size of sprite-aux-list which drives this).
|
||||
int sprite_idx = 0;
|
||||
m_distort_stats.total_sprites = 0;
|
||||
|
||||
while (looks_like_distort_frame_data(dma)) {
|
||||
math::Vector<u32, 4> num_sprites_vec;
|
||||
|
||||
// Read sprite packets
|
||||
do {
|
||||
int qwc = dma.current_tag().qwc;
|
||||
int dest = dma.current_tag_vifcode1().immediate;
|
||||
auto distort_data = dma.read_and_advance();
|
||||
|
||||
if (dest == 511) {
|
||||
// VU address 511 specifies the number of sprites
|
||||
unpack_to_no_stcycl(&num_sprites_vec, distort_data, VifCode::Kind::UNPACK_V4_32, 16, dest,
|
||||
false, false);
|
||||
} else {
|
||||
// VU address >= 512 is the actual vertex data
|
||||
ASSERT(dest >= 512);
|
||||
ASSERT(sprite_idx + (qwc / 3) <= (int)m_sprite_distorter_frame_data.capacity());
|
||||
|
||||
unpack_to_no_stcycl(&m_sprite_distorter_frame_data.at(sprite_idx), distort_data,
|
||||
VifCode::Kind::UNPACK_V4_32, qwc * 16, dest, false, false);
|
||||
|
||||
sprite_idx += qwc / 3;
|
||||
}
|
||||
} while (looks_like_distort_frame_data(dma));
|
||||
|
||||
// Sprite packets should always end with a mscalf flush
|
||||
ASSERT(dma.current_tag().kind == DmaTag::Kind::CNT);
|
||||
ASSERT(dma.current_tag_vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(dma.current_tag_vifcode1().kind == VifCode::Kind::FLUSH);
|
||||
dma.read_and_advance();
|
||||
|
||||
m_distort_stats.total_sprites += num_sprites_vec.x();
|
||||
}
|
||||
|
||||
// Done
|
||||
ASSERT(m_distort_stats.total_sprites <= SPRITE_RENDERER_MAX_DISTORT_SPRITES);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets up OpenGL data for each distort sprite.
|
||||
*/
|
||||
void Sprite3::distort_setup(ScopedProfilerNode& /*prof*/) {
|
||||
m_distort_stats.total_tris = 0;
|
||||
|
||||
m_sprite_distorter_vertices.clear();
|
||||
m_sprite_distorter_indices.clear();
|
||||
|
||||
int sprite_idx = 0;
|
||||
int sprites_left = m_distort_stats.total_sprites;
|
||||
|
||||
// This part is mostly ripped from the VU program
|
||||
while (sprites_left != 0) {
|
||||
// flag seems to represent the 'resolution' of the circle sprite used to create the distortion
|
||||
// effect For example, a flag value of 3 will create a circle using 3 "pie-slice" shapes
|
||||
u32 flag = m_sprite_distorter_frame_data.at(sprite_idx).flag;
|
||||
u32 slices_left = flag;
|
||||
|
||||
// flag has a minimum value of 3 which represents the first ientry
|
||||
// Additionally, the ientry index has 352 added to it (which is the start of the entry array
|
||||
// in VU memory), so we need to subtract that as well
|
||||
int entry_index = m_sprite_distorter_sine_tables.ientry[flag - 3].x() - 352;
|
||||
|
||||
// Here would be adding the giftag, but we don't need that
|
||||
|
||||
// Get the frame data for the next distort sprite
|
||||
SpriteDistortFrameData frame_data = m_sprite_distorter_frame_data.at(sprite_idx);
|
||||
sprite_idx++;
|
||||
|
||||
// Build the OpenGL data for the sprite
|
||||
math::Vector2f vf03 = frame_data.st;
|
||||
math::Vector3f vf14 = frame_data.xyz;
|
||||
|
||||
// Each slice shares a center vertex, we can use this fact and cut out duplicate vertices
|
||||
u32 center_vert_idx = m_sprite_distorter_vertices.size();
|
||||
m_sprite_distorter_vertices.push_back({vf14, vf03});
|
||||
|
||||
do {
|
||||
math::Vector3f vf06 = m_sprite_distorter_sine_tables.entry[entry_index++].xyz();
|
||||
math::Vector2f vf07 = m_sprite_distorter_sine_tables.entry[entry_index++].xy();
|
||||
math::Vector3f vf08 = m_sprite_distorter_sine_tables.entry[entry_index + 0].xyz();
|
||||
math::Vector2f vf09 = m_sprite_distorter_sine_tables.entry[entry_index + 1].xy();
|
||||
|
||||
slices_left--;
|
||||
|
||||
math::Vector2f vf11 = (vf07 * frame_data.rgba.z()) + frame_data.st;
|
||||
math::Vector2f vf13 = (vf09 * frame_data.rgba.z()) + frame_data.st;
|
||||
math::Vector3f vf06_2 = (vf06 * frame_data.rgba.x()) + frame_data.xyz;
|
||||
math::Vector2f vf07_2 = (vf07 * frame_data.rgba.x()) + frame_data.st;
|
||||
math::Vector3f vf08_2 = (vf08 * frame_data.rgba.x()) + frame_data.xyz;
|
||||
math::Vector2f vf09_2 = (vf09 * frame_data.rgba.x()) + frame_data.st;
|
||||
math::Vector3f vf10 = (vf06 * frame_data.rgba.y()) + frame_data.xyz;
|
||||
math::Vector3f vf12 = (vf08 * frame_data.rgba.y()) + frame_data.xyz;
|
||||
math::Vector3f vf06_3 = vf06_2;
|
||||
math::Vector3f vf08_3 = vf08_2;
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf06_3, vf07_2});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf08_3, vf09_2});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf10, vf11});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf12, vf13});
|
||||
|
||||
// Originally, would add the shared center vertex, but in our case we can just add the index
|
||||
m_sprite_distorter_indices.push_back(center_vert_idx);
|
||||
// m_sprite_distorter_vertices.push_back({vf14, vf03});
|
||||
|
||||
m_distort_stats.total_tris += 2;
|
||||
} while (slices_left != 0);
|
||||
|
||||
// Mark the end of the triangle strip
|
||||
m_sprite_distorter_indices.push_back(UINT32_MAX);
|
||||
|
||||
sprites_left--;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets up OpenGL data for rendering distort sprites using instanced rendering.
|
||||
*
|
||||
* A mesh is built once for each possible sprite resolution and is only re-built
|
||||
* when the dimensions of the window are changed. These meshes are built just like
|
||||
* the triangle strips in the VU program, but with the sprite-specific data removed.
|
||||
*
|
||||
* Required sprite-specific frame data is kept as is and is grouped by resolution.
|
||||
*/
|
||||
void Sprite3::distort_setup_instanced(ScopedProfilerNode& /*prof*/) {
|
||||
if (m_distort_instanced_ogl.last_aspect_x != m_sprite_distorter_sine_tables_aspect.x() ||
|
||||
m_distort_instanced_ogl.last_aspect_y != m_sprite_distorter_sine_tables_aspect.y()) {
|
||||
m_distort_instanced_ogl.last_aspect_x = m_sprite_distorter_sine_tables_aspect.x();
|
||||
m_distort_instanced_ogl.last_aspect_y = m_sprite_distorter_sine_tables_aspect.y();
|
||||
// Aspect ratio changed, which means we have a new sine table
|
||||
m_sprite_distorter_vertices_instanced.clear();
|
||||
|
||||
// Build a mesh for every possible distort sprite resolution
|
||||
auto vf03 = math::Vector2f(0, 0);
|
||||
auto vf14 = math::Vector3f(0, 0, 0);
|
||||
|
||||
for (int res = 3; res < 12; res++) {
|
||||
int entry_index = m_sprite_distorter_sine_tables.ientry[res - 3].x() - 352;
|
||||
|
||||
for (int i = 0; i < res; i++) {
|
||||
math::Vector3f vf06 = m_sprite_distorter_sine_tables.entry[entry_index++].xyz();
|
||||
math::Vector2f vf07 = m_sprite_distorter_sine_tables.entry[entry_index++].xy();
|
||||
math::Vector3f vf08 = m_sprite_distorter_sine_tables.entry[entry_index + 0].xyz();
|
||||
math::Vector2f vf09 = m_sprite_distorter_sine_tables.entry[entry_index + 1].xy();
|
||||
|
||||
// Normally, there would be a bunch of transformations here against the sprite data.
|
||||
// Instead, we'll let the shader do it and just store the sine table specific parts here.
|
||||
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf06, vf07});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf08, vf09});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf06, vf07});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf08, vf09});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf14, vf03});
|
||||
}
|
||||
}
|
||||
|
||||
m_distort_instanced_ogl.vertex_data_changed = true;
|
||||
}
|
||||
|
||||
// Set up instance data for each sprite
|
||||
m_distort_stats.total_tris = 0;
|
||||
|
||||
for (auto& [res, vec] : m_sprite_distorter_instances_by_res) {
|
||||
vec.clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_distort_stats.total_sprites; i++) {
|
||||
SpriteDistortFrameData frame_data = m_sprite_distorter_frame_data.at(i);
|
||||
|
||||
// Shader just needs the position, tex coords, and scale
|
||||
auto x_y_z_s = math::Vector4f(frame_data.xyz.x(), frame_data.xyz.y(), frame_data.xyz.z(),
|
||||
frame_data.st.x());
|
||||
auto sx_sy_sz_t = math::Vector4f(frame_data.rgba.x(), frame_data.rgba.y(), frame_data.rgba.z(),
|
||||
frame_data.st.y());
|
||||
|
||||
int res = frame_data.flag;
|
||||
|
||||
m_sprite_distorter_instances_by_res[res].push_back({x_y_z_s, sx_sy_sz_t});
|
||||
|
||||
m_distort_stats.total_tris += res * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draws each distort sprite.
|
||||
*/
|
||||
void Sprite3::distort_draw(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// First, make sure the distort framebuffer is the correct size
|
||||
distort_setup_framebuffer_dims(render_state);
|
||||
|
||||
if (m_distort_stats.total_tris == 0) {
|
||||
// No distort sprites to draw, we can end early
|
||||
return;
|
||||
}
|
||||
|
||||
// Do common distort drawing logic
|
||||
distort_draw_common(render_state, prof);
|
||||
|
||||
// Set up shader
|
||||
auto shader = &render_state->shaders[ShaderId::SPRITE_DISTORT];
|
||||
shader->activate();
|
||||
|
||||
Vector4f colorf = Vector4f(m_sprite_distorter_sine_tables.color.x() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.y() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.z() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.w() / 255.0f);
|
||||
glUniform4fv(glGetUniformLocation(shader->id(), "u_color"), 1, colorf.data());
|
||||
|
||||
// Bind vertex array
|
||||
glBindVertexArray(m_distort_ogl.vao);
|
||||
|
||||
// Enable prim restart, we need this to break up the triangle strips
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
|
||||
// Upload vertex data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_sprite_distorter_vertices.size() * sizeof(SpriteDistortVertex),
|
||||
m_sprite_distorter_vertices.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload element data
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_distort_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_sprite_distorter_indices.size() * sizeof(u32),
|
||||
m_sprite_distorter_indices.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Draw
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_distort_stats.total_tris);
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, m_sprite_distorter_indices.size(), GL_UNSIGNED_INT, (void*)0);
|
||||
|
||||
// Done
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draws each distort sprite using instanced rendering.
|
||||
*/
|
||||
void Sprite3::distort_draw_instanced(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// First, make sure the distort framebuffer is the correct size
|
||||
distort_setup_framebuffer_dims(render_state);
|
||||
|
||||
if (m_distort_stats.total_tris == 0) {
|
||||
// No distort sprites to draw, we can end early
|
||||
return;
|
||||
}
|
||||
|
||||
// Do common distort drawing logic
|
||||
distort_draw_common(render_state, prof);
|
||||
|
||||
// Set up shader
|
||||
auto shader = &render_state->shaders[ShaderId::SPRITE_DISTORT_INSTANCED];
|
||||
shader->activate();
|
||||
|
||||
Vector4f colorf = Vector4f(m_sprite_distorter_sine_tables.color.x() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.y() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.z() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.w() / 255.0f);
|
||||
glUniform4fv(glGetUniformLocation(shader->id(), "u_color"), 1, colorf.data());
|
||||
|
||||
// Bind vertex array
|
||||
glBindVertexArray(m_distort_instanced_ogl.vao);
|
||||
|
||||
// Upload vertex data (if it changed)
|
||||
if (m_distort_instanced_ogl.vertex_data_changed) {
|
||||
m_distort_instanced_ogl.vertex_data_changed = false;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
m_sprite_distorter_vertices_instanced.size() * sizeof(SpriteDistortVertex),
|
||||
m_sprite_distorter_vertices_instanced.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
// Draw each resolution group
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.instance_buffer);
|
||||
prof.add_tri(m_distort_stats.total_tris);
|
||||
|
||||
int vert_offset = 0;
|
||||
for (int res = 3; res < 12; res++) {
|
||||
auto& instances = m_sprite_distorter_instances_by_res[res];
|
||||
int num_verts = res * 5;
|
||||
|
||||
if (instances.size() > 0) {
|
||||
// Upload instance data
|
||||
glBufferData(GL_ARRAY_BUFFER, instances.size() * sizeof(SpriteDistortInstanceData),
|
||||
instances.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Draw
|
||||
prof.add_draw_call();
|
||||
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, vert_offset, num_verts, instances.size());
|
||||
}
|
||||
|
||||
vert_offset += num_verts;
|
||||
}
|
||||
|
||||
// Done
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Sprite3::distort_draw_common(SharedRenderState* render_state, ScopedProfilerNode& /*prof*/) {
|
||||
// The distort effect needs to read the current framebuffer, so copy what's been rendered so far
|
||||
// to a texture that we can then pass to the shader
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_distort_ogl.fbo);
|
||||
|
||||
glBlitFramebuffer(render_state->render_fb_x, // srcX0
|
||||
render_state->render_fb_y, // srcY0
|
||||
render_state->render_fb_x + render_state->render_fb_w, // srcX1
|
||||
render_state->render_fb_y + render_state->render_fb_h, // srcY1
|
||||
0, // dstX0
|
||||
0, // dstY0
|
||||
m_distort_ogl.fbo_width, // dstX1
|
||||
m_distort_ogl.fbo_height, // dstY1
|
||||
GL_COLOR_BUFFER_BIT, // mask
|
||||
GL_NEAREST // filter
|
||||
);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
|
||||
// Set up OpenGL state
|
||||
m_current_mode.set_depth_write_enable(!m_sprite_distorter_setup.zbuf.zmsk()); // zbuf
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture); // tex0
|
||||
m_current_mode.set_filt_enable(m_sprite_distorter_setup.tex1.mmag()); // tex1
|
||||
update_mode_from_alpha1(m_sprite_distorter_setup.alpha.data, m_current_mode); // alpha1
|
||||
// note: clamp and miptbp are skipped since that is set up ahead of time with the distort
|
||||
// framebuffer texture
|
||||
|
||||
setup_opengl_from_draw_mode(m_current_mode, GL_TEXTURE0, false);
|
||||
}
|
||||
|
||||
void Sprite3::distort_setup_framebuffer_dims(SharedRenderState* render_state) {
|
||||
// Distort framebuffer must be the same dimensions as the default window framebuffer
|
||||
if (m_distort_ogl.fbo_width != render_state->render_fb_w ||
|
||||
m_distort_ogl.fbo_height != render_state->render_fb_h) {
|
||||
m_distort_ogl.fbo_width = render_state->render_fb_w;
|
||||
m_distort_ogl.fbo_height = render_state->render_fb_h;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_distort_ogl.fbo_width, m_distort_ogl.fbo_height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Handle DMA data that does the per-frame setup.
|
||||
* This should get the dma chain immediately after the call to sprite-draw-distorters.
|
||||
@ -1026,23 +399,29 @@ void Sprite3::render_jak2(DmaFollower& dma,
|
||||
auto child = prof.make_scoped_child("2d-group1");
|
||||
render_2d_group1(dma, render_state, child);
|
||||
flush_sprites(render_state, prof, true);
|
||||
auto nop_flushe = dma.read_and_advance();
|
||||
ASSERT(nop_flushe.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(nop_flushe.vifcode1().kind == VifCode::Kind::FLUSHE);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
// TODO finish this up.
|
||||
{
|
||||
auto p = prof.make_scoped_child("glow");
|
||||
glow_dma_and_draw(dma, render_state, p);
|
||||
}
|
||||
|
||||
// fmt::print("next bucket is 0x{}\n", render_state->next_bucket);
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
// auto tag = dma.current_tag();
|
||||
// fmt::print("@ 0x{:x} tag: {}", dma.current_tag_offset(), tag.print());
|
||||
// auto tag = dma.current_tag();
|
||||
auto data = dma.read_and_advance();
|
||||
VifCode code(data.vif0());
|
||||
(void)data;
|
||||
// VifCode code(data.vif0());
|
||||
// fmt::print("@ 0x{:x} tag: {}", dma.current_tag_offset(), tag.print());
|
||||
// fmt::print(" vif0: {}\n", code.print());
|
||||
if (code.kind == VifCode::Kind::NOP) {
|
||||
// fmt::print(" vif1: {}\n", VifCode(data.vif1()).print());
|
||||
}
|
||||
// fmt::print(" vif1: {}\n", VifCode(data.vif1()).print());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1128,6 +507,8 @@ void Sprite3::draw_debug_window() {
|
||||
ImGui::Checkbox("3d", &m_3d_enable);
|
||||
ImGui::Checkbox("Distort", &m_distort_enable);
|
||||
ImGui::Checkbox("Distort instancing", &m_enable_distort_instancing);
|
||||
ImGui::Separator();
|
||||
m_glow_renderer.draw_debug_window();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
@ -9,7 +9,8 @@
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/background/background_common.h"
|
||||
#include "game/graphics/opengl_renderer/sprite_common.h"
|
||||
#include "game/graphics/opengl_renderer/sprite/GlowRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/sprite/sprite_common.h"
|
||||
|
||||
class Sprite3 : public BucketRenderer {
|
||||
public:
|
||||
@ -61,6 +62,11 @@ class Sprite3 : public BucketRenderer {
|
||||
|
||||
void flush_sprites(SharedRenderState* render_state, ScopedProfilerNode& prof, bool double_draw);
|
||||
|
||||
GlowRenderer m_glow_renderer;
|
||||
void glow_dma_and_draw(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
struct SpriteDistorterSetup {
|
||||
GifTag gif_tag;
|
||||
GsZbuf zbuf;
|
630
game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp
Normal file
630
game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp
Normal file
@ -0,0 +1,630 @@
|
||||
#include "Sprite3.h"
|
||||
#include "game/graphics/opengl_renderer/dma_helpers.h"
|
||||
|
||||
namespace {
|
||||
/*!
|
||||
* Does the next DMA transfer look like the frame data for sprite distort?
|
||||
*/
|
||||
bool looks_like_distort_frame_data(const DmaFollower& dma) {
|
||||
return dma.current_tag().kind == DmaTag::Kind::CNT &&
|
||||
dma.current_tag_vifcode0().kind == VifCode::Kind::NOP &&
|
||||
dma.current_tag_vifcode1().kind == VifCode::Kind::UNPACK_V4_32;
|
||||
}
|
||||
|
||||
constexpr int SPRITE_RENDERER_MAX_DISTORT_SPRITES =
|
||||
256 * 10; // size of sprite-aux-list in GOAL code * SPRITE_MAX_AMOUNT_MULT
|
||||
} // namespace
|
||||
|
||||
void Sprite3::opengl_setup_distort() {
|
||||
// Create framebuffer to snapshot current render to a texture that can be bound for the distort
|
||||
// shader This will represent tex0 from the original GS data
|
||||
glGenFramebuffers(1, &m_distort_ogl.fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_distort_ogl.fbo);
|
||||
|
||||
glGenTextures(1, &m_distort_ogl.fbo_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_distort_ogl.fbo_width, m_distort_ogl.fbo_height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
// Texture clamping here matches the GS init data for distort
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
m_distort_ogl.fbo_texture, 0);
|
||||
|
||||
ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// Non-instancing
|
||||
// ----------------------
|
||||
glGenBuffers(1, &m_distort_ogl.vertex_buffer);
|
||||
glGenVertexArrays(1, &m_distort_ogl.vao);
|
||||
glBindVertexArray(m_distort_ogl.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_ogl.vertex_buffer);
|
||||
// note: each sprite shares a single vertex per slice, account for that here
|
||||
int distort_vert_buffer_len =
|
||||
SPRITE_RENDERER_MAX_DISTORT_SPRITES *
|
||||
((5 - 1) * 11 + 1); // max * ((verts_per_slice - 1) * max_slices + 1)
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_vert_buffer_len * sizeof(SpriteDistortVertex), nullptr,
|
||||
GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, xyz) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
2, // 2 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, st) // offset in array
|
||||
);
|
||||
|
||||
// note: add one extra element per sprite that marks the end of a triangle strip
|
||||
int distort_idx_buffer_len = SPRITE_RENDERER_MAX_DISTORT_SPRITES *
|
||||
((5 * 11) + 1); // max * ((verts_per_slice * max_slices) + 1)
|
||||
glGenBuffers(1, &m_distort_ogl.index_buffer);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_distort_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, distort_idx_buffer_len * sizeof(u32), nullptr,
|
||||
GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_sprite_distorter_vertices.resize(distort_vert_buffer_len);
|
||||
m_sprite_distorter_indices.resize(distort_idx_buffer_len);
|
||||
m_sprite_distorter_frame_data.resize(SPRITE_RENDERER_MAX_DISTORT_SPRITES);
|
||||
|
||||
// Instancing
|
||||
// ----------------------
|
||||
glGenVertexArrays(1, &m_distort_instanced_ogl.vao);
|
||||
glBindVertexArray(m_distort_instanced_ogl.vao);
|
||||
|
||||
int distort_max_sprite_slices = 0;
|
||||
for (int i = 3; i < 12; i++) {
|
||||
// For each 'resolution', there can be that many slices
|
||||
distort_max_sprite_slices += i;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &m_distort_instanced_ogl.vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.vertex_buffer);
|
||||
|
||||
int distort_instanced_vert_buffer_len = distort_max_sprite_slices * 5; // 5 vertices per slice
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_instanced_vert_buffer_len * sizeof(SpriteDistortVertex),
|
||||
nullptr, GL_STREAM_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
3, // 3 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, xyz) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, // location 1 in the shader
|
||||
2, // 2 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // don't normalize, ignored
|
||||
sizeof(SpriteDistortVertex), //
|
||||
(void*)offsetof(SpriteDistortVertex, st) // offset in array
|
||||
);
|
||||
|
||||
glGenBuffers(1, &m_distort_instanced_ogl.instance_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.instance_buffer);
|
||||
|
||||
int distort_instance_buffer_len = SPRITE_RENDERER_MAX_DISTORT_SPRITES;
|
||||
glBufferData(GL_ARRAY_BUFFER, distort_instance_buffer_len * sizeof(SpriteDistortInstanceData),
|
||||
nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, // location 2 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored,
|
||||
sizeof(SpriteDistortInstanceData), //
|
||||
(void*)offsetof(SpriteDistortInstanceData, x_y_z_s) // offset in array
|
||||
);
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, // location 3 in the shader
|
||||
4, // 4 floats per vert
|
||||
GL_FLOAT, // floats
|
||||
GL_FALSE, // normalized, ignored,
|
||||
sizeof(SpriteDistortInstanceData), //
|
||||
(void*)offsetof(SpriteDistortInstanceData, sx_sy_sz_t) // offset in array
|
||||
);
|
||||
|
||||
glVertexAttribDivisor(2, 1);
|
||||
glVertexAttribDivisor(3, 1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
m_sprite_distorter_vertices_instanced.resize(distort_instanced_vert_buffer_len);
|
||||
|
||||
for (int i = 3; i < 12; i++) {
|
||||
auto vec = std::vector<SpriteDistortInstanceData>();
|
||||
vec.resize(distort_instance_buffer_len);
|
||||
|
||||
m_sprite_distorter_instances_by_res[i] = vec;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Run the sprite distorter.
|
||||
*/
|
||||
void Sprite3::render_distorter(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// Skip to distorter DMA
|
||||
m_direct.reset_state();
|
||||
while (dma.current_tag().qwc != 7) {
|
||||
auto direct_data = dma.read_and_advance();
|
||||
m_direct.render_vif(direct_data.vif0(), direct_data.vif1(), direct_data.data,
|
||||
direct_data.size_bytes, render_state, prof);
|
||||
}
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
|
||||
// Read DMA
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("dma");
|
||||
distort_dma(dma, prof_node);
|
||||
}
|
||||
|
||||
if (!m_enabled || !m_distort_enable) {
|
||||
// Distort disabled, we can stop here since all the DMA has been read
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up vertex data
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("setup");
|
||||
if (m_enable_distort_instancing) {
|
||||
distort_setup_instanced(prof_node);
|
||||
} else {
|
||||
distort_setup(prof_node);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw
|
||||
{
|
||||
auto prof_node = prof.make_scoped_child("drawing");
|
||||
if (m_enable_distort_instancing) {
|
||||
distort_draw_instanced(render_state, prof_node);
|
||||
} else {
|
||||
distort_draw(render_state, prof_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reads all sprite distort related DMA packets.
|
||||
*/
|
||||
void Sprite3::distort_dma(DmaFollower& dma, ScopedProfilerNode& /*prof*/) {
|
||||
// First should be the GS setup
|
||||
auto sprite_distorter_direct_setup = dma.read_and_advance();
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
ASSERT(sprite_distorter_direct_setup.vifcode1().immediate == 7);
|
||||
memcpy(&m_sprite_distorter_setup, sprite_distorter_direct_setup.data, 7 * 16);
|
||||
|
||||
auto gif_tag = m_sprite_distorter_setup.gif_tag;
|
||||
ASSERT(gif_tag.nloop() == 1);
|
||||
ASSERT(gif_tag.eop() == 1);
|
||||
ASSERT(gif_tag.nreg() == 6);
|
||||
ASSERT(gif_tag.reg(0) == GifTag::RegisterDescriptor::AD);
|
||||
|
||||
auto zbuf1 = m_sprite_distorter_setup.zbuf;
|
||||
ASSERT(zbuf1.zbp() == 0x1c0);
|
||||
ASSERT(zbuf1.zmsk() == true);
|
||||
ASSERT(zbuf1.psm() == TextureFormat::PSMZ24);
|
||||
|
||||
auto tex0 = m_sprite_distorter_setup.tex0;
|
||||
ASSERT(tex0.tbw() == 8);
|
||||
ASSERT(tex0.tw() == 9);
|
||||
ASSERT(tex0.th() == 8);
|
||||
|
||||
auto tex1 = m_sprite_distorter_setup.tex1;
|
||||
ASSERT(tex1.mmag() == true);
|
||||
ASSERT(tex1.mmin() == 1);
|
||||
|
||||
auto alpha = m_sprite_distorter_setup.alpha;
|
||||
ASSERT(alpha.a_mode() == GsAlpha::BlendMode::SOURCE);
|
||||
ASSERT(alpha.b_mode() == GsAlpha::BlendMode::DEST);
|
||||
ASSERT(alpha.c_mode() == GsAlpha::BlendMode::SOURCE);
|
||||
ASSERT(alpha.d_mode() == GsAlpha::BlendMode::DEST);
|
||||
|
||||
// Next is the aspect used by the sine tables (PC only)
|
||||
//
|
||||
// This was added to let the renderer reliably detect when the sine tables changed,
|
||||
// which is whenever the aspect ratio changed. However, the tables aren't always
|
||||
// updated on the same frame that the aspect changed, so this just lets the game
|
||||
// easily notify the renderer when it finally does get updated.
|
||||
auto sprite_distort_tables_aspect = dma.read_and_advance();
|
||||
ASSERT(sprite_distort_tables_aspect.size_bytes == 16);
|
||||
ASSERT(sprite_distort_tables_aspect.vifcode1().kind == VifCode::Kind::PC_PORT);
|
||||
memcpy(&m_sprite_distorter_sine_tables_aspect, sprite_distort_tables_aspect.data,
|
||||
sizeof(math::Vector4f));
|
||||
|
||||
// Next thing should be the sine tables
|
||||
auto sprite_distorter_tables = dma.read_and_advance();
|
||||
unpack_to_stcycl(&m_sprite_distorter_sine_tables, sprite_distorter_tables,
|
||||
VifCode::Kind::UNPACK_V4_32, 4, 4, 0x8b * 16, 0x160, false, false);
|
||||
|
||||
ASSERT(GsPrim(m_sprite_distorter_sine_tables.gs_gif_tag.prim()).kind() ==
|
||||
GsPrim::Kind::TRI_STRIP);
|
||||
|
||||
// Finally, should be frame data packets (containing sprites)
|
||||
// Up to 170 sprites will be DMA'd at a time followed by a mscalf,
|
||||
// and this process can happen twice up to a maximum of 256 sprites DMA'd
|
||||
// (256 is the size of sprite-aux-list which drives this).
|
||||
int sprite_idx = 0;
|
||||
m_distort_stats.total_sprites = 0;
|
||||
|
||||
while (looks_like_distort_frame_data(dma)) {
|
||||
math::Vector<u32, 4> num_sprites_vec;
|
||||
|
||||
// Read sprite packets
|
||||
do {
|
||||
int qwc = dma.current_tag().qwc;
|
||||
int dest = dma.current_tag_vifcode1().immediate;
|
||||
auto distort_data = dma.read_and_advance();
|
||||
|
||||
if (dest == 511) {
|
||||
// VU address 511 specifies the number of sprites
|
||||
unpack_to_no_stcycl(&num_sprites_vec, distort_data, VifCode::Kind::UNPACK_V4_32, 16, dest,
|
||||
false, false);
|
||||
} else {
|
||||
// VU address >= 512 is the actual vertex data
|
||||
ASSERT(dest >= 512);
|
||||
ASSERT(sprite_idx + (qwc / 3) <= (int)m_sprite_distorter_frame_data.capacity());
|
||||
|
||||
unpack_to_no_stcycl(&m_sprite_distorter_frame_data.at(sprite_idx), distort_data,
|
||||
VifCode::Kind::UNPACK_V4_32, qwc * 16, dest, false, false);
|
||||
|
||||
sprite_idx += qwc / 3;
|
||||
}
|
||||
} while (looks_like_distort_frame_data(dma));
|
||||
|
||||
// Sprite packets should always end with a mscalf flush
|
||||
ASSERT(dma.current_tag().kind == DmaTag::Kind::CNT);
|
||||
ASSERT(dma.current_tag_vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(dma.current_tag_vifcode1().kind == VifCode::Kind::FLUSH);
|
||||
dma.read_and_advance();
|
||||
|
||||
m_distort_stats.total_sprites += num_sprites_vec.x();
|
||||
}
|
||||
|
||||
// Done
|
||||
ASSERT(m_distort_stats.total_sprites <= SPRITE_RENDERER_MAX_DISTORT_SPRITES);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets up OpenGL data for each distort sprite.
|
||||
*/
|
||||
void Sprite3::distort_setup(ScopedProfilerNode& /*prof*/) {
|
||||
m_distort_stats.total_tris = 0;
|
||||
|
||||
m_sprite_distorter_vertices.clear();
|
||||
m_sprite_distorter_indices.clear();
|
||||
|
||||
int sprite_idx = 0;
|
||||
int sprites_left = m_distort_stats.total_sprites;
|
||||
|
||||
// This part is mostly ripped from the VU program
|
||||
while (sprites_left != 0) {
|
||||
// flag seems to represent the 'resolution' of the circle sprite used to create the distortion
|
||||
// effect For example, a flag value of 3 will create a circle using 3 "pie-slice" shapes
|
||||
u32 flag = m_sprite_distorter_frame_data.at(sprite_idx).flag;
|
||||
u32 slices_left = flag;
|
||||
|
||||
// flag has a minimum value of 3 which represents the first ientry
|
||||
// Additionally, the ientry index has 352 added to it (which is the start of the entry array
|
||||
// in VU memory), so we need to subtract that as well
|
||||
int entry_index = m_sprite_distorter_sine_tables.ientry[flag - 3].x() - 352;
|
||||
|
||||
// Here would be adding the giftag, but we don't need that
|
||||
|
||||
// Get the frame data for the next distort sprite
|
||||
SpriteDistortFrameData frame_data = m_sprite_distorter_frame_data.at(sprite_idx);
|
||||
sprite_idx++;
|
||||
|
||||
// Build the OpenGL data for the sprite
|
||||
math::Vector2f vf03 = frame_data.st;
|
||||
math::Vector3f vf14 = frame_data.xyz;
|
||||
|
||||
// Each slice shares a center vertex, we can use this fact and cut out duplicate vertices
|
||||
u32 center_vert_idx = m_sprite_distorter_vertices.size();
|
||||
m_sprite_distorter_vertices.push_back({vf14, vf03});
|
||||
|
||||
do {
|
||||
math::Vector3f vf06 = m_sprite_distorter_sine_tables.entry[entry_index++].xyz();
|
||||
math::Vector2f vf07 = m_sprite_distorter_sine_tables.entry[entry_index++].xy();
|
||||
math::Vector3f vf08 = m_sprite_distorter_sine_tables.entry[entry_index + 0].xyz();
|
||||
math::Vector2f vf09 = m_sprite_distorter_sine_tables.entry[entry_index + 1].xy();
|
||||
|
||||
slices_left--;
|
||||
|
||||
math::Vector2f vf11 = (vf07 * frame_data.rgba.z()) + frame_data.st;
|
||||
math::Vector2f vf13 = (vf09 * frame_data.rgba.z()) + frame_data.st;
|
||||
math::Vector3f vf06_2 = (vf06 * frame_data.rgba.x()) + frame_data.xyz;
|
||||
math::Vector2f vf07_2 = (vf07 * frame_data.rgba.x()) + frame_data.st;
|
||||
math::Vector3f vf08_2 = (vf08 * frame_data.rgba.x()) + frame_data.xyz;
|
||||
math::Vector2f vf09_2 = (vf09 * frame_data.rgba.x()) + frame_data.st;
|
||||
math::Vector3f vf10 = (vf06 * frame_data.rgba.y()) + frame_data.xyz;
|
||||
math::Vector3f vf12 = (vf08 * frame_data.rgba.y()) + frame_data.xyz;
|
||||
math::Vector3f vf06_3 = vf06_2;
|
||||
math::Vector3f vf08_3 = vf08_2;
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf06_3, vf07_2});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf08_3, vf09_2});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf10, vf11});
|
||||
|
||||
m_sprite_distorter_indices.push_back(m_sprite_distorter_vertices.size());
|
||||
m_sprite_distorter_vertices.push_back({vf12, vf13});
|
||||
|
||||
// Originally, would add the shared center vertex, but in our case we can just add the index
|
||||
m_sprite_distorter_indices.push_back(center_vert_idx);
|
||||
// m_sprite_distorter_vertices.push_back({vf14, vf03});
|
||||
|
||||
m_distort_stats.total_tris += 2;
|
||||
} while (slices_left != 0);
|
||||
|
||||
// Mark the end of the triangle strip
|
||||
m_sprite_distorter_indices.push_back(UINT32_MAX);
|
||||
|
||||
sprites_left--;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets up OpenGL data for rendering distort sprites using instanced rendering.
|
||||
*
|
||||
* A mesh is built once for each possible sprite resolution and is only re-built
|
||||
* when the dimensions of the window are changed. These meshes are built just like
|
||||
* the triangle strips in the VU program, but with the sprite-specific data removed.
|
||||
*
|
||||
* Required sprite-specific frame data is kept as is and is grouped by resolution.
|
||||
*/
|
||||
void Sprite3::distort_setup_instanced(ScopedProfilerNode& /*prof*/) {
|
||||
if (m_distort_instanced_ogl.last_aspect_x != m_sprite_distorter_sine_tables_aspect.x() ||
|
||||
m_distort_instanced_ogl.last_aspect_y != m_sprite_distorter_sine_tables_aspect.y()) {
|
||||
m_distort_instanced_ogl.last_aspect_x = m_sprite_distorter_sine_tables_aspect.x();
|
||||
m_distort_instanced_ogl.last_aspect_y = m_sprite_distorter_sine_tables_aspect.y();
|
||||
// Aspect ratio changed, which means we have a new sine table
|
||||
m_sprite_distorter_vertices_instanced.clear();
|
||||
|
||||
// Build a mesh for every possible distort sprite resolution
|
||||
auto vf03 = math::Vector2f(0, 0);
|
||||
auto vf14 = math::Vector3f(0, 0, 0);
|
||||
|
||||
for (int res = 3; res < 12; res++) {
|
||||
int entry_index = m_sprite_distorter_sine_tables.ientry[res - 3].x() - 352;
|
||||
|
||||
for (int i = 0; i < res; i++) {
|
||||
math::Vector3f vf06 = m_sprite_distorter_sine_tables.entry[entry_index++].xyz();
|
||||
math::Vector2f vf07 = m_sprite_distorter_sine_tables.entry[entry_index++].xy();
|
||||
math::Vector3f vf08 = m_sprite_distorter_sine_tables.entry[entry_index + 0].xyz();
|
||||
math::Vector2f vf09 = m_sprite_distorter_sine_tables.entry[entry_index + 1].xy();
|
||||
|
||||
// Normally, there would be a bunch of transformations here against the sprite data.
|
||||
// Instead, we'll let the shader do it and just store the sine table specific parts here.
|
||||
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf06, vf07});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf08, vf09});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf06, vf07});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf08, vf09});
|
||||
m_sprite_distorter_vertices_instanced.push_back({vf14, vf03});
|
||||
}
|
||||
}
|
||||
|
||||
m_distort_instanced_ogl.vertex_data_changed = true;
|
||||
}
|
||||
|
||||
// Set up instance data for each sprite
|
||||
m_distort_stats.total_tris = 0;
|
||||
|
||||
for (auto& [res, vec] : m_sprite_distorter_instances_by_res) {
|
||||
vec.clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_distort_stats.total_sprites; i++) {
|
||||
SpriteDistortFrameData frame_data = m_sprite_distorter_frame_data.at(i);
|
||||
|
||||
// Shader just needs the position, tex coords, and scale
|
||||
auto x_y_z_s = math::Vector4f(frame_data.xyz.x(), frame_data.xyz.y(), frame_data.xyz.z(),
|
||||
frame_data.st.x());
|
||||
auto sx_sy_sz_t = math::Vector4f(frame_data.rgba.x(), frame_data.rgba.y(), frame_data.rgba.z(),
|
||||
frame_data.st.y());
|
||||
|
||||
int res = frame_data.flag;
|
||||
|
||||
m_sprite_distorter_instances_by_res[res].push_back({x_y_z_s, sx_sy_sz_t});
|
||||
|
||||
m_distort_stats.total_tris += res * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draws each distort sprite.
|
||||
*/
|
||||
void Sprite3::distort_draw(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// First, make sure the distort framebuffer is the correct size
|
||||
distort_setup_framebuffer_dims(render_state);
|
||||
|
||||
if (m_distort_stats.total_tris == 0) {
|
||||
// No distort sprites to draw, we can end early
|
||||
return;
|
||||
}
|
||||
|
||||
// Do common distort drawing logic
|
||||
distort_draw_common(render_state, prof);
|
||||
|
||||
// Set up shader
|
||||
auto shader = &render_state->shaders[ShaderId::SPRITE_DISTORT];
|
||||
shader->activate();
|
||||
|
||||
Vector4f colorf = Vector4f(m_sprite_distorter_sine_tables.color.x() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.y() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.z() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.w() / 255.0f);
|
||||
glUniform4fv(glGetUniformLocation(shader->id(), "u_color"), 1, colorf.data());
|
||||
|
||||
// Bind vertex array
|
||||
glBindVertexArray(m_distort_ogl.vao);
|
||||
|
||||
// Enable prim restart, we need this to break up the triangle strips
|
||||
glEnable(GL_PRIMITIVE_RESTART);
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
|
||||
// Upload vertex data
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_sprite_distorter_vertices.size() * sizeof(SpriteDistortVertex),
|
||||
m_sprite_distorter_vertices.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Upload element data
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_distort_ogl.index_buffer);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_sprite_distorter_indices.size() * sizeof(u32),
|
||||
m_sprite_distorter_indices.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Draw
|
||||
prof.add_draw_call();
|
||||
prof.add_tri(m_distort_stats.total_tris);
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, m_sprite_distorter_indices.size(), GL_UNSIGNED_INT, (void*)0);
|
||||
|
||||
// Done
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Draws each distort sprite using instanced rendering.
|
||||
*/
|
||||
void Sprite3::distort_draw_instanced(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// First, make sure the distort framebuffer is the correct size
|
||||
distort_setup_framebuffer_dims(render_state);
|
||||
|
||||
if (m_distort_stats.total_tris == 0) {
|
||||
// No distort sprites to draw, we can end early
|
||||
return;
|
||||
}
|
||||
|
||||
// Do common distort drawing logic
|
||||
distort_draw_common(render_state, prof);
|
||||
|
||||
// Set up shader
|
||||
auto shader = &render_state->shaders[ShaderId::SPRITE_DISTORT_INSTANCED];
|
||||
shader->activate();
|
||||
|
||||
Vector4f colorf = Vector4f(m_sprite_distorter_sine_tables.color.x() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.y() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.z() / 255.0f,
|
||||
m_sprite_distorter_sine_tables.color.w() / 255.0f);
|
||||
glUniform4fv(glGetUniformLocation(shader->id(), "u_color"), 1, colorf.data());
|
||||
|
||||
// Bind vertex array
|
||||
glBindVertexArray(m_distort_instanced_ogl.vao);
|
||||
|
||||
// Upload vertex data (if it changed)
|
||||
if (m_distort_instanced_ogl.vertex_data_changed) {
|
||||
m_distort_instanced_ogl.vertex_data_changed = false;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
m_sprite_distorter_vertices_instanced.size() * sizeof(SpriteDistortVertex),
|
||||
m_sprite_distorter_vertices_instanced.data(), GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
// Draw each resolution group
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_distort_instanced_ogl.instance_buffer);
|
||||
prof.add_tri(m_distort_stats.total_tris);
|
||||
|
||||
int vert_offset = 0;
|
||||
for (int res = 3; res < 12; res++) {
|
||||
auto& instances = m_sprite_distorter_instances_by_res[res];
|
||||
int num_verts = res * 5;
|
||||
|
||||
if (instances.size() > 0) {
|
||||
// Upload instance data
|
||||
glBufferData(GL_ARRAY_BUFFER, instances.size() * sizeof(SpriteDistortInstanceData),
|
||||
instances.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
// Draw
|
||||
prof.add_draw_call();
|
||||
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, vert_offset, num_verts, instances.size());
|
||||
}
|
||||
|
||||
vert_offset += num_verts;
|
||||
}
|
||||
|
||||
// Done
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Sprite3::distort_draw_common(SharedRenderState* render_state, ScopedProfilerNode& /*prof*/) {
|
||||
// The distort effect needs to read the current framebuffer, so copy what's been rendered so far
|
||||
// to a texture that we can then pass to the shader
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_distort_ogl.fbo);
|
||||
|
||||
glBlitFramebuffer(render_state->render_fb_x, // srcX0
|
||||
render_state->render_fb_y, // srcY0
|
||||
render_state->render_fb_x + render_state->render_fb_w, // srcX1
|
||||
render_state->render_fb_y + render_state->render_fb_h, // srcY1
|
||||
0, // dstX0
|
||||
0, // dstY0
|
||||
m_distort_ogl.fbo_width, // dstX1
|
||||
m_distort_ogl.fbo_height, // dstY1
|
||||
GL_COLOR_BUFFER_BIT, // mask
|
||||
GL_NEAREST // filter
|
||||
);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb);
|
||||
|
||||
// Set up OpenGL state
|
||||
m_current_mode.set_depth_write_enable(!m_sprite_distorter_setup.zbuf.zmsk()); // zbuf
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture); // tex0
|
||||
m_current_mode.set_filt_enable(m_sprite_distorter_setup.tex1.mmag()); // tex1
|
||||
update_mode_from_alpha1(m_sprite_distorter_setup.alpha.data, m_current_mode); // alpha1
|
||||
// note: clamp and miptbp are skipped since that is set up ahead of time with the distort
|
||||
// framebuffer texture
|
||||
|
||||
setup_opengl_from_draw_mode(m_current_mode, GL_TEXTURE0, false);
|
||||
}
|
||||
|
||||
void Sprite3::distort_setup_framebuffer_dims(SharedRenderState* render_state) {
|
||||
// Distort framebuffer must be the same dimensions as the default window framebuffer
|
||||
if (m_distort_ogl.fbo_width != render_state->render_fb_w ||
|
||||
m_distort_ogl.fbo_height != render_state->render_fb_h) {
|
||||
m_distort_ogl.fbo_width = render_state->render_fb_w;
|
||||
m_distort_ogl.fbo_height = render_state->render_fb_h;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_distort_ogl.fbo_texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_distort_ogl.fbo_width, m_distort_ogl.fbo_height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
228
game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp
Normal file
228
game/graphics/opengl_renderer/sprite/Sprite3_Glow.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
#include "game/graphics/opengl_renderer/sprite/Sprite3.h"
|
||||
|
||||
struct SpriteGlowData {
|
||||
float pos[3];
|
||||
float size_x;
|
||||
|
||||
float size_probe;
|
||||
float z_offset;
|
||||
float rot_angle;
|
||||
float size_y;
|
||||
|
||||
float color[4];
|
||||
|
||||
float fade_a;
|
||||
float fade_b;
|
||||
u32 tex_id;
|
||||
u32 dummy;
|
||||
};
|
||||
static_assert(sizeof(SpriteGlowData) == 16 * 4);
|
||||
|
||||
/*!
|
||||
* Transformation math from the sprite-glow vu1 program.
|
||||
* Populates the SpriteGlowOutput struct with the same data that would get filled into the
|
||||
* output template on VU1. Excludes float to int conversions.
|
||||
*
|
||||
* Not a particularly efficient implementation, but I think the total number of glow sprites is
|
||||
* small, so not a big deal.
|
||||
*/
|
||||
bool glow_math(const SpriteGlowConsts* consts,
|
||||
const void* vec_data,
|
||||
const void* adgif_data,
|
||||
SpriteGlowOutput* out) {
|
||||
const auto* in = (const SpriteGlowData*)vec_data;
|
||||
static_assert(sizeof(out->adgif) == 5 * 16);
|
||||
memcpy(&out->adgif, adgif_data, 5 * 16);
|
||||
|
||||
// the transformation here is a bit strange - there's two matrix multiplies.
|
||||
// one for camera, and one for perspective. Usually they do one, or when they really need both
|
||||
// for stuff like emerc, they optimize knowing which entires of perspective are always 0.
|
||||
// But not this time. My guess is that the VU program time is very small compared to actual
|
||||
// drawing, so they don't really care.
|
||||
|
||||
// Transform point to camera frame.
|
||||
Vector4f p0 = consts->camera[3] + consts->camera[0] * in->pos[0] +
|
||||
consts->camera[1] * in->pos[1] + consts->camera[2] * in->pos[2];
|
||||
|
||||
// Compute fade. Interestingly, the fade is computed based on depth, not distance from the camera.
|
||||
// I think this is kind of wrong, and it leads to some weird fadeout behavior.
|
||||
float fade = in->fade_a * p0.z() + in->fade_b; // fade_a is negative
|
||||
if (fade < 0)
|
||||
fade = 0;
|
||||
if (fade > 1)
|
||||
fade = 1;
|
||||
|
||||
// Adjust color based on fade.
|
||||
Vector4f rgba(in->color[0], in->color[1], in->color[2], in->color[3]);
|
||||
rgba.x() *= rgba.w() * fade / 128.f;
|
||||
rgba.y() *= rgba.w() * fade / 128.f;
|
||||
rgba.z() *= rgba.w() * fade / 128.f;
|
||||
out->flare_draw_color = rgba;
|
||||
|
||||
// Apply an offset. This moves the point along a line between its original position, and the
|
||||
// camera (so this offset doesn't make the thing move up/down/left/right on screen, just "toward"
|
||||
// the camera).
|
||||
float pscale = 1.f - (in->z_offset / p0.z());
|
||||
p0.x() *= pscale;
|
||||
p0.y() *= pscale;
|
||||
p0.z() *= pscale;
|
||||
|
||||
// Apply perspective transformation (no divide yet)
|
||||
p0 = consts->perspective[3] + consts->perspective[0] * p0.x() + consts->perspective[1] * p0.y() +
|
||||
consts->perspective[2] * p0.z();
|
||||
|
||||
// HMGE's meaning is unknown, but it's scaling factors for clipping. Apply those, and reject if
|
||||
// the origin is off-screen.
|
||||
Vector4f pos_hmged = p0.elementwise_multiply(consts->hmge);
|
||||
float clip_plus = std::abs(pos_hmged.w());
|
||||
float clip_minus = -clip_plus;
|
||||
if (pos_hmged.x() > clip_plus || pos_hmged.x() < clip_minus)
|
||||
return false;
|
||||
if (pos_hmged.y() > clip_plus || pos_hmged.y() < clip_minus)
|
||||
return false;
|
||||
if (pos_hmged.z() > clip_plus || pos_hmged.z() < clip_minus)
|
||||
return false;
|
||||
|
||||
// apply perspective divide. Interestingly using hmge's w here...
|
||||
float perspective_q = 1.f / pos_hmged.w();
|
||||
p0.x() *= perspective_q;
|
||||
p0.y() *= perspective_q;
|
||||
p0.z() *= perspective_q;
|
||||
out->perspective_q = perspective_q;
|
||||
|
||||
// apply offset to final point. These offsets are applied after perspective divide, and are
|
||||
// required for the PS2 screen coordinates (centered at 2048, 2048).
|
||||
p0 += consts->hvdf;
|
||||
|
||||
// from this point on, things are in screen coordinates. So our sizes (not screen coordinates)
|
||||
// should be scaled by q to become sizes in screen coordinates.
|
||||
Vector4f vf02(in->size_probe, in->z_offset, in->size_x, in->size_y);
|
||||
vf02 *= perspective_q;
|
||||
|
||||
// clamp the probe size to be in (1, clamp_max.w)
|
||||
if (vf02.x() < 1)
|
||||
vf02.x() = 1; // size_probe
|
||||
if (vf02.x() > consts->clamp_max.w())
|
||||
vf02.x() = consts->clamp_max.w(); // size probe
|
||||
|
||||
// clamp the maximum size_x/size_y to clamp_max.z
|
||||
if (vf02.z() > consts->clamp_max.z())
|
||||
vf02.z() = consts->clamp_max.z(); // size x
|
||||
if (vf02.w() > consts->clamp_max.z())
|
||||
vf02.w() = consts->clamp_max.z(); // size y
|
||||
|
||||
// compute the minimum safe position for the center of the probe, so corner ends up at min/max
|
||||
math::Vector2f vf09_min_probe_center(consts->clamp_min.x() + vf02.x(),
|
||||
consts->clamp_min.y() + vf02.x());
|
||||
math::Vector2f vf10_max_probe_center(consts->clamp_max.x() - vf02.x(),
|
||||
consts->clamp_max.y() - vf02.x());
|
||||
|
||||
// clear corners. these don't have rotation applied, I guess (vf11, vf12)
|
||||
out->second_clear_pos[0] = Vector4f(p0.x() - vf02.x(), p0.y() - vf02.x(), p0.z(), p0.w());
|
||||
out->second_clear_pos[1] = Vector4f(p0.x() + vf02.x(), p0.y() + vf02.x(), p0.z(), p0.w());
|
||||
|
||||
// compute offset from center of sprite to corner. This includes the rotation
|
||||
math::Vector2f basis_x(consts->basis_x[0], 0); // x scaling factor
|
||||
math::Vector2f basis_y(0, consts->basis_y[1]); // y scarling factor
|
||||
// rotate them
|
||||
float rot_rad = in->rot_angle * consts->deg_to_rad;
|
||||
float rot_sin = std::sin(rot_rad);
|
||||
float rot_cos = std::cos(rot_rad);
|
||||
math::Vector2f vf15_rotated_basis_x = basis_x * rot_sin - basis_y * rot_cos;
|
||||
math::Vector2f vf16_rotated_basis_y = basis_x * rot_cos + basis_y * rot_sin;
|
||||
vf15_rotated_basis_x *= vf02.z(); // scale x
|
||||
vf16_rotated_basis_y *= vf02.w(); // scale y
|
||||
|
||||
// limit position so the clear doesn't go out of bounds
|
||||
// max.xy vf20, vf01, vf09 -> is this bugged? I think the x broadcast here is wrong
|
||||
// this breaks fadeout as the sprite moves off the top of the screen. I've fixed it here because
|
||||
// I'm pretty sure this is just a mistake.
|
||||
math::Vector2f vf20_pos(std::max(p0.x(), vf09_min_probe_center.x()),
|
||||
std::max(p0.y(), vf09_min_probe_center.y()));
|
||||
vf20_pos.min_in_place(vf10_max_probe_center);
|
||||
|
||||
// vf17 thing, vf18 thing
|
||||
math::Vector2f vf17(consts->clamp_min.x() - 1, consts->clamp_min.y() - 1);
|
||||
math::Vector2f vf18(consts->clamp_min.x() + 1, consts->clamp_min.y() + 1);
|
||||
vf17 = vf20_pos - vf17;
|
||||
vf17 -= vf02.x();
|
||||
vf18 = vf20_pos - vf18;
|
||||
vf18 += vf02.x();
|
||||
out->offscreen_uv[0] = vf17;
|
||||
out->offscreen_uv[1] = vf18;
|
||||
|
||||
out->first_clear_pos[0] =
|
||||
Vector4f(vf20_pos.x() - vf02.x() - 1, vf20_pos.y() - vf02.x() - 1, 0xffffff, p0.w());
|
||||
out->first_clear_pos[1] =
|
||||
Vector4f(vf20_pos.x() + vf02.x() + 1, vf20_pos.y() + vf02.x() + 1, 0xffffff, p0.w());
|
||||
|
||||
// mulaw.xyzw ACC, vf01, vf00
|
||||
// maddax.xyzw ACC, vf15, vf11
|
||||
// maddy.xyzw vf11, vf16, vf11
|
||||
for (int i = 0; i < 4; i++) {
|
||||
out->flare_xyzw[i] = p0;
|
||||
math::Vector2f off = (vf15_rotated_basis_x * consts->xy_array[i].x()) +
|
||||
(vf16_rotated_basis_y * consts->xy_array[i].y());
|
||||
out->flare_xyzw[i].x() += off.x();
|
||||
out->flare_xyzw[i].y() += off.y();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Handle glow dma and draw glow sprites using GlowRenderer
|
||||
*/
|
||||
void Sprite3::glow_dma_and_draw(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
auto maybe_consts_setup = dma.read_and_advance();
|
||||
if (maybe_consts_setup.size_bytes != sizeof(SpriteGlowConsts)) {
|
||||
fmt::print("no consts...\n");
|
||||
return;
|
||||
}
|
||||
SpriteGlowConsts consts;
|
||||
memcpy(&consts, maybe_consts_setup.data, sizeof(SpriteGlowConsts));
|
||||
|
||||
auto templ_1 = dma.read_and_advance();
|
||||
ASSERT(templ_1.size_bytes == 16 * 0x54);
|
||||
|
||||
auto templ_2 = dma.read_and_advance();
|
||||
ASSERT(templ_2.size_bytes == 16 * 0x54);
|
||||
|
||||
auto bo = dma.read_and_advance();
|
||||
ASSERT(bo.size_bytes == 0);
|
||||
|
||||
auto flushe = dma.read_and_advance();
|
||||
ASSERT(flushe.size_bytes == 0);
|
||||
|
||||
auto control_xfer = dma.read_and_advance();
|
||||
while (control_xfer.size_bytes == 0 && control_xfer.vifcode0().kind == VifCode::Kind::NOP &&
|
||||
control_xfer.vifcode1().kind == VifCode::Kind::NOP) {
|
||||
control_xfer = dma.read_and_advance();
|
||||
}
|
||||
while (control_xfer.size_bytes == 16) {
|
||||
auto vecdata_xfer = dma.read_and_advance();
|
||||
auto shader_xfer = dma.read_and_advance();
|
||||
auto call = dma.read_and_advance();
|
||||
(void)call;
|
||||
|
||||
u32 num_sprites;
|
||||
memcpy(&num_sprites, control_xfer.data, 4);
|
||||
ASSERT(num_sprites == 1); // always, for whatever reason.
|
||||
|
||||
ASSERT(vecdata_xfer.size_bytes == 4 * 16);
|
||||
ASSERT(shader_xfer.size_bytes == 5 * 16);
|
||||
|
||||
auto* out = m_glow_renderer.alloc_sprite();
|
||||
if (!glow_math(&consts, vecdata_xfer.data, shader_xfer.data, out)) {
|
||||
m_glow_renderer.cancel_sprite();
|
||||
}
|
||||
control_xfer = dma.read_and_advance();
|
||||
while (control_xfer.size_bytes == 0 && control_xfer.vifcode0().kind == VifCode::Kind::NOP &&
|
||||
control_xfer.vifcode1().kind == VifCode::Kind::NOP) {
|
||||
control_xfer = dma.read_and_advance();
|
||||
}
|
||||
}
|
||||
|
||||
m_glow_renderer.flush(render_state, prof);
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/sprite_common.h"
|
||||
#include "game/graphics/opengl_renderer/sprite/sprite_common.h"
|
||||
|
||||
class SpriteRenderer : public BucketRenderer {
|
||||
public:
|
@ -209,4 +209,35 @@ enum SpriteProgMem {
|
||||
|
||||
static_assert(offsetof(SpriteFrameData, hmge_scale) == 256);
|
||||
static_assert(sizeof(SpriteFrameDataJak1) == 0x290, "SpriteFrameData size");
|
||||
static_assert(sizeof(SpriteFrameData) == 0x2a0, "SpriteFrameData size");
|
||||
static_assert(sizeof(SpriteFrameData) == 0x2a0, "SpriteFrameData size");
|
||||
|
||||
/*!
|
||||
* Post-transformation description of a sprite glow - passed to the GlowRenderer.
|
||||
*/
|
||||
struct SpriteGlowOutput {
|
||||
math::Vector4f first_clear_pos[2]; // 8, 9
|
||||
math::Vector4f second_clear_pos[2]; // 11, 12 corners for the second clear draw
|
||||
math::Vector2f offscreen_uv[2]; // 24, 26
|
||||
math::Vector4f flare_xyzw[4];
|
||||
AdGifData adgif; // 68, 69, 70, 71, 72
|
||||
math::Vector4f flare_draw_color; // 75
|
||||
float perspective_q;
|
||||
};
|
||||
|
||||
struct SpriteGlowConsts {
|
||||
math::Vector4f camera[4];
|
||||
math::Vector4f perspective[4];
|
||||
math::Vector4f hvdf;
|
||||
math::Vector4f hmge;
|
||||
float pfog0;
|
||||
float deg_to_rad;
|
||||
float min_scale;
|
||||
float inv_area;
|
||||
math::Vector4f sincos[5];
|
||||
math::Vector4f basis_x;
|
||||
math::Vector4f basis_y;
|
||||
math::Vector4f xy_array[4];
|
||||
math::Vector4f clamp_min;
|
||||
math::Vector4f clamp_max;
|
||||
};
|
||||
static_assert(sizeof(SpriteGlowConsts) == 0x180);
|
@ -1805,7 +1805,7 @@
|
||||
(when (not (paused?))
|
||||
(clear *stdcon1*)
|
||||
(debug-reset-buffers)
|
||||
;(clear! *simple-sprite-system*)
|
||||
(clear! *simple-sprite-system*)
|
||||
)
|
||||
(set! (-> s5-1 bucket-group) (dma-buffer-add-buckets (-> s5-1 calc-buf) 327))
|
||||
)
|
||||
|
@ -79,6 +79,7 @@
|
||||
(signal 96)
|
||||
(finish 97)
|
||||
(label 98)
|
||||
(hack 127)
|
||||
)
|
||||
|
||||
(defenum gs-reg64
|
||||
|
@ -8,17 +8,18 @@
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(deftype sprite-glow-data (structure)
|
||||
((position vector :inline :offset-assert 0)
|
||||
(size-x float :offset 12)
|
||||
(size-probe float :offset-assert 16)
|
||||
(z-offset float :offset-assert 20)
|
||||
(rot-angle float :offset-assert 24)
|
||||
(size-y float :offset-assert 28)
|
||||
(color rgbaf :inline :offset-assert 32)
|
||||
(fade-a float :offset-assert 48)
|
||||
(fade-b float :offset-assert 52)
|
||||
(tex-id texture-id :offset-assert 56)
|
||||
(dummy uint32 :offset-assert 60)
|
||||
((position vector :inline :offset-assert 0)
|
||||
(size-x float :offset 12)
|
||||
(size-probe float :offset-assert 16)
|
||||
(z-offset float :offset-assert 20)
|
||||
(rot-angle float :offset-assert 24)
|
||||
(size-y float :offset-assert 28)
|
||||
(color rgbaf :inline :offset-assert 32)
|
||||
(fade-a float :offset-assert 48)
|
||||
(fade-b float :offset-assert 52)
|
||||
(tex-id texture-id :offset-assert 56)
|
||||
(dummy uint32 :offset-assert 60)
|
||||
(quads vector 4 :inline :offset 0)
|
||||
)
|
||||
:method-count-assert 10
|
||||
:size-assert #x40
|
||||
@ -39,16 +40,16 @@
|
||||
)
|
||||
|
||||
(deftype simple-sprite-system (structure)
|
||||
((count int16 :offset-assert 0)
|
||||
(max-count int16 :offset-assert 2)
|
||||
(data sprite-glow-data :offset-assert 4)
|
||||
((count int16 :offset-assert 0)
|
||||
(max-count int16 :offset-assert 2)
|
||||
(data (inline-array sprite-glow-data) :offset-assert 4)
|
||||
)
|
||||
:method-count-assert 12
|
||||
:size-assert #x8
|
||||
:flag-assert #xc00000008
|
||||
(:methods
|
||||
(add! (_type_ dma-buffer) none 9)
|
||||
(simple-sprite-system-method-10 (_type_ dma-buffer) none 10)
|
||||
(add! (_type_ sprite-glow-data) none 9)
|
||||
(draw-all-sprites! (_type_ dma-buffer) none 10)
|
||||
(clear! (_type_) none 11)
|
||||
)
|
||||
)
|
||||
|
@ -7,3 +7,790 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(deftype sprite-glow-template (structure)
|
||||
((clear-init-giftag gs-gif-tag :inline :offset-assert 0)
|
||||
(clear-init-adcmds gs-adcmd 5 :inline :offset-assert 16)
|
||||
(clear-draw-giftag gs-gif-tag :inline :offset-assert 96)
|
||||
(clear-draw-clr-0 gs-packed-rgba :inline :offset-assert 112)
|
||||
(clear-draw-xyz-0 gs-packed-xyzw 2 :inline :offset-assert 128) ;; 8
|
||||
(clear-draw-clr-1 gs-packed-rgba :inline :offset-assert 160)
|
||||
(clear-draw-xyz-1 vector 2 :inline :offset-assert 176) ;; 11
|
||||
|
||||
(offscr-setup-giftag gs-gif-tag :inline :offset-assert 208) ;; 13
|
||||
(offscr-setup-adcmds gs-adcmd 8 :inline :offset-assert 224)
|
||||
(offscr-first-giftag gs-gif-tag :inline :offset-assert 352)
|
||||
(offscr-first-clr gs-packed-rgba :inline :offset-assert 368)
|
||||
(offscr-first-uv-0 gs-packed-uv :inline :offset-assert 384) ;; 24
|
||||
(offscr-first-xyzw-0 gs-packed-xyzw :inline :offset-assert 400)
|
||||
(offscr-first-uv-1 gs-packed-uv :inline :offset-assert 416) ;; 26
|
||||
(offscr-first-xyzw-1 gs-packed-xyzw :inline :offset-assert 432)
|
||||
|
||||
(repeat-draw-giftag gs-gif-tag :inline :offset-assert 448) ;; 28
|
||||
(repeat-draw-adcmds gs-adcmd 29 :inline :offset-assert 464)
|
||||
|
||||
(flare-alpha-giftag gs-gif-tag :inline :offset-assert 928) ;; 58
|
||||
(flare-alpha-clr gs-packed-rgba :inline :offset-assert 944)
|
||||
(flare-alpha-uv gs-packed-uv :inline :offset-assert 960)
|
||||
(flare-alpha-xyzw-0 gs-packed-xyzw :inline :offset-assert 976) ;; 61
|
||||
(flare-alpha-xyzw-1 gs-packed-xyzw :inline :offset-assert 992)
|
||||
(flare-alpha-xyzw-2 gs-packed-xyzw :inline :offset-assert 1008)
|
||||
(flare-alpha-xyzw-3 gs-packed-xyzw :inline :offset-assert 1024)
|
||||
|
||||
(flare-init-giftag gs-gif-tag :inline :offset-assert 1040) ;; 65
|
||||
(flare-init-adcmds gs-adcmd 8 :inline :offset-assert 1056)
|
||||
|
||||
(flare-draw-giftag gs-gif-tag :inline :offset-assert 1184) ;; 74
|
||||
(flare-draw-clr gs-packed-rgba :inline :offset-assert 1200)
|
||||
(flare-draw-stq-0 gs-packed-stq :inline :offset-assert 1216)
|
||||
(flare-draw-xyzw-0 gs-packed-xyzw :inline :offset-assert 1232) ;; 77
|
||||
(flare-draw-stq-1 gs-packed-stq :inline :offset-assert 1248)
|
||||
(flare-draw-xyzw-1 gs-packed-xyzw :inline :offset-assert 1264)
|
||||
(flare-draw-stq-2 gs-packed-stq :inline :offset-assert 1280)
|
||||
(flare-draw-xyzw-2 gs-packed-xyzw :inline :offset-assert 1296)
|
||||
(flare-draw-stq-3 gs-packed-stq :inline :offset-assert 1312)
|
||||
(flare-draw-xyzw-3 gs-packed-xyzw :inline :offset-assert 1328)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x540
|
||||
:flag-assert #x900000540
|
||||
)
|
||||
|
||||
|
||||
(deftype sprite-glow-consts (structure)
|
||||
((camera matrix :inline :offset-assert 0)
|
||||
(perspective matrix :inline :offset-assert 64)
|
||||
(hvdf-offset vector :inline :offset-assert 128)
|
||||
(hmge-scale vector :inline :offset-assert 144)
|
||||
(consts vector :inline :offset-assert 160)
|
||||
(pfog0 float :offset 160)
|
||||
(deg-to-rad float :offset 164)
|
||||
(min-scale float :offset 168)
|
||||
(inv-area float :offset 172)
|
||||
(sincos-01 vector :inline :offset-assert 176)
|
||||
(sincos-23 vector :inline :offset-assert 192)
|
||||
(sincos-45 vector :inline :offset-assert 208)
|
||||
(sincos-67 vector :inline :offset-assert 224)
|
||||
(sincos-89 vector :inline :offset-assert 240)
|
||||
(basis-x vector :inline :offset-assert 256)
|
||||
(basis-y vector :inline :offset-assert 272)
|
||||
(xy-array vector 4 :inline :offset-assert 288)
|
||||
(clamp-min vector :inline :offset-assert 352)
|
||||
(clamp-max vector :inline :offset-assert 368)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x180
|
||||
:flag-assert #x900000180
|
||||
)
|
||||
|
||||
|
||||
(define *sprite-glow-template*
|
||||
(new 'static 'sprite-glow-template
|
||||
:clear-init-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x5 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:clear-init-adcmds (new 'static 'inline-array gs-adcmd 5
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
;; (new 'static 'gs-alpha :a 2 :b 2 :c 2 :d 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-1) :x #x6a)
|
||||
;; (new 'static 'gs-test :ate 1 :afail 1 :zte 1 :ztst 2)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-1) :x #x51001)
|
||||
;; (new 'static 'gs-zbuf :zbp 304 :psm 1 :zmsk 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-1) :x #x1000130 :y #x1)
|
||||
;; (new 'static 'gs-frame :fbp 408 :fbw 8 :fbmsk #xffffff)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-1) :x #x80198 :y #xffffff)
|
||||
)
|
||||
:clear-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x2
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type sprite))
|
||||
:nreg #x3
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id rgbaq) :regs1 (gif-reg-id xyzf2) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
:clear-draw-xyz-0 (new 'static 'inline-array gs-packed-xyzw 2
|
||||
(new 'static 'gs-packed-xyzw :iz -1)
|
||||
(new 'static 'gs-packed-xyzw :iz -1)
|
||||
)
|
||||
:clear-draw-clr-1 (new 'static 'gs-packed-rgba :x #xff :w #xff)
|
||||
:offscr-setup-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x8 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:offscr-setup-adcmds (new 'static 'inline-array gs-adcmd 8
|
||||
;; (new 'static 'gs-frame :fbp 144 :fbw 1 :fbmsk #xffffff)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-2) :x #x10090 :y #xffffff)
|
||||
;; (new 'static 'gs-zbuf :zbp 304 :psm 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-2) :x #x1000130)
|
||||
;; mmag/mmin on
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex1-2) :x #x60)
|
||||
;; (new 'static 'gs-tex0 :tbp0 #x3300 :tbw 8 :tw 9 :th 9 :tcc 1 :tfx 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex0-2) :x #x64023300 :y #xe)
|
||||
;; wms, wmt both 1
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 clamp-2) :x #x5)
|
||||
;; ate 1, afail 1, zte 1, ztst 1
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x31001)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyoffset-2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
)
|
||||
:offscr-first-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type sprite) :tme #x1 :fst #x1 :ctxt #x1)
|
||||
:nreg #x5
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id uv)
|
||||
:regs2 (gif-reg-id xyz2)
|
||||
:regs3 (gif-reg-id uv)
|
||||
:regs4 (gif-reg-id xyz2)
|
||||
)
|
||||
)
|
||||
:offscr-first-clr (new 'static 'gs-packed-rgba :x #x80 :y #x80 :z #x80 :w #x80)
|
||||
:offscr-first-xyzw-1 (new 'static 'gs-packed-xyzw :ix #x200 :iy #x200)
|
||||
:repeat-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x1d :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:repeat-draw-adcmds (new 'static 'inline-array gs-adcmd 29
|
||||
;; tbp: 0x1200, tbw 1, tw = 5, th = 5, tcc = 1, tfx = 1
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex0-2) :x #x54005200 :y #xd)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x2100210)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x1000100)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x1100110)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x800080)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x900090)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x400040)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x500050)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x200020)
|
||||
;; fbp = 408, fbw = 8 (normal screen drawing)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-2) :x #x80198 :y #xffffff)
|
||||
;; (new 'static 'gs-test :ate 1 :afail 1 :zte 1 :ztst 2)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x51001)
|
||||
;; (new 'static 'gs-zbuf :zbp 304 :psm 1 :zmsk 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-2) :x #x1000130 :y #x1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyoffset-2) :x #x7000 :y #x7300)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 scissor-2) :x #x1ff0000 :y #x19f0000)
|
||||
;; zte = 1, ztst = 2
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x50000)
|
||||
;; (new 'static 'gs-alpha :a 2 :b 2 :c 2 :d 1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-2) :x #x6a)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
)
|
||||
:flare-alpha-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :tme #x1 :fst #x1 :ctxt #x1)
|
||||
:nreg #x6
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id uv)
|
||||
:regs2 (gif-reg-id xyzf2)
|
||||
:regs3 (gif-reg-id xyzf2)
|
||||
:regs4 (gif-reg-id xyzf2)
|
||||
:regs5 (gif-reg-id xyzf2)
|
||||
)
|
||||
)
|
||||
:flare-alpha-clr (new 'static 'gs-packed-rgba :x #x80 :y #x80 :z #x80 :w #x80)
|
||||
:flare-alpha-uv (new 'static 'gs-packed-uv :x (the-as float #x10) :y (the-as float #x10))
|
||||
:flare-alpha-xyzw-0 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-1 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-2 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-3 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-init-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x8 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:flare-init-adcmds (new 'static 'inline-array gs-adcmd 8
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
;; normal frame, no mask
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-1) :x #x80198)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
;; a = 0, b = 2, c = 1, d = 1
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-1) :x #x58)
|
||||
)
|
||||
:flare-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:eop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :tme #x1 :abe #x1)
|
||||
:nreg #x9
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id st)
|
||||
:regs2 (gif-reg-id xyzf2)
|
||||
:regs3 (gif-reg-id st)
|
||||
:regs4 (gif-reg-id xyzf2)
|
||||
:regs5 (gif-reg-id st)
|
||||
:regs6 (gif-reg-id xyzf2)
|
||||
:regs7 (gif-reg-id st)
|
||||
:regs8 (gif-reg-id xyzf2)
|
||||
)
|
||||
)
|
||||
:flare-draw-clr (new 'static 'gs-packed-rgba :y 64 :w #x80)
|
||||
:flare-draw-stq-0 (new 'static 'gs-packed-stq :z 1.0)
|
||||
:flare-draw-xyzw-0 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-1 (new 'static 'gs-packed-stq :x 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-1 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-2 (new 'static 'gs-packed-stq :x 1.0 :y 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-2 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-3 (new 'static 'gs-packed-stq :y 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-3 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
)
|
||||
)
|
||||
|
||||
(define sprite-glow-vu1-block (new 'static 'vu-function #|:length #x86 :qlength 67|#))
|
||||
|
||||
;; WARN: Return type mismatch vector vs none.
|
||||
(defun sprite-glow-init-consts ((arg0 sprite-glow-consts))
|
||||
(let ((v1-0 *math-camera*))
|
||||
(let* ((t0-0 (-> arg0 camera))
|
||||
(t1-0 (-> v1-0 camera-rot))
|
||||
(a1-0 (-> t1-0 quad 0))
|
||||
(a2-0 (-> t1-0 quad 1))
|
||||
(a3-0 (-> t1-0 quad 2))
|
||||
(t1-1 (-> t1-0 trans quad))
|
||||
)
|
||||
(set! (-> t0-0 quad 0) a1-0)
|
||||
(set! (-> t0-0 quad 1) a2-0)
|
||||
(set! (-> t0-0 quad 2) a3-0)
|
||||
(set! (-> t0-0 trans quad) t1-1)
|
||||
)
|
||||
(let* ((t0-1 (-> arg0 perspective))
|
||||
(t1-2 (-> v1-0 perspective))
|
||||
(a1-1 (-> t1-2 quad 0))
|
||||
(a2-1 (-> t1-2 quad 1))
|
||||
(a3-1 (-> t1-2 quad 2))
|
||||
(t1-3 (-> t1-2 trans quad))
|
||||
)
|
||||
(set! (-> t0-1 quad 0) a1-1)
|
||||
(set! (-> t0-1 quad 1) a2-1)
|
||||
(set! (-> t0-1 quad 2) a3-1)
|
||||
(set! (-> t0-1 trans quad) t1-3)
|
||||
)
|
||||
(set! (-> arg0 hvdf-offset quad) (-> v1-0 hvdf-off quad))
|
||||
(set! (-> arg0 hmge-scale quad) (-> v1-0 hmge-scale quad))
|
||||
(set! (-> arg0 basis-x quad) (the-as uint128 0))
|
||||
(set! (-> arg0 basis-x x) (- (-> *math-camera* perspective vector 0 x)))
|
||||
(set! (-> arg0 basis-y quad) (the-as uint128 0))
|
||||
(set! (-> arg0 basis-y y) (- (-> *math-camera* perspective vector 1 y)))
|
||||
(set! (-> arg0 pfog0) (-> v1-0 pfog0))
|
||||
)
|
||||
(set! (-> arg0 deg-to-rad) 0.000095873795)
|
||||
(set! (-> arg0 min-scale) (sqrtf (* (/ 1.0 (-> arg0 basis-x x)) (/ 1.0 (-> arg0 basis-y y)))))
|
||||
(set! (-> arg0 inv-area) (/ 1.0 (* (-> arg0 min-scale) (-> arg0 min-scale))))
|
||||
(let ((v1-5 (-> arg0 sincos-01)))
|
||||
(set! (-> v1-5 z) 0.999998)
|
||||
(set! (-> v1-5 w) 1.0)
|
||||
)
|
||||
(let ((v1-6 (-> arg0 sincos-23)))
|
||||
(set! (-> v1-6 z) -0.16666014)
|
||||
(set! (-> v1-6 w) -0.49998003)
|
||||
)
|
||||
(let ((v1-7 (-> arg0 sincos-45)))
|
||||
(set! (-> v1-7 z) 0.008326521)
|
||||
(set! (-> v1-7 w) 0.041620404)
|
||||
)
|
||||
(let ((v1-8 (-> arg0 sincos-67)))
|
||||
(set! (-> v1-8 z) -0.0001956241)
|
||||
(set! (-> v1-8 w) -0.0013636408)
|
||||
)
|
||||
(let ((v1-9 (-> arg0 sincos-89)))
|
||||
(set! (-> v1-9 z) 0.0000023042373)
|
||||
(set! (-> v1-9 w) 0.000020170546)
|
||||
)
|
||||
(set-vector! (-> arg0 xy-array 0) -0.5 -0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 1) 0.5 -0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 2) 0.5 0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 3) -0.5 0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 clamp-min) 1792.0 1840.0 0.0 0.0)
|
||||
(set-vector! (-> arg0 clamp-max) 2304.0 2256.0 2048.0 50.0)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun sprite-glow-init-engine ((arg0 dma-buffer))
|
||||
(dma-buffer-add-vu-function arg0 sprite-glow-vu1-block 1)
|
||||
(let ((s5-0 24))
|
||||
(let* ((v1-0 arg0)
|
||||
(a0-2 (the-as dma-packet (-> v1-0 base)))
|
||||
)
|
||||
(set! (-> a0-2 dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s5-0))
|
||||
(set! (-> a0-2 vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> a0-2 vif1) (new 'static 'vif-tag :imm #x3d4 :cmd (vif-cmd unpack-v4-32) :num s5-0))
|
||||
(set! (-> v1-0 base) (the-as pointer (&+ a0-2 16)))
|
||||
)
|
||||
(sprite-glow-init-consts (the-as sprite-glow-consts (-> arg0 base)))
|
||||
(&+! (-> arg0 base) (* s5-0 16))
|
||||
)
|
||||
(let ((v1-3 84))
|
||||
(let* ((a0-6 arg0)
|
||||
(a1-6 (the-as dma-packet (-> a0-6 base)))
|
||||
)
|
||||
(set! (-> a1-6 dma)
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref) :addr (the-as int *sprite-glow-template*) :qwc v1-3)
|
||||
)
|
||||
(set! (-> a1-6 vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> a1-6 vif1) (new 'static 'vif-tag :imm #x320 :cmd (vif-cmd unpack-v4-32) :num v1-3))
|
||||
(set! (-> a0-6 base) (the-as pointer (&+ a1-6 16)))
|
||||
)
|
||||
(let* ((a0-7 arg0)
|
||||
(a1-8 (the-as dma-packet (-> a0-7 base)))
|
||||
)
|
||||
(set! (-> a1-8 dma)
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref) :addr (the-as int *sprite-glow-template*) :qwc v1-3)
|
||||
)
|
||||
(set! (-> a1-8 vif0) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x0))
|
||||
(set! (-> a1-8 vif1) (new 'static 'vif-tag :imm #x374 :cmd (vif-cmd unpack-v4-32) :num v1-3))
|
||||
(set! (-> a0-7 base) (the-as pointer (&+ a1-8 16)))
|
||||
)
|
||||
)
|
||||
(let* ((v1-8 arg0)
|
||||
(a0-8 (the-as dma-packet (-> v1-8 base)))
|
||||
)
|
||||
(set! (-> a0-8 dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> a0-8 vif0) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> a0-8 vif1) (new 'static 'vif-tag :imm #x190 :cmd (vif-cmd offset)))
|
||||
(set! (-> v1-8 base) (the-as pointer (&+ a0-8 16)))
|
||||
)
|
||||
(let ((v1-9 (the-as dma-packet (-> arg0 base))))
|
||||
(set! (-> v1-9 dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> v1-9 vif0) (new 'static 'vif-tag))
|
||||
(set! (-> v1-9 vif1) (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-9 16)))
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(deftype sprite-glow-dma-packet-data (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 16)
|
||||
(shader-cnt-packet dma-packet :inline :offset-assert 32)
|
||||
(shader-ref-packet dma-packet :inline :offset-assert 48)
|
||||
(mscal-packet dma-packet :inline :offset-assert 64)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x50
|
||||
:flag-assert #x900000050
|
||||
)
|
||||
|
||||
|
||||
(deftype sprite-glow-cnt-template (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
(shader adgif-shader :inline :offset-assert 128)
|
||||
(mscal-packet dma-packet :inline :offset-assert 208)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xe0
|
||||
:flag-assert #x9000000e0
|
||||
)
|
||||
|
||||
|
||||
(deftype sprite-glow-ref-template (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
(shader-packet-ptr pointer :offset 116)
|
||||
(mscal-packet dma-packet :inline :offset-assert 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x90
|
||||
:flag-assert #x900000090
|
||||
)
|
||||
|
||||
|
||||
(define *sprite-glow-dma-packet-data*
|
||||
(new 'static 'sprite-glow-dma-packet-data
|
||||
:control-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x1 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8000 :num #x1 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:vecdata-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x4 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8001 :num #x4 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:shader-cnt-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x5 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8091 :num #x5 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:shader-ref-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x5 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8091 :num #x5 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:mscal-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id cnt))
|
||||
:vif1 (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(set! (-> *sprite-glow-dma-packet-data* mscal-packet vif0)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #xa)
|
||||
)
|
||||
|
||||
;; WARN: Return type mismatch sprite-glow-cnt-template vs none.
|
||||
(defun sprite-glow-add-sprite ((arg0 dma-buffer) (arg1 sprite-vec-data-2d) (arg2 float) (arg3 float) (arg4 float) (arg5 adgif-shader))
|
||||
(let ((v1-0 (the-as sprite-glow-cnt-template (-> arg0 base))))
|
||||
(let* ((t5-0 *sprite-glow-dma-packet-data*)
|
||||
(t2-0 (-> t5-0 control-packet quad))
|
||||
(t3-0 (-> t5-0 vecdata-packet quad))
|
||||
(t4-0 (-> t5-0 shader-cnt-packet quad))
|
||||
(t5-1 (-> t5-0 mscal-packet quad))
|
||||
)
|
||||
(set! (-> v1-0 control-packet quad) t2-0)
|
||||
(set! (-> v1-0 num-sprites-quad) (the-as uint128 0))
|
||||
(set! (-> v1-0 vecdata-packet quad) t3-0)
|
||||
(set! (-> v1-0 shader-packet quad) t4-0)
|
||||
(set! (-> v1-0 mscal-packet quad) t5-1)
|
||||
)
|
||||
(let ((t2-1 (-> arg1 x-y-z-sx quad))
|
||||
(t3-1 (-> arg1 flag-rot-sy quad))
|
||||
(a1-1 (-> arg1 r-g-b-a quad))
|
||||
)
|
||||
(set! (-> v1-0 vecdata position quad) t2-1)
|
||||
(set! (-> v1-0 vecdata quads 1 quad) t3-1)
|
||||
(set! (-> v1-0 vecdata color quad) a1-1)
|
||||
)
|
||||
(let ((a1-2 1))
|
||||
(set! (-> v1-0 vecdata z-offset) arg4)
|
||||
(set! (-> v1-0 vecdata fade-a) arg2)
|
||||
(set! (-> v1-0 vecdata fade-b) arg3)
|
||||
(set! (-> v1-0 num-sprites) (the-as uint a1-2))
|
||||
)
|
||||
(let ((a1-3 (-> arg5 quad 0 quad))
|
||||
(a2-1 (-> arg5 quad 1 quad))
|
||||
(a3-1 (-> arg5 quad 2 quad))
|
||||
(t0-1 (-> arg5 quad 3 quad))
|
||||
(t1-1 (-> arg5 quad 4 quad))
|
||||
)
|
||||
(set! (-> v1-0 shader quad 0 quad) a1-3)
|
||||
(set! (-> v1-0 shader quad 1 quad) a2-1)
|
||||
(set! (-> v1-0 shader quad 2 quad) a3-1)
|
||||
(set! (-> v1-0 shader quad 3 quad) t0-1)
|
||||
(set! (-> v1-0 shader quad 4 quad) t1-1)
|
||||
)
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-0 224)))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; WARN: Return type mismatch sprite-glow-ref-template vs none.
|
||||
(defun sprite-glow-add-simple-sprite ((arg0 dma-buffer) (arg1 sprite-glow-dma-packet-data) (arg2 sprite-glow-data) (arg3 pointer))
|
||||
(let ((v1-0 (the-as sprite-glow-ref-template (-> arg0 base))))
|
||||
(let ((t0-0 (-> arg1 control-packet quad))
|
||||
(t1-0 (-> arg1 vecdata-packet quad))
|
||||
(t2-0 (-> arg1 shader-ref-packet quad))
|
||||
(a1-1 (-> arg1 mscal-packet quad))
|
||||
)
|
||||
(set! (-> v1-0 control-packet quad) t0-0)
|
||||
(set! (-> v1-0 num-sprites-quad) (the-as uint128 0))
|
||||
(set! (-> v1-0 vecdata-packet quad) t1-0)
|
||||
(set! (-> v1-0 shader-packet quad) t2-0)
|
||||
(set! (-> v1-0 mscal-packet quad) a1-1)
|
||||
)
|
||||
(let ((a1-2 (-> arg2 position quad))
|
||||
(t0-1 (-> arg2 quads 1 quad))
|
||||
(t1-1 (-> arg2 color quad))
|
||||
(a2-1 (-> arg2 quads 3 quad))
|
||||
(t2-1 1)
|
||||
)
|
||||
(set! (-> v1-0 vecdata position quad) a1-2)
|
||||
(set! (-> v1-0 vecdata quads 1 quad) t0-1)
|
||||
(set! (-> v1-0 vecdata color quad) t1-1)
|
||||
(set! (-> v1-0 vecdata quads 3 quad) a2-1)
|
||||
(set! (-> v1-0 num-sprites) (the-as uint t2-1))
|
||||
)
|
||||
(set! (-> v1-0 shader-packet-ptr) arg3)
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-0 144)))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
(defun sprite-glow-draw ((arg0 dma-buffer))
|
||||
(local-vars (a2-0 float))
|
||||
(let* ((s5-0 *sprite-aux-list*)
|
||||
(s4-0 (-> s5-0 entry))
|
||||
(s3-0 #f)
|
||||
)
|
||||
(dotimes (s2-0 s4-0)
|
||||
(let ((v1-2 (-> s5-0 data s2-0)))
|
||||
(when (and (not s3-0) (= (-> v1-2 aux-type) (sprite-aux-type glow)))
|
||||
(let* ((a0-5 (-> v1-2 aux-data omega))
|
||||
(a3-0 (cond
|
||||
((zero? a0-5)
|
||||
(set! a2-0 0.0)
|
||||
1.0
|
||||
)
|
||||
(else
|
||||
(let* ((f1-1 (* 0.00024414062 a0-5))
|
||||
(f0-4 (- f1-1 (the float (the int f1-1))))
|
||||
)
|
||||
(let ((f1-3 (* 4096.0 (- f1-1 f0-4))))
|
||||
(set! a2-0 (/ -1.0 (* (- 1.0 f0-4) f1-3)))
|
||||
)
|
||||
(/ f0-4 (- 1.0 f0-4))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(sprite-glow-add-sprite arg0 (-> v1-2 vec-data) a2-0 a3-0 (-> v1-2 aux-data user-float) (-> v1-2 gif-data))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod add! simple-sprite-system ((obj simple-sprite-system) (arg0 sprite-glow-data))
|
||||
(let ((v1-0 (-> obj count)))
|
||||
(when (< v1-0 (-> obj max-count))
|
||||
(let* ((a2-3 (-> obj data v1-0))
|
||||
(v1-2 arg0)
|
||||
(a1-1 a2-3)
|
||||
(a2-4 (-> v1-2 position quad))
|
||||
(a3-0 (-> v1-2 quads 1 quad))
|
||||
(t0-0 (-> v1-2 color quad))
|
||||
(v1-3 (-> v1-2 quads 3 quad))
|
||||
)
|
||||
(set! (-> a1-1 position quad) a2-4)
|
||||
(set! (-> a1-1 quads 1 quad) a3-0)
|
||||
(set! (-> a1-1 color quad) t0-0)
|
||||
(set! (-> a1-1 quads 3 quad) v1-3)
|
||||
)
|
||||
(+! (-> obj count) 1)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; WARN: Return type mismatch pointer vs adgif-shader.
|
||||
(defun add-shader-to-dma ((arg0 dma-buffer))
|
||||
(let* ((a1-0 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id next))))
|
||||
(v1-0 (-> arg0 base))
|
||||
(a1-1 (-> a1-0 quad))
|
||||
(v0-0 (&+ v1-0 16))
|
||||
)
|
||||
(let ((a2-0 (&+ v1-0 96)))
|
||||
(set! (-> (the-as (pointer uint128) v1-0)) a1-1)
|
||||
(set! (-> (the-as (pointer uint32) v1-0) 1) (the-as uint a2-0))
|
||||
(set! (-> arg0 base) a2-0)
|
||||
)
|
||||
(the-as adgif-shader v0-0)
|
||||
)
|
||||
)
|
||||
|
||||
(defmethod draw-all-sprites! simple-sprite-system ((obj simple-sprite-system) (arg0 dma-buffer))
|
||||
(local-vars (sv-528 sprite-glow-dma-packet-data) (sv-532 (pointer texture-id)) (sv-536 pointer))
|
||||
(b! (zero? (-> obj count)) cfg-13 :delay (nop!))
|
||||
(set! sv-528 *sprite-glow-dma-packet-data*)
|
||||
(set! sv-532 (new 'stack-no-clear 'array 'texture-id 128))
|
||||
(set! sv-536 (-> arg0 base))
|
||||
(when (> (-> obj count) 128)
|
||||
(format 0 "TOO MANY SPRITES (~D)~%" (-> obj count))
|
||||
(break!)
|
||||
)
|
||||
(dotimes (v1-5 (-> obj count))
|
||||
(set! (-> sv-532 v1-5) (-> obj data v1-5 tex-id))
|
||||
)
|
||||
(countdown (s4-0 (-> obj count))
|
||||
(let ((s3-0 (-> sv-532 s4-0)))
|
||||
(when (nonzero? s3-0)
|
||||
(let ((s2-0 (add-shader-to-dma arg0)))
|
||||
(adgif-shader<-texture-simple! s2-0 (lookup-texture-by-id s3-0))
|
||||
(countdown (s1-1 (+ s4-0 1))
|
||||
(when (= s3-0 (-> sv-532 s1-1))
|
||||
(set! (-> sv-532 s1-1) (new 'static 'texture-id))
|
||||
(let ((a2-1 (-> obj data s1-1)))
|
||||
(sprite-glow-add-simple-sprite arg0 sv-528 a2-1 (the-as pointer s2-0))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(label cfg-13)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(defmethod clear! simple-sprite-system ((obj simple-sprite-system))
|
||||
(set! (-> obj count) 0)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
(define *simple-sprite-system*
|
||||
(new 'static 'simple-sprite-system :max-count #x80 :data (new 'static 'inline-array sprite-glow-data 128
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -929,10 +929,9 @@
|
||||
;; sprite glow
|
||||
;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO: figure out what this is doing
|
||||
; (sprite-glow-init-engine dma-buff)
|
||||
; (sprite-glow-draw dma-buff)
|
||||
; (simple-sprite-system-method-10 *simple-sprite-system* dma-buff)
|
||||
(sprite-glow-init-engine dma-buff)
|
||||
(sprite-glow-draw dma-buff)
|
||||
(draw-all-sprites! *simple-sprite-system* dma-buff)
|
||||
(let* ((v1-26 dma-buff)
|
||||
(pkt6 (the-as dma-packet (-> v1-26 base)))
|
||||
)
|
||||
|
@ -271,7 +271,7 @@
|
||||
)
|
||||
(when (nonzero? *simple-sprite-system*)
|
||||
;; added nonzero check
|
||||
(add! *simple-sprite-system* (the-as dma-buffer (-> s3-1 1)))
|
||||
(add! *simple-sprite-system* (the sprite-glow-data (-> s3-1 1)))
|
||||
)
|
||||
(forward-up->quaternion (the-as quaternion (-> s3-1 0)) arg1 (the-as vector (-> obj rbody state matrix)))
|
||||
(quaternion-rotate-local-x! (the-as quaternion (-> s3-1 0)) (the-as quaternion (-> s3-1 0)) 32768.0)
|
||||
@ -386,7 +386,7 @@
|
||||
(set! (-> s4-0 color x) 255.0)
|
||||
(set! (-> s4-0 color y) (rand-vu-float-range 192.0 255.0))
|
||||
(set! (-> s4-0 color w) (* f30-1 (rand-vu-float-range 16.0 18.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-0))
|
||||
(add! *simple-sprite-system* s4-0)
|
||||
(let ((f0-21 (-> obj camera-dist2))
|
||||
(f1-6 245760.0)
|
||||
)
|
||||
@ -399,7 +399,7 @@
|
||||
(set! (-> s4-0 fade-b) 2.3332994)
|
||||
(set! (-> s4-0 color z) (rand-vu-float-range 128.0 160.0))
|
||||
(set! (-> s4-0 color w) (* f30-1 (rand-vu-float-range 32.0 36.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-0))
|
||||
(add! *simple-sprite-system* s4-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -419,7 +419,7 @@
|
||||
(set! (-> s4-1 rot-angle) (* 182.04445 (rand-vu-float-range -4.0 4.0)))
|
||||
(set! (-> s4-1 color y) (* 64.0 (rand-vu)))
|
||||
(set! (-> s4-1 color w) (* f30-1 (rand-vu-float-range 16.0 21.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-1))
|
||||
(add! *simple-sprite-system* s4-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
12
test/decompiler/reference/jak2/engine/gfx/hw/gs_REF.gc
generated
vendored
12
test/decompiler/reference/jak2/engine/gfx/hw/gs_REF.gc
generated
vendored
@ -410,7 +410,7 @@ bits 5 and 6 (0x20 and 0x40) should be zero"
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'gs-adcmd)
|
||||
(format #t "~1Tword[4] @ #x~X~%" (-> obj word))
|
||||
(format #t "~1Tword[4] @ #x~X~%" (&-> obj x))
|
||||
(format #t "~1Tquad: ~D~%" (-> obj quad))
|
||||
(format #t "~1Tdata: ~D~%" (-> obj data))
|
||||
(format #t "~1Tcmds: ~D~%" (-> obj cmds))
|
||||
@ -1039,16 +1039,16 @@ bits 5 and 6 (0x20 and 0x40) should be zero"
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'gs-packed-xyzw)
|
||||
(format #t "~1Tdata[4] @ #x~X~%" (&-> obj x))
|
||||
(format #t "~1Tdata[4] @ #x~X~%" (&-> obj ix))
|
||||
(format #t "~1Tx: ~f~%" (-> obj x))
|
||||
(format #t "~1Ty: ~f~%" (-> obj y))
|
||||
(format #t "~1Tz: ~f~%" (-> obj z))
|
||||
(format #t "~1Tw: ~f~%" (-> obj w))
|
||||
(format #t "~1Tquad: ~D~%" (-> obj quad))
|
||||
(format #t "~1Tix: ~D~%" (-> obj x))
|
||||
(format #t "~1Tiy: ~D~%" (-> obj y))
|
||||
(format #t "~1Tiz: ~D~%" (-> obj z))
|
||||
(format #t "~1Tiw: ~D~%" (-> obj w))
|
||||
(format #t "~1Tix: ~D~%" (-> obj ix))
|
||||
(format #t "~1Tiy: ~D~%" (-> obj iy))
|
||||
(format #t "~1Tiz: ~D~%" (-> obj iz))
|
||||
(format #t "~1Tiw: ~D~%" (-> obj iw))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
4
test/decompiler/reference/jak2/engine/gfx/lightning_REF.gc
generated
vendored
4
test/decompiler/reference/jak2/engine/gfx/lightning_REF.gc
generated
vendored
@ -27,8 +27,8 @@
|
||||
:regs (new 'static 'gif-tag-regs-32 :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
:adnops (new 'static 'inline-array gs-adcmd 2
|
||||
(new 'static 'gs-adcmd :word (new 'static 'array uint32 4 #x0 #x0 #x7f #x0))
|
||||
(new 'static 'gs-adcmd :word (new 'static 'array uint32 4 #x0 #x0 #x7f #x0))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
33
test/decompiler/reference/jak2/engine/gfx/sprite/simple-sprite-h_REF.gc
generated
vendored
33
test/decompiler/reference/jak2/engine/gfx/sprite/simple-sprite-h_REF.gc
generated
vendored
@ -3,17 +3,18 @@
|
||||
|
||||
;; definition of type sprite-glow-data
|
||||
(deftype sprite-glow-data (structure)
|
||||
((position vector :inline :offset-assert 0)
|
||||
(size-x float :offset 12)
|
||||
(size-probe float :offset-assert 16)
|
||||
(z-offset float :offset-assert 20)
|
||||
(rot-angle float :offset-assert 24)
|
||||
(size-y float :offset-assert 28)
|
||||
(color rgbaf :inline :offset-assert 32)
|
||||
(fade-a float :offset-assert 48)
|
||||
(fade-b float :offset-assert 52)
|
||||
(tex-id texture-id :offset-assert 56)
|
||||
(dummy uint32 :offset-assert 60)
|
||||
((position vector :inline :offset-assert 0)
|
||||
(size-x float :offset 12)
|
||||
(size-probe float :offset-assert 16)
|
||||
(z-offset float :offset-assert 20)
|
||||
(rot-angle float :offset-assert 24)
|
||||
(size-y float :offset-assert 28)
|
||||
(color rgbaf :inline :offset-assert 32)
|
||||
(fade-a float :offset-assert 48)
|
||||
(fade-b float :offset-assert 52)
|
||||
(tex-id texture-id :offset-assert 56)
|
||||
(dummy uint32 :offset-assert 60)
|
||||
(quads vector 4 :inline :offset 0)
|
||||
)
|
||||
:method-count-assert 10
|
||||
:size-assert #x40
|
||||
@ -59,16 +60,16 @@
|
||||
|
||||
;; definition of type simple-sprite-system
|
||||
(deftype simple-sprite-system (structure)
|
||||
((count int16 :offset-assert 0)
|
||||
(max-count int16 :offset-assert 2)
|
||||
(data sprite-glow-data :offset-assert 4)
|
||||
((count int16 :offset-assert 0)
|
||||
(max-count int16 :offset-assert 2)
|
||||
(data (inline-array sprite-glow-data) :offset-assert 4)
|
||||
)
|
||||
:method-count-assert 12
|
||||
:size-assert #x8
|
||||
:flag-assert #xc00000008
|
||||
(:methods
|
||||
(add! (_type_ dma-buffer) none 9)
|
||||
(simple-sprite-system-method-10 (_type_ dma-buffer) none 10)
|
||||
(add! (_type_ sprite-glow-data) none 9)
|
||||
(draw-all-sprites! (_type_ dma-buffer) none 10)
|
||||
(clear! (_type_) none 11)
|
||||
)
|
||||
)
|
||||
|
917
test/decompiler/reference/jak2/engine/gfx/sprite/sprite-glow_REF.gc
generated
vendored
Normal file
917
test/decompiler/reference/jak2/engine/gfx/sprite/sprite-glow_REF.gc
generated
vendored
Normal file
@ -0,0 +1,917 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
|
||||
;; definition of type sprite-glow-template
|
||||
(deftype sprite-glow-template (structure)
|
||||
((clear-init-giftag gs-gif-tag :inline :offset-assert 0)
|
||||
(clear-init-adcmds gs-adcmd 5 :inline :offset-assert 16)
|
||||
(clear-draw-giftag gs-gif-tag :inline :offset-assert 96)
|
||||
(clear-draw-clr-0 gs-packed-rgba :inline :offset-assert 112)
|
||||
(clear-draw-xyz-0 gs-packed-xyzw 2 :inline :offset-assert 128)
|
||||
(clear-draw-clr-1 gs-packed-rgba :inline :offset-assert 160)
|
||||
(clear-draw-xyz-1 vector 2 :inline :offset-assert 176)
|
||||
(offscr-setup-giftag gs-gif-tag :inline :offset-assert 208)
|
||||
(offscr-setup-adcmds gs-adcmd 8 :inline :offset-assert 224)
|
||||
(offscr-first-giftag gs-gif-tag :inline :offset-assert 352)
|
||||
(offscr-first-clr gs-packed-rgba :inline :offset-assert 368)
|
||||
(offscr-first-uv-0 gs-packed-uv :inline :offset-assert 384)
|
||||
(offscr-first-xyzw-0 gs-packed-xyzw :inline :offset-assert 400)
|
||||
(offscr-first-uv-1 gs-packed-uv :inline :offset-assert 416)
|
||||
(offscr-first-xyzw-1 gs-packed-xyzw :inline :offset-assert 432)
|
||||
(repeat-draw-giftag gs-gif-tag :inline :offset-assert 448)
|
||||
(repeat-draw-adcmds gs-adcmd 29 :inline :offset-assert 464)
|
||||
(flare-alpha-giftag gs-gif-tag :inline :offset-assert 928)
|
||||
(flare-alpha-clr gs-packed-rgba :inline :offset-assert 944)
|
||||
(flare-alpha-uv gs-packed-uv :inline :offset-assert 960)
|
||||
(flare-alpha-xyzw-0 gs-packed-xyzw :inline :offset-assert 976)
|
||||
(flare-alpha-xyzw-1 gs-packed-xyzw :inline :offset-assert 992)
|
||||
(flare-alpha-xyzw-2 gs-packed-xyzw :inline :offset-assert 1008)
|
||||
(flare-alpha-xyzw-3 gs-packed-xyzw :inline :offset-assert 1024)
|
||||
(flare-init-giftag gs-gif-tag :inline :offset-assert 1040)
|
||||
(flare-init-adcmds gs-adcmd 8 :inline :offset-assert 1056)
|
||||
(flare-draw-giftag gs-gif-tag :inline :offset-assert 1184)
|
||||
(flare-draw-clr gs-packed-rgba :inline :offset-assert 1200)
|
||||
(flare-draw-stq-0 gs-packed-stq :inline :offset-assert 1216)
|
||||
(flare-draw-xyzw-0 gs-packed-xyzw :inline :offset-assert 1232)
|
||||
(flare-draw-stq-1 gs-packed-stq :inline :offset-assert 1248)
|
||||
(flare-draw-xyzw-1 gs-packed-xyzw :inline :offset-assert 1264)
|
||||
(flare-draw-stq-2 gs-packed-stq :inline :offset-assert 1280)
|
||||
(flare-draw-xyzw-2 gs-packed-xyzw :inline :offset-assert 1296)
|
||||
(flare-draw-stq-3 gs-packed-stq :inline :offset-assert 1312)
|
||||
(flare-draw-xyzw-3 gs-packed-xyzw :inline :offset-assert 1328)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x540
|
||||
:flag-assert #x900000540
|
||||
)
|
||||
|
||||
;; definition for method 3 of type sprite-glow-template
|
||||
(defmethod inspect sprite-glow-template ((obj sprite-glow-template))
|
||||
(when (not obj)
|
||||
(set! obj obj)
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'sprite-glow-template)
|
||||
(format #t "~1Tclear-init-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj clear-init-giftag))
|
||||
(format #t "~1Tclear-init-adcmds[5] @ #x~X~%" (-> obj clear-init-adcmds))
|
||||
(format #t "~1Tclear-draw-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj clear-draw-giftag))
|
||||
(format #t "~1Tclear-draw-clr-0: #<gs-packed-rgba @ #x~X>~%" (-> obj clear-draw-clr-0))
|
||||
(format #t "~1Tclear-draw-xyz-0[2] @ #x~X~%" (-> obj clear-draw-xyz-0))
|
||||
(format #t "~1Tclear-draw-clr-1: #<gs-packed-rgba @ #x~X>~%" (-> obj clear-draw-clr-1))
|
||||
(format #t "~1Tclear-draw-xyz-1[2] @ #x~X~%" (-> obj clear-draw-xyz-1))
|
||||
(format #t "~1Toffscr-setup-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj offscr-setup-giftag))
|
||||
(format #t "~1Toffscr-setup-adcmds[8] @ #x~X~%" (-> obj offscr-setup-adcmds))
|
||||
(format #t "~1Toffscr-first-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj offscr-first-giftag))
|
||||
(format #t "~1Toffscr-first-clr: #<gs-packed-rgba @ #x~X>~%" (-> obj offscr-first-clr))
|
||||
(format #t "~1Toffscr-first-uv-0: #<gs-packed-uv @ #x~X>~%" (-> obj offscr-first-uv-0))
|
||||
(format #t "~1Toffscr-first-xyzw-0: #<gs-packed-xyzw @ #x~X>~%" (-> obj offscr-first-xyzw-0))
|
||||
(format #t "~1Toffscr-first-uv-1: #<gs-packed-uv @ #x~X>~%" (-> obj offscr-first-uv-1))
|
||||
(format #t "~1Toffscr-first-xyzw-1: #<gs-packed-xyzw @ #x~X>~%" (-> obj offscr-first-xyzw-1))
|
||||
(format #t "~1Trepeat-draw-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj repeat-draw-giftag))
|
||||
(format #t "~1Trepeat-draw-adcmds[29] @ #x~X~%" (-> obj repeat-draw-adcmds))
|
||||
(format #t "~1Tflare-alpha-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj flare-alpha-giftag))
|
||||
(format #t "~1Tflare-alpha-clr: #<gs-packed-rgba @ #x~X>~%" (-> obj flare-alpha-clr))
|
||||
(format #t "~1Tflare-alpha-uv: #<gs-packed-uv @ #x~X>~%" (-> obj flare-alpha-uv))
|
||||
(format #t "~1Tflare-alpha-xyzw-0: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-alpha-xyzw-0))
|
||||
(format #t "~1Tflare-alpha-xyzw-1: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-alpha-xyzw-1))
|
||||
(format #t "~1Tflare-alpha-xyzw-2: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-alpha-xyzw-2))
|
||||
(format #t "~1Tflare-alpha-xyzw-3: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-alpha-xyzw-3))
|
||||
(format #t "~1Tflare-init-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj flare-init-giftag))
|
||||
(format #t "~1Tflare-init-adcmds[8] @ #x~X~%" (-> obj flare-init-adcmds))
|
||||
(format #t "~1Tflare-draw-giftag: #<gs-gif-tag @ #x~X>~%" (-> obj flare-draw-giftag))
|
||||
(format #t "~1Tflare-draw-clr: #<gs-packed-rgba @ #x~X>~%" (-> obj flare-draw-clr))
|
||||
(format #t "~1Tflare-draw-stq-0: #<gs-packed-stq @ #x~X>~%" (-> obj flare-draw-stq-0))
|
||||
(format #t "~1Tflare-draw-xyzw-0: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-draw-xyzw-0))
|
||||
(format #t "~1Tflare-draw-stq-1: #<gs-packed-stq @ #x~X>~%" (-> obj flare-draw-stq-1))
|
||||
(format #t "~1Tflare-draw-xyzw-1: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-draw-xyzw-1))
|
||||
(format #t "~1Tflare-draw-stq-2: #<gs-packed-stq @ #x~X>~%" (-> obj flare-draw-stq-2))
|
||||
(format #t "~1Tflare-draw-xyzw-2: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-draw-xyzw-2))
|
||||
(format #t "~1Tflare-draw-stq-3: #<gs-packed-stq @ #x~X>~%" (-> obj flare-draw-stq-3))
|
||||
(format #t "~1Tflare-draw-xyzw-3: #<gs-packed-xyzw @ #x~X>~%" (-> obj flare-draw-xyzw-3))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition of type sprite-glow-consts
|
||||
(deftype sprite-glow-consts (structure)
|
||||
((camera matrix :inline :offset-assert 0)
|
||||
(perspective matrix :inline :offset-assert 64)
|
||||
(hvdf-offset vector :inline :offset-assert 128)
|
||||
(hmge-scale vector :inline :offset-assert 144)
|
||||
(consts vector :inline :offset-assert 160)
|
||||
(pfog0 float :offset 160)
|
||||
(deg-to-rad float :offset 164)
|
||||
(min-scale float :offset 168)
|
||||
(inv-area float :offset 172)
|
||||
(sincos-01 vector :inline :offset-assert 176)
|
||||
(sincos-23 vector :inline :offset-assert 192)
|
||||
(sincos-45 vector :inline :offset-assert 208)
|
||||
(sincos-67 vector :inline :offset-assert 224)
|
||||
(sincos-89 vector :inline :offset-assert 240)
|
||||
(basis-x vector :inline :offset-assert 256)
|
||||
(basis-y vector :inline :offset-assert 272)
|
||||
(xy-array vector 4 :inline :offset-assert 288)
|
||||
(clamp-min vector :inline :offset-assert 352)
|
||||
(clamp-max vector :inline :offset-assert 368)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x180
|
||||
:flag-assert #x900000180
|
||||
)
|
||||
|
||||
;; definition for method 3 of type sprite-glow-consts
|
||||
(defmethod inspect sprite-glow-consts ((obj sprite-glow-consts))
|
||||
(when (not obj)
|
||||
(set! obj obj)
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'sprite-glow-consts)
|
||||
(format #t "~1Tcamera: #<matrix @ #x~X>~%" (-> obj camera))
|
||||
(format #t "~1Tperspective: #<matrix @ #x~X>~%" (-> obj perspective))
|
||||
(format #t "~1Thvdf-offset: #<vector @ #x~X>~%" (-> obj hvdf-offset))
|
||||
(format #t "~1Thmge-scale: #<vector @ #x~X>~%" (-> obj hmge-scale))
|
||||
(format #t "~1Tconsts: #<vector @ #x~X>~%" (&-> obj pfog0))
|
||||
(format #t "~1Tpfog0: ~f~%" (-> obj pfog0))
|
||||
(format #t "~1Tdeg-to-rad: ~f~%" (-> obj deg-to-rad))
|
||||
(format #t "~1Tmin-scale: ~f~%" (-> obj min-scale))
|
||||
(format #t "~1Tinv-area: ~f~%" (-> obj inv-area))
|
||||
(format #t "~1Tsincos-01: #<vector @ #x~X>~%" (-> obj sincos-01))
|
||||
(format #t "~1Tsincos-23: #<vector @ #x~X>~%" (-> obj sincos-23))
|
||||
(format #t "~1Tsincos-45: #<vector @ #x~X>~%" (-> obj sincos-45))
|
||||
(format #t "~1Tsincos-67: #<vector @ #x~X>~%" (-> obj sincos-67))
|
||||
(format #t "~1Tsincos-89: #<vector @ #x~X>~%" (-> obj sincos-89))
|
||||
(format #t "~1Tbasis-x: #<vector @ #x~X>~%" (-> obj basis-x))
|
||||
(format #t "~1Tbasis-y: #<vector @ #x~X>~%" (-> obj basis-y))
|
||||
(format #t "~1Txy-array[4] @ #x~X~%" (-> obj xy-array))
|
||||
(format #t "~1Tclamp-min: #<vector @ #x~X>~%" (-> obj clamp-min))
|
||||
(format #t "~1Tclamp-max: #<vector @ #x~X>~%" (-> obj clamp-max))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for symbol *sprite-glow-template*, type sprite-glow-template
|
||||
(define *sprite-glow-template*
|
||||
(new 'static 'sprite-glow-template
|
||||
:clear-init-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x5 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:clear-init-adcmds (new 'static 'inline-array gs-adcmd 5
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-1) :x #x6a)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-1) :x #x51001)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-1) :x #x1000130 :y #x1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-1) :x #x80198 :y #xffffff)
|
||||
)
|
||||
:clear-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x2
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type sprite))
|
||||
:nreg #x3
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id rgbaq) :regs1 (gif-reg-id xyzf2) :regs2 (gif-reg-id xyzf2))
|
||||
)
|
||||
:clear-draw-xyz-0 (new 'static 'inline-array gs-packed-xyzw 2
|
||||
(new 'static 'gs-packed-xyzw :iz -1)
|
||||
(new 'static 'gs-packed-xyzw :iz -1)
|
||||
)
|
||||
:clear-draw-clr-1 (new 'static 'gs-packed-rgba :x #xff :w #xff)
|
||||
:offscr-setup-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x8 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:offscr-setup-adcmds (new 'static 'inline-array gs-adcmd 8
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-2) :x #x10090 :y #xffffff)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-2) :x #x1000130)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex1-2) :x #x60)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex0-2) :x #x64023300 :y #xe)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 clamp-2) :x #x5)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x31001)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyoffset-2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
)
|
||||
:offscr-first-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type sprite) :tme #x1 :fst #x1 :ctxt #x1)
|
||||
:nreg #x5
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id uv)
|
||||
:regs2 (gif-reg-id xyz2)
|
||||
:regs3 (gif-reg-id uv)
|
||||
:regs4 (gif-reg-id xyz2)
|
||||
)
|
||||
)
|
||||
:offscr-first-clr (new 'static 'gs-packed-rgba :x #x80 :y #x80 :z #x80 :w #x80)
|
||||
:offscr-first-xyzw-1 (new 'static 'gs-packed-xyzw :ix #x200 :iy #x200)
|
||||
:repeat-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x1d :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:repeat-draw-adcmds (new 'static 'inline-array gs-adcmd 29
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 tex0-2) :x #x54005200 :y #xd)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x2100210)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x1000100)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x1100110)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x800080)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x900090)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x400040)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x100010)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 uv) :x #x500050)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyz2) :x #x200020)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-2) :x #x80198 :y #xffffff)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x51001)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 zbuf-2) :x #x1000130 :y #x1)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 xyoffset-2) :x #x7000 :y #x7300)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 scissor-2) :x #x1ff0000 :y #x19f0000)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 test-2) :x #x50000)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-2) :x #x6a)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
)
|
||||
:flare-alpha-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :tme #x1 :fst #x1 :ctxt #x1)
|
||||
:nreg #x6
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id uv)
|
||||
:regs2 (gif-reg-id xyzf2)
|
||||
:regs3 (gif-reg-id xyzf2)
|
||||
:regs4 (gif-reg-id xyzf2)
|
||||
:regs5 (gif-reg-id xyzf2)
|
||||
)
|
||||
)
|
||||
:flare-alpha-clr (new 'static 'gs-packed-rgba :x #x80 :y #x80 :z #x80 :w #x80)
|
||||
:flare-alpha-uv (new 'static 'gs-packed-uv :x (the-as float #x10) :y (the-as float #x10))
|
||||
:flare-alpha-xyzw-0 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-1 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-2 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-alpha-xyzw-3 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-init-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64 :nloop #x8 :nreg #x1)
|
||||
:regs (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))
|
||||
)
|
||||
:flare-init-adcmds (new 'static 'inline-array gs-adcmd 8
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 texflush))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 frame-1) :x #x80198)
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 hack))
|
||||
(new 'static 'gs-adcmd :cmds (gs-reg64 alpha-1) :x #x58)
|
||||
)
|
||||
:flare-draw-giftag (new 'static 'gs-gif-tag
|
||||
:tag (new 'static 'gif-tag64
|
||||
:nloop #x1
|
||||
:eop #x1
|
||||
:pre #x1
|
||||
:prim (new 'static 'gs-prim :prim (gs-prim-type tri-fan) :tme #x1 :abe #x1)
|
||||
:nreg #x9
|
||||
)
|
||||
:regs (new 'static 'gif-tag-regs
|
||||
:regs0 (gif-reg-id rgbaq)
|
||||
:regs1 (gif-reg-id st)
|
||||
:regs2 (gif-reg-id xyzf2)
|
||||
:regs3 (gif-reg-id st)
|
||||
:regs4 (gif-reg-id xyzf2)
|
||||
:regs5 (gif-reg-id st)
|
||||
:regs6 (gif-reg-id xyzf2)
|
||||
:regs7 (gif-reg-id st)
|
||||
:regs8 (gif-reg-id xyzf2)
|
||||
)
|
||||
)
|
||||
:flare-draw-clr (new 'static 'gs-packed-rgba :y 64 :w #x80)
|
||||
:flare-draw-stq-0 (new 'static 'gs-packed-stq :z 1.0)
|
||||
:flare-draw-xyzw-0 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-1 (new 'static 'gs-packed-stq :x 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-1 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-2 (new 'static 'gs-packed-stq :x 1.0 :y 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-2 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
:flare-draw-stq-3 (new 'static 'gs-packed-stq :y 1.0 :z 1.0)
|
||||
:flare-draw-xyzw-3 (new 'static 'gs-packed-xyzw :iz -1)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for symbol sprite-glow-vu1-block, type vu-function
|
||||
(define sprite-glow-vu1-block (new 'static 'vu-function :length #x86 :qlength 67))
|
||||
|
||||
;; definition for function sprite-glow-init-consts
|
||||
;; INFO: Used lq/sq
|
||||
;; WARN: Return type mismatch vector vs none.
|
||||
(defun sprite-glow-init-consts ((arg0 sprite-glow-consts))
|
||||
(let ((v1-0 *math-camera*))
|
||||
(let* ((t0-0 (-> arg0 camera))
|
||||
(t1-0 (-> v1-0 camera-rot))
|
||||
(a1-0 (-> t1-0 quad 0))
|
||||
(a2-0 (-> t1-0 quad 1))
|
||||
(a3-0 (-> t1-0 quad 2))
|
||||
(t1-1 (-> t1-0 trans quad))
|
||||
)
|
||||
(set! (-> t0-0 quad 0) a1-0)
|
||||
(set! (-> t0-0 quad 1) a2-0)
|
||||
(set! (-> t0-0 quad 2) a3-0)
|
||||
(set! (-> t0-0 trans quad) t1-1)
|
||||
)
|
||||
(let* ((t0-1 (-> arg0 perspective))
|
||||
(t1-2 (-> v1-0 perspective))
|
||||
(a1-1 (-> t1-2 quad 0))
|
||||
(a2-1 (-> t1-2 quad 1))
|
||||
(a3-1 (-> t1-2 quad 2))
|
||||
(t1-3 (-> t1-2 trans quad))
|
||||
)
|
||||
(set! (-> t0-1 quad 0) a1-1)
|
||||
(set! (-> t0-1 quad 1) a2-1)
|
||||
(set! (-> t0-1 quad 2) a3-1)
|
||||
(set! (-> t0-1 trans quad) t1-3)
|
||||
)
|
||||
(set! (-> arg0 hvdf-offset quad) (-> v1-0 hvdf-off quad))
|
||||
(set! (-> arg0 hmge-scale quad) (-> v1-0 hmge-scale quad))
|
||||
(set! (-> arg0 basis-x quad) (the-as uint128 0))
|
||||
(set! (-> arg0 basis-x x) (- (-> *math-camera* perspective vector 0 x)))
|
||||
(set! (-> arg0 basis-y quad) (the-as uint128 0))
|
||||
(set! (-> arg0 basis-y y) (- (-> *math-camera* perspective vector 1 y)))
|
||||
(set! (-> arg0 pfog0) (-> v1-0 pfog0))
|
||||
)
|
||||
(set! (-> arg0 deg-to-rad) 0.000095873795)
|
||||
(set! (-> arg0 min-scale) (sqrtf (* (/ 1.0 (-> arg0 basis-x x)) (/ 1.0 (-> arg0 basis-y y)))))
|
||||
(set! (-> arg0 inv-area) (/ 1.0 (* (-> arg0 min-scale) (-> arg0 min-scale))))
|
||||
(let ((v1-5 (-> arg0 sincos-01)))
|
||||
(set! (-> v1-5 z) 0.999998)
|
||||
(set! (-> v1-5 w) 1.0)
|
||||
)
|
||||
(let ((v1-6 (-> arg0 sincos-23)))
|
||||
(set! (-> v1-6 z) -0.16666014)
|
||||
(set! (-> v1-6 w) -0.49998003)
|
||||
)
|
||||
(let ((v1-7 (-> arg0 sincos-45)))
|
||||
(set! (-> v1-7 z) 0.008326521)
|
||||
(set! (-> v1-7 w) 0.041620404)
|
||||
)
|
||||
(let ((v1-8 (-> arg0 sincos-67)))
|
||||
(set! (-> v1-8 z) -0.0001956241)
|
||||
(set! (-> v1-8 w) -0.0013636408)
|
||||
)
|
||||
(let ((v1-9 (-> arg0 sincos-89)))
|
||||
(set! (-> v1-9 z) 0.0000023042373)
|
||||
(set! (-> v1-9 w) 0.000020170546)
|
||||
)
|
||||
(set-vector! (-> arg0 xy-array 0) -0.5 -0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 1) 0.5 -0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 2) 0.5 0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 xy-array 3) -0.5 0.5 0.0 0.0)
|
||||
(set-vector! (-> arg0 clamp-min) 1792.0 1840.0 0.0 0.0)
|
||||
(set-vector! (-> arg0 clamp-max) 2304.0 2256.0 2048.0 50.0)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function sprite-glow-init-engine
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
(defun sprite-glow-init-engine ((arg0 dma-buffer))
|
||||
(dma-buffer-add-vu-function arg0 sprite-glow-vu1-block 1)
|
||||
(let ((s5-0 24))
|
||||
(let* ((v1-0 arg0)
|
||||
(a0-2 (the-as dma-packet (-> v1-0 base)))
|
||||
)
|
||||
(set! (-> a0-2 dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s5-0))
|
||||
(set! (-> a0-2 vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> a0-2 vif1) (new 'static 'vif-tag :imm #x3d4 :cmd (vif-cmd unpack-v4-32) :num s5-0))
|
||||
(set! (-> v1-0 base) (the-as pointer (&+ a0-2 16)))
|
||||
)
|
||||
(sprite-glow-init-consts (the-as sprite-glow-consts (-> arg0 base)))
|
||||
(&+! (-> arg0 base) (* s5-0 16))
|
||||
)
|
||||
(let ((v1-3 84))
|
||||
(let* ((a0-6 arg0)
|
||||
(a1-6 (the-as dma-packet (-> a0-6 base)))
|
||||
)
|
||||
(set! (-> a1-6 dma)
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref) :addr (the-as int *sprite-glow-template*) :qwc v1-3)
|
||||
)
|
||||
(set! (-> a1-6 vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
|
||||
(set! (-> a1-6 vif1) (new 'static 'vif-tag :imm #x320 :cmd (vif-cmd unpack-v4-32) :num v1-3))
|
||||
(set! (-> a0-6 base) (the-as pointer (&+ a1-6 16)))
|
||||
)
|
||||
(let* ((a0-7 arg0)
|
||||
(a1-8 (the-as dma-packet (-> a0-7 base)))
|
||||
)
|
||||
(set! (-> a1-8 dma)
|
||||
(new 'static 'dma-tag :id (dma-tag-id ref) :addr (the-as int *sprite-glow-template*) :qwc v1-3)
|
||||
)
|
||||
(set! (-> a1-8 vif0) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x0))
|
||||
(set! (-> a1-8 vif1) (new 'static 'vif-tag :imm #x374 :cmd (vif-cmd unpack-v4-32) :num v1-3))
|
||||
(set! (-> a0-7 base) (the-as pointer (&+ a1-8 16)))
|
||||
)
|
||||
)
|
||||
(let* ((v1-8 arg0)
|
||||
(a0-8 (the-as dma-packet (-> v1-8 base)))
|
||||
)
|
||||
(set! (-> a0-8 dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> a0-8 vif0) (new 'static 'vif-tag :cmd (vif-cmd base)))
|
||||
(set! (-> a0-8 vif1) (new 'static 'vif-tag :imm #x190 :cmd (vif-cmd offset)))
|
||||
(set! (-> v1-8 base) (the-as pointer (&+ a0-8 16)))
|
||||
)
|
||||
(let ((v1-9 (the-as dma-packet (-> arg0 base))))
|
||||
(set! (-> v1-9 dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
(set! (-> v1-9 vif0) (new 'static 'vif-tag))
|
||||
(set! (-> v1-9 vif1) (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-9 16)))
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition of type sprite-glow-dma-packet-data
|
||||
(deftype sprite-glow-dma-packet-data (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 16)
|
||||
(shader-cnt-packet dma-packet :inline :offset-assert 32)
|
||||
(shader-ref-packet dma-packet :inline :offset-assert 48)
|
||||
(mscal-packet dma-packet :inline :offset-assert 64)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x50
|
||||
:flag-assert #x900000050
|
||||
)
|
||||
|
||||
;; definition for method 3 of type sprite-glow-dma-packet-data
|
||||
(defmethod inspect sprite-glow-dma-packet-data ((obj sprite-glow-dma-packet-data))
|
||||
(when (not obj)
|
||||
(set! obj obj)
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'sprite-glow-dma-packet-data)
|
||||
(format #t "~1Tcontrol-packet: #<dma-packet @ #x~X>~%" (-> obj control-packet))
|
||||
(format #t "~1Tvecdata-packet: #<dma-packet @ #x~X>~%" (-> obj vecdata-packet))
|
||||
(format #t "~1Tshader-cnt-packet: #<dma-packet @ #x~X>~%" (-> obj shader-cnt-packet))
|
||||
(format #t "~1Tshader-ref-packet: #<dma-packet @ #x~X>~%" (-> obj shader-ref-packet))
|
||||
(format #t "~1Tmscal-packet: #<dma-packet @ #x~X>~%" (-> obj mscal-packet))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition of type sprite-glow-cnt-template
|
||||
(deftype sprite-glow-cnt-template (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
(shader adgif-shader :inline :offset-assert 128)
|
||||
(mscal-packet dma-packet :inline :offset-assert 208)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #xe0
|
||||
:flag-assert #x9000000e0
|
||||
)
|
||||
|
||||
;; definition for method 3 of type sprite-glow-cnt-template
|
||||
(defmethod inspect sprite-glow-cnt-template ((obj sprite-glow-cnt-template))
|
||||
(when (not obj)
|
||||
(set! obj obj)
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'sprite-glow-cnt-template)
|
||||
(format #t "~1Tcontrol-packet: #<dma-packet @ #x~X>~%" (-> obj control-packet))
|
||||
(format #t "~1Tnum-sprites: ~D~%" (-> obj num-sprites))
|
||||
(format #t "~1Tdummys[3] @ #x~X~%" (-> obj dummys))
|
||||
(format #t "~1Tvecdata-packet: #<dma-packet @ #x~X>~%" (-> obj vecdata-packet))
|
||||
(format #t "~1Tvecdata: #<sprite-glow-data @ #x~X>~%" (-> obj vecdata))
|
||||
(format #t "~1Tshader-packet: #<dma-packet @ #x~X>~%" (-> obj shader-packet))
|
||||
(format #t "~1Tshader: #<adgif-shader @ #x~X>~%" (-> obj shader))
|
||||
(format #t "~1Tmscal-packet: #<dma-packet @ #x~X>~%" (-> obj mscal-packet))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition of type sprite-glow-ref-template
|
||||
(deftype sprite-glow-ref-template (structure)
|
||||
((control-packet dma-packet :inline :offset-assert 0)
|
||||
(num-sprites uint32 :offset-assert 16)
|
||||
(dummys uint32 3 :offset-assert 20)
|
||||
(num-sprites-quad uint128 :offset 16)
|
||||
(vecdata-packet dma-packet :inline :offset-assert 32)
|
||||
(vecdata sprite-glow-data :inline :offset-assert 48)
|
||||
(shader-packet dma-packet :inline :offset-assert 112)
|
||||
(shader-packet-ptr pointer :offset 116)
|
||||
(mscal-packet dma-packet :inline :offset-assert 128)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x90
|
||||
:flag-assert #x900000090
|
||||
)
|
||||
|
||||
;; definition for method 3 of type sprite-glow-ref-template
|
||||
(defmethod inspect sprite-glow-ref-template ((obj sprite-glow-ref-template))
|
||||
(when (not obj)
|
||||
(set! obj obj)
|
||||
(goto cfg-4)
|
||||
)
|
||||
(format #t "[~8x] ~A~%" obj 'sprite-glow-ref-template)
|
||||
(format #t "~1Tcontrol-packet: #<dma-packet @ #x~X>~%" (-> obj control-packet))
|
||||
(format #t "~1Tnum-sprites: ~D~%" (-> obj num-sprites))
|
||||
(format #t "~1Tdummys[3] @ #x~X~%" (-> obj dummys))
|
||||
(format #t "~1Tvecdata-packet: #<dma-packet @ #x~X>~%" (-> obj vecdata-packet))
|
||||
(format #t "~1Tvecdata: #<sprite-glow-data @ #x~X>~%" (-> obj vecdata))
|
||||
(format #t "~1Tshader-packet: #<dma-packet @ #x~X>~%" (-> obj shader-packet))
|
||||
(format #t "~1Tmscal-packet: #<dma-packet @ #x~X>~%" (-> obj mscal-packet))
|
||||
(label cfg-4)
|
||||
obj
|
||||
)
|
||||
|
||||
;; definition for symbol *sprite-glow-dma-packet-data*, type sprite-glow-dma-packet-data
|
||||
(define *sprite-glow-dma-packet-data*
|
||||
(new 'static 'sprite-glow-dma-packet-data
|
||||
:control-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x1 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8000 :num #x1 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:vecdata-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x4 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8001 :num #x4 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:shader-cnt-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x5 :id (dma-tag-id cnt))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8091 :num #x5 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:shader-ref-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :qwc #x5 :id (dma-tag-id ref))
|
||||
:vif0 (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))
|
||||
:vif1 (new 'static 'vif-tag :imm #x8091 :num #x5 :cmd (vif-cmd unpack-v4-32))
|
||||
)
|
||||
:mscal-packet (new 'static 'dma-packet
|
||||
:dma (new 'static 'dma-tag :id (dma-tag-id cnt))
|
||||
:vif1 (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; failed to figure out what this is:
|
||||
(set! (-> *sprite-glow-dma-packet-data* mscal-packet vif0)
|
||||
(new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #xa)
|
||||
)
|
||||
|
||||
;; definition for function sprite-glow-add-sprite
|
||||
;; INFO: Used lq/sq
|
||||
;; WARN: Return type mismatch sprite-glow-cnt-template vs none.
|
||||
(defun sprite-glow-add-sprite ((arg0 dma-buffer) (arg1 sprite-vec-data-2d) (arg2 float) (arg3 float) (arg4 float) (arg5 adgif-shader))
|
||||
(let ((v1-0 (the-as sprite-glow-cnt-template (-> arg0 base))))
|
||||
(let* ((t5-0 *sprite-glow-dma-packet-data*)
|
||||
(t2-0 (-> t5-0 control-packet quad))
|
||||
(t3-0 (-> t5-0 vecdata-packet quad))
|
||||
(t4-0 (-> t5-0 shader-cnt-packet quad))
|
||||
(t5-1 (-> t5-0 mscal-packet quad))
|
||||
)
|
||||
(set! (-> v1-0 control-packet quad) t2-0)
|
||||
(set! (-> v1-0 num-sprites-quad) (the-as uint128 0))
|
||||
(set! (-> v1-0 vecdata-packet quad) t3-0)
|
||||
(set! (-> v1-0 shader-packet quad) t4-0)
|
||||
(set! (-> v1-0 mscal-packet quad) t5-1)
|
||||
)
|
||||
(let ((t2-1 (-> arg1 x-y-z-sx quad))
|
||||
(t3-1 (-> arg1 flag-rot-sy quad))
|
||||
(a1-1 (-> arg1 r-g-b-a quad))
|
||||
)
|
||||
(set! (-> v1-0 vecdata position quad) t2-1)
|
||||
(set! (-> v1-0 vecdata quads 1 quad) t3-1)
|
||||
(set! (-> v1-0 vecdata color quad) a1-1)
|
||||
)
|
||||
(let ((a1-2 1))
|
||||
(set! (-> v1-0 vecdata z-offset) arg4)
|
||||
(set! (-> v1-0 vecdata fade-a) arg2)
|
||||
(set! (-> v1-0 vecdata fade-b) arg3)
|
||||
(set! (-> v1-0 num-sprites) (the-as uint a1-2))
|
||||
)
|
||||
(let ((a1-3 (-> arg5 quad 0 quad))
|
||||
(a2-1 (-> arg5 quad 1 quad))
|
||||
(a3-1 (-> arg5 quad 2 quad))
|
||||
(t0-1 (-> arg5 quad 3 quad))
|
||||
(t1-1 (-> arg5 quad 4 quad))
|
||||
)
|
||||
(set! (-> v1-0 shader quad 0 quad) a1-3)
|
||||
(set! (-> v1-0 shader quad 1 quad) a2-1)
|
||||
(set! (-> v1-0 shader quad 2 quad) a3-1)
|
||||
(set! (-> v1-0 shader quad 3 quad) t0-1)
|
||||
(set! (-> v1-0 shader quad 4 quad) t1-1)
|
||||
)
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-0 224)))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function sprite-glow-add-simple-sprite
|
||||
;; INFO: Used lq/sq
|
||||
;; WARN: Return type mismatch sprite-glow-ref-template vs none.
|
||||
(defun sprite-glow-add-simple-sprite ((arg0 dma-buffer) (arg1 sprite-glow-dma-packet-data) (arg2 sprite-glow-data) (arg3 pointer))
|
||||
(let ((v1-0 (the-as sprite-glow-ref-template (-> arg0 base))))
|
||||
(let ((t0-0 (-> arg1 control-packet quad))
|
||||
(t1-0 (-> arg1 vecdata-packet quad))
|
||||
(t2-0 (-> arg1 shader-ref-packet quad))
|
||||
(a1-1 (-> arg1 mscal-packet quad))
|
||||
)
|
||||
(set! (-> v1-0 control-packet quad) t0-0)
|
||||
(set! (-> v1-0 num-sprites-quad) (the-as uint128 0))
|
||||
(set! (-> v1-0 vecdata-packet quad) t1-0)
|
||||
(set! (-> v1-0 shader-packet quad) t2-0)
|
||||
(set! (-> v1-0 mscal-packet quad) a1-1)
|
||||
)
|
||||
(let ((a1-2 (-> arg2 position quad))
|
||||
(t0-1 (-> arg2 quads 1 quad))
|
||||
(t1-1 (-> arg2 color quad))
|
||||
(a2-1 (-> arg2 quads 3 quad))
|
||||
(t2-1 1)
|
||||
)
|
||||
(set! (-> v1-0 vecdata position quad) a1-2)
|
||||
(set! (-> v1-0 vecdata quads 1 quad) t0-1)
|
||||
(set! (-> v1-0 vecdata color quad) t1-1)
|
||||
(set! (-> v1-0 vecdata quads 3 quad) a2-1)
|
||||
(set! (-> v1-0 num-sprites) (the-as uint t2-1))
|
||||
)
|
||||
(set! (-> v1-0 shader-packet-ptr) arg3)
|
||||
(set! (-> arg0 base) (the-as pointer (&+ v1-0 144)))
|
||||
)
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function sprite-glow-draw
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
(defun sprite-glow-draw ((arg0 dma-buffer))
|
||||
(local-vars (a2-0 float))
|
||||
(let* ((s5-0 *sprite-aux-list*)
|
||||
(s4-0 (-> s5-0 entry))
|
||||
(s3-0 #f)
|
||||
)
|
||||
(dotimes (s2-0 s4-0)
|
||||
(let ((v1-2 (-> s5-0 data s2-0)))
|
||||
(when (and (not s3-0) (= (-> v1-2 aux-type) (sprite-aux-type glow)))
|
||||
(let* ((a0-5 (-> v1-2 aux-data omega))
|
||||
(a3-0 (cond
|
||||
((zero? a0-5)
|
||||
(set! a2-0 0.0)
|
||||
1.0
|
||||
)
|
||||
(else
|
||||
(let* ((f1-1 (* 0.00024414062 a0-5))
|
||||
(f0-4 (- f1-1 (the float (the int f1-1))))
|
||||
)
|
||||
(let ((f1-3 (* 4096.0 (- f1-1 f0-4))))
|
||||
(set! a2-0 (/ -1.0 (* (- 1.0 f0-4) f1-3)))
|
||||
)
|
||||
(/ f0-4 (- 1.0 f0-4))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(sprite-glow-add-sprite arg0 (-> v1-2 vec-data) a2-0 a3-0 (-> v1-2 aux-data user-float) (-> v1-2 gif-data))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 9 of type simple-sprite-system
|
||||
;; INFO: Used lq/sq
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
(defmethod add! simple-sprite-system ((obj simple-sprite-system) (arg0 sprite-glow-data))
|
||||
(let ((v1-0 (-> obj count)))
|
||||
(when (< v1-0 (-> obj max-count))
|
||||
(let* ((a2-3 (-> obj data v1-0))
|
||||
(v1-2 arg0)
|
||||
(a1-1 a2-3)
|
||||
(a2-4 (-> v1-2 position quad))
|
||||
(a3-0 (-> v1-2 quads 1 quad))
|
||||
(t0-0 (-> v1-2 color quad))
|
||||
(v1-3 (-> v1-2 quads 3 quad))
|
||||
)
|
||||
(set! (-> a1-1 position quad) a2-4)
|
||||
(set! (-> a1-1 quads 1 quad) a3-0)
|
||||
(set! (-> a1-1 color quad) t0-0)
|
||||
(set! (-> a1-1 quads 3 quad) v1-3)
|
||||
)
|
||||
(+! (-> obj count) 1)
|
||||
)
|
||||
)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for function add-shader-to-dma
|
||||
;; INFO: Used lq/sq
|
||||
;; WARN: Return type mismatch pointer vs adgif-shader.
|
||||
(defun add-shader-to-dma ((arg0 dma-buffer))
|
||||
(let* ((a1-0 (new 'static 'dma-packet :dma (new 'static 'dma-tag :id (dma-tag-id next))))
|
||||
(v1-0 (-> arg0 base))
|
||||
(a1-1 (-> a1-0 quad))
|
||||
(v0-0 (&+ v1-0 16))
|
||||
)
|
||||
(let ((a2-0 (&+ v1-0 96)))
|
||||
(set! (-> (the-as (pointer uint128) v1-0)) a1-1)
|
||||
(set! (-> (the-as (pointer uint32) v1-0) 1) (the-as uint a2-0))
|
||||
(set! (-> arg0 base) a2-0)
|
||||
)
|
||||
(the-as adgif-shader v0-0)
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for method 10 of type simple-sprite-system
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
(defmethod draw-all-sprites! simple-sprite-system ((obj simple-sprite-system) (arg0 dma-buffer))
|
||||
(local-vars (sv-528 sprite-glow-dma-packet-data) (sv-532 (pointer texture-id)) (sv-536 pointer))
|
||||
(b! (zero? (-> obj count)) cfg-13 :delay (nop!))
|
||||
(set! sv-528 *sprite-glow-dma-packet-data*)
|
||||
(set! sv-532 (new 'stack-no-clear 'array 'texture-id 128))
|
||||
(set! sv-536 (-> arg0 base))
|
||||
(dotimes (v1-5 (-> obj count))
|
||||
(set! (-> sv-532 v1-5) (-> obj data v1-5 tex-id))
|
||||
)
|
||||
(countdown (s4-0 (-> obj count))
|
||||
(let ((s3-0 (-> sv-532 s4-0)))
|
||||
(when (nonzero? s3-0)
|
||||
(let ((s2-0 (add-shader-to-dma arg0)))
|
||||
(adgif-shader<-texture-simple! s2-0 (lookup-texture-by-id s3-0))
|
||||
(countdown (s1-1 (+ s4-0 1))
|
||||
(when (= s3-0 (-> sv-532 s1-1))
|
||||
(set! (-> sv-532 s1-1) (new 'static 'texture-id))
|
||||
(let ((a2-1 (-> obj data s1-1)))
|
||||
(sprite-glow-add-simple-sprite arg0 sv-528 a2-1 (the-as pointer s2-0))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(label cfg-13)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for method 11 of type simple-sprite-system
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
(defmethod clear! simple-sprite-system ((obj simple-sprite-system))
|
||||
(set! (-> obj count) 0)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
;; definition for symbol *simple-sprite-system*, type simple-sprite-system
|
||||
(define *simple-sprite-system*
|
||||
(new 'static 'simple-sprite-system :max-count #x80 :data (new 'static 'inline-array sprite-glow-data 128
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
(new 'static 'sprite-glow-data)
|
||||
)
|
||||
)
|
||||
)
|
5
test/decompiler/reference/jak2/engine/gfx/sprite/sprite_REF.gc
generated
vendored
5
test/decompiler/reference/jak2/engine/gfx/sprite/sprite_REF.gc
generated
vendored
@ -791,8 +791,7 @@
|
||||
|
||||
;; definition for function sprite-draw
|
||||
;; WARN: Return type mismatch int vs none.
|
||||
;; WARN: Failed store: (s.w! (+ v1-27 8) 0) at op 160
|
||||
;; WARN: Failed store: (s.w! (+ v1-27 12) 0) at op 161
|
||||
;; ERROR: Failed store: (s.w! (+ v1-27 8) 0) at op 160
|
||||
(defun sprite-draw ((disp display))
|
||||
(let ((dma-mem-begin (-> *display* frames (-> *display* on-screen) global-buf base)))
|
||||
(with-dma-buffer-add-bucket ((dma-buff (-> *display* frames (-> *display* on-screen) global-buf))
|
||||
@ -878,7 +877,7 @@
|
||||
)
|
||||
(sprite-glow-init-engine dma-buff)
|
||||
(sprite-glow-draw dma-buff)
|
||||
(simple-sprite-system-method-10 *simple-sprite-system* dma-buff)
|
||||
(draw-all-sprites! *simple-sprite-system* dma-buff)
|
||||
(let ((v1-26 dma-buff))
|
||||
(let ((pkt6 (the-as dma-packet (-> v1-26 base))))
|
||||
(set! (-> pkt6 dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
||||
|
8
test/decompiler/reference/jak2/levels/city/common/vehicle-effects_REF.gc
generated
vendored
8
test/decompiler/reference/jak2/levels/city/common/vehicle-effects_REF.gc
generated
vendored
@ -273,7 +273,7 @@
|
||||
(set! (-> s3-1 1 normal w) f0-14)
|
||||
(set! (-> s3-1 1 normal x) (* 0.025 f0-14))
|
||||
)
|
||||
(add! *simple-sprite-system* (the-as dma-buffer (-> s3-1 1)))
|
||||
(add! *simple-sprite-system* (the-as sprite-glow-data (-> s3-1 1)))
|
||||
(forward-up->quaternion (the-as quaternion (-> s3-1 0)) arg1 (the-as vector (-> obj rbody state matrix)))
|
||||
(quaternion-rotate-local-x! (the-as quaternion (-> s3-1 0)) (the-as quaternion (-> s3-1 0)) 32768.0)
|
||||
(let ((v1-16 (-> s3-1 0 normal)))
|
||||
@ -390,7 +390,7 @@
|
||||
(set! (-> s4-0 color x) 255.0)
|
||||
(set! (-> s4-0 color y) (rand-vu-float-range 192.0 255.0))
|
||||
(set! (-> s4-0 color w) (* f30-1 (rand-vu-float-range 16.0 18.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-0))
|
||||
(add! *simple-sprite-system* s4-0)
|
||||
(let ((f0-21 (-> obj camera-dist2))
|
||||
(f1-6 245760.0)
|
||||
)
|
||||
@ -403,7 +403,7 @@
|
||||
(set! (-> s4-0 fade-b) 2.3332994)
|
||||
(set! (-> s4-0 color z) (rand-vu-float-range 128.0 160.0))
|
||||
(set! (-> s4-0 color w) (* f30-1 (rand-vu-float-range 32.0 36.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-0))
|
||||
(add! *simple-sprite-system* s4-0)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -423,7 +423,7 @@
|
||||
(set! (-> s4-1 rot-angle) (* 182.04445 (rand-vu-float-range -4.0 4.0)))
|
||||
(set! (-> s4-1 color y) (* 64.0 (rand-vu)))
|
||||
(set! (-> s4-1 color w) (* f30-1 (rand-vu-float-range 16.0 21.0)))
|
||||
(add! *simple-sprite-system* (the-as dma-buffer s4-1))
|
||||
(add! *simple-sprite-system* s4-1)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user