2011-12-13 10 views
7

Creo una aplicación FireMonkey con 3 tImage3D semitransparentes. Aquí está el código y la pantalla. Todo parece bien.Firemonkey semitransparente Image3D a veces es opaco

procedure TForm1.Form3DCreate(Sender: TObject); 

// create a new semi-transparent timage3d 
// object with color and Z position. 
procedure NewImage (const nColor : tColor; 
        const nZ  : integer); 
begin 
    // create the image 
    with tImage3D . Create (self) do 
    begin 
     // put it on the screen 
     Parent := self; 
     // set the size 
     Width := 10; 
     Height := 10; 
     // set the image to a single pixel. 
     Bitmap . Width := 1; 
     Bitmap . Height := 1; 
     // set the Alpha to $80 to make it 
     // semi-transparent 
     Bitmap . Pixels [ 0, 0 ] := $80000000 + nColor; 
     // set the z position 
     Position . Z := nZ; 
    end; 
end; 

begin 
    NewImage (claRed, +10); 
    NewImage (claGreen, 0); 
    NewImage (claBlue, -10); 
end; 

All is well

Ahora invertir el orden. Ahora son opacos.

begin 
    NewImage (claRed, -10); 
    NewImage (claGreen, 0); 
    NewImage (claBlue, +10); 
end; 

Now they are opaque

¿Qué me falta?

+3

Aparentemente, un objeto es solo semitransparente para un objeto creado anteriormente. Si eso tiene algún sentido. El recuadro rojo aparece rosa porque puedes ver el fondo blanco, pero no puedes ver los recuadros verde o azul a través de él. A través del cuadro verde, puede ver el fondo blanco y el cuadro rojo, pero no el cuadro azul. Tuve la misma ocurrencia con objetos text3d también. –

+0

Creo que @user tiene razón. Intenta redibujar los objetos en el frente. Si el objeto no detecta nada debajo de él, probablemente omita las funciones de mezcla y el fondo blanco no cuente. –

+0

¿Qué quiere decir con volver a dibujar los objetos en el frente? Este es un ejemplo muy simplificado para ilustrar el problema. La aplicación original tenía varias imágenes y texto giratorios flotantes, y la posición de cada objeto se cambiaba cada 50 ms, por lo que constantemente se redibujaba. –

Respuesta

4

FireMonkey (a partir de ahora) no admite la representación de objetos semitransparentes en 3D.

FireMonkey sólo admite mezcla de objetos semitransparentes (ya sea a través de la propiedad Opacidad o debido a su textura, por ejemplo, una imagen PNG semitransparente), pero blending por sí sola no es suficiente para hacerlo bien en 3D con a Z-Buffer (que es lo que FMX y la mayoría de las aplicaciones 3D están usando).

Para una explicación técnica, puede leer acerca de Transparency sorting, el artículo es sobre OpenGL, pero también se aplica a DirectX.

Para obtener una representación correcta, debe tener sus objetos semitransparentes ordenados al frente desde el punto de vista de la cámara.

usted puede obtener más detalles y un poco de código en este post para solucionar el problema:

Rendering semi-transparent object in FireMonkey

pero tenga en cuenta que sólo será una solución.

ideal sería que esto debe ser manejado por el FireMonkey escena gráfica, ya que es la representación dependiente, de lo contrario, al final tener que cambiar la estructura de la escena-gráfico, que puede tener varios otros efectos secundarios, y es aún más problemático si tiene más de una cámara mirando la misma escena.

Además, el enfoque de clasificación sólo funciona con objetos convexos que no se intersecan, y para los que no tienen triple superposición, como en:

Triple Overlap example

para la que no existe ningún clasificación correcta (ninguno de los elementos está enfrente de los demás).

0

Como ya ha descubierto, tiene que dibujar objetos transparentes de atrás hacia adelante.

Al dibujar un objeto transparente, el objeto se dibuja, y se mezcla con los píxeles que están detrás de él.

Esto sucede cuando dibuja de atrás hacia adelante:
Dibuja la imagen roja, se mezcla con el fondo blanco. Puede ver por el color "rosado" en lugar del rojo puro que se mezcla con el fondo blanco. Luego dibuja la imagen verde, se mezcla con el fondo blanco ya dibujado y la imagen roja. Finalmente dibuja la imagen azul, que se mezcla con los objetos ya dibujados.

Pero ahora dibujamos de adelante hacia atrás:
Primero dibujamos el plano rojo. Se mezcla con el fondo blanco que puedes ver porque es de color rosa en lugar de rojo. Ahora dibujamos el plano verde. Se mezcla con el fondo blanco, se puede decir por el color, no es puro, profundo, verde. Pero, el renderizador ve que una parte cae detrás del plano rojo, por lo que no dibuja esa parte. Pero, piensas: ¡el avión rojo es transparente, el procesador debería dibujar detrás de ese plano rojo! Bueno, no, el renderizador solo realiza un seguimiento de la profundidad/orden z de los píxeles en z-buffer/depth-buffer, no sabe si ese pixel es transparente o no. La misma historia va para el plano azul, solo se dibuja la parte que no está oscurecida por otros objetos.

¿De qué está hablando este búfer de profundidad?
En el buffer de profundidad se almacena la profundidad de cada píxel. Cuando dibuja un píxel a 2,2 con un az de 1, el buffer de profundidad a 2,2 se actualiza con el valor 1. Ahora, cuando dibuja una línea de 1,2 a 3,2 con un az de 3, el renderizador solo dibujará los píxeles donde el buffer de profundidad tiene un valor de> = 3. Entonces se dibuja el píxel 1,2 (y el buffer de profundidad a 1,2 se establece en 3). El píxel 2,2 no se dibuja, porque el buffer de profundidad indica que ese píxel ya se dibujó con una profundidad menor (1 frente a 3). Se dibuja el píxel 3,2 y el buffer de profundidad a 3,2 se establece en 3.
Así que el buffer de profundidad se utiliza para realizar un seguimiento del orden z de cada píxel para evitar sobrescribir ese píxel con un píxel que es más lejos.

Si desea dibujar objetos transparentes de la manera correcta, consulte this answer.

extracto de esa respuesta:

  • primer sorteo objetos opacos.
  • Deshabilitar las escrituras del búfer de profundidad (para que el búfer de profundidad no se actualice), pero mantener habilitada la comprobación del búfer de profundidad.
  • Dibuja objetos transparentes. Debido a que el buffer de profundidad no se actualiza, no tiene el problema de que los objetos transparentes se oscurezcan entre sí.Como la comprobación del búfer de profundidad está habilitada, no dibuja detrás de objetos opacos.

No sé si FireMonkey admite la desactivación de las escrituras del buffer de profundidad, tiene que descubrirlo usted mismo.

Cuestiones relacionadas