Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: Loover en 11 de Diciembre de 2003, 02:03:42 AM

Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 11 de Diciembre de 2003, 02:03:42 AM
 Buenas.

Estoy portando una serie de clases que había implementado con OpenGL a Direct3d y me han surgido algunas dudas.
Una de ellas es la forma en que yo hacía una especie de "entintado" en las imágenes:

OPENGL
A cada frame:

glColor4f (1.0f, 1.0f, 1.0f, 0.5f);
glCallList (displayList);

Y ale, la imagen que estaba en displayList se entintaba.

DIRECT3D

¿Cómo hago eso a cada frame en Direct3d sin tener que lockear el vertex buffer, cambiar el color de todos los vértices, unlockear y dibujar?

Porque según tengo entendido, lockear a cada frame es muy costoso.

Un saludo!
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 11 de Diciembre de 2003, 02:14:56 AM
 Lo único que se me ocurre ahora mismo es, o bien utilizar un material o bien utilizar vertex shaders. Esta última me parece la mejor opción.

Ten en cuenta que con un vertex shader puedes modificar todas las propiedades de los vértices sin bloquear el vertex buffer para nada.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 11 de Diciembre de 2003, 02:17:41 AM
 Sí, eso es lo que había pensado tras ver el código de la semana de Ak47 (que por cierto, se lo curró). Pero me parecía extranísimo que una cosa que es tan sencilla de hacer en OpenGl (sin pérdida de velocidad) sea bastante más complicada en DX9 (tirar de shaders).
No sé, me parece muy fuerte.

Sino hay más remedio...

Gracias

PD: ¿Cómo se haría con el material? ¿Sería muy costoso? Si necesito activar la iluminación sí...
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 11 de Diciembre de 2003, 09:37:45 AM
 Hola:

Si que se puede hacer lo que quieres sin necesidad de hacer algo tan complejo. Has de usar el TextureFactor.
Si quieres tener un color por vertice, textura y ademas todo esto poder tintarlo de un color, debes hacer:

En el stage 0 pones que se multiplique la textura y el color por vertice.
En el stage 1 pones que el resultado anterior se multiplique por el TextureFactor.
El codigo seria algo asi:
p_Device9->SetRenderState( D3DRS_TEXTUREFACTOR, color/* Aqui pon el color que quieras*/ );
p_Device9->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
p_Device9->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
p_Device9->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
p_Device9->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
p_Device9->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
p_Device9->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR );

Si solamente quieres texture y tintar de un color:

En el stage 0 pones que se multiplique la textura y el TextureFactor:
Y su codigo correspondiente:
p_Device9->SetRenderState( D3DRS_TEXTUREFACTOR, color/* Aqui pon el color que quieras*/ );
p_Device9->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
p_Device9->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
p_Device9->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TFACTOR );

Espero que te sirva!

Un saludote!!
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 11 de Diciembre de 2003, 02:32:06 PM
 Ey! Muchas gracias, aún no lo he probado pero tiene buena pinta.
Un par de dudas:
- ¿El color se lo meto con esto? color = D3DCOLOR_COLORVALUE (r, g, b, a); ¿Si en a pongo un valor 128 se verá semitransparente siempre que esté activado el alphablending?
- ¿Esto es usando multitextura, no? Vaya, no la necesitaba en OGL. ¿Cómo se hace para saber si una tarjeta soporta multitextura?

Gracias
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 11 de Diciembre de 2003, 02:51:28 PM
 En realidad, creo que MChiz ha tenido un pequeño despiste (supongo que al copiar y pegar).

Si sólo quieres aplicar una textura y tintar la superficie, sólo necesitas una unidad de textura. El código sería:

p_Device9->SetRenderState( D3DRS_TEXTUREFACTOR, color/* Aqui pon el color que quieras*/ );
p_Device9->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
p_Device9->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
p_Device9->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );

De todas formas, ¿qué aceleradora no soporta al menos dos unidades de textura?. Que yo sepa la voodoo1 ya soportaba dos unidades.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 11 de Diciembre de 2003, 02:54:25 PM
 ¿Y en el caso en el que tb usa el diffuse tb se puede hacer todo en el stage 0?
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Zaelsius en 11 de Diciembre de 2003, 02:57:58 PM
 No, sólo se pueden utilizar dos argumentos por textura. (textura+factor, o textura+vertexcolor, etc)
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 11 de Diciembre de 2003, 02:59:11 PM
 En ese caso creo que el código que necesitas es justamente el primer caso que te ha puesto MChiz. Ahí sí estarías utilizando multitextura. La otra opción para no utilizar multitextura ya sabes que es bloquear el vertex buffer y la otra, y la mejor opción, utilizar vertex shaders.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 11 de Diciembre de 2003, 03:49:33 PM
 Juas, esto:

CitarPor cierto, después de probar los vertex & pixel shaders, la fixed pipeline acaba pareciéndote patética

lo quería decir en este mensaje no en el otro que ha puesto MChiz. Aunque bueno, nunca está de más decirlo :D

Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 11 de Diciembre de 2003, 07:37:21 PM
 Buens!

