Support separate U and V texture wrap modes.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2872 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2009-11-16 15:58:54 +00:00
parent 53b01b72b0
commit e5488e1777
15 changed files with 300 additions and 229 deletions

View File

@ -1,5 +1,7 @@
Changes in 1.7
- Separate TextureWrap mode into U and V fields
- Add mirror texture wrap modes
- windows show now active/inactive state

View File

@ -185,7 +185,10 @@ namespace video
case EMF_BILINEAR_FILTER: material.TextureLayer[0].BilinearFilter = Material.TextureLayer[0].BilinearFilter; break;
case EMF_TRILINEAR_FILTER: material.TextureLayer[0].TrilinearFilter = Material.TextureLayer[0].TrilinearFilter; break;
case EMF_ANISOTROPIC_FILTER: material.TextureLayer[0].AnisotropicFilter = Material.TextureLayer[0].AnisotropicFilter; break;
case EMF_TEXTURE_WRAP: material.TextureLayer[0].TextureWrap = Material.TextureLayer[0].TextureWrap; break;
case EMF_TEXTURE_WRAP:
material.TextureLayer[0].TextureWrapU = Material.TextureLayer[0].TextureWrapU;
material.TextureLayer[0].TextureWrapV = Material.TextureLayer[0].TextureWrapV;
break;
}
}
}

View File

@ -477,7 +477,10 @@ namespace video
case EMF_TEXTURE_WRAP:
{
for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
TextureLayer[i].TextureWrap = (E_TEXTURE_CLAMP)value;
{
TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)value;
TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)value;
}
}
break;
case EMF_ANTI_ALIASING:
@ -528,10 +531,14 @@ namespace video
case EMF_NORMALIZE_NORMALS:
return NormalizeNormals;
case EMF_TEXTURE_WRAP:
return !(TextureLayer[0].TextureWrap ||
TextureLayer[1].TextureWrap ||
TextureLayer[2].TextureWrap ||
TextureLayer[3].TextureWrap);
return !(TextureLayer[0].TextureWrapU ||
TextureLayer[0].TextureWrapV ||
TextureLayer[1].TextureWrapU ||
TextureLayer[1].TextureWrapV ||
TextureLayer[2].TextureWrapU ||
TextureLayer[2].TextureWrapV ||
TextureLayer[3].TextureWrapU ||
TextureLayer[3].TextureWrapV);
case EMF_ANTI_ALIASING:
return (AntiAliasing==1);
case EMF_COLOR_MASK:

View File

@ -51,7 +51,8 @@ namespace video
//! Default constructor
SMaterialLayer()
: Texture(0),
TextureWrap(ETC_REPEAT),
TextureWrapU(ETC_REPEAT),
TextureWrapV(ETC_REPEAT),
BilinearFilter(true),
TrilinearFilter(false),
AnisotropicFilter(0),
@ -106,7 +107,8 @@ namespace video
else
TextureMatrix = 0;
}
TextureWrap = other.TextureWrap;
TextureWrapU = other.TextureWrapU;
TextureWrapV = other.TextureWrapV;
BilinearFilter = other.BilinearFilter;
TrilinearFilter = other.TrilinearFilter;
AnisotropicFilter = other.AnisotropicFilter;
@ -115,36 +117,6 @@ namespace video
return *this;
}
//! Texture
ITexture* Texture;
//! Texture Clamp Mode
u8 TextureWrap;
//! Is bilinear filtering enabled? Default: true
bool BilinearFilter:1;
//! Is trilinear filtering enabled? Default: false
/** If the trilinear filter flag is enabled,
the bilinear filtering flag is ignored. */
bool TrilinearFilter:1;
//! Is anisotropic filtering enabled? Default: 0, disabled
/** In Irrlicht you can use anisotropic texture filtering
in conjunction with bilinear or trilinear texture
filtering to improve rendering results. Primitives
will look less blurry with this flag switched on. The number gives
the maximal anisotropy degree, and is often in the range 2-16.
Value 1 is equivalent to 0, but should be avoided. */
u8 AnisotropicFilter;
//! Bias for the mipmap choosing decision.
/** This value can make the textures more or less blurry than with the
default value of 0. The value (divided by 8.f) is added to the mipmap level
chosen initially, and thus takes a smaller mipmap for a region
if the value is positive. */
s8 LODBias;
//! Gets the texture transformation matrix
/** \return Texture matrix of this layer. */
core::matrix4& getTextureMatrix()
@ -187,7 +159,8 @@ namespace video
{
bool different =
Texture != b.Texture ||
TextureWrap != b.TextureWrap ||
TextureWrapU != b.TextureWrapU ||
TextureWrapV != b.TextureWrapV ||
BilinearFilter != b.BilinearFilter ||
TrilinearFilter != b.TrilinearFilter ||
AnisotropicFilter != b.AnisotropicFilter ||
@ -207,6 +180,38 @@ namespace video
inline bool operator==(const SMaterialLayer& b) const
{ return !(b!=*this); }
//! Texture
ITexture* Texture;
//! Texture Clamp Mode
/** Values are tkane from E_TEXTURE_CLAMP. */
u8 TextureWrapU:4;
u8 TextureWrapV:4;
//! Is bilinear filtering enabled? Default: true
bool BilinearFilter:1;
//! Is trilinear filtering enabled? Default: false
/** If the trilinear filter flag is enabled,
the bilinear filtering flag is ignored. */
bool TrilinearFilter:1;
//! Is anisotropic filtering enabled? Default: 0, disabled
/** In Irrlicht you can use anisotropic texture filtering
in conjunction with bilinear or trilinear texture
filtering to improve rendering results. Primitives
will look less blurry with this flag switched on. The number gives
the maximal anisotropy degree, and is often in the range 2-16.
Value 1 is equivalent to 0, but should be avoided. */
u8 AnisotropicFilter;
//! Bias for the mipmap choosing decision.
/** This value can make the textures more or less blurry than with the
default value of 0. The value (divided by 8.f) is added to the mipmap level
chosen initially, and thus takes a smaller mipmap for a region
if the value is positive. */
s8 LODBias;
private:
friend class SMaterial;
irr::core::irrAllocator<irr::core::matrix4> MatrixAllocator;

View File

@ -922,9 +922,9 @@ void CB3DMeshFileLoader::loadTextures(SB3dMaterial& material) const
material.Material.setTexture(i, tex);
}
if (material.Textures[i]->Flags & 0x10) // Clamp U
material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP;
material.Material.TextureLayer[i].TextureWrapU=video::ETC_CLAMP;
if (material.Textures[i]->Flags & 0x20) // Clamp V
material.Material.TextureLayer[i].TextureWrap=video::ETC_CLAMP;
material.Material.TextureLayer[i].TextureWrapV=video::ETC_CLAMP;
}
}

View File

