Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Tratamiento De Los Formatos De Las Superficies

Iniciado por Cronodragón, 18 de Octubre de 2005, 07:34:37 AM

« anterior - próximo »

Cronodragón

 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.

Haddd

 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

Cronodragón

 Pero los pixel shaders se hacen en el "aire". Yo me refería a grabar datos en una superficie. :D  

zupervaca

 si quieres usar surfaces usa la funcion StrechRect, si tu objectivo es pintar pixel sobre una textura usa D3DXFillTexture

Pogacha

 Usá OpenGL y vas a ver que no se te van a ir ninguna función JajaJaja!
Saludos.

zupervaca

 jeje, que pifias somos algunas veces

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


Ray

 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.

Cronodragón

 De cuál interface son esos métodos? :huh:  

Ray

 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.

KACHORRO

 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.

[EX3]

 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...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

KACHORRO

 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.  

Ray

 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);
     }
}






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.