Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: Cronodragón en 18 de Octubre de 2005, 07:34:37 AM

Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Cronodragón en 18 de Octubre de 2005, 07:34:37 AM
 Estaba revisando unos ejemplos de DX8, y me dí cuenta de que ya no existe en DX9 el método CopyRect. No solo eso, en realidad DirectSurface9 no tiene nada para poner un pixel, así que me imagino hay que hacer todo a pie con Lock y los bits de cada pixel. La pregunta es, si hay tantos formatos de superficie, especialmente si se trata de dibujar al frontbuffer, cuyo formato se ha obtenido con D3DFMT_UNKNOWN, ¿cómo se puede hacer un tratamiento sencillo para dibujar pixeles en la superficie? Lo mejor que se me ocurre por ahora es hacer una función a la que pasas los componentes RGB, y que la función se encargue de devolverte los bits correctamente enmascarados para el formato de la superficie que estas usando. No quiero ponerme a inventar el agua caliente si ya DX9 trae un método para manejar esto.
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Haddd en 18 de Octubre de 2005, 07:38:09 AM
 claro, para tratar un pixel utiliza shaders. Porque como tu bien dices, te puedes volver loco con los formatos disponibles...

Mírate el método FillTexture o algo así.... :P
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Cronodragón en 18 de Octubre de 2005, 07:50:10 AM
 Pero los pixel shaders se hacen en el "aire". Yo me refería a grabar datos en una superficie. :D  
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: zupervaca en 18 de Octubre de 2005, 12:13:09 PM
 si quieres usar surfaces usa la funcion StrechRect, si tu objectivo es pintar pixel sobre una textura usa D3DXFillTexture
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Pogacha en 18 de Octubre de 2005, 12:58:10 PM
 Usá OpenGL y vas a ver que no se te van a ir ninguna función JajaJaja!
Saludos.
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: zupervaca en 18 de Octubre de 2005, 01:13:10 PM
 jeje, que pifias somos algunas veces

editado: post erroneo, vamos que entendi algo que no era (nooo)

Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Ray en 18 de Octubre de 2005, 02:40:59 PM
 El método similar a CopyRect es UpdateSurface aunque debido a las restricciones tambien se debe usar StrechRect, GetRenderTargetData o GetFrontBufferData, dependiendo de cada caso.

saludos.
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Cronodragón en 18 de Octubre de 2005, 04:29:06 PM
 De cuál interface son esos métodos? :huh:  
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Ray en 18 de Octubre de 2005, 05:16:38 PM
 De IDirect3DDevice9, cuyo objeto deberá ser el mismo con el que has creado las surfaces (supongo), tambien lo puedes obtener con GetDevice como método de la propia surface que vayas a copiar.
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: KACHORRO en 26 de Octubre de 2005, 10:55:17 PM
 Yo he accedido a la textura mediante el metodo LockRect
En mi caso fué para hacer un getpixel, aunque supongo que podrás hacerlo a la inversa.

Te muestro mi codigo:

Citar
        DWORD*   ptr;
   DWORD bytesporpixel;
        RECT r;
        D3DLOCKED_RECT data;
   r.left=x;
        r.top=y;
        r.right=x+tamx;
        r.bottom=y+tamy;
   textura->LockRect(0, &data, &r, 0);
   ptr = (DWORD*)data.pBits;
   bytesporpixel = data.Pitch / sizeof(DWORD);
   textura->UnlockRect(0);

Y ya está, en ptr tienes el puntero a los datos... eso sí, no sé cuan ineficiente puede llegar a ser el método de bloquear un rect en la textura, pero para un getpixel que no es en tiempo real de juego, me va de maravilla... otra cosa es para historias mas complejas.
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: [EX3] en 27 de Octubre de 2005, 01:16:47 AM
 Para hacer GetPixel() y PutPixel() eficientes en D3D mejor almacenar los valores de los pixeles en un array en una tajada y acceder directamente a ellos para leer o escribir a traves del array, sin bloqueos ni desbloqueos ganando asi mucho tiempo y velocidad. Luego para actualizar simplemente escribes el array en el puntero de la superficie bloqueando y desbloqueandola, esto es mas rapido que tener que hacer un bloqueo/desbloqueo para cada pixel. La nueva version de la dx_lib32 utiliza este metodo, 4 funciones: una para leer todos los pixeles de la superficie y almacenarlo es un array, una funcion para leer los valores del array, otra para escribirlos y otra para actualizar la superficie con los nuevos datos del array escribiendo el array en la superficie. No se si habra algun metodo mas eficiente pero esto es mejor que lo que hacia antes y lo que veo haces KACHORRO, bloquear/desbloquear por cada pixel.

Esto lo aprendi gracias a los consejos que aportaron zupervaca y algunos otros en el ultimo COTW que subi ;) (para que luego digan que no hago caso de los consejo que me dan :P)

Salu2...
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: KACHORRO en 27 de Octubre de 2005, 12:24:46 PM
 Bueno, realmente a mi no me importa mucho el rendimiento de este getpixel porque se hace en un momento muy puntual en el que el rendimiento no es critico. En cualquier caso, es bueno saber como hacerlo más eficiente.  
Título: Tratamiento De Los Formatos De Las Superficies
Publicado por: Ray en 27 de Octubre de 2005, 03:46:02 PM
 Con LockRect estás trabajando a muy bajo nivel, nunca asumas que lo que te funciona en una circustancia lo vaya a hacer en otras o en otro ordenador.

En la forma en que obtienes los pixels te aconsejaría que no accedas a la superficie o textura con el puntero "ptr" una vez desbloqueada.

Intenta comprobar siempre que el metodo han pasado correctamente y usa el pitch para obtener el ancho real de la textura o surface.

Crea la textura con D3DPOOL_MANAGED, seguramente puedas hacer cientos de lecturas sin perder nada de velocidad, aunque como ya he dicho antes, a veces no se puede saber nada con seguridad sin antes probarlo en montones de ordenadores.

Te pongo mi versión para leer un pixel asumiendo que el color es de 4 bytes (DWORD), pruebala y compara el rendimiento con la tuya si quieres, aunque supongo que no diferirá mucho en velocidad.


void GetPixelTextura(LPDIRECT3DTEXTURE9 &textura, int px, int py, DWORD *Color)
{
D3DLOCKED_RECT rect;
if (SUCCEEDED( textura->LockRect(0, &rect, NULL, 0) ) ) {
     *Color = *((DWORD *)rect.pBits + (rect.Pitch>>2) * py + px);
     textura->UnlockRect(0);
     }
}