[Aqsis-commits] SF.net SVN: aqsis: [1813] branches/texfiltering/aqsis/texturing/texlib
Brought to you by:
ltatkinson,
pgregory
From: <c4...@us...> - 2007-12-02 02:31:43
|
Revision: 1813 http://aqsis.svn.sourceforge.net/aqsis/?rev=1813&view=rev Author: c42f Date: 2007-12-01 18:31:46 -0800 (Sat, 01 Dec 2007) Log Message: ----------- * Change the way that sampling options are stored and used by making SqTextureSampleOptions into a class, and having CqTextureMap2 hold an instance of this class which can be modified to change the sampling. * Introduce a CqMipmapLevel class which is a cache for the mipmap levels of a given texture. The cache handles proper on-demand initialization of the mipmap level samplers, and also holds default sampling options which were deduced from the texture file. * Make the CqTextureMap2 class a simple container for a pair of CqMipmapLevels and CqTextureSamplingOptions classes, so that any number of instances can be easily created on demand by the shaderVM, and the texture sampling options modified in a thread-safe way. Modified Paths: -------------- branches/texfiltering/aqsis/texturing/texlib/CMakeLists.txt branches/texfiltering/aqsis/texturing/texlib/itexturesampler.h branches/texfiltering/aqsis/texturing/texlib/texturemap2.cpp branches/texfiltering/aqsis/texturing/texlib/texturemap2.h branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.cpp branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.h branches/texfiltering/aqsis/texturing/texlib/texturesampler.h Added Paths: ----------- branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.cpp branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.h Modified: branches/texfiltering/aqsis/texturing/texlib/CMakeLists.txt =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/CMakeLists.txt 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/CMakeLists.txt 2007-12-02 02:31:46 UTC (rev 1813) @@ -20,6 +20,7 @@ itexoutputfile.cpp itexturesampler.cpp magicnumber.cpp + mipmaplevels.cpp texfileheader.cpp tiffdirhandle.cpp tiffinputfile.cpp Modified: branches/texfiltering/aqsis/texturing/texlib/itexturesampler.h =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/itexturesampler.h 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/itexturesampler.h 2007-12-02 02:31:46 UTC (rev 1813) @@ -53,7 +53,7 @@ * \param outSamps - the outSamps samples will be placed here. */ virtual void filter(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const = 0; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const = 0; /** \brief Create and return a IqTextureSampler derived class * Added: branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.cpp =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.cpp (rev 0) +++ branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.cpp 2007-12-02 02:31:46 UTC (rev 1813) @@ -0,0 +1,60 @@ +// Aqsis +// Copyright (C) 1997 - 2007, Paul C. Gregory +// +// Contact: pgr...@aq... +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/** \file + * + * \brief Implementation of a class which holds a collection of mipmap levels. + * + * \author Chris Foster [ chris42f (at) gmail (dot) com ] + */ + +#include "mipmaplevels.h" + +#include "itexturesampler.h" + +namespace Aqsis +{ + +//------------------------------------------------------------------------------ +// Implementation of CqMipmapLevels + +CqMipmapLevels::CqMipmapLevels(const std::string& texName) + : m_texName(texName), + m_defaultSampleOptions(), + m_mipLevels() +{ + // \todo decide how many mipmap levels are needed. + m_mipLevels.resize(1); + // \todo: Init default sampling opts from texture file +} + +const IqTextureSampler& CqMipmapLevels::level(TqInt levelNum) +{ + assert(levelNum >= 0); + IqTextureSampler* sampler = m_mipLevels[levelNum].get(); + if(!sampler) + { + m_mipLevels[levelNum] = IqTextureSampler::create( + boost::shared_ptr<IqTiledTexInputFile>()); + sampler = m_mipLevels[levelNum].get(); + } + return *sampler; +} + +} // namespace Aqsis Added: branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.h =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.h (rev 0) +++ branches/texfiltering/aqsis/texturing/texlib/mipmaplevels.h 2007-12-02 02:31:46 UTC (rev 1813) @@ -0,0 +1,129 @@ +// Aqsis +// Copyright (C) 1997 - 2007, Paul C. Gregory +// +// Contact: pgr...@aq... +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +/** \file + * + * \brief Declare a class for holding a collection of mipmap levels. + * + * \author Chris Foster [ chris42f (at) gmail (dot) com ] + */ + +#ifndef MIPMAPLEVELS_H_INCLUDED +#define MIPMAPLEVELS_H_INCLUDED + +#include "aqsis.h" + +#include <string> +#include <vector> + +#include <boost/shared_ptr.hpp> + +#include "texturesampleoptions.h" + +namespace Aqsis +{ + +class IqTextureSampler; + +//------------------------------------------------------------------------------ +/** \brief A container for a set of texture mipmap levels. + * + * This class holds texture mipmap level data, in a way which is independent of + * the sampling options. This makes sense because our typical usage is for + * sampling options to change very often, while the underlying data is fixed. + * + * CqMipmapLevels is the class which will be held in the texture cache. + * + * In addition to holding mipmap levels, this class also caches the default + * sampling options, as determined from attributes of the underlying texture + * file. When these aren't present, we attempt to choose sensible defaults. + */ +class CqMipmapLevels +{ + public: + /** \brief Construct a set of mipmap levels from a file + * + * If the file named by texName doesn't exist, this class is still + * constructed sucessfully. However, the number of levels is then set + * to one, and that level is a dummy texture consisting of a single + * pixel. This allows us to gracefully recover from a missing file. + * + * \param texName - Name of the texture file to open. + * + * \todo: Consider whether this should really take a pointer to an open + * file inestead of a file name... + */ + CqMipmapLevels(const std::string& texName); + /** \brief Get the texture sampler for a given level. + * + * \param levelNum - mipmap level to grab + */ + const IqTextureSampler& level(TqInt levelNum); + /** \brief Get the number of levels in this mipmap. + * + */ + inline TqInt numLevels() const; + /** \brief Get the default sample options associated with the texture file. + * + * \return The default sample options - these include options which + * were used when the texture was created (things like the texutre wrap + * mode). + */ + inline const CqTextureSampleOptions& defaultSampleOptions(); + /** \brief Get the texture name + * + * This is the name of the associated texture file, (if the file + * doesn't exist, this is still the name which was passed to the + * constructor). + * + * \return The texture name + */ + inline const std::string& name() const; + private: + std::string m_texName; ///< Name of texture + /// Default texture sampling options for the set of mipmap levels. + CqTextureSampleOptions m_defaultSampleOptions; + /** \brief List of samplers for mipmap levels. The pointers to these + * may be NULL since they are created only on demand. + */ + mutable std::vector<boost::shared_ptr<IqTextureSampler> > m_mipLevels; +}; + + +//============================================================================== +// Implementation details +//============================================================================== +inline TqInt CqMipmapLevels::numLevels() const +{ + return m_mipLevels.size(); +} + +inline const CqTextureSampleOptions& CqMipmapLevels::defaultSampleOptions() +{ + return m_defaultSampleOptions; +} + +inline const std::string& CqMipmapLevels::name() const +{ + return m_texName; +} + +} // namespace Aqsis + +#endif // MIPMAPLEVELS_H_INCLUDED Modified: branches/texfiltering/aqsis/texturing/texlib/texturemap2.cpp =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/texturemap2.cpp 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/texturemap2.cpp 2007-12-02 02:31:46 UTC (rev 1813) @@ -29,9 +29,11 @@ #include "vector3d.h" #include "matrix.h" #include "itexturesampler.h" +#include "mipmaplevels.h" #include "ishaderdata.h" /// \todo remove when removing the wrapper. #include "logging.h" +#include "smartptr.h" namespace Aqsis { @@ -39,16 +41,11 @@ //------------------------------------------------------------------------------ // Implementation of CqTextureMap2 -CqTextureMap2::CqTextureMap2(const std::string& fileName) - : m_fileName(fileName), - m_mipLevels(), - m_defaultSampleOptions() +CqTextureMap2::CqTextureMap2(const boost::shared_ptr<CqMipmapLevels>& mipmapLevels) + : m_mipLevels(mipmapLevels), + m_sampleOptions() { - // \todo decide how many mipmap levels are needed. - m_mipLevels.resize(1); - m_mipLevels[0] = IqTextureSampler::create( - boost::shared_ptr<IqTiledTexInputFile>()); - // \todo: Init default sampling opts from texture file + assert(m_mipLevels); } TqInt CqTextureMap2::numSamples() const @@ -59,22 +56,22 @@ const std::string& CqTextureMap2::name() const { - return m_fileName; + return m_mipLevels->name(); } -void CqTextureMap2::sampleMap(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamples) const +void CqTextureMap2::sampleMap(const SqSampleQuad& sampleQuad, TqFloat* outSamples) const { - m_mipLevels[0]->filter(sampleQuad, sampleOpts, outSamples); + m_mipLevels->level(0).filter(sampleQuad, m_sampleOptions, outSamples); } //------------------------------------------------------------------------------ // Implementation of CqTextureMap2Wrapper -CqTextureMap2Wrapper::CqTextureMap2Wrapper(const std::string& fileName) - : m_fileName(), - m_realMap(fileName), +CqTextureMap2Wrapper::CqTextureMap2Wrapper(const std::string& texName) + : m_texName(), + m_levels(texName), + m_realMap(boost::shared_ptr<CqMipmapLevels>(&m_levels, nullDeleter)), m_sampleOptions() { } @@ -90,8 +87,14 @@ void CqTextureMap2Wrapper::PrepareSampleOptions(std::map<std::string, IqShaderData*>& paramMap ) { - m_sampleOptions = SqTextureSampleOptions(0,0, 1,1, TextureFilter_Gaussian, - 0, 0, SamplesPerPixel(), 4, WrapMode_Black, WrapMode_Black); + m_sampleOptions.setBlur(0); + m_sampleOptions.setWidth(1); + m_sampleOptions.setFilterType(TextureFilter_Gaussian); + m_sampleOptions.setFill(0); + m_sampleOptions.setStartChannel(0); + m_sampleOptions.setNumChannels(SamplesPerPixel()); + m_sampleOptions.setNumSamples(4); + m_sampleOptions.setWrapMode(WrapMode_Black); if(paramMap.size() != 0) { std::map<std::string, IqShaderData*>::const_iterator i; @@ -102,17 +105,24 @@ { TqFloat width = 1; i->second->GetFloat(width); - m_sampleOptions.swidth = width; - m_sampleOptions.twidth = width; + m_sampleOptions.setWidth(width); } else { i = paramMap.find("swidth"); if(i != end) - i->second->GetFloat(m_sampleOptions.swidth); + { + TqFloat tmp = 0; + i->second->GetFloat(tmp); + m_sampleOptions.setSWidth(tmp); + } i = paramMap.find("twidth"); if(i != end) - i->second->GetFloat(m_sampleOptions.twidth); + { + TqFloat tmp = 0; + i->second->GetFloat(tmp); + m_sampleOptions.setTWidth(tmp); + } } // Load filter blurs i = paramMap.find("blur"); @@ -120,17 +130,24 @@ { TqFloat blur = 0; i->second->GetFloat(blur); - m_sampleOptions.sblur = blur; - m_sampleOptions.tblur = blur; + m_sampleOptions.setBlur(blur); } else { i = paramMap.find("sblur"); if(i != end) - i->second->GetFloat(m_sampleOptions.sblur); + { + TqFloat tmp = 0; + i->second->GetFloat(tmp); + m_sampleOptions.setSBlur(tmp); + } i = paramMap.find("tblur"); if(i != end) - i->second->GetFloat(m_sampleOptions.tblur); + { + TqFloat tmp = 0; + i->second->GetFloat(tmp); + m_sampleOptions.setTBlur(tmp); + } } // number of samples for stochastic filters i = paramMap.find("samples"); @@ -138,7 +155,7 @@ { TqFloat samples = 0; i->second->GetFloat(samples); - m_sampleOptions.numSamples = lfloor(samples); + m_sampleOptions.setNumSamples(lfloor(samples)); } /// \todo pixelvariance ? // Filter type @@ -155,7 +172,7 @@ << filterName << "\". Using gaussian\n"; filterType = TextureFilter_Gaussian; } - m_sampleOptions.filterType = filterType; + m_sampleOptions.setFilterType(filterType); } } } @@ -177,10 +194,9 @@ TqFloat s3, TqFloat t3, TqFloat s4, TqFloat t4, std::valarray<TqFloat>& val ) { - // \todo implementation val.resize(SamplesPerPixel()); const SqSampleQuad sQuad(s1,t1, s2,t2, s3,t3, s4,t4); - m_realMap.sampleMap(sQuad, m_sampleOptions, &val[0]); + m_realMap.sampleMap(sQuad, &val[0]); } inline CqMatrix& CqTextureMap2Wrapper::GetMatrix(TqInt which, TqInt index) Modified: branches/texfiltering/aqsis/texturing/texlib/texturemap2.h =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/texturemap2.h 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/texturemap2.h 2007-12-02 02:31:46 UTC (rev 1813) @@ -38,35 +38,23 @@ #include "sstring.h" #include "texfileheader.h" +#include "mipmaplevels.h" /// \todo may be removed when removing wrapper class. + namespace Aqsis { class IqTextureSampler; +class CqMipmapLevels; //------------------------------------------------------------------------------ - /* \brief A multi-resolution filtering texture sampler * - * There are two alternatives for specifying options for how the underlying - * image should be sampled: - * * The sample options can be passed into the sampleMap function as a - * SqTextureSampleOptions structure. This is good when the sample options - * change regularly (eg, in the shader VM), and in multithreaded - * environments when more than one set of sample options may being used. - * * For general use in other circumstances when the sample options don't - * change often it makes more sense to set some default sample options once - * with a member function. This is possible with setDefaultSampleOptions. - * - * The initial values for the default sampling options are obtained from any - * stored attributes present in the underlying texture file, otherwise sensible - * defaults are chosen. - * * \todo Rename this to CqTextureMap after the old CqTextureMap is removed. */ class CqTextureMap2 { public: - CqTextureMap2(const std::string& fileName); + CqTextureMap2(const boost::shared_ptr<CqMipmapLevels>& mipmapLevels); /** \brief Get the texture attributes of the underlying file. * * This function allows access to the texture file attributes such as @@ -83,34 +71,22 @@ /** \brief Sample the texture map. * * \param sampleQuad - quadrilateral region to sample over - * \param sampleOpts - options to the sampler, including filter widths etc. * \param outSamples - the output samples will be placed here. */ - virtual void sampleMap(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamples) const; - /** \brief Sample the map with the default sampling options - * - * \param sampleQuad - quadrilateral region to sample over - * \param outSamples - the output samples will be placed here. - */ virtual inline void sampleMap(const SqSampleQuad& sampleQuad, TqFloat* outSamples) const; - /** \brief Get the current default sample options + /** \brief Get the current sample options */ - virtual inline SqTextureSampleOptions& defaultSampleOptions(); - /** \brief Get the current default sample options (const version) + virtual inline CqTextureSampleOptions& sampleOptions(); + /** \brief Get the current sample options (const version) */ - virtual inline const SqTextureSampleOptions& defaultSampleOptions() const; + virtual inline const CqTextureSampleOptions& sampleOptions() const; virtual ~CqTextureMap2() {} private: - std::string m_fileName; - /** \brief List of samplers for mipmap levels. The pointers to these - * may be NULL since they are created only on demand. - */ - mutable std::vector<boost::shared_ptr<IqTextureSampler> > m_mipLevels; - SqTextureSampleOptions m_defaultSampleOptions; + boost::shared_ptr<CqMipmapLevels> m_mipLevels; ///< Collection of mipmap levels + CqTextureSampleOptions m_sampleOptions; ///< sampler options }; /** Temporary wrapper class for CqTextureMap2 to squash it into the shape of @@ -121,7 +97,7 @@ class CqTextureMap2Wrapper : public IqTextureMap { public: - CqTextureMap2Wrapper(const std::string& fileName); + CqTextureMap2Wrapper(const std::string& texName); // The following are overridden from IqTextureMap. It's rather a fat // interface and badly needs to be slimmed down. @@ -151,10 +127,10 @@ virtual TqInt NumPages() const; private: - /// \todo replace this with std::string when the interface is revamped. - mutable CqString m_fileName; + mutable CqString m_texName; + CqMipmapLevels m_levels; CqTextureMap2 m_realMap; - SqTextureSampleOptions m_sampleOptions; + CqTextureSampleOptions m_sampleOptions; }; @@ -162,27 +138,20 @@ // Implementation details //============================================================================== -// CqTextureMap2 implementation -inline void CqTextureMap2::sampleMap(const SqSampleQuad& sampleQuad, - TqFloat* outSamples) const -{ - sampleMap(sampleQuad, m_defaultSampleOptions, outSamples); -} - inline const CqTexFileHeader* CqTextureMap2::attributes() const { /// \todo implementation return 0; } -inline SqTextureSampleOptions& CqTextureMap2::defaultSampleOptions() +inline CqTextureSampleOptions& CqTextureMap2::sampleOptions() { - return m_defaultSampleOptions; + return m_sampleOptions; } -inline const SqTextureSampleOptions& CqTextureMap2::defaultSampleOptions() const +inline const CqTextureSampleOptions& CqTextureMap2::sampleOptions() const { - return m_defaultSampleOptions; + return m_sampleOptions; } @@ -221,8 +190,8 @@ inline const CqString& CqTextureMap2Wrapper::getName() const { // \todo implementation - m_fileName = m_realMap.name(); - return m_fileName; + m_texName = m_realMap.name(); + return m_texName; } inline bool CqTextureMap2Wrapper::IsValid() const Modified: branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.cpp =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.cpp 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.cpp 2007-12-02 02:31:46 UTC (rev 1813) @@ -44,4 +44,37 @@ } +//------------------------------------------------------------------------------ +// CqTextureSampleOptions implementation + +void CqTextureSampleOptions::adjustSampleQuad(SqSampleQuad& quad) +{ + bool widthAdjust = m_sWidth != 1 || m_tWidth != 1; + bool blurAdjust = m_sBlur > 0 || m_tBlur > 0; + if(widthAdjust || blurAdjust) + { + CqVector2D center = 0.25*(quad.v1 + quad.v2 + quad.v3 + quad.v4); + if(widthAdjust) + { + TqFloat csWeighted = (1-m_sWidth)*center.x(); + TqFloat ctWeighted = (1-m_tWidth)*center.y(); + // Expand v1...v4 away from the quad center by multiplying the x + // and y components of the vectors which point from the quad center to + // the vertices by the s and t widths respectively. + quad.v1.x(m_sWidth*quad.v1.x() + csWeighted); + quad.v1.y(m_tWidth*quad.v1.y() + ctWeighted); + quad.v2.x(m_sWidth*quad.v2.x() + csWeighted); + quad.v2.y(m_tWidth*quad.v2.y() + ctWeighted); + quad.v3.x(m_sWidth*quad.v3.x() + csWeighted); + quad.v3.y(m_tWidth*quad.v3.y() + ctWeighted); + quad.v4.x(m_sWidth*quad.v4.x() + csWeighted); + quad.v4.y(m_tWidth*quad.v4.y() + ctWeighted); + } + if(blurAdjust) + { + /// \todo implementation + } + } +} + } // namespace Aqsis Modified: branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.h =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.h 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/texturesampleoptions.h 2007-12-02 02:31:46 UTC (rev 1813) @@ -29,6 +29,8 @@ #include "aqsis.h" +#include "samplequad.h" + namespace Aqsis { @@ -79,53 +81,138 @@ //---------------------------------------------------------------------- /** \brief Contain the standard renderman texture/environment sampling options * - * This struct holds many of the sampling parameters which may be passed to the + * This class holds many of the sampling parameters which may be passed to the * texture() and environment() RSL calls. Note that blur and width are left - * out; the more specific sblur,tblur, are used instead. + * out; the more specific sBlur,tBlur, etc are used instead. */ -struct SqTextureSampleOptions +class CqTextureSampleOptions { - /// Additional texture blurs in the s and t directions. - TqFloat sblur; - TqFloat tblur; - /// Filter widths as a multiple of the given filter box. - TqFloat swidth; - TqFloat twidth; - /// Type of filter - represents both the filter weight function and filtering algorithm. - EqTextureFilter filterType; - /// Value to fill a channel with if the associated texture doesn't contain sufficiently many channels. - TqFloat fill; - /// Index of the starting channel (the first channel has index 0) - TqInt startChannel; - /// Number of channels to sample from the texture. - TqInt numChannels; - /// Number of samples to take when using a stochastic sampler - TqInt numSamples; - /// Wrap modes specifying what the sampler should do with (s,t) coordinates lying off the image edge. - EqWrapMode sWrapMode; - EqWrapMode tWrapMode; + public: + /// Trivial constructor. + inline CqTextureSampleOptions(TqFloat sBlur, TqFloat tBlur, TqFloat sWidth, + TqFloat tWidth, EqTextureFilter filterType, TqFloat fill, + TqInt startChannel, TqInt numChannels, + TqInt numSamples, EqWrapMode sWrapMode, EqWrapMode tWrapMode); + /** Default constructor + * + * Set all numerical quantities to 0 except for numSamples and numChannels + * which are set to 1. The filter is set to gaussian, and wrap modes to + * black. + */ + inline CqTextureSampleOptions(); - /// Trivial constructor. - inline SqTextureSampleOptions(TqFloat sblur, TqFloat tblur, TqFloat swidth, - TqFloat twidth, EqTextureFilter filterType, TqFloat fill, - TqInt startChannel, TqInt numChannels, TqInt numSamples, - EqWrapMode sWrapMode, EqWrapMode tWrapMode); - /** Default constructor - * - * Set all numerical quantities to 0 except for numSamples and numChannels - * which are set to 1. The filter is set to gaussian, and wrap modes to - * black. - */ - inline SqTextureSampleOptions(); + //-------------------------------------------------- + /// \name Accessors for all relevant texture sample options. + //@{ + /// Get the blur in the s-direction + inline TqFloat sBlur() const; + /// Get the blur in the t-direction + inline TqFloat tBlur() const; + /// Get the width multiplier in the s-direction + inline TqFloat sWidth() const; + /// Get the width multiplier in the t-direction + inline TqFloat tWidth() const; + /// Get the filter type + inline EqTextureFilter filterType() const; + /// Get the fill value for texture channels indices outside the available range + inline TqFloat fill() const; + /// Get the start channel index where channels will be read from. + inline TqInt startChannel() const; + /// Get the number of channels to sample + inline TqInt numChannels() const; + /// Get the number of samples used by stochastic sampling methods. + inline TqInt numSamples() const; + /// Get the wrap mode in the s-direction + inline EqWrapMode sWrapMode() const; + /// Get the wrap mode in the t-direction + inline EqWrapMode tWrapMode() const; + //@} + + //-------------------------------------------------- + /// \name Modifiers for all relevant texture sample options. + //@{ + /// Set the blur in both directions + inline void setBlur(TqFloat blur); + /// Set the blur in the s-direction + inline void setSBlur(TqFloat sBlur); + /// Set the blur in the t-direction + inline void setTBlur(TqFloat tBlur); + /// Set the width multiplier in all directions. + inline void setWidth(TqFloat width); + /// Set the width multiplier in the s-direction + inline void setSWidth(TqFloat sWidth); + /// Set the width multiplier in the t-direction + inline void setTWidth(TqFloat tWidth); + /// Set the filter type + inline void setFilterType(EqTextureFilter type); + /// Set the fill value for texture channels indices outside the available range + inline void setFill(TqFloat fill); + /// Set the start channel index where channels will be read from. + inline void setStartChannel(TqInt startChannel); + /// Set the number of channels to sample + inline void setNumChannels(TqInt numChannels); + /// Set the number of samples used by stochastic sampling methods. + inline void setNumSamples(TqInt numSamples); + /// Set the wrap mode in both directions + inline void setWrapMode(EqWrapMode wrapMode); + /// Set the wrap mode in the s-direction + inline void setSWrapMode(EqWrapMode sWrapMode); + /// Set the wrap mode in the t-direction + inline void setTWrapMode(EqWrapMode tWrapMode); + //@} + + //-------------------------------------------------- + /** \brief Adjust a sample quad to take into account the current blur + * and width parameters. + * + * The width parameter effects the quad in a simple way: All the + * vertices are contracted toward or exapanded away from the quad + * center point by multiplying by the width in the appropriate + * direction. + * + * The effect which blur *should* have on the quad is less certian, + * and perhaps it shouldn't effect it at all for ultimate quality. + * Here we take the approch that the quad is expanded by an additional + * amount equal to the blur parameters. This effectively causes blur + * by sampling with a coarser mipmap level. Experiments are required + * to determine whether the resulting quality will be sufficient. + * + * \param quad - sample quadrilateral to adjust. + */ + void adjustSampleQuad(SqSampleQuad& quad); + + protected: + /// Texture blur amount in the s and t directions. + TqFloat m_sBlur; + TqFloat m_tBlur; + /// Filter widths as a multiple of the given filter box. + TqFloat m_sWidth; + TqFloat m_tWidth; + /// Type of filter - represents both the filter weight function and filtering algorithm. + EqTextureFilter m_filterType; + /// Value to fill a channel with if the associated texture doesn't contain sufficiently many channels. + TqFloat m_fill; + /// Index of the starting channel (the first channel has index 0) + TqInt m_startChannel; + /// Number of channels to sample from the texture. + TqInt m_numChannels; + /// Limit on the number of channels in the associated texture file. + //TqInt m_numChannelsLimit; + /// Number of samples to take when using a stochastic sampler + TqInt m_numSamples; + /// Wrap modes specifying what the sampler should do with (s,t) coordinates + /// lying off the image edge. + EqWrapMode m_sWrapMode; + EqWrapMode m_tWrapMode; }; -struct SqShadowSampleOptions : private SqTextureSampleOptions +struct SqShadowSampleOptions : private CqTextureSampleOptions { /// \todo: Flesh this out when we eventually get around to redoing the shadow maps. - // (The inherited members need to be pulled in with "using") - TqFloat biasLow; - TqFloat biasHigh; + // (The inherited functions need to be pulled in with "using") + TqFloat m_biasLow; + TqFloat m_biasHigh; }; @@ -133,39 +220,177 @@ // Implementation details. //============================================================================== -// SqTextureSampleOptions implementation +// CqTextureSampleOptions implementation -inline SqTextureSampleOptions::SqTextureSampleOptions( TqFloat sblur, TqFloat tblur, - TqFloat swidth, TqFloat twidth, EqTextureFilter filterType, TqFloat fill, +inline CqTextureSampleOptions::CqTextureSampleOptions( TqFloat sBlur, TqFloat tBlur, + TqFloat sWidth, TqFloat tWidth, EqTextureFilter filterType, TqFloat fill, TqInt startChannel, TqInt numChannels, TqInt numSamples, EqWrapMode sWrapMode, EqWrapMode tWrapMode) - : sblur(sblur), - tblur(tblur), - swidth(swidth), - twidth(twidth), - filterType(filterType), - fill(fill), - startChannel(startChannel), - numChannels(numChannels), - numSamples(numSamples), - sWrapMode(sWrapMode), - tWrapMode(tWrapMode) + : m_sBlur(sBlur), + m_tBlur(tBlur), + m_sWidth(sWidth), + m_tWidth(tWidth), + m_filterType(filterType), + m_fill(fill), + m_startChannel(startChannel), + m_numChannels(numChannels), + m_numSamples(numSamples), + m_sWrapMode(sWrapMode), + m_tWrapMode(tWrapMode) { } -inline SqTextureSampleOptions::SqTextureSampleOptions() - : sblur(0), - tblur(0), - swidth(0), - twidth(0), - filterType(TextureFilter_Gaussian), - fill(0), - startChannel(0), - numChannels(1), - numSamples(1), - sWrapMode(WrapMode_Black), - tWrapMode(WrapMode_Black) +inline CqTextureSampleOptions::CqTextureSampleOptions() + : m_sBlur(0), + m_tBlur(0), + m_sWidth(0), + m_tWidth(0), + m_filterType(TextureFilter_Gaussian), + m_fill(0), + m_startChannel(0), + m_numChannels(1), + m_numSamples(1), + m_sWrapMode(WrapMode_Black), + m_tWrapMode(WrapMode_Black) { } + +inline TqFloat CqTextureSampleOptions::sBlur() const +{ + return m_sBlur; +} + +inline TqFloat CqTextureSampleOptions::tBlur() const +{ + return m_tBlur; +} + +inline TqFloat CqTextureSampleOptions::sWidth() const +{ + return m_sWidth; +} + +inline TqFloat CqTextureSampleOptions::tWidth() const +{ + return m_tWidth; +} + +inline EqTextureFilter CqTextureSampleOptions::filterType() const +{ + return m_filterType; +} + +inline TqFloat CqTextureSampleOptions::fill() const +{ + return m_fill; +} + +inline TqInt CqTextureSampleOptions::startChannel() const +{ + return m_startChannel; +} + +inline TqInt CqTextureSampleOptions::numChannels() const +{ + return m_numChannels; +} + +inline TqInt CqTextureSampleOptions::numSamples() const +{ + return m_numSamples; +} + +inline EqWrapMode CqTextureSampleOptions::sWrapMode() const +{ + return m_sWrapMode; +} + +inline EqWrapMode CqTextureSampleOptions::tWrapMode() const +{ + return m_tWrapMode; +} + + +inline void CqTextureSampleOptions::setBlur(TqFloat blur) +{ + setSBlur(blur); + setTBlur(blur); +} + +inline void CqTextureSampleOptions::setSBlur(TqFloat sBlur) +{ + assert(sBlur >= 0); + m_sBlur = sBlur; +} + +inline void CqTextureSampleOptions::setTBlur(TqFloat tBlur) +{ + assert(tBlur >= 0); + m_tBlur = tBlur; +} + +inline void CqTextureSampleOptions::setWidth(TqFloat width) +{ + setSWidth(width); + setTWidth(width); +} + +inline void CqTextureSampleOptions::setSWidth(TqFloat sWidth) +{ + assert(sWidth >= 0); + m_sWidth = sWidth; +} + +inline void CqTextureSampleOptions::setTWidth(TqFloat tWidth) +{ + assert(tWidth >= 0); + m_tWidth = tWidth; +} + +inline void CqTextureSampleOptions::setFilterType(EqTextureFilter type) +{ + assert(type != TextureFilter_Unknown); + m_filterType = type; +} + +inline void CqTextureSampleOptions::setFill(TqFloat fill) +{ + m_fill = fill; +} + +inline void CqTextureSampleOptions::setStartChannel(TqInt startChannel) +{ + assert(startChannel >= 0); + m_startChannel = startChannel; +} + +inline void CqTextureSampleOptions::setNumChannels(TqInt numChannels) +{ + assert(numChannels >= 0); + m_numChannels = numChannels; +} + +inline void CqTextureSampleOptions::setNumSamples(TqInt numSamples) +{ + assert(numSamples >= 0); + m_numSamples = numSamples; +} + +inline void CqTextureSampleOptions::setWrapMode(EqWrapMode wrapMode) +{ + setSWrapMode(wrapMode); + setTWrapMode(wrapMode); +} + +inline void CqTextureSampleOptions::setSWrapMode(EqWrapMode sWrapMode) +{ + m_sWrapMode = sWrapMode; +} + +inline void CqTextureSampleOptions::setTWrapMode(EqWrapMode tWrapMode) +{ + m_tWrapMode = tWrapMode; +} + } // namespace Aqsis #endif // TEXTURESAMPLEOPTIONS_H_INCLUDED Modified: branches/texfiltering/aqsis/texturing/texlib/texturesampler.h =================================================================== --- branches/texfiltering/aqsis/texturing/texlib/texturesampler.h 2007-12-02 01:14:13 UTC (rev 1812) +++ branches/texfiltering/aqsis/texturing/texlib/texturesampler.h 2007-12-02 02:31:46 UTC (rev 1813) @@ -51,7 +51,7 @@ public: CqTextureSamplerImpl(const boost::shared_ptr<CqTileArray<T> >& texData); virtual void filter(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; private: inline TqFloat wrapCoord(TqFloat pos, EqWrapMode mode) const; inline CqVector2D texToRasterCoords(const CqVector2D& pos, @@ -65,7 +65,7 @@ * \param outSamps - the outSamps samples will be placed here. */ void filterSimple(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; //-------------------------------------------------- /// Methods for EWA filtering @@ -93,7 +93,7 @@ * \param outSamps - the outSamps samples will be placed here. */ void filterEWA(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; //@} //-------------------------------------------------- @@ -106,7 +106,7 @@ * \param samples - outSamps array for the samples. */ inline void sampleBilinear(const CqVector2D& st, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; /** \brief Filter using Monte Carlo integration with a box filter. * * Given an arbitrary filter weighting function, determining the @@ -122,7 +122,7 @@ * \param outSamps - the outSamps samples will be placed here. */ void filterMC(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const; //@} /// May be better put in the CqTextureTileArray class. @@ -155,9 +155,9 @@ { } template<typename T> -void CqTextureSamplerImpl<T>::filter(const SqSampleQuad& sampleQuad, const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const +void CqTextureSamplerImpl<T>::filter(const SqSampleQuad& sampleQuad, const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const { - switch(sampleOpts.filterType) + switch(sampleOpts.filterType()) { case TextureFilter_Box: filterMC(sampleQuad, sampleOpts, outSamps); @@ -202,7 +202,7 @@ template<typename T> void CqTextureSamplerImpl<T>::filterSimple( const SqSampleQuad& sQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const { sampleBilinear((sQuad.v1 + sQuad.v2 + sQuad.v3 + sQuad.v4)/4, sampleOpts, outSamps); @@ -321,11 +321,11 @@ template<typename T> void CqTextureSamplerImpl<T>::filterEWA( const SqSampleQuad& sQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const { /// \todo Write a function for this. // Zero the samples - for(TqInt i = 0; i < sampleOpts.numChannels; ++i) + for(TqInt i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] = 0; // Translate the sample quad to into raster coords. /// \todo Deal with edge effects... This may be tricky. @@ -365,7 +365,7 @@ if(q < logEdgeWeight) { TqFloat weight = exp(-q); - for(TqInt i = 0; i < sampleOpts.numChannels; ++i) + for(TqInt i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] += weight*dummyGridTex(s,t); totWeight += weight; } @@ -373,22 +373,22 @@ } // Renormalize the samples TqFloat renormalizer = 1/totWeight; - for(TqInt i = 0; i < sampleOpts.numChannels; ++i) + for(TqInt i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] *= renormalizer; } template<typename T> inline void CqTextureSamplerImpl<T>::sampleBilinear(const CqVector2D& st, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const { CqVector2D stRaster = texToRasterCoords(st, - sampleOpts.sWrapMode, sampleOpts.tWrapMode); + sampleOpts.sWrapMode(), sampleOpts.tWrapMode()); TqInt s = lfloor(stRaster.x()); TqInt t = lfloor(stRaster.y()); TqFloat sInterp = stRaster.x() - s; TqFloat tInterp = stRaster.y() - t; - for(TqInt i = 0; i < sampleOpts.numChannels; ++i) + for(TqInt i = 0; i < sampleOpts.numChannels(); ++i) { TqFloat texVal1 = dummyGridTex(s, t); TqFloat texVal2 = dummyGridTex(s+1, t); @@ -404,11 +404,11 @@ template<typename T> void CqTextureSamplerImpl<T>::filterMC(const SqSampleQuad& sampleQuad, - const SqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const + const CqTextureSampleOptions& sampleOpts, TqFloat* outSamps) const { - std::vector<TqFloat> tempSamps(sampleOpts.numChannels, 0); + std::vector<TqFloat> tempSamps(sampleOpts.numChannels(), 0); // zero all samples - for(int i = 0; i < sampleOpts.numChannels; ++i) + for(int i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] = 0; // MC integration loop /// \todo adjust quad for swidth, sblur etc. @@ -417,7 +417,7 @@ /// \todo Possible optimizaton: tabulate the random numbers? // CqRandom randGen; CqLowDiscrepancy randGen(2); - for(int i = 0; i < sampleOpts.numSamples; ++i) + for(int i = 0; i < sampleOpts.numSamples(); ++i) { // TqFloat interp1 = randGen.RandomFloat(); // TqFloat interp2 = randGen.RandomFloat(); @@ -428,12 +428,12 @@ lerp(interp2, adjustedQuad.v3, adjustedQuad.v4) ); sampleBilinear(samplePos, sampleOpts, &tempSamps[0]); - for(int i = 0; i < sampleOpts.numChannels; ++i) + for(int i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] += tempSamps[i]; } // normalize result by the number of samples - TqFloat renormalizer = 1.0f/sampleOpts.numSamples; - for(int i = 0; i < sampleOpts.numChannels; ++i) + TqFloat renormalizer = 1.0f/sampleOpts.numSamples(); + for(int i = 0; i < sampleOpts.numChannels(); ++i) outSamps[i] *= renormalizer; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |