mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
softgpu: Make perspective correct uv mapping code more readable and implement projection mapping.
This commit is contained in:
parent
104feea8eb
commit
d2f30961af
5 changed files with 46 additions and 15 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue