diff --git a/Engine/source/T3D/assets/ImageAsset.cpp b/Engine/source/T3D/assets/ImageAsset.cpp index 2d068123ca..37a49400a8 100644 --- a/Engine/source/T3D/assets/ImageAsset.cpp +++ b/Engine/source/T3D/assets/ImageAsset.cpp @@ -230,6 +230,11 @@ ImageAsset::ImageAsset() : mImageFile(StringTable->EmptyString()), mUseMips(true), mIsHDRImage(false), + mFilterType(GFXTextureFilter_COUNT), + mAddressMode(GFXAddress_COUNT), + mMaxAnisotropy(0), + mUseMipLODBias(false), + mMipLODBias(0.0f), mImageType(Albedo), mIsNamedTarget(false), mImageWidth(-1), @@ -282,6 +287,30 @@ void ImageAsset::initPersistFields() addProtectedField("useMips", TypeBool, Offset(mUseMips, ImageAsset), &setGenMips, &defaultProtectedGetFn, &writeGenMips, "Generate mip maps?"); addProtectedField("isHDRImage", TypeBool, Offset(mIsHDRImage, ImageAsset), &setTextureHDR, &defaultProtectedGetFn, &writeTextureHDR, "HDR Image?"); + addField("filterType", TYPEID< GFXTextureFilterType >(), Offset(mFilterType, ImageAsset), + "Explicit texture filtering override for this image. Leave as the default " + "(or set to GFXTextureFilterNone) to let the material's own filtering/anisotropy " + "settings apply as normal; set to Point, Linear, or Anisotropic to force that " + "filtering mode whenever this image is bound, regardless of the material."); + + addField("addressMode", TYPEID< GFXTextureAddressMode >(), Offset(mAddressMode, ImageAsset), + "Explicit U/V wrap mode override for this image. Leave as the default " + "(or set to GFXAddressWrap) to let the material decide; set to Clamp, " + "Mirror, Border, or MirrorOnce to force that wrap mode whenever this " + "image is bound, regardless of the material."); + + addField("maxAnisotropy", TypeS32, Offset(mMaxAnisotropy, ImageAsset), + "Explicit anisotropy level override (e.g. 2/4/8/16). 0 (default) means " + "let the material decide. Only has an effect when filterType is " + "Anisotropic (or left unset and the material picks Anisotropic itself)."); + + addField("useMipLODBias", TypeBool, Offset(mUseMipLODBias, ImageAsset), + "Whether mipLODBias below should override the material's default of 0."); + + addField("mipLODBias", TypeF32, Offset(mMipLODBias, ImageAsset), + "Explicit mip LOD bias override for this image. Only applied when " + "useMipLODBias is true."); + addField("imageType", TypeImageAssetType, Offset(mImageType, ImageAsset), "What the main use-case for the image is for."); } bool ImageAsset::onAdd() @@ -377,7 +406,7 @@ StringTableEntry ImageAsset::getAssetIdByFilename(StringTableEntry fileName) return imgAsset; } } - + } } } @@ -489,6 +518,10 @@ void ImageAsset::copyTo(SimObject* object) pAsset->setImageFile(getImageFile()); pAsset->setGenMips(getGenMips()); pAsset->setTextureHDR(getTextureHDR()); + pAsset->setFilterType(getFilterType()); + pAsset->setAddressMode(getAddressMode()); + pAsset->setMaxAnisotropy(getMaxAnisotropy()); + pAsset->setMipLODBias(getUseMipLODBias(), getMipLODBias()); } void ImageAsset::setImageFile(StringTableEntry pImageFile) @@ -537,6 +570,36 @@ void ImageAsset::setTextureHDR(const bool pIsHDR) refreshAsset(); } +void ImageAsset::setupSamplerState(GFXSamplerStateDesc* ssd) const +{ + // FIRST (== GFXTextureFilterNone) and COUNT are both treated as "not + // explicitly set" -- leave the sampler desc alone and let the calling class + // fill out. + if (mFilterType != GFXTextureFilter_FIRST && mFilterType != GFXTextureFilter_COUNT) + { + ssd->minFilter = mFilterType; + ssd->magFilter = mFilterType; + ssd->mipFilter = mFilterType; + + if (mFilterType != GFXTextureFilterAnisotropic) + ssd->maxAnisotropy = 1; + } + + // Same "unset" convention for address mode: FIRST (== GFXAddressWrap) + if (mAddressMode != GFXAddress_FIRST && mAddressMode != GFXAddress_COUNT) + { + ssd->addressModeU = mAddressMode; + ssd->addressModeV = mAddressMode; + } + + // 0 is not a valid anisotropy level, so it doubles as "unset". + if (mMaxAnisotropy > 0) + ssd->maxAnisotropy = mMaxAnisotropy; + + if (mUseMipLODBias) + ssd->mipLODBias = mMipLODBias; +} + U32 ImageAsset::load() { if (mLoadedState == Ok) @@ -595,14 +658,14 @@ GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile) if (mLoadedState == Ok) { - //If we don't have an existing map case to the requested format, we'll just create it and insert it in - GFXTexHandle newTex; - newTex.set(mImageFile, requestedProfile, avar("%s %s() - mTextureObject (line %d)", mImageFile, __FUNCTION__, __LINE__)); - if (newTex) - { - mResourceMap.insert(requestedProfile, newTex); - return newTex; - } + //If we don't have an existing map case to the requested format, we'll just create it and insert it in + GFXTexHandle newTex; + newTex.set(mImageFile, requestedProfile, avar("%s %s() - mTextureObject (line %d)", mImageFile, __FUNCTION__, __LINE__)); + if (newTex) + { + mResourceMap.insert(requestedProfile, newTex); + return newTex; + } } if (smNoImageAssetFallbackAssetPtr.notNull() && smNoImageAssetFallbackAssetPtr != this) @@ -792,7 +855,7 @@ void ImageAsset::populateImage(void) } // we only support 2d textures..... for now ;) - mImageDepth = 1; + mImageDepth = 1; } } @@ -1004,9 +1067,28 @@ GuiControl* GuiInspectorTypeImageAssetPtr::constructEditControl() mEditButton->registerObject(); addObject(mEditButton); + // Create inline filter type popup - lets you see/change the resolved + // ImageAsset's own filtering setting + mFilterTypePopup = new GuiPopUpMenuCtrl(); + mFilterTypePopup->registerObject(); + + if (toolDefaultProfile) + mFilterTypePopup->setControlProfile(toolDefaultProfile); + + GuiControlProfile* toolPopupProfile = NULL; + if (Sim::findObject("ToolsGuiPopUpMenuProfile", toolPopupProfile)) + mFilterTypePopup->setControlProfile(toolPopupProfile); + + dSprintf(szBuffer, sizeof(szBuffer), "%d.onFilterTypeSelected();", getId()); + mFilterTypePopup->setField("Command", szBuffer); + + addObject(mFilterTypePopup); + + updateFilterTypePopup(); + // mUseHeightOverride = true; - mHeightOverride = 72; + mHeightOverride = 96; return retCtrl; } @@ -1031,6 +1113,16 @@ bool GuiInspectorTypeImageAssetPtr::updateRects() mEditButton->resize(Point2I(mEdit->getPosition().x + mEdit->getExtent().x, mEdit->getPosition().y), Point2I(rowSize, rowSize)); + // Filter type popup gets its own row directly under the filename field, + // lined up on the same x-offset and spanning the same width mEdit + + // mEditButton together occupy. + if (mFilterTypePopup) + { + Point2I filterPos(editPos, mEdit->getPosition().y + rowSize + 4); + Point2I filterExtent(fieldExtent.x - editPos - 5, rowSize); + mFilterTypePopup->resize(filterPos, filterExtent); + } + mBrowseButton->setHidden(true); return true; @@ -1114,6 +1206,7 @@ void GuiInspectorTypeImageAssetPtr::updateValue() Parent::updateValue(); updatePreviewImage(); + updateFilterTypePopup(); } void GuiInspectorTypeImageAssetPtr::updatePreviewImage() @@ -1178,6 +1271,69 @@ void GuiInspectorTypeImageAssetPtr::setPreviewImage(StringTableEntry assetId) mPreviewImage->_setBitmap(StringTable->insert("ToolsModule:genericAssetIcon_image")); } +AssetPtr GuiInspectorTypeImageAssetPtr::resolveImageAsset() +{ + const char* assetId = getData(); + if (!assetId || !assetId[0] || ImageAsset::isNamedTarget(StringTable->insert(assetId))) + return NULL; // empty field, or a named render target ($backBuffer etc) - no per-asset filter setting + + AssetPtr imageAsset; + U32 assetState = ImageAsset::getAssetById(assetId, &imageAsset); + if (imageAsset.isNull() || assetState == ImageAsset::Failed) + return NULL; + + return imageAsset; +} + +void GuiInspectorTypeImageAssetPtr::updateFilterTypePopup() +{ + if (!mFilterTypePopup) + return; + + mFilterTypePopup->clear(); + mFilterTypePopup->addEntry("Default", GFXTextureFilter_COUNT); + mFilterTypePopup->addEntry("Point", GFXTextureFilterPoint); + mFilterTypePopup->addEntry("Linear", GFXTextureFilterLinear); + mFilterTypePopup->addEntry("Anisotropic", GFXTextureFilterAnisotropic); + + ImageAsset* imageAsset = resolveImageAsset(); + + // No resolvable asset (empty field, named target, bad ID) - hide it + // rather than show a control that can't do anything meaningful. + mFilterTypePopup->setVisible(imageAsset != NULL); + if (!imageAsset) + return; + + GFXTextureFilterType currentType = imageAsset->getFilterType(); + + // FIRST and None share the value 0 -- both mean "not explicitly set", + // so show the same "Default" entry for either. + if (currentType == GFXTextureFilter_FIRST) + currentType = GFXTextureFilter_COUNT; + + mFilterTypePopup->setSelected(currentType, false); // false: don't re-fire onFilterTypeSelected +} + +void GuiInspectorTypeImageAssetPtr::onFilterTypeSelected() +{ + ImageAsset* imageAsset = resolveImageAsset(); + if (!imageAsset || !mFilterTypePopup) + return; + + imageAsset->setFilterType((GFXTextureFilterType)mFilterTypePopup->getSelected()); + + // Updates the live, in-memory instance immediately (so anything + // currently rendering with it picks it up on the next state block + // rebuild) AND writes it back to disk so the change survives a reload. + if (!imageAsset->saveAsset()) + Con::errorf("GuiInspectorTypeImageAssetPtr::onFilterTypeSelected() - failed to save asset '%s'", imageAsset->getAssetId()); +} + +DefineEngineMethod(GuiInspectorTypeImageAssetPtr, onFilterTypeSelected, void, (), , "@internal - fired when the inline filter type popup's selection changes.") +{ + object->onFilterTypeSelected(); +} + void GuiInspectorTypeImageAssetPtr::setCaption(StringTableEntry caption) { mCaption = caption; diff --git a/Engine/source/T3D/assets/ImageAsset.h b/Engine/source/T3D/assets/ImageAsset.h index 500040dd41..5430f112eb 100644 --- a/Engine/source/T3D/assets/ImageAsset.h +++ b/Engine/source/T3D/assets/ImageAsset.h @@ -49,6 +49,9 @@ #ifndef _GFXDEVICE_H_ #include "gfx/gfxDevice.h" #endif +#ifndef _GFXSTATEBLOCK_H_ +#include "gfx/gfxStateBlock.h" +#endif #ifndef _MATTEXTURETARGET_H_ #include "materials/matTextureTarget.h" #endif @@ -139,6 +142,22 @@ class ImageAsset : public AssetBase StringTableEntry mImageFile; bool mUseMips; bool mIsHDRImage; + + /// Explicit filtering override for this image. Defaults to + /// GFXTextureFilter_COUNT (out of range / unset). + GFXTextureFilterType mFilterType; + + /// Explicit U/V wrap mode override for this image. Same "unset" sentinel + /// convention as mFilterType: GFXAddress_FIRST (== GFXAddressWrap) + GFXTextureAddressMode mAddressMode; + + /// Explicit anisotropy level override. + U32 mMaxAnisotropy; + + /// Whether mMipLODBias below should override the material's default of + /// zero. + bool mUseMipLODBias; + F32 mMipLODBias; ImageTypes mImageType; ImageTextureMap mResourceMap; bool mIsNamedTarget; @@ -179,6 +198,22 @@ class ImageAsset : public AssetBase void setTextureHDR(const bool pIsHDR); inline bool getTextureHDR(void) const { return mIsHDRImage; }; + inline void setFilterType(const GFXTextureFilterType pFilterType) { mFilterType = pFilterType; }; + inline GFXTextureFilterType getFilterType(void) const { return mFilterType; }; + + inline void setAddressMode(const GFXTextureAddressMode pAddressMode) { mAddressMode = pAddressMode; }; + inline GFXTextureAddressMode getAddressMode(void) const { return mAddressMode; }; + + inline void setMaxAnisotropy(const U32 pMaxAnisotropy) { mMaxAnisotropy = pMaxAnisotropy; }; + inline U32 getMaxAnisotropy(void) const { return mMaxAnisotropy; }; + + inline void setMipLODBias(const bool pUseBias, const F32 pBias) { mUseMipLODBias = pUseBias; mMipLODBias = pBias; }; + inline bool getUseMipLODBias(void) const { return mUseMipLODBias; }; + inline F32 getMipLODBias(void) const { return mMipLODBias; }; + + /// Populates the sampler state description based on this asset's own settings + void setupSamplerState(GFXSamplerStateDesc* ssd) const; + GFXTexHandle getTexture(GFXTextureProfile* requestedProfile); static StringTableEntry getImageTypeNameFromType(ImageTypes type); diff --git a/Engine/source/T3D/assets/ImageAssetInspectors.h b/Engine/source/T3D/assets/ImageAssetInspectors.h index 3820ebfa0a..6f7b31ece6 100644 --- a/Engine/source/T3D/assets/ImageAssetInspectors.h +++ b/Engine/source/T3D/assets/ImageAssetInspectors.h @@ -6,6 +6,7 @@ #include "gui/editor/guiInspectorTypes.h" #endif #include +#include #ifdef TORQUE_TOOLS class GuiInspectorTypeImageAssetPtr : public GuiInspectorTypeFileName @@ -18,6 +19,13 @@ class GuiInspectorTypeImageAssetPtr : public GuiInspectorTypeFileName GuiBitmapCtrl* mPreviewImage = NULL; GuiBitmapButtonCtrl* mEditButton = NULL; + /// Lets the user see and change the resolved ImageAsset's own filtering + /// setting (GFXTextureFilterType) right from this field, without having + /// to dig into the asset editor. The ImageAsset is the ground truth here + /// -- this writes directly onto the resolved asset instance, not onto + /// whatever object/field this inspector row is otherwise editing. + GuiPopUpMenuCtrl* mFilterTypePopup = NULL; + bool mIsDeleteButtonVisible; DECLARE_CONOBJECT(GuiInspectorTypeImageAssetPtr); @@ -32,6 +40,19 @@ class GuiInspectorTypeImageAssetPtr : public GuiInspectorTypeFileName void updatePreviewImage(); void setPreviewImage(StringTableEntry assetId); + /// Resolves the ImageAsset currently referenced by this field's value + /// (the asset ID string) to a live pointer. Returns NULL if the field + /// is empty, points at a named target, or the asset can't be found. + AssetPtr resolveImageAsset(); + + /// Rebuilds the filter type popup's entries and syncs its current + /// selection from the resolved ImageAsset's getFilterType(). + void updateFilterTypePopup(); + + /// Fired when the popup's selection changes; writes the chosen filter + /// type directly onto the resolved ImageAsset. + void onFilterTypeSelected(); + /// Sets this control's caption text, usually set within setInspectorField, /// this is exposed in case someone wants to override the normal caption. void setCaption(StringTableEntry caption) override; diff --git a/Engine/source/gui/editor/guiInspector.cpp b/Engine/source/gui/editor/guiInspector.cpp index 5596523d4e..653f56336e 100644 --- a/Engine/source/gui/editor/guiInspector.cpp +++ b/Engine/source/gui/editor/guiInspector.cpp @@ -797,6 +797,8 @@ void GuiInspector::updateVisibility() for (GuiInspectorGroup* group : mGroups) { + if (!group) return; + const AbstractClassRep::Field* g = target->findField(group->getGroupName().c_str()); // if group has its own visibility function let it control it. diff --git a/Engine/source/materials/materialDefinition.h b/Engine/source/materials/materialDefinition.h index b932607836..2646347b0f 100644 --- a/Engine/source/materials/materialDefinition.h +++ b/Engine/source/materials/materialDefinition.h @@ -226,60 +226,71 @@ class Material : public BaseMaterialDefinition inline StringTableEntry getNormalMapAssetId(const U32& index) const { return mNormalMapAssetRef[index].assetId; } void setNormalMap(StringTableEntry assetId, const U32& index) { mNormalMapAssetRef[index] = assetId; } GFXTexHandle getNormalMap(const U32& index) { return mNormalMapAssetRef[index].notNull() ? mNormalMapAssetRef[index].assetPtr->getTexture(&GFXNormalMapProfile) : GFXTexHandle(); } + AssetPtr getNormalMapAsset(const U32& index) { return mNormalMapAssetRef[index].assetPtr; } AssetRef mDetailNormalMapAssetRef[MAX_STAGES]; inline StringTableEntry getDetailNormalMapAssetId(const U32& index) const { return mDetailNormalMapAssetRef[index].assetId; } void setDetailNormalMap(StringTableEntry assetId, const U32& index) { mDetailNormalMapAssetRef[index] = assetId; } GFXTexHandle getDetailNormalMap(const U32& index) { return mDetailNormalMapAssetRef[index].notNull() ? mDetailNormalMapAssetRef[index].assetPtr->getTexture(&GFXNormalMapProfile) : GFXTexHandle(); } + AssetPtr getDetailNormalMapAsset(const U32& index) { return mDetailNormalMapAssetRef[index].assetPtr; } AssetRef mOverlayMapAssetRef[MAX_STAGES]; inline StringTableEntry getOverlayMapAssetId(const U32& index) const { return mOverlayMapAssetRef[index].assetId; } void setOverlayMap(StringTableEntry assetId, const U32& index) { mOverlayMapAssetRef[index] = assetId; } GFXTexHandle getOverlayMap(const U32& index) { return mOverlayMapAssetRef[index].notNull() ? mOverlayMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getOverlayMapAsset(const U32& index) { return mOverlayMapAssetRef[index].assetPtr; } AssetRef mLightMapAssetRef[MAX_STAGES]; inline StringTableEntry getLightMapAssetId(const U32& index) const { return mLightMapAssetRef[index].assetId; } void setLightMap(StringTableEntry assetId, const U32& index) { mLightMapAssetRef[index] = assetId; } GFXTexHandle getLightMap(const U32& index) { return mLightMapAssetRef[index].notNull() ? mLightMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getLightMapAsset(const U32& index) { return mLightMapAssetRef[index].assetPtr; } AssetRef mToneMapAssetRef[MAX_STAGES]; inline StringTableEntry getToneMapAssetId(const U32& index) const { return mToneMapAssetRef[index].assetId; } void setToneMap(StringTableEntry assetId, const U32& index) { mToneMapAssetRef[index] = assetId; } GFXTexHandle getToneMap(const U32& index) { return mToneMapAssetRef[index].notNull() ? mToneMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getToneMapAsset(const U32& index) { return mToneMapAssetRef[index].assetPtr; } AssetRef mDetailMapAssetRef[MAX_STAGES]; inline StringTableEntry getDetailMapAssetId(const U32& index) const { return mDetailMapAssetRef[index].assetId; } void setDetailMap(StringTableEntry assetId, const U32& index) { mDetailMapAssetRef[index] = assetId; } GFXTexHandle getDetailMap(const U32& index) { return mDetailMapAssetRef[index].notNull() ? mDetailMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getDetailMapAsset(const U32& index) { return mDetailMapAssetRef[index].assetPtr; } AssetRef mORMConfigMapAssetRef[MAX_STAGES]; inline StringTableEntry getORMConfigMapAssetId(const U32& index) const { return mORMConfigMapAssetRef[index].assetId; } void setORMConfigMap(StringTableEntry assetId, const U32& index) { mORMConfigMapAssetRef[index] = assetId; } GFXTexHandle getORMConfigMap(const U32& index) { return getORMConfigMap(&GFXStaticTextureProfile, index); } GFXTexHandle getORMConfigMap(GFXTextureProfile* requestedProfile, const U32& index) { return mORMConfigMapAssetRef[index].notNull() ? mORMConfigMapAssetRef[index].assetPtr->getTexture(requestedProfile) : GFXTexHandle(); } + AssetPtr getORMConfigMapAsset(const U32& index) { return mORMConfigMapAssetRef[index].assetPtr; } AssetRef mAOMapAssetRef[MAX_STAGES]; inline StringTableEntry getAOMapAssetId(const U32& index) const { return mAOMapAssetRef[index].assetId; } void setAOMap(StringTableEntry assetId, const U32& index) { mAOMapAssetRef[index] = assetId; } GFXTexHandle getAOMap(const U32& index) { return mAOMapAssetRef[index].notNull() ? mAOMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getAOMapAsset(const U32& index) { return mAOMapAssetRef[index].assetPtr; } StringTableEntry getAOMapFile(const U32& index) { return mAOMapAssetRef[index].notNull() ? mAOMapAssetRef[index].assetPtr->getImageFile() : StringTable->EmptyString(); } AssetRef mRoughMapAssetRef[MAX_STAGES]; inline StringTableEntry getRoughMapAssetId(const U32& index) const { return mRoughMapAssetRef[index].assetId; } void setRoughMap(StringTableEntry assetId, const U32& index) { mRoughMapAssetRef[index] = assetId; } GFXTexHandle getRoughMap(const U32& index) { return mRoughMapAssetRef[index].notNull() ? mRoughMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getRoughMapAsset(const U32& index) { return mRoughMapAssetRef[index].assetPtr; } StringTableEntry getRoughMapFile(const U32& index) { return mRoughMapAssetRef[index].notNull() ? mRoughMapAssetRef[index].assetPtr->getImageFile() : StringTable->EmptyString(); } AssetRef mMetalMapAssetRef[MAX_STAGES]; inline StringTableEntry getMetalMapAssetId(const U32& index) const { return mMetalMapAssetRef[index].assetId; } void setMetalMap(StringTableEntry assetId, const U32& index) { mMetalMapAssetRef[index] = assetId; } GFXTexHandle getMetalMap(const U32& index) { return mMetalMapAssetRef[index].notNull() ? mMetalMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getMetalMapAsset(const U32& index) { return mMetalMapAssetRef[index].assetPtr; } StringTableEntry getMetalMapFile(const U32& index) { return mMetalMapAssetRef[index].notNull() ? mMetalMapAssetRef[index].assetPtr->getImageFile() : StringTable->EmptyString(); } AssetRef mGlowMapAssetRef[MAX_STAGES]; inline StringTableEntry getGlowMapAssetId(const U32& index) const { return mGlowMapAssetRef[index].assetId; } void setGlowMap(StringTableEntry assetId, const U32& index) { mGlowMapAssetRef[index] = assetId; } GFXTexHandle getGlowMap(const U32& index) { return mGlowMapAssetRef[index].notNull() ? mGlowMapAssetRef[index].assetPtr->getTexture(&GFXStaticTextureProfile) : GFXTexHandle(); } + AssetPtr getGlowMapAsset(const U32& index) { return mGlowMapAssetRef[index].assetPtr; } bool mDiffuseMapSRGB[MAX_STAGES]; // SRGB diffuse bool mIsSRGb[MAX_STAGES]; // SRGB ORM @@ -421,7 +432,7 @@ class Material : public BaseMaterialDefinition ///@} String mMapTo; // map Material to this texture name - + /// /// Material interface /// diff --git a/Engine/source/materials/processedMaterial.cpp b/Engine/source/materials/processedMaterial.cpp index 6dc807df6b..e6ffbb477b 100644 --- a/Engine/source/materials/processedMaterial.cpp +++ b/Engine/source/materials/processedMaterial.cpp @@ -43,10 +43,10 @@ void RenderPassData::reset() for( U32 i = 0; i < Material::MAX_TEX_PER_PASS; ++ i ) { destructInPlace( &mTexSlot[ i ] ); + constructInPlace( &mTexSlot[i] ); mSamplerNames[ i ].clear(); } - dMemset( &mTexSlot, 0, sizeof(mTexSlot) ); dMemset( &mTexType, 0, sizeof(mTexType) ); mCubeMap = NULL; @@ -275,6 +275,10 @@ void ProcessedMaterial::_initPassStateBlock( RenderPassData *rpd, GFXStateBlockD result.samplers[i].minFilter = GFXTextureFilterLinear; result.samplers[i].magFilter = GFXTextureFilterLinear; } + + if (rpd->mTexSlot[i].texImageAsset) + rpd->mTexSlot[i].texImageAsset->setupSamplerState(&result.samplers[i]); + break; } diff --git a/Engine/source/materials/processedMaterial.h b/Engine/source/materials/processedMaterial.h index e93c3558d7..50f80d27ab 100644 --- a/Engine/source/materials/processedMaterial.h +++ b/Engine/source/materials/processedMaterial.h @@ -69,6 +69,9 @@ struct RenderPassData /// @see mTexType NamedTexTargetRef texTarget; + /// The ImageAsset bound to this slot, if any. + AssetPtr texImageAsset; + } mTexSlot[Material::MAX_TEX_PER_PASS]; U32 mTexType[Material::MAX_TEX_PER_PASS]; diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index b66fa0d5c1..b118c4c79a 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -546,7 +546,40 @@ void ProcessedShaderMaterial::_determineFeatures( U32 stageNum, fd.features.filter( features ); } -bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, U32 stageNum, const FeatureSet &features ) +AssetPtr ProcessedShaderMaterial::_getStageImageAsset(const FeatureType& type, U32 stageNum) +{ + if (!mMaterial) + return NULL; + + if (type == MFT_DiffuseMap) + return mMaterial->getDiffuseMapAsset(stageNum); + if (type == MFT_NormalMap) + return mMaterial->getNormalMapAsset(stageNum); + if (type == MFT_DetailNormalMap) + return mMaterial->getDetailNormalMapAsset(stageNum); + if (type == MFT_OverlayMap) + return mMaterial->getOverlayMapAsset(stageNum); + if (type == MFT_LightMap) + return mMaterial->getLightMapAsset(stageNum); + if (type == MFT_ToneMap) + return mMaterial->getToneMapAsset(stageNum); + if (type == MFT_DetailMap) + return mMaterial->getDetailMapAsset(stageNum); + if (type == MFT_OrmMap) + return mMaterial->getORMConfigMapAsset(stageNum); + /*if (type == MFT_AOMap) + return mMaterial->getAOMapAsset(stageNum); + if (type == MFT_RoughMap) + return mMaterial->getRoughMapAsset(stageNum); + if (type == MFT_MetalMap) + return mMaterial->getMetalMapAsset(stageNum);*/ + if (type == MFT_GlowMap) + return mMaterial->getGlowMapAsset(stageNum); + + return NULL; +} + +bool ProcessedShaderMaterial::_createPasses(MaterialFeatureData& stageFeatures, U32 stageNum, const FeatureSet& features) { // Creates passes for the given stage ShaderRenderPassData passData; @@ -574,11 +607,19 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, passData.mNumTexReg += numTexReg; passData.mFeatureData.features.addFeature( *info.type ); -#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL) U32 oldTexNumber = texIndex; -#endif - info.feature->setTexData( mStages[stageNum], stageFeatures, passData, texIndex ); + info.feature->setTexData(mStages[stageNum], stageFeatures, passData, texIndex); + + if (texIndex != oldTexNumber) + { + AssetPtr stageImageAsset = _getStageImageAsset(*info.type, stageNum); + if (stageImageAsset.notNull()) + { + for (U32 texNum = oldTexNumber; texNum < texIndex; texNum++) + passData.mTexSlot[texNum].texImageAsset = stageImageAsset; + } + } #if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL) if(oldTexNumber != texIndex) @@ -618,7 +659,7 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, } return true; -} +} void ProcessedShaderMaterial::_initMaterialParameters() { diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index 438c879e52..967d6bec28 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -58,16 +58,16 @@ class ShaderConstHandles GFXShaderConstHandle* mAccuCoverageSC; GFXShaderConstHandle* mAccuSpecularSC; GFXShaderConstHandle* mFogDataSC; - GFXShaderConstHandle* mFogColorSC; + GFXShaderConstHandle* mFogColorSC; GFXShaderConstHandle* mDetailScaleSC; GFXShaderConstHandle* mVisiblitySC; GFXShaderConstHandle* mColorMultiplySC; GFXShaderConstHandle* mAlphaTestValueSC; GFXShaderConstHandle* mModelViewProjSC; - GFXShaderConstHandle* mWorldViewOnlySC; + GFXShaderConstHandle* mWorldViewOnlySC; GFXShaderConstHandle* mWorldToCameraSC; GFXShaderConstHandle* mCameraToWorldSC; - GFXShaderConstHandle* mWorldToObjSC; + GFXShaderConstHandle* mWorldToObjSC; GFXShaderConstHandle* mViewToObjSC; GFXShaderConstHandle* mInvCameraTransSC; GFXShaderConstHandle* mCameraToScreenSC; @@ -89,13 +89,13 @@ class ShaderConstHandles GFXShaderConstHandle* mBumpAtlasParamsSC; GFXShaderConstHandle* mDiffuseAtlasTileSC; GFXShaderConstHandle* mBumpAtlasTileSC; - GFXShaderConstHandle *mRTSizeSC; - GFXShaderConstHandle *mOneOverRTSizeSC; + GFXShaderConstHandle* mRTSizeSC; + GFXShaderConstHandle* mOneOverRTSizeSC; GFXShaderConstHandle* mDetailBumpStrength; GFXShaderConstHandle* mViewProjSC; - GFXShaderConstHandle *mImposterUVs; - GFXShaderConstHandle *mImposterLimits; + GFXShaderConstHandle* mImposterUVs; + GFXShaderConstHandle* mImposterLimits; // Deferred Shading : Material Info Flags GFXShaderConstHandle* mMatInfoFlagsSC; @@ -108,13 +108,13 @@ class ShaderConstHandles GFXShaderConstHandle* mIsCapturingSC; struct customHandleData { - StringTableEntry handleName; - GFXShaderConstHandle* handle; + StringTableEntry handleName; + GFXShaderConstHandle* handle; }; Vector mCustomHandles; - void init( GFXShader* shader, CustomMaterial* mat = NULL); - + void init(GFXShader* shader, CustomMaterial* mat = NULL); + }; class ShaderRenderPassData : public RenderPassData @@ -139,7 +139,7 @@ class ProcessedShaderMaterial : public ProcessedMaterial public: ProcessedShaderMaterial(); - ProcessedShaderMaterial(Material &mat); + ProcessedShaderMaterial(Material& mat); ~ProcessedShaderMaterial(); // ProcessedMaterial @@ -152,12 +152,12 @@ class ProcessedShaderMaterial : public ProcessedMaterial void setNodeTransforms(const MatrixF *address, const U32 numTransforms, const U32 pass) override; void setCustomShaderData(Vector &shaderData, const U32 pass) override; void setSceneInfo(SceneRenderState *, const SceneData& sgData, U32 pass) override; - void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer) override; + void setBuffers(GFXVertexBufferHandleBase* vertBuffer, GFXPrimitiveBufferHandle* primBuffer) override; bool stepInstance() override; void dumpMaterialInfo() override; void getMaterialInfo(GuiTreeViewCtrl* tree, U32 item) override; - MaterialParameters* allocMaterialParameters() override; - MaterialParameters* getDefaultMaterialParameters() override { return mDefaultParameters; } + MaterialParameters* allocMaterialParameters() override; + MaterialParameters* getDefaultMaterialParameters() override { return mDefaultParameters; } MaterialParameterHandle* getMaterialParameterHandle(const String& name) override; U32 getNumStages() override; @@ -183,27 +183,27 @@ class ProcessedShaderMaterial : public ProcessedMaterial ~InstancingState() { - delete [] mBuffer; + delete[] mBuffer; } - void setFormat( const GFXVertexFormat *instFormat, const GFXVertexFormat *vertexFormat ) + void setFormat(const GFXVertexFormat* instFormat, const GFXVertexFormat* vertexFormat) { mInstFormat = instFormat; - mDeclFormat.copy( *vertexFormat ); - mDeclFormat.append( *mInstFormat, 1 ); + mDeclFormat.copy(*vertexFormat); + mDeclFormat.append(*mInstFormat, 1); // Let the declaration know we have instancing. mDeclFormat.enableInstancing(); mDeclFormat.getDecl(); - delete [] mBuffer; - mBuffer = new U8[ mInstFormat->getSizeInBytes() * COUNT ]; + delete[] mBuffer; + mBuffer = new U8[mInstFormat->getSizeInBytes() * COUNT]; mCount = -1; } - bool step( U8 **outPtr ) + bool step(U8** outPtr) { // Are we starting a new draw call? - if ( mCount < 0 ) + if (mCount < 0) { *outPtr = mBuffer; mCount = 0; @@ -240,7 +240,7 @@ class ProcessedShaderMaterial : public ProcessedMaterial /// The instancing state if this material /// supports instancing. InstancingState *mInstancingState; - + /// @name Internal functions /// /// @{ @@ -261,7 +261,11 @@ class ProcessedShaderMaterial : public ProcessedMaterial const FeatureSet &features); /// Creates passes for the given stage - virtual bool _createPasses( MaterialFeatureData &fd, U32 stageNum, const FeatureSet &features ); + virtual bool _createPasses(MaterialFeatureData& fd, U32 stageNum, const FeatureSet& features); + + /// Resolves the ImageAsset (if any) that a given texture feature type + /// draws from for the given stage + virtual AssetPtr _getStageImageAsset(const FeatureType& type, U32 stageNum); /// Fills in the MaterialFeatureData for the given stage virtual void _determineFeatures( U32 stageNum,