MW2 Rendering: Difference between revisions
| (One intermediate revision by the same user not shown) | |||
| Line 48: | Line 48: | ||
Compare funcs: NEVER, LESS, EQUAL, LEQUAL, GREATER, NOTEQUAL, GEQUAL, ALWAYS | Compare funcs: NEVER, LESS, EQUAL, LEQUAL, GREATER, NOTEQUAL, GEQUAL, ALWAYS | ||
Depth funcs seen: ALWAYS, LESS, EQUAL, LEQUAL | Depth funcs seen: ALWAYS, LESS, EQUAL, LEQUAL | ||
</syntaxhighlight> | |||
=== Render Side Usage === | |||
<syntaxhighlight lang="C"> | |||
typedef struct RsxCommand { | |||
unsigned int method; | |||
unsigned int value; | |||
const char *name; // correlated display/debug name | |||
} RsxCommand; | |||
static const GfxStateBits *SelectStateBits( | |||
const MaterialAsset *material, | |||
int techniqueSlot) | |||
{ | |||
for (int i = 0; i < 37; i++) { | |||
MaterialStateBitsEntry e = material->stateBitsEntries[i]; | |||
if (e.techniqueSlot == techniqueSlot && | |||
e.stateBitsIndex < material->stateBitsCount) { | |||
return &material->stateBits[e.stateBitsIndex]; | |||
} | |||
} | |||
return 0; | |||
} | |||
static int DecodeMaterialStateBits( | |||
const GfxStateBits *state, | |||
RsxCommand *out, | |||
int maxOut) | |||
{ | |||
int n = 0; | |||
unsigned int word0 = state->loadBits[0]; | |||
unsigned int word1 = state->loadBits[1]; | |||
// The exact bit extraction still needs to be completed from PS3 traces. | |||
// These are examples of the bridge destination methods, not final masks. | |||
out[n++] = (RsxCommand){ | |||
.method = 0x0324, | |||
.value = /* decoded color mask from word0 */ 0xf, | |||
.name = "NV30_3D_COLOR_MASK" | |||
}; | |||
out[n++] = (RsxCommand){ | |||
.method = 0x0A74, | |||
.value = /* decoded depth-test enable from word1 */ 1, | |||
.name = "NV30_3D_DEPTH_TEST_ENABLE" | |||
}; | |||
out[n++] = (RsxCommand){ | |||
.method = 0x0A6C, | |||
.value = /* lookup decoded depth func */ 0x0201, | |||
.name = "NV30_3D_DEPTH_FUNC" | |||
}; | |||
out[n++] = (RsxCommand){ | |||
.method = 0x0310, | |||
.value = /* decoded blend enable from word0 */ 0, | |||
.name = "NV30_3D_BLEND_FUNC_ENABLE" | |||
}; | |||
return n; | |||
} | |||
void DrawGfxWorld(XAsset *asset) | |||
{ | |||
if (!asset || asset->kind != ASSET_GFX_WORLD) | |||
return; | |||
GfxWorldAsset *world = (GfxWorldAsset *)asset; | |||
for (unsigned int i = 0; i < world->surfaceCount; i++) { | |||
GfxSurface *surface = &world->surfaces[i]; | |||
MaterialAsset *material = surface->material; | |||
if (!material) | |||
continue; | |||
int techniqueSlot = 0; // selected by draw path/pass | |||
const GfxStateBits *state = SelectStateBits(material, techniqueSlot); | |||
if (state) { | |||
RsxCommand cmds[64]; | |||
int count = DecodeMaterialStateBits(state, cmds, 64); | |||
for (int c = 0; c < count; c++) { | |||
// In the real renderer this becomes OpenGL state, | |||
// but the RSX command/value remains the source of truth. | |||
ApplyOrRecordRsxCommand(cmds[c].method, cmds[c].value, cmds[c].name); | |||
} | |||
} | |||
DrawSurfaceGeometry(surface, material); | |||
} | |||
} | |||
</syntaxhighlight> | |||
The key relationship is: | |||
<syntaxhighlight> | |||
GfxWorldAsset | |||
-> GfxSurface | |||
-> MaterialAsset | |||
-> technique slot | |||
-> GfxStateBits row | |||
-> raw loadBits | |||
-> RSX/NV4097 commands | |||
</syntaxhighlight> | </syntaxhighlight> | ||
== Xbox 360 == | == Xbox 360 == | ||
<code>n/a</code> | <code>n/a</code> | ||
Latest revision as of 18:42, 5 July 2026
Rendering
This section is to give you information on how to render surfaces, triangles, maps and apply texture blends and material technique sets per platform.
Playstation 3
The ps3 uses a different translation due to it's RSX chip.
RSX Method Names
Mapped material-state methods:
- NV30_3D_COLOR_MASK
- NV30_3D_ALPHA_FUNC_ENABLE
- NV30_3D_ALPHA_FUNC_FUNC
- NV30_3D_ALPHA_FUNC_REF
- NV30_3D_CULL_FACE_ENABLE
- NV30_3D_CULL_FACE
- NV30_3D_POLYGON_MODE_FRONT
- NV30_3D_POLYGON_MODE_BACK
- NV30_3D_BLEND_FUNC_ENABLE
- NV40_3D_BLEND_EQUATION
- NV30_3D_BLEND_FUNC_SRC
- NV30_3D_BLEND_FUNC_DST
- NV30_3D_DEPTH_WRITE_ENABLE
- NV30_3D_DEPTH_TEST_ENABLE
- NV30_3D_DEPTH_FUNC
- NV30_3D_POLYGON_OFFSET_FILL_ENABLE
- NV30_3D_POLYGON_OFFSET_FACTOR
- NV30_3D_POLYGON_OFFSET_UNITS
- NV30_3D_STENCIL_ENABLE
- NV30_3D_STENCIL_OP_FAIL/ZFAIL/ZPASS
- NV30_3D_STENCIL_FUNC_FUNC
Texture/program names:
- NV30_3D_TEX_OFFSET
- NV30_3D_TEX_FORMAT
- NV30_3D_TEX_NPOT_SIZE
- NV40_3D_TEX_SIZE1
- NV30_3D_TEX_SWIZZLE
- NV30_3D_TEX_ENABLE
- NV30_3D_TEX_FILTER
- NV30_3D_TEX_WRAP
- NV30_3D_FP_ACTIVE_PROGRAM
Enum/Payload Names
From the TOC[-0x7174] lookup table:
Blend equation: FUNC_ADD, FUNC_SUBTRACT, FUNC_REVERSE_SUBTRACT, MIN, MAX
Blend factors: SRC_COLOR, ONE_MINUS_SRC_COLOR, SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, DST_COLOR, ONE_MINUS_DST_COLOR
Stencil ops: KEEP, REPLACE, INCR, DECR, INVERT, INCR_WRAP, DECR_WRAP
Compare funcs: NEVER, LESS, EQUAL, LEQUAL, GREATER, NOTEQUAL, GEQUAL, ALWAYS
Depth funcs seen: ALWAYS, LESS, EQUAL, LEQUALRender Side Usage
typedef struct RsxCommand {
unsigned int method;
unsigned int value;
const char *name; // correlated display/debug name
} RsxCommand;
static const GfxStateBits *SelectStateBits(
const MaterialAsset *material,
int techniqueSlot)
{
for (int i = 0; i < 37; i++) {
MaterialStateBitsEntry e = material->stateBitsEntries[i];
if (e.techniqueSlot == techniqueSlot &&
e.stateBitsIndex < material->stateBitsCount) {
return &material->stateBits[e.stateBitsIndex];
}
}
return 0;
}
static int DecodeMaterialStateBits(
const GfxStateBits *state,
RsxCommand *out,
int maxOut)
{
int n = 0;
unsigned int word0 = state->loadBits[0];
unsigned int word1 = state->loadBits[1];
// The exact bit extraction still needs to be completed from PS3 traces.
// These are examples of the bridge destination methods, not final masks.
out[n++] = (RsxCommand){
.method = 0x0324,
.value = /* decoded color mask from word0 */ 0xf,
.name = "NV30_3D_COLOR_MASK"
};
out[n++] = (RsxCommand){
.method = 0x0A74,
.value = /* decoded depth-test enable from word1 */ 1,
.name = "NV30_3D_DEPTH_TEST_ENABLE"
};
out[n++] = (RsxCommand){
.method = 0x0A6C,
.value = /* lookup decoded depth func */ 0x0201,
.name = "NV30_3D_DEPTH_FUNC"
};
out[n++] = (RsxCommand){
.method = 0x0310,
.value = /* decoded blend enable from word0 */ 0,
.name = "NV30_3D_BLEND_FUNC_ENABLE"
};
return n;
}
void DrawGfxWorld(XAsset *asset)
{
if (!asset || asset->kind != ASSET_GFX_WORLD)
return;
GfxWorldAsset *world = (GfxWorldAsset *)asset;
for (unsigned int i = 0; i < world->surfaceCount; i++) {
GfxSurface *surface = &world->surfaces[i];
MaterialAsset *material = surface->material;
if (!material)
continue;
int techniqueSlot = 0; // selected by draw path/pass
const GfxStateBits *state = SelectStateBits(material, techniqueSlot);
if (state) {
RsxCommand cmds[64];
int count = DecodeMaterialStateBits(state, cmds, 64);
for (int c = 0; c < count; c++) {
// In the real renderer this becomes OpenGL state,
// but the RSX command/value remains the source of truth.
ApplyOrRecordRsxCommand(cmds[c].method, cmds[c].value, cmds[c].name);
}
}
DrawSurfaceGeometry(surface, material);
}
}The key relationship is:
GfxWorldAsset
-> GfxSurface
-> MaterialAsset
-> technique slot
-> GfxStateBits row
-> raw loadBits
-> RSX/NV4097 commandsXbox 360
n/a