Implementing Fog in Direct3D Douglas Rogers NVIDIA Corportaion

Similar documents
CSE 167: Introduction to Computer Graphics Lecture #5: Rasterization. Jürgen P. Schulze, Ph.D. University of California, San Diego Fall Quarter 2015

For each question, indicate whether the statement is true or false by circling T or F, respectively.

Rendering If we have a precise computer representation of the 3D world, how realistic are the 2D images we can generate? What are the best way to mode

Projection and viewing. Computer Graphics CSE 167 Lecture 4

Real Time Reflections Han-Wei Shen

CSE 167: Introduction to Computer Graphics Lecture #5: Projection. Jürgen P. Schulze, Ph.D. University of California, San Diego Fall Quarter 2017

CS 4620 Midterm, March 21, 2017

Computer Graphics. Lecture 02 Graphics Pipeline. Edirlei Soares de Lima.

More 3D - Overview. Alpha Blending (Transparency)

Rasterization Overview

CSE 167: Introduction to Computer Graphics Lecture #9: Visibility. Jürgen P. Schulze, Ph.D. University of California, San Diego Fall Quarter 2018

CS 130 Final. Fall 2015

Pipeline Operations. CS 4620 Lecture 10

graphics pipeline computer graphics graphics pipeline 2009 fabio pellacini 1

graphics pipeline computer graphics graphics pipeline 2009 fabio pellacini 1

C P S C 314 S H A D E R S, O P E N G L, & J S RENDERING PIPELINE. Mikhail Bessmeltsev

Robust Stencil Shadow Volumes. CEDEC 2001 Tokyo, Japan

Shadow Algorithms. CSE 781 Winter Han-Wei Shen

Pipeline Operations. CS 4620 Lecture Steve Marschner. Cornell CS4620 Spring 2018 Lecture 11

CS451Real-time Rendering Pipeline

CS 112 The Rendering Pipeline. Slide 1

COMS 4160: Problems on Transformations and OpenGL

Pipeline Operations. CS 4620 Lecture 14

Introduction to Shaders.

Approximating Refraction Kenneth Hurley Please send me comments/questions/suggestions

Clipping. CSC 7443: Scientific Information Visualization

Spring 2011 Prof. Hyesoon Kim

CS GPU and GPGPU Programming Lecture 2: Introduction; GPU Architecture 1. Markus Hadwiger, KAUST

Canonical Shaders for Optimal Performance. Sébastien Dominé Manager of Developer Technology Tools

Real-Time Rendering (Echtzeitgraphik) Michael Wimmer

CS 130 Exam I. Fall 2015

The Rasterization Pipeline

1.2.3 The Graphics Hardware Pipeline

Models and The Viewing Pipeline. Jian Huang CS456

What for? Shadows tell us about the relative locations. Vienna University of Technology 2

Optimizing Direct3D for the GeForce 256 Douglas H. Rogers Please send me your comments/questions/suggestions

Lighting and Shading

Ch 10: Game Event Management. Quiz # 4 Discussion

Spring 2009 Prof. Hyesoon Kim

TSBK03 Screen-Space Ambient Occlusion

Textures. Texture coordinates. Introduce one more component to geometry

CS 130 Exam I. Fall 2015

Shadows in the graphics pipeline

Evolution of GPUs Chris Seitz

Virtual Cameras and The Transformation Pipeline

GPU Programming EE Midterm Examination

Recall: Indexing into Cube Map

CS 4620 Program 3: Pipeline

3D Viewing. CS 4620 Lecture 8

Tutorial on GPU Programming #2. Joong-Youn Lee Supercomputing Center, KISTI

Computergrafik. Matthias Zwicker. Herbst 2010

Advanced Shading I: Shadow Rasterization Techniques

Computer Graphics. Shadows

Midterm Exam Fundamentals of Computer Graphics (COMP 557) Thurs. Feb. 19, 2015 Professor Michael Langer

Viewing with Computers (OpenGL)

Project 1, 467. (Note: This is not a graphics class. It is ok if your rendering has some flaws, like those gaps in the teapot image above ;-)

Module Contact: Dr Stephen Laycock, CMP Copyright of the University of East Anglia Version 1

Texture. Texture Mapping. Texture Mapping. CS 475 / CS 675 Computer Graphics. Lecture 11 : Texture

