rasterize: perspective correct textures and backface culling

This commit is contained in:
zeromus 2009-02-03 07:49:28 +00:00
parent 517a27294a
commit 5e90f6ae10
3 changed files with 101 additions and 38 deletions

View File

@ -231,6 +231,14 @@ float Vector3Dot(const float *a, const float *b)
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
} }
void Vector3Cross(float* dst, const float *a, const float *b)
{
dst[0] = a[1]*b[2] - a[2]*b[1];
dst[1] = a[2]*b[0] - a[0]*b[2];
dst[2] = a[0]*b[1] - a[1]*b[0];
}
float Vector3Length(const float *a) float Vector3Length(const float *a)
{ {
float lengthSquared = Vector3Dot(a,a); float lengthSquared = Vector3Dot(a,a);
@ -245,6 +253,13 @@ void Vector3Add(float *dst, const float *src)
dst[2] += src[2]; dst[2] += src[2];
} }
void Vector3Subtract(float *dst, const float *src)
{
dst[0] -= src[0];
dst[1] -= src[1];
dst[2] -= src[2];
}
void Vector3Scale(float *dst, const float scale) void Vector3Scale(float *dst, const float scale)
{ {
dst[0] *= scale; dst[0] *= scale;

View File

@ -63,8 +63,10 @@ float* MatrixStackGet (MatrixStack *stack);
void MatrixStackLoadMatrix (MatrixStack *stack, int pos, const float *ptr); void MatrixStackLoadMatrix (MatrixStack *stack, int pos, const float *ptr);
float Vector3Dot(const float *a, const float *b); float Vector3Dot(const float *a, const float *b);
void Vector3Cross(float* dst, const float *a, const float *b);
float Vector3Length(const float *a); float Vector3Length(const float *a);
void Vector3Add(float *dst, const float *src); void Vector3Add(float *dst, const float *src);
void Vector3Subtract(float *dst, const float *src);
void Vector3Scale(float *dst, const float scale); void Vector3Scale(float *dst, const float scale);
void Vector3Copy(float *dst, const float *src); void Vector3Copy(float *dst, const float *src);
void Vector3Normalize(float *dst); void Vector3Normalize(float *dst);

View File

@ -32,6 +32,7 @@
#include "bits.h" #include "bits.h"
#include "common.h" #include "common.h"
#include "matrix.h"
#include "render3D.h" #include "render3D.h"
#include "gfx3d.h" #include "gfx3d.h"
#include "texcache.h" #include "texcache.h"
@ -180,18 +181,19 @@ struct Shader
mode = (polyattr>>4)&0x3; mode = (polyattr>>4)&0x3;
} }
float u, v; float invu, invv, invw;
Fragment::Color materialColor; Fragment::Color materialColor;
void shade(Fragment& dst) void shade(Fragment& dst)
{ {
Fragment::Color texColor; Fragment::Color texColor;
//if(mode==0||mode==1) float u,v;
// texColor = sampler.sample(i_tex_u.Z,i_tex_v.Z);
switch(mode) switch(mode)
{ {
case 0: //modulate case 0: //modulate
u = invu/invw;
v = invv/invw;
texColor = sampler.sample(u,v); texColor = sampler.sample(u,v);
dst.color.components.r = ((texColor.components.r+1) * (materialColor.components.r+1)-1)>>5; dst.color.components.r = ((texColor.components.r+1) * (materialColor.components.r+1)-1)>>5;
dst.color.components.g = ((texColor.components.g+1) * (materialColor.components.g+1)-1)>>5; dst.color.components.g = ((texColor.components.g+1) * (materialColor.components.g+1)-1)>>5;
@ -201,6 +203,8 @@ struct Shader
case 1: //decal case 1: //decal
case 2: case 2:
case 3: //..and everything else, for now case 3: //..and everything else, for now
u = invu/invw;
v = invv/invw;
texColor = sampler.sample(u,v); texColor = sampler.sample(u,v);
dst.color = texColor; dst.color = texColor;
break; break;
@ -212,19 +216,30 @@ struct Shader
struct Interpolator struct Interpolator
{ {
int A,B,C;
float dx, dy; float dx, dy;
float Z, pZ; float Z, pZ;
struct { struct {
int x,y,z; float x,y,z;
} point0; } point0;
Interpolator(int x1, int x2, int x3, int y1, int y2, int y3, float z1, float z2, float z3)
{
float A = (z3 - z1) * (y2 - y1) - (z2 - z1) * (y3 - y1);
float B = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1);
float C = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
dx = -(float)A / C;
dy = -(float)B / C;
point0.x = x1;
point0.y = y1;
point0.z = z1;
}
Interpolator(int x1, int x2, int x3, int y1, int y2, int y3, int z1, int z2, int z3) Interpolator(int x1, int x2, int x3, int y1, int y2, int y3, int z1, int z2, int z3)
{ {
A = (z3 - z1) * (y2 - y1) - (z2 - z1) * (y3 - y1); int A = (z3 - z1) * (y2 - y1) - (z2 - z1) * (y3 - y1);
B = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1); int B = (x3 - x1) * (z2 - z1) - (x2 - x1) * (z3 - z1);
C = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); int C = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
dx = -(float)A / C; dx = -(float)A / C;
dy = -(float)B / C; dy = -(float)B / C;
point0.x = x1; point0.x = x1;
@ -314,18 +329,20 @@ void triangle_from_devmaster()
Interpolator i_color_g(fx1,fx2,fx3,fy1,fy2,fy3,g1,g2,g3); Interpolator i_color_g(fx1,fx2,fx3,fy1,fy2,fy3,g1,g2,g3);
Interpolator i_color_b(fx1,fx2,fx3,fy1,fy2,fy3,b1,b2,b3); Interpolator i_color_b(fx1,fx2,fx3,fy1,fy2,fy3,b1,b2,b3);
Interpolator i_color_a(fx1,fx2,fx3,fy1,fy2,fy3,a1,a2,a3); Interpolator i_color_a(fx1,fx2,fx3,fy1,fy2,fy3,a1,a2,a3);
Interpolator i_tex_u(fx1,fx2,fx3,fy1,fy2,fy3,u1,u2,u3); Interpolator i_tex_invu(fx1,fx2,fx3,fy1,fy2,fy3,u1*4096.0f/w1,u2*4096.0f/w2,u3*4096.0f/w3);
Interpolator i_tex_v(fx1,fx2,fx3,fy1,fy2,fy3,v1,v2,v3); Interpolator i_tex_invv(fx1,fx2,fx3,fy1,fy2,fy3,v1*4096.0f/w1,v2*4096.0f/w2,v3*4096.0f/w3);
Interpolator i_w(fx1,fx2,fx3,fy1,fy2,fy3,w1,w2,w3); Interpolator i_w(fx1,fx2,fx3,fy1,fy2,fy3,w1,w2,w3);
Interpolator i_invw(fx1,fx2,fx3,fy1,fy2,fy3,4096.0f/w1,4096.0f/w2,4096.0f/w3);
i_color_r.init(minx,miny); i_color_r.init(minx,miny);
i_color_g.init(minx,miny); i_color_g.init(minx,miny);
i_color_b.init(minx,miny); i_color_b.init(minx,miny);
i_color_a.init(minx,miny); i_color_a.init(minx,miny);
i_tex_u.init(minx,miny); i_tex_invu.init(minx,miny);
i_tex_v.init(minx,miny); i_tex_invv.init(minx,miny);
i_w.init(minx,miny); i_w.init(minx,miny);
i_invw.init(minx,miny);
for(int y = miny; y < maxy; y++) for(int y = miny; y < maxy; y++)
{ {
@ -336,9 +353,9 @@ void triangle_from_devmaster()
int CX3 = CY3; int CX3 = CY3;
bool done = false; bool done = false;
i_color_r.push(); i_color_g.push(); i_color_b.push(); ; i_color_a.push(); i_color_r.push(); i_color_g.push(); i_color_b.push(); i_color_a.push();
i_tex_u.push(); i_tex_v.push(); i_tex_invu.push(); i_tex_invv.push();
i_w.push(); i_w.push(); i_invw.push();
if(y>=0 && y<192) if(y>=0 && y<192)
{ {
@ -358,8 +375,8 @@ void triangle_from_devmaster()
//since we dont, we are receiving waaay out of bounds polys and so unless we do this we spend a lot of time calculating //since we dont, we are receiving waaay out of bounds polys and so unless we do this we spend a lot of time calculating
//out of bounds pixels //out of bounds pixels
i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum); i_color_r.incx(xaccum); i_color_g.incx(xaccum); i_color_b.incx(xaccum); i_color_a.incx(xaccum);
i_tex_u.incx(xaccum); i_tex_v.incx(xaccum); i_tex_invu.incx(xaccum); i_tex_invv.incx(xaccum);
i_w.incx(xaccum); i_w.incx(xaccum); i_invw.incx(xaccum);
xaccum = 0; xaccum = 0;
int adr = (y<<8)+x; int adr = (y<<8)+x;
@ -370,11 +387,9 @@ void triangle_from_devmaster()
if(w>destFragment.depth) if(w>destFragment.depth)
goto rejected_fragment; goto rejected_fragment;
//material color shader.invw = i_invw.Z;
//color = R5G5B5TORGB15(i_color_r.cur(),i_color_g.cur(),i_color_b.cur()); shader.invu = i_tex_invu.Z;
shader.invv = i_tex_invv.Z;
shader.u = i_tex_u.Z;
shader.v = i_tex_v.Z;
shader.materialColor.components.a = i_color_a.cur(); shader.materialColor.components.a = i_color_a.cur();
shader.materialColor.components.r = i_color_r.cur(); shader.materialColor.components.r = i_color_r.cur();
shader.materialColor.components.g = i_color_g.cur(); shader.materialColor.components.g = i_color_g.cur();
@ -394,7 +409,7 @@ void triangle_from_devmaster()
destFragment.color.components.r = (alpha*shaderOutput.color.components.r + invAlpha*destFragment.color.components.r)>>5; destFragment.color.components.r = (alpha*shaderOutput.color.components.r + invAlpha*destFragment.color.components.r)>>5;
destFragment.color.components.g = (alpha*shaderOutput.color.components.g + invAlpha*destFragment.color.components.g)>>5; destFragment.color.components.g = (alpha*shaderOutput.color.components.g + invAlpha*destFragment.color.components.g)>>5;
destFragment.color.components.b = (alpha*shaderOutput.color.components.b + invAlpha*destFragment.color.components.b)>>5; destFragment.color.components.b = (alpha*shaderOutput.color.components.b + invAlpha*destFragment.color.components.b)>>5;
destFragment.color.components.a = max(shaderOutput.color.components.b,destFragment.color.components.a); destFragment.color.components.a = max(shaderOutput.color.components.a,destFragment.color.components.a);
} }
destFragment.depth = w; destFragment.depth = w;
@ -412,9 +427,10 @@ void triangle_from_devmaster()
i_color_r.pop(); i_color_r.incy(); i_color_r.pop(); i_color_r.incy();
i_color_g.pop(); i_color_g.incy(); i_color_g.pop(); i_color_g.incy();
i_color_b.pop(); i_color_b.incy(); i_color_b.pop(); i_color_b.incy();
i_tex_u.pop(); i_tex_u.incy(); i_tex_invu.pop(); i_tex_invu.incy();
i_tex_v.pop(); i_tex_v.incy(); i_tex_invv.pop(); i_tex_invv.incy();
i_w.pop(); i_w.incy(); i_w.pop(); i_w.incy();
i_invw.pop(); i_invw.incy();
CY1 += FDX12; CY1 += FDX12;
@ -443,11 +459,13 @@ static void GetLine(int line, u16* dst, u8* dstAlpha)
Fragment* src = screen+((191-line)<<8); Fragment* src = screen+((191-line)<<8);
for(int i=0;i<256;i++) for(int i=0;i<256;i++)
{ {
u8 r = src->color.components.r; u8 r = src->color.components.r;
u8 g = src->color.components.g; u8 g = src->color.components.g;
u8 b = src->color.components.b; u8 b = src->color.components.b;
*dst = R5G5B5TORGB15(r,g,b); *dst = R5G5B5TORGB15(r,g,b);
if(src->color.components.a > 0) *dst |= 0x8000; if(src->color.components.a > 0)
*dst |= 0x8000;
*dstAlpha = alpha_5bit_to_4bit[src->color.components.a]; *dstAlpha = alpha_5bit_to_4bit[src->color.components.a];
src++; src++;
dst++; dst++;
@ -479,13 +497,40 @@ static void Render()
vert.coord[1] = (vert.coord[1]+vert.coord[3])*192 / (2*vert.coord[3]) + 0; vert.coord[1] = (vert.coord[1]+vert.coord[3])*192 / (2*vert.coord[3]) + 0;
} }
int culled = 0;
//iterate over gfx3d.polylist and gfx3d.vertlist //iterate over gfx3d.polylist and gfx3d.vertlist
for(int i=0;i<gfx3d.polylist->count;i++) { for(int i=0;i<gfx3d.polylist->count;i++)
{
POLY *poly = &gfx3d.polylist->list[gfx3d.indexlist[i]]; POLY *poly = &gfx3d.polylist->list[gfx3d.indexlist[i]];
int type = poly->type; int type = poly->type;
VERT* verts[4] = {
&gfx3d.vertlist->list[poly->vertIndexes[0]],
&gfx3d.vertlist->list[poly->vertIndexes[1]],
&gfx3d.vertlist->list[poly->vertIndexes[2]],
type==4?&gfx3d.vertlist->list[poly->vertIndexes[3]]:0
};
//HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built
//because it is too convoluted right now.
//(must we throw out verts if a poly gets backface culled? if not, then it might be easier)
//TODO - use some freaking matrix and vector classes
float ab[3], ac[3];
Vector3Copy(ab,verts[0]->coord);
Vector3Copy(ac,verts[0]->coord);
Vector3Subtract(ab,verts[1]->coord);
Vector3Subtract(ac,verts[2]->coord);
float cross[3];
Vector3Cross(cross,ab,ac);
float view[3] = {0,0,1};
float dot = Vector3Dot(view,cross);
if(dot<0) {
culled++;
continue;
}
TexCache_SetTexture(poly->texParam,poly->texPalette); TexCache_SetTexture(poly->texParam,poly->texPalette);
sampler.setup(poly->texParam); sampler.setup(poly->texParam);
@ -494,29 +539,30 @@ static void Render()
//but then again, what does it matter? //but then again, what does it matter?
if(type == 4) { if(type == 4) {
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[2]]); SubmitVertex(verts[2]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[1]]); SubmitVertex(verts[1]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[0]]); SubmitVertex(verts[0]);
triangle_from_devmaster(); triangle_from_devmaster();
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[0]]); SubmitVertex(verts[0]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[3]]); SubmitVertex(verts[3]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[2]]); SubmitVertex(verts[2]);
triangle_from_devmaster(); triangle_from_devmaster();
} }
if(type == 3) { if(type == 3) {
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[2]]); SubmitVertex(verts[2]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[1]]); SubmitVertex(verts[1]);
SubmitVertex(&gfx3d.vertlist->list[poly->vertIndexes[0]]); SubmitVertex(verts[0]);
triangle_from_devmaster(); triangle_from_devmaster();
} }
} }
printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
} }