softgpu: Make perspective correct uv mapping code more readable and implement projection mapping.

This commit is contained in:
Tony Wasserka 2013-07-24 13:55:10 +02:00 committed by neobrain
parent 104feea8eb
commit d2f30961af
5 changed files with 46 additions and 15 deletions

View file

@ -327,8 +327,8 @@ struct GPUgstate
unsigned int getSpecularColorB(int chan) const { return (lcolor[2+chan*3]>>16)&0xFF; }
// UV gen
int getUVGenMode() const { return texmapmode & 3;} // 2 bits
int getUVProjMode() const { return (texmapmode >> 8) & 3;} // 2 bits
GETexMapMode getUVGenMode() const { return static_cast<GETexMapMode>(texmapmode & 3);} // 2 bits
GETexProjMapMode getUVProjMode() const { return static_cast<GETexProjMapMode>((texmapmode >> 8) & 3);} // 2 bits
int getUVLS0() const { return texshade & 0x3; } // 2 bits
int getUVLS1() const { return (texshade >> 8) & 0x3; } // 2 bits

View file

@ -422,12 +422,6 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData&
if (w0 == w1 && w1 == w2 && w2 == 0)
continue;
// TODO: Make sure this is not ridiculously small?
float den = 1.0f/v0.clippos.w * w0 + 1.0f/v1.clippos.w * w1 + 1.0f/v2.clippos.w * w2;
float s = (v0.texturecoords.s() * w0 / v0.clippos.w + v1.texturecoords.s() * w1 / v1.clippos.w + v2.texturecoords.s() * w2 / v2.clippos.w) / den;
float t = (v0.texturecoords.t() * w0 / v0.clippos.w + v1.texturecoords.t() * w1 / v1.clippos.w + v2.texturecoords.t() * w2 / v2.clippos.w) / den;
Vec3<int> prim_color_rgb(0, 0, 0);
int prim_color_a = 0;
Vec3<int> sec_color(0, 0, 0);
@ -453,18 +447,38 @@ void DrawTriangle(const VertexData& v0, const VertexData& v1, const VertexData&
unsigned int u = 0, v = 0;
if (gstate.isModeThrough()) {
// TODO: Is it really this simple?
u = s;
v = t;
u = (v0.texturecoords.s() * w0 + v1.texturecoords.s() * w1 + v2.texturecoords.s() * w2) / (w0+w1+w2);
v = (v0.texturecoords.t() * w0 + v1.texturecoords.t() * w1 + v2.texturecoords.t() * w2) / (w0+w1+w2);
} else {
if (gstate.getUVGenMode() == 0) {
if (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS) {
float q0 = 1.f / v0.clippos.w;
float q1 = 1.f / v1.clippos.w;
float q2 = 1.f / v2.clippos.w;
float q = q0 * w0 + q1 * w1 + q2 * w2;
float s = (v0.texturecoords.s() * q0 * w0 + v1.texturecoords.s() * q1 * w1 + v2.texturecoords.s() * q2 * w2) / q;
float t = (v0.texturecoords.t() * q0 * w0 + v1.texturecoords.t() * q1 * w1 + v2.texturecoords.t() * q2 * w2) / q;
uv_map(0, s, t, u, v);
} else if (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX) {
// projection mapping
Vec3<float> source;
if (gstate.getUVProjMode() == GE_PROJMAP_POSITION) {
source = ((v0.modelpos * w0 + v1.modelpos * w1 + v2.modelpos * w2) / (w0+w1+w2));
} else {
ERROR_LOG(G3D, "Unsupported UV projection mode %x", gstate.getUVProjMode());
}
Mat3x3<float> tgen(gstate.tgenMatrix);
Vec3<float> stq = tgen * source + Vec3<float>(gstate.tgenMatrix[9], gstate.tgenMatrix[10], gstate.tgenMatrix[11]);
uv_map(0, stq.x/stq.z, stq.y/stq.z, u, v);
} else {
ERROR_LOG(G3D, "Unknown texture mapping mode!");
ERROR_LOG(G3D, "Unsupported texture mapping mode %x!", gstate.getUVGenMode());
}
}
Vec4<int> texcolor = Vec4<int>::FromRGBA(SampleNearest(0, u, v));
Vec4<int> out = GetTextureFunctionOutput(prim_color_rgb, prim_color_a, texcolor, s, t);
Vec4<int> out = GetTextureFunctionOutput(prim_color_rgb, prim_color_a, texcolor, u, v);
prim_color_rgb = out.rgb();
prim_color_a = out.a();
}

View file

@ -117,8 +117,8 @@ static VertexData ReadVertex(VertexReader& vreader)
}
if (!gstate.isModeThrough()) {
ModelCoords mcoords(pos[0], pos[1], pos[2]);
vertex.worldpos = WorldCoords(TransformUnit::ModelToWorld(mcoords));
vertex.modelpos = ModelCoords(pos[0], pos[1], pos[2]);
vertex.worldpos = WorldCoords(TransformUnit::ModelToWorld(vertex.modelpos));
vertex.clippos = ClipCoords(TransformUnit::ViewToClip(TransformUnit::WorldToView(vertex.worldpos)));
vertex.drawpos = DrawingCoords(TransformUnit::ScreenToDrawing(ClipToScreenInternal(vertex.clippos)));

View file

@ -76,6 +76,7 @@ struct VertexData
{
// World coords only needed for lighting, so we don't Lerp those
modelpos = ::Lerp(a.modelpos, b.modelpos, t);
clippos = ::Lerp(a.clippos, b.clippos, t);
drawpos = ::Lerp(a.drawpos, b.drawpos, t); // TODO: Should use a LerpInt (?)
texturecoords = ::Lerp(a.texturecoords, b.texturecoords, t);
@ -86,6 +87,7 @@ struct VertexData
color1 = LerpInt<Vec3<int>,256>(a.color1, b.color1, t_int);
}
ModelCoords modelpos;
WorldCoords worldpos; // TODO: Storing this is dumb, should transform the light to clip space instead
ClipCoords clippos;
DrawingCoords drawpos; // TODO: Shouldn't store this ?

View file

@ -457,6 +457,21 @@ enum GEStencilOp
#define GE_TFILT_NEAREST_MIPMAP_LINEAR 6
#define GE_TFILT_LINEAR_MIPMAP_LINEAR 7
enum GETexMapMode
{
GE_TEXMAP_TEXTURE_COORDS=0,
GE_TEXMAP_TEXTURE_MATRIX=1,
GE_TEXMAP_ENVIRONMENT_MAP=2,
};
enum GETexProjMapMode
{
GE_PROJMAP_POSITION=0,
GE_PROJMAP_UV=1,
GE_PROJMAP_NORMALIZED_NORMAL=2,
GE_PROJMAP_NORMAL=3
};
enum GEPrimitiveType
{
GE_PRIM_POINTS=0,