Wenas.
Estos dias he estado retomando unos deberes que me deje guardado para ultimo momento en el apartado grafico de la dx_lib32 y estos son intentar aplicar ciertos efectos de modificacion de color en texturas sin usar shaders: invertir colores, exclusion y conversion a escala de grises.
La inversion de color la he logrado pero con el inconveniente de que siempre le aplica traslucencia como si se le aplicara opacidad aditiva (render states srcblend=zero y destblend=invsrccolor) y la exclusion la aplica sin problemas (render states srcblend=invdestcolor y destblend=invsrccolor). El problema lo tengo en la forma de aplicar la conversion a escala de grises. Despues de patearme medio google he visto que en muchos sitios lo hacen aplicando dotProduct3 a la textura con el factor de conversion de color a escala de gris.
El asunto es que al igual que con la inversion de color y la exclusion lo aplica con una traslucencia en plan aditivo (resultado innesperado pero posiblemente util en otros usos) e invirtiendo los colores en la conversion a grises (esto lo he solucionado re-invirtiendo los colores con srcblend=zero y destblend=invsrccolor). El problema en si es que la informacion del canal alpha en texturas PNG se come, pintando las zonas transparentes como solidas, en este caso en negro y me fastidia el invento para usarlo en sprites (la idea era usarlo a nivel global).
El codigo que aplico es el siguiente:
D3DDevice.SetRenderState D3DRS_TEXTUREFACTOR, D3DColorMake(0.299, 0.587, 0.114, 1.0)
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, D3DTA_TFACTOR
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ZERO
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR
He probado cambiando destblend=invsrcalpha y los estados de textura a D3DTSS_ALPHAOP y D3DTSS_ALPHAARGn en vez de D3DTSS_COLOROP y D3DTSS_COLORARGn y no logro los resultados esperados (hace un invertido de colores en solido pero no aplica escala de grises).
Notese que no ando muy puesto en temas de estados de textura y de renderizados (este ultimo lo justo) y sus combinaciones por lo que posiblemente este metiendo la pata hasta el fondo en algun detalle que desconozco.
En caso de ir por mal camino, existe otra forma que no sea mediante shaders de este efecto "basico"? De ser mediante los estados de textura y renderizado, cual seria la combinacion es correcta para lograr este efecto o aproximacion al mismo?
Gracias.
Salu2...
Pasa que estas meando fuera del tarro.
srcblend y destblend dicen como se va a mezclar el resultado del shader con lo que hay en pantalla.
Si quieres que ande el canal alpha tienes que si o si poner:
srcblend = alpha y destblend = one_minus_alpha
o si lo premultiplicas por el canal alpha:
srcblend = one y destblend = one_minus_alpha
Para hacer la escala de grises, como dices usas el dot3 pero al canal alpha lo debes dejar intacto.
Otro problema es que no todas las placas tienen dot3 para ese caso lo que puedes hacer es una primera pasada modulado en negro, luego habilitas solo la escritura de cada canal y pones el blending en suma y premultiplicando por alpha y por la constante de cada canal haces las tres pasadas.
Para la inversion de color tienes dos opciones:
1 - Invertir el color en el shader y dejar el alpha tal cual.
2 - Invertir el color en el blending y premultiplicar ek color en el shader pero dejando el canal alpha tal cual.
Saludos
Cita de: "Pogacha"Pasa que estas meando fuera del tarro.
Con razon me estaba salpicando je :D
Cita de: "Pogacha"Si quieres que ande el canal alpha tienes que si o si poner:
srcblend = alpha y destblend = one_minus_alpha
(...)
o si lo premultiplicas por el canal alpha:
srcblend = one y destblend = one_minus_alpha
Cual constante es "one_minus_alpha"? Tal que asi no esta documentada en DirectX:
Cita de: "CONST_D3DBLEND"D3DBLEND_ZERO = 1
D3DBLEND_ONE = 2
D3DBLEND_SRCCOLOR = 3
D3DBLEND_INVSRCCOLOR = 4
D3DBLEND_SRCALPHA = 5
D3DBLEND_INVSRCALPHA = 6
D3DBLEND_DESTALPHA = 7
D3DBLEND_INVDESTALPHA = 8
D3DBLEND_DESTCOLOR = 9
D3DBLEND_INVDESTCOLOR = 10
D3DBLEND_SRCALPHASAT = 11
D3DBLEND_BOTHSRCALPHA = 12
D3DBLEND_BOTHINVSRCALPHA = 13
D3DBLEND_INVSRCALPHA quizas?
Cita de: "Pogacha"Otro problema es que no todas las placas tienen dot3 para ese caso lo que puedes hacer es una primera pasada modulado en negro, luego habilitas solo la escritura de cada canal y pones el blending en suma y premultiplicando por alpha y por la constante de cada canal haces las tres pasadas.
Aqui me he quedado un poco perdido. Seria pintar 3 veces la misma textura cambiando los render states y render textures o se puede en la misma pasada cambiando los estados usando multitextura (diferentes stages)?
Cita de: "Pogacha"Para hacer la escala de grises, como dices usas el dot3 pero al canal alpha lo debes dejar intacto.
Supongo que dices de desactivar el estado de render del alphablending. Si es haciendo multiples pasadas bajo multitextura en una de las pasadas deberia poder reactivar el alphablending ya que el objetivo que busco es poder modular la opacidad o transparencia mediante canal alpha del color. Es posible o es incompatible?
Por cierto, cuando te refieres a "shaders" supongo que te refieres a la operacion que se genera mediante la combinacion de estados, por que programacion a bajo nivel de shaders como tal no estoy aplicando (lo que viene a ser comun a dia de hoy, un bloque de codigo, un pixel shader).
Salu2...
P.D.: Webs o articulos que conozcais y que traten el tema en detalle? Todo lo que he encontrado ha sido en su mayoria entradas de foros donde lo trataban con pinzas el asunto de la escala de grises y ninguno concreto sobre la inversion de colores.
D3DBLEND_INVSRCALPHA quizas? Si, one_minus_src_alpha es de openGL :P
Aqui me he quedado un poco perdido. Seria pintar 3 veces la misma textura cambiando los render states y render textures o se puede en la misma pasada cambiando los estados usando multitextura (diferentes stages)? No, aqui me equivoque yo, en OpenGL puedes cambiar el origen y destino de los canales pero tiene menos disponibilidad que el Dot3.
Dot3 es a partir de GeForce2 y Ati9200 asi que no es para tanto, incluso antes ya habia, practicamente fue el paso siguiente que agregaron las placas despues de la multitextura.
Para invertir el color te diria que pruebes con:
CitarD3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, (D3DTA_TEXTURE Or D3DTA_COMPLEMENT)
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
Hey, genial, funciono a la perfeccion :D Le hice una ligera modificacion y he logrado poder graduar por el canal alpha del color de los vertices:
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, (D3DTA_TEXTURE Or D3DTA_COMPLEMENT)
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
Funciona de maravillas, mil gracias :D
He estado tambien intentado aplicar tu codigo a la implementacion de conversion a escala de grises pero no logro combinacion adecuada para que me respete el canal alpha de la textura. Lo mas que he logrado ha sido que respete el alpha pero el resultado es que dibuja la silueta "visible" de la textura en blanco :? Mañana seguire intentandolo con mas calma.
Salu2...
Sobre la escala de grises, en teoria seria así:
Primera pasada:
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_DISABLE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ZERO
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
Segunda pasada:
D3DDevice.SetRenderState D3DRS_TEXTUREFACTOR, D3DColorMake(0.299, 0.587, 0.114, 1.0)
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE)
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_CURRENT
D3DDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_TFACTOR
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ONE
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_ONE
Luego me cuentas ...
Oye, pues conforme vayas consiguiendo resultados (inversión de color, borde del sprite, escala de grises, etc), podrías ir poniendo el código y el resultado del sprite. Me parece algo muy útil.
Lo de las pasadas me confunde un poco, pensaba que eso era lo de aplicar estados en diferentes stages de una textura (multitextura). Se supone que deberia dibujar dos veces la textura, una con los primeros estados, y otra con los estados en los dos stages de la textura?
Cita de: "Loover"Oye, pues conforme vayas consiguiendo resultados (inversión de color, borde del sprite, escala de grises, etc), podrías ir poniendo el código y el resultado del sprite. Me parece algo muy útil.
Por supuesto :) De momento ahi tienes la de inversion de colores que hizo
Pogacha con la modificacion para modular por el alpha del color de vertice que funciona a las mil maravillas. Lo del borde del sprite, te refieres a sacar el contorno solido?
Salu2...
Si, lamentablemente tendrás que dibujarlo dos veces, si no utilizas shaders el muy maldito Dot3 se propaga a todos los canales incluido el canal alpha. Es algo que no está especificado muy claramente en el SDK.
Leelo un poco:
http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dx81_c/directx_cpp/Graphics/Reference/CPP/D3D/Enums/d3dtextureop.asp
CitarD3DTOP_DOTPRODUCT3
Modulate the components of each argument as signed components, add their products; then replicate the sum to all color channels, including alpha. This operation is supported for color and alpha operations.
In DirectX 6.0 and 7.0 multitexture operations the above inputs are all shifted down by half (y = x - 0.5) before use to simulate signed data, and the scalar result is automatically clamped to positive values and replicated to all three output channels. Also, note that as a color operation this does not updated the alpha it just updates the rgb components.
However, in DirectX 8.1 shaders you can specify that the output be routed to the .rgb or the .a components or both (the default). You can also specify a separate scalar operation on the alpha channel.
La unica solucion que encontre es hacer el blending en 2 etapas, primero el fondo*=(1-alpha) y luego +=(alpha*color) Dot3 ConstanteGris
En teoria debe andar la desgracia es que tienes que dibujar dos veces el quad para que funcione.
Vale. He dibujado primero la textura con el primer bloque de estados que has puesto y despues vuelvo a dibujar superpuesto la misma textura con el segundo bloque y activando el stage 1 de la textura. El resultado es que se ve en escala de grises invertido y sin respetar el alpha:
(http://img260.imageshack.us/img260/251/coloret8.png) (http://img152.imageshack.us/img152/4381/grayscalekm5.png)
El verde que se ve en la primera captura forma parte del fondo de renderizado (en el momento de borrar) y no de la textura.
Salu2...
Que te dibuja si solo haces la primera pasada?
En teoria deberia ser la sombra del dibujo tan solo.
Me dibuja la textura integra en negro, sin respetar alpha tampoco.
Estos son los resultados por separado de cada pasada:
(http://img213.imageshack.us/img213/5492/pass1fj9.png) (http://img297.imageshack.us/img297/3296/pass2cw4.png)
Salu2...
En la primera pasada no deberia hacer eso, prueba a poner los render states del pipeline por defecto y deja los states del blending, cersiorate de estar desactivando el segundo stage para la primera pasada.
No se por que pero en la segunda pasada te esta invirtiendo el color.
Prueba a cambiar esto.
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE Or D3DTA_COMPLEMENT)
Una vez limpiado el fondo a negro en el interior del área que ocupará el sprite, lo mismo te da usar para la segunda pasada blend aditivo que imodular con invsrcalpha.
Una vez tengas arreglada la primera pasada, prueba en la segunda pasada con:
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
En teoría debería dar igual pero tú prueba.
Cita de: "Pogacha"En la primera pasada no deberia hacer eso, prueba a poner los render states del pipeline por defecto y deja los states del blending, cersiorate de estar desactivando el segundo stage para la primera pasada.
Desactive todos los renderstates que inicializa dx_lib32 excepto los de blending de esta pasada (SrcBelnd=Zero e DestBlend=InvSrcAlpha) y ahora sale en blanco en vez de negro :?
Cita de: "Pogacha"No se por que pero en la segunda pasada te esta invirtiendo el color.
Prueba a cambiar esto.
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE Or D3DTA_COMPLEMENT)
Lo de la inversion de color es normal por lo que decian aqui (http://66.102.9.104/search?q=cache:cLTAskZ8aIIJ:www.gamedev.net/community/forums/topic.asp%3Ftopic_id%3D345032+convert+texture+to+grayscale+d3d&hl=es&ct=clnk&cd=5&gl=es&client=firefox-a), que es donde empece a hacer pruebas con el DotProduct3. He añadido el flag para la inversion y se ve que en combinacion de AlphaReplicate hace un efecto algo extraño:
(http://img258.imageshack.us/img258/2189/texoralphaorcomplqm2.png)
No se aprecia apenas pero como que difumina los pixeles de la textura con el fondo.
Cita de: "senior wapo"Una vez limpiado el fondo a negro en el interior del área que ocupará el sprite, lo mismo te da usar para la segunda pasada blend aditivo que imodular con invsrcalpha.
Antes de nada quiero asegurarme. Asi en pseudocodigo seria como estoy implementando el asunto de las pasadas, por si resulta que estoy haciendo algo mal:
// Pasada 1
SetTextureStageRender(0, D3DTSS_COLOROP, D3DTOP_DISABLE)
SetTextureStageRender(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)
SetTextureStageRender(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)
SetTexture(0, Textura)
DibujoTextura()
// Pasada 2
SetRenderState(D3DRS_TEXTUREFACTOR, D3DColorMake(0.299, 0.587, 0.114, 1.0)
SetTextureStageRender(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)
SetTextureStageRender(0, D3DTSS_COLOROP, D3DTOP_MODULATE)
SetTextureStageRender(0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE))
SetTextureStageRender(1, D3DTSS_COLORARG1, D3DTA_CURRENT)
SetTextureStageRender(1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3)
SetTextureStageRender(1, D3DTSS_COLORARG2, D3DTA_TFACTOR)
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE)
SetTexture(0, Textura)
SetTexture(1, Textura)
DibujoTextura()
A ver si es que lo estoy haciendo mal y por eso los resultados no son los esperados.
Salu2...
Pruebalo así, pero deberia estar andando.
// Pasada 1
SetTextureStageRender(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)
SetTextureStageRender(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1)
SetTextureStageRender(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE)
SetTextureStageRender(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1)
SetTextureStageRender(1, D3DTSS_COLOROP, D3DTOP_DISABLE)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA)
SetTexture(0, Textura)
DibujoTextura()
// Pasada 2
SetRenderState(D3DRS_TEXTUREFACTOR, D3DColorMake(0.299, 0.587, 0.114, 1.0) )
SetTextureStageRender(0, D3DTSS_COLORARG1, D3DTA_TEXTURE)
SetTextureStageRender(0, D3DTSS_COLOROP, D3DTOP_MODULATE)
SetTextureStageRender(0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE) )
SetTextureStageRender(1, D3DTSS_COLORARG1, D3DTA_CURRENT)
SetTextureStageRender(1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3)
SetTextureStageRender(1, D3DTSS_COLORARG2, D3DTA_TFACTOR)
SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE)
SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE)
SetTexture(0, Textura)
DibujoTextura()
Le he modificado un par de estados y excepto por el alpha del canal de la textura ya lo pinta en escala de grises y con posibilidad de modular la opacidad mediante el alpha del color de los vertices, tal y como hago en el resto de efectos:
(http://img215.imageshack.us/img215/797/clipboard04ad7.png)
El codigo:
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_DISABLE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 Or D3DTOP_MODULATE
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
D3DDevice.SetRenderState D3DRS_TEXTUREFACTOR, D3DColorMake(0.299, 0.587, 0.114, 1.0)
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE)
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_CURRENT
D3DDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_TFACTOR
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ZERO
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
Tomando este punto, voy a ver si soy capaz de aplicar el canal alpha de la textura y ver si remato el asunto. Estaba pensando en si alguno de los estados de textura me permite definir un colorkey. Mi idea sera hacer que tomara el negro RGBA(0,0,0,1.0) como color de mascara para que no lo dibuje. Estoy mirando pero no me aclaro mucho con la documentacion, estoy leyendo acerca de la constante D3DTA_SELECTMASK pero me parece (http://64.233.183.104/search?q=cache:TKSX51LtvnsJ:www.gamedev.net/community/forums/topic.asp%3Ftopic_id%3D134016+D3DTA_SELECTMASK&hl=es&ct=clnk&cd=1&gl=es&client=firefox-a) que el uso es bien distinto al que busco. Hay forma de definir mascara de color mediante estados o alguna triquiñuela para indicar un color como transparente?
Ya te debo 2, Pogacha, mil gracias :D
Salu2...
La idea de lo que el codigo deberia hacer es:
Siendo el alpha blending:
Src = TexturaRGB Dot3 GreyScaleFactor
Dst = Src * SrcAlpha + Dst * (1-SrcAlpha)
Como el Dot3 se replica a todos los canales, perdemos el alpha con lo que debemos hacer dos pasadas.
Pasada 1:
Dst = Dst * (1-SrcAlpha)
Pasada 2:
Dsp = Dst + Src * SrcAlpha;
La primera pasada no te anda pero deberia sin mas.
La ecuacion de blending debe ser Src * Zero + Dst * InvSrcAlpha
Para la segunda pasada tenemos que multiplicar el alpha por el color por eso en el primer stage hacemos que el alpha se replique a todos los canales y lo modulamos por el color.
O sea
Stage1Result.r = Src.r * Src.a
Stage1Result.g = Src.g * Src.a
Stage1Result.b = Src.b * Src.a
Stage1Result.a = Src.a // este nos olvidamos
En el segundo stage tomamos este resultado y hacemos el dot3
Curr = Stage1Result
Stage2Result.rgba = Curr.r * GreyScaleFactor.r + Curr.g * GreyScaleFactor.g + Curr.b * GreyScaleFactor.b
Y el blending debe ser:
Dst = Stage2Result * ONE + Dst * ONE
En teoria la primera pasada debe dejarte el hueco negro de la silueta, has andar esto.
Si pones la segunda pasada solo deberia ponerte en escalas de grises pero de modo aditivo, como un reflejo en un espejo.
Saludos
Cita de: "Pogacha"En teoria la primera pasada debe dejarte el hueco negro de la silueta, has andar esto.
Te refieres a esto?
(http://img134.imageshack.us/img134/3236/clipboard05lg1.png)
Cambiando el estado D3DTSS_COLOROP de D3DTOP_DISABLE a D3DTOP_MODULATE.
Cita de: "Pogacha"Si pones la segunda pasada solo deberia ponerte en escalas de grises pero de modo aditivo, como un reflejo en un espejo.
Lo hace pero pintando el fondo opaco e invirtiendo los colores:
(http://img146.imageshack.us/img146/6794/clipboard06fr2.png)
Salu2...
Ok, has la primera pasada y la segunda pasada asi como me mostraste arriva pero cambia esta linea en el segundo stage de la segunda pasada
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_CURRENT
por
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_CURRENT Or D3DTA_COMPLEMENT
me muero por saber si con esto andara!
Weno, diria que algo ha salido, el fondo ya no se pinta pero la escala de grises se ha ido "casi" por completo :D
(http://img221.imageshack.us/img221/3765/clipboard07hw2.png)
Digo "casi" por que fijate que algunos pixeles han quedado transparentes, en la rodilla por ejemplo, lo que supongo que querra decir que esta afectando algo al resultado del paso anterior.
Salu2...
EDIT! Casi lo he sacado! :D (casi por que simplemente sale algo oscura)
(http://img231.imageshack.us/img231/8854/clipboard8yf7.png)
He añadido el flag D3DTA_COMPLEMENT en el argumento D3DTSS_COLORARG1 y los estados de blending SrcBlend a InvSrcColor y DestBlend a InvSrcAlpha del stage 0 de la 2º pasada y ha salido el asunto. Ahora a ver si logro que la luminosidad sea la correcta.
Bueno, no te olvides de mostrar el resultado final!
Por supuesto:
(http://img85.imageshack.us/img85/7551/clipboard16tg8.png)
El reborde "dentado" de color blanco que aparece es por un fallo de la textura, no de codigo. La textura inicialmente tenia el fondo de color solido y al pasarlo a alpha se solapo con el contorno del sprite.
Digamos que he logrado el tono correcto (comparandolo con la textura original pasada a escala de grises con Photoshop) pero sigo teniendo un ligero fallo por culpa de los estados de blending que hace que los pixeles blancos no los pinte. En esta textura se aprecia mejor:
(http://img69.imageshack.us/img69/3955/clipboard14zh2.png) (http://img231.imageshack.us/img231/8826/texturema3.png)
Añado otro problema y es que la modulacion de opacidad mediante el componente alpha del color de los vertices oviamente tampoco me lo aplica en el resultado final, solo en el paso 1 lo que me vale de poco ya que el 2 paso se mantendra con opacidad aditiva :?
El codigo final es este, tuve que añadir un stage mas al 2º paso para invertir el color:
// Paso 1
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE
D3DDevice.SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 Or D3DTOP_MODULATE
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_ZERO
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA
// Paso 2
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE Or D3DTA_COMPLEMENT
D3DDevice.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE
D3DDevice.SetTextureStageState 0, D3DTSS_COLORARG2, (D3DTA_TEXTURE Or D3DTA_ALPHAREPLICATE)
D3DDevice.SetRenderState D3DRS_TEXTUREFACTOR, D3DColorMake(0.33333, 0.33333, 0.33333, 1.0)
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG1, D3DTA_CURRENT
D3DDevice.SetTextureStageState 1, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3
D3DDevice.SetTextureStageState 1, D3DTSS_COLORARG2, D3DTA_TFACTOR Or D3DTA_COMPLEMENT
D3DDevice.SetTextureStageState 2, D3DTSS_COLOROP, D3DTOP_SELECTARG1
D3DDevice.SetTextureStageState 2, D3DTSS_COLORARG1, (D3DTA_CURRENT Or D3DTA_COMPLEMENT)
D3DDevice.SetTextureStageState 2, D3DTSS_COLORARG2, D3DTA_CURRENT
D3DDevice.SetTextureStageState 2, D3DTSS_ALPHAOP, D3DTOP_MODULATE Or D3DTOP_ADD // D3DTOP_MODULATE para intentar regular la opacidad mediante el alpha del color de vertice (sin exito)
D3DDevice.SetRenderState D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA
D3DDevice.SetRenderState D3DRS_DESTBLEND, D3DBLEND_SRCALPHA
D3DBLEND_ONE funciona tambien para el estado de blending pero ilumina de mas el resultado (que segun casos puede quedar mejor o peor). Mañana intentare seguir buscando forma de solucionar como minimo lo de que no pinte los pixeles blancos. La regulacion de opacidad por alpha de color de vertice me vendria de perlas pero podria vivir sin ella. Si se os ocurre algo bienvenido sea.
Una vez mas gracias, Pogacha, me ha resultado muy instructivo el dia de hoy referente al uso de los estados de textura & cia., al menos ya me entiendo mejor su funcionamiento :)
Salu2...