@ -1354,6 +1354,39 @@ bool CD3D8Driver::setRenderStates3DMode()
}
//! Map Irrlicht texture wrap mode to native values
D3DTEXTUREADDRESS CD3D8Driver::getTextureWrapMode(const E_TEXTURE_CLAMP clamp)
{
switch (clamp)
{
case ETC_REPEAT:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
return D3DTADDRESS_WRAP;
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
return D3DTADDRESS_CLAMP;
case ETC_MIRROR:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
return D3DTADDRESS_MIRROR;
case ETC_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
return D3DTADDRESS_BORDER;
else
return D3DTADDRESS_CLAMP;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
case ETC_MIRROR_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
return D3DTADDRESS_MIRRORONCE;
else
return D3DTADDRESS_CLAMP;
default:
return D3DTADDRESS_WRAP;
}
}
//! Can be called by an IMaterialRenderer to make its work easier.
void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates)
@ -1530,43 +1563,13 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria
pID3DDevice->SetTextureStageState(st, D3DTSS_MIPMAPLODBIAS, *(DWORD*)(&tmp));
}
if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrap != material.TextureLayer[st].TextureWrap)
{
u32 mode = D3DTADDRESS_WRAP;
switch (material.TextureLayer[st].TextureWrap)
{
case ETC_REPEAT:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
mode=D3DTADDRESS_WRAP;
break;
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
mode=D3DTADDRESS_CLAMP;
break;
case ETC_MIRROR:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
mode=D3DTADDRESS_MIRROR;
break;
case ETC_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
mode=D3DTADDRESS_BORDER;
else
mode=D3DTADDRESS_CLAMP;
break;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
case ETC_MIRROR_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
mode=D3DTADDRESS_MIRRORONCE;
else
mode=D3DTADDRESS_CLAMP;
break;
}
pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSU, mode );
pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, mode );
}
if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU)
pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
// If separate UV not supported reuse U for V
if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV))
pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV)
pID3DDevice->SetTextureStageState(st, D3DTSS_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV));
// Bilinear and/or trilinear
if (resetAllRenderstates ||

View File

@ -275,6 +275,8 @@ namespace video
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
E_INDEX_TYPE iType, bool is3D);
D3DTEXTUREADDRESS getTextureWrapMode(const E_TEXTURE_CLAMP clamp);
inline D3DCOLORVALUE colorToD3D(const SColor& col)
{
const f32 f = 1.0f / 255.0f;

View File

@ -1919,6 +1919,39 @@ bool CD3D9Driver::setRenderStates3DMode()
}
//! Map Irrlicht texture wrap mode to native values
D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const E_TEXTURE_CLAMP clamp)
{
switch (clamp)
{
case ETC_REPEAT:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
return D3DTADDRESS_WRAP;
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
return D3DTADDRESS_CLAMP;
case ETC_MIRROR:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
return D3DTADDRESS_MIRROR;
case ETC_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
return D3DTADDRESS_BORDER;
else
return D3DTADDRESS_CLAMP;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
case ETC_MIRROR_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
return D3DTADDRESS_MIRRORONCE;
else
return D3DTADDRESS_CLAMP;
default:
return D3DTADDRESS_WRAP;
}
}
//! Can be called by an IMaterialRenderer to make its work easier.
void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates)
@ -2131,43 +2164,13 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria
pID3DDevice->SetSamplerState(st, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)(&tmp));
}
if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrap != material.TextureLayer[st].TextureWrap)
{
u32 mode = D3DTADDRESS_WRAP;
switch (material.TextureLayer[st].TextureWrap)
{
case ETC_REPEAT:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
mode=D3DTADDRESS_WRAP;
break;
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
mode=D3DTADDRESS_CLAMP;
break;
case ETC_MIRROR:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
mode=D3DTADDRESS_MIRROR;
break;
case ETC_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
mode=D3DTADDRESS_BORDER;
else
mode=D3DTADDRESS_CLAMP;
break;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
case ETC_MIRROR_CLAMP_TO_BORDER:
if (Caps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
mode=D3DTADDRESS_MIRRORONCE;
else
mode=D3DTADDRESS_CLAMP;
break;
}
pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, mode );
pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, mode );
}
if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapU != material.TextureLayer[st].TextureWrapU)
pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSU, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
// If separate UV not supported reuse U for V
if (!(Caps.TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV))
pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapU));
else if (resetAllRenderstates || lastmaterial.TextureLayer[st].TextureWrapV != material.TextureLayer[st].TextureWrapV)
pID3DDevice->SetSamplerState(st, D3DSAMP_ADDRESSV, getTextureWrapMode(material.TextureLayer[st].TextureWrapV));
// Bilinear, trilinear, and anisotropic filter
if (resetAllRenderstates ||

View File

@ -360,6 +360,8 @@ namespace video
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
E_INDEX_TYPE iType, bool is3D);
D3DTEXTUREADDRESS getTextureWrapMode(const E_TEXTURE_CLAMP clamp);
inline D3DCOLORVALUE colorToD3D(const SColor& col)
{
const f32 f = 1.0f / 255.0f;

View File

@ -1617,9 +1617,12 @@ io::IAttributes* CNullDriver::createAttributesFromMaterial(const video::SMateria
prefix = "AnisotropicFilter";
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].AnisotropicFilter);
prefix="TextureWrap";
prefix="TextureWrapU";
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrap, aTextureClampNames);
attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapU, aTextureClampNames);
prefix="TextureWrapV";
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
attr->addEnum((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].TextureWrapV, aTextureClampNames);
prefix="LODBias";
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
attr->addInt((prefix+core::stringc(i+1)).c_str(), material.TextureLayer[i].LODBias);
@ -1692,8 +1695,22 @@ void CNullDriver::fillMaterialStructureFromAttributes(video::SMaterial& outMater
outMaterial.TextureLayer[i].AnisotropicFilter = attr->getAttributeAsInt((prefix+core::stringc(i+1)).c_str());
prefix = "TextureWrap";
if (attr->existsAttribute(prefix.c_str())) // legacy
{
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
outMaterial.TextureLayer[i].TextureWrap = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames);
{
outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+core::stringc(i+1)).c_str(), aTextureClampNames);
outMaterial.TextureLayer[i].TextureWrapV = outMaterial.TextureLayer[i].TextureWrapU;
}
}
else
{
for (i=0; i<MATERIAL_MAX_TEXTURES; ++i)
{
outMaterial.TextureLayer[i].TextureWrapU = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"U"+core::stringc(i+1)).c_str(), aTextureClampNames);
outMaterial.TextureLayer[i].TextureWrapV = (E_TEXTURE_CLAMP)attr->getAttributeAsEnumeration((prefix+"V"+core::stringc(i+1)).c_str(), aTextureClampNames);
}
}
// default 0 is ok
prefix="LODBias";

