瀏覽代碼

Reduce number of distinct shader parameter groups to prepare for mapping them to constant buffers.

Lasse Öörni 10 年之前
父節點
當前提交
48483ac07c

+ 177 - 181
Source/Urho3D/Graphics/Batch.cpp

@@ -212,24 +212,20 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
     if (graphics->NeedParameterUpdate(SP_FRAME, (void*)0))
         view->SetGlobalShaderParameters();
     
-    // Set camera shader parameters
+    // Set camera & viewport shader parameters
     unsigned cameraHash = (unsigned)(size_t)camera_;
-    if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash)))
-        view->SetCameraShaderParameters(camera_, true);
-    
-    // Set viewport shader parameters
     IntRect viewport = graphics->GetViewport();
     IntVector2 viewSize = IntVector2(viewport.Width(), viewport.Height());
     unsigned viewportHash = viewSize.x_ | (viewSize.y_ << 16);
-    
-    if (graphics->NeedParameterUpdate(SP_VIEWPORT, reinterpret_cast<void*>(viewportHash)))
+    if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash + viewportHash)))
     {
+        view->SetCameraShaderParameters(camera_, true);
         // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
         view->SetGBufferShaderParameters(viewSize, IntRect(0, 0, viewSize.x_, viewSize.y_));
     }
     
     // Set model or skinning transforms
-    if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, worldTransform_))
+    if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECT, worldTransform_))
     {
         if (geometryType_ == GEOM_SKINNED)
         {
@@ -294,7 +290,8 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
     // Set light-related shader parameters
     if (lightQueue_)
     {
-        if (lightQueue_->vertexLights_.Size() && graphics->NeedParameterUpdate(SP_VERTEXLIGHTS, lightQueue_) && graphics->HasShaderParameter(VSP_VERTEXLIGHTS))
+        if (lightQueue_->vertexLights_.Size() && graphics->HasShaderParameter(VSP_VERTEXLIGHTS) && graphics->NeedParameterUpdate(
+            SP_LIGHT, reinterpret_cast<void*>((unsigned)(size_t)lightQueue_ + 0x80000000)))
         {
             Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3];
             const PODVector<Light*>& lights = lightQueue_->vertexLights_;
@@ -343,208 +340,207 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
             
             graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
         }
-    }
-    
-    if (light && graphics->NeedParameterUpdate(SP_LIGHT, light))
-    {
-        // Deferred light volume batches operate in a camera-centered space. Detect from material, zone & pass all being null
-        bool isLightVolume = !material_ && !pass_ && !zone_;
-        
-        Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
-        Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation();
-
-        Node* lightNode = light->GetNode();
-        Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix();
-        
-        graphics->SetShaderParameter(VSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
-        
-        float atten = 1.0f / Max(light->GetRange(), M_EPSILON);
-        graphics->SetShaderParameter(VSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition(), atten));
-        
-        if (graphics->HasShaderParameter(VSP_LIGHTMATRICES))
+        else if (light && graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
         {
-            switch (light->GetLightType())
+            // Deferred light volume batches operate in a camera-centered space. Detect from material, zone & pass all being null
+            bool isLightVolume = !material_ && !pass_ && !zone_;
+            
+            Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
+            Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation();
+            
+            Node* lightNode = light->GetNode();
+            Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix();
+            
+            graphics->SetShaderParameter(VSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
+            
+            float atten = 1.0f / Max(light->GetRange(), M_EPSILON);
+            graphics->SetShaderParameter(VSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition(), atten));
+            
+            if (graphics->HasShaderParameter(VSP_LIGHTMATRICES))
             {
-            case LIGHT_DIRECTIONAL:
+                switch (light->GetLightType())
                 {
-                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
-                    unsigned numSplits = Min(MAX_CASCADE_SPLITS, (int)lightQueue_->shadowSplits_.Size());
-
-                    for (unsigned i = 0; i < numSplits; ++i)
-                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, Vector3::ZERO);
+                case LIGHT_DIRECTIONAL:
+                    {
+                        Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
+                        unsigned numSplits = Min(MAX_CASCADE_SPLITS, (int)lightQueue_->shadowSplits_.Size());
                     
-                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
-                }
-                break;
+                        for (unsigned i = 0; i < numSplits; ++i)
+                            CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, Vector3::ZERO);
+                        
+                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
+                    }
+                    break;
                 
-            case LIGHT_SPOT:
-                {
-                    Matrix4 shadowMatrices[2];
-                    
-                    CalculateSpotMatrix(shadowMatrices[0], light, Vector3::ZERO);
-                    bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP);
-                    if (isShadowed)
-                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, Vector3::ZERO);
+                case LIGHT_SPOT:
+                    {
+                        Matrix4 shadowMatrices[2];
                     
-                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
-                }
-                break;
+                        CalculateSpotMatrix(shadowMatrices[0], light, Vector3::ZERO);
+                        bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP);
+                        if (isShadowed)
+                            CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, Vector3::ZERO);
+                        
+                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
+                    }
+                    break;
                 
