Browse Source

Texture unit refactoring. On desktop ensure continuous range of 8 material texture units, while mobile has 5. Material can define a volume (3D) texture in the volume unit (desktop only.)

Lasse Öörni 10 years ago
parent
commit
56f64c60b9

+ 6 - 7
Source/Urho3D/Graphics/Batch.cpp

@@ -556,14 +556,11 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
                 graphics->SetShaderParameter(i->first_, i->second_.value_);
         }
         
-        const SharedPtr<Texture>* textures = material_->GetTextures();
-        unsigned numTextures = material_->GetNumUsedTextureUnits();
-
-        for (unsigned i = 0; i < numTextures; ++i)
+        const HashMap<TextureUnit, SharedPtr<Texture> >& textures = material_->GetTextures();
+        for (HashMap<TextureUnit, SharedPtr<Texture> >::ConstIterator i = textures.Begin(); i != textures.End(); ++i)
         {
-            TextureUnit unit = (TextureUnit)i;
-            if (textures[i] && graphics->HasTextureUnit(unit))
-                graphics->SetTexture(i, textures[i]);
+            if (graphics->HasTextureUnit(i->first_))
+                graphics->SetTexture(i->first_, i->second_.Get());
         }
     }
     
@@ -589,8 +586,10 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
     }
     
     // Set zone texture if necessary
+    #ifdef DESKTOP_GRAPHICS
     if (zone_ && graphics->HasTextureUnit(TU_ZONE))
         graphics->SetTexture(TU_ZONE, zone_->GetZoneTexture());
+    #endif
 }
 
 void Batch::Draw(View* view, bool allowDepthWrite) const

+ 18 - 9
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -242,18 +242,27 @@ enum TextureUnit
     TU_SPECULAR = 2,
     TU_EMISSIVE = 3,
     TU_ENVIRONMENT = 4,
-    MAX_MATERIAL_TEXTURE_UNITS = 5,
+#ifdef DESKTOP_GRAPHICS
+    TU_VOLUMEMAP = 5,
+    TU_CUSTOM1 = 6,
+    TU_CUSTOM2 = 7,
+    TU_LIGHTRAMP = 8,
+    TU_LIGHTSHAPE = 9,
+    TU_SHADOWMAP = 10,
+    TU_FACESELECT = 11,
+    TU_INDIRECTION = 12,
+    TU_DEPTHBUFFER = 13,
+    TU_LIGHTBUFFER = 14,
+    TU_ZONE = 15,
+    MAX_MATERIAL_TEXTURE_UNITS = 8,
+    MAX_TEXTURE_UNITS = 16
+#else
     TU_LIGHTRAMP = 5,
     TU_LIGHTSHAPE = 6,
     TU_SHADOWMAP = 7,
-    TU_FACESELECT = 8,
-    TU_INDIRECTION = 9,
-    TU_DEPTHBUFFER = 10,
-    TU_LIGHTBUFFER = 11,
-    TU_VOLUMEMAP = 12,
-    TU_ZONE = 13,
-    MAX_NAMED_TEXTURE_UNITS = 14,
-    MAX_TEXTURE_UNITS = 16
+    MAX_MATERIAL_TEXTURE_UNITS = 5,
+    MAX_TEXTURE_UNITS = 8
+#endif
 };
 
 /// Billboard camera facing modes.

+ 39 - 21
Source/Urho3D/Graphics/Material.cpp

@@ -35,6 +35,7 @@
 #include "../Core/StringUtils.h"
 #include "../Graphics/Technique.h"
 #include "../Graphics/Texture2D.h"
+#include "../Graphics/Texture3D.h"
 #include "../Graphics/TextureCube.h"
 #include "../Scene/ValueAnimation.h"
 #include "../Resource/XMLFile.h"
@@ -53,6 +54,10 @@ static const char* textureUnitNames[] =
     "specular",
     "emissive",
     "environment",
+#ifdef DESKTOP_GRAPHICS
+    "volume",
+    "custom1",
+    "custom2",
     "lightramp",
     "lightshape",
     "shadowmap",
@@ -60,9 +65,14 @@ static const char* textureUnitNames[] =
     "indirection",
     "depth",
     "light",
-    "volume",
     "zone",
     0
+#else
+    "lightramp",
+    "lightshape",
+    "shadowmap",
+    0
+#endif
 };
 
 static const char* cullModeNames[] =
@@ -153,7 +163,6 @@ void ShaderParameterAnimationInfo::ApplyValue(const Variant& newValue)
 Material::Material(Context* context) :
     Resource(context),
     auxViewFrameNumber_(0),
