mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-20 07:31:56 +00:00
817 lines
20 KiB
C++
817 lines
20 KiB
C++
|
/**********************************************************************************************
|
|||
|
*
|
|||
|
* Copyright <EFBFBD> DreamWorks Interactive. 1996
|
|||
|
*
|
|||
|
* Contents:
|
|||
|
* Classes for using, or not using, Gouraud shading in raster primitives.
|
|||
|
*
|
|||
|
* Notes:
|
|||
|
*
|
|||
|
* To Do:
|
|||
|
*
|
|||
|
**********************************************************************************************
|
|||
|
*
|
|||
|
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/GouraudT.hpp $
|
|||
|
*
|
|||
|
* 28 98.09.19 12:39a Mmouni
|
|||
|
* Added "forceinline" to many small inline functions.
|
|||
|
* Inlined some functions for speed.
|
|||
|
*
|
|||
|
* 27 8/25/98 3:06p Rvande
|
|||
|
* Qualified fixed as being in the global scope
|
|||
|
*
|
|||
|
* 26 98.04.08 8:42p Mmouni
|
|||
|
* Added support for fogged dithered flat shaded primitive.
|
|||
|
*
|
|||
|
* 25 98.02.17 10:20p Mmouni
|
|||
|
* Gouraud shaded gradient is now zeroed if gradients from any two subtriangles have different
|
|||
|
* signs.
|
|||
|
*
|
|||
|
* 24 98/01/02 17:22 Speter
|
|||
|
* Added safety check before setting iNumIntensities.
|
|||
|
*
|
|||
|
* 23 97/11/06 4:49p Pkeet
|
|||
|
* Added class 'CGouraudFog.'
|
|||
|
*
|
|||
|
* 22 97.10.15 7:41p Mmouni
|
|||
|
* Removed support for right to left scanlines.
|
|||
|
*
|
|||
|
* 21 97/10/13 2:16p Pkeet
|
|||
|
* Fixed bug with alpha.
|
|||
|
*
|
|||
|
* 20 97/10/12 20:41 Speter
|
|||
|
* Replaced rvIntensity with cvIntensity, pre-scaled. Removed SetNumIntensities().
|
|||
|
* iNumIntensities is a debug-only variable.
|
|||
|
*
|
|||
|
* 19 97/08/05 14:19 Speter
|
|||
|
* Slightly optimised polygon vertex setup by adding InitializeVertexData() functions.
|
|||
|
*
|
|||
|
* 18 97/07/16 15:54 Speter
|
|||
|
* InitializeTriangleData now takes two params to use as coefficients in derivative calculation
|
|||
|
* rather than f_invdx; also takes b_update parameter to use for multiple-triangle gradient
|
|||
|
* calculations. Added AssertXRange function to test the validity of a single scanline.
|
|||
|
*
|
|||
|
* 17 97/07/07 14:05 Speter
|
|||
|
* Now copy vertices for current polygon locally to arvRasterVertices, and set rvIntensity to
|
|||
|
* scaled intensity.
|
|||
|
*
|
|||
|
* 16 97/06/27 15:31 Speter
|
|||
|
* Added new CGouraudNone, which does no base intensity calculation. CGouraudOff now uses
|
|||
|
* polygon's rvFace rather than averaging vertices. Moved code into new
|
|||
|
* InitializePolygonData(), added bIsPlanar().
|
|||
|
*
|
|||
|
* 15 6/26/97 9:59a Mlange
|
|||
|
* Now uses the (fast) float to int conversion functions.
|
|||
|
*
|
|||
|
* 14 97/06/23 20:31 Speter
|
|||
|
* Made gcfScreen a static member of CScreenRender.
|
|||
|
*
|
|||
|
* 13 6/16/97 8:35p Mlange
|
|||
|
* Updated for fixed::fxFromFloat() name change.
|
|||
|
*
|
|||
|
* 12 97/01/20 11:51 Speter
|
|||
|
* Moved gcfScreen from CScreenRender to a global var for this rasteriser.
|
|||
|
*
|
|||
|
* 11 97/01/16 11:55 Speter
|
|||
|
* Updated for CScreenRender changes.
|
|||
|
*
|
|||
|
* 10 97/01/07 12:05 Speter
|
|||
|
* Updated for ptr_const.
|
|||
|
*
|
|||
|
* 9 96/12/31 17:04 Speter
|
|||
|
* Changed some pointers to ptr<>.
|
|||
|
*
|
|||
|
* 8 96/12/17 13:17 Speter
|
|||
|
* Added gamma correction code.
|
|||
|
* Moved extern fClutRampScale declaration to DrawTriangle.hpp.
|
|||
|
*
|
|||
|
* 7 10/14/96 11:47a Pkeet
|
|||
|
* Maded statically declared global variables externally declared global variables.
|
|||
|
*
|
|||
|
* 6 10/09/96 7:38p Pkeet
|
|||
|
* Added constructors.
|
|||
|
*
|
|||
|
* 5 10/04/96 5:36p Pkeet
|
|||
|
* Added an abstract base class. Added the '-' operator member function.
|
|||
|
*
|
|||
|
* 4 10/03/96 6:17p Pkeet
|
|||
|
* Added the 'iBaseIntensity' variable to the module.
|
|||
|
*
|
|||
|
* 3 10/03/96 3:16p Pkeet
|
|||
|
* Moved constants and static global variables associated with Gouraud shading here.
|
|||
|
*
|
|||
|
* 2 10/01/96 3:18p Pkeet
|
|||
|
* Enabled the 'iInitializeTriangleData' function to work without a texture pointer. This would
|
|||
|
* occur when using the LineBumpMake raster drawing routine.
|
|||
|
*
|
|||
|
* 1 9/27/96 4:32p Pkeet
|
|||
|
* Initial implementation.
|
|||
|
*
|
|||
|
*********************************************************************************************/
|
|||
|
|
|||
|
#ifndef HEADER_LIB_RENDERER_PRIMITIVES_GOURAUDT_HPP
|
|||
|
#define HEADER_LIB_RENDERER_PRIMITIVES_GOURAUDT_HPP
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Constants.
|
|||
|
//
|
|||
|
const float fGouraudTolerance = 0.05f;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Static variables used for assembly coding.
|
|||
|
//
|
|||
|
|
|||
|
// Floating and fixed point representation of intensity step values with respect to x.
|
|||
|
extern float fDeltaXIntensity;
|
|||
|
extern ::fixed fxDeltaXIntensity;
|
|||
|
|
|||
|
// Value for modulus subtract.
|
|||
|
extern ::fixed fxIModDiv;
|
|||
|
|
|||
|
#if VER_DEBUG
|
|||
|
// Maximum intensity value (range-checking only).
|
|||
|
#include "Lib/Renderer/Fog.hpp"
|
|||
|
extern int iNumIntensities;
|
|||
|
#endif
|
|||
|
|
|||
|
// Base intensity value for the triangle.
|
|||
|
extern int iBaseIntensity;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Class definitions.
|
|||
|
//
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CGouraudNone
|
|||
|
//
|
|||
|
// Defines a base class for Gouraud shading.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
public:
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
// CGouraudNone member functions.
|
|||
|
//
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudNone
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudNone
|
|||
|
(
|
|||
|
const CGouraudNone& gour
|
|||
|
)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline uint32 u4Offset
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns the offset into the clut for a given intensity.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
void AssertRange
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
void AssertXRange
|
|||
|
(
|
|||
|
int i_xrange
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void operator +=
|
|||
|
(
|
|||
|
const CGouraudNone& gour // Amount to increment intensity by.
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void operator -
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void ModulusSubtract
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
forceinline void operator ++
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
static forceinline bool bIsPlanar()
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// Whether this feature has planar gradients across any polygon.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
static forceinline bool bGouraudFog()
|
|||
|
//
|
|||
|
// Returns 'true' if this class is used for fogging.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializePolygonData
|
|||
|
(
|
|||
|
ptr_const<CTexture> ptex, // Texture for polygon.
|
|||
|
TClutVal cv_face // Face-wide lighting.
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
iBaseIntensity = 0;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeVertexData
|
|||
|
(
|
|||
|
SRenderVertex* prv_src,
|
|||
|
SRenderVertex* prv_dst
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeTriangleData
|
|||
|
(
|
|||
|
SRenderVertex* prv_1, // First of three non-colinear coordinates describing the
|
|||
|
// plane of the triangle in screen coordinates.
|
|||
|
SRenderVertex* prv_2, // Second coordinate describing the plane.
|
|||
|
SRenderVertex* prv_3, // Third coordinate describing the plane.
|
|||
|
float f_yab_invdx, // Multipliers for gradients.
|
|||
|
float f_yac_invdx,
|
|||
|
bool b_update = false // Modify the gradients rather than setting them.
|
|||
|
)
|
|||
|
//
|
|||
|
// Sets the average intensity across the triangle.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeAsBase
|
|||
|
(
|
|||
|
const SRenderVertex* prv_from,
|
|||
|
const SRenderVertex* prv_to,
|
|||
|
float f_inverse_dy,
|
|||
|
float f_start_y,
|
|||
|
float f_x_difference,
|
|||
|
CGouraudNone* pgour_increment,
|
|||
|
float f_xdiff_increment
|
|||
|
)
|
|||
|
//
|
|||
|
// Does nothing.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CGouraudOff: public CGouraudNone
|
|||
|
//
|
|||
|
// Defines a class which applies constant lighting, without Gouraud shading.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
public:
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
// CGouraudOff member functions.
|
|||
|
//
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializePolygonData
|
|||
|
(
|
|||
|
ptr_const<CTexture> ptex, // Texture for polygon.
|
|||
|
TClutVal cv_face // Face-wide lighting.
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
iBaseIntensity = iPosFloatCast(cv_face);
|
|||
|
#if VER_DEBUG
|
|||
|
iNumIntensities = 0;
|
|||
|
if (ptex && ptex->ppcePalClut && ptex->ppcePalClut->pclutClut)
|
|||
|
{
|
|||
|
iNumIntensities = ptex->ppcePalClut->pclutClut->iNumRampValues;
|
|||
|
Assert(iBaseIntensity < ptex->ppcePalClut->pclutClut->iNumRampValues);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CGouraudOn : public CGouraudNone
|
|||
|
//
|
|||
|
// Defines a class for rasterizing primitives with Gouraud shading.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
public:
|
|||
|
|
|||
|
::fixed fxIntensity;
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
// CGouraudOn member functions.
|
|||
|
//
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudOn
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudOn
|
|||
|
(
|
|||
|
const CGouraudOn& gour
|
|||
|
)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
fxIntensity = gour.fxIntensity;
|
|||
|
AssertRange();
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void operator +=
|
|||
|
(
|
|||
|
const CGouraudOn& gour // Amount to increment intensity by.
|
|||
|
)
|
|||
|
//
|
|||
|
// Increments intensity by an amount.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
fxIntensity += gour.fxIntensity;
|
|||
|
AssertRange();
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void operator -
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Negates the sign of the modulus subtraction factor.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
fxIModDiv = -fxIModDiv;
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline void ModulusSubtract
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Perform modulus subtraction.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
fxIntensity += fxIModDiv;
|
|||
|
AssertRange();
|
|||
|
}
|
|||
|
|
|||
|
forceinline void operator ++
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Increments the intensity value for the next position on the horizontal scanline.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
fxIntensity += fxDeltaXIntensity;
|
|||
|
AssertRange();
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline uint32 u4Offset
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Returns the offset into the clut for a given intensity.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
// Check that the intensity is in a valid range.
|
|||
|
AssertRange();
|
|||
|
|
|||
|
return uint32(int(fxIntensity)) << 8;
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
void AssertRange
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
// Uses asserts to check the if the value of an intensity is valid.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
/*
|
|||
|
Assert(fxIntensity >= fixed(0));
|
|||
|
Assert(fxIntensity < fixed(iNumIntensities));
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
void AssertXRange
|
|||
|
(
|
|||
|
int i_xrange
|
|||
|
)
|
|||
|
//
|
|||
|
// Uses asserts to check if the range of intensities for this scanline is valid.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
#if VER_DEBUG
|
|||
|
/*
|
|||
|
// Check starting value.
|
|||
|
AssertRange();
|
|||
|
|
|||
|
// Check ending value.
|
|||
|
fixed fx_end = fxIntensity + fxDeltaXIntensity * fixed(i_xrange);
|
|||
|
Assert(fx_end >= fixed(0));
|
|||
|
Assert(fx_end < fixed(iNumIntensities));
|
|||
|
*/
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
static forceinline bool bIsPlanar()
|
|||
|
//
|
|||
|
// Returns:
|
|||
|
// Whether this feature has planar gradients across any polygon.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializePolygonData
|
|||
|
(
|
|||
|
ptr_const<CTexture> ptex, // Texture for polygon.
|
|||
|
TClutVal cv_face // Face-wide lighting.
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
#if VER_DEBUG
|
|||
|
iNumIntensities = 0;
|
|||
|
if (ptex && ptex->ppcePalClut && ptex->ppcePalClut->pclutClut)
|
|||
|
iNumIntensities = ptex->ppcePalClut->pclutClut->iNumRampValues;
|
|||
|
#endif
|
|||
|
iBaseIntensity = 0;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeVertexData
|
|||
|
(
|
|||
|
SRenderVertex* prv_src,
|
|||
|
SRenderVertex* prv_dst
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
prv_dst->cvIntensity = prv_src->cvIntensity;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeTriangleData
|
|||
|
(
|
|||
|
SRenderVertex* prv_1, // First of three non-colinear coordinates describing
|
|||
|
// the plane of the triangle in screen coordinates.
|
|||
|
SRenderVertex* prv_2, // Second coordinate describing the plane.
|
|||
|
SRenderVertex* prv_3, // Third coordinate describing the plane.
|
|||
|
float f_yab_invdx, // Multipliers for gradients.
|
|||
|
float f_yac_invdx,
|
|||
|
bool b_update = false // Modify the gradients rather than setting them.
|
|||
|
)
|
|||
|
//
|
|||
|
// Setup up triangle-wide data for a Gouraud-shaded triangle; specifically setting the step
|
|||
|
// value with respect to the 'x' axis for intensity and finding the base address in the clut
|
|||
|
// for the colour.
|
|||
|
//
|
|||
|
// Returns 0.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
Assert(prv_1);
|
|||
|
Assert(prv_2);
|
|||
|
Assert(prv_3);
|
|||
|
|
|||
|
//
|
|||
|
// Find the step value for intensity with respect to the horizontal axis.
|
|||
|
//
|
|||
|
float f_di_invdx = (prv_2->cvIntensity - prv_1->cvIntensity) * f_yac_invdx -
|
|||
|
(prv_3->cvIntensity - prv_1->cvIntensity) * f_yab_invdx;
|
|||
|
|
|||
|
if (b_update)
|
|||
|
{
|
|||
|
// If the sign of two gradients is different, then use zero.
|
|||
|
if (CIntFloat(f_di_invdx).bSign() != CIntFloat(fDeltaXIntensity).bSign())
|
|||
|
{
|
|||
|
fDeltaXIntensity = 0.0f;
|
|||
|
fxDeltaXIntensity = 0;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Skip update if we already have a smaller value.
|
|||
|
if (fabs(f_di_invdx) >= fabs(fDeltaXIntensity))
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
fDeltaXIntensity = f_di_invdx;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that intensity does not exceed the maximum ramp value of the clut.
|
|||
|
// This clamping is necessary because triangles that are viewed almost edge on can
|
|||
|
// generate very large values for fDeltaXIntensity -- resulting in small inaccuracies
|
|||
|
// that cause texture coordinates to go out-of-range.
|
|||
|
//
|
|||
|
// It can be assumed that if intensity is actually larger than the ramp value of the
|
|||
|
// clut, there will never have more than one pixel per scanline. Therefore clamping
|
|||
|
// this value will not cause incorrect mapping to be used, but will keep inaccuracies
|
|||
|
// from causing the primitive to fail.
|
|||
|
//
|
|||
|
Clamp(fDeltaXIntensity, 16.0f);
|
|||
|
|
|||
|
// Convert to fixed point representation.
|
|||
|
fxDeltaXIntensity.fxFromFloat(fDeltaXIntensity);
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializeAsBase
|
|||
|
(
|
|||
|
const SRenderVertex* prv_from,
|
|||
|
const SRenderVertex* prv_to,
|
|||
|
float f_inverse_dy,
|
|||
|
float f_start_y,
|
|||
|
float f_x_difference,
|
|||
|
CGouraudOn* pgour_increment,
|
|||
|
float f_xdiff_increment
|
|||
|
)
|
|||
|
//
|
|||
|
// Initializes the intensity components of a base edge, including starting position and
|
|||
|
// edge walking increment.
|
|||
|
//
|
|||
|
// Notes:
|
|||
|
// The subpixel 'y' calculation made in CEdge is applied here.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
Assert(prv_from);
|
|||
|
Assert(prv_to);
|
|||
|
Assert(pgour_increment);
|
|||
|
|
|||
|
//
|
|||
|
// Find the i increment value across x. The value is calculated from:
|
|||
|
//
|
|||
|
// di (i1 - i0)
|
|||
|
// i increment = ---- = ---------
|
|||
|
// dy (y1 - y0)
|
|||
|
//
|
|||
|
// Note that f_increment_i may be positive or negative, therefore no fast float to
|
|||
|
// int conversion can be used.
|
|||
|
//
|
|||
|
float f_increment_i = f_inverse_dy * (prv_to->cvIntensity - prv_from->cvIntensity);
|
|||
|
|
|||
|
//
|
|||
|
// The modulus subtraction value might be a different sign than fxDeltaXIntensity,
|
|||
|
// therefore it has to be stored separately.
|
|||
|
//
|
|||
|
fxIModDiv = fxDeltaXIntensity;
|
|||
|
|
|||
|
//
|
|||
|
// Set up the increments for edge walking. Note that the increment of the x difference
|
|||
|
// must be incorporated into this value.
|
|||
|
//
|
|||
|
pgour_increment->fxIntensity.fxFromFloat(f_increment_i + f_xdiff_increment * fDeltaXIntensity);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust intensity to the value it would be when the edge first intersects the first
|
|||
|
// horizontal line, and add the starting adjust value with respect to x.
|
|||
|
//
|
|||
|
fxIntensity.fxFromFloat(prv_from->cvIntensity + f_increment_i * f_start_y +
|
|||
|
f_x_difference * fDeltaXIntensity);
|
|||
|
AssertRange();
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
class CGouraudFog : public CGouraudOn
|
|||
|
//
|
|||
|
// Uses the Gouraud shading algorithm to supply values for fogging.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
public:
|
|||
|
|
|||
|
float fFog;
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudFog
|
|||
|
(
|
|||
|
)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
forceinline CGouraudFog
|
|||
|
(
|
|||
|
const CGouraudFog& gour
|
|||
|
)
|
|||
|
: CGouraudOn(gour)
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
static forceinline bool bGouraudFog()
|
|||
|
//
|
|||
|
// Returns 'true' if this class is used for fogging.
|
|||
|
//
|
|||
|
//**********************************
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
//*********************************************************************************************
|
|||
|
//
|
|||
|
forceinline void InitializePolygonData
|
|||
|
(
|
|||
|
ptr_const<CTexture> ptex, // Texture for polygon.
|
|||
|
TClutVal cv_face // Face-wide lighting.
|
|||
|
)
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
#if VER_DEBUG
|
|||
|
iNumIntensities = iNUM_TERRAIN_FOG_BANDS;
|
|||
|
#endif
|
|||
|
// Get the base color value, the fog is applied via a seperate table.
|
|||
|
iBaseIntensity = iPosFloatCast(cv_face);
|
|||
|
}
|
|||
|
|
|||
|
//*****************************************************************************************
|
|||
|
//
|
|||
|
void AssertXRange
|
|||
|
(
|
|||
|
int i_xrange
|
|||
|
)
|
|||
|
//
|
|||
|
// Uses asserts to check if the range of intensities for this scanline is valid.
|
|||
|
//
|
|||
|
//**************************************
|
|||
|
{
|
|||
|
#if VER_DEBUG
|
|||
|
/*
|
|||
|
// Check starting value.
|
|||
|
AssertRange();
|
|||
|
|
|||
|
// Check ending value.
|
|||
|
fixed fx_end = fxIntensity + fxDeltaXIntensity * fixed(i_xrange);
|
|||
|
Assert(fx_end >= fixed(0));
|
|||
|
Assert(fx_end < fixed(iNumIntensities));
|
|||
|
*/
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
#endif
|