Niebla de píxeles (Direct3D 9)

La niebla de píxeles obtiene su nombre del hecho de que se calcula por píxel en el controlador del dispositivo. Esto es diferente de la niebla de vértices, que se calcula mediante la canalización durante los cálculos de transformación e iluminación. A veces, la niebla de píxeles se denomina niebla de tabla porque algunos controladores usan una tabla de búsqueda precalculada para determinar el factor de niebla, utilizando la profundidad de cada píxel para aplicar en cálculos de mezcla. Se puede aplicar mediante cualquier fórmula de niebla identificada por los miembros del tipo enumerado D3DFOGMODE . Las implementaciones de estas fórmulas son específicas del controlador. Si un controlador no admite una fórmula compleja de niebla, debe degradarse a una fórmula menos compleja.

Eye-Relative frente a profundidad basada en Z

Para aliviar los artefactos gráficos relacionados con la niebla causados por la distribución desigual de valores z en un búfer de profundidad, la mayoría de los dispositivos de hardware usan profundidad relativa a los ojos en lugar de valores de profundidad basados en z para la niebla de píxeles. La profundidad relativa a los ojos es esencialmente el elemento w de un conjunto de coordenadas homogéneo. Microsoft Direct3D toma la recíproca del elemento RHW de un conjunto de coordenadas de espacio de dispositivo para reproducir true w. Si un dispositivo admite niebla relativa a los ojos, establece la marca D3DPRASTERCAPS_WFOG en el miembro RasterCaps de la estructura D3DCAPS9 al llamar al método IDirect3DDevice9::GetDeviceCaps . A excepción del rasterizador de referencia, los dispositivos de software siempre usan z para calcular efectos de niebla de píxeles.

Cuando se admite la niebla relativa a los ojos, el sistema usa automáticamente la profundidad relativa a los ojos en lugar de la profundidad basada en z si la matriz de proyección proporcionada genera valores z en el espacio mundial que son equivalentes a los valores w en el espacio del dispositivo. Para establecer la matriz de proyección, llame al método IDirect3DDevice9::SetTransform , utilizando el valor de D3DTS_PROJECTION y pasando una estructura D3DMATRIX que representa la matriz deseada. Si la matriz de proyección no es compatible con este requisito, los efectos de niebla no se aplican correctamente. Para obtener más información sobre cómo generar una matriz compatible, vea Transformación de proyección (Direct3D 9).

Direct3D usa la matriz de proyección establecida actualmente en sus cálculos de profundidad basados en w. Como resultado, una aplicación debe establecer una matriz de proyección compatible para recibir las características deseadas basadas en w, incluso si no usa la canalización de transformación Direct3D.

Direct3D comprueba la cuarta columna de la matriz de proyección. Si los coeficientes son [0,0,0,1] (para una proyección afín), el sistema usará valores de profundidad basados en Z para niebla. En este caso, también debe especificar las distancias de inicio y finalización para efectos de niebla lineales en el espacio del dispositivo, que oscila entre 0,0 en el punto más cercano al usuario y 1,0 en el punto más lejano.

Uso de niebla de píxeles

Siga estos pasos para habilitar la niebla de píxeles en la aplicación.

  1. Habilite la fusión de niebla estableciendo el estado de representación del D3DRS_FOGENABLE en TRUE.
  2. Establezca el color de niebla deseado en el estado de representación D3DRS_FOGCOLOR.
  3. Elija la fórmula de niebla que se usará estableciendo el estado de representación D3DRS_FOGTABLEMODE en el miembro correspondiente del tipo enumerado D3DFOGMODE .
  4. Establezca los parámetros de niebla según sea necesario para el modo de niebla seleccionado en los estados de representación asociados. Esto incluye las distancias de inicio y final para niebla lineal y densidad de niebla para el modo de niebla exponencial.

En el ejemplo siguiente se muestra el aspecto de estos pasos en el código.

// For brevity, error values in this example are not checked 
//   after each call. A real-world application should check 
//   these values appropriately.
//
// For the purposes of this example, g_pDevice is a valid
//   pointer to an IDirect3DDevice9 interface.
void SetupPixelFog(DWORD Color, DWORD Mode)
{
    float Start   = 0.5f;    // For linear mode
    float End     = 0.8f;
    float Density = 0.66f;   // For exponential modes
 
    // Enable fog blending.
    g_pDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
 
    // Set the fog color.
    g_pDevice->SetRenderState(D3DRS_FOGCOLOR, Color);
    
    // Set fog parameters.
    if( Mode == D3DFOG_LINEAR )
    {
        g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGSTART, *(DWORD *)(&Start));
        g_pDevice->SetRenderState(D3DRS_FOGEND,   *(DWORD *)(&End));
    }
    else
    {
        g_pDevice->SetRenderState(D3DRS_FOGTABLEMODE, Mode);
        g_pDevice->SetRenderState(D3DRS_FOGDENSITY, *(DWORD *)(&Density));
    }

Algunos parámetros de niebla son necesarios como valores de punto flotante, aunque el método IDirect3DDevice9::SetRenderState solo acepte valores DWORD en el segundo parámetro. En el ejemplo anterior se proporcionan los valores de punto flotante a IDirect3DDevice9::SetRenderState sin traducción de datos mediante la conversión de las direcciones de las variables de punto flotante como punteros DWORD y, a continuación, desreferenciarlos.

Tipos de niebla