-    numUsedTextureUnits_(0),
     shaderParameterHash_(0),
     occlusion_(true),
     specular_(false),
@@ -202,7 +211,17 @@ bool Material::BeginLoad(Deserializer& source)
                 // Detect cube maps by file extension: they are defined by an XML file
                 /// \todo Differentiate with 3D textures by actually reading the XML content
                 if (GetExtension(name) == ".xml")
-                    cache->BackgroundLoadResource<TextureCube>(name, true, this);
+                {
+                    #ifdef DESKTOP_GRAPHICS
+                    TextureUnit unit = TU_DIFFUSE;
+                    if (textureElem.HasAttribute("unit"))
+                        unit = ParseTextureUnitName(textureElem.GetAttribute("unit"));
+                    if (unit == TU_VOLUMEMAP)
+                        cache->BackgroundLoadResource<Texture3D>(name, true, this);
+                    else
+                    #endif
+                        cache->BackgroundLoadResource<TextureCube>(name, true, this);
+                }
                 else
                     cache->BackgroundLoadResource<Texture2D>(name, true, this);
                 textureElem = textureElem.GetNext("texture");
@@ -294,7 +313,14 @@ bool Material::Load(const XMLElement& source)
             // Detect cube maps by file extension: they are defined by an XML file
             /// \todo Differentiate with 3D textures by actually reading the XML content
             if (GetExtension(name) == ".xml")
-                SetTexture(unit, cache->GetResource<TextureCube>(name));
+            {
+                #ifdef DESKTOP_GRAPHICS
+                if (unit == TU_VOLUMEMAP)
+                    SetTexture(unit, cache->GetResource<Texture3D>(name));
+                else
+                #endif
+                    SetTexture(unit, cache->GetResource<TextureCube>(name));
+            }
             else
                 SetTexture(unit, cache->GetResource<Texture2D>(name));
         }
@@ -385,7 +411,7 @@ bool Material::Save(XMLElement& dest) const
         if (texture)
         {
             XMLElement textureElem = dest.CreateChild("texture");
-            textureElem.SetString("unit", j < MAX_NAMED_TEXTURE_UNITS ? textureUnitNames[j] : String(j).CString());
+            textureElem.SetString("unit", textureUnitNames[j]);
             textureElem.SetString("name", texture->GetName());
         }
     }
@@ -526,16 +552,10 @@ void Material::SetTexture(TextureUnit unit, Texture* texture)
 {
     if (unit < MAX_TEXTURE_UNITS)
     {
-        textures_[unit] = texture;
-
-        // Update the number of used texture units
-        if (texture && (unsigned)unit >= numUsedTextureUnits_)
-            numUsedTextureUnits_ = unit + 1;
-        else if (!texture && unit == numUsedTextureUnits_ - 1)
-        {
-            while (numUsedTextureUnits_ && !textures_[numUsedTextureUnits_ - 1])
-                --numUsedTextureUnits_;
-        }
+        if (texture)
+            textures_[unit] = texture;
+        else
+            textures_.Erase(unit);
     }
 }
 
@@ -626,13 +646,11 @@ SharedPtr<Material> Material::Clone(const String& cloneName) const
     ret->SetName(cloneName);
     ret->techniques_ = techniques_;
     ret->shaderParameters_ = shaderParameters_;
-    for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
-        ret->textures_[i] = textures_[i];
+    ret->textures_ = textures_;
     ret->occlusion_ = occlusion_;
     ret->specular_ = specular_;
     ret->cullMode_ = cullMode_;
     ret->shadowCullMode_ = shadowCullMode_;
-    ret->numUsedTextureUnits_ = numUsedTextureUnits_;
     ret->RefreshMemoryUse();
 
     return ret;
@@ -666,7 +684,8 @@ Pass* Material::GetPass(unsigned index, StringHash passType) const
 
 Texture* Material::GetTexture(TextureUnit unit) const
 {
-    return unit < MAX_TEXTURE_UNITS ? textures_[unit] : (Texture*)0;
+    HashMap<TextureUnit, SharedPtr<Texture> >::ConstIterator i = textures_.Find(unit);
+    return i != textures_.End() ? i->second_.Get() : (Texture*)0;
 }
 
 const Variant& Material::GetShaderParameter(const String& name) const
