Browse Source

Added support for zones defining a texture (either cube or 3D), that will be available in pixel shaders when rendering objects inside the zone.

Lasse Öörni 11 years ago
parent
commit
e82b3d53a1

+ 2 - 0
Bin/CoreData/Shaders/GLSL/Samplers.glsl

@@ -18,6 +18,8 @@ uniform samplerCube sLightCubeMap;
     uniform sampler2DShadow sShadowMap;
     uniform sampler2DShadow sShadowMap;
     uniform samplerCube sFaceSelectCubeMap;
     uniform samplerCube sFaceSelectCubeMap;
     uniform samplerCube sIndirectionCubeMap;
     uniform samplerCube sIndirectionCubeMap;
+    uniform samplerCube sZoneCubeMap;
+    uniform sampler3D sZoneVolumeMap;
 #else
 #else
     uniform sampler2D sShadowMap;
     uniform sampler2D sShadowMap;
 #endif
 #endif

+ 2 - 0
Bin/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -17,6 +17,8 @@ samplerCUBE sIndirectionCubeMap : register(S9);
 sampler2D sDepthBuffer : register(S10);
 sampler2D sDepthBuffer : register(S10);
 sampler2D sLightBuffer : register(S11);
 sampler2D sLightBuffer : register(S11);
 sampler3D sVolumeMap : register(S12);
 sampler3D sVolumeMap : register(S12);
+samplerCUBE sZoneCubeMap : register(S13);
+sampler3D sZoneVolumeMap : register(S13);
 
 
 float4 Sample(sampler2D map, float2 texCoord)
 float4 Sample(sampler2D map, float2 texCoord)
 {
 {

+ 18 - 2
Bin/Data/Scripts/Editor/AttributeEditor.as

@@ -898,6 +898,7 @@ void InitResourcePicker()
     resourcePickers.Push(ResourcePicker("Technique", "*.xml"));
     resourcePickers.Push(ResourcePicker("Technique", "*.xml"));
     resourcePickers.Push(ResourcePicker("Texture2D", textureFilters));
     resourcePickers.Push(ResourcePicker("Texture2D", textureFilters));
     resourcePickers.Push(ResourcePicker("TextureCube", "*.xml"));
     resourcePickers.Push(ResourcePicker("TextureCube", "*.xml"));
+    resourcePickers.Push(ResourcePicker("Texture3D", "*.xml"));
     resourcePickers.Push(ResourcePicker("XMLFile", "*.xml"));
     resourcePickers.Push(ResourcePicker("XMLFile", "*.xml"));
     resourcePickers.Push(ResourcePicker("Sprite2D", textureFilters, ACTION_PICK | ACTION_OPEN));
     resourcePickers.Push(ResourcePicker("Sprite2D", textureFilters, ACTION_PICK | ACTION_OPEN));
     resourcePickers.Push(ResourcePicker("AnimationSet2D", anmSetFilters, ACTION_PICK | ACTION_OPEN));
     resourcePickers.Push(ResourcePicker("AnimationSet2D", anmSetFilters, ACTION_PICK | ACTION_OPEN));
@@ -1034,10 +1035,25 @@ void StoreResourcePickerPath()
 Resource@ GetPickedResource(String resourceName)
 Resource@ GetPickedResource(String resourceName)
 {
 {
     resourceName = GetResourceNameFromFullName(resourceName);
     resourceName = GetResourceNameFromFullName(resourceName);
-    Resource@ res = cache.GetResource(resourcePicker.typeName, resourceName);
+    String type = resourcePicker.typeName;
+    // Cube and 3D textures both use .xml extension. In that case interrogate the proper resource type
+    // from the file itself
+    if (type == "Texture3D" || type == "TextureCube")
+    {
+        XMLFile@ xmlRes = cache.GetResource("XMLFile", resourceName);
+        if (xmlRes !is null)
+        {
+            if (xmlRes.root.name.Compare("cubemap", false) == 0 || xmlRes.root.name.Compare("texturecube", false) == 0)
+                type = "TextureCube";
+            else if (xmlRes.root.name.Compare("texture3d", false) == 0)
+                type = "Texture3D";
+        }
+    }
+
+    Resource@ res = cache.GetResource(type, resourceName);
 
 
     if (res is null)
     if (res is null)
-        log.Warning("Cannot find resource type: " + resourcePicker.typeName + " Name:" + resourceName);
+        log.Warning("Cannot find resource type: " + type + " Name:" + resourceName);
 
 
     return res;
     return res;
 }
 }

+ 2 - 1
Docs/Reference.dox

@@ -1341,8 +1341,9 @@ Zones have three special flags: height fog mode, override mode and ambient gradi
 - If the camera is inside a zone with override mode enabled, all rendered objects will use that zone's ambient and fog settings, instead of the zone they belong to. This can be used for example to implement an underwater effect.
 - If the camera is inside a zone with override mode enabled, all rendered objects will use that zone's ambient and fog settings, instead of the zone they belong to. This can be used for example to implement an underwater effect.
 - When ambient gradient mode is enabled, the zone's own ambient color value is not used, but instead it will look for two highest-priority neighbor zones that touch it at the minimum and maximum Z face of its oriented bounding box: any objects inside will then get a per-vertex ambient color fade between the neighbor zones' ambient colors. To ensure objects use the gradient zone when inside it, the gradient zone should have higher priority than the neighbor zones. The gradient is always oriented along the gradient zone's local Z axis.
 - When ambient gradient mode is enabled, the zone's own ambient color value is not used, but instead it will look for two highest-priority neighbor zones that touch it at the minimum and maximum Z face of its oriented bounding box: any objects inside will then get a per-vertex ambient color fade between the neighbor zones' ambient colors. To ensure objects use the gradient zone when inside it, the gradient zone should have higher priority than the neighbor zones. The gradient is always oriented along the gradient zone's local Z axis.
 
 
-Zones also define a lightmask and a shadowmask (with all bits set by default.) An object's final lightmask for light culling is determined by ANDing the object lightmask and the zone lightmask. The final shadowmask is also calculated in the same way.
+Like lights, zones also define a lightmask and a shadowmask (with all bits set by default.) An object's final lightmask for light culling is determined by ANDing the object lightmask and the zone lightmask. The final shadowmask is also calculated in the same way.
 
 
+Finally, zones can optionally define a texture, see \ref Zone::SetZoneTexture "SetZoneTexture()". This should be either a cube or 3D texture that will be bound to the zone texture unit (TU_ZONE) when rendering objects within the zone. This could be used to achieve for example precomputed environment reflections, ambient lighting or ambient occlusion in custom shaders; the default shaders do not use this texture. Due to texture unit limitations it is not available on OpenGL ES 2.0.
 
 
 \page AuxiliaryViews Auxiliary views
 \page AuxiliaryViews Auxiliary views
 
 

+ 4 - 0
Source/Engine/Graphics/Batch.cpp

@@ -588,6 +588,10 @@ void Batch::Prepare(View* view, bool setModelTransform) const
             graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture);
             graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture);
         }
         }
     }
     }
