Hey y'all,
This is my first tutorial in a long time, so comment below and let me know what you think.

Preable
The worst part about developing a rendering based Tool(d3d, opengl, etc) is figuring out what's what in the scene. A few different methods exist, each with their advantages and disadvantages. The two most popular are Vertex Counts and Texture CRCs.

Vertex counts pros
- simple to find
- simple to make

Vertex counts cons
- time consuming
- dependent on individuals settings (rendering quality)
- dependent on range (dynamic LOD)


Texture checksum pros
- not dependent on dynamic LOD
- simple to find

Texture checksum cons
- time consuming
- dependent on individuals settings (texture quality)


One common problem for both these methods is that they are both very time consuming. The typical method of getting the right vertex count or texture CRC is to setup binds on your keyboards to change a variable that matches a range of the vertex count or texture CRC.


My Solution
Being unsatisfied with the amount of time it takes to create recognition for objects, I decided to invent a new, quick method of doing this.

In a nutshell, we represent our texture CRCs as colour.
This is not a new concept, as if you have ever used a game that uses normal mapping, which uses a similar method of conveying information as colour.

In a normal map, each RGB component corresponds the X, Y, Z components. Meaning pure red (1, 0, 0), means straight up along the X axis.

We will be using a similar concept to display our CRCs on the screen, but instead of storing a normal map, we're going to use the CRC to display this colour.

Meaning, we will convert a CRC (0xAABBCCDD) to a colour, the problem is that a CRC is 4 bytes, meanwhile a colour is just 3. So we will use the first 3 bytes in the CRC as R, G, and B.

Red = AA, Green = BB, Blue = CC, and DD is unused.


The Code
Now that was have the concept down, we must someone render our objects (players, scenery, guns, smoke, etc.) with this colour. The best way would be to use a pixel shader to ensure a pure single colour is sent to the screen. Here is the pixel shader assembly:

Code:
ps_1_3
mov r0, c0
If you're unfamiliar with pixel shaders, this just means that the output colour (r0) will be filled with whatever is stored in constant register 0 (c0). The first instruction lets the compiler know its PS 1.3 (directx8 shader, which will work for a Geforce4ti / Radeon 8500 or higher).

To create this shader for use by Direct3D, we must assemble it. Below is how to do so:

Code:
ID3DXBuffer *pShaderBuf = NULL;
char szShader[] = "ps_1_3 \nmov r0, c0 \n";

if( SUCCEEDED(D3DXAssembleShader(szShader, sizeof(szShader), NULL, NULL, 0, &pShaderBuf, NULL)) )
{
 m_pD3Ddev->CreatePixelShader((const DWORD*)pShaderBuf->GetBufferPointer(), &m_pSimpleShader);
 pShaderBuf->Release();
}
The variable m_pSimpleShader is defined as IDirect3DPixelShader9*, I store this in my Direct3DDevice9 object.

Next, we're going to render our objects using this pixel shader. Below is the code to do so:

Code:
if( m_stage0Crc != 0 )
{
 IDirect3DPixelShader9 *tmpShader;

 m_pD3Ddev->GetPixelShader(&tmpShader);
 m_pD3Ddev->SetPixelShader(this->m_pSimpleShader);

 float vals[] = { 
  ((m_stage0Crc >> 24)&0xFF) / 255.0f,
  ((m_stage0Crc >> 16)&0xFF) / 255.0f,
  ((m_stage0Crc >> 8)&0xFF) / 255.0f,
  1.0f
 };

 m_pD3Ddev->SetPixelShaderConstantF(0, vals, 1);

 HRESULT result = m_pD3Ddev->DrawIndexedPrimitive(Type,BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);

 m_pD3Ddev->SetPixelShader(tmpShader);
  
 return result;
}
The variable m_stage0Crc is the CRC for the texture stored in stage 0 (from SetTexture).
The variable vals contains the RGBA components to be sent to the shader constant register 0. These values must be between 0.0 and 1.0, so we pick apart m_stage0Crc and divide by 255 to get the individual components.

Notice how Alpha is set to 1.0, we do this because any sort of blending will produce a different colour, and we need exact values.

Now that we have our shader working, lets see how it looks in game:

Resigzed ImageClick this bar to view the full image.


Getting the CRC
Like I said above, we need exact values, so make sure when you're getting a screenshot, make sure that it is not lossy compressed. I play my game in windowed mode and use the Print Screen button, which seems to work well.

Since we have our screenshot, use your favorite image editing program to get the colour. I used photoshops eyedropper tool, it's very convenient because it will give you a hex value of that colour, which we will then compare to our list of CRCs we saved.

We want to know the CRC for the texture of the soldiers chest, so use our eyedropper tool, and we find that its colour in hex is #b74fd6.

From this number, we know that our CRC must start with 0xB74FD6xx, so we check our log files for any CRCs matching this, and we get 0xB74FD655. Tada, our CRC for the soldiers chest is 0xB74FD655.

Verifying our Findings
A very simple way to verify if our CRC is correct is to somehow tag it, the simplest method is to skip rendering of any objects that use that texture:

Code:
if( m_stage0Crc == 0xb74fd655 )
     return D3D_OK;
Resigzed ImageClick this bar to view the full image.


As you can see, the soldiers chest is no longer being rendered, meaning we have the right CRC, mission accomplished.

Notes
One thing to keep in mind, is although our pixel shader is rendering a pure colour object, that does not necessarily mean that's what will be outputted to the screen. Post processing, fog, screen overlays can corrupt our colour, meaning you will have to first disable those to sure the pure colour is being passed to the monitor alone.

For Call of Duty Modern Warfare 2, I just prevent calls to SetRenderState, and that fixed my problem, however different games and different configurations may be different.


Post your questions or comments below.
-Azorbix