MW2 Rendering

From COD Engine Research

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, LEQUAL

Render 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(BaseAsset *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 Silk/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 commands

Xbox 360

n/a