@@ -737,8 +756,7 @@ void Material::ResetToDefaults()
     SetNumTechniques(1);
     SetTechnique(0, GetSubsystem<ResourceCache>()->GetResource<Technique>("Techniques/NoTexture.xml"));
 
-    for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
-        textures_[i] = 0;
+    textures_.Clear();
 
     batchedParameterUpdate_ = true;
     shaderParameters_.Clear();

+ 8 - 6
Source/Urho3D/Graphics/Material.h

@@ -90,6 +90,12 @@ private:
     String name_;
 };
 
+/// TextureUnit hash function.
+template<> inline unsigned MakeHash(const TextureUnit& value)
+{
+    return (unsigned)value;
+}
+
 /// Describes how to render 3D geometries.
 class URHO3D_API Material : public Resource
 {
@@ -164,7 +170,7 @@ public:
     /// Return texture by unit.
     Texture* GetTexture(TextureUnit unit) const;
    /// Return all textures.
-    const SharedPtr<Texture>* GetTextures() const { return &textures_[0]; }
+    const HashMap<TextureUnit, SharedPtr<Texture> >& GetTextures() const { return textures_; }
     /// Return shader parameter.
     const Variant& GetShaderParameter(const String& name) const;
     /// Return shader parameter animation.
@@ -189,8 +195,6 @@ public:
     bool GetSpecular() const { return specular_; }
     /// Return the scene associated with the material for shader parameter animation updates.
     Scene* GetScene() const;
-    /// Return the last non-null texture unit + 1. Used as an optimization when applying the material to render state.
-    unsigned GetNumUsedTextureUnits() const { return numUsedTextureUnits_; }
     /// Return shader parameter hash value. Used as an optimization to avoid setting shader parameters unnecessarily.
     unsigned GetShaderParameterHash() const { return shaderParameterHash_; }
 
@@ -218,7 +222,7 @@ private:
     /// Techniques.
     Vector<TechniqueEntry> techniques_;
     /// Textures.
-    SharedPtr<Texture> textures_[MAX_TEXTURE_UNITS];
+    HashMap<TextureUnit, SharedPtr<Texture> > textures_;
     /// %Shader parameters.
     HashMap<StringHash, MaterialShaderParameter> shaderParameters_;
     /// %Shader parameters animation infos.
@@ -231,8 +235,6 @@ private:
     BiasParameters depthBias_;
     /// Last auxiliary view rendered frame number.
     unsigned auxViewFrameNumber_;
-    /// Number of maximum non-null texture unit + 1.
-    unsigned numUsedTextureUnits_;
     /// Shader parameter hash value.
     unsigned shaderParameterHash_;
     /// Render occlusion flag.

+ 5 - 3
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -3032,7 +3032,9 @@ void Graphics::SetTextureUnitMappings()
 {
     textureUnits_["DiffMap"] = TU_DIFFUSE;
     textureUnits_["DiffCubeMap"] = TU_DIFFUSE;
+    textureUnits_["AlbedoBuffer"] = TU_ALBEDOBUFFER;
     textureUnits_["NormalMap"] = TU_NORMAL;
+    textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
     textureUnits_["SpecMap"] = TU_SPECULAR;
     textureUnits_["EmissiveMap"] = TU_EMISSIVE;
     textureUnits_["EnvMap"] = TU_ENVIRONMENT;
@@ -3041,15 +3043,15 @@ void Graphics::SetTextureUnitMappings()
     textureUnits_["LightSpotMap"] = TU_LIGHTSHAPE;
     textureUnits_["LightCubeMap"]  = TU_LIGHTSHAPE;
     textureUnits_["ShadowMap"] = TU_SHADOWMAP;
+    #ifdef DESKTOP_GRAPHICS
+    textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
     textureUnits_["FaceSelectCubeMap"] = TU_FACESELECT;
     textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
-    textureUnits_["AlbedoBuffer"] = TU_ALBEDOBUFFER;
-    textureUnits_["NormalBuffer"] = TU_NORMALBUFFER;
     textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
     textureUnits_["LightBuffer"] = TU_LIGHTBUFFER;
-    textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
     textureUnits_["ZoneCubeMap"] = TU_ZONE;
     textureUnits_["ZoneVolumeMap"] = TU_ZONE;
+    #endif
 }
 
 void RegisterGraphicsLibrary(Context* context)

+ 5 - 4
Source/Urho3D/Graphics/View.cpp

@@ -1725,9 +1725,11 @@ bool View::SetTextures(RenderPathCommand& command)
         if (GetExtension(command.textureNames_[i]) == ".xml")
         {
             // Assume 3D textures are only bound to the volume map unit, otherwise it's a cube texture
+            #ifdef DESKTOP_GRAPHICS
             if (i == TU_VOLUMEMAP)
                 texture = cache->GetResource<Texture3D>(command.textureNames_[i]);
             else
+            #endif
                 texture = cache->GetResource<TextureCube>(command.textureNames_[i]);
         }
         else
@@ -2740,12 +2742,11 @@ Technique* View::GetTechnique(Drawable* drawable, Material* material)
 
 void View::CheckMaterialForAuxView(Material* material)
 {
-    const SharedPtr<Texture>* textures = material->GetTextures();
-    unsigned numTextures = material->GetNumUsedTextureUnits();
+    const HashMap<TextureUnit, SharedPtr<Texture> >& textures = material->GetTextures();
 
-    for (unsigned i = 0; i < numTextures; ++i)
+    for (HashMap<TextureUnit, SharedPtr<Texture> >::ConstIterator i = textures.Begin(); i != textures.End(); ++i)
     {
-        Texture* texture = textures[i];
+        Texture* texture = i->second_.Get();
         if (texture && texture->GetUsage() == TEXTURE_RENDERTARGET)
         {
             // Have to check cube & 2D textures separately

+ 1 - 12
Source/Urho3D/LuaScript/pkgs/Graphics/GraphicsDefs.pkg

@@ -168,6 +168,7 @@ enum ShaderParameterGroup
     MAX_SHADER_PARAMETER_GROUPS
 };
 
+// Texture unit numbering depends on graphics capability (mobile or desktop). Expose only the units we are sure of
 enum TextureUnit
 {
     TU_DIFFUSE = 0,
@@ -177,18 +178,6 @@ enum TextureUnit
     TU_SPECULAR = 2,
     TU_EMISSIVE = 3,
     TU_ENVIRONMENT = 4,
-    MAX_MATERIAL_TEXTURE_UNITS = 5,
-    TU_LIGHTRAMP = 5,
-    TU_LIGHTSHAPE = 6,
-    TU_SHADOWMAP = 7,
-    TU_FACESELECT = 8,
-    TU_INDIRECTION = 9,
-    TU_DEPTHBUFFER = 10,
-    TU_LIGHTBUFFER = 11,
-    TU_VOLUMEMAP = 12,
-    TU_ZONE = 13,
-    MAX_NAMED_TEXTURE_UNITS = 14,
-    MAX_TEXTURE_UNITS = 16
 };
 
 enum FaceCameraMode

+ 0 - 4
Source/Urho3D/LuaScript/pkgs/Graphics/Material.pkg

@@ -45,16 +45,12 @@ class Material : public Resource
     CullMode GetCullMode() const;
     CullMode GetShadowCullMode() const;
     const BiasParameters& GetDepthBias() const;
-    unsigned GetAuxViewFrameNumber() const;
-    unsigned GetNumUsedTextureUnits() const;
     bool GetOcclusion() const;
     bool GetSpecular() const;
     Scene* GetScene() const;
 
     tolua_readonly tolua_property__get_set CullMode cullMode;
     tolua_readonly tolua_property__get_set CullMode shadowCullMode;
-    tolua_readonly tolua_property__get_set unsigned auxViewFrameNumber;
-    tolua_readonly tolua_property__get_set unsigned numUsedTextureUnits;
     tolua_readonly tolua_property__get_set bool occlusion;
     tolua_readonly tolua_property__get_set bool specular;
     tolua_property__get_set Scene* scene;

+ 7 - 5
Source/Urho3D/Script/GraphicsAPI.cpp

@@ -278,23 +278,26 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     
     engine->RegisterEnum("TextureUnit");
     engine->RegisterEnumValue("TextureUnit", "TU_DIFFUSE", TU_DIFFUSE);
+    engine->RegisterEnumValue("TextureUnit", "TU_ALBEDOBUFFER", TU_ALBEDOBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_NORMAL", TU_NORMAL);
+    engine->RegisterEnumValue("TextureUnit", "TU_NORMALBUFFER", TU_NORMALBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_SPECULAR", TU_SPECULAR);
     engine->RegisterEnumValue("TextureUnit", "TU_EMISSIVE", TU_EMISSIVE);
     engine->RegisterEnumValue("TextureUnit", "TU_ENVIRONMENT", TU_ENVIRONMENT);
     engine->RegisterEnumValue("TextureUnit", "TU_LIGHTRAMP", TU_LIGHTRAMP);
     engine->RegisterEnumValue("TextureUnit", "TU_LIGHTSHAPE", TU_LIGHTSHAPE);
     engine->RegisterEnumValue("TextureUnit", "TU_SHADOWMAP", TU_SHADOWMAP);
+    #ifdef DESKTOP_GRAPHICS
+    engine->RegisterEnumValue("TextureUnit", "TU_CUSTOM1", TU_CUSTOM1);
+    engine->RegisterEnumValue("TextureUnit", "TU_CUSTOM2", TU_CUSTOM2);
+    engine->RegisterEnumValue("TextureUnit", "TU_VOLUMEMAP", TU_VOLUMEMAP);
     engine->RegisterEnumValue("TextureUnit", "TU_FACESELECT", TU_FACESELECT);
     engine->RegisterEnumValue("TextureUnit", "TU_INDIRECTION", TU_INDIRECTION);
-    engine->RegisterEnumValue("TextureUnit", "TU_ALBEDOBUFFER", TU_ALBEDOBUFFER);
-    engine->RegisterEnumValue("TextureUnit", "TU_NORMALBUFFER", TU_NORMALBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_DEPTHBUFFER", TU_DEPTHBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_LIGHTBUFFER", TU_LIGHTBUFFER);
-    engine->RegisterEnumValue("TextureUnit", "TU_VOLUMEMAP", TU_VOLUMEMAP);
     engine->RegisterEnumValue("TextureUnit", "TU_ZONE", TU_ZONE);
+    #endif
     engine->RegisterEnumValue("TextureUnit", "MAX_MATERIAL_TEXTURE_UNITS", MAX_MATERIAL_TEXTURE_UNITS);
-    engine->RegisterEnumValue("TextureUnit", "MAX_NAMED_TEXTURE_UNITS", MAX_NAMED_TEXTURE_UNITS);
     engine->RegisterEnumValue("TextureUnit", "MAX_TEXTURE_UNITS", MAX_TEXTURE_UNITS);
     
     engine->RegisterObjectType("RenderTargetInfo", sizeof(RenderTargetInfo), asOBJ_VALUE | asOBJ_APP_CLASS_C);
@@ -688,7 +691,6 @@ static void RegisterMaterial(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Material", "CullMode get_shadowCullMode() const", asMETHOD(Material, GetShadowCullMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "void set_depthBias(const BiasParameters&in)", asMETHOD(Material, SetDepthBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "const BiasParameters& get_depthBias() const", asMETHOD(Material, GetDepthBias), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Material", "uint get_numUsedTextureUnits() const", asMETHOD(Material, GetNumUsedTextureUnits), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "void set_scene(Scene@+)", asMETHOD(Material, SetScene), asCALL_THISCALL);
     engine->RegisterObjectMethod("Material", "Scene@+ get_scene() const", asMETHOD(Material, GetScene), asCALL_THISCALL);
     

+ 11 - 11
bin/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -7,18 +7,18 @@ sampler2D sNormalBuffer : register(S1);
 sampler2D sSpecMap : register(S2);
 sampler2D sEmissiveMap : register(S3);
 sampler2D sEnvMap : register(S4);
+sampler3D sVolumeMap : register(S5);
 samplerCUBE sEnvCubeMap : register(S4);
-sampler1D sLightRampMap : register(S5);
-sampler2D sLightSpotMap : register(S6);
-samplerCUBE sLightCubeMap : register(S6);
-sampler2D sShadowMap : register(S7);
-samplerCUBE sFaceSelectCubeMap : register(S8);
-samplerCUBE sIndirectionCubeMap : register(S9);
-sampler2D sDepthBuffer : register(S10);
-sampler2D sLightBuffer : register(S11);
-sampler3D sVolumeMap : register(S12);
-samplerCUBE sZoneCubeMap : register(S13);
-sampler3D sZoneVolumeMap : register(S13);
+sampler1D sLightRampMap : register(S8);
+sampler2D sLightSpotMap : register(S9);
+samplerCUBE sLightCubeMap : register(S9);
+sampler2D sShadowMap : register(S10);
+samplerCUBE sFaceSelectCubeMap : register(S11);
+samplerCUBE sIndirectionCubeMap : register(S12);
+sampler2D sDepthBuffer : register(S13);
+sampler2D sLightBuffer : register(S14);
+samplerCUBE sZoneCubeMap : register(S15);
+sampler3D sZoneVolumeMap : register(S15);
 
 float4 Sample(sampler2D map, float2 texCoord)
 {