+    
+    // Set zone texture if necessary
+    if (zone_ && graphics->HasTextureUnit(TU_ZONE))
+        graphics->SetTexture(TU_ZONE, zone_->GetZoneTexture());
 }
 }
 
 
 void Batch::Draw(View* view) const
 void Batch::Draw(View* view) const

+ 2 - 0
Source/Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -2766,6 +2766,8 @@ void Graphics::SetTextureUnitMappings()
     textureUnits_["FaceSelectCubeMap"] = TU_FACESELECT;
     textureUnits_["FaceSelectCubeMap"] = TU_FACESELECT;
     textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
     textureUnits_["IndirectionCubeMap"] = TU_INDIRECTION;
     textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
     textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
+    textureUnits_["ZoneCubeMap"] = TU_ZONE;
+    textureUnits_["ZoneVolumeMap"] = TU_ZONE;
 }
 }
 
 
 void RegisterGraphicsLibrary(Context* context)
 void RegisterGraphicsLibrary(Context* context)

+ 2 - 1
Source/Engine/Graphics/GraphicsDefs.h

@@ -230,7 +230,8 @@ enum TextureUnit
     TU_DEPTHBUFFER = 10,
     TU_DEPTHBUFFER = 10,
     TU_LIGHTBUFFER = 11,
     TU_LIGHTBUFFER = 11,
     TU_VOLUMEMAP = 12,
     TU_VOLUMEMAP = 12,