Lecture 17: Shading in OpenGL. CITS3003 Graphics & Animation

CS 475 / CS 675 Computer Graphics. Lecture 11 : Texture

Projections and Hardware Rendering. Brian Curless CSE 557 Fall 2014

Homework #2 and #3 Due Friday, October 12 th and Friday, October 19 th

Simpler Soft Shadow Mapping Lee Salzman September 20, 2007

Graphics Pipeline 2D Geometric Transformations

CS Exam 1 Review Problems Fall 2017

Real-Time Shadows. Last Time? Textures can Alias. Schedule. Questions? Quiz 1: Tuesday October 26 th, in class (1 week from today!

CMSC427 Advanced shading getting global illumination by local methods. Credit: slides Prof. Zwicker

Fondamenti di Grafica 3D The Rasterization Pipeline.

lecture 21 volume rendering - blending N layers - OpenGL fog (not on final exam) - transfer functions - rendering level surfaces

CS4620/5620: Lecture 14 Pipeline

Practical Shadow Mapping

3D Graphics for Game Programming (J. Han) Chapter II Vertex Processing

Introduction to Computer Graphics with WebGL

CS 4204 Computer Graphics

Triangle Rasterization

Programming Graphics Hardware

Chapter 7 - Light, Materials, Appearance

Clipping and Scan Conversion

Overview. By end of the week:

Models and Architectures

CSE 690: GPGPU. Lecture 2: Understanding the Fabric - Intro to Graphics. Klaus Mueller Stony Brook University Computer Science Department

The Importance of Matrices in the DirectX API. by adding support in the programming language for frequently used calculations.

Underwater Manager (Optional)

Transformation Pipeline

Graphics Hardware. Graphics Processing Unit (GPU) is a Subsidiary hardware. With massively multi-threaded many-core. Dedicated to 2D and 3D graphics

CMSC427: Computer Graphics Lecture Notes Last update: November 21, 2014

6.837 Introduction to Computer Graphics Quiz 2 Thursday November 20, :40-4pm One hand-written sheet of notes allowed

Real Time Atmosphere Rendering for the Space Simulators

3D Viewing. CS 4620 Lecture Steve Marschner. Cornell CS4620 Spring 2018 Lecture 9

Blue colour text questions Black colour text sample answers Red colour text further explanation or references for the sample answers

Shaders. Slide credit to Prof. Zwicker

Real-Time Shadows. Last Time? Today. Why are Shadows Important? Shadows as a Depth Cue. For Intuition about Scene Lighting

3D Computer Games Technology and History. Markus Hadwiger VRVis Research Center

Wire-Frame 3D Graphics Accelerator IP Core. C Library Specification

CSE 167: Introduction to Computer Graphics Lecture #5: Visibility, OpenGL

Page 1. Area-Subdivision Algorithms z-buffer Algorithm List Priority Algorithms BSP (Binary Space Partitioning Tree) Scan-line Algorithms

Perspective Projection and Texture Mapping

Scanline Rendering 2 1/42

Real - Time Rendering. Graphics pipeline. Michal Červeňanský Juraj Starinský

Chapter Answers. Appendix A. Chapter 1. This appendix provides answers to all of the book s chapter review questions.

Transcription:

Implementing Fog in Direct3D Douglas Rogers NVIDIA Corportaion drogers@nvidia.com Fog is a special effect that is used to blend a scene into a predefined color to give the impression that "fog" is present in the scene. Fog is usually implemented as it appears in the physical world. The farther objects are, the more they are obscured by fog. Objects that are close to the observer are clearer. Unfogged Scene Fogged Scene Fog can also be useful to reduce the complexity in a scene. In the above right image, the pegs in the distance might not need to be rendered. Fog Types There are two ways to implement fog, vertex-based fog and table-based fog. In addition, there are additional attributes that control the application of fog. Distance Calculation (Range or Plane Based) Drop Off (Linear, Exponential or Exponential Squared) Z or W based Vertex Fog Using vertex fog, a fog coverage value is calculated for each vertex of a triangle, then interpolated within the triangle.

(Pixel) Fog fog, also called pixel fog, is calculated independent of vertices. Ideally, fog is calculated on a pixel basis, but many device drivers emulate this feature in software with vertex fog values. It is called table fog because traditionally tables have been used to look up fog values. Fog Distance: In addition to fog type, you must specify how the fog distance is calculated. The two methods for specifying fog distance are range and plane based. With linear fog (explained below), fog has a start (fogstart) and an end (fogend). Objects that are closer than fogstart have no fog applied, objects that are greater than fogend are completely fogged. When objects are in between, fog is applied by linearly interpolating from fogstart to fogend. Plane Based Fog Object 3 (Completely Fogged) Plane based fog is calculated as the distance from the viewplane to the object, shown here as d. There can be unwanted artifacts when using plane based fog, however. When an observer rotates about a point, an object may jump in and out of the fog area. Notice that object1 and object2 reverse their presence in the fog area depending on the orientation of the observer. fog_start d Object 1 (not in Fog) viewpoint Object 2 (in Fog) Plane Based Fog d View Plane fog_end Object 2 (in Fog) Object 2 (not in Fog) Object 1 (not in Fog) Object 1 ( in Fog) View Plane View Plane viewpoint viewpoint Before Plane Based Fog Artifact After

Range Based Fog Range based fog addresses the visual artifact that plane based fog introduces. Range based fog diminishes radially from a point, rather than linearly from a plane so objects do not enter and leave the fog area depending on the orientation of the observer. Range based fog is more expensive to calculate than plane based fog. Range based fog cannot be used with table fog. Object 2 (in Fog) Object 2 (in Fog) Object 1 (not in Fog) Object 1 (not in Fog) fog_startt fog_end Before viewpoint After Range Based Fog You enable range based fog with the following call: pd3ddevice->setrenderstate( D3DRENDERSTATE_RANGEFOGENABLE,, TRUE); The following entry from D3DIM.DOC regarding range based fog may be misleading: "If the current device supports range-based fog, it will set the D3DPRASTERCAPS_FOGRANGE capability flag in the dwrastercaps member of the D3DPRIMCAPS structure when you call the IDirect3DDevice3::GetCaps method. To enable range-based fog, set the D3DRENDERSTATE_RANGEFOGENABLE render state to TRUE." D3DPRASTERCAPS_FOGRANGE is not checked by D3D because the range is calculated in software from the matrices. So even if the D3DPRASTERCAPS_FOGRANGE capability bit is not set, you can enable range based fog because the range values are calculated in software.

Visibility Dropoff You must specify how the fog visibility drops off with distance. There are three formulas to specify fog visibility drop-off. These are linear, exponential and exponential squared. The formula are indicated below: LINEAR fogend d f = fogend fogstart Linear fog interpolates from the fogstart to fogend. d is the distance from the observer to the object. EXP 1 f = ( d fogdensity e ) Exponental fog produces a rapid transition for fog. This is controlled only by fogdensity and distance, fogstart and fogend are not used. 1 f = ( d fogdensity e ) 2 Exponental fog produces a sharp transition for fog. This is controlled only by fogdensity and distance, fogstart and fogend are not used. 100% Y D3DFOG_LINEAR D3DFOG_, density =.33 Amount of original color D3DFOG_, density =.66 D3DFOG_EXP, density =.66 D3DFOG_EXP, density =.33 0% X (0.0) Distance (1.0) Near Far plane plane Fog Dropoff (from D3DIM.doc)

How Fog is Applied Fog is turned on by enabling it with: pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGENABLE, TRUE ); The fog color that is applied is a 32 bit color value set with: pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGCOLOR, fogcolor); 0 R G B fogcolor The formula for combining fogcolor with a pixel is: pixel = f C + 1 f ) fogcolor ( Eq. 1 where f is the fog value, C is the pixel before fogging and pixel is the final pixel. Note that when f = 1.0, no fog is applied; when f = 0.0, full fog is applied. This excludes the alpha blending of the color. Vertex Fog As mentioned before, vertex fog is applied on a per vertex basis. The fog applied to a vertex is specified in the 'alpha' field of the specular color component for the vertex. This f value is used the pixel fogging calculation Eq. 1. The value 1.0 is represented as 0xFF and means that there is no fog, only the pixel color C. f R G B specular color (f = fog component) To enable vertex fog, table fog is set to NONE: pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE ); Performing Your Own Vertex Fogging Calculations If you perform your own fogging calculations, you must calculate the fog intensity at each vertex. Place the fog value in the alpha component in the specular color. Turn off the vertex fog mode in the light state and the table mode fog in the render state. // turn off all D3D fogging pd3ddevice->setlightstate( D3DLIGHTSTATE_FOGMODE, D3DFOG_NONE); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE ); The graphics hardware will linearly interpolate the fog values that you have specified, and apply the fog accordingly.