-            case LIGHT_POINT:
-                {
-                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
-                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
-                    // the next parameter
-                    #ifdef URHO3D_OPENGL
-                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16);
-                    #else
-                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12);
-                    #endif
+                case LIGHT_POINT:
+                    {
+                        Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
+                        // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
+                        // the next parameter
+                        #ifdef URHO3D_OPENGL
+                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16);
+                        #else
+                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12);
+                        #endif
+                    }
+                    break;
                 }
-                break;
             }
-        }
-        
-        float fade = 1.0f;
-        float fadeEnd = light->GetDrawDistance();
-        float fadeStart = light->GetFadeDistance();
-        
-        // Do fade calculation for light if both fade & draw distance defined
-        if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
-            fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
-        
-        // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter
-        graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(),
-            light->GetEffectiveSpecularIntensity()) * fade);
-        graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
-        graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4((isLightVolume ? (lightNode->GetWorldPosition() -
-            cameraEffectivePos) : lightNode->GetWorldPosition()), atten));
+            
+            float fade = 1.0f;
+            float fadeEnd = light->GetDrawDistance();
+            float fadeStart = light->GetFadeDistance();
+            
+            // Do fade calculation for light if both fade & draw distance defined
+            if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
+                fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
         
-        if (graphics->HasShaderParameter(PSP_LIGHTMATRICES))
-        {
-            switch (light->GetLightType())
+            // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter
+            graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(),
+                light->GetEffectiveSpecularIntensity()) * fade);
+            graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
+            graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4((isLightVolume ? (lightNode->GetWorldPosition() -
+                cameraEffectivePos) : lightNode->GetWorldPosition()), atten));
+            
+            if (graphics->HasShaderParameter(PSP_LIGHTMATRICES))
             {
-            case LIGHT_DIRECTIONAL:
+                switch (light->GetLightType())
                 {
-                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
-                    unsigned numSplits = Min(MAX_CASCADE_SPLITS, (int)lightQueue_->shadowSplits_.Size());
-
-                    for (unsigned i = 0; i < numSplits; ++i)
+                case LIGHT_DIRECTIONAL:
                     {
-                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos :
-                            Vector3::ZERO);
+                        Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
+                        unsigned numSplits = Min(MAX_CASCADE_SPLITS, (int)lightQueue_->shadowSplits_.Size());
+
+                        for (unsigned i = 0; i < numSplits; ++i)
+                        {
+                            CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos :
+                                Vector3::ZERO);
+                        }
+                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                     }
-                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
-                }
-                break;
+                    break;
                 
-            case LIGHT_SPOT:
-                {
-                    Matrix4 shadowMatrices[2];
+                case LIGHT_SPOT:
+                    {
+                        Matrix4 shadowMatrices[2];
                     
-                    CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
-                    bool isShadowed = lightQueue_->shadowMap_ != 0;
-                    if (isShadowed)
+                        CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
+                        bool isShadowed = lightQueue_->shadowMap_ != 0;
+                        if (isShadowed)
+                        {
+                            CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos :
+                                Vector3::ZERO);
+                        }
+                    
+                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
+                    }
+                    break;
+                
+                case LIGHT_POINT:
                     {
-                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos :
-                            Vector3::ZERO);
+                        Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
+                        // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
+                        // the next parameter
+                        #ifdef URHO3D_OPENGL
+                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
+                        #else
+                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
+                        #endif
                     }
-                    
-                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
+                    break;
                 }