Lo primerisimo de todo: Berserker tiene razon; me equivoque al copypastear :b Lo que ha puesto Berserker esta bien.

Una cosa que parece estar confundida: El usar 2 stages no significa utilizar multitextura ( CREO ). Lo digo porque he llegado a hacer muchas operaciones, sobrepasando el limite de texturas simultaneas de mi tarjeta, y todo rula. Asi que CREO que utilizar el primer metodo que expuse no te obliga a tener multitextura. Que alguien me corrija si me equivoco ( o pruebalo tu mismo : ) )

Y a lo otro que decias, Loover: Si, si le metes 128 de alpha y tienes el alpha blending activado, funcionara : )

Saludotes!!!!!
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Zaelsius en 11 de Diciembre de 2003, 07:42:13 PM
 ¿Podría ser que Direct3D hace automáticamente las siguientes pasadas si no se puede pintar todo en una pasada? :huh:  
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 11 de Diciembre de 2003, 07:55:53 PM
 Me pareceria demasiado raro ( y bonito ;b ).  Pensemoslo como si fuese un pixel shader:

float4 main( InData in, uniform sampler2D tex1, uniform sampler2D tex2 ) {
   return ( float4 )tex2D( tex1, in.texCoord0 ) + ( float4 )tex2D( tex2, in.texCoord0 );
}

Este anterior shader NECESITA dos unidades de textura.

float4 main( InData in, uniform sampler2D tex1, uniform float4 textureFactor ) {
   return ( float4 )tex2D( tex1, in.texCoord0 ) + textureFactor;
}

Y este utiliza UNA unidad de textura y ADEMAS tiene una constante que, en este caso, es el textureFactor.
Se me acaba de ocurrir... pienso que si va por este camino, esta claro que una stage NO equivale a una unidad de textura.

Saludoteeees!
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: _Grey en 11 de Diciembre de 2003, 08:17:51 PM
 
glColor4f (1.0f, 1.0f, 1.0f, 0.5f);
glCallList (displayList);


Usa Material, y prepara el SetRenderSatge, para que te lo tenga encuenta, en lugar del color independiente de cada vertice.

PD: Por que sacais el tema de las texturas!? :blink:  :ph34r:  
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 11 de Diciembre de 2003, 10:46:23 PM
 Sigo pensando que es mas facil con el TextureFactor...
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: ProD en 12 de Diciembre de 2003, 12:37:37 AM
 Yo uso el texture factor y va genial... será que todavía no me he metido con vs y ps.. como berserker.. pero todo llega.

Un saludo

PD: si usas el stage 0 y 1... a la vez es multitextura como por ejemplo..

SetTextureStageState(0, COLOR_OP, Select_arg_1)
SetTextureStageState(0, COLOR_ARG1, D3DTA_TEXTURE)

SetTextureStageState(1, COLOR_OP, MODULATE)
SetTextureStageState(1, COLOR_ARG1, D3DTA_TEXTURE)
SetTextureStageState(1, COLOR_ARG2, D3DTA_CURRENT)

m_pDevice->SetTexture(0, pTexture1);
m_pDevice->SetTexture(1, pTexture2);

.....................






Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 12 de Diciembre de 2003, 12:45:50 AM
 Ajá, gracias a todos.
¿Sabe alguien como averiguar cuantas "stages" simultaneas por superficie soporta una tarjeta dada?

PD
Mchiz no me he enterao de tu post  :blink: :

Citar
Me pareceria demasiado raro ( y bonito ;b ). Pensemoslo como si fuese un pixel shader:
...

Es que no sé nada de shaders... ¿cuál es la conclusión a la que llegas?
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 12 de Diciembre de 2003, 12:57:08 AM
 Lo que quiere decir es que sería genial que uno pudiera utilizar todos los stages que quisiera (digamos 16) y si la aceleradora sobre la que corre el programa tiene menos de 16 unidades de textura, el API se encargaría de separar los stages y dar tantas pasadas como fuese necesario. Evidentemente eso ahora mismo no es posible de forma que le toca a uno mismo dar tantas pasadas como sea necesario.

Me parece recordar que Carmack hablaba de que algún día eso será posible...

Y para saber cuántas texturas simultaneas puedes utilizar, creo recordar que te lo decía el flag MaxSimultaneousTextures de las Caps de Direct3D.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 12 de Diciembre de 2003, 02:19:36 AM
Cita de: "Loover"Es que no sé nada de shaders... ¿cuál es la conclusión a la que llegas?
Ah bueno, si te referías a qué intentaba explicar MChiz con el pixel shader que ha puesto...

Lo que estaba tratando de demostrar es que aunque hagamos la operación Texture * Diffuse * TextureFactor utilizando dos stages, si la fixed pipeline sigue el mismo criterio que el pixel shader, cuando estamos utilizando el stage en el que entra en juego el TextureFactor (en el ejemplo de MChiz, el stage 1), realmente no se está ocupando un registro de textura ya que en realidad TextureFactor sería una constante que se le pasa al pixel shader.