When performing your own fogging calculations, you must send the RHW value to the device driver. This value is used to perform perspectively correct fogging calculations. Note: The interpolation is done without regard to fogstart and fogend. This may produce some unwanted visual problems. If your vertices straddle the fog range, linear interpolation may not be what you expect. Vertex 0 f = 1 Interpolated half-way point f = 0.5 Vertex 1 f = 0 fog_start fog_end Unexpected Fog Values with Vertex Fog Here vertex 0 is closer than the fogstart, so f is set to one (no fog). Vertex 1 is beyond the fogend, so f is set to zero (completely fogged). When this is interpolated, the halfway point will be half fogged, but this is not necessarily halfway into the fog region. Since you cannot specify fog values out side of the region zero and one, this generates visual artifacts. If you wish, you can solve this by clipping your objects to the fog planes and introducing new vertices at the fogstart and fogend boundaries. Below vertex two and vertex three are introduced at the fog boundaries to allow the vertex fog to be correctly interpolated.

Vertex 2 f = 1 Vertex 3 f = 0 Vertex 0 f = 1 Interpolated f = 0.5 Vertex 1 f = 0 fog_start fog_end Introducing Vertices to Correct Vertex Fog Interpolation Errors You can tesselate your geometry to a greater degree to reduce this problem, too. Using D3D to Perform Vertex Fogging If you are using Direct3D to perform vertex fogging, it is controlled through the light state interface. D3D will calculate the fog values relative to fogstart and fogend and place them in the fog component of the specular color. D3D currently only supports linear based vertex fog so you must turn off table mode fog, specify linear vertex fog and set the vertex fogstart and fogend values. Fogdensity is only used for exponential fog mode so does not need to be specified for linear fog. For DirectX 6.0 // disable table fog pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE ); // select linear vertex fog pd3ddevice->setlightstate( D3DLIGHTSTATE_FOGMODE, D3DFOG_LINEAR); pd3ddevice ->SetLightState(D3DLIGHTSTATE_FOGSTART, *(DWORD *)&vertex_fogstart); pd3ddevice ->SetLightState(D3DLIGHTSTATE_FOGEND, *(DWORD *)&vertex_fogend); // not currently used pd3ddevice ->SetLightState(D3DLIGHTSTATE_FOGDENSITY, *(DWORD *)&vertex_fogdensity ); D3DLIGHTSTATE_FOGSTART, D3DLIGHTSTATE_FOGSTART and D3DLIGHTSTATE_FOGDENSITY require floating point values, but the interface to SetLightState is a DWORD value, so we cast the parameter to a DWORD. For DirectX 7.0, a vertex based fog renderstate has been added. pd3ddevice->setrenderstate(d3drenderstate_fogvertexmode, D3DFOG_LINEAR); pd3ddevice->setrenderstate(d3drenderstate_fogstart, *(DWORD *)&vertexfogstart);

