mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
softgpu: Implement triangle texture projection.
This commit is contained in:
parent
6282f8b05f
commit
faa6c2d461
@ -129,6 +129,7 @@ void ComputeRasterizerState(RasterizerState *state) {
|
||||
state->mipFilt = gstate.isMipmapFilteringEnabled();
|
||||
state->minFilt = gstate.isMinifyFilteringEnabled();
|
||||
state->magFilt = gstate.isMagnifyFilteringEnabled();
|
||||
state->textureProj = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
}
|
||||
|
||||
state->shadeGouraud = gstate.getShadeMode() == GE_SHADE_GOURAUD;
|
||||
@ -224,8 +225,6 @@ static inline u8 ClampFogDepth(float fogdepth) {
|
||||
}
|
||||
|
||||
static inline void GetTextureCoordinates(const VertexData& v0, const VertexData& v1, const float p, float &s, float &t) {
|
||||
// All UV gen modes, by the time they get here, behave the same.
|
||||
|
||||
// Note that for environment mapping, texture coordinates have been calculated during lighting
|
||||
float q0 = 1.f / v0.clipw;
|
||||
float q1 = 1.f / v1.clipw;
|
||||
@ -233,14 +232,26 @@ static inline void GetTextureCoordinates(const VertexData& v0, const VertexData&
|
||||
float wq1 = (1.0f - p) * q1;
|
||||
|
||||
float q_recip = 1.0f / (wq0 + wq1);
|
||||
// TODO: Handle projection.
|
||||
s = (v0.texturecoords.s() * wq0 + v1.texturecoords.s() * wq1) * q_recip;
|
||||
t = (v0.texturecoords.t() * wq0 + v1.texturecoords.t() * wq1) * q_recip;
|
||||
}
|
||||
|
||||
static inline void GetTextureCoordinatesProj(const VertexData& v0, const VertexData& v1, const float p, float &s, float &t) {
|
||||
// This is for texture matrix projection.
|
||||
float q0 = 1.f / v0.clipw;
|
||||
float q1 = 1.f / v1.clipw;
|
||||
float wq0 = p * q0;
|
||||
float wq1 = (1.0f - p) * q1;
|
||||
|
||||
float q_recip = 1.0f / (wq0 + wq1);
|
||||
float q = (v0.texturecoords.q() * wq0 + v1.texturecoords.q() * wq1) * q_recip;
|
||||
q_recip *= 1.0f / q;
|
||||
|
||||
s = (v0.texturecoords.s() * wq0 + v1.texturecoords.s() * wq1) * q_recip;
|
||||
t = (v0.texturecoords.t() * wq0 + v1.texturecoords.t() * wq1) * q_recip;
|
||||
}
|
||||
|
||||
static inline void GetTextureCoordinates(const VertexData &v0, const VertexData &v1, const VertexData &v2, const Vec4<int> &w0, const Vec4<int> &w1, const Vec4<int> &w2, const Vec4<float> &wsum_recip, Vec4<float> &s, Vec4<float> &t) {
|
||||
// All UV gen modes, by the time they get here, behave the same.
|
||||
|
||||
// Note that for environment mapping, texture coordinates have been calculated during lighting.
|
||||
float q0 = 1.f / v0.clipw;
|
||||
float q1 = 1.f / v1.clipw;
|
||||
@ -250,7 +261,23 @@ static inline void GetTextureCoordinates(const VertexData &v0, const VertexData
|
||||
Vec4<float> wq2 = w2.Cast<float>() * q2;
|
||||
|
||||
Vec4<float> q_recip = (wq0 + wq1 + wq2).Reciprocal();
|
||||
// TODO: Handle projection.
|
||||
s = Interpolate(v0.texturecoords.s(), v1.texturecoords.s(), v2.texturecoords.s(), wq0, wq1, wq2, q_recip);
|
||||
t = Interpolate(v0.texturecoords.t(), v1.texturecoords.t(), v2.texturecoords.t(), wq0, wq1, wq2, q_recip);
|
||||
}
|
||||
|
||||
static inline void GetTextureCoordinatesProj(const VertexData &v0, const VertexData &v1, const VertexData &v2, const Vec4<int> &w0, const Vec4<int> &w1, const Vec4<int> &w2, const Vec4<float> &wsum_recip, Vec4<float> &s, Vec4<float> &t) {
|
||||
// This is for texture matrix projection.
|
||||
float q0 = 1.f / v0.clipw;
|
||||
float q1 = 1.f / v1.clipw;
|
||||
float q2 = 1.f / v2.clipw;
|
||||
Vec4<float> wq0 = w0.Cast<float>() * q0;
|
||||
Vec4<float> wq1 = w1.Cast<float>() * q1;
|
||||
Vec4<float> wq2 = w2.Cast<float>() * q2;
|
||||
|
||||
Vec4<float> q_recip = (wq0 + wq1 + wq2).Reciprocal();
|
||||
Vec4<float> q = Interpolate(v0.texturecoords.q(), v1.texturecoords.q(), v2.texturecoords.q(), wq0, wq1, wq2, q_recip);
|
||||
q_recip = q_recip * q.Reciprocal();
|
||||
|
||||
s = Interpolate(v0.texturecoords.s(), v1.texturecoords.s(), v2.texturecoords.s(), wq0, wq1, wq2, q_recip);
|
||||
t = Interpolate(v0.texturecoords.t(), v1.texturecoords.t(), v2.texturecoords.t(), wq0, wq1, wq2, q_recip);
|
||||
}
|
||||
@ -676,6 +703,9 @@ void DrawTriangleSlice(
|
||||
// For levels > 0, mipmapping is always based on level 0. Simpler to scale first.
|
||||
s *= 1.0f / (float)(1 << state.samplerID.width0Shift);
|
||||
t *= 1.0f / (float)(1 << state.samplerID.height0Shift);
|
||||
} else if (state.textureProj) {
|
||||
// Texture coordinate interpolation must definitely be perspective-correct.
|
||||
GetTextureCoordinatesProj(v0, v1, v2, w0, w1, w2, wsum_recip, s, t);
|
||||
} else {
|
||||
// Texture coordinate interpolation must definitely be perspective-correct.
|
||||
GetTextureCoordinates(v0, v1, v2, w0, w1, w2, wsum_recip, s, t);
|
||||
@ -961,6 +991,8 @@ void DrawPoint(const VertexData &v0, const BinCoords &range, const RasterizerSta
|
||||
if (state.throughMode) {
|
||||
s *= 1.0f / (float)(1 << state.samplerID.width0Shift);
|
||||
t *= 1.0f / (float)(1 << state.samplerID.height0Shift);
|
||||
} else if (state.textureProj) {
|
||||
GetTextureCoordinatesProj(v0, v0, 0.0f, s, t);
|
||||
} else {
|
||||
// Texture coordinate interpolation must definitely be perspective-correct.
|
||||
GetTextureCoordinates(v0, v0, 0.0f, s, t);
|
||||
@ -1278,6 +1310,9 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const BinCoords &range
|
||||
s1 = tc1.s() * (1.0f / (float)(1 << state.samplerID.width0Shift));
|
||||
t = tc.t() * (1.0f / (float)(1 << state.samplerID.height0Shift));
|
||||
t1 = tc1.t() * (1.0f / (float)(1 << state.samplerID.height0Shift));
|
||||
} else if (state.textureProj) {
|
||||
GetTextureCoordinatesProj(v0, v1, (float)(steps - i) / steps1, s, t);
|
||||
GetTextureCoordinatesProj(v0, v1, (float)(steps - i - 1) / steps1, s1, t1);
|
||||
} else {
|
||||
// Texture coordinate interpolation must definitely be perspective-correct.
|
||||
GetTextureCoordinates(v0, v1, (float)(steps - i) / steps1, s, t);
|
||||
|
@ -54,6 +54,7 @@ struct RasterizerState {
|
||||
bool minFilt : 1;
|
||||
bool magFilt : 1;
|
||||
bool antialiasLines : 1;
|
||||
bool textureProj : 1;
|
||||
};
|
||||
|
||||
#if defined(SOFTGPU_MEMORY_TAGGING_DETAILED) || defined(SOFTGPU_MEMORY_TAGGING_BASIC)
|
||||
|
@ -160,7 +160,7 @@ const SoftwareCommandTableEntry softgpuCommandTable[] = {
|
||||
{ GE_CMD_LOGICOP, 0, SoftDirty::PIXEL_BASIC | SoftDirty::PIXEL_CACHED },
|
||||
{ GE_CMD_LOGICOPENABLE, 0, SoftDirty::PIXEL_BASIC | SoftDirty::PIXEL_CACHED },
|
||||
|
||||
{ GE_CMD_TEXMAPMODE, 0, SoftDirty::TRANSFORM_BASIC },
|
||||
{ GE_CMD_TEXMAPMODE, 0, SoftDirty::TRANSFORM_BASIC | SoftDirty::RAST_TEX },
|
||||
|
||||
// These are read on every SubmitPrim, no need for dirtying or flushing.
|
||||
{ GE_CMD_TEXSCALEU },
|
||||
|
@ -261,6 +261,8 @@ void ComputeTransformState(TransformState *state, const VertexReader &vreader) {
|
||||
state->negateNormals = gstate.areNormalsReversed();
|
||||
|
||||
state->uvGenMode = gstate.getUVGenMode();
|
||||
if (state->uvGenMode == GE_TEXMAP_UNKNOWN)
|
||||
state->uvGenMode = GE_TEXMAP_TEXTURE_COORDS;
|
||||
|
||||
if (state->enableTransform) {
|
||||
bool canSkipWorldPos = true;
|
||||
@ -441,17 +443,11 @@ ClipVertexData TransformUnit::ReadVertex(VertexReader &vreader, const TransformS
|
||||
case GE_PROJMAP_NORMAL:
|
||||
source = normal;
|
||||
break;
|
||||
|
||||
default:
|
||||
source = Vec3f::AssignToAll(0.0f);
|
||||
ERROR_LOG_REPORT(G3D, "Software: Unsupported UV projection mode %x", gstate.getUVProjMode());
|
||||
break;
|
||||
}
|
||||
|
||||
// Note that UV scale/offset are not used in this mode.
|
||||
Vec3<float> stq = Vec3ByMatrix43(source, gstate.tgenMatrix);
|
||||
float z_recip = 1.0f / stq.z;
|
||||
vertex.v.texturecoords = Vec3Packedf(stq.x * z_recip, stq.y * z_recip, 1.0f);
|
||||
vertex.v.texturecoords = Vec3Packedf(stq.x, stq.y, stq.z);
|
||||
} else if (state.uvGenMode == GE_TEXMAP_ENVIRONMENT_MAP) {
|
||||
Lighting::GenerateLightST(vertex.v, worldnormal);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user