MW2 Rendering
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