pd3ddevice->setrenderstate(d3drenderstate_fogend, *(DWORD *)&vertexfogend); pd3ddevice->setrenderstate(d3drenderstate_fogdensity, *(DWORD *)&vertexfogdensity); Because D3D does not introduce extra vertices and fog values cannot be less than zero or greater than one, vertex fogging will suffer from the interpolation problem described above when using D3D's linear vertex fogging calculations.

D3D Code to set the vertex fog values: // computes range or plane distance D3DVALUE ComputeDistance(D3DVECTOR &v) { if (dwflags & D3DPV_RANGEBASEDFOG) { D3DVALUE x,y,z; x = v.x * m._11 + v.y * m._21 + v.z * m._31 + m._41; y = v.x * m._12 + v.y * m._22 + v.z * m._32 + m._42; z = v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43; return SQRTF(x * x + y * y + z * z); } else return v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43; } #define D3DFE_SET_ALPHA(color, a) ((char*)&color)[3] = (unsigned char)a; fogfactor = 255.0 / (fogend - fogstart); // return value from ComputeDistance is passed to FOG_VERTEX inline void FOG_VERTEX(D3DVALUE d) { int f; } if (d < fogstart) D3DFE_SET_ALPHA(Specular, 255) else if (d >= fogend) D3DFE_SET_ALPHA(Specular, 0) else { D3DVALUE v = (fogend - d) * fogfactor; f = FTOI(v); D3DFE_SET_ALPHA(Specular, f) }