View File

@ -2094,19 +2094,11 @@ void COpenGLDriver::setRenderStates3DMode()
}
void COpenGLDriver::setWrapMode(const SMaterial& material)
//! Get native wrap mode value
GLint COpenGLDriver::getTextureWrapMode(const u8 clamp)
{
// texture address mode
// Has to be checked always because it depends on the textures
for (u32 u=0; u<MaxTextureUnits; ++u)
{
if (MultiTextureExtension)
extGlActiveTexture(GL_TEXTURE0_ARB + u);
else if (u>0)
break; // stop loop
GLint mode=GL_REPEAT;
switch (material.TextureLayer[u].TextureWrap)
switch (clamp)
{
case ETC_REPEAT:
mode=GL_REPEAT;
@ -2200,9 +2192,23 @@ void COpenGLDriver::setWrapMode(const SMaterial& material)
mode=GL_CLAMP;
break;
}
return mode;
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
void COpenGLDriver::setWrapMode(const SMaterial& material)
{
// texture address mode
// Has to be checked always because it depends on the textures
for (u32 u=0; u<MaxTextureUnits; ++u)
{
if (MultiTextureExtension)
extGlActiveTexture(GL_TEXTURE0_ARB + u);
else if (u>0)
break; // stop loop
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[u].TextureWrapU));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[u].TextureWrapV));
}
}

View File

@ -347,6 +347,9 @@ namespace video
//! Set GL pipeline to desired texture wrap modes of the material
void setWrapMode(const SMaterial& material);
//! get native wrap mode value
GLint getTextureWrapMode(const u8 clamp);
//! sets the needed renderstates
void setRenderStates3DMode();

View File

@ -378,7 +378,8 @@ void CQuake3ShaderSceneNode::render()
material.MaterialType = blendfunc.type;
material.MaterialTypeParam = blendfunc.param0;
material.TextureLayer[0].TextureWrap = q.TextureAddressMode;
material.TextureLayer[0].TextureWrapU = q.TextureAddressMode;
material.TextureLayer[0].TextureWrapV = q.TextureAddressMode;
//material.TextureLayer[0].TrilinearFilter = 1;
//material.TextureLayer[0].AnisotropicFilter = 0xFF;
material.setTextureMatrix( 0, textureMatrix );

View File

@ -41,7 +41,8 @@ CSkyBoxSceneNode::CSkyBoxSceneNode(video::ITexture* top, video::ITexture* bottom
mat.ZBuffer = video::ECFN_NEVER;
mat.ZWriteEnable = false;
mat.AntiAliasing=0;
mat.TextureLayer[0].TextureWrap = video::ETC_CLAMP;
mat.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
mat.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
/* Hey, I am no artist, but look at that
cool ASCII art I made! ;)

View File

@ -956,26 +956,17 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex,
sizeof ( f32 ) * 2 );
}
switch ( Material.org.TextureLayer[t].TextureWrap )
switch ( Material.org.TextureLayer[t].TextureWrapU )
{
case ETC_REPEAT:
default:
dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8];
dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
break;
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
case ETC_CLAMP_TO_BORDER:
dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f );
dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f );
break;
case ETC_MIRROR:
dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8];
if (core::fract(dest->Tex[t].x)>0.5f)
dest->Tex[t].x=1.f-dest->Tex[t].x;
dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
if (core::fract(dest->Tex[t].y)>0.5f)
dest->Tex[t].y=1.f-dest->Tex[t].y;
break;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
@ -983,10 +974,35 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex,
dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f );
if (core::fract(dest->Tex[t].x)>0.5f)
dest->Tex[t].x=1.f-dest->Tex[t].x;
break;
case ETC_REPEAT:
default:
dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8];
break;
}
switch ( Material.org.TextureLayer[t].TextureWrapV )
{
case ETC_CLAMP:
case ETC_CLAMP_TO_EDGE:
case ETC_CLAMP_TO_BORDER:
dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f );
break;
case ETC_MIRROR:
dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
if (core::fract(dest->Tex[t].y)>0.5f)
dest->Tex[t].y=1.f-dest->Tex[t].y;
break;
case ETC_MIRROR_CLAMP:
case ETC_MIRROR_CLAMP_TO_EDGE:
case ETC_MIRROR_CLAMP_TO_BORDER:
dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f );
if (core::fract(dest->Tex[t].y)>0.5f)
dest->Tex[t].y=1.f-dest->Tex[t].y;
break;
case ETC_REPEAT:
default:
dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
break;
}
}
}