diff --git a/source/Irrlicht/CSoftwareDriver2.cpp b/source/Irrlicht/CSoftwareDriver2.cpp index 98460b6f..678070f3 100644 --- a/source/Irrlicht/CSoftwareDriver2.cpp +++ b/source/Irrlicht/CSoftwareDriver2.cpp @@ -2350,13 +2350,14 @@ void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vert // select mipmap for (size_t m = 0; m < VertexCache.vSize[VertexCache.vType].TexSize; ++m) { + video::CSoftwareTexture2* tex = MAT_TEXTURE(m); + //only guessing: take more detail (lower mipmap) in light+bump textures //assume transparent add is ~50% transparent -> more detail f32 lod_bias = Material.org.MaterialType == EMT_TRANSPARENT_ADD_COLOR ? 0.1f : 0.33f; + lod_bias *= tex->get_lod_bias(); s32 lodFactor = lodFactor_inside(face, m, dc_area, lod_bias); - - video::CSoftwareTexture2* tex = MAT_TEXTURE(m); CurrentShader->setTextureParam(m, tex, lodFactor); //currently shader receives texture coordinate as Pixelcoo of 1 Texture select_polygon_mipmap_inside(face, m, tex->getTexBound()); @@ -3713,16 +3714,17 @@ IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video ITexture* CBurningVideoDriver::createDeviceDependentTexture(const io::path& name, IImage* image) { - CSoftwareTexture2* texture = new CSoftwareTexture2(image, name, - (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) | - (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? CSoftwareTexture2::ALLOW_NPOT : 0) + u32 flags = + ((TextureCreationFlags & ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0) + | ((TextureCreationFlags & ETCF_AUTO_GENERATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP_AUTO : 0) + | ((TextureCreationFlags & ETCF_ALLOW_NON_POWER_2) ? CSoftwareTexture2::ALLOW_NPOT : 0) #if defined(IRRLICHT_sRGB) - | (getTextureCreationFlag(ETCF_IMAGE_IS_LINEAR) ? CSoftwareTexture2::IMAGE_IS_LINEAR : 0) - | (getTextureCreationFlag(ETCF_TEXTURE_IS_LINEAR) ? CSoftwareTexture2::TEXTURE_IS_LINEAR : 0) + | ((TextureCreationFlags & ETCF_IMAGE_IS_LINEAR) ? CSoftwareTexture2::IMAGE_IS_LINEAR : 0) + | ((TextureCreationFlags & ETCF_TEXTURE_IS_LINEAR) ? CSoftwareTexture2::TEXTURE_IS_LINEAR : 0) #endif - ,this - ); + ; + CSoftwareTexture2* texture = new CSoftwareTexture2(image, name, flags, this); return texture; } diff --git a/source/Irrlicht/CSoftwareTexture2.cpp b/source/Irrlicht/CSoftwareTexture2.cpp index acb239ec..5b485e66 100644 --- a/source/Irrlicht/CSoftwareTexture2.cpp +++ b/source/Irrlicht/CSoftwareTexture2.cpp @@ -29,15 +29,17 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, u32 fl #endif #ifndef SOFTWARE_DRIVER_2_MIPMAPPING - Flags &= ~GEN_MIPMAP; + Flags &= ~(GEN_MIPMAP| GEN_MIPMAP_AUTO); #endif + //set baseclass properties DriverType = EDT_BURNINGSVIDEO; ColorFormat = BURNINGSHADER_COLOR_FORMAT; IsRenderTarget = (Flags & IS_RENDERTARGET) != 0; HasMipMaps = (Flags & GEN_MIPMAP) != 0; MipMap0_Area[0] = 1; MipMap0_Area[1] = 1; + LodBIAS = 1.f; for ( size_t i = 0; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i ) MipMap[i] = 0; if (!image) return; @@ -135,9 +137,9 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) core::dimension2d newSize; - //deactivated outside mipdata until TA knows how to handle this. - if (HasMipMaps && (0 == data || 1)) + if (HasMipMaps && ( (Flags & GEN_MIPMAP_AUTO) || 0 == data ) ) { + //need memory also if autogen mipmap disabled for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) { const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); @@ -158,9 +160,27 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) } else if (HasMipMaps && data) { - core::dimension2d origSize = Size; + //deactivated outside mipdata until TA knows how to handle this. - for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX; ++i) + //query mipmap dimension + u8* mip_current = (u8*)data; + const u8* mip_end = (u8*)data; + + core::dimension2d origSize = OriginalSize; + i = 1; + do + { + if (origSize.Width > 1) origSize.Width >>= 1; + if (origSize.Height > 1) origSize.Height >>= 1; + mip_end += IImage::getDataSizeFromFormat(OriginalFormat, origSize.Width, origSize.Height); + i += 1; + } while ((origSize.Width != 1 || origSize.Height != 1) && i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX); + + //TODO: this is not true + LodBIAS = i*0.75f; + + origSize = OriginalSize; + for (i = 1; i < SOFTWARE_DRIVER_2_MIPMAPPING_MAX && mip_current < mip_end; ++i) { const core::dimension2du& upperDim = MipMap[i - 1]->getDimension(); //isotropic @@ -169,12 +189,12 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) if (upperDim == newSize) break; - origSize.Width = core::s32_max(1, origSize.Width >> 1); - origSize.Height = core::s32_max(1, origSize.Height >> 1); + if (origSize.Width > 1) origSize.Width >>= 1; + if (origSize.Height > 1) origSize.Height >>= 1; if (OriginalFormat != BURNINGSHADER_COLOR_FORMAT) { - IImage* tmpImage = new CImage(OriginalFormat, origSize, data, true, false); + IImage* tmpImage = new CImage(OriginalFormat, origSize, mip_current, true, false); MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); if (origSize == newSize) tmpImage->copyTo(MipMap[i]); @@ -185,16 +205,16 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) else { if (origSize == newSize) - MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, data, false); + MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize, mip_current, false); else { MipMap[i] = new CImage(BURNINGSHADER_COLOR_FORMAT, newSize); - IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, data, true, false); + IImage* tmpImage = new CImage(BURNINGSHADER_COLOR_FORMAT, origSize, mip_current, true, false); tmpImage->copyToScalingBoxFilter(MipMap[i]); tmpImage->drop(); } } - data = (u8*)data + origSize.getArea()*IImage::getBitsPerPixelFromFormat(OriginalFormat) / 8; + mip_current += IImage::getDataSizeFromFormat(OriginalFormat, origSize.Width, origSize.Height); } } @@ -212,7 +232,7 @@ void CSoftwareTexture2::regenerateMipMapLevels(void* data, u32 layer) */ static u32 color[] = { 0xFFFFFFFF,0xFFFF0000,0xFF00FF00,0xFF0000FF, - 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFF0000FF, + 0xFFFFFF00,0xFF00FFFF,0xFFFF00FF,0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFF0000FF, 0xFF0000FF,0xFF0000FF,0xFF0000FF,0xFFFF00FF }; diff --git a/source/Irrlicht/CSoftwareTexture2.h b/source/Irrlicht/CSoftwareTexture2.h index 06a66cf7..d556af50 100644 --- a/source/Irrlicht/CSoftwareTexture2.h +++ b/source/Irrlicht/CSoftwareTexture2.h @@ -36,11 +36,12 @@ public: //! constructor enum eTex2Flags { - GEN_MIPMAP = 1, - IS_RENDERTARGET = 2, - ALLOW_NPOT = 4, //allow non power of two - IMAGE_IS_LINEAR = 8, - TEXTURE_IS_LINEAR = 16, + GEN_MIPMAP = 1, // has mipmaps + GEN_MIPMAP_AUTO = 2, // automatic mipmap generation + IS_RENDERTARGET = 4, + ALLOW_NPOT = 8, //allow non power of two + IMAGE_IS_LINEAR = 16, + TEXTURE_IS_LINEAR = 32, }; CSoftwareTexture2(IImage* surface, const io::path& name, u32 flags /*eTex2Flags*/, CBurningVideoDriver* driver); @@ -107,6 +108,7 @@ public: virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_; + f32 get_lod_bias() const { return LodBIAS; } private: void calcDerivative(); @@ -119,6 +121,7 @@ private: CImage* MipMap[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; CSoftwareTexture2_Bound TexBound[SOFTWARE_DRIVER_2_MIPMAPPING_MAX]; u32 MipMap0_Area[2]; + f32 LodBIAS; }; /*!