JurassicParkTrespasser/jp2_pc/Source/Lib/Renderer/Primitives/P5/DrawSubTriangleGourEx.inl

406 lines
10 KiB
Plaintext
Raw Permalink Normal View History

2018-01-01 22:07:24 +00:00
/***********************************************************************************************
*
* Copyright <20> DreamWorks Interactive, 1997.
*
* Contents:
* Specialized (non-template) versions of the DrawSubtriangle function.
* Optimized for the Pentium Processor
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/P5/DrawSubTriangleGourEx.cpp $
*
* 9 97.12.22 9:08p Mmouni
* Fixed error with destination of terrain gouraud shading primitive.
*
* 8 97.12.22 6:07p Mmouni
* Changed terrain gouraud shading routines so that they don't always draw to the screen.
*
* 7 97.12.22 2:53p Mmouni
* Added new terrain gouraud shading primitive.
*
* 6 10/10/97 1:47p Mmouni
* All inner loops are now left to right only, and optimized some.
*
* 5 9/15/97 2:10p Mmouni
* Optimized inner loops (not final yet).
*
* 4 9/01/97 8:02p Rwyatt
*
* 3 97/07/18 3:29p Pkeet
* Removed use of the 'b_right' parameter from DrawSubTriangle.
*
* 2 7/14/97 12:36p Rwyatt
* Checkled in so Scott can move them....
*
* 1 7/07/97 11:15p Rwyatt
* Initial Implementation of Pentium Specifics
*
***********************************************************************************************
***********************************************************************************************
*
* 5 97/06/12 5:56p Pkeet
* Added capability to render only every other scanline and to double the number of scanlines.
*
* 4 97/06/11 11:41p Pkeet
* Added more optimal inner loop code.
*
* 3 97/06/11 11:27p Pkeet
* Initial assembly version.
*
* 2 97/06/11 11:20p Pkeet
* Simplified the C++ version.
*
* 1 97/06/11 10:15p Pkeet
* Initial C++ versions of primitives.
*
**********************************************************************************************/
#include "Common.hpp"
#include "Lib/View/Raster.hpp"
#include "Lib/Renderer/Primitives/DrawTriangle.hpp"
//
// Temporary Globals.
//
// Notes:
// These variables should be arraigned along with the external globals for maximum
// cache efficiency.
//
static fixed fx_gour_inc;
static int i_line_pixels;
static uint16* ppix_clut;
//*****************************************************************************************
// Gouraud shaded triangle function.
//
void DrawSubtriangle(TGour* pscan, CDrawPolygon<TGour>* pdtri)
{
static TGour* pscanGlbl;
static CDrawPolygon<TGour>* pdtriGlbl;
fx_inc = pdtri->pedgeBase->lineIncrement.fxX;
fx_diff = pdtri->pedgeBase->lineIncrement.fxXDifference;
fx_gour_inc = pdtri->pedgeBase->lineIncrement.gourIntensity.fxIntensity;
i_line_pixels = pdtri->prasScreen->iLinePixels;
ppix_clut = ((uint16*)pvClutConversion) + u4ConstColour;
pscanGlbl = pscan;
pdtriGlbl = pdtri;
_asm
{
mov edx,[pdtri]
mov ecx,[pscan]
push ebp
mov eax,[edx]CDrawPolygonBase.iY
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
// ecx, edi, eax and edx are also set from the loop end.
//--------------------------------------------------------------------------------------
// scan line start
NEXT_SCAN:
and eax,[bEvenScanlinesOnly]
jnz short SKIP_LOOP
//--------------------------------------------------------------------------------------
// Calculate start, length of edge.
mov esi,[ecx]TGour.fxX.i4Fx
mov eax,[edx]CDrawPolygonBase.fxLineLength.i4Fx
add eax,esi
sar eax,16
mov ebx,gsGlobals.pvScreen
sar esi,16
add edi,eax
sub esi,eax
jge short SKIP_LOOP
// Get the starting gouraud shading value.
mov edx,[ecx]TGour.gourIntensity.fxIntensity.i4Fx
lea edi,[edi*2+ebx]
mov ecx,[ppix_clut]
mov ebx,0xFFFF0000
mov [pvBaseOfLine],edi
mov ebp,[fxDeltaXIntensity]
lea eax,[edi + esi*2]
test eax,3
jz short ALIGNED
// Check for one pixel before starting.
inc esi
jz short FINISH_REMAINDER
//
// Do one pixel for alignment.
//
and ebx,edx // Copy and mask intensity value
add edx,ebp // Step intensity value
shr ebx,8 // Shift masked intensity value
// AGI on ebx
mov bx,[ecx + ebx*2] // Lookup pixel
mov [edi + esi*2 - 2],bx // Store pixel
mov ebx,0xFFFF0000 // Load mask value into ebx
ALIGNED:
// Make sure we have two pixels left.
add esi,2
jg short FINISH_REMAINDER
mov edi,0xFFFF0000 // Load mask value into edi.
//
// Do two pixels at a time.
//
INNER_LOOP_2P:
and ebx,edx // Copy and mask intensity (1).
add edx,ebp // Step intensity.
shr ebx,8 // Shift masked intensity value (1).
and edi,edx // Copy and mask intensity (2).
shr edi,8 // Shift masked intensity value (2).
xor eax,eax // Clear eax
add edx,ebp // Step intensity.
mov al,[ecx + ebx*2] // Lookup low byte of pixel (1)
mov ah,[ecx + ebx*2 + 1] // Lookup high byte of pixel (1)
mov bl,[ecx + edi*2] // Lookup low byte of pixel (2)
mov bh,[ecx + edi*2 + 1] // Lookup high byte of pixel (2)
mov edi,[pvBaseOfLine] // Load pointer to base of scanline.
shl ebx,16 // Shift second pixel up
or eax,ebx // Merge pixels
mov ebx,0xFFFF0000 // Load mask value into ebx.
mov [edi + esi*2 - 4],eax // Store pixel.
mov edi,0xFFFF0000 // Load mask value into edi.
add esi,2
jle short INNER_LOOP_2P
// esi is 1 if there is a pixel left.
cmp esi,1
jne short SKIP_LOOP
//
// Finish left over pixel.
//
FINISH_REMAINDER:
and ebx,edx // Copy and mask intensity value
mov edi,[pvBaseOfLine] // Load pointer to base of scanline.
shr ebx,8 // Shift masked intensity value
// AGI on ebx
mov bx,[ecx + ebx*2] // Lookup pixel
mov [edi - 2],bx // Store pixel
//--------------------------------------------------------------------------------------
// Loop control an sub pixel correction for edges
SKIP_LOOP:
mov edx,[pdtriGlbl]
mov ecx,[pscanGlbl]
mov esi,[ecx]TGour.gourIntensity.fxIntensity.i4Fx
mov ebx,[ecx]TGour.fxXDifference
add esi,[fx_gour_inc]
add ebx,[fx_diff]
mov eax,[fxIModDiv]
jge short NO_UNDERFLOW
// Undeflow of fxXDifference.
add ebx,0x00010000
add esi,eax
jmp short DONE_Y
NO_UNDERFLOW:
cmp ebx,0x00010000
jl short DONE_Y
// Overflow of fxXDifference.
sub ebx,0x00010000
add esi,eax
DONE_Y:
// Store modified variables.
mov [ecx]TGour.gourIntensity.fxIntensity.i4Fx,esi
mov [ecx]TGour.fxXDifference,ebx
// Step length, line starting address.
mov ebx,[edx]CDrawPolygonBase.fxLineLength.i4Fx
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
add ebx,[edx]CDrawPolygonBase.fxDeltaLineLength.i4Fx
add edi,[i_line_pixels]
mov [edx]CDrawPolygonBase.fxLineLength.i4Fx,ebx
mov [edx]CDrawPolygonBase.iLineStartIndex,edi
mov ebx,[ecx]TGour.fxX
mov esi,[fx_inc]
add ebx,esi
mov eax,[edx]CDrawPolygonBase.iY
mov [ecx]TGour.fxX,ebx
inc eax
mov ebx,[edx]CDrawPolygonBase.iYTo
mov [edx]CDrawPolygonBase.iY,eax
// ecx, edi, eax and edx are set for the next interation of the loop.
cmp eax,ebx
jl NEXT_SCAN
pop ebp
}
}
//*****************************************************************************************
// Gouraud shaded triangle function that draws to a composite texture map.
//
void DrawSubtriangle(TShadeTerrain* pscan, CDrawPolygon<TShadeTerrain>* pdtri)
{
typedef CDrawPolygon<TShadeTerrain> TAccess;
static TShadeTerrain* pscanGlbl;
static CDrawPolygon<TShadeTerrain>* pdtriGlbl;
fx_inc = pdtri->pedgeBase->lineIncrement.fxX;
fx_diff = pdtri->pedgeBase->lineIncrement.fxXDifference;
fx_gour_inc = pdtri->pedgeBase->lineIncrement.gourIntensity.fxIntensity;
i_line_pixels = pdtri->prasScreen->iLinePixels;
pscanGlbl = pscan;
pdtriGlbl = pdtri;
_asm
{
mov edx,[pdtri]
mov ecx,[pscan]
mov eax,[edx]CDrawPolygonBase.iY
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
// ecx, edi, eax and edx are also set from the loop end.
//--------------------------------------------------------------------------------------
// scan line start
NEXT_SCAN:
and eax,[bEvenScanlinesOnly]
jnz short SKIP_LOOP
//--------------------------------------------------------------------------------------
// Calculate start, length of edge.
mov esi,[ecx]TGour.fxX.i4Fx
mov eax,[edx]CDrawPolygonBase.fxLineLength.i4Fx
add eax,esi
sar eax,16
mov ebx,[edx]TAccess.prasScreen
sar esi,16
add edi,eax
mov ebx,[ebx]CRasterBase.pSurface
sub esi,eax
jge short SKIP_LOOP
// Get the starting gouraud shading value.
mov edx,[ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx
lea edi,[edi*2+ebx]
mov [pvBaseOfLine],edi
mov eax,[fxDeltaXIntensity]
//
// Write intensity value to every other pixel.
//
INNER_LOOP:
mov ebx,edx // Copy intensity value
add edx,eax // Step intensity value
shr ebx,16 // Shift intensity value
mov [edi + esi*2 + 1],bl // Store integer intensity byte
inc esi // Step count
jnz short INNER_LOOP
//--------------------------------------------------------------------------------------
// Loop control an sub pixel correction for edges
SKIP_LOOP:
mov edx,[pdtriGlbl]
mov ecx,[pscanGlbl]
mov esi,[ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx
mov ebx,[ecx]TShadeTerrain.fxXDifference
add esi,[fx_gour_inc]
add ebx,[fx_diff]
mov eax,[fxIModDiv]
jge short NO_UNDERFLOW
// Undeflow of fxXDifference.
add ebx,0x00010000
add esi,eax
jmp short DONE_Y
NO_UNDERFLOW:
cmp ebx,0x00010000
jl short DONE_Y
// Overflow of fxXDifference.
sub ebx,0x00010000
add esi,eax
DONE_Y:
// Store modified variables.
mov [ecx]TShadeTerrain.gourIntensity.fxIntensity.i4Fx,esi
mov [ecx]TShadeTerrain.fxXDifference,ebx
// Step length, line starting address.
mov ebx,[edx]CDrawPolygonBase.fxLineLength.i4Fx
mov edi,[edx]CDrawPolygonBase.iLineStartIndex
add ebx,[edx]CDrawPolygonBase.fxDeltaLineLength.i4Fx
add edi,[i_line_pixels]
mov [edx]CDrawPolygonBase.fxLineLength.i4Fx,ebx
mov [edx]CDrawPolygonBase.iLineStartIndex,edi
mov ebx,[ecx]TShadeTerrain.fxX
mov esi,[fx_inc]
add ebx,esi
mov eax,[edx]CDrawPolygonBase.iY
mov [ecx]TShadeTerrain.fxX,ebx
inc eax
mov ebx,[edx]CDrawPolygonBase.iYTo
mov [edx]CDrawPolygonBase.iY,eax
// ecx, edi, eax and edx are set for the next interation of the loop.
cmp eax,ebx
jl NEXT_SCAN
}
}