-                break;
-                
-            case LIGHT_POINT:
+            }
+            
+            // Set shadow mapping shader parameters
+            if (shadowMap)
+            {
                 {
-                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
-                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
-                    // the next parameter
+                    // Calculate point light shadow sampling offsets (unrolled cube map)
+                    unsigned faceWidth = shadowMap->GetWidth() / 2;
+                    unsigned faceHeight = shadowMap->GetHeight() / 3;
+                    float width = (float)shadowMap->GetWidth();
+                    float height = (float)shadowMap->GetHeight();
                     #ifdef URHO3D_OPENGL
-                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
+                        float mulX = (float)(faceWidth - 3) / width;
+                        float mulY = (float)(faceHeight - 3) / height;
+                        float addX = 1.5f / width;
+                        float addY = 1.5f / height;
                     #else
-                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
+                        float mulX = (float)(faceWidth - 4) / width;
+                        float mulY = (float)(faceHeight - 4) / height;
+                        float addX = 2.5f / width;
+                        float addY = 2.5f / height;
                     #endif
+                    // If using 4 shadow samples, offset the position diagonally by half pixel
+                    if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
+                    {
+                        addX -= 0.5f / width;
+                        addY -= 0.5f / height;
+                    }
+                    graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
                 }
-                break;
-            }
-        }
-        
-        // Set shadow mapping shader parameters
-        if (shadowMap)
-        {
-            {
-                // Calculate point light shadow sampling offsets (unrolled cube map)
-                unsigned faceWidth = shadowMap->GetWidth() / 2;
-                unsigned faceHeight = shadowMap->GetHeight() / 3;
-                float width = (float)shadowMap->GetWidth();
-                float height = (float)shadowMap->GetHeight();
-                #ifdef URHO3D_OPENGL
-                    float mulX = (float)(faceWidth - 3) / width;
-                    float mulY = (float)(faceHeight - 3) / height;
-                    float addX = 1.5f / width;
-                    float addY = 1.5f / height;
-                #else
-                    float mulX = (float)(faceWidth - 4) / width;
-                    float mulY = (float)(faceHeight - 4) / height;
-                    float addX = 2.5f / width;
-                    float addY = 2.5f / height;
-                #endif
-                // If using 4 shadow samples, offset the position diagonally by half pixel
-                if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
+                
                 {
-                    addX -= 0.5f / width;
-                    addY -= 0.5f / height;
+                    // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for
+                    //  directional light shadows, stored in the same uniform
+                    Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
+                    float nearClip = shadowCamera->GetNearClip();
+                    float farClip = shadowCamera->GetFarClip();
+                    float q = farClip / (farClip - nearClip);
+                    float r = -q * nearClip;
+                    
+                    const CascadeParameters& parameters = light->GetShadowCascade();
+                    float viewFarClip = camera_->GetFarClip();
+                    float shadowRange = parameters.GetShadowRange();
+                    float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip;
+                    float fadeEnd = shadowRange / viewFarClip;
+                    float fadeRange = fadeEnd - fadeStart;
+                    
+                    graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
                 }
-                graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
-            }
-            
-            {
-                // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for
-                //  directional light shadows, stored in the same uniform
-                Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
-                float nearClip = shadowCamera->GetNearClip();
-                float farClip = shadowCamera->GetFarClip();
-                float q = farClip / (farClip - nearClip);
-                float r = -q * nearClip;
-                
-                const CascadeParameters& parameters = light->GetShadowCascade();
-                float viewFarClip = camera_->GetFarClip();
-                float shadowRange = parameters.GetShadowRange();
-                float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip;
-                float fadeEnd = shadowRange / viewFarClip;
-                float fadeRange = fadeEnd - fadeStart;
                 
-                graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
-            }
-            
-            {
-                float intensity = light->GetShadowIntensity();
-                float fadeStart = light->GetShadowFadeDistance();
-                float fadeEnd = light->GetShadowDistance();
-                if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
-                    intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
-                float pcfValues = (1.0f - intensity);
-                float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;
+                {
+                    float intensity = light->GetShadowIntensity();
+                    float fadeStart = light->GetShadowFadeDistance();
+                    float fadeEnd = light->GetShadowDistance();
+                    if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
+                        intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
+                    float pcfValues = (1.0f - intensity);
+                    float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;
 
-                graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f));
+                    graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f));
+                }
+                
+                float sizeX = 1.0f / (float)shadowMap->GetWidth();
+                float sizeY = 1.0f / (float)shadowMap->GetHeight();
+                graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
+                
+                Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE);
+                if (lightQueue_->shadowSplits_.Size() > 1)
+                    lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera_->GetFarClip();
+                if (lightQueue_->shadowSplits_.Size() > 2)
+                    lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera_->GetFarClip();
+                if (lightQueue_->shadowSplits_.Size() > 3)
+                    lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera_->GetFarClip();
+                
+                graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);
             }
-            
-            float sizeX = 1.0f / (float)shadowMap->GetWidth();
-            float sizeY = 1.0f / (float)shadowMap->GetHeight();
-            graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
-            
-            Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE);
-            if (lightQueue_->shadowSplits_.Size() > 1)
-                lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera_->GetFarClip();
-            if (lightQueue_->shadowSplits_.Size() > 2)
-                lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera_->GetFarClip();
-            if (lightQueue_->shadowSplits_.Size() > 3)
-                lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera_->GetFarClip();
-            
-            graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);
         }
     }
-    
+
     // Set material-specific shader parameters and textures
     if (material_)
     {
@@ -634,7 +630,7 @@ void BatchGroup::Draw(View* view, bool allowDepthWrite) const
             
             for (unsigned i = 0; i < instances_.Size(); ++i)
             {
-                if (graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, instances_[i].worldTransform_))
+                if (graphics->NeedParameterUpdate(SP_OBJECT, instances_[i].worldTransform_))
                     graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_);
                 
                 graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),

+ 1 - 1
Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -1063,7 +1063,7 @@ void Graphics::ClearParameterSources()
 void Graphics::ClearTransformSources()
 {
     shaderParameterSources_[SP_CAMERA] = (const void*)M_MAX_UNSIGNED;
-    shaderParameterSources_[SP_OBJECTTRANSFORM] = (const void*)M_MAX_UNSIGNED;
+    shaderParameterSources_[SP_OBJECT] = (const void*)M_MAX_UNSIGNED;
 }
 
 void Graphics::SetTexture(unsigned index, Texture* texture)

+ 54 - 0
Source/Urho3D/Graphics/Direct3D11/D3D11ShaderProgram.h

@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2008-2015 the Urho3D project.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include "../../Container/HashMap.h"
+#include "../../Graphics/ShaderVariation.h"
+
+namespace Urho3D
+{
+
+/// Combined information for specific vertex and pixel shaders.
+class ShaderProgram : public RefCounted
+{
+public:
+    /// Construct.
+    ShaderProgram(ShaderVariation* vertexShader, ShaderVariation* pixelShader)
+    {
+        const HashMap<StringHash, ShaderParameter>& vsParams = vertexShader->GetParameters();
+        for (HashMap<StringHash, ShaderParameter>::ConstIterator i = vsParams.Begin(); i != vsParams.End(); ++i)
+            parameters_[i->first_] = i->second_;
+
+        const HashMap<StringHash, ShaderParameter>& psParams = pixelShader->GetParameters();
+        for (HashMap<StringHash, ShaderParameter>::ConstIterator i = psParams.Begin(); i != psParams.End(); ++i)
+            parameters_[i->first_] = i->second_;
+
+        // Optimize shader parameter lookup by rehashing to next power of two
+        parameters_.Rehash(NextPowerOfTwo(parameters_.Size()));
+    }
+
+    /// Combined parameters from the vertex and pixel shader.
+    HashMap<StringHash, ShaderParameter> parameters_;
+};
+
+}

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -1412,7 +1412,7 @@ void Graphics::ClearParameterSources()
 void Graphics::ClearTransformSources()
 {
     shaderParameterSources_[SP_CAMERA] = (const void*)M_MAX_UNSIGNED;
-    shaderParameterSources_[SP_OBJECTTRANSFORM] = (const void*)M_MAX_UNSIGNED;
+    shaderParameterSources_[SP_OBJECT] = (const void*)M_MAX_UNSIGNED;
 }
 
 void Graphics::SetTexture(unsigned index, Texture* texture)

+ 1 - 1
Source/Urho3D/Graphics/Direct3D9/D3D9ShaderProgram.h

@@ -28,7 +28,7 @@
 namespace Urho3D
 {
 
-/// Combined information for a combination of vertex and pixel shaders.
+/// Combined information for specific vertex and pixel shaders.
 class ShaderProgram : public RefCounted
 {
 public:

+ 2 - 4
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -218,17 +218,15 @@ enum ShaderType
     PS,
 };
 
-/// Shader parameter groups for determining need to update.
+/// Shader parameter groups for determining need to update. On APIs that support constant buffers, these correspond to different constant buffers.
 enum ShaderParameterGroup
 {
     SP_FRAME = 0,
     SP_CAMERA,
-    SP_VIEWPORT,
     SP_ZONE,
     SP_LIGHT,
-    SP_VERTEXLIGHTS,
     SP_MATERIAL,
-    SP_OBJECTTRANSFORM,
+    SP_OBJECT,
     MAX_SHADER_PARAMETER_GROUPS
 };
 

+ 1 - 1
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -1428,7 +1428,7 @@ void Graphics::ClearParameterSources()
 void Graphics::ClearTransformSources()
 {
     shaderParameterSources_[SP_CAMERA] = (const void*)M_MAX_UNSIGNED;
-    shaderParameterSources_[SP_OBJECTTRANSFORM] = (const void*)M_MAX_UNSIGNED;
+    shaderParameterSources_[SP_OBJECT] = (const void*)M_MAX_UNSIGNED;
 }
 
 void Graphics::SetTexture(unsigned index, Texture* texture)

+ 1 - 1
Source/Urho3D/UI/UI.cpp

@@ -807,7 +807,7 @@ void UI::Render(bool resetRenderTargets, VertexBuffer* buffer, const PODVector<U
         }
 
         graphics_->SetShaders(vs, ps);
-        if (graphics_->NeedParameterUpdate(SP_OBJECTTRANSFORM, this))
+        if (graphics_->NeedParameterUpdate(SP_OBJECT, this))
             graphics_->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY);
         if (graphics_->NeedParameterUpdate(SP_CAMERA, this))
             graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);