mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-26 22:38:34 +00:00
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:
parent
5beb6dfd47
commit
cc7c6cd35f
16 changed files with 704 additions and 323 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue