|
|
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) Microsoft Corporation, 1998.
//
// AttrFunc.cpp
//
// Direct3D Reference Rasterizer - Attribute Function Processing
//
///////////////////////////////////////////////////////////////////////////////
#include "pch.cpp"
#pragma hdrstop
//-----------------------------------------------------------------------------
//
// WrapDiff - returns the difference (B-A) as defined under the D3D WRAPU/V
// rules which is the shortest path between the two assuming a coincident
// position at 1. and 0. The fA and fB input range is 0. to 1.
//
//-----------------------------------------------------------------------------
static FLOAT WrapDiff( FLOAT fB, FLOAT fA ) { // compute straight distance
FLOAT fDist1 = fB - fA; // compute distance 'warping' between 0. and 1.
FLOAT fDist2 = ( fDist1 < 0 ) ? ( fDist1+1 ) : ( fDist1-1 );
// return minimum of these
return ( fabs( fDist1) < fabs( fDist2) ) ? ( fDist1) : ( fDist2 ); }
///////////////////////////////////////////////////////////////////////////////
//
// RRAttribFuncStatic - Attribute function data which is shared by all
// attributes and contains per-primitive and per-pixel data. Cannot use static
// data members in RRAttribFunc class because there can be multiple instances
// of rasterizer object.
//
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// SetPerTriangleData - Called once per triangle during setup to set per-triangle
// data used to compute attribute functions.
//
//-----------------------------------------------------------------------------
void RRAttribFuncStatic::SetPerTriangleData( FLOAT fX0, FLOAT fY0, FLOAT fRHW0, FLOAT fX1, FLOAT fY1, FLOAT fRHW1, FLOAT fX2, FLOAT fY2, FLOAT fRHW2, INT32 cTextureStages, FLOAT* pfRHQW, FLOAT fDet ) { m_PrimType = RR_TRIANGLE;
// compute fixed point x,y coords snapped to n.4 with nearest-even round
INT32 iX0 = AS_INT32( (DOUBLE)fX0 + DOUBLE_4_SNAP ); INT32 iY0 = AS_INT32( (DOUBLE)fY0 + DOUBLE_4_SNAP ); INT32 iX1 = AS_INT32( (DOUBLE)fX1 + DOUBLE_4_SNAP ); INT32 iY1 = AS_INT32( (DOUBLE)fY1 + DOUBLE_4_SNAP ); INT32 iX2 = AS_INT32( (DOUBLE)fX2 + DOUBLE_4_SNAP ); INT32 iY2 = AS_INT32( (DOUBLE)fY2 + DOUBLE_4_SNAP ); fX0 = (FLOAT)iX0 * 1.0F/16.0F; fY0 = (FLOAT)iY0 * 1.0F/16.0F; fX1 = (FLOAT)iX1 * 1.0F/16.0F; fY1 = (FLOAT)iY1 * 1.0F/16.0F; fX2 = (FLOAT)iX2 * 1.0F/16.0F; fY2 = (FLOAT)iY2 * 1.0F/16.0F;
m_fX0 = fX0; m_fY0 = fY0; m_cTextureStages = cTextureStages;
m_fRHW0 = fRHW0; m_fRHW1 = fRHW1; m_fRHW2 = fRHW2;
m_fDelX10 = fX1 - fX0; m_fDelX02 = fX0 - fX2; m_fDelY01 = fY0 - fY1; m_fDelY20 = fY2 - fY0;
// compute inverse determinant
m_fTriOODet = 1.f/fDet;
// compute linear function for 1/W (for perspective correction)
// compute linear deltas along two edges
FLOAT fDelAttrib10 = m_fRHW1 - m_fRHW0; FLOAT fDelAttrib20 = m_fRHW2 - m_fRHW0;
// compute A & B terms (dVdX and dVdY)
m_fRHWA = m_fTriOODet * ( fDelAttrib10 * m_fDelY20 + fDelAttrib20 * m_fDelY01 ); m_fRHWB = m_fTriOODet * ( fDelAttrib20 * m_fDelX10 + fDelAttrib10 * m_fDelX02 );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fRHWC = m_fRHW0 - ( m_fRHWA * m_fX0 ) - ( m_fRHWB * m_fY0 );
for(INT32 i = 0; i < m_cTextureStages; i++) { m_fRHQW0[i] = pfRHQW[0]; m_fRHQW1[i] = pfRHQW[1]; m_fRHQW2[i] = pfRHQW[2]; pfRHQW += 3;
// compute linear function for Q/W (for transformed, projected, perspective corrected texture)
fDelAttrib10 = m_fRHQW1[i] - m_fRHQW0[i]; fDelAttrib20 = m_fRHQW2[i] - m_fRHQW0[i];
// compute A & B terms (dVdX and dVdY)
m_fRHQWA[i] = m_fTriOODet * ( fDelAttrib10 * m_fDelY20 + fDelAttrib20 * m_fDelY01 ); m_fRHQWB[i] = m_fTriOODet * ( fDelAttrib20 * m_fDelX10 + fDelAttrib10 * m_fDelX02 );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fRHQWC[i] = m_fRHQW0[i] - ( m_fRHQWA[i] * m_fX0 ) - ( m_fRHQWB[i] * m_fY0 ); } }
//-----------------------------------------------------------------------------
//
// SetPerLineData - Called once per line during setup to set per-line
// data used to compute attribute functions.
//
//-----------------------------------------------------------------------------
void RRAttribFuncStatic::SetPerLineData( FLOAT fX0, FLOAT fY0, FLOAT fRHW0, FLOAT fX1, FLOAT fY1, FLOAT fRHW1, INT32 cTextureStages, FLOAT* pfRHQW, FLOAT fMajorExtent, BOOL bXMajor ) { m_PrimType = RR_LINE;
m_fLineMajorLength = fMajorExtent; m_bLineXMajor = bXMajor;
m_fX0 = fX0; m_fY0 = fY0; m_cTextureStages = cTextureStages;
m_fRHW0 = fRHW0; m_fRHW1 = fRHW1;
// compute linear function for 1/W (for perspective correction)
FLOAT fDelta = ( m_fRHW1 - m_fRHW0 ) / m_fLineMajorLength; m_fRHWA = ( m_bLineXMajor ) ? ( fDelta ) : ( 0. ); m_fRHWB = ( m_bLineXMajor ) ? ( 0. ) : ( fDelta ); m_fRHWC = fRHW0 - ( m_fRHWA * m_fX0 ) - ( m_fRHWB * m_fY0 ); for(INT32 i = 0; i < m_cTextureStages; i++) { m_fRHQW0[i] = pfRHQW[0]; m_fRHQW1[i] = pfRHQW[1]; pfRHQW += 3;
// compute linear function for Q/W (for transformed, projected, perspective corrected texture)
FLOAT fDelta = ( m_fRHQW1[i] - m_fRHQW0[i] ) / m_fLineMajorLength; m_fRHQWA[i] = ( m_bLineXMajor ) ? ( fDelta ) : ( 0. ); m_fRHQWB[i] = ( m_bLineXMajor ) ? ( 0. ) : ( fDelta ); m_fRHQWC[i] = m_fRHQW0[i] - ( m_fRHQWA[i] * m_fX0 ) - ( m_fRHQWB[i] * m_fY0 ); } }
//-----------------------------------------------------------------------------
//
// SetPixel - Called once per pixel to do preparation for per-pixel attribute
// evaluations.
//
//-----------------------------------------------------------------------------
void RRAttribFuncStatic::SetPerPixelData( INT16 iX, INT16 iY ) { m_iX = iX; m_iY = iY;
// evalute 1/W function
FLOAT fPixelRHW = ( m_fRHWA * (FLOAT)m_iX ) + ( m_fRHWB * (FLOAT)m_iY ) + m_fRHWC; m_fPixelW = ( 0. != fPixelRHW ) ? ( 1./fPixelRHW ) : ( 0. ); for(INT32 i = 0; i < m_cTextureStages; i++) { FLOAT fPixelRHQW = ( m_fRHQWA[i] * (FLOAT)m_iX ) + ( m_fRHQWB[i] * (FLOAT)m_iY ) + m_fRHQWC[i]; m_fPixelQW[i] = ( 0. != fPixelRHQW ) ? ( 1./fPixelRHQW ) : ( 0. ); } }
//-----------------------------------------------------------------------------
//
// GetPixelW,GetPixelQW,GetRhwXGradient,GetRhwYGradient,
// GetRhqwXGradient,GetRhqwYGradient - Functions to get static
// data members.
//
//-----------------------------------------------------------------------------
FLOAT RRAttribFuncStatic::GetPixelW( void ) { return m_fPixelW; } FLOAT RRAttribFuncStatic::GetPixelQW( INT32 iStage ) { return m_fPixelQW[iStage]; } FLOAT RRAttribFuncStatic::GetRhqwXGradient( INT32 iStage ) { return m_fRHQWA[iStage]; } FLOAT RRAttribFuncStatic::GetRhqwYGradient( INT32 iStage ) { return m_fRHQWB[iStage]; }
///////////////////////////////////////////////////////////////////////////////
//
// RRAttribFunc - methods
//
///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// SetConstant - Sets function to evaluate to constant value.
//
//-----------------------------------------------------------------------------
void RRAttribFunc::SetConstant( FLOAT fC ) { m_bIsPerspective = FALSE; m_fA = 0.; m_fB = 0.; m_fC = fC; }
//-----------------------------------------------------------------------------
//
// SetLinearFunc - Computes linear function for scalar attribute specified at
// triangle vertices.
//
//-----------------------------------------------------------------------------
void RRAttribFunc::SetLinearFunc( FLOAT fVal0, FLOAT fVal1, FLOAT fVal2 ) { m_bIsPerspective = FALSE;
switch ( m_pSD->m_PrimType ) { case RR_TRIANGLE: { // compute A,B,C for triangle function
// compute linear deltas along two edges
FLOAT fDelAttrib10 = fVal1 - fVal0; FLOAT fDelAttrib20 = fVal2 - fVal0;
// compute A & B terms (dVdX and dVdY)
m_fA = m_pSD->m_fTriOODet * ( fDelAttrib10 * m_pSD->m_fDelY20 + fDelAttrib20 * m_pSD->m_fDelY01 ); m_fB = m_pSD->m_fTriOODet * ( fDelAttrib20 * m_pSD->m_fDelX10 + fDelAttrib10 * m_pSD->m_fDelX02 );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = fVal0 - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 ); } break;
case RR_LINE: { // compute A,B,C for line function - delta is normalized difference
// in major direction; C is computed from knowing the function value
// at the vertices (vertex 0 is always used here)
FLOAT fDelta = ( fVal1 - fVal0 ) / m_pSD->m_fLineMajorLength; m_fA = ( m_pSD->m_bLineXMajor ) ? ( fDelta ) : ( 0. ); m_fB = ( m_pSD->m_bLineXMajor ) ? ( 0. ) : ( fDelta );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = fVal0 - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 ); } break;
case RR_POINT:
// use constant function for point
m_fA = 0.; m_fB = 0.; m_fC = fVal0;
break; }
}
//-----------------------------------------------------------------------------
//
// SetPerspFunc - Computes perspective corrected function for scalar attribute
// specified at triangle vertices.
//
//-----------------------------------------------------------------------------
void RRAttribFunc::SetPerspFunc( FLOAT fVal0, FLOAT fVal1, FLOAT fVal2 ) { switch ( m_pSD->m_PrimType ) { case RR_TRIANGLE: { // triangle function
// compute adjusted values for vertices 1,2 based on wrap flag
FLOAT fVal1P = (fVal1); FLOAT fVal2P = (fVal2);
// compute perspective corrected linear deltas along two edges
FLOAT fDelAttrib10 = ( fVal1P * m_pSD->m_fRHW1 ) - ( fVal0 * m_pSD->m_fRHW0 ); FLOAT fDelAttrib20 = ( fVal2P * m_pSD->m_fRHW2 ) - ( fVal0 * m_pSD->m_fRHW0 );
// compute A & B terms (dVdX and dVdY)
m_fA = m_pSD->m_fTriOODet * ( fDelAttrib10 * m_pSD->m_fDelY20 + fDelAttrib20 * m_pSD->m_fDelY01 ); m_fB = m_pSD->m_fTriOODet * ( fDelAttrib20 * m_pSD->m_fDelX10 + fDelAttrib10 * m_pSD->m_fDelX02 );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = ( fVal0* m_pSD->m_fRHW0) - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 );
m_bIsPerspective = TRUE; } break;
case RR_LINE: { // line function
FLOAT fVal1P = (fVal1); FLOAT fDelta = ( fVal1P*m_pSD->m_fRHW1 - fVal0*m_pSD->m_fRHW0) / m_pSD->m_fLineMajorLength; m_fA = ( m_pSD->m_bLineXMajor ) ? ( fDelta ) : ( 0. ); m_fB = ( m_pSD->m_bLineXMajor ) ? ( 0. ) : ( fDelta ); // compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = ( fVal0* m_pSD->m_fRHW0) - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 );
m_bIsPerspective = TRUE; } break;
case RR_POINT:
// use constant function for point
m_fA = 0.; m_fB = 0.; m_fC = fVal0;
// don't correct constant functions
m_bIsPerspective = FALSE;
break; } }
//-----------------------------------------------------------------------------
//
// Eval - Evaluates function at pixel position set in RRAttribFunc::SetPerPixelData.
// Functions know if they are perspective corrected or not, and if so then do
// the multiply through by the 1/(1/w) term to normalize.
//
//-----------------------------------------------------------------------------
FLOAT RRAttribFunc::Eval( void ) { FLOAT fRet = ( m_fA * (FLOAT)m_pSD->m_iX ) + ( m_fB * (FLOAT)m_pSD->m_iY ) + m_fC; if ( m_bIsPerspective ) { fRet *= m_pSD->m_fPixelW; } return fRet; }
//-----------------------------------------------------------------------------
//
// SetPerspFunc - Computes perspective corrected function for scalar attribute
// specified at triangle vertices.
//
//-----------------------------------------------------------------------------
void RRAttribFunc::SetPerspFunc( FLOAT fVal0, FLOAT fVal1, FLOAT fVal2, BOOL bWrap, BOOL bIsShadowMap ) { switch ( m_pSD->m_PrimType ) { case RR_TRIANGLE: { // triangle function
FLOAT fRHW0 = m_pSD->m_fRHW0; FLOAT fRHW1 = m_pSD->m_fRHW1; FLOAT fRHW2 = m_pSD->m_fRHW2; if (bIsShadowMap) { fRHW0 = 1.0f; fRHW1 = 1.0f; fRHW2 = 1.0f; }
// compute adjusted values for vertices 1,2 based on wrap flag
FLOAT fVal1P = bWrap ? ( fVal0 + WrapDiff(fVal1,fVal0) ) : (fVal1); FLOAT fVal2P = bWrap ? ( fVal0 + WrapDiff(fVal2,fVal0) ) : (fVal2);
// compute perspective corrected linear deltas along two edges
FLOAT fDelAttrib10 = ( fVal1P * fRHW1 ) - ( fVal0 * fRHW0 ); FLOAT fDelAttrib20 = ( fVal2P * fRHW2 ) - ( fVal0 * fRHW0 );
// compute A & B terms (dVdX and dVdY)
m_fA = m_pSD->m_fTriOODet * ( fDelAttrib10 * m_pSD->m_fDelY20 + fDelAttrib20 * m_pSD->m_fDelY01 ); m_fB = m_pSD->m_fTriOODet * ( fDelAttrib20 * m_pSD->m_fDelX10 + fDelAttrib10 * m_pSD->m_fDelX02 );
// compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = ( fVal0 * fRHW0 ) - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 );
m_bIsPerspective = TRUE; } break;
case RR_LINE: { // line function
FLOAT fRHW0 = m_pSD->m_fRHW0; FLOAT fRHW1 = m_pSD->m_fRHW1; if (bIsShadowMap) { fRHW0 = 1.0f; fRHW1 = 1.0f; }
FLOAT fVal1P = bWrap ? ( fVal0 + WrapDiff(fVal1,fVal0) ) : (fVal1); FLOAT fDelta = ( fVal1P*fRHW1 - fVal0*fRHW0) / m_pSD->m_fLineMajorLength; m_fA = ( m_pSD->m_bLineXMajor ) ? ( fDelta ) : ( 0. ); m_fB = ( m_pSD->m_bLineXMajor ) ? ( 0. ) : ( fDelta ); // compute C term (Fv = A*Xv + B*Yv + C => C = Fv - A*Xv - B*Yv)
m_fC = ( fVal0* fRHW0) - ( m_fA * m_pSD->m_fX0 ) - ( m_fB * m_pSD->m_fY0 );
m_bIsPerspective = TRUE; } break;
case RR_POINT:
// use constant function for point
m_fA = 0.; m_fB = 0.; m_fC = fVal0;
// don't correct constant functions
m_bIsPerspective = FALSE;
break; } }
//-----------------------------------------------------------------------------
//
// Eval - Evaluates function at pixel position set in RRAttribFunc::SetPerPixelData.
// Functions know if they are perspective corrected or not, and if so then do
// the multiply through by the 1/(q/w) term to normalize.
//
//-----------------------------------------------------------------------------
FLOAT RRAttribFunc::Eval( INT32 iStage ) { FLOAT fRet = ( m_fA * (FLOAT)m_pSD->m_iX ) + ( m_fB * (FLOAT)m_pSD->m_iY ) + m_fC; // m_bIsPerspective will always be set since persp function is always
// used for texture coords
if ( m_bIsPerspective ) { fRet *= m_pSD->m_fPixelQW[iStage]; } return fRet; }
///////////////////////////////////////////////////////////////////////////////
// end
|