Texture coordinates are stored in fixed point format in TEV which allows overflows to be emulated correctly. Added logic to calculated texture LOD and use the correct mip. Dumping textures will now dump all mip levels. Added line rendering. Changed data stored in vertex from float arrays to vectors for cleaner math.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5178 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
donkopunchstania 2010-03-09 04:38:07 +00:00
parent 5beb6dfd47
commit cc7c6cd35f
16 changed files with 704 additions and 323 deletions

View file

@ -23,29 +23,11 @@
#include <cmath>
#define ALLOW_MIPMAP 1
namespace TextureSampler
{
inline int iround(float x)
{
int t;
#if defined(_WIN32) && !defined(_M_X64)
__asm
{
fld x
fistp t
}
#else
t = (int)x;
if((x - t) >= 0.5)
return t + 1;
#endif
return t;
}
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
{
switch (wrapMode)
@ -85,9 +67,53 @@ inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
outTexel[3] += inTexel[3] * fract;
}
void Sample(float s, float t, float lod, u8 texmap, u8 *sample)
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
{
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
int baseMip = 0;
bool mipLinear = false;
#if (ALLOW_MIPMAP)
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
s32 lodFract = lod & 0xf;
if (lod > 0 && tm0.min_filter & 3)
{
// use mipmap
baseMip = lod >> 4;
mipLinear = (lodFract && tm0.min_filter & 2);
// if using nearest mip filter and lodFract >= 0.5 round up to next mip
baseMip += (lodFract >> 3) & (tm0.min_filter & 1);
}
if (mipLinear)
{
u8 sampledTex[4];
u32 texel[4];
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
SetTexel(sampledTex, texel, (16 - lodFract));
SampleMip(s, t, baseMip + 1, linear, texmap, sampledTex);
AddTexel(sampledTex, texel, lodFract);
sample[0] = (u8)(texel[0] >> 4);
sample[1] = (u8)(texel[1] >> 4);
sample[2] = (u8)(texel[2] >> 4);
sample[3] = (u8)(texel[3] >> 4);
}
else
#endif
{
SampleMip(s, t, baseMip, linear, texmap, sample);
}
}
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
{
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
TexMode0& tm0 = texUnit.texMode0[subTexmap];
@ -97,59 +123,85 @@ void Sample(float s, float t, float lod, u8 texmap, u8 *sample)
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
u8 *imageSrc = g_VideoInitialize.pGetMemoryPointer(imageBase);
bool linear = false;
if ((lod > 0 && tm0.min_filter > 4) || (lod <= 0 && tm0.mag_filter))
linear = true;
int imageWidth = ti0.width;
int imageHeight = ti0.height;
int tlutAddress = texTlut.tmem_offset << 9;
// reduce sample location and texture size to mip level
// move texture pointer to mip location
if (mip)
{
int mipWidth = imageWidth + 1;
int mipHeight = imageHeight + 1;
int fmtWidth = TexDecoder_GetBlockWidthInTexels(ti0.format);
int fmtHeight = TexDecoder_GetBlockHeightInTexels(ti0.format);
int fmtDepth = TexDecoder_GetTexelSizeInNibbles(ti0.format);
imageWidth >>= mip;
imageHeight >>= mip;
s >>= mip;
t >>= mip;
while (mip)
{
mipWidth = max(mipWidth, fmtWidth);
mipHeight = max(mipHeight, fmtHeight);
u32 size = (mipWidth * mipHeight * fmtDepth) >> 1;
imageSrc += size;
mipWidth >>= 1;
mipHeight >>= 1;
mip--;
}
}
// integer part of sample location
int imageS = s >> 7;
int imageT = t >> 7;
if (linear)
{
s32 s256 = s32((s - 0.5f) * 256);
s32 t256 = s32((t- 0.5f) * 256);
int imageS = s256 >> 8;
int imageSPlus1 = imageS + 1;
u32 fractS = s256 & 0xff;
fractS += fractS >> 7;
int imageT = t256 >> 8;
// linear sampling
int imageSPlus1 = imageS + 1;
int fractS = s & 0x7f;
int imageTPlus1 = imageT + 1;
u32 fractT = t256 & 0xff;
fractT += fractT >> 7;
int fractT = t & 0x7f;
u8 sampledTex[4];
u32 texel[4];
WrapCoord(imageS, tm0.wrap_s, ti0.width);
WrapCoord(imageT, tm0.wrap_t, ti0.height);
WrapCoord(imageSPlus1, tm0.wrap_s, ti0.width);
WrapCoord(imageTPlus1, tm0.wrap_t, ti0.height);
WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
SetTexel(sampledTex, texel, (256 - fractS) * (256 - fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
SetTexel(sampledTex, texel, (128 - fractS) * (128 - fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
AddTexel(sampledTex, texel, (fractS) * (256 - fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
AddTexel(sampledTex, texel, (fractS) * (128 - fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
AddTexel(sampledTex, texel, (256 - fractS) * (fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageS, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
AddTexel(sampledTex, texel, (128 - fractS) * (fractT));
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
TexDecoder_DecodeTexel(sampledTex, imageSrc, imageSPlus1, imageTPlus1, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
AddTexel(sampledTex, texel, (fractS) * (fractT));
sample[0] = (u8)(texel[0] >> 16);
sample[1] = (u8)(texel[1] >> 16);
sample[2] = (u8)(texel[2] >> 16);
sample[3] = (u8)(texel[3] >> 16);
sample[0] = (u8)(texel[0] >> 14);
sample[1] = (u8)(texel[1] >> 14);
sample[2] = (u8)(texel[2] >> 14);
sample[3] = (u8)(texel[3] >> 14);
}
else
{
int imageS = int(s);
int imageT = int(t);
// nearest neighbor sampling
WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageS, tm0.wrap_s, ti0.width);
WrapCoord(imageT, tm0.wrap_t, ti0.height);
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, ti0.width, ti0.format, texTlut.tmem_offset << 9, texTlut.tlut_format);
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
}
}