/src/ogre/OgreMain/src/OgreTextureUnitState.cpp
Line | Count | Source |
1 | | /* |
2 | | ----------------------------------------------------------------------------- |
3 | | This source file is part of OGRE |
4 | | (Object-oriented Graphics Rendering Engine) |
5 | | For the latest info, see http://www.ogre3d.org |
6 | | |
7 | | Copyright (c) 2000-2014 Torus Knot Software Ltd |
8 | | |
9 | | Permission is hereby granted, free of charge, to any person obtaining a copy |
10 | | of this software and associated documentation files (the "Software"), to deal |
11 | | in the Software without restriction, including without limitation the rights |
12 | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | | copies of the Software, and to permit persons to whom the Software is |
14 | | furnished to do so, subject to the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be included in |
17 | | all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
20 | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
21 | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
22 | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
23 | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
24 | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
25 | | THE SOFTWARE. |
26 | | ----------------------------------------------------------------------------- |
27 | | */ |
28 | | #include "OgreStableHeaders.h" |
29 | | |
30 | | #include "OgreTextureUnitState.h" |
31 | | #include "OgreControllerManager.h" |
32 | | #include "OgreTextureManager.h" |
33 | | #include "OgreHardwarePixelBuffer.h" |
34 | | |
35 | | namespace Ogre { |
36 | | // allow operation without hardware support |
37 | | static SamplerPtr DUMMY_SAMPLER = std::make_shared<Sampler>(); |
38 | | |
39 | | Sampler::Sampler() |
40 | 4 | : mBorderColour(ColourValue::Black) |
41 | 4 | , mMaxAniso(1) |
42 | 4 | , mMipmapBias(0) |
43 | 4 | , mMinFilter(FO_LINEAR) |
44 | 4 | , mMagFilter(FO_LINEAR) |
45 | 4 | , mMipFilter(FO_POINT) |
46 | 4 | , mCompareFunc(CMPF_GREATER_EQUAL) |
47 | 4 | , mCompareEnabled(false) |
48 | 4 | , mDirty(true) |
49 | 4 | { |
50 | 4 | setAddressingMode(TAM_WRAP); |
51 | 4 | } |
52 | 0 | Sampler::~Sampler() {} |
53 | | //----------------------------------------------------------------------- |
54 | | void Sampler::setAddressingMode(const UVWAddressingMode& uvw) |
55 | 4 | { |
56 | 4 | mAddressMode = uvw; |
57 | 4 | mDirty = true; |
58 | 4 | } |
59 | | |
60 | | //----------------------------------------------------------------------- |
61 | | void Sampler::setFiltering(TextureFilterOptions filterType) |
62 | 0 | { |
63 | 0 | switch (filterType) |
64 | 0 | { |
65 | 0 | case TFO_NONE: |
66 | 0 | setFiltering(FO_POINT, FO_POINT, FO_NONE); |
67 | 0 | break; |
68 | 0 | case TFO_BILINEAR: |
69 | 0 | setFiltering(FO_LINEAR, FO_LINEAR, FO_POINT); |
70 | 0 | break; |
71 | 0 | case TFO_TRILINEAR: |
72 | 0 | setFiltering(FO_LINEAR, FO_LINEAR, FO_LINEAR); |
73 | 0 | break; |
74 | 0 | case TFO_ANISOTROPIC: |
75 | 0 | setFiltering(FO_ANISOTROPIC, FO_ANISOTROPIC, FO_LINEAR); |
76 | 0 | break; |
77 | 0 | } |
78 | 0 | } |
79 | | //----------------------------------------------------------------------- |
80 | | void Sampler::setFiltering(FilterType ft, FilterOptions fo) |
81 | 0 | { |
82 | 0 | switch (ft) |
83 | 0 | { |
84 | 0 | case FT_MIN: |
85 | 0 | mMinFilter = fo; |
86 | 0 | break; |
87 | 0 | case FT_MAG: |
88 | 0 | mMagFilter = fo; |
89 | 0 | break; |
90 | 0 | case FT_MIP: |
91 | 0 | mMipFilter = fo; |
92 | 0 | break; |
93 | 0 | } |
94 | 0 | mDirty = true; |
95 | 0 | } |
96 | | //----------------------------------------------------------------------- |
97 | | void Sampler::setFiltering(FilterOptions minFilter, FilterOptions magFilter, FilterOptions mipFilter) |
98 | 0 | { |
99 | 0 | mMinFilter = minFilter; |
100 | 0 | mMagFilter = magFilter; |
101 | 0 | mMipFilter = mipFilter; |
102 | 0 | mDirty = true; |
103 | 0 | } |
104 | | //----------------------------------------------------------------------- |
105 | | FilterOptions Sampler::getFiltering(FilterType ft) const |
106 | 0 | { |
107 | 0 | switch (ft) |
108 | 0 | { |
109 | 0 | case FT_MIN: |
110 | 0 | return mMinFilter; |
111 | 0 | case FT_MAG: |
112 | 0 | return mMagFilter; |
113 | 0 | case FT_MIP: |
114 | 0 | return mMipFilter; |
115 | 0 | } |
116 | | // to keep compiler happy |
117 | 0 | return mMinFilter; |
118 | 0 | } |
119 | | //----------------------------------------------------------------------- |
120 | | TextureUnitState::TextureUnitState(Pass* parent) |
121 | 0 | : mCurrentFrame(0) |
122 | 0 | , mAnimDuration(0) |
123 | 0 | , mUnorderedAccessMipLevel(-1) |
124 | 0 | , mGamma(1) |
125 | 0 | , mUMod(0) |
126 | 0 | , mVMod(0) |
127 | 0 | , mUScale(1) |
128 | 0 | , mVScale(1) |
129 | 0 | , mRotate(0) |
130 | 0 | , mTexModMatrix(Matrix4::IDENTITY) |
131 | 0 | , mContentType(CONTENT_NAMED) |
132 | 0 | , mTextureLoadFailed(false) |
133 | 0 | , mRecalcTexMatrix(false) |
134 | 0 | , mTextureCoordSetIndex(0) |
135 | 0 | , mFramePtrs(1) |
136 | 0 | , mSampler(TextureManager::getSingletonPtr() ? TextureManager::getSingleton().getDefaultSampler() : DUMMY_SAMPLER) |
137 | 0 | , mParent(parent) |
138 | 0 | , mAnimController(0) |
139 | 0 | { |
140 | 0 | mColourBlendMode.blendType = LBT_COLOUR; |
141 | 0 | mAlphaBlendMode.operation = LBX_MODULATE; |
142 | 0 | mAlphaBlendMode.blendType = LBT_ALPHA; |
143 | 0 | mAlphaBlendMode.source1 = LBS_TEXTURE; |
144 | 0 | mAlphaBlendMode.source2 = LBS_CURRENT; |
145 | 0 | setColourOperation(LBO_MODULATE); |
146 | |
|
147 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
148 | 0 | { |
149 | 0 | mParent->_dirtyHash(); |
150 | 0 | } |
151 | |
|
152 | 0 | } |
153 | | |
154 | | //----------------------------------------------------------------------- |
155 | | TextureUnitState::TextureUnitState(Pass* parent, const TextureUnitState& oth ) |
156 | 0 | { |
157 | 0 | mParent = parent; |
158 | 0 | mAnimController = 0; |
159 | 0 | *this = oth; |
160 | 0 | } |
161 | | |
162 | | //----------------------------------------------------------------------- |
163 | | TextureUnitState::TextureUnitState( Pass* parent, const String& texName, uint8 texCoordSet) |
164 | 0 | : TextureUnitState(parent) |
165 | 0 | { |
166 | 0 | setTextureName(texName); |
167 | 0 | setTextureCoordSet(texCoordSet); |
168 | 0 | } |
169 | | //----------------------------------------------------------------------- |
170 | | TextureUnitState::~TextureUnitState() |
171 | 0 | { |
172 | | // Unload ensure all controllers destroyed |
173 | 0 | _unload(); |
174 | 0 | } |
175 | | //----------------------------------------------------------------------- |
176 | | TextureUnitState & TextureUnitState::operator = ( |
177 | | const TextureUnitState &oth ) |
178 | 0 | { |
179 | 0 | if (this == &oth) |
180 | 0 | return *this; |
181 | | |
182 | 0 | assert(mAnimController == 0); |
183 | 0 | removeAllEffects(); |
184 | | |
185 | | // copy basic members (int's, real's) |
186 | 0 | memcpy( (uchar*)this, &oth, (const uchar *)(&oth.mFramePtrs) - (const uchar *)(&oth) ); |
187 | | // copy complex members |
188 | 0 | mFramePtrs = oth.mFramePtrs; |
189 | 0 | mSampler = oth.mSampler; |
190 | 0 | mName = oth.mName; |
191 | 0 | mEffects = oth.mEffects; |
192 | |
|
193 | 0 | mCompositorRefName = oth.mCompositorRefName; |
194 | 0 | mCompositorRefTexName = oth.mCompositorRefTexName; |
195 | | // Can't sharing controllers with other TUS, reset to null to avoid potential bug. |
196 | 0 | for (auto & e : mEffects) |
197 | 0 | { |
198 | 0 | e.second.controller = 0; |
199 | 0 | } |
200 | | |
201 | | // Load immediately if Material loaded |
202 | 0 | if (isLoaded()) |
203 | 0 | { |
204 | 0 | _load(); |
205 | 0 | } |
206 | | |
207 | | // Tell parent to recalculate hash |
208 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
209 | 0 | { |
210 | 0 | mParent->_dirtyHash(); |
211 | 0 | } |
212 | |
|
213 | 0 | return *this; |
214 | 0 | } |
215 | | //----------------------------------------------------------------------- |
216 | | const String& TextureUnitState::getTextureName(void) const |
217 | 0 | { |
218 | | // Return name of current frame |
219 | 0 | if (mCurrentFrame < mFramePtrs.size() && mFramePtrs[mCurrentFrame]) |
220 | 0 | return mFramePtrs[mCurrentFrame]->getName(); |
221 | 0 | else |
222 | 0 | return BLANKSTRING; |
223 | 0 | } |
224 | | //----------------------------------------------------------------------- |
225 | | void TextureUnitState::setTextureName( const String& name) |
226 | 0 | { |
227 | 0 | if(TexturePtr tex = retrieveTexture(name)) |
228 | 0 | setTexture(tex); |
229 | 0 | } |
230 | | |
231 | | void TextureUnitState::setTextureName( const String& name, TextureType texType) |
232 | 0 | { |
233 | 0 | TexturePtr tex = retrieveTexture(name); |
234 | |
|
235 | 0 | if(!tex) |
236 | 0 | return; |
237 | | |
238 | 0 | tex->setTextureType(texType); |
239 | 0 | setTexture(tex); |
240 | 0 | } |
241 | | //----------------------------------------------------------------------- |
242 | | void TextureUnitState::setTexture( const TexturePtr& texPtr) |
243 | 0 | { |
244 | 0 | if (!texPtr) |
245 | 0 | { |
246 | 0 | OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, |
247 | 0 | "Texture Pointer is empty.", |
248 | 0 | "TextureUnitState::setTexture"); |
249 | 0 | } |
250 | | |
251 | 0 | setContentType(CONTENT_NAMED); |
252 | 0 | mTextureLoadFailed = false; |
253 | | |
254 | 0 | if (texPtr->getTextureType() == TEX_TYPE_EXTERNAL_OES) |
255 | 0 | { |
256 | 0 | setTextureAddressingMode( TAM_CLAMP ); |
257 | 0 | setTextureFiltering(FT_MIP, FO_NONE); |
258 | 0 | } |
259 | |
|
260 | 0 | mFramePtrs.resize(1); |
261 | 0 | mFramePtrs[0] = texPtr; |
262 | |
|
263 | 0 | mCurrentFrame = 0; |
264 | | |
265 | | // Load immediately ? |
266 | 0 | if (isLoaded()) |
267 | 0 | { |
268 | 0 | _load(); // reload |
269 | 0 | } |
270 | | // Tell parent to recalculate hash |
271 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
272 | 0 | { |
273 | 0 | mParent->_dirtyHash(); |
274 | 0 | } |
275 | 0 | } |
276 | | //----------------------------------------------------------------------- |
277 | | void TextureUnitState::setContentType(TextureUnitState::ContentType ct) |
278 | 0 | { |
279 | 0 | mContentType = ct; |
280 | 0 | } |
281 | | //----------------------------------------------------------------------- |
282 | | TextureUnitState::ContentType TextureUnitState::getContentType(void) const |
283 | 0 | { |
284 | 0 | return mContentType; |
285 | 0 | } |
286 | | //----------------------------------------------------------------------- |
287 | | TextureType TextureUnitState::getTextureType(void) const |
288 | 0 | { |
289 | 0 | return !mFramePtrs[0] ? TEX_TYPE_2D : mFramePtrs[0]->getTextureType(); |
290 | 0 | } |
291 | | |
292 | | //----------------------------------------------------------------------- |
293 | | void TextureUnitState::setFrameTextureName(const String& name, unsigned int frameNumber) |
294 | 0 | { |
295 | 0 | mTextureLoadFailed = false; |
296 | 0 | OgreAssert(frameNumber < mFramePtrs.size(), "out of range"); |
297 | | |
298 | 0 | mFramePtrs[frameNumber] = retrieveTexture(name); |
299 | |
|
300 | 0 | if (isLoaded()) |
301 | 0 | { |
302 | 0 | _load(); // reload |
303 | 0 | } |
304 | | // Tell parent to recalculate hash |
305 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
306 | 0 | { |
307 | 0 | mParent->_dirtyHash(); |
308 | 0 | } |
309 | 0 | } |
310 | | |
311 | | //----------------------------------------------------------------------- |
312 | | void TextureUnitState::addFrameTextureName(const String& name) |
313 | 0 | { |
314 | 0 | setContentType(CONTENT_NAMED); |
315 | 0 | mTextureLoadFailed = false; |
316 | |
|
317 | 0 | mFramePtrs.push_back(retrieveTexture(name)); |
318 | | |
319 | | // Load immediately if Material loaded |
320 | 0 | if (isLoaded()) |
321 | 0 | { |
322 | 0 | _load(); |
323 | 0 | } |
324 | | // Tell parent to recalculate hash |
325 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
326 | 0 | { |
327 | 0 | mParent->_dirtyHash(); |
328 | 0 | } |
329 | 0 | } |
330 | | |
331 | | //----------------------------------------------------------------------- |
332 | | void TextureUnitState::deleteFrameTextureName(const size_t frameNumber) |
333 | 0 | { |
334 | 0 | mTextureLoadFailed = false; |
335 | 0 | OgreAssert(frameNumber < mFramePtrs.size(), "out of range"); |
336 | 0 | mFramePtrs.erase(mFramePtrs.begin() + frameNumber); |
337 | |
|
338 | 0 | if (isLoaded()) |
339 | 0 | { |
340 | 0 | _load(); |
341 | 0 | } |
342 | | // Tell parent to recalculate hash |
343 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
344 | 0 | { |
345 | 0 | mParent->_dirtyHash(); |
346 | 0 | } |
347 | 0 | } |
348 | | |
349 | | void TextureUnitState::setCubicTextureName(const String* const names, bool forUVW) |
350 | 0 | { |
351 | 0 | setLayerArrayNames(TEX_TYPE_CUBE_MAP, std::vector<String>(names, names + 6)); |
352 | 0 | } |
353 | | |
354 | | //----------------------------------------------------------------------- |
355 | | void TextureUnitState::setAnimatedTextureName( const String& name, size_t numFrames, Real duration) |
356 | 0 | { |
357 | 0 | String baseName, ext; |
358 | 0 | StringUtil::splitBaseFilename(name, baseName, ext); |
359 | |
|
360 | 0 | std::vector<String> names(numFrames); |
361 | 0 | for (uint32 i = 0; i < names.size(); ++i) |
362 | 0 | { |
363 | 0 | names[i] = StringUtil::format("%s_%u.%s", baseName.c_str(), i, ext.c_str()); |
364 | 0 | } |
365 | |
|
366 | 0 | setAnimatedTextureName(names, duration); |
367 | 0 | } |
368 | | //----------------------------------------------------------------------- |
369 | | void TextureUnitState::setAnimatedTextureName(const String* const names, size_t numFrames, Real duration) |
370 | 0 | { |
371 | 0 | setContentType(CONTENT_NAMED); |
372 | 0 | mTextureLoadFailed = false; |
373 | | |
374 | | // resize pointers, but don't populate until needed |
375 | 0 | mFramePtrs.resize(numFrames); |
376 | 0 | mAnimDuration = duration; |
377 | 0 | mCurrentFrame = 0; |
378 | |
|
379 | 0 | for (unsigned int i = 0; i < mFramePtrs.size(); ++i) |
380 | 0 | { |
381 | 0 | mFramePtrs[i] = retrieveTexture(names[i]); |
382 | 0 | } |
383 | | |
384 | | // Load immediately if Material loaded |
385 | 0 | if (isLoaded()) |
386 | 0 | { |
387 | 0 | _load(); |
388 | 0 | } |
389 | | // Tell parent to recalculate hash |
390 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
391 | 0 | { |
392 | 0 | mParent->_dirtyHash(); |
393 | 0 | } |
394 | 0 | } |
395 | | void TextureUnitState::setLayerArrayNames(TextureType type, const std::vector<String>& names) |
396 | 0 | { |
397 | 0 | OgreAssert(!names.empty(), "array layers empty"); |
398 | | |
399 | 0 | const char* typeName; |
400 | 0 | switch(type) |
401 | 0 | { |
402 | 0 | case TEX_TYPE_CUBE_MAP: |
403 | 0 | typeName = "Cube"; |
404 | 0 | break; |
405 | 0 | case TEX_TYPE_2D_ARRAY: |
406 | 0 | typeName = "Array"; |
407 | 0 | break; |
408 | 0 | case TEX_TYPE_3D: |
409 | 0 | typeName = "Volume"; |
410 | 0 | break; |
411 | 0 | default: |
412 | 0 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "arrays not possible for this texture type"); |
413 | 0 | return; |
414 | 0 | } |
415 | | |
416 | | // use hash to auto-name the texture |
417 | 0 | uint32 hash = 0; |
418 | 0 | for(const String& name : names) |
419 | 0 | hash = FastHash(name.data(), name.size(), hash); |
420 | |
|
421 | 0 | auto tex = retrieveTexture(StringUtil::format("%sTex_%x", typeName, hash)); |
422 | 0 | tex->setTextureType(type); |
423 | 0 | tex->setLayerNames(names); |
424 | 0 | setTexture(tex); |
425 | 0 | } |
426 | | |
427 | | //----------------------------------------------------------------------- |
428 | | std::pair<uint32, uint32> TextureUnitState::getTextureDimensions(unsigned int frame) const |
429 | 0 | { |
430 | | |
431 | 0 | TexturePtr tex = _getTexturePtr(frame); |
432 | 0 | if (!tex) |
433 | 0 | OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, "Could not find texture " + StringConverter::toString(frame), |
434 | 0 | "TextureUnitState::getTextureDimensions" ); |
435 | | |
436 | 0 | return {tex->getWidth(), tex->getHeight()}; |
437 | 0 | } |
438 | | //----------------------------------------------------------------------- |
439 | | void TextureUnitState::setCurrentFrame(unsigned int frameNumber) |
440 | 0 | { |
441 | 0 | OgreAssert(frameNumber < mFramePtrs.size(), "out of range"); |
442 | 0 | mCurrentFrame = frameNumber; |
443 | | // this will affect the hash |
444 | 0 | if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) |
445 | 0 | { |
446 | 0 | mParent->_dirtyHash(); |
447 | 0 | } |
448 | 0 | } |
449 | | //----------------------------------------------------------------------- |
450 | | unsigned int TextureUnitState::getCurrentFrame(void) const |
451 | 0 | { |
452 | 0 | return mCurrentFrame; |
453 | 0 | } |
454 | | //----------------------------------------------------------------------- |
455 | | unsigned int TextureUnitState::getNumFrames(void) const |
456 | 0 | { |
457 | 0 | return (unsigned int)mFramePtrs.size(); |
458 | 0 | } |
459 | | //----------------------------------------------------------------------- |
460 | | const String& TextureUnitState::getFrameTextureName(unsigned int frameNumber) const |
461 | 0 | { |
462 | 0 | OgreAssert(frameNumber < mFramePtrs.size(), "out of range"); |
463 | | |
464 | 0 | return mFramePtrs[0] ? mFramePtrs[frameNumber]->getName() : BLANKSTRING; |
465 | 0 | } |
466 | | //----------------------------------------------------------------------- |
467 | | void TextureUnitState::setDesiredFormat(PixelFormat desiredFormat) |
468 | 0 | { |
469 | 0 | OgreAssert(mFramePtrs[0], "frame must not be blank"); |
470 | 0 | for(auto& frame : mFramePtrs) |
471 | 0 | frame->setFormat(desiredFormat); |
472 | 0 | } |
473 | | //----------------------------------------------------------------------- |
474 | | PixelFormat TextureUnitState::getDesiredFormat(void) const |
475 | 0 | { |
476 | 0 | return !mFramePtrs[0] ? PF_UNKNOWN : mFramePtrs[0]->getDesiredFormat(); |
477 | 0 | } |
478 | | //----------------------------------------------------------------------- |
479 | | void TextureUnitState::setNumMipmaps(int numMipmaps) |
480 | 0 | { |
481 | 0 | OgreAssert(mFramePtrs[0], "frame must not be blank"); |
482 | 0 | for (auto& frame : mFramePtrs) |
483 | 0 | frame->setNumMipmaps(numMipmaps == MIP_DEFAULT |
484 | 0 | ? TextureManager::getSingleton().getDefaultNumMipmaps() |
485 | 0 | : numMipmaps); |
486 | 0 | } |
487 | | //----------------------------------------------------------------------- |
488 | | int TextureUnitState::getNumMipmaps(void) const |
489 | 0 | { |
490 | 0 | return !mFramePtrs[0] ? int(MIP_DEFAULT) : mFramePtrs[0]->getNumMipmaps(); |
491 | 0 | } |
492 | | //----------------------------------------------------------------------- |
493 | | void TextureUnitState::setIsAlpha(bool isAlpha) |
494 | 0 | { |
495 | 0 | OgreAssert(mFramePtrs[0], "frame must not be blank"); |
496 | 0 | OGRE_IGNORE_DEPRECATED_BEGIN |
497 | 0 | for(auto& frame : mFramePtrs) |
498 | 0 | frame->setTreatLuminanceAsAlpha(isAlpha); |
499 | 0 | OGRE_IGNORE_DEPRECATED_END |
500 | 0 | } |
501 | | float TextureUnitState::getGamma() const |
502 | 0 | { |
503 | 0 | return !mFramePtrs[0] ? 1.0f : mFramePtrs[0]->getGamma(); |
504 | 0 | } |
505 | | void TextureUnitState::setGamma(float gamma) |
506 | 0 | { |
507 | 0 | OgreAssert(mFramePtrs[0], "frame must not be blank"); |
508 | 0 | for(auto& frame : mFramePtrs) |
509 | 0 | frame->setGamma(gamma); |
510 | 0 | } |
511 | | //----------------------------------------------------------------------- |
512 | | void TextureUnitState::setHardwareGammaEnabled(bool g) |
513 | 0 | { |
514 | 0 | OgreAssert(mFramePtrs[0], "frame must not be blank"); |
515 | 0 | for(auto& frame : mFramePtrs) |
516 | 0 | frame->setHardwareGammaEnabled(g); |
517 | 0 | } |
518 | | //----------------------------------------------------------------------- |
519 | | bool TextureUnitState::isHardwareGammaEnabled() const |
520 | 0 | { |
521 | 0 | return mFramePtrs[0] && mFramePtrs[0]->isHardwareGammaEnabled(); |
522 | 0 | } |
523 | | //----------------------------------------------------------------------- |
524 | | uint8 TextureUnitState::getTextureCoordSet(void) const |
525 | 0 | { |
526 | 0 | return mTextureCoordSetIndex; |
527 | 0 | } |
528 | | //----------------------------------------------------------------------- |
529 | | void TextureUnitState::setTextureCoordSet(uint8 set) |
530 | 0 | { |
531 | 0 | mTextureCoordSetIndex = set; |
532 | 0 | } |
533 | | //----------------------------------------------------------------------- |
534 | | void TextureUnitState::setColourOperationEx(LayerBlendOperationEx op, |
535 | | LayerBlendSource source1, |
536 | | LayerBlendSource source2, |
537 | | const ColourValue& arg1, |
538 | | const ColourValue& arg2, |
539 | | Real manualBlend) |
540 | 0 | { |
541 | 0 | mColourBlendMode.operation = op; |
542 | 0 | mColourBlendMode.source1 = source1; |
543 | 0 | mColourBlendMode.source2 = source2; |
544 | 0 | mColourBlendMode.colourArg1 = arg1; |
545 | 0 | mColourBlendMode.colourArg2 = arg2; |
546 | 0 | mColourBlendMode.factor = manualBlend; |
547 | 0 | } |
548 | | //----------------------------------------------------------------------- |
549 | | void TextureUnitState::setColourOperation(LayerBlendOperation op) |
550 | 0 | { |
551 | | // Set up the multitexture and multipass blending operations |
552 | 0 | switch (op) |
553 | 0 | { |
554 | 0 | case LBO_REPLACE: |
555 | 0 | setColourOperationEx(LBX_SOURCE1, LBS_TEXTURE, LBS_CURRENT); |
556 | 0 | setColourOpMultipassFallback(SBF_ONE, SBF_ZERO); |
557 | 0 | break; |
558 | 0 | case LBO_ADD: |
559 | 0 | setColourOperationEx(LBX_ADD, LBS_TEXTURE, LBS_CURRENT); |
560 | 0 | setColourOpMultipassFallback(SBF_ONE, SBF_ONE); |
561 | 0 | break; |
562 | 0 | case LBO_MODULATE: |
563 | 0 | setColourOperationEx(LBX_MODULATE, LBS_TEXTURE, LBS_CURRENT); |
564 | 0 | setColourOpMultipassFallback(SBF_DEST_COLOUR, SBF_ZERO); |
565 | 0 | break; |
566 | 0 | case LBO_ALPHA_BLEND: |
567 | 0 | setColourOperationEx(LBX_BLEND_TEXTURE_ALPHA, LBS_TEXTURE, LBS_CURRENT); |
568 | 0 | setColourOpMultipassFallback(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA); |
569 | 0 | break; |
570 | 0 | } |
571 | | |
572 | |
|
573 | 0 | } |
574 | | //----------------------------------------------------------------------- |
575 | | void TextureUnitState::setColourOpMultipassFallback(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor) |
576 | 0 | { |
577 | 0 | mColourBlendFallbackSrc = sourceFactor; |
578 | 0 | mColourBlendFallbackDest = destFactor; |
579 | 0 | } |
580 | | //----------------------------------------------------------------------- |
581 | | void TextureUnitState::setAlphaOperation(LayerBlendOperationEx op, |
582 | | LayerBlendSource source1, |
583 | | LayerBlendSource source2, |
584 | | Real arg1, |
585 | | Real arg2, |
586 | | Real manualBlend) |
587 | 0 | { |
588 | 0 | mAlphaBlendMode.operation = op; |
589 | 0 | mAlphaBlendMode.source1 = source1; |
590 | 0 | mAlphaBlendMode.source2 = source2; |
591 | 0 | mAlphaBlendMode.alphaArg1 = arg1; |
592 | 0 | mAlphaBlendMode.alphaArg2 = arg2; |
593 | 0 | mAlphaBlendMode.factor = manualBlend; |
594 | 0 | } |
595 | | //----------------------------------------------------------------------- |
596 | | void TextureUnitState::addEffect(TextureEffect effect) |
597 | 0 | { |
598 | | // Ensure controller pointer is null |
599 | 0 | effect.controller = 0; |
600 | |
|
601 | 0 | if (effect.type != ET_TRANSFORM) |
602 | 0 | { |
603 | | // Replace - must be unique |
604 | | // Search for existing effect of this type |
605 | 0 | EffectMap::iterator i = mEffects.find(effect.type); |
606 | 0 | if (i != mEffects.end()) |
607 | 0 | { |
608 | | // Destroy old effect controller if exist |
609 | 0 | if (i->second.controller) |
610 | 0 | { |
611 | 0 | ControllerManager::getSingleton().destroyController(i->second.controller); |
612 | 0 | } |
613 | |
|
614 | 0 | mEffects.erase(i); |
615 | 0 | } |
616 | 0 | } |
617 | |
|
618 | 0 | if (isLoaded()) |
619 | 0 | { |
620 | | // Create controller |
621 | 0 | createEffectController(effect); |
622 | 0 | } |
623 | | |
624 | | // Record new effect |
625 | 0 | mEffects.emplace(effect.type, effect); |
626 | |
|
627 | 0 | } |
628 | | //----------------------------------------------------------------------- |
629 | | void TextureUnitState::removeAllEffects(void) |
630 | 0 | { |
631 | | // Iterate over effects to remove controllers |
632 | 0 | EffectMap::iterator i, iend; |
633 | 0 | iend = mEffects.end(); |
634 | 0 | for (i = mEffects.begin(); i != iend; ++i) |
635 | 0 | { |
636 | 0 | if (i->second.controller) |
637 | 0 | { |
638 | 0 | ControllerManager::getSingleton().destroyController(i->second.controller); |
639 | 0 | } |
640 | 0 | } |
641 | |
|
642 | 0 | mEffects.clear(); |
643 | 0 | } |
644 | | |
645 | | //----------------------------------------------------------------------- |
646 | | bool TextureUnitState::isBlank(void) const |
647 | 0 | { |
648 | 0 | return !mFramePtrs[0] || mTextureLoadFailed; |
649 | 0 | } |
650 | | |
651 | | //----------------------------------------------------------------------- |
652 | | SceneBlendFactor TextureUnitState::getColourBlendFallbackSrc(void) const |
653 | 0 | { |
654 | 0 | return mColourBlendFallbackSrc; |
655 | 0 | } |
656 | | //----------------------------------------------------------------------- |
657 | | SceneBlendFactor TextureUnitState::getColourBlendFallbackDest(void) const |
658 | 0 | { |
659 | 0 | return mColourBlendFallbackDest; |
660 | 0 | } |
661 | | //----------------------------------------------------------------------- |
662 | | const LayerBlendModeEx& TextureUnitState::getColourBlendMode(void) const |
663 | 0 | { |
664 | 0 | return mColourBlendMode; |
665 | 0 | } |
666 | | //----------------------------------------------------------------------- |
667 | | const LayerBlendModeEx& TextureUnitState::getAlphaBlendMode(void) const |
668 | 0 | { |
669 | 0 | return mAlphaBlendMode; |
670 | 0 | } |
671 | | //----------------------------------------------------------------------- |
672 | | void TextureUnitState::setEnvironmentMap(bool enable, int envMapType) |
673 | 0 | { |
674 | 0 | if (enable) |
675 | 0 | { |
676 | 0 | TextureEffect eff = {ET_ENVIRONMENT_MAP}; |
677 | 0 | eff.subtype = envMapType; |
678 | 0 | addEffect(eff); |
679 | 0 | } |
680 | 0 | else |
681 | 0 | { |
682 | 0 | removeEffect(ET_ENVIRONMENT_MAP); |
683 | 0 | } |
684 | 0 | } |
685 | | //----------------------------------------------------------------------- |
686 | | void TextureUnitState::removeEffect(TextureEffectType type) |
687 | 0 | { |
688 | | // Get range of items matching this effect |
689 | 0 | std::pair< EffectMap::iterator, EffectMap::iterator > remPair = |
690 | 0 | mEffects.equal_range( type ); |
691 | | // Remove controllers |
692 | 0 | for (EffectMap::iterator i = remPair.first; i != remPair.second; ++i) |
693 | 0 | { |
694 | 0 | if (i->second.controller) |
695 | 0 | { |
696 | 0 | ControllerManager::getSingleton().destroyController(i->second.controller); |
697 | 0 | } |
698 | 0 | } |
699 | | // Erase |
700 | 0 | mEffects.erase( remPair.first, remPair.second ); |
701 | 0 | } |
702 | | //----------------------------------------------------------------------- |
703 | | void TextureUnitState::setBlank(void) |
704 | 0 | { |
705 | 0 | mFramePtrs.clear(); |
706 | 0 | mFramePtrs.push_back(TexturePtr()); // insert nullptr to show warning tex |
707 | 0 | } |
708 | | //----------------------------------------------------------------------- |
709 | | void TextureUnitState::setTextureTransform(const Matrix4& xform) |
710 | 0 | { |
711 | 0 | mTexModMatrix = xform; |
712 | 0 | mRecalcTexMatrix = false; |
713 | 0 | } |
714 | | //----------------------------------------------------------------------- |
715 | | void TextureUnitState::setTextureScroll(float u, float v) |
716 | 0 | { |
717 | 0 | mUMod = u; |
718 | 0 | mVMod = v; |
719 | 0 | mRecalcTexMatrix = true; |
720 | 0 | } |
721 | | //----------------------------------------------------------------------- |
722 | | void TextureUnitState::setTextureScale(float uScale, float vScale) |
723 | 0 | { |
724 | 0 | mUScale = uScale; |
725 | 0 | mVScale = vScale; |
726 | 0 | mRecalcTexMatrix = true; |
727 | 0 | } |
728 | | //----------------------------------------------------------------------- |
729 | | void TextureUnitState::setTextureRotate(const Radian& angle) |
730 | 0 | { |
731 | 0 | mRotate = angle; |
732 | 0 | mRecalcTexMatrix = true; |
733 | 0 | } |
734 | | //----------------------------------------------------------------------- |
735 | | const Matrix4& TextureUnitState::getTextureTransform() const |
736 | 0 | { |
737 | 0 | if (mRecalcTexMatrix) |
738 | 0 | recalcTextureMatrix(); |
739 | 0 | return mTexModMatrix; |
740 | |
|
741 | 0 | } |
742 | | //----------------------------------------------------------------------- |
743 | | void TextureUnitState::recalcTextureMatrix() const |
744 | 0 | { |
745 | | // Assumption: 2D texture coords |
746 | | // that would make this Affine2(Matrix3), but we lack such a class |
747 | | // Matrix3 is horribly unoptimized ATM |
748 | 0 | Affine3 xform = Affine3::IDENTITY; |
749 | |
|
750 | 0 | if (mUScale != 1 || mVScale != 1) |
751 | 0 | { |
752 | | // Offset to center of texture |
753 | 0 | xform[0][0] = 1/mUScale; |
754 | 0 | xform[1][1] = 1/mVScale; |
755 | | // Skip matrix concat since first matrix update |
756 | 0 | xform[0][3] = (-0.5f * xform[0][0]) + 0.5f; |
757 | 0 | xform[1][3] = (-0.5f * xform[1][1]) + 0.5f; |
758 | 0 | } |
759 | |
|
760 | 0 | if (mUMod || mVMod) |
761 | 0 | { |
762 | 0 | xform = Affine3::getTrans(mUMod, mVMod, 0) * xform; |
763 | 0 | } |
764 | |
|
765 | 0 | if (mRotate != Radian(0)) |
766 | 0 | { |
767 | 0 | Affine3 rot = Affine3::IDENTITY; |
768 | 0 | Radian theta ( mRotate ); |
769 | 0 | Real cosTheta = Math::Cos(theta); |
770 | 0 | Real sinTheta = Math::Sin(theta); |
771 | |
|
772 | 0 | rot[0][0] = cosTheta; |
773 | 0 | rot[0][1] = -sinTheta; |
774 | 0 | rot[1][0] = sinTheta; |
775 | 0 | rot[1][1] = cosTheta; |
776 | | // Offset center of rotation to center of texture |
777 | 0 | rot[0][3] = 0.5f + ( (-0.5f * cosTheta) - (-0.5f * sinTheta) ); |
778 | 0 | rot[1][3] = 0.5f + ( (-0.5f * sinTheta) + (-0.5f * cosTheta) ); |
779 | |
|
780 | 0 | xform = rot * xform; |
781 | 0 | } |
782 | |
|
783 | 0 | mTexModMatrix = xform; |
784 | 0 | mRecalcTexMatrix = false; |
785 | |
|
786 | 0 | } |
787 | | //----------------------------------------------------------------------- |
788 | | void TextureUnitState::setTextureUScroll(float value) |
789 | 0 | { |
790 | 0 | mUMod = value; |
791 | 0 | mRecalcTexMatrix = true; |
792 | 0 | } |
793 | | //----------------------------------------------------------------------- |
794 | | void TextureUnitState::setTextureVScroll(float value) |
795 | 0 | { |
796 | 0 | mVMod = value; |
797 | 0 | mRecalcTexMatrix = true; |
798 | 0 | } |
799 | | //----------------------------------------------------------------------- |
800 | | void TextureUnitState::setTextureUScale(float value) |
801 | 0 | { |
802 | 0 | mUScale = value; |
803 | 0 | mRecalcTexMatrix = true; |
804 | 0 | } |
805 | | //----------------------------------------------------------------------- |
806 | | void TextureUnitState::setTextureVScale(float value) |
807 | 0 | { |
808 | 0 | mVScale = value; |
809 | 0 | mRecalcTexMatrix = true; |
810 | 0 | } |
811 | | //----------------------------------------------------------------------- |
812 | | void TextureUnitState::setScrollAnimation(float uSpeed, float vSpeed) |
813 | 0 | { |
814 | | // Remove existing effects |
815 | 0 | removeEffect(ET_UVSCROLL); |
816 | 0 | removeEffect(ET_USCROLL); |
817 | 0 | removeEffect(ET_VSCROLL); |
818 | | |
819 | | // don't create an effect if the speeds are both 0 |
820 | 0 | if (uSpeed == 0.0f && vSpeed == 0.0f) |
821 | 0 | { |
822 | 0 | return; |
823 | 0 | } |
824 | | |
825 | | // Create new effect |
826 | 0 | if (uSpeed == vSpeed) |
827 | 0 | { |
828 | 0 | addEffect({ET_UVSCROLL, uSpeed}); |
829 | 0 | } |
830 | 0 | else |
831 | 0 | { |
832 | 0 | if (uSpeed) |
833 | 0 | { |
834 | 0 | addEffect({ET_USCROLL, uSpeed}); |
835 | 0 | } |
836 | 0 | if (vSpeed) |
837 | 0 | { |
838 | 0 | addEffect({ET_VSCROLL, vSpeed}); |
839 | 0 | } |
840 | 0 | } |
841 | 0 | } |
842 | | //----------------------------------------------------------------------- |
843 | | void TextureUnitState::setRotateAnimation(float speed) |
844 | 0 | { |
845 | | // Remove existing effect |
846 | 0 | removeEffect(ET_ROTATE); |
847 | | // don't create an effect if the speed is 0 |
848 | 0 | if(speed == 0.0f) |
849 | 0 | { |
850 | 0 | return; |
851 | 0 | } |
852 | | // Create new effect |
853 | 0 | addEffect({ET_ROTATE, speed}); |
854 | 0 | } |
855 | | //----------------------------------------------------------------------- |
856 | | void TextureUnitState::setTransformAnimation(TextureTransformType ttype, |
857 | | WaveformType waveType, float base, float frequency, float phase, float amplitude) |
858 | 0 | { |
859 | | // Remove existing effect |
860 | | // note, only remove for subtype, not entire ET_TRANSFORM |
861 | | // otherwise we won't be able to combine subtypes |
862 | | // Get range of items matching this effect |
863 | 0 | for (EffectMap::iterator i = mEffects.begin(); i != mEffects.end(); ++i) |
864 | 0 | { |
865 | 0 | if (i->second.type == ET_TRANSFORM && i->second.subtype == ttype) |
866 | 0 | { |
867 | 0 | if (i->second.controller) |
868 | 0 | { |
869 | 0 | ControllerManager::getSingleton().destroyController(i->second.controller); |
870 | 0 | } |
871 | 0 | mEffects.erase(i); |
872 | | |
873 | | // should only be one, so jump out |
874 | 0 | break; |
875 | 0 | } |
876 | 0 | } |
877 | | |
878 | | // don't create an effect if the given values are all 0 |
879 | 0 | if(base == 0.0f && phase == 0.0f && frequency == 0.0f && amplitude == 0.0f) |
880 | 0 | { |
881 | 0 | return; |
882 | 0 | } |
883 | | // Create new effect |
884 | 0 | TextureEffect eff = {ET_TRANSFORM}; |
885 | 0 | eff.subtype = ttype; |
886 | 0 | eff.waveType = waveType; |
887 | 0 | eff.base = base; |
888 | 0 | eff.frequency = frequency; |
889 | 0 | eff.phase = phase; |
890 | 0 | eff.amplitude = amplitude; |
891 | 0 | addEffect(eff); |
892 | 0 | } |
893 | | //----------------------------------------------------------------------- |
894 | | void TextureUnitState::_prepare(void) |
895 | 0 | { |
896 | | // Unload first |
897 | | //_unload(); |
898 | | |
899 | | // Load textures |
900 | 0 | for (unsigned int i = 0; i < mFramePtrs.size(); ++i) |
901 | 0 | { |
902 | 0 | ensurePrepared(i); |
903 | 0 | } |
904 | 0 | } |
905 | | //----------------------------------------------------------------------- |
906 | | void TextureUnitState::_load(void) |
907 | 0 | { |
908 | | |
909 | | // Load textures |
910 | 0 | for (unsigned int i = 0; i < mFramePtrs.size(); ++i) |
911 | 0 | { |
912 | 0 | ensureLoaded(i); |
913 | 0 | } |
914 | | // Animation controller |
915 | 0 | if (mAnimDuration != 0) |
916 | 0 | { |
917 | 0 | createAnimController(); |
918 | 0 | } |
919 | | // Effect controllers |
920 | 0 | for (auto & e : mEffects) |
921 | 0 | { |
922 | 0 | createEffectController(e.second); |
923 | 0 | } |
924 | |
|
925 | 0 | } |
926 | | //----------------------------------------------------------------------- |
927 | | const TexturePtr& TextureUnitState::_getTexturePtr(void) const |
928 | 0 | { |
929 | 0 | return _getTexturePtr(mCurrentFrame); |
930 | 0 | } |
931 | | //----------------------------------------------------------------------- |
932 | | const TexturePtr& TextureUnitState::_getTexturePtr(size_t frame) const |
933 | 0 | { |
934 | 0 | if (frame < mFramePtrs.size()) |
935 | 0 | { |
936 | 0 | if (mContentType == CONTENT_NAMED) |
937 | 0 | { |
938 | 0 | ensureLoaded(frame); |
939 | 0 | } |
940 | |
|
941 | 0 | return mFramePtrs[frame]; |
942 | 0 | } |
943 | | |
944 | | // Silent fail with empty texture for internal method |
945 | 0 | static TexturePtr nullTexPtr; |
946 | 0 | return nullTexPtr; |
947 | 0 | } |
948 | | //----------------------------------------------------------------------- |
949 | | void TextureUnitState::_setTexturePtr(const TexturePtr& texptr) |
950 | 0 | { |
951 | 0 | _setTexturePtr(texptr, mCurrentFrame); |
952 | 0 | } |
953 | | //----------------------------------------------------------------------- |
954 | | void TextureUnitState::_setTexturePtr(const TexturePtr& texptr, size_t frame) |
955 | 0 | { |
956 | 0 | assert(frame < mFramePtrs.size()); |
957 | 0 | mFramePtrs[frame] = texptr; |
958 | 0 | } |
959 | | //----------------------------------------------------------------------- |
960 | 0 | TexturePtr TextureUnitState::retrieveTexture(const String& name) { |
961 | 0 | TextureManager::ResourceCreateOrRetrieveResult res; |
962 | 0 | res = TextureManager::getSingleton().createOrRetrieve(name, mParent->getResourceGroup()); |
963 | 0 | return static_pointer_cast<Texture>(res.first); |
964 | 0 | } |
965 | | //----------------------------------------------------------------------- |
966 | | bool TextureUnitState::checkTexCalcSettings(const TexturePtr& tex) const |
967 | 0 | { |
968 | 0 | if(mContentType != TextureUnitState::CONTENT_NAMED) |
969 | 0 | return true; // can only check normal textures |
970 | | |
971 | 0 | String err; |
972 | 0 | auto texCalc = _deriveTexCoordCalcMethod(); |
973 | 0 | if ((texCalc == TEXCALC_ENVIRONMENT_MAP_PLANAR || texCalc == TEXCALC_ENVIRONMENT_MAP) && |
974 | 0 | getTextureType() != TEX_TYPE_2D) |
975 | 0 | { |
976 | 0 | err = "env_map setting requires a 2d texture"; |
977 | 0 | } |
978 | 0 | else if ((texCalc == TEXCALC_ENVIRONMENT_MAP_NORMAL || texCalc == TEXCALC_ENVIRONMENT_MAP_REFLECTION) && |
979 | 0 | getTextureType() != TEX_TYPE_CUBE_MAP) |
980 | 0 | { |
981 | 0 | err = "env_map setting requires a cubic texture"; |
982 | 0 | } |
983 | 0 | if(err.empty()) |
984 | 0 | return true; |
985 | | |
986 | 0 | String msg = err+", but '"+tex->getName()+"' is not. Texture layer will be blank"; |
987 | 0 | LogManager::getSingleton().logError(msg); |
988 | 0 | mTextureLoadFailed = true; |
989 | 0 | return false; |
990 | 0 | } |
991 | | void TextureUnitState::ensurePrepared(size_t frame) const |
992 | 0 | { |
993 | 0 | const TexturePtr& tex = mFramePtrs[frame]; |
994 | 0 | if (!tex || mTextureLoadFailed || !checkTexCalcSettings(tex)) |
995 | 0 | return; |
996 | | |
997 | 0 | tex->setGamma(mGamma); |
998 | |
|
999 | 0 | try { |
1000 | 0 | tex->prepare(); |
1001 | 0 | } |
1002 | 0 | catch (Exception& e) |
1003 | 0 | { |
1004 | 0 | String msg = "preparing texture '" + tex->getName() + |
1005 | 0 | "'. Texture layer will be blank: " + e.getDescription(); |
1006 | 0 | LogManager::getSingleton().logError(msg); |
1007 | 0 | mTextureLoadFailed = true; |
1008 | 0 | } |
1009 | 0 | } |
1010 | | //----------------------------------------------------------------------- |
1011 | | void TextureUnitState::ensureLoaded(size_t frame) const |
1012 | 0 | { |
1013 | 0 | const TexturePtr& tex = mFramePtrs[frame]; |
1014 | 0 | if (!tex || mTextureLoadFailed || !checkTexCalcSettings(tex)) |
1015 | 0 | return; |
1016 | | |
1017 | 0 | tex->setGamma(mGamma); |
1018 | |
|
1019 | 0 | if(mUnorderedAccessMipLevel > -1) |
1020 | 0 | tex->setUsage(HBU_GPU_ONLY | TU_UNORDERED_ACCESS); |
1021 | |
|
1022 | 0 | try { |
1023 | 0 | tex->load(); |
1024 | 0 | } |
1025 | 0 | catch (Exception& e) |
1026 | 0 | { |
1027 | 0 | String msg = "loading texture '" + tex->getName() + |
1028 | 0 | "'. Texture layer will be blank: " + e.getDescription(); |
1029 | 0 | LogManager::getSingleton().logError(msg); |
1030 | 0 | mTextureLoadFailed = true; |
1031 | 0 | } |
1032 | 0 | } |
1033 | | //----------------------------------------------------------------------- |
1034 | | void TextureUnitState::createAnimController(void) |
1035 | 0 | { |
1036 | 0 | if (mAnimController) |
1037 | 0 | { |
1038 | 0 | ControllerManager::getSingleton().destroyController(mAnimController); |
1039 | 0 | mAnimController = 0; |
1040 | 0 | } |
1041 | 0 | mAnimController = ControllerManager::getSingleton().createTextureAnimator(this, mAnimDuration); |
1042 | |
|
1043 | 0 | } |
1044 | | //----------------------------------------------------------------------- |
1045 | | void TextureUnitState::createEffectController(TextureEffect& effect) |
1046 | 0 | { |
1047 | 0 | if (effect.controller) |
1048 | 0 | { |
1049 | 0 | ControllerManager::getSingleton().destroyController(effect.controller); |
1050 | 0 | effect.controller = 0; |
1051 | 0 | } |
1052 | 0 | ControllerManager& cMgr = ControllerManager::getSingleton(); |
1053 | 0 | switch (effect.type) |
1054 | 0 | { |
1055 | 0 | case ET_UVSCROLL: |
1056 | 0 | effect.controller = cMgr.createTextureUVScroller(this, effect.arg1); |
1057 | 0 | break; |
1058 | 0 | case ET_USCROLL: |
1059 | 0 | effect.controller = cMgr.createTextureUScroller(this, effect.arg1); |
1060 | 0 | break; |
1061 | 0 | case ET_VSCROLL: |
1062 | 0 | effect.controller = cMgr.createTextureVScroller(this, effect.arg1); |
1063 | 0 | break; |
1064 | 0 | case ET_ROTATE: |
1065 | 0 | effect.controller = cMgr.createTextureRotater(this, effect.arg1); |
1066 | 0 | break; |
1067 | 0 | case ET_TRANSFORM: |
1068 | 0 | effect.controller = cMgr.createTextureWaveTransformer(this, (TextureUnitState::TextureTransformType)effect.subtype, effect.waveType, effect.base, |
1069 | 0 | effect.frequency, effect.phase, effect.amplitude); |
1070 | 0 | break; |
1071 | 0 | case ET_PROJECTIVE_TEXTURE: |
1072 | 0 | case ET_ENVIRONMENT_MAP: |
1073 | 0 | break; |
1074 | 0 | } |
1075 | 0 | } |
1076 | | //----------------------------------------------------------------------- |
1077 | | float TextureUnitState::getTextureUScroll(void) const |
1078 | 0 | { |
1079 | 0 | return mUMod; |
1080 | 0 | } |
1081 | | |
1082 | | //----------------------------------------------------------------------- |
1083 | | float TextureUnitState::getTextureVScroll(void) const |
1084 | 0 | { |
1085 | 0 | return mVMod; |
1086 | 0 | } |
1087 | | |
1088 | | //----------------------------------------------------------------------- |
1089 | | float TextureUnitState::getTextureUScale(void) const |
1090 | 0 | { |
1091 | 0 | return mUScale; |
1092 | 0 | } |
1093 | | |
1094 | | //----------------------------------------------------------------------- |
1095 | | float TextureUnitState::getTextureVScale(void) const |
1096 | 0 | { |
1097 | 0 | return mVScale; |
1098 | 0 | } |
1099 | | |
1100 | | //----------------------------------------------------------------------- |
1101 | | const Radian& TextureUnitState::getTextureRotate(void) const |
1102 | 0 | { |
1103 | 0 | return mRotate; |
1104 | 0 | } |
1105 | | |
1106 | | //----------------------------------------------------------------------- |
1107 | | Real TextureUnitState::getAnimationDuration(void) const |
1108 | 0 | { |
1109 | 0 | return mAnimDuration; |
1110 | 0 | } |
1111 | | |
1112 | | //----------------------------------------------------------------------- |
1113 | | const TextureUnitState::EffectMap& TextureUnitState::getEffects(void) const |
1114 | 0 | { |
1115 | 0 | return mEffects; |
1116 | 0 | } |
1117 | | //----------------------------------------------------------------------- |
1118 | | void TextureUnitState::_unprepare(void) |
1119 | 0 | { |
1120 | | // don't unload textures. may be used elsewhere |
1121 | 0 | } |
1122 | | //----------------------------------------------------------------------- |
1123 | | void TextureUnitState::_unload(void) |
1124 | 0 | { |
1125 | | // Destroy animation controller |
1126 | 0 | if (mAnimController) |
1127 | 0 | { |
1128 | 0 | ControllerManager::getSingleton().destroyController(mAnimController); |
1129 | 0 | mAnimController = 0; |
1130 | 0 | } |
1131 | | |
1132 | | // Destroy effect controllers |
1133 | 0 | for (auto & e : mEffects) |
1134 | 0 | { |
1135 | 0 | if (e.second.controller) |
1136 | 0 | { |
1137 | 0 | ControllerManager::getSingleton().destroyController(e.second.controller); |
1138 | 0 | e.second.controller = 0; |
1139 | 0 | } |
1140 | 0 | } |
1141 | | |
1142 | | // don't unload named textures. may be used elsewhere |
1143 | | // drop references on managed textures, however |
1144 | 0 | if(mContentType != CONTENT_NAMED) |
1145 | 0 | mFramePtrs[0].reset(); |
1146 | 0 | } |
1147 | | //----------------------------------------------------------------------------- |
1148 | | bool TextureUnitState::isLoaded(void) const |
1149 | 0 | { |
1150 | 0 | return mParent->isLoaded(); |
1151 | 0 | } |
1152 | | //----------------------------------------------------------------------- |
1153 | | void TextureUnitState::_notifyNeedsRecompile(void) |
1154 | 0 | { |
1155 | 0 | mParent->_notifyNeedsRecompile(); |
1156 | 0 | } |
1157 | | //----------------------------------------------------------------------- |
1158 | | void TextureUnitState::setProjectiveTexturing(bool enable, |
1159 | | const Frustum* projectionSettings) |
1160 | 0 | { |
1161 | 0 | if (enable) |
1162 | 0 | { |
1163 | 0 | TextureEffect eff = {ET_PROJECTIVE_TEXTURE}; |
1164 | 0 | eff.frustum = projectionSettings; |
1165 | 0 | addEffect(eff); |
1166 | 0 | } |
1167 | 0 | else |
1168 | 0 | { |
1169 | 0 | removeEffect(ET_PROJECTIVE_TEXTURE); |
1170 | 0 | } |
1171 | |
|
1172 | 0 | } |
1173 | | const Frustum* TextureUnitState::getProjectiveTexturingFrustum() const |
1174 | 0 | { |
1175 | 0 | EffectMap::const_iterator i = mEffects.find(ET_PROJECTIVE_TEXTURE); |
1176 | 0 | if (i != mEffects.end()) |
1177 | 0 | { |
1178 | 0 | return i->second.frustum; |
1179 | 0 | } |
1180 | | |
1181 | 0 | return 0; |
1182 | 0 | } |
1183 | | //----------------------------------------------------------------------- |
1184 | | void TextureUnitState::setName(const String& name) |
1185 | 0 | { |
1186 | 0 | mName = name; |
1187 | 0 | } |
1188 | | //----------------------------------------------------------------------------- |
1189 | | void TextureUnitState::_notifyParent(Pass* parent) |
1190 | 0 | { |
1191 | 0 | mParent = parent; |
1192 | 0 | } |
1193 | | //----------------------------------------------------------------------------- |
1194 | | void TextureUnitState::setCompositorReference(const String& compositorName, const String& textureName, uint32 mrtIndex) |
1195 | 0 | { |
1196 | 0 | mCompositorRefName = compositorName; |
1197 | 0 | mCompositorRefTexName = textureName; |
1198 | 0 | mCompositorRefMrtIndex = mrtIndex; |
1199 | 0 | } |
1200 | | //----------------------------------------------------------------------- |
1201 | | size_t TextureUnitState::calculateSize(void) const |
1202 | 0 | { |
1203 | 0 | size_t memSize = sizeof(*this); |
1204 | 0 | memSize += mFramePtrs.size() * sizeof(TexturePtr); |
1205 | 0 | memSize += mEffects.size() * sizeof(TextureEffect); |
1206 | 0 | return memSize; |
1207 | 0 | } |
1208 | | |
1209 | 0 | bool TextureUnitState::isDefaultFiltering() const { |
1210 | 0 | return mSampler == TextureManager::getSingleton().getDefaultSampler(); |
1211 | 0 | } |
1212 | | |
1213 | | const SamplerPtr& TextureUnitState::_getLocalSampler() |
1214 | 0 | { |
1215 | 0 | if(isDefaultFiltering()) |
1216 | 0 | mSampler = TextureManager::getSingleton().createSampler(); |
1217 | |
|
1218 | 0 | return mSampler; |
1219 | 0 | } |
1220 | | |
1221 | | TexCoordCalcMethod TextureUnitState::_deriveTexCoordCalcMethod() const |
1222 | 0 | { |
1223 | 0 | TexCoordCalcMethod texCoordCalcMethod = TEXCALC_NONE; |
1224 | 0 | for (const auto& effi : mEffects) |
1225 | 0 | { |
1226 | 0 | switch (effi.second.type) |
1227 | 0 | { |
1228 | 0 | case ET_ENVIRONMENT_MAP: |
1229 | 0 | texCoordCalcMethod = (TexCoordCalcMethod)effi.second.subtype; |
1230 | 0 | break; |
1231 | 0 | case ET_UVSCROLL: |
1232 | 0 | case ET_USCROLL: |
1233 | 0 | case ET_VSCROLL: |
1234 | 0 | case ET_ROTATE: |
1235 | 0 | case ET_TRANSFORM: |
1236 | 0 | break; |
1237 | 0 | case ET_PROJECTIVE_TEXTURE: |
1238 | 0 | texCoordCalcMethod = TEXCALC_PROJECTIVE_TEXTURE; |
1239 | 0 | break; |
1240 | 0 | } |
1241 | 0 | } |
1242 | | |
1243 | 0 | return texCoordCalcMethod; |
1244 | 0 | } |
1245 | | } |