Bladeren bron

Clean up / reorder light shader parameter handling.

Lasse Öörni 10 jaren geleden
bovenliggende
commit
5ac8f1fb43
1 gewijzigde bestanden met toevoegingen van 148 en 148 verwijderingen
  1. 148 148
      Source/Urho3D/Graphics/Batch.cpp

+ 148 - 148
Source/Urho3D/Graphics/Batch.cpp

@@ -290,180 +290,130 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
     // Set light-related shader parameters
     if (lightQueue_)
     {
-        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_;
-            
-            for (unsigned i = 0; i < lights.Size(); ++i)
-            {
-                Light* vertexLight = lights[i];
-                Node* vertexLightNode = vertexLight->GetNode();
-                LightType type = vertexLight->GetLightType();
-                
-                // Attenuation
-                float invRange, cutoff, invCutoff;
-                if (type == LIGHT_DIRECTIONAL)
-                    invRange = 0.0f;
-                else
-                    invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON);
-                if (type == LIGHT_SPOT)
-                {
-                    cutoff = Cos(vertexLight->GetFov() * 0.5f);
-                    invCutoff = 1.0f / (1.0f - cutoff);
-                }
-                else
-                {
-                    cutoff = -1.0f;
-                    invCutoff = 1.0f;
-                }
-                
-                // Color
-                float fade = 1.0f;
-                float fadeEnd = vertexLight->GetDrawDistance();
-                float fadeStart = vertexLight->GetFadeDistance();
-                
-                // Do fade calculation for light if both fade & draw distance defined
-                if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
-                    fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
-                
-                Color color = vertexLight->GetEffectiveColor() * fade;
-                vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange);
-                
-                // Direction
-                vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff);
-                
-                // Position
-                vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff);
-            }
-            
-            graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
-        }
-        else if (light && graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
+        if (light && graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
         {
             // 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))
             {
                 switch (light->GetLightType())
                 {
                 case LIGHT_DIRECTIONAL:
-                    {
-                        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);
-                        
-                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
-                    }
-                    break;
-                
+                {
+                    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);
+
+                    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);
-                        
-                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
-                    }
-                    break;
-                
+                {
+                    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);
+
+                    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
-                    }
-                    break;
+                {
+                    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;
                 }
             }
-            
+
             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));
-            
+
             if (graphics->HasShaderParameter(PSP_LIGHTMATRICES))
             {
                 switch (light->GetLightType())
                 {
                 case LIGHT_DIRECTIONAL:
+                {
+                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
+                    unsigned numSplits = Min(MAX_CASCADE_SPLITS, (int)lightQueue_->shadowSplits_.Size());
+
+                    for (unsigned i = 0; i < numSplits; ++i)
                     {
-                        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);
+                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos :
+                            Vector3::ZERO);
                     }
-                    break;
-                
+                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
+                }
+                break;
+
                 case LIGHT_SPOT:
+                {
+                    Matrix4 shadowMatrices[2];
+
+                    CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
+                    bool isShadowed = lightQueue_->shadowMap_ != 0;
+                    if (isShadowed)
                     {
-                        Matrix4 shadowMatrices[2];
-                    
-                        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);
+                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos :
+                            Vector3::ZERO);
                     }
-                    break;
-                
+
+                    graphics->SetShaderParameter(PSP_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(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
-                        #else
-                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
-                        #endif
-                    }
-                    break;
+                {
+                    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
+                }
+                break;
                 }
             }
-            
+
             // Set shadow mapping shader parameters
             if (shadowMap)
             {
@@ -473,17 +423,17 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
                     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
+#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)
                     {
@@ -492,7 +442,7 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
                     }
                     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
@@ -501,17 +451,17 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
                     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();
@@ -523,11 +473,11 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
 
                     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();
@@ -535,10 +485,60 @@ void Batch::Prepare(View* view, bool setModelTransform, bool allowDepthWrite) co
                     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);
             }
         }
+        else if (lightQueue_->vertexLights_.Size() && graphics->HasShaderParameter(VSP_VERTEXLIGHTS) &&
+            graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
+        {
+            Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3];
+            const PODVector<Light*>& lights = lightQueue_->vertexLights_;
+            
+            for (unsigned i = 0; i < lights.Size(); ++i)
+            {
+                Light* vertexLight = lights[i];
+                Node* vertexLightNode = vertexLight->GetNode();
+                LightType type = vertexLight->GetLightType();
+                
+                // Attenuation
+                float invRange, cutoff, invCutoff;
+                if (type == LIGHT_DIRECTIONAL)
+                    invRange = 0.0f;
+                else
+                    invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON);
+                if (type == LIGHT_SPOT)
+                {
+                    cutoff = Cos(vertexLight->GetFov() * 0.5f);
+                    invCutoff = 1.0f / (1.0f - cutoff);
+                }
+                else
+                {
+                    cutoff = -1.0f;
+                    invCutoff = 1.0f;
+                }
+                
+                // Color
+                float fade = 1.0f;
+                float fadeEnd = vertexLight->GetDrawDistance();
+                float fadeStart = vertexLight->GetFadeDistance();
+                
+                // Do fade calculation for light if both fade & draw distance defined
+                if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
+                    fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
+                
+                Color color = vertexLight->GetEffectiveColor() * fade;
+                vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange);
+                
+                // Direction
+                vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff);
+                
+                // Position
+                vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff);
+            }
+            
+            graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
+        }
     }
 
     // Set material-specific shader parameters and textures