(Pixel) Fog fog parameters are set through the SetRenderState interface. Range based fog is not supported when using table mode and must be disabled. Disable vertex fog as well. The RIVA 128, RIVA128ZX and the RIVA TNT all emulate table fog using vertex based fog. The GeForce 256 supports table fog in hardware. To use table based fog, you must select which drop off method to use linear, exponential or exponential squared. fog cannot be combined with range based fog. // disable vertex fog pd3ddevice->setlightstate( D3DLIGHTSTATE_FOGMODE, D3DFOG_NONE ); // must disable range based fog pd3ddevice->setrenderstate( D3DRENDERSTATE_RANGEFOGENABLE, FALSE ); // // FogMode = D3DFOG_ D3DFOG_ or D3DFOG_LINEAR // pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, FogMode ); // table)fogstart and table_fogend are not used with exponential fog pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLESTART, *(DWORD *)&table_fogstart); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEEND, *(DWORD *)&table_fogend); // table_fogdensity is not used with linear table fog pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEDENSITY, *(DWORD *)&table_fogdensity); Z based or W based Fog using D3D fogging. When a vertex is passed to D3D to be transformed, the projection matrix is used. Based on this matrix, screen coordinates and a homogeneous W are created. The screen Z (sz) coordinate has a range from zero to one and W is specified (in eye space) as a scaled distance to the observer. For more information about projection matrices, see my papers "W-Buffering" and " Z-buffering, Interpolation and More W-buffering". Z Based Fog When the fog distance is calculated by D3D, the projection matrix is examined and a determination is made whether to use Z based or W based fog. If the projection matrix is affine, then Z based fog is calculated otherwise W based fog is implemented. 0 0 0 1 Affine Matrix ('-' is don't care.) The projection matrix is determined to be affine if the fourth column is [0, 0, 0, 1]. When this occurs, Z based fog is used and the values for fogstart and fogend range from [0, 1].

W Based Fog Normally, you will want to use W based fog with a standard projection matrix. However, there are some restrictions on the projection matrix that you provide to D3D to use for your transformations. If the projection matrix includes a (3,4) coefficient that is not 1, you must scale all coefficients by the inverse of the (3,4) coefficient to produce a compatible matrix. If you don't provide a compliant matrix, fog effects will not be applied correctly. Theoretically, the capability D3DPRASTERCAPS_WFOG must be available to use this mode, but it does not appear that it is checked in D3D, so any non-affine projection matrix should use W fog. c 0 M = 0 0 0 c 0 0 0 0 Q Qz n 0 0 s 0 Incorrect Projection Matrix for Accurate W Based Fog c 0 0 0 s 0 c 0 0 s M = 0 0 Q 1 Qz s 0 0 n 0 s Correct Projection Matrix for Accurate W based Fog The reason to scale the matrix is so the W value is actual distance to the object. Using matrix M, W = s * Z, not W = Z which is what we want. When you use W based fog, fogend and fogstart are specified in world coordinates. Fog Index Calculation Computing the distance d that is used in the above calculations, in D3D, is basically: Float d, Wnear, Wfar; // m is the projection matrix WNear = m._44 - m._43 / m._33 * m._34; WFar = (m._44 - m._43) / (m._33 - m._34) * m._34 + m._44; if (( 1.0f == Wnear ) && ( 1.0f == Wfar ) ) // affine matrix { // use clamped Z for affine projection d = sz; // screen z clamped to [znear, zfar] } else // use W for non-affine projection d = 1.0/ RHW; // reciprocal of homogeneous W

Example As an example of how to set the fog parameters, here is the code from the MFCFOG example. inline DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); } pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGENABLE, TRUE ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGCOLOR, g_dwfogcolor ); in DirectX 6.0 if( g_busingfog ) { pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLESTART, FtoDW(g_fFogStart) ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEEND, FtoDW(g_fFogEnd) ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEDENSITY, FtoDW(g_fFogDensity) ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, g_dwfogmode ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGMODE, D3DFOG_NONE ); } else { pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGSTART, FtoDW(g_fFogStart) ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGEND, FtoDW(g_fFogEnd) ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGMODE, g_dwfogmode ); pd3ddevice->setrenderstate( D3DRENDERSTATE_RANGEFOGENABLE, g_brangebasedfog ); pd3ddevice->setrenderstate( D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE ); }