-    MAX_TEXTURE_UNITS = 13
+    TU_ZONE = 13,
+    MAX_TEXTURE_UNITS = 14
 };
 };
 
 
 /// Billboard camera facing modes.
 /// Billboard camera facing modes.

+ 1 - 3
Source/Engine/Graphics/Light.h

@@ -25,14 +25,12 @@
 #include "Color.h"
 #include "Color.h"
 #include "Drawable.h"
 #include "Drawable.h"
 #include "Frustum.h"
 #include "Frustum.h"
+#include "Texture.h"
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
 class Camera;
 class Camera;
-class Texture;
-class Texture2D;
-class TextureCube;
 struct LightBatchQueue;
 struct LightBatchQueue;
 
 
 /// %Light types.
 /// %Light types.

+ 2 - 0
Source/Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -2954,6 +2954,8 @@ void Graphics::SetTextureUnitMappings()
     textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
     textureUnits_["DepthBuffer"] = TU_DEPTHBUFFER;
     textureUnits_["LightBuffer"] = TU_LIGHTBUFFER;
     textureUnits_["LightBuffer"] = TU_LIGHTBUFFER;
     textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
     textureUnits_["VolumeMap"] = TU_VOLUMEMAP;
+    textureUnits_["ZoneCubeMap"] = TU_ZONE;
+    textureUnits_["ZoneVolumeMap"] = TU_ZONE;
 }
 }
 
 
 void RegisterGraphicsLibrary(Context* context)
 void RegisterGraphicsLibrary(Context* context)

+ 20 - 0
Source/Engine/Graphics/Zone.cpp

@@ -25,7 +25,9 @@
 #include "DebugRenderer.h"
 #include "DebugRenderer.h"
 #include "Node.h"
 #include "Node.h"
 #include "Octree.h"
 #include "Octree.h"
+#include "ResourceCache.h"
 #include "Scene.h"
 #include "Scene.h"
+#include "TextureCube.h"
 #include "Zone.h"
 #include "Zone.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
@@ -82,6 +84,7 @@ void Zone::RegisterObject(Context* context)
     ATTRIBUTE(Zone, VAR_BOOL, "Override Mode", override_, false, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_BOOL, "Override Mode", override_, false, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_BOOL, "Ambient Gradient", ambientGradient_, false, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_BOOL, "Ambient Gradient", ambientGradient_, false, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Priority", priority_, 0, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Priority", priority_, 0, AM_DEFAULT);
+    ACCESSOR_ATTRIBUTE(Zone, VAR_RESOURCEREF, "Zone Texture", GetZoneTextureAttr, SetZoneTextureAttr, ResourceRef, ResourceRef(TextureCube::GetTypeStatic()), AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Light Mask", lightMask_, DEFAULT_LIGHTMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Light Mask", lightMask_, DEFAULT_LIGHTMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Shadow Mask", shadowMask_, DEFAULT_SHADOWMASK, AM_DEFAULT);
     ATTRIBUTE(Zone, VAR_INT, "Shadow Mask", shadowMask_, DEFAULT_SHADOWMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Zone, VAR_INT, "Zone Mask", GetZoneMask, SetZoneMask, unsigned, DEFAULT_ZONEMASK, AM_DEFAULT);
     ACCESSOR_ATTRIBUTE(Zone, VAR_INT, "Zone Mask", GetZoneMask, SetZoneMask, unsigned, DEFAULT_ZONEMASK, AM_DEFAULT);
@@ -158,6 +161,12 @@ void Zone::SetPriority(int priority)
     MarkNetworkUpdate();
     MarkNetworkUpdate();
 }
 }
 
 
+void Zone::SetZoneTexture(Texture* texture)
+{
+    zoneTexture_ = texture;
+    MarkNetworkUpdate();
+}
+
 void Zone::SetHeightFog(bool enable)
 void Zone::SetHeightFog(bool enable)
 {
 {
     heightFog_ = enable;
     heightFog_ = enable;
@@ -216,6 +225,17 @@ bool Zone::IsInside(const Vector3& point) const
     return boundingBox_.IsInside(localPoint) != OUTSIDE;
     return boundingBox_.IsInside(localPoint) != OUTSIDE;
 }
 }
 
 
