1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/**
* This file implements a framebuffer effect relying on the depth buffer (Z buffer).
* It merely allows LERPing between two colors (from color2 to color1), using the Z buffer bytes (interpreted as either
* ia16 or rgba16 depending on the type being 0 or not) as the factor.
*
* Z buffer values are two bytes each. They are floating point, which makes the effect not that interesting for an
* actual application as that doesn't map well to be interpreted as ia16 or rgba16, though some discontinuous gradients
* can be seen.
*
* The bit layout of Z buffer values is:
* 0bEEEM_MMMM_MMMM_MMDD
* Where E is the 3 exponent bits, M is the 11 mantissa bits,
* and D is 2 of the 4 dz value bits (the remaining two are stored in the "hidden" 9th bit of each byte).
* In 3D space, Z values increase from front (near plane) to back (far plane).
*
* Interpreted as ia16:
* 0bIIII_IIII_AAAA_AAAA
* The intensity channel takes its value from the exponent bits and the high mantissa bits, so it continuously increases
* from front to back.
* The alpha channel mostly takes its value from the lowest mantissa bits, so it increases from front to back but also
* rolls over frequently.
* This can be observed in-game by setting color1 to white and color2 to black.
* From front to back, the intensity gradient is a continuous increase.
* The alpha is ignored due to the render mode VisZBuffer uses.
*
* Interpreted as rgba16:
* 0bRRRR_RGGG_GGBB_BBBA
* The red channel mostly takes its value from the exponent bits, so it continuously increases from front to back.
* The green channel takes its value from the middle mantissa bits, so it increases from front to back but also rolls
* over frequently.
* The blue channel mostly takes its value from the lowest mantissa bits, so it increases from front to back and also
* rolls over even more frequently.
* This can be observed in-game by setting color1 to white and color2 to black.
* From front to back, the gradients for each color channel are then:
* - red: continuous increase
* - green: discontinuous succession of continuous increases
* - blue: like green but even higher frequency
*/
#include "vis.h"
#include "color.h"
#include "gfx.h"
#include "ultra64.h"
#include <stdbool.h>
// z-buffer
extern u16 D_0E000000[];
void VisZBuffer_Init(VisZBuffer* this) {
this->params.type = 0;
this->params.setScissor = false;
this->params.color1.r = 255;
this->params.color1.g = 255;
this->params.color1.b = 255;
this->params.color1.a = 255;
// clang-format off
this->params.color2.r = 0; \
this->params.color2.g = 0; \
this->params.color2.b = 0; \
this->params.color2.a = 255;
// clang-format on
}
void VisZBuffer_Destroy(VisZBuffer* this) {
}
void VisZBuffer_Draw(VisZBuffer* this, Gfx** gfxP) {
Gfx* gfx = *gfxP;
s32 pad;
u16* tex = D_0E000000;
s32 fmt = this->params.type == 0 ? G_IM_FMT_IA : G_IM_FMT_RGBA;
s32 y;
s32 height = TMEM_SIZE / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES);
gDPPipeSync(gfx++);
if (this->params.setScissor == true) {
gDPSetScissor(gfx++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
gDPSetOtherMode(gfx++,
G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2);
gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT);
gDPSetColor(gfx++, G_SETPRIMCOLOR, this->params.color1.rgba);
gDPSetColor(gfx++, G_SETENVCOLOR, this->params.color2.rgba);
for (y = 0; y <= SCREEN_HEIGHT - height; y += height) {
gDPLoadTextureBlock(gfx++, tex, fmt, G_IM_SIZ_16b, SCREEN_WIDTH, height, 0, G_TX_NOMIRROR | G_TX_CLAMP,
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPTextureRectangle(gfx++, 0, y << 2, SCREEN_WIDTH << 2, (y + height) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10,
1 << 10);
tex += SCREEN_WIDTH * height;
}
gDPPipeSync(gfx++);
*gfxP = gfx;
}
|