mirror of https://github.com/ClassiCube/ClassiCube
96 lines
2.7 KiB
C#
96 lines
2.7 KiB
C#
using System;
|
|
using OpenTK;
|
|
|
|
namespace SoftwareRasterizer.Engine {
|
|
|
|
public unsafe partial class SoftwareEngine {
|
|
|
|
public void Filled_DrawIndexedTriangles( Vector3[] vertices, ushort[] indices ) {
|
|
for( int i = 0; i < indices.Length; i += 3 ) {
|
|
Vector3 vertex1 = vertices[indices[i + 0]];
|
|
Vector3 vertex2 = vertices[indices[i + 1]];
|
|
Vector3 vertex3 = vertices[indices[i + 2]];
|
|
|
|
Vector3 p1, p2, p3;
|
|
Project( ref vertex1, out p1 );
|
|
Project( ref vertex2, out p2 );
|
|
Project( ref vertex3, out p3 );
|
|
byte col = (byte)( 255 * ( 0.25f + ( ( i / 3 ) % indices.Length ) * 0.75f / indices.Length ) );
|
|
FastColour col2 = new FastColour( col, col, col );
|
|
DrawTriangle( p1, p2, p3, ref col2 );
|
|
}
|
|
}
|
|
|
|
float Clamp( float value ) {
|
|
if( value < 0 ) return 0;
|
|
if( value > 1 ) return 1;
|
|
return value;
|
|
}
|
|
|
|
float lerp( float min, float max, float gradient ) {
|
|
return min + ( max - min ) * Clamp( gradient );
|
|
}
|
|
|
|
void ProcessScanLine( int y, Vector3 pa, Vector3 pb, Vector3 pc, Vector3 pd, ref FastColour col ) {
|
|
float gradient1 = pa.Y != pb.Y ? (y - pa.Y) / (pb.Y - pa.Y) : 1;
|
|
float gradient2 = pc.Y != pd.Y ? (y - pc.Y) / (pd.Y - pc.Y) : 1;
|
|
|
|
int sx = (int)lerp( pa.X, pb.X, gradient1 );
|
|
int ex = (int)lerp( pc.X, pd.X, gradient2 );
|
|
float z1 = lerp( pa.Z, pb.Z, gradient1 );
|
|
float z2 = lerp( pc.Z, pd.Z, gradient2 );
|
|
|
|
for( int x = sx; x < ex; x++ ) {
|
|
float gradient = ( x - sx) / (float)( ex - sx );
|
|
float z = lerp( z1, z2, gradient );
|
|
SetPixelClipped( ref x, ref y, ref z, ref col );
|
|
}
|
|
}
|
|
|
|
void Swap( ref Vector3 a, ref Vector3 b ) {
|
|
Vector3 c = a;
|
|
a = b;
|
|
b = c;
|
|
}
|
|
|
|
void DrawTriangle( Vector3 p1, Vector3 p2, Vector3 p3, ref FastColour col ) {
|
|
if( p1.Y > p2.Y ) Swap( ref p1, ref p2 );
|
|
if( p2.Y > p3.Y ) Swap( ref p2, ref p3 );
|
|
if( p1.Y > p2.Y ) Swap( ref p1, ref p2 );
|
|
|
|
float dP1P2, dP1P3;
|
|
|
|
// http://en.wikipedia.org/wiki/Slope
|
|
// Computing inverse slopes
|
|
if( p2.Y - p1.Y > 0 )
|
|
dP1P2 = ( p2.X - p1.X ) / ( p2.Y - p1.Y );
|
|
else
|
|
dP1P2 = 0;
|
|
|
|
if( p3.Y - p1.Y > 0 )
|
|
dP1P3 = ( p3.X - p1.X ) / ( p3.Y - p1.Y );
|
|
else
|
|
dP1P3 = 0;
|
|
|
|
if( dP1P2 > dP1P3 ) {
|
|
for( int y = (int)p1.Y; y <= (int)p3.Y; y++ ) {
|
|
if( y < p2.Y ) {
|
|
ProcessScanLine( y, p1, p3, p1, p2, ref col );
|
|
} else {
|
|
ProcessScanLine( y, p1, p3, p2, p3, ref col );
|
|
}
|
|
}
|
|
} else {
|
|
for( int y = (int)p1.Y; y <= (int)p3.Y; y++ ) {
|
|
if( y < p2.Y ) {
|
|
ProcessScanLine( y, p1, p2, p1, p3, ref col );
|
|
} else {
|
|
ProcessScanLine( y, p2, p3, p1, p3, ref col );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|