Skip to content

Commit 6e1ef4f

Browse files
authored
Bilinear luma filtering for SEGA Model 2 textured render path (#14293)
* Bilinear luma filtering for SEGA Model 2 textured render path * Bilinear improvements discussed on pull request thread 1. Code standard 2. Anti Alpha higlighted edges ala Supermodel 3. Cleaner bilinear edge cases ala Supermodel
1 parent ab0a33a commit 6e1ef4f

File tree

1 file changed

+66
-20
lines changed

1 file changed

+66
-20
lines changed

src/mame/sega/model2rd.ipp

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -139,46 +139,92 @@ void MODEL2_FUNC_NAME(int32_t scanline, const extent_t& extent, const m2_poly_ex
139139
float dvoz = extent.param[2].dpdx;
140140
int x;
141141

142-
tex_x_mask = (tex_mirr_x ? (tex_width * 2) : tex_width) - 1;
143-
tex_y_mask = (tex_mirr_y ? (tex_height * 2) : tex_height) - 1;
142+
tex_x_mask = tex_width - 1;
143+
tex_y_mask = tex_height - 1;
144144

145145
colorbase = state->m_palram[(colorbase + 0x1000)] & 0x7fff;
146146

147147
colortable_r += ((colorbase >> 0) & 0x1f) << 8;
148148
colortable_g += ((colorbase >> 5) & 0x1f) << 8;
149149
colortable_b += ((colorbase >> 10) & 0x1f) << 8;
150150

151-
for(x = extent.startx; x < extent.stopx; x++, uoz += duoz, voz += dvoz, ooz += dooz)
151+
for (x = extent.startx; x < extent.stopx; x++, uoz += duoz, voz += dvoz, ooz += dooz)
152152
{
153153
float z = recip_approx(ooz) * 256.0f;
154154
int32_t u = uoz * z;
155155
int32_t v = voz * z;
156156
int tr, tg, tb;
157-
u16 t;
157+
u32 t, tex1, tex2, tex3, tex4, frac1, frac2, frac3, frac4;
158+
#if defined(MODEL2_TRANSLUCENT)
159+
u32 alp, alp1, alp2, alp3, alp4;
160+
#endif
158161
u8 luma;
159-
int u2;
160-
int v2;
162+
int u2, u2n;
163+
int v2, v2n;
161164

162165
#if defined(MODEL2_CHECKER)
163-
if ( ((x^scanline) & 1) == 0 )
166+
if (((x ^ scanline) & 1) == 0)
164167
continue;
165168
#endif
166-
u2 = (u >> 8) & tex_x_mask;
167-
v2 = (v >> 8) & tex_y_mask;
168-
169-
if (tex_mirr_x && u2 >= tex_width)
170-
u2 = (tex_width * 2 - 1) - u2;
171-
172-
if (tex_mirr_y && v2 >= tex_height)
173-
v2 = (tex_height * 2 - 1) - v2;
174-
175-
t = get_texel( tex_x, tex_y, u2, v2, sheet );
176-
169+
u2 = u >> 8;
170+
v2 = v >> 8;
171+
172+
if (tex_mirr_x && ((u2 & tex_width) != 0)) // Only flip if even number of tilings
173+
{
174+
u2 = (u2 ^ tex_x_mask) & tex_x_mask;
175+
u2n = std::max(0, u2 - 1); // Ensure sample is inside texture
176+
}
177+
else
178+
{
179+
u2 &= tex_x_mask;
180+
u2n = std::min(u2 + 1, (int) tex_x_mask); // Ensure sample is inside texture
181+
}
182+
if (tex_mirr_y && ((v2 & tex_height) != 0)) // Only flip if even number of tilings
183+
{
184+
v2 = (v2 ^ tex_y_mask) & tex_y_mask;
185+
v2n = std::max(0, v2 - 1); // Ensure sample is inside texture
186+
}
187+
else
188+
{
189+
v2 &= tex_y_mask;
190+
v2n = std::min(v2 + 1, (int) tex_y_mask); // Ensure sample is inside texture
191+
}
192+
193+
frac1 = u & 0xFF;
194+
frac2 = 0x100 - frac1;
195+
frac3 = v & 0xFF;
196+
frac4 = 0x100 - frac3;
197+
tex1 = get_texel(tex_x, tex_y, u2, v2, sheet);
198+
tex2 = get_texel(tex_x, tex_y, u2n, v2, sheet);
199+
tex3 = get_texel(tex_x, tex_y, u2, v2n, sheet);
200+
tex4 = get_texel(tex_x, tex_y, u2n, v2n, sheet);
177201
#if defined(MODEL2_TRANSLUCENT)
178-
if ( t == 0x0f )
202+
alp1 = (tex1 + 1) >> 4;
203+
alp2 = (tex2 + 1) >> 4;
204+
alp3 = (tex3 + 1) >> 4;
205+
alp4 = (tex4 + 1) >> 4;
206+
alp = alp1 * frac2 * frac4 + alp2 * frac1 * frac4 + alp3 * frac2 * frac3 + alp4 * frac1 * frac3;
207+
if ( alp >= 0x8000 )
179208
continue;
209+
// Anti Alpha Highlighted Edges
210+
tex1 &= alp1 - 1;
211+
tex2 &= alp2 - 1;
212+
tex3 &= alp3 - 1;
213+
tex4 &= alp4 - 1;
214+
u32 maxValidTex = std::max(std::max(std::max(tex1, tex2), tex3), tex4);
215+
if (alp1)
216+
tex1 = maxValidTex;
217+
if (alp2)
218+
tex2 = maxValidTex;
219+
if (alp3)
220+
tex3 = maxValidTex;
221+
if (alp4)
222+
tex4 = maxValidTex;
180223
#endif
181-
luma = (u32)lumaram[lumabase + (t << 3)] * object.luma / 256;
224+
t = tex1 * frac2 * frac4 + tex2 * frac1 * frac4 + tex3 * frac2 * frac3 + tex4 * frac1 * frac3;
225+
226+
// Bilinear combination has 16 bits of precision, and the table needs t to be shifted by 3 on the left
227+
luma = (u32)lumaram[lumabase + (t >> 13)] * object.luma / 256;
182228

183229
// Virtua Striker sets up a luma of 0x40 for national flags on bleachers, fix here.
184230
luma = std::min((int)luma,0x3f);

0 commit comments

Comments
 (0)