+void Zone::SetZoneTextureAttr(ResourceRef value)
+{
+    ResourceCache* cache = GetSubsystem<ResourceCache>();
+    zoneTexture_ = static_cast<Texture*>(cache->GetResource(value.type_, value.name_));
+}
+
+ResourceRef Zone::GetZoneTextureAttr() const
+{
+    return GetResourceRef(zoneTexture_, TextureCube::GetTypeStatic());
+}
+
 void Zone::OnMarkedDirty(Node* node)
 void Zone::OnMarkedDirty(Node* node)
 {
 {
     // Due to the octree query and weak pointer manipulation, is not safe from worker threads
     // Due to the octree query and weak pointer manipulation, is not safe from worker threads

+ 12 - 1
Source/Engine/Graphics/Zone.h

@@ -24,6 +24,7 @@
 
 
 #include "Color.h"
 #include "Color.h"
 #include "Drawable.h"
 #include "Drawable.h"
+#include "Texture.h"
 
 
 namespace Urho3D
 namespace Urho3D
 {
 {
@@ -64,10 +65,12 @@ public:
     void SetPriority(int priority);
     void SetPriority(int priority);
     /// Set height fog mode.
     /// Set height fog mode.
     void SetHeightFog(bool enable);
     void SetHeightFog(bool enable);
-    /// Set override mode. If camera is inside an override zone, it will also be used for all drawables.
+    /// Set override mode. If camera is inside an override zone, that zone will be used for all rendered objects instead of their own zone.
     void SetOverride(bool enable);
     void SetOverride(bool enable);
     /// Set ambient gradient mode. In gradient mode ambient color is interpolated from neighbor zones.
     /// Set ambient gradient mode. In gradient mode ambient color is interpolated from neighbor zones.
     void SetAmbientGradient(bool enable);
     void SetAmbientGradient(bool enable);
+    /// Set zone texture. This will be bound to the zone texture unit when rendering objects inside the zone. Note that the default shaders do not use it.
+    void SetZoneTexture(Texture* texture);
     
     
     /// Return inverse world transform.
     /// Return inverse world transform.
     const Matrix3x4& GetInverseWorldTransform() const;
     const Matrix3x4& GetInverseWorldTransform() const;
@@ -95,9 +98,15 @@ public:
     bool GetOverride() const { return override_; }
     bool GetOverride() const { return override_; }
     /// Return whether ambient gradient mode is enabled.
     /// Return whether ambient gradient mode is enabled.
     bool GetAmbientGradient() const { return ambientGradient_; }
     bool GetAmbientGradient() const { return ambientGradient_; }
+    /// Return zone texture.
+    Texture* GetZoneTexture() const { return zoneTexture_; }
     
     
     /// Check whether a point is inside.
     /// Check whether a point is inside.
     bool IsInside(const Vector3& point) const;
     bool IsInside(const Vector3& point) const;
+    /// Set zone texture attribute.
+    void SetZoneTextureAttr(ResourceRef value);
+    /// Return zone texture attribute.
+    ResourceRef GetZoneTextureAttr() const;
     
     
 protected:
 protected:
     /// Handle node transform being dirtied.
     /// Handle node transform being dirtied.
@@ -141,6 +150,8 @@ protected:
     float fogHeightScale_;
     float fogHeightScale_;
     /// Zone priority.
     /// Zone priority.
     int priority_;
     int priority_;
+    /// Zone texture.
+    SharedPtr<Texture> zoneTexture_;
     /// Last zone used for ambient gradient start color.
     /// Last zone used for ambient gradient start color.
     WeakPtr<Zone> lastAmbientStartZone_;
     WeakPtr<Zone> lastAmbientStartZone_;
     /// Last zone used for ambient gradient end color.
     /// Last zone used for ambient gradient end color.

+ 2 - 1
Source/Engine/LuaScript/pkgs/Graphics/GraphicsDefs.pkg

@@ -182,7 +182,8 @@ enum TextureUnit
     TU_DEPTHBUFFER = 10,
     TU_DEPTHBUFFER = 10,
     TU_LIGHTBUFFER = 11,
     TU_LIGHTBUFFER = 11,
     TU_VOLUMEMAP = 12,
     TU_VOLUMEMAP = 12,
-    MAX_TEXTURE_UNITS = 13
+    TU_ZONE = 13,
+    MAX_TEXTURE_UNITS = 14
 };
 };
 
 
 enum FaceCameraMode
 enum FaceCameraMode

+ 3 - 0
Source/Engine/LuaScript/pkgs/Graphics/Zone.pkg

@@ -13,6 +13,7 @@ class Zone : public Drawable
     void SetHeightFog(bool enable);
     void SetHeightFog(bool enable);
     void SetOverride(bool enable);
     void SetOverride(bool enable);
     void SetAmbientGradient(bool enable);
     void SetAmbientGradient(bool enable);
+    void SetZoneTexture(Texture* texture);
     
     
     const Matrix3x4& GetInverseWorldTransform() const;
     const Matrix3x4& GetInverseWorldTransform() const;
     const Color& GetAmbientColor() const;
     const Color& GetAmbientColor() const;
@@ -27,6 +28,7 @@ class Zone : public Drawable
     bool GetHeightFog() const;
     bool GetHeightFog() const;
     bool GetOverride() const;
     bool GetOverride() const;
     bool GetAmbientGradient() const;
     bool GetAmbientGradient() const;
+    Texture* GetZoneTexture() const;
     
     
     bool IsInside(const Vector3& point) const;
     bool IsInside(const Vector3& point) const;
     
     
@@ -44,4 +46,5 @@ class Zone : public Drawable
     tolua_property__get_set bool heightFog;
     tolua_property__get_set bool heightFog;
     tolua_property__get_set bool override;
     tolua_property__get_set bool override;
     tolua_property__get_set bool ambientGradient;
     tolua_property__get_set bool ambientGradient;
+    tolua_property__get_set Texture* zoneTexture;
 };
 };