En definitiva, que si la fixed pipeline sigue la misma lógica que el pixel shader, aunque estés utilizando dos stages, en realidad no estás utilizando dos unidades de textura por lo que en teoría, con una aceleradora sin soporte para multitextura, debería funcionar.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 12 de Diciembre de 2003, 07:39:05 AM
 Exacto. Lo que dice Berserker es lo que intentaba demostrar : )
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 12 de Diciembre de 2003, 03:27:11 PM
 Ah, y por eso decía MChiz que parecía como que Direct3D se encargaba sola de dar las pasadas si era necesario... lo que en realidad ocurría es que no estaba utilizando más registros de textura de los necesarios, sino la cte esa.
Ok, gracias, ahora lo entiendo (más o menos, pq nunca me he metido con shaders).

PD:
Por cierto, los shaders me recuerda un montón a asm... registros, etc. No parecen tan difíciles como pensaba.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: BeRSeRKeR en 12 de Diciembre de 2003, 03:46:13 PM
Cita de: "Loover"Por cierto, los shaders me recuerda un montón a asm... registros, etc. No parecen tan difíciles como pensaba.
Cierto, pero si utilizas un lenguaje de alto nivel como HLSL (si usas Direct3D) o Cg, te resultará aún más sencillo.

Saludos.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 02 de Enero de 2004, 08:21:23 PM
 Bueno, he vuelto con esto. En su tiempo probé el entintado y funcionaba bien. Sinembargo tengo problemas con el alpha:

Por un lado tengo este formato de vértice:

// Formato del vértice
struct CUSTOMVERTEX2D
{
// Posición
float mX, mY, mZ;

// Coordenadas de textura
float mU, mV;
};
#define D3DFVF_CUSTOMVERTEX2D (D3DFVF_XYZ | D3DFVF_TEX1)


Y luego al dibujar:

mRender->GetDevice()->SetRenderState (D3DRS_ALPHABLENDENABLE, TRUE);

mRender->GetDevice()->SetRenderState (D3DRS_TEXTUREFACTOR, D3DCOLOR_COLORVALUE (1.0f, 1.0f, 1.0f, 0.5f));
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_COLOROP, D3DTOP_MODULATE);
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_TFACTOR);


Si en el color pongo un rojo por ejemplo, la imagen se tinta de ese color. Sinembargo, si intento que la imagen apareza "medio transparente" (con un valor alpha 0.5f) se lo pasa por el pito del sereno y la dibuja normal y corriente. La textura sinembargo está creada con RGBA (A8R8G8B8).
¿Seguro que se puede hacer lo de cambiar el alpha sin lockear el vertex buffer?
¿Qué estoy haciendo mal?

Un saludo
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 02 de Enero de 2004, 09:22:27 PM
 No estoy muy seguro, pero no tienes que tocar algo del ALPHAOP? No he probado esto nunca, asi que si digo una chorrada, que salte el que quiera :b

mRender->GetDevice()->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);

Imagino que esto te multiplicara el alpha de la textura por el del TextureFactor. Si no quieres usar el alpha de la textura y asi tener la imagen en RGB8 para ocupar menos memoria, prueba con:

mRender->GetDevice()->SetTextureStageState (0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
mRender->GetDevice()->SetTextureStageState (0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);

Ya me diras que tal ha ido : )
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 02 de Enero de 2004, 11:59:25 PM
 Sip, tb había probado eso, lo había visto "rebuscando" por la ayuda. Pero nada.
Tengo fundadas sospechas de que no hay más remedio que lockear el buffer. Por lo menos en el Special  Effects lo hace así. Pero claro este libro esta basado en dx 8.1 y quería ver si había alguna otra forma...
Aunque en la ayuda, sección "Texture Alpha" sale un ejemplo de una esfera semitransparente y lo hacen sin lockear, de la manera que tu has dicho y estaba probando. No sé que estoy haciendo mal.
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 03 de Enero de 2004, 01:53:30 AM
 Hey sí! Claro que funciona, solo que se me había olvidado poner esto:

mRender->GetDevice()->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
mRender->GetDevice()->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

;)

Por cierto, haciendo pruebas he visto como hacer un fade to color. Utilizando D3DTOP_BLENDFACTORALPHA  (uoh)

Gracias!
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: MChiz en 03 de Enero de 2004, 12:26:49 PM
 Ole! Me alegro que lo hayas conseguido! : )

A que te refieres con un 'fade to color'??
Título: Cambiar El Color De Un Vértice Sin Lockear El Vf
Publicado por: Loover en 03 de Enero de 2004, 08:24:53 PM
 Sip, ir cambiando progresivamente de la imagen a un color dado. Por ejemplo completamente rojo.
Lo normal son fades a negro o a blanco, y a pantalla completa. Pero bueno, ya que puedo dar la posibilidad por imagen tb bienvenida sea. Eso sí, con cuidado de solo activarla si el usuario le da valores R, G, B.

Un saludo!