La forma en que hago esto es la siguiente.
IDirect3DDevice9 :: GetBackBuffer : Obtenga acceso a IDirect3DSurface9 que representa el búfer posterior, igual que lo que tiene actualmente. ¡No olvide liberar esta superficie cuando termine ya que esta llamada incrementará el recuento de referencias!
IDirect3DSurface :: GetDesc : Obtenga la descripción de la superficie del búfer posterior, que le dará su ancho, alto y formato.
IDirect3DDevice9 :: CreateOffscreenPlainSurface : crea un nuevo objeto de superficie en D3DPOOL_SCRATCH; normalmente desea usar el mismo ancho, alto y formato (pero en realidad no tiene que hacerlo con este método). Nuevamente, suelte cuando haya terminado. Si está realizando esta operación en cada cuadro (en cuyo caso es mejor que busque alternativas como un enfoque basado en sombreador para lo que está tratando de hacer), podría crear la superficie plana fuera de la pantalla una vez al inicio y reutilizarla. en lugar de crearlo cada cuadro.
D3DXLoadSurfaceFromSurface : copie desde la superficie del búfer posterior a la superficie plana descentrada. Esto hará un cambio de tamaño y conversión de formato automáticamente para usted. Alternativamente, si no desea o necesita cambiar el tamaño o cambiar el formato, puede usar IDirect3DDevice9 :: GetRenderTargetData , pero si es así, cree la superficie plana fuera de la pantalla en D3DPOOL_SYSTEMMEM.
IDirect3DSurface9 :: LockRect : Obtenga acceso a los datos en la superficie plana fuera de la pantalla y tenga su propio mal camino; DesbloquearRect cuando haya terminado.
Esto parece mucho más código, pero descubrirá que es tan rápido como glReadPixels, e incluso puede ser más rápido si no necesita hacer una conversión de formato (que glReadPixels usando GL_RGB casi seguramente lo hace).
Editar para agregar: algunas funciones auxiliares (rought 'n' ready) que también tengo que pueden ser útiles para usar este método para capturas de pantalla:
// assumes pitch is measured in 32-bit texels, not bytes; use locked_rect.Pitch >> 2
void CollapseRowPitch (unsigned *data, int width, int height, int pitch)
{
if (width != pitch)
{
unsigned *out = data;
// as a minor optimization we can skip the first row
// since out and data point to the same this is OK
out += width;
data += pitch;
for (int h = 1; h < height; h++)
{
for (int w = 0; w < width; w++)
out[w] = data[w];
out += width;
data += pitch;
}
}
}
void Compress32To24 (byte *data, int width, int height)
{
byte *out = data;
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++, data += 4, out += 3)
{
out[0] = data[0];
out[1] = data[1];
out[2] = data[2];
}
}
}
// bpp is bits, not bytes
void WriteDataToTGA (char *name, void *data, int width, int height, int bpp)
{
if ((bpp == 24 || bpp == 8) && name && data && width > 0 && height > 0)
{
FILE *f = fopen (name, "wb");
if (f)
{
byte header[18];
memset (header, 0, 18);
header[2] = 2;
header[12] = width & 255;
header[13] = width >> 8;
header[14] = height & 255;
header[15] = height >> 8;
header[16] = bpp;
header[17] = 0x20;
fwrite (header, 18, 1, f);
fwrite (data, (width * height * bpp) >> 3, 1, f);
fclose (f);
}
}
}