+ 3 - 0
Source/Engine/Script/GraphicsAPI.cpp

@@ -292,6 +292,7 @@ static void RegisterRenderPath(asIScriptEngine* engine)
     engine->RegisterEnumValue("TextureUnit", "TU_DEPTHBUFFER", TU_DEPTHBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_DEPTHBUFFER", TU_DEPTHBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_LIGHTBUFFER", TU_LIGHTBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_LIGHTBUFFER", TU_LIGHTBUFFER);
     engine->RegisterEnumValue("TextureUnit", "TU_VOLUMEMAP", TU_VOLUMEMAP);
     engine->RegisterEnumValue("TextureUnit", "TU_VOLUMEMAP", TU_VOLUMEMAP);
+    engine->RegisterEnumValue("TextureUnit", "TU_ZONE", TU_ZONE);
     engine->RegisterEnumValue("TextureUnit", "MAX_MATERIAL_TEXTURE_UNITS", MAX_MATERIAL_TEXTURE_UNITS);
     engine->RegisterEnumValue("TextureUnit", "MAX_MATERIAL_TEXTURE_UNITS", MAX_MATERIAL_TEXTURE_UNITS);
     engine->RegisterEnumValue("TextureUnit", "MAX_TEXTURE_UNITS", MAX_TEXTURE_UNITS);
     engine->RegisterEnumValue("TextureUnit", "MAX_TEXTURE_UNITS", MAX_TEXTURE_UNITS);
     
     
@@ -851,6 +852,8 @@ static void RegisterZone(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Zone", "bool get_override() const", asMETHOD(Zone, GetOverride), asCALL_THISCALL);
     engine->RegisterObjectMethod("Zone", "bool get_override() const", asMETHOD(Zone, GetOverride), asCALL_THISCALL);
     engine->RegisterObjectMethod("Zone", "void set_ambientGradient(bool)", asMETHOD(Zone, SetAmbientGradient), asCALL_THISCALL);
     engine->RegisterObjectMethod("Zone", "void set_ambientGradient(bool)", asMETHOD(Zone, SetAmbientGradient), asCALL_THISCALL);
     engine->RegisterObjectMethod("Zone", "bool get_ambientGradient() const", asMETHOD(Zone, GetAmbientGradient), asCALL_THISCALL);
     engine->RegisterObjectMethod("Zone", "bool get_ambientGradient() const", asMETHOD(Zone, GetAmbientGradient), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Zone", "void set_zoneTexture(Texture@+)", asMETHOD(Zone, SetZoneTexture), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Zone", "Texture@+ get_zoneTexture() const", asMETHOD(Zone, GetZoneTexture), asCALL_THISCALL);
 }
 }
 
 
 static void RegisterStaticModel(asIScriptEngine* engine)
 static void RegisterStaticModel(asIScriptEngine* engine)