This is table of the possible fog modes available in D3D and the parameters required to achieve the mode. Use this table when D3D is perform the fogging calculations. Parameters Lighting Mode Vertex Z based Plane Direct3D Calculated Fog Vertex Z based Range Vertex W based Plane Vertex W based Range Z based Plane Z based Range W based Plane W based Range D3DLIGHTSTATE_FOGMODE LINEAR LINEAR LINEAR LINEAR NONE NONE NONE NONE D3DLIGHTSTATE_FOGSTART [0, 1] [0, 1] world World - - - - D3DLIGHTSTATE_FOGEND [0, 1] [0, 1] world World - - - - D3DLIGHTSTATE_FOGDENSITY 2 n/u n/u n/u n/u - - - - D3DRENDERSTATE_FOGTABLEMODE 3 NONE NONE NONE NONE LINEAR, LINEAR, LINEAR, LINEAR, D3DRENDERSTATE_FOGTABLESTART - - - - [0, 1] [0, 1] world world D3DRENDERSTATE_FOGTABLEEND - - - - [0, 1] [0, 1] world world D3DRENDERSTATE_FOGTABLEDENSITY - - - - [0, 1] [0, 1] [0, 1] [0, 1] D3DRENDERSTATE_RANGEFOGENABLE 7 FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE Perspective Projection Matrix and No No Yes Yes No No Yes Yes D3DPRASTERCAPS_WFOG 6 Notes: 5, 9 5, 9 4, 9 4, 9 5, 8 1 4, 8 1 Notes: 1. Direct3D performs range-based fog only when using vertex fog with the Direct3D transformation and lighting engine. This is not a legal mode. 2. D3DLIGHTSTATE_FOGDENSITY is not used because the only vertex fog mode is linear which does not use the density component. 3. Setting D3DRENDERSTATE_FOGTABLEMODE to D3DFOG_NONE enables vertex fog. 4. W based fog. Projection matrix must be normalized about the entry (3, 4). See W Based Fog above. Fog parameters are in world coordinates. 5. Z based fog. Fog parameters range between zero and one. 6. It does not appear that D3DPRASTERCAPS_WFOG is checked for by D3D, it may actually be forced to enabled. No means an affine matrix 7. D3DPRASTERCAPS_FOGRANGE is not checked by D3D because all the vertex range calculations are done in software and set in the vertex. 8. D3DPRASTERCAPS_FOGTABLE capability must exist. 9. D3DPRASTERCAPS_FOGVERTEX capability must exist. Key: [0, 1] values range from zero to one, inclusive world values are specified in world coordinates n/u not used in the current implementation.

Parameters Lighting Mode Application Calculated Fog Vertex Z based Plane Z based Range W based Plane W based Range D3DLIGHTSTATE_FOGMODE NONE NONE NONE NONE NONE D3DLIGHTSTATE_FOGSTART - - - - - D3DLIGHTSTATE_FOGEND - - - - - D3DLIGHTSTATE_FOGDENSITY - - - - - D3DRENDERSTATE_FOGTABLEMODE NONE LINEAR, LINEAR, LINEAR, LINEAR, D3DRENDERSTATE_FOGTABLESTART - [0, 1] [0, 1] world world D3DRENDERSTATE_FOGTABLEEND - [0, 1] [0, 1] world world D3DRENDERSTATE_FOGTABLEDENSITY - [0, 1] [0, 1] [0, 1] [0, 1] D3DRENDERSTATE_RANGEFOGENABLE 7 - FALSE TRUE FALSE TRUE Perspective Projection Matrix and - No No Yes Yes D3DPRASTERCAPS_WFOG 2 Notes: 1 3 3, 4 3 3, 4 Notes: 1. Fog values are placed in the alpha component of the specular color and linearly interpolated. RHW must be set for the vertex. Range and distance calculations have already been made. 2. You must still set the perspective projection matrix so that Wnear and Wfar are initialized. 3. This is emulated with vertex fog in the RIVA128, RIVA128ZX and RIVATNT 4. Range Based Fog is not supported