Browse Source

Fixed a logic error where a OpenGL ShaderVariation would hold a link to a single ShaderProgram, although it can be linked to many.
Fixed a possible bug in CollisionShape where the wrong amount of vertex data would be allocated for a triangle mesh.
ShaderVariations no longer hold a weak pointer to the parent shader.
Changed shader variation compile/creation to happen on demand.
Optimized drawing triangle mesh physics debug geometry.
Changed OpenGL ShaderProgram to remember last parameter sources (instead of Graphics remembering them globally) to eliminate redundant uniform assignment after changing shaders.
OpenGL VertexBuffer & IndexBuffer will create a new data store if locking the whole buffer in discard mode.
Removed most ClearParameterSources() calls from view rendering as unnecessary.

Lasse Öörni 14 years ago
parent
commit
1c26218eeb

+ 1 - 1
Engine/Graphics/Batch.cpp

@@ -122,7 +122,7 @@ void Batch::Prepare(Graphics* graphics, const HashMap<ShaderParameter, Vector4>&
     {
     {
         // If we override the view matrix, also disable any projection jittering
         // If we override the view matrix, also disable any projection jittering
         /// \todo This may not be correct in all cases (skybox rendering?)
         /// \todo This may not be correct in all cases (skybox rendering?)
-        if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, &Matrix3x4::IDENTITY))
+        if (graphics->NeedParameterUpdate(VSP_VIEWPROJ, ((unsigned char*)camera_) + 4))
             graphics->SetShaderParameter(VSP_VIEWPROJ, camera_->GetProjection(false));
             graphics->SetShaderParameter(VSP_VIEWPROJ, camera_->GetProjection(false));
     }
     }
     else
     else

+ 47 - 2
Engine/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -907,20 +907,65 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
 {
 {
     if (vs != vertexShader_)
     if (vs != vertexShader_)
     {
     {
+        // Create the shader now if not yet created. If already attempted, do not retry
+        if ((vs) && (!vs->IsCreated()))
+        {
+            if (!vs->IsFailed())
+            {
+                PROFILE(CreateVertexShader);
+                
+                bool success = vs->Create();
+                if (success)
+                    LOGDEBUG("Created vertex shader " + vs->GetName());
+                else
+                {
+                    LOGERROR("Failed to create vertex shader " + vs->GetName());
+                    vs = 0;
+                }
+            }
+            else
+                vs = 0;
+        }
+        
         if ((vs) && (vs->GetShaderType() == VS))
         if ((vs) && (vs->GetShaderType() == VS))
             impl_->device_->SetVertexShader((IDirect3DVertexShader9*)vs->GetGPUObject());
             impl_->device_->SetVertexShader((IDirect3DVertexShader9*)vs->GetGPUObject());
         else
         else
+        {
             impl_->device_->SetVertexShader(0);
             impl_->device_->SetVertexShader(0);
-            
+            vs = 0;
+        }
+        
         vertexShader_ = vs;
         vertexShader_ = vs;
     }
     }
     
     
     if (ps != pixelShader_)
     if (ps != pixelShader_)
     {
     {
+        if ((ps) && (!ps->IsCreated()))
+        {
+            if (!ps->IsFailed())
+            {
+                PROFILE(CreatePixelShader);
+                
+                bool success = ps->Create();
+                if (success)
+                    LOGDEBUG("Created pixel shader " + ps->GetName());
+                else
+                {
+                    LOGERROR("Failed to create pixel shader " + ps->GetName());
+                    ps = 0;
+                }
+            }
+            else
+                ps = 0;
+        }
+        
         if ((ps) && (ps->GetShaderType() == PS))
         if ((ps) && (ps->GetShaderType() == PS))
             impl_->device_->SetPixelShader((IDirect3DPixelShader9*)ps->GetGPUObject());
             impl_->device_->SetPixelShader((IDirect3DPixelShader9*)ps->GetGPUObject());
         else
         else
+        {
             impl_->device_->SetPixelShader(0);
             impl_->device_->SetPixelShader(0);
+            ps = 0;
+        }
         
         
         pixelShader_ = ps;
         pixelShader_ = ps;
     }
     }
@@ -1102,7 +1147,7 @@ bool Graphics::NeedTextureUnit(TextureUnit unit)
     return (pixelShader_) && (pixelShader_->HasTextureUnit(unit));
     return (pixelShader_) && (pixelShader_->HasTextureUnit(unit));
 }
 }
 
 
-void Graphics::ClearLastParameterSources()
+void Graphics::ClearParameterSources()
 {
 {
     for (unsigned i = 0; i < MAX_SHADER_PARAMETERS; ++i)
     for (unsigned i = 0; i < MAX_SHADER_PARAMETERS; ++i)
         lastShaderParameterSources_[i] = (const void*)M_MAX_UNSIGNED;
         lastShaderParameterSources_[i] = (const void*)M_MAX_UNSIGNED;

+ 1 - 1
Engine/Graphics/Direct3D9/D3D9Graphics.h

@@ -127,7 +127,7 @@ public:
     /// Check whether the current pixel shader uses a texture unit
     /// Check whether the current pixel shader uses a texture unit
     bool NeedTextureUnit(TextureUnit unit);
     bool NeedTextureUnit(TextureUnit unit);
     /// Clear remembered shader parameter sources
     /// Clear remembered shader parameter sources
-    void ClearLastParameterSources();
+    void ClearParameterSources();
     /// Clear remembered transform shader parameter sources
     /// Clear remembered transform shader parameter sources
     void ClearTransformSources();
     void ClearTransformSources();
     /// Set texture
     /// Set texture

+ 12 - 21
Engine/Graphics/Direct3D9/D3D9Shader.cpp

@@ -24,6 +24,7 @@
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Context.h"
 #include "Context.h"
 #include "Deserializer.h"
 #include "Deserializer.h"
+#include "FileSystem.h"
 #include "Graphics.h"
 #include "Graphics.h"
 #include "GraphicsImpl.h"
 #include "GraphicsImpl.h"
 #include "Log.h"
 #include "Log.h"
@@ -76,6 +77,7 @@ bool Shader::Load(Deserializer& source)
         return false;
         return false;
     }
     }
     
     
+    String fileName = GetFileName(source.GetName());
     shaderType_ = (ShaderType)source.ReadShort();
     shaderType_ = (ShaderType)source.ReadShort();
     isSM3_ = (source.ReadShort() == 3);
     isSM3_ = (source.ReadShort() == 3);
     
     
@@ -116,7 +118,12 @@ bool Shader::Load(Deserializer& source)
     for (unsigned i = 0; i < numVariations; ++i)
     for (unsigned i = 0; i < numVariations; ++i)
     {
     {
         SharedPtr<ShaderVariation> variation(new ShaderVariation(this, shaderType_, isSM3_));
         SharedPtr<ShaderVariation> variation(new ShaderVariation(this, shaderType_, isSM3_));
-        variation->SetName(source.ReadString());
+        String variationName = source.ReadString();
+        StringHash nameHash(variationName);
+        if (!variationName.Empty())
+            variation->SetName(fileName + "_" + variationName);
+        else
+            variation->SetName(fileName);
         
         
         // Fill the parameter & texture unit use information
         // Fill the parameter & texture unit use information
         for (unsigned j = 0; j < numParameters; ++j)
         for (unsigned j = 0; j < numParameters; ++j)
@@ -149,7 +156,7 @@ bool Shader::Load(Deserializer& source)
         }
         }
         
         
         // Store the variation
         // Store the variation
-        variations_[StringHash(variation->GetName())] = variation;
+        variations_[nameHash] = variation;
     }
     }
     
     
     // This is not exactly accurate, but a reasonable estimate
     // This is not exactly accurate, but a reasonable estimate
@@ -165,24 +172,8 @@ ShaderVariation* Shader::GetVariation(const String& name)
 ShaderVariation* Shader::GetVariation(StringHash nameHash)
 ShaderVariation* Shader::GetVariation(StringHash nameHash)
 {
 {
     Map<StringHash, SharedPtr<ShaderVariation> >::Iterator i = variations_.Find(nameHash);
     Map<StringHash, SharedPtr<ShaderVariation> >::Iterator i = variations_.Find(nameHash);
-    if (i == variations_.End())
+    if (i != variations_.End())
+        return i->second_;
+    else
         return 0;
         return 0;
-    ShaderVariation* variation = i->second_;
-    
-    // Create shader object now if not yet created. If fails, remove the variation
-    if (!variation->GetGPUObject())
-    {
-        LOGDEBUG("Creating variation " + variation->GetName() + " of shader " + GetName());
-        
-        PROFILE(CreateShaderVariation);
-        bool success = variation->Create();
-        if (!success)
-        {
-            LOGERROR("Failed to create variation " + variation->GetName() + " of shader " + GetName());
-            variations_.Erase(i);
-            return 0;
-        }
-    }
-    
-    return variation;
 }
 }

+ 9 - 7
Engine/Graphics/Direct3D9/D3D9ShaderVariation.cpp

@@ -33,9 +33,9 @@
 
 
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type, bool isSM3) :
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type, bool isSM3) :
     GPUObject(shader->GetSubsystem<Graphics>()),
     GPUObject(shader->GetSubsystem<Graphics>()),
-    shader_(shader),
     shaderType_(type),
     shaderType_(type),
-    isSM3_(isSM3)
+    isSM3_(isSM3),
+    failed_(false)
 {
 {
     ClearParameters();
     ClearParameters();
 }
 }
@@ -58,17 +58,17 @@ bool ShaderVariation::Create()
         if ((!device) || (FAILED(device->CreateVertexShader(
         if ((!device) || (FAILED(device->CreateVertexShader(
             (const DWORD*)byteCode_.GetPtr(),
             (const DWORD*)byteCode_.GetPtr(),
             (IDirect3DVertexShader9**)&object_))))
             (IDirect3DVertexShader9**)&object_))))
-            return false;
+            failed_ = true;
     }
     }
     else
     else
     {
     {
         if ((!device) || (FAILED(device->CreatePixelShader(
         if ((!device) || (FAILED(device->CreatePixelShader(
             (const DWORD*)byteCode_.GetPtr(),
             (const DWORD*)byteCode_.GetPtr(),
             (IDirect3DPixelShader9**)&object_))))
             (IDirect3DPixelShader9**)&object_))))
-            return false;
+            failed_ = true;
     }
     }
     
     
-    return true;
+    return !failed_;
 }
 }
 
 
 void ShaderVariation::Release()
 void ShaderVariation::Release()
@@ -95,6 +95,8 @@ void ShaderVariation::Release()
         
         
         object_ = 0;
         object_ = 0;
     }
     }
+    
+    failed_ = false;
 }
 }
 
 
 void ShaderVariation::SetName(const String& name)
 void ShaderVariation::SetName(const String& name)
@@ -129,7 +131,7 @@ void ShaderVariation::ClearParameters()
         useTextureUnit_[i] = false;
         useTextureUnit_[i] = false;
 }
 }
 
 
-Shader* ShaderVariation::GetShader() const
+bool ShaderVariation::IsCreated() const
 {
 {
-    return shader_;
+    return object_ != 0;
 }
 }

+ 10 - 8
Engine/Graphics/Direct3D9/D3D9ShaderVariation.h

@@ -55,12 +55,14 @@ public:
     /// Clear parameter and texture unit use flags
     /// Clear parameter and texture unit use flags
     void ClearParameters();
     void ClearParameters();
     
     
-    /// Return parent shader
-    Shader* GetShader() const;
     /// Return shader type
     /// Return shader type
     ShaderType GetShaderType() const { return shaderType_; }
     ShaderType GetShaderType() const { return shaderType_; }
-    /// Return variation name
+    /// Return full shader name
     const String& GetName() const { return name_; }
     const String& GetName() const { return name_; }
+    /// Return whether created successfully
+    bool IsCreated() const;
+    /// Return whether compile failed
+    bool IsFailed() const { return failed_; }
     /// Return whether requires Shader Model 3
     /// Return whether requires Shader Model 3
     bool IsSM3() const { return isSM3_; }
     bool IsSM3() const { return isSM3_; }
     /// Return whether uses a specific shader parameter
     /// Return whether uses a specific shader parameter
@@ -69,16 +71,16 @@ public:
     bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
     bool HasTextureUnit(TextureUnit unit) const { return useTextureUnit_[unit]; }
     
     
 private:
 private:
-    /// Parent shader
-    WeakPtr<Shader> shader_;
-    /// Shader bytecode
-    SharedArrayPtr<unsigned char> byteCode_;
     /// Shader type
     /// Shader type
     ShaderType shaderType_;
     ShaderType shaderType_;
-    /// Variation name
+    /// Full shader name
     String name_;
     String name_;
+    /// Shader bytecode
+    SharedArrayPtr<unsigned char> byteCode_;
     /// Shader Model 3 flag
     /// Shader Model 3 flag
     bool isSM3_;
     bool isSM3_;
+    /// Compile failed flag
+    bool failed_;
     /// Parameter use flags
     /// Parameter use flags
     bool useParameter_[MAX_SHADER_PARAMETERS];
     bool useParameter_[MAX_SHADER_PARAMETERS];
     /// Texture unit use flags
     /// Texture unit use flags

+ 61 - 23
Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -134,7 +134,8 @@ Graphics::Graphics(Context* context_) :
     immediateVertexCount_(0),
     immediateVertexCount_(0),
     defaultTextureFilterMode_(FILTER_BILINEAR),
     defaultTextureFilterMode_(FILTER_BILINEAR),
     shadowMapFormat_(0),
     shadowMapFormat_(0),
-    hiresShadowMapFormat_(0)
+    hiresShadowMapFormat_(0),
+    shaderParameterFrame_(0)
 {
 {
     ResetCachedState();
     ResetCachedState();
     InitializeShaderParameters();
     InitializeShaderParameters();
@@ -365,7 +366,7 @@ bool Graphics::TakeScreenShot(Image& destImage)
 {
 {
     PROFILE(TakeScreenShot);
     PROFILE(TakeScreenShot);
     
     
-    SetRenderTarget(0, (RenderSurface*)0);
+    ResetRenderTargets();
     destImage.SetSize(width_, height_, 3);
     destImage.SetSize(width_, height_, 3);
     glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
     glReadPixels(0, 0, width_, height_, GL_RGB, GL_UNSIGNED_BYTE, destImage.GetData());
     
     
@@ -733,8 +734,45 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
     if ((vs == vertexShader_) && (ps == pixelShader_))
     if ((vs == vertexShader_) && (ps == pixelShader_))
         return;
         return;
     
     
-    // All vertex attributes must be re-bound after shader change, and uniforms need to be reassigned
-    ClearLastParameterSources();
+    // Compile the shaders now if not yet compiled. If already attempted, do not retry
+    if ((vs) && (!vs->IsCompiled()))
+    {
+        if (vs->GetCompilerOutput().Empty())
+        {
+            PROFILE(CompileVertexShader);
+
+            bool success = vs->Create();
+            if (success)
+                LOGDEBUG("Compiled vertex shader " + vs->GetName());
+            else
+            {
+                LOGERROR("Failed to compile vertex shader " + vs->GetName() + ":\n" + vs->GetCompilerOutput());
+                vs = 0;
+            }
+        }
+        else
+            vs = 0;
+    }
+    
+    if ((ps) && (!ps->IsCompiled()))
+    {
+        if (ps->GetCompilerOutput().Empty())
+        {
+            PROFILE(CompilePixelShader);
+
+            bool success = ps->Create();
+            if (success)
+                LOGDEBUG("Compiled pixel shader " + ps->GetName());
+            else
+            {
+                LOGERROR("Failed to compile pixel shader " + ps->GetName() + ":\n" + ps->GetCompilerOutput());
+                ps = 0;
+            }
+        }
+        else
+            ps = 0;
+    }
+    
     for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
     for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
     {
     {
         vertexBuffers_[i] = 0;
         vertexBuffers_[i] = 0;
@@ -774,19 +812,20 @@ void Graphics::SetShaders(ShaderVariation* vs, ShaderVariation* ps)
         {
         {
             // Link a new combination
             // Link a new combination
             SharedPtr<ShaderProgram> newProgram(new ShaderProgram(this, vs, ps));
             SharedPtr<ShaderProgram> newProgram(new ShaderProgram(this, vs, ps));
-            if (!newProgram->Link())
-            {
-                LOGERROR("Failed to link shader " + vs->GetShader()->GetName() + ":\n" +
-                    newProgram->GetLinkerOutput());
-                glUseProgram(0);
-                shaderProgram_ = 0;
-            }
-            else
+            if (newProgram->Link())
             {
             {
+                LOGDEBUG("Linked vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName());
                 // Note: Link() calls glUseProgram() to set the texture sampler uniforms,
                 // Note: Link() calls glUseProgram() to set the texture sampler uniforms,
                 // so it is not necessary to call it again
                 // so it is not necessary to call it again
                 shaderProgram_ = newProgram;
                 shaderProgram_ = newProgram;
             }
             }
+            else
+            {
+                LOGERROR("Failed to link vertex shader " + vs->GetName() + " and pixel shader " + ps->GetName() + ":\n" +
+                    newProgram->GetLinkerOutput());
+                glUseProgram(0);
+                shaderProgram_ = 0;
+            }
             
             
             shaderPrograms_[combination] = newProgram;
             shaderPrograms_[combination] = newProgram;
         }
         }
@@ -988,11 +1027,8 @@ void Graphics::SetShaderParameter(ShaderParameter param, const Matrix3x4& matrix
 
 
 bool Graphics::NeedParameterUpdate(ShaderParameter param, const void* source)
 bool Graphics::NeedParameterUpdate(ShaderParameter param, const void* source)
 {
 {
-    if ((shaderProgram_) && (shaderProgram_->HasParameter(param)) && (lastShaderParameterSources_[param] != source))
-    {
-        lastShaderParameterSources_[param] = source;
-        return true;
-    }
+    if (shaderProgram_)
+        return shaderProgram_->NeedParameterUpdate(param, source, shaderParameterFrame_);
     
     
     return false;
     return false;
 }
 }
@@ -1005,16 +1041,18 @@ bool Graphics::NeedTextureUnit(TextureUnit unit)
     return false;
     return false;
 }
 }
 
 
-void Graphics::ClearLastParameterSources()
+void Graphics::ClearParameterSources()
 {
 {
-    for (unsigned i = 0; i < MAX_SHADER_PARAMETERS; ++i)
-        lastShaderParameterSources_[i] = (const void*)M_MAX_UNSIGNED;
+    ++shaderParameterFrame_;
 }
 }
 
 
 void Graphics::ClearTransformSources()
 void Graphics::ClearTransformSources()
 {
 {
-    lastShaderParameterSources_[VSP_MODEL] = (const void*)M_MAX_UNSIGNED;
-    lastShaderParameterSources_[VSP_VIEWPROJ] = (const void*)M_MAX_UNSIGNED;
+    if (shaderProgram_)
+    {
+        shaderProgram_->ClearParameterSource(VSP_MODEL);
+        shaderProgram_->ClearParameterSource(VSP_VIEWPROJ);
+    }
 }
 }
 
 
 void Graphics::CleanupShaderPrograms()
 void Graphics::CleanupShaderPrograms()
@@ -1022,7 +1060,7 @@ void Graphics::CleanupShaderPrograms()
     for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
     for (ShaderProgramMap::Iterator i = shaderPrograms_.Begin(); i != shaderPrograms_.End();)
     {
     {
         ShaderProgramMap::Iterator current = i++;
         ShaderProgramMap::Iterator current = i++;
-        if (!current->second_->GetGPUObject())
+        if ((!current->second_->GetVertexShader()->GetGPUObject()) || (!current->second_->GetPixelShader()->GetGPUObject()))
         {
         {
             if (shaderProgram_ == current->second_)
             if (shaderProgram_ == current->second_)
                 shaderProgram_ = 0;
                 shaderProgram_ = 0;

+ 3 - 3
Engine/Graphics/OpenGL/OGLGraphics.h

@@ -127,7 +127,7 @@ public:
     /// Check whether the current pixel shader uses a texture unit
     /// Check whether the current pixel shader uses a texture unit
     bool NeedTextureUnit(TextureUnit unit);
     bool NeedTextureUnit(TextureUnit unit);
     /// Clear remembered shader parameter sources
     /// Clear remembered shader parameter sources
-    void ClearLastParameterSources();
+    void ClearParameterSources();
     /// Clear remembered transform shader parameter sources
     /// Clear remembered transform shader parameter sources
     void ClearTransformSources();
     void ClearTransformSources();
     /// Clean up unused shader programs
     /// Clean up unused shader programs
@@ -462,8 +462,8 @@ private:
     Map<String, ShaderParameter> shaderParameters_;
     Map<String, ShaderParameter> shaderParameters_;
     /// Linked shader programs
     /// Linked shader programs
     ShaderProgramMap shaderPrograms_;
     ShaderProgramMap shaderPrograms_;
-    /// Last shader parameter sources per parameter
-    const void* lastShaderParameterSources_[MAX_SHADER_PARAMETERS];
+    /// Shader parameters global frame number
+    unsigned shaderParameterFrame_;
     /// Textures in use
     /// Textures in use
     Texture* textures_[MAX_TEXTURE_UNITS];
     Texture* textures_[MAX_TEXTURE_UNITS];
     /// OpenGL texture types in use
     /// OpenGL texture types in use

+ 10 - 3
Engine/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -170,6 +170,10 @@ void* IndexBuffer::Lock(unsigned start, unsigned count, LockMode mode)
     if (object_)
     if (object_)
     {
     {
         graphics_->SetIndexBuffer(this);
         graphics_->SetIndexBuffer(this);
+        // If locking the whole buffer in discard mode, create a new data store
+        if ((mode == LOCK_DISCARD) && (count == indexCount_))
+            glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        
         hwData = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, glLockMode);
         hwData = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, glLockMode);
         if (!hwData)
         if (!hwData)
             return 0;
             return 0;
@@ -241,14 +245,17 @@ bool IndexBuffer::GetUsedVertexRange(unsigned start, unsigned count, unsigned& m
 
 
 bool IndexBuffer::Create()
 bool IndexBuffer::Create()
 {
 {
-    Release();
-    
     if (!indexCount_)
     if (!indexCount_)
+    {
+        Release();
         return true;
         return true;
+    }
     
     
     if (graphics_)
     if (graphics_)
     {
     {
-        glGenBuffers(1, &object_);
+        if (!object_)
+            glGenBuffers(1, &object_);
+        
         graphics_->SetIndexBuffer(this);
         graphics_->SetIndexBuffer(this);
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount_ * indexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }

+ 15 - 25
Engine/Graphics/OpenGL/OGLShader.cpp

@@ -24,6 +24,7 @@
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Context.h"
 #include "Context.h"
 #include "Deserializer.h"
 #include "Deserializer.h"
+#include "FileSystem.h"
 #include "Graphics.h"
 #include "Graphics.h"
 #include "GraphicsImpl.h"
 #include "GraphicsImpl.h"
 #include "Log.h"
 #include "Log.h"
@@ -37,7 +38,8 @@ OBJECTTYPESTATIC(Shader);
 
 
 Shader::Shader(Context* context) :
 Shader::Shader(Context* context) :
     Resource(context),
     Resource(context),
-    shaderType_(VS)
+    shaderType_(VS),
+    sourceCodeLength_(0)
 {
 {
 }
 }
 
 
@@ -61,10 +63,11 @@ bool Shader::Load(Deserializer& source)
     if (!graphics)
     if (!graphics)
         return false;
         return false;
     
     
-    unsigned codeLength = source.GetSize();
-    shaderCode_.Resize(codeLength);
-    source.Read(&shaderCode_[0], codeLength);
+    sourceCodeLength_ = source.GetSize();
+    sourceCode_ = new char[sourceCodeLength_];
+    source.Read(&sourceCode_[0], sourceCodeLength_);
     
     
+    String fileName = GetFileName(source.GetName());
     String xmlName = source.GetName() + ".xml";
     String xmlName = source.GetName() + ".xml";
     XMLFile* file = GetSubsystem<ResourceCache>()->GetResource<XMLFile>(xmlName);
     XMLFile* file = GetSubsystem<ResourceCache>()->GetResource<XMLFile>(xmlName);
     if (!file)
     if (!file)
@@ -79,7 +82,11 @@ bool Shader::Load(Deserializer& source)
         String variationName = variationElem.GetString("name");
         String variationName = variationElem.GetString("name");
         StringHash nameHash(variationName);
         StringHash nameHash(variationName);
         SharedPtr<ShaderVariation> newVariation(new ShaderVariation(this, shaderType_));
         SharedPtr<ShaderVariation> newVariation(new ShaderVariation(this, shaderType_));
-        newVariation->SetName(variationName);
+        if (!variationName.Empty())
+            newVariation->SetName(fileName + "_" + variationName);
+        else
+            newVariation->SetName(fileName);
+        newVariation->SetSourceCode(sourceCode_, sourceCodeLength_);
         newVariation->SetDefines(variationElem.GetString("defines").Split(' '));
         newVariation->SetDefines(variationElem.GetString("defines").Split(' '));
         variations_[nameHash] = newVariation;
         variations_[nameHash] = newVariation;
         
         
@@ -97,25 +104,8 @@ ShaderVariation* Shader::GetVariation(const String& name)
 ShaderVariation* Shader::GetVariation(StringHash nameHash)
 ShaderVariation* Shader::GetVariation(StringHash nameHash)
 {
 {
     Map<StringHash, SharedPtr<ShaderVariation> >::Iterator i = variations_.Find(nameHash);
     Map<StringHash, SharedPtr<ShaderVariation> >::Iterator i = variations_.Find(nameHash);
-    if (i == variations_.End())
+    if (i != variations_.End())
+        return i->second_;
+    else
         return 0;
         return 0;
-    ShaderVariation* variation = i->second_;
-    
-    // Create shader object now if not yet created. If fails, remove the variation
-    if (!variation->GetGPUObject())
-    {
-        LOGDEBUG("Creating variation " + variation->GetName() + " of shader " + GetName());
-        
-        PROFILE(CreateShaderVariation);
-        bool success = variation->Create();
-        if (!success)
-        {
-            LOGERROR("Failed to create variation " + variation->GetName() + " of shader " + GetName() + ":\n" +
-                variation->GetCompilerOutput());
-            variations_.Erase(i);
-            return 0;
-        }
-    }
-    
-    return variation;
 }
 }

+ 5 - 4
Engine/Graphics/OpenGL/OGLShader.h

@@ -24,6 +24,7 @@
 #pragma once
 #pragma once
 
 
 #include "Resource.h"
 #include "Resource.h"
+#include "SharedArrayPtr.h"
 
 
 class ShaderVariation;
 class ShaderVariation;
 
 
@@ -54,14 +55,14 @@ public:
     ShaderType GetShaderType() const { return shaderType_; }
     ShaderType GetShaderType() const { return shaderType_; }
     /// Return number of variations
     /// Return number of variations
     unsigned GetNumVariations() const { return variations_.Size(); }
     unsigned GetNumVariations() const { return variations_.Size(); }
-    /// Return shader source code
-    const String& GetShaderCode() const { return shaderCode_; }
     
     
 private:
 private:
     /// Shader type
     /// Shader type
     ShaderType shaderType_;
     ShaderType shaderType_;
-    /// Shader source code
-    String shaderCode_;
+    /// GLSL source code
+    SharedArrayPtr<char> sourceCode_;
+    /// Source code length
+    unsigned sourceCodeLength_;
     /// Shader variations. Will be in an unloaded state until requested
     /// Shader variations. Will be in an unloaded state until requested
     Map<StringHash, SharedPtr<ShaderVariation> > variations_;
     Map<StringHash, SharedPtr<ShaderVariation> > variations_;
 };
 };

+ 33 - 0
Engine/Graphics/OpenGL/OGLShaderProgram.cpp

@@ -35,6 +35,7 @@ ShaderProgram::ShaderProgram(Graphics* graphics, ShaderVariation* vertexShader,
     GPUObject(graphics),
     GPUObject(graphics),
     vertexShader_(vertexShader),
     vertexShader_(vertexShader),
     pixelShader_(pixelShader),
     pixelShader_(pixelShader),
+    lastParameterFrame_(0),
     linked_(false)
     linked_(false)
 {
 {
     for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
     for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
@@ -65,6 +66,7 @@ void ShaderProgram::Release()
         glDeleteProgram(object_);
         glDeleteProgram(object_);
         object_ = 0;
         object_ = 0;
         linked_ = false;
         linked_ = false;
+        linkerOutput_.Clear();
     }
     }
 }
 }
 
 
@@ -173,6 +175,37 @@ bool ShaderProgram::Link()
     return true;
     return true;
 }
 }
 
 
+bool ShaderProgram::NeedParameterUpdate(ShaderParameter param, const void* source, unsigned int frame)
+{
+    // If global parameter frame has changed, clear all remembered sources
+    if (frame != lastParameterFrame_)
+    {
+        lastParameterFrame_ = frame;
+        lastParameterSources_.Clear();
+    }
+    
+    if (uniformInfos_.Find(param) == uniformInfos_.End())
+        return false;
+    
+    HashMap<ShaderParameter, const void*>::Iterator i = lastParameterSources_.Find(param);
+    if (i != lastParameterSources_.End())
+    {
+        if (i->second_ == source)
+            return false;
+        
+        i->second_ = source;
+        return true;
+    }
+    
+    lastParameterSources_[param] = source;
+    return true;
+}
+
+void ShaderProgram::ClearParameterSource(ShaderParameter param)
+{
+    lastParameterSources_.Erase(param);
+}
+
 ShaderVariation* ShaderProgram::GetVertexShader() const
 ShaderVariation* ShaderProgram::GetVertexShader() const
 {
 {
     return vertexShader_;
     return vertexShader_;

+ 9 - 0
Engine/Graphics/OpenGL/OGLShaderProgram.h

@@ -53,6 +53,10 @@ public:
     virtual void Release();
     virtual void Release();
     /// Link the shaders and examine the uniforms and samplers used. Return true if successful
     /// Link the shaders and examine the uniforms and samplers used. Return true if successful
     bool Link();
     bool Link();
+    /// Check whether needs a parameter update
+    bool NeedParameterUpdate(ShaderParameter param, const void* source, unsigned frame);
+    /// Clear a specific remembered parameter source
+    void ClearParameterSource(ShaderParameter param);
     
     
     /// Return the vertex shader
     /// Return the vertex shader
     ShaderVariation* GetVertexShader() const;
     ShaderVariation* GetVertexShader() const;
@@ -78,6 +82,10 @@ private:
     WeakPtr<ShaderVariation> pixelShader_;
     WeakPtr<ShaderVariation> pixelShader_;
     /// Uniform info map
     /// Uniform info map
     HashMap<ShaderParameter, UniformInfo> uniformInfos_;
     HashMap<ShaderParameter, UniformInfo> uniformInfos_;
+    /// Shader parameter last source map
+    HashMap<ShaderParameter, const void*> lastParameterSources_;
+    /// Shader parameters global frame number
+    unsigned lastParameterFrame_;
     /// Texture unit use
     /// Texture unit use
     bool useTextureUnit_[MAX_TEXTURE_UNITS];
     bool useTextureUnit_[MAX_TEXTURE_UNITS];
     /// Vertex attribute bindings
     /// Vertex attribute bindings
@@ -86,4 +94,5 @@ private:
     String linkerOutput_;
     String linkerOutput_;
     /// Linked flag
     /// Linked flag
     bool linked_;
     bool linked_;
+    
 };
 };

+ 12 - 14
Engine/Graphics/OpenGL/OGLShaderVariation.cpp

@@ -34,8 +34,8 @@
 
 
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type) :
 ShaderVariation::ShaderVariation(Shader* shader, ShaderType type) :
     GPUObject(shader->GetSubsystem<Graphics>()),
     GPUObject(shader->GetSubsystem<Graphics>()),
-    shader_(shader),
     shaderType_(type),
     shaderType_(type),
+    sourceCodeLength_(0),
     compiled_(false)
     compiled_(false)
 {
 {
 }
 }
@@ -63,17 +63,12 @@ void ShaderVariation::Release()
                 graphics_->SetShaders(0, 0);
                 graphics_->SetShaders(0, 0);
         }
         }
         
         
-        // Release the linked shader program if exists
-        if (shaderProgram_)
-        {
-            shaderProgram_->Release();
-            shaderProgram_.Reset();
-            graphics_->CleanupShaderPrograms();
-        }
+        graphics_->CleanupShaderPrograms();
         
         
         glDeleteShader(object_);
         glDeleteShader(object_);
         object_ = 0;
         object_ = 0;
         compiled_ = false;
         compiled_ = false;
+        compilerOutput_.Clear();
     }
     }
 }
 }
 
 
@@ -81,7 +76,7 @@ bool ShaderVariation::Create()
 {
 {
     Release();
     Release();
     
     
-    if (!shader_)
+    if ((!sourceCode_) || (!sourceCodeLength_))
         return false;
         return false;
     
     
     object_ = glCreateShader((shaderType_ == VS) ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
     object_ = glCreateShader((shaderType_ == VS) ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
@@ -95,7 +90,9 @@ bool ShaderVariation::Create()
     String shaderCode;
     String shaderCode;
     for (unsigned i = 0; i < defines_.Size(); ++i)
     for (unsigned i = 0; i < defines_.Size(); ++i)
         shaderCode += "#define " + defines_[i] + "\n";
         shaderCode += "#define " + defines_[i] + "\n";
-    shaderCode += shader_->GetShaderCode();
+    if (!defines_.Empty())
+        shaderCode += "\n";
+    shaderCode += String(sourceCode_.GetPtr(), sourceCodeLength_);
     
     
     const char* shaderCStr = shaderCode.CString();
     const char* shaderCStr = shaderCode.CString();
     glShaderSource(object_, 1, &shaderCStr, 0);
     glShaderSource(object_, 1, &shaderCStr, 0);
@@ -121,12 +118,13 @@ void ShaderVariation::SetName(const String& name)
     name_ = name;
     name_ = name;
 }
 }
 
 
-void ShaderVariation::SetDefines(const Vector<String>& defines)
+void ShaderVariation::SetSourceCode(const SharedArrayPtr<char>& code, unsigned length)
 {
 {
-    defines_ = defines;
+    sourceCode_ = code;
+    sourceCodeLength_ = length;
 }
 }
 
 
-Shader* ShaderVariation::GetShader() const
+void ShaderVariation::SetDefines(const Vector<String>& defines)
 {
 {
-    return shader_;
+    defines_ = defines;
 }
 }

+ 9 - 8
Engine/Graphics/OpenGL/OGLShaderVariation.h

@@ -26,6 +26,7 @@
 #include "GPUObject.h"
 #include "GPUObject.h"
 #include "GraphicsDefs.h"
 #include "GraphicsDefs.h"
 #include "RefCounted.h"
 #include "RefCounted.h"
+#include "SharedArrayPtr.h"
 
 
 class Shader;
 class Shader;
 class ShaderProgram;
 class ShaderProgram;
@@ -46,14 +47,14 @@ public:
     
     
     /// Set name
     /// Set name
     void SetName(const String& name);
     void SetName(const String& name);
+    /// Set source code
+    void SetSourceCode(const SharedArrayPtr<char>& code, unsigned length);
     /// Set defines
     /// Set defines
     void SetDefines(const Vector<String>& defines);
     void SetDefines(const Vector<String>& defines);
     
     
-    /// Return parent shader
-    Shader* GetShader() const;
     /// Return shader type
     /// Return shader type
     ShaderType GetShaderType() const { return shaderType_; }
     ShaderType GetShaderType() const { return shaderType_; }
-    /// Return variation name
+    /// Return full shader name
     const String& GetName() const { return name_; }
     const String& GetName() const { return name_; }
     /// Return defines
     /// Return defines
     const Vector<String>& GetDefines() const { return defines_; }
     const Vector<String>& GetDefines() const { return defines_; }
@@ -63,14 +64,14 @@ public:
     const String& GetCompilerOutput() const { return compilerOutput_; }
     const String& GetCompilerOutput() const { return compilerOutput_; }
     
     
 private:
 private:
-    /// Parent shader
-    WeakPtr<Shader> shader_;
-    /// Parent linked shader program
-    WeakPtr<ShaderProgram> shaderProgram_;
     /// Shader type
     /// Shader type
     ShaderType shaderType_;
     ShaderType shaderType_;
-    /// Variation name
+    /// Full shader name
     String name_;
     String name_;
+    /// GLSL source code
+    SharedArrayPtr<char> sourceCode_;
+    /// Source code length
+    unsigned sourceCodeLength_;
     /// Defines to use in compiling
     /// Defines to use in compiling
     Vector<String> defines_;
     Vector<String> defines_;
     /// Shader compile error string
     /// Shader compile error string

+ 10 - 3
Engine/Graphics/OpenGL/OGLVertexBuffer.cpp

@@ -275,6 +275,10 @@ void* VertexBuffer::Lock(unsigned start, unsigned count, LockMode mode)
     if (object_)
     if (object_)
     {
     {
         glBindBuffer(GL_ARRAY_BUFFER, object_);
         glBindBuffer(GL_ARRAY_BUFFER, object_);
+        // If locking the whole buffer in discard mode, create a new data store
+        if ((mode == LOCK_DISCARD) && (count == vertexCount_))
+            glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+        
         hwData = glMapBuffer(GL_ARRAY_BUFFER, glLockMode);
         hwData = glMapBuffer(GL_ARRAY_BUFFER, glLockMode);
         if (!hwData)
         if (!hwData)
             return 0;
             return 0;
@@ -369,14 +373,17 @@ unsigned VertexBuffer::GetVertexSize(unsigned mask)
 
 
 bool VertexBuffer::Create()
 bool VertexBuffer::Create()
 {
 {
-    Release();
-    
     if ((!vertexCount_) || (!elementMask_))
     if ((!vertexCount_) || (!elementMask_))
+    {
+        Release();
         return true;
         return true;
+    }
     
     
     if (graphics_)
     if (graphics_)
     {
     {
-        glGenBuffers(1, &object_);
+        if (!object_)
+            glGenBuffers(1, &object_);
+        
         glBindBuffer(GL_ARRAY_BUFFER, object_);
         glBindBuffer(GL_ARRAY_BUFFER, object_);
         glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
         glBufferData(GL_ARRAY_BUFFER, vertexCount_ * vertexSize_, 0, dynamic_ ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
     }
     }

+ 16 - 18
Engine/Graphics/Renderer.cpp

@@ -971,20 +971,6 @@ void Renderer::SetLightVolumeShaders(Batch& batch)
         psi += DLPS_ORTHO;
         psi += DLPS_ORTHO;
     }
     }
     
     
-    unsigned hwShadows = graphics_->GetHardwareShadowSupport() ? 1 : 0;
-    
-    if (!lightVS_[vsi])
-        lightVS_[vsi] = GetVertexShader("Light_" + deferredLightVSVariations[vsi]);
-    
-    if (!lightPS_[psi])
-    {
-        unsigned variation = psi % DLPS_SPOT;
-        if ((variation == DLPS_SHADOW) || (variation == DLPS_SHADOWSPEC))
-            lightPS_[psi] = GetPixelShader("Light_" + lightPSVariations[psi] + hwVariations[hwShadows]);
-        else
-            lightPS_[psi] = GetPixelShader("Light_" + lightPSVariations[psi]);
-    }
-    
     batch.material_ = 0;
     batch.material_ = 0;
     batch.pass_ = 0;
     batch.pass_ = 0;
     batch.vertexShader_ = lightVS_[vsi];
     batch.vertexShader_ = lightVS_[vsi];
@@ -1010,9 +996,22 @@ void Renderer::LoadShaders()
     RenderMode mode = graphics_->GetRenderMode();
     RenderMode mode = graphics_->GetRenderMode();
     if (mode != RENDER_FORWARD)
     if (mode != RENDER_FORWARD)
     {
     {
-        // There are rather many light volume shader variations, so load them later on-demand
         lightVS_.Resize(MAX_DEFERRED_LIGHT_VS_VARIATIONS);
         lightVS_.Resize(MAX_DEFERRED_LIGHT_VS_VARIATIONS);
         lightPS_.Resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
         lightPS_.Resize(MAX_DEFERRED_LIGHT_PS_VARIATIONS);
+        
+        unsigned hwShadows = graphics_->GetHardwareShadowSupport() ? 1 : 0;
+        
+        for (unsigned i = 0; i < MAX_DEFERRED_LIGHT_VS_VARIATIONS; ++i)
+            lightVS_[i] = GetVertexShader("Light_" + deferredLightVSVariations[i]);
+        
+        for (unsigned i = 0; i < MAX_DEFERRED_LIGHT_PS_VARIATIONS; ++i)
+        {
+            unsigned variation = i % DLPS_SPOT;
+            if ((variation == DLPS_SHADOW) || (variation == DLPS_SHADOWSPEC))
+                lightPS_[i] = GetPixelShader("Light_" + lightPSVariations[i] + hwVariations[hwShadows]);
+            else
+                lightPS_[i] = GetPixelShader("Light_" + lightPSVariations[i]);
+        }
     }
     }
     
     
     // Remove shaders that are no longer referenced from the cache
     // Remove shaders that are no longer referenced from the cache
@@ -1338,7 +1337,6 @@ Node* Renderer::CreateTempNode()
 
 
 void Renderer::SetupLightBatch(Batch& batch)
 void Renderer::SetupLightBatch(Batch& batch)
 {
 {
-    graphics_->ClearTransformSources();
     Matrix3x4 view(batch.camera_->GetInverseWorldTransform());
     Matrix3x4 view(batch.camera_->GetInverseWorldTransform());
     
     
     Light* light = batch.light_;
     Light* light = batch.light_;
@@ -1373,6 +1371,7 @@ void Renderer::SetupLightBatch(Batch& batch)
             graphics_->SetShaders(stencilVS_, stencilPS_);
             graphics_->SetShaders(stencilVS_, stencilPS_);
             graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);
             graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);
             graphics_->SetShaderParameter(VSP_MODEL, nearTransform);
             graphics_->SetShaderParameter(VSP_MODEL, nearTransform);
+            graphics_->ClearTransformSources();
             
             
             // Draw to stencil
             // Draw to stencil
             batch.geometry_->Draw(graphics_);
             batch.geometry_->Draw(graphics_);
@@ -1455,8 +1454,6 @@ void Renderer::SetupLightBatch(Batch& batch)
 
 
 void Renderer::DrawFullScreenQuad(Camera& camera, ShaderVariation* vs, ShaderVariation* ps, bool nearQuad, const HashMap<ShaderParameter, Vector4>& shaderParameters)
 void Renderer::DrawFullScreenQuad(Camera& camera, ShaderVariation* vs, ShaderVariation* ps, bool nearQuad, const HashMap<ShaderParameter, Vector4>& shaderParameters)
 {
 {
-    graphics_->ClearTransformSources();
-    
     Light quadDirLight(context_);
     Light quadDirLight(context_);
     Matrix3x4 model(quadDirLight.GetDirLightTransform(camera, nearQuad));
     Matrix3x4 model(quadDirLight.GetDirLightTransform(camera, nearQuad));
     
     
@@ -1465,6 +1462,7 @@ void Renderer::DrawFullScreenQuad(Camera& camera, ShaderVariation* vs, ShaderVar
     graphics_->SetShaderParameter(VSP_MODEL, model);
     graphics_->SetShaderParameter(VSP_MODEL, model);
     // Get projection without jitter offset to ensure the whole screen is filled
     // Get projection without jitter offset to ensure the whole screen is filled
     graphics_->SetShaderParameter(VSP_VIEWPROJ, camera.GetProjection(false));
     graphics_->SetShaderParameter(VSP_VIEWPROJ, camera.GetProjection(false));
+    graphics_->ClearTransformSources();
     
     
     // Set global shader parameters as needed
     // Set global shader parameters as needed
     for (HashMap<ShaderParameter, Vector4>::ConstIterator i = shaderParameters.Begin(); i != shaderParameters.End(); ++i)
     for (HashMap<ShaderParameter, Vector4>::ConstIterator i = shaderParameters.Begin(); i != shaderParameters.End(); ++i)

+ 15 - 26
Engine/Graphics/View.cpp

@@ -46,11 +46,6 @@
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
-static const String aaVariation[] = {
-    "",
-    "Ortho"
-};
-
 static const Vector3 directions[] =
 static const Vector3 directions[] =
 {
 {
     Vector3::RIGHT,
     Vector3::RIGHT,
@@ -207,6 +202,9 @@ void View::Render()
     if ((!octree_) || (!camera_))
     if ((!octree_) || (!camera_))
         return;
         return;
     
     
+    // Forget parameter sources from the previous view
+    graphics_->ClearParameterSources();
+    
     // If stream offset is supported, write all instance transforms to a single large buffer
     // If stream offset is supported, write all instance transforms to a single large buffer
     // Else we must lock the instance buffer for each batch group
     // Else we must lock the instance buffer for each batch group
     if ((renderer_->GetDynamicInstancing()) && (graphics_->GetStreamOffsetSupport()))
     if ((renderer_->GetDynamicInstancing()) && (graphics_->GetStreamOffsetSupport()))
@@ -725,7 +723,6 @@ void View::RenderBatchesForward()
         // Render opaque objects' base passes
         // Render opaque objects' base passes
         PROFILE(RenderBasePass);
         PROFILE(RenderBasePass);
         
         
-        graphics_->ClearLastParameterSources();
         graphics_->SetColorWrite(true);
         graphics_->SetColorWrite(true);
         graphics_->SetStencilTest(false);
         graphics_->SetStencilTest(false);
         graphics_->SetRenderTarget(0, renderTarget_);
         graphics_->SetRenderTarget(0, renderTarget_);
@@ -748,7 +745,6 @@ void View::RenderBatchesForward()
             if ((renderer_->reuseShadowMaps_) && (queue.light_->GetShadowMap()))
             if ((renderer_->reuseShadowMaps_) && (queue.light_->GetShadowMap()))
                 RenderShadowMap(queue);
                 RenderShadowMap(queue);
             
             
-            graphics_->ClearLastParameterSources();
             graphics_->SetRenderTarget(0, renderTarget_);
             graphics_->SetRenderTarget(0, renderTarget_);
             graphics_->SetDepthStencil(depthStencil_);
             graphics_->SetDepthStencil(depthStencil_);
             graphics_->SetViewport(screenRect_);
             graphics_->SetViewport(screenRect_);
@@ -769,7 +765,6 @@ void View::RenderBatchesForward()
         // Render extra / custom passes
         // Render extra / custom passes
         PROFILE(RenderExtraPass);
         PROFILE(RenderExtraPass);
         
         
-        graphics_->ClearLastParameterSources();
         graphics_->SetRenderTarget(0, renderTarget_);
         graphics_->SetRenderTarget(0, renderTarget_);
         graphics_->SetDepthStencil(depthStencil_);
         graphics_->SetDepthStencil(depthStencil_);
         graphics_->SetViewport(screenRect_);
         graphics_->SetViewport(screenRect_);
@@ -847,8 +842,6 @@ void View::RenderBatchesDeferred()
         // Clear and render the G-buffer
         // Clear and render the G-buffer
         PROFILE(RenderGBuffer);
         PROFILE(RenderGBuffer);
         
         
-        graphics_->ClearLastParameterSources();
-        
         graphics_->SetColorWrite(true);
         graphics_->SetColorWrite(true);
         graphics_->SetScissorTest(false);
         graphics_->SetScissorTest(false);
         graphics_->SetStencilTest(false);
         graphics_->SetStencilTest(false);
@@ -889,7 +882,6 @@ void View::RenderBatchesDeferred()
         PROFILE(RenderAmbientQuad);
         PROFILE(RenderAmbientQuad);
         
         
         // Render ambient color & fog. On OpenGL the depth buffer will be copied now
         // Render ambient color & fog. On OpenGL the depth buffer will be copied now
-        graphics_->ClearLastParameterSources();
         graphics_->SetDepthTest(CMP_ALWAYS);
         graphics_->SetDepthTest(CMP_ALWAYS);
         graphics_->SetRenderTarget(0, renderBuffer);
         graphics_->SetRenderTarget(0, renderBuffer);
         graphics_->ResetRenderTarget(1);
         graphics_->ResetRenderTarget(1);
@@ -899,15 +891,15 @@ void View::RenderBatchesDeferred()
         graphics_->ResetRenderTarget(2);
         graphics_->ResetRenderTarget(2);
         #endif
         #endif
         graphics_->SetDepthStencil(depthStencil_);
         graphics_->SetDepthStencil(depthStencil_);
+        graphics_->SetViewport(screenRect_);
         graphics_->SetTexture(TU_DIFFBUFFER, diffBuffer);
         graphics_->SetTexture(TU_DIFFBUFFER, diffBuffer);
         graphics_->SetTexture(TU_DEPTHBUFFER, depthBuffer);
         graphics_->SetTexture(TU_DEPTHBUFFER, depthBuffer);
-        graphics_->SetViewport(screenRect_);
         
         
         String pixelShaderName = "Ambient";
         String pixelShaderName = "Ambient";
         #ifdef USE_OPENGL
         #ifdef USE_OPENGL
         if (camera_->IsOrthographic())
         if (camera_->IsOrthographic())
             pixelShaderName += "Ortho";
             pixelShaderName += "Ortho";
-        // On OpenGL, set up a stencil operation to reset the stencil during the quad rendering
+        // On OpenGL, set up a stencil operation to reset the stencil during ambient quad rendering
         graphics_->SetStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_KEEP);
         graphics_->SetStencilTest(true, CMP_ALWAYS, OP_ZERO, OP_KEEP, OP_KEEP);
         #endif
         #endif
         
         
@@ -935,8 +927,6 @@ void View::RenderBatchesDeferred()
             // Light volume batches are not sorted as there should be only one of them
             // Light volume batches are not sorted as there should be only one of them
             if (queue.volumeBatches_.Size())
             if (queue.volumeBatches_.Size())
             {
             {
-                graphics_->ClearLastParameterSources();
-                
                 graphics_->SetRenderTarget(0, renderBuffer);
                 graphics_->SetRenderTarget(0, renderBuffer);
                 graphics_->SetDepthStencil(depthStencil_);
                 graphics_->SetDepthStencil(depthStencil_);
                 graphics_->SetViewport(screenRect_);
                 graphics_->SetViewport(screenRect_);
@@ -959,14 +949,12 @@ void View::RenderBatchesDeferred()
         // Non-shadowed lights
         // Non-shadowed lights
         if (noShadowLightQueue_.sortedBatches_.Size())
         if (noShadowLightQueue_.sortedBatches_.Size())
         {
         {
-            graphics_->ClearLastParameterSources();
-            
             graphics_->SetRenderTarget(0, renderBuffer);
             graphics_->SetRenderTarget(0, renderBuffer);
             graphics_->SetDepthStencil(depthStencil_);
             graphics_->SetDepthStencil(depthStencil_);
+            graphics_->SetViewport(screenRect_);
             graphics_->SetTexture(TU_DIFFBUFFER, diffBuffer);
             graphics_->SetTexture(TU_DIFFBUFFER, diffBuffer);
             graphics_->SetTexture(TU_NORMALBUFFER, normalBuffer);
             graphics_->SetTexture(TU_NORMALBUFFER, normalBuffer);
             graphics_->SetTexture(TU_DEPTHBUFFER, depthBuffer);
             graphics_->SetTexture(TU_DEPTHBUFFER, depthBuffer);
-            graphics_->SetViewport(screenRect_);
             
             
             for (unsigned i = 0; i < noShadowLightQueue_.sortedBatches_.Size(); ++i)
             for (unsigned i = 0; i < noShadowLightQueue_.sortedBatches_.Size(); ++i)
             {
             {
@@ -980,14 +968,13 @@ void View::RenderBatchesDeferred()
         // Render base passes
         // Render base passes
         PROFILE(RenderBasePass);
         PROFILE(RenderBasePass);
         
         
-        graphics_->ClearLastParameterSources();
         graphics_->SetStencilTest(false);
         graphics_->SetStencilTest(false);
-        graphics_->SetRenderTarget(0, renderBuffer);
-        graphics_->SetDepthStencil(depthStencil_);
-        graphics_->SetViewport(screenRect_);
         graphics_->SetTexture(TU_DIFFBUFFER, 0);
         graphics_->SetTexture(TU_DIFFBUFFER, 0);
         graphics_->SetTexture(TU_NORMALBUFFER, 0);
         graphics_->SetTexture(TU_NORMALBUFFER, 0);
         graphics_->SetTexture(TU_DEPTHBUFFER, 0);
         graphics_->SetTexture(TU_DEPTHBUFFER, 0);
+        graphics_->SetRenderTarget(0, renderBuffer);
+        graphics_->SetDepthStencil(depthStencil_);
+        graphics_->SetViewport(screenRect_);
         
         
         RenderBatchQueue(baseQueue_, true);
         RenderBatchQueue(baseQueue_, true);
     }
     }
@@ -1020,8 +1007,9 @@ void View::RenderBatchesDeferred()
         else
         else
             depthMode.w_ = 1.0f / camera_->GetFarClip();
             depthMode.w_ = 1.0f / camera_->GetFarClip();
         
         
-        unsigned index = camera_->IsOrthographic() ? 1 : 0;
-        String shaderName = "TemporalAA_" + aaVariation[index];
+        String shaderName = "TemporalAA";
+        if (camera_->IsOrthographic())
+            shaderName += "_Ortho";
         
         
         graphics_->SetAlphaTest(false);
         graphics_->SetAlphaTest(false);
         graphics_->SetBlendMode(BLEND_REPLACE);
         graphics_->SetBlendMode(BLEND_REPLACE);
@@ -2013,7 +2001,6 @@ void View::CalculateShaderParameters()
 
 
 void View::DrawSplitLightToStencil(Camera& camera, Light* light, bool clear)
 void View::DrawSplitLightToStencil(Camera& camera, Light* light, bool clear)
 {
 {
-    graphics_->ClearTransformSources();
     Matrix3x4 view(camera.GetInverseWorldTransform());
     Matrix3x4 view(camera.GetInverseWorldTransform());
     
     
     switch (light->GetLightType())
     switch (light->GetLightType())
@@ -2035,6 +2022,7 @@ void View::DrawSplitLightToStencil(Camera& camera, Light* light, bool clear)
             graphics_->SetShaders(renderer_->stencilVS_, renderer_->stencilPS_);
             graphics_->SetShaders(renderer_->stencilVS_, renderer_->stencilPS_);
             graphics_->SetShaderParameter(VSP_MODEL, model);
             graphics_->SetShaderParameter(VSP_MODEL, model);
             graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * view);
             graphics_->SetShaderParameter(VSP_VIEWPROJ, projection * view);
+            graphics_->ClearTransformSources();
             
             
             // Draw the faces to stencil which we should draw (where no light has not been rendered yet)
             // Draw the faces to stencil which we should draw (where no light has not been rendered yet)
             graphics_->SetStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
             graphics_->SetStencilTest(true, CMP_EQUAL, OP_INCR, OP_KEEP, OP_KEEP, 0);
@@ -2096,6 +2084,8 @@ void View::DrawSplitLightToStencil(Camera& camera, Light* light, bool clear)
                     graphics_->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
                     graphics_->SetStencilTest(true, CMP_ALWAYS, OP_REF, OP_ZERO, OP_ZERO, 1);
                 }
                 }
                 
                 
+                graphics_->ClearTransformSources();
+                
                 renderer_->dirLightGeometry_->Draw(graphics_);
                 renderer_->dirLightGeometry_->Draw(graphics_);
                 graphics_->SetColorWrite(true);
                 graphics_->SetColorWrite(true);
                 graphics_->SetStencilTest(true, CMP_EQUAL, OP_KEEP, OP_KEEP, OP_KEEP, 1);
                 graphics_->SetStencilTest(true, CMP_EQUAL, OP_KEEP, OP_KEEP, OP_KEEP, 1);
@@ -2213,7 +2203,6 @@ void View::RenderShadowMap(const LightBatchQueue& queue)
     
     
     Texture2D* shadowMap = queue.light_->GetShadowMap();
     Texture2D* shadowMap = queue.light_->GetShadowMap();
     
     
-    graphics_->ClearLastParameterSources();
     graphics_->SetColorWrite(false);
     graphics_->SetColorWrite(false);
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
     graphics_->SetTexture(TU_SHADOWMAP, 0);
     graphics_->SetTexture(TU_SHADOWMAP, 0);

+ 22 - 15
Engine/Physics/CollisionShape.cpp

@@ -68,7 +68,10 @@ void GetVertexAndIndexData(const Model* model, unsigned lodLevel, SharedArrayPtr
     
     
     for (unsigned i = 0; i < geometries.Size(); ++i)
     for (unsigned i = 0; i < geometries.Size(); ++i)
     {
     {
-        unsigned subGeometryLodLevel = Clamp(lodLevel, 0, geometries[i].Size());
+        unsigned subGeometryLodLevel = lodLevel;
+        if (subGeometryLodLevel >= geometries[i].Size())
+            subGeometryLodLevel = geometries[i].Size() / 2;
+        
         Geometry* geom = geometries[i][subGeometryLodLevel];
         Geometry* geom = geometries[i][subGeometryLodLevel];
         if (!geom)
         if (!geom)
             continue;
             continue;
@@ -151,7 +154,8 @@ void GetVertexAndIndexData(const Model* model, unsigned lodLevel, SharedArrayPtr
 }
 }
 
 
 TriangleMeshData::TriangleMeshData(Model* model, bool makeConvexHull, float thickness, unsigned lodLevel, const Vector3& scale) :
 TriangleMeshData::TriangleMeshData(Model* model, bool makeConvexHull, float thickness, unsigned lodLevel, const Vector3& scale) :
-    triMesh_(0)
+    triMesh_(0),
+    indexCount_(0)
 {
 {
     modelName_ = model->GetName();
     modelName_ = model->GetName();
     
     
@@ -199,6 +203,8 @@ TriangleMeshData::TriangleMeshData(Model* model, bool makeConvexHull, float thic
     
     
     dGeomTriMeshDataBuildSingle(triMesh_, vertexData_.GetPtr(), sizeof(Vector3), vertexCount,
     dGeomTriMeshDataBuildSingle(triMesh_, vertexData_.GetPtr(), sizeof(Vector3), vertexCount,
         indexData_.GetPtr(), indexCount, 3 * sizeof(unsigned));
         indexData_.GetPtr(), indexCount, 3 * sizeof(unsigned));
+    
+    indexCount_ = indexCount;
 }
 }
 
 
 TriangleMeshData::~TriangleMeshData()
 TriangleMeshData::~TriangleMeshData()
@@ -714,21 +720,22 @@ void CollisionShape::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
         
         
     case dTriMeshClass:
     case dTriMeshClass:
         {
         {
-            unsigned numTriangles = dGeomTriMeshGetTriangleCount(geometry_);
-            for (unsigned i = 0; i < numTriangles; ++i)
+            TriangleMeshData* data = static_cast<TriangleMeshData*>(geometryData_.GetPtr());
+            if (!data)
+                return;
+            
+            const Vector3* vertices = data->vertexData_;
+            const unsigned* indices = data->indexData_;
+            
+            for (unsigned i = 0; i < data->indexCount_; i += 3)
             {
             {
-                dVector3 v0;
-                dVector3 v1;
-                dVector3 v2;
+                Vector3 v0 = transform * vertices[indices[i]];
+                Vector3 v1 = transform * vertices[indices[i + 1]];
+                Vector3 v2 = transform * vertices[indices[i + 2]];
                 
                 
-                dGeomTriMeshGetTriangle(geometry_, i, &v0, &v1, &v2);
-                
-                Vector3 a(v0[0], v0[1], v0[2]);
-                Vector3 b(v1[0], v1[1], v1[2]);
-                Vector3 c(v2[0], v2[1], v2[2]);
-                debug->AddLine(a, b, color, depthTest);
-                debug->AddLine(b, c, color, depthTest);
-                debug->AddLine(c, a, color, depthTest);
+                debug->AddLine(v0, v1, color, depthTest);
+                debug->AddLine(v1, v2, color, depthTest);
+                debug->AddLine(v2, v0, color, depthTest);
             }
             }
         }
         }
         break;
         break;

+ 2 - 0
Engine/Physics/CollisionShape.h

@@ -68,6 +68,8 @@ struct TriangleMeshData : public CollisionGeometryData
     SharedArrayPtr<Vector3> vertexData_;
     SharedArrayPtr<Vector3> vertexData_;
     /// Index data
     /// Index data
     SharedArrayPtr<unsigned> indexData_;
     SharedArrayPtr<unsigned> indexData_;
+    /// Number of indices
+    unsigned indexCount_;
 };
 };
 
 
 /// Heightfield geometry data
 /// Heightfield geometry data

+ 1 - 1
Engine/UI/UI.cpp

@@ -244,6 +244,7 @@ void UI::Render()
     projection.m23_ = 0.0f;
     projection.m23_ = 0.0f;
     projection.m33_ = 1.0f;
     projection.m33_ = 1.0f;
     
     
+    graphics_->ClearParameterSources();
     graphics_->ResetRenderTargets();
     graphics_->ResetRenderTargets();
     graphics_->SetAlphaTest(false);
     graphics_->SetAlphaTest(false);
     graphics_->SetCullMode(CULL_CCW);
     graphics_->SetCullMode(CULL_CCW);
@@ -251,7 +252,6 @@ void UI::Render()
     graphics_->SetDepthWrite(false);
     graphics_->SetDepthWrite(false);
     graphics_->SetFillMode(FILL_SOLID);
     graphics_->SetFillMode(FILL_SOLID);
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
-    graphics_->ClearLastParameterSources();
     
     
     ShaderVariation* ps = 0;
     ShaderVariation* ps = 0;
     ShaderVariation* vs = 0;
     ShaderVariation* vs = 0;