Browse Source

Merge branch 'master' into vertexdeclaration

Lasse Öörni 9 years ago
parent
commit
c003af1114

+ 0 - 1
.travis.yml

@@ -352,7 +352,6 @@ env:
     - MAKEFILE=1    URHO3D_LIB_TYPE=SHARED URHO3D_DEPLOYMENT_TARGET=generic
     - MAKEFILE=1    URHO3D_LIB_TYPE=SHARED URHO3D_DEPLOYMENT_TARGET=generic
     - XCODE=1       URHO3D_LIB_TYPE=STATIC CMAKE_OSX_DEPLOYMENT_TARGET=10.11 SF_DEFAULT=mac:OSX-64bit-STATIC.tar.gz
     - XCODE=1       URHO3D_LIB_TYPE=STATIC CMAKE_OSX_DEPLOYMENT_TARGET=10.11 SF_DEFAULT=mac:OSX-64bit-STATIC.tar.gz
     - XCODE=1       URHO3D_LIB_TYPE=SHARED CMAKE_OSX_DEPLOYMENT_TARGET=10.11
     - XCODE=1       URHO3D_LIB_TYPE=SHARED CMAKE_OSX_DEPLOYMENT_TARGET=10.11
-    - XCODE=1 IOS=1 URHO3D_LIB_TYPE=STATIC IPHONEOS_DEPLOYMENT_TARGET=9.1 sdk=iphonesimulator URHO3D_64BIT=0
     - XCODE=1 IOS=1 URHO3D_LIB_TYPE=STATIC IPHONEOS_DEPLOYMENT_TARGET=9.1 sdk=iphonesimulator
     - XCODE=1 IOS=1 URHO3D_LIB_TYPE=STATIC IPHONEOS_DEPLOYMENT_TARGET=9.1 sdk=iphonesimulator
 matrix:
 matrix:
   fast_finish: true
   fast_finish: true

+ 2 - 5
CMake/Modules/Urho3D-CMake-common.cmake

@@ -1028,11 +1028,8 @@ macro (setup_target)
         unset (TARGET_PROPERTIES)
         unset (TARGET_PROPERTIES)
     endif ()
     endif ()
 
 
-    if (DEFINED ENV{TRAVIS})
-        # Workaround to avoid technical error due to Travis CI build time limit
-        add_custom_command (TARGET ${TARGET_NAME} POST_BUILD COMMAND rake ci_timeup WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
-    else ()
-        # Workaround CMake/Xcode generator bug where it always appends '/build' path element to SYMROOT attribute and as such the items in Products are always rendered as red in the Xcode IDE as if they are not yet built
+    # Workaround CMake/Xcode generator bug where it always appends '/build' path element to SYMROOT attribute and as such the items in Products are always rendered as red in the Xcode IDE as if they are not yet built
+    if (NOT DEFINED ENV{TRAVIS})
         if (XCODE AND NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
         if (XCODE AND NOT CMAKE_PROJECT_NAME MATCHES ^Urho3D-ExternalProject-)
             file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/build)
             file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/build)
             get_target_property (LOCATION ${TARGET_NAME} LOCATION)
             get_target_property (LOCATION ${TARGET_NAME} LOCATION)

+ 1 - 1
CMakeLists.txt

@@ -83,7 +83,7 @@ set (DEST_PKGCONFIG_DIR lib${LIB_SUFFIX}/pkgconfig)
 file (GLOB APP_SCRIPTS ${CMAKE_SOURCE_DIR}/bin/*${SCRIPT_EXT})
 file (GLOB APP_SCRIPTS ${CMAKE_SOURCE_DIR}/bin/*${SCRIPT_EXT})
 install (PROGRAMS ${APP_SCRIPTS} DESTINATION ${DEST_RUNTIME_DIR})   # DEST_RUNTIME_DIR variable is set by the set_output_directories() macro call in the Urho3D-CMake-common module
 install (PROGRAMS ${APP_SCRIPTS} DESTINATION ${DEST_RUNTIME_DIR})   # DEST_RUNTIME_DIR variable is set by the set_output_directories() macro call in the Urho3D-CMake-common module
 # Install resource directories required by applications built with Urho3D library
 # Install resource directories required by applications built with Urho3D library
-install (DIRECTORY ${CMAKE_SOURCE_DIR}/bin/CoreData ${CMAKE_SOURCE_DIR}/bin/Data DESTINATION ${DEST_SHARE_DIR}/Resources)
+install (DIRECTORY ${CMAKE_SOURCE_DIR}/bin/Autoload ${CMAKE_SOURCE_DIR}/bin/CoreData ${CMAKE_SOURCE_DIR}/bin/Data DESTINATION ${DEST_SHARE_DIR}/Resources)
 # Install CMake modules and toolchains provided by and for Urho3D
 # Install CMake modules and toolchains provided by and for Urho3D
 install (DIRECTORY ${CMAKE_SOURCE_DIR}/CMake/ DESTINATION ${DEST_SHARE_DIR}/CMake)    # Note: the trailing slash is significant
 install (DIRECTORY ${CMAKE_SOURCE_DIR}/CMake/ DESTINATION ${DEST_SHARE_DIR}/CMake)    # Note: the trailing slash is significant
 # Install CMake build scripts
 # Install CMake build scripts

+ 22 - 25
Rakefile

@@ -350,14 +350,11 @@ task :ci do
     system 'rake ci_push_bindings' or abort
     system 'rake ci_push_bindings' or abort
     next
     next
   end
   end
-  # Enable more granular timeup check for Xcode
-  system 'touch enabled_time_check.log' if ENV['XCODE']
-  if !system "bash -c 'rake make'"
+  if !wait_for_block { system "bash -c 'rake make'" }
     abort 'Failed to build Urho3D library' unless File.exists?('already_timeup.log')
     abort 'Failed to build Urho3D library' unless File.exists?('already_timeup.log')
     $stderr.puts "Skipped the rest of the CI processes due to insufficient time"
     $stderr.puts "Skipped the rest of the CI processes due to insufficient time"
     next
     next
   end
   end
-  File.delete 'enabled_time_check.log' if ENV['XCODE']
   if ENV['URHO3D_TESTING'] && !timeup
   if ENV['URHO3D_TESTING'] && !timeup
     # Multi-config CMake generators use different test target name than single-config ones for no good reason
     # Multi-config CMake generators use different test target name than single-config ones for no good reason
     test = "rake make target=#{ENV['OS'] || ENV['XCODE'] ? 'RUN_TESTS' : 'test'}"
     test = "rake make target=#{ENV['OS'] || ENV['XCODE'] ? 'RUN_TESTS' : 'test'}"
@@ -370,13 +367,11 @@ task :ci do
   unless ENV['CI'] && (ENV['IOS'] || ENV['WEB']) && ENV['PACKAGE_UPLOAD'] || ENV['XCODE_64BIT_ONLY'] || timeup
   unless ENV['CI'] && (ENV['IOS'] || ENV['WEB']) && ENV['PACKAGE_UPLOAD'] || ENV['XCODE_64BIT_ONLY'] || timeup
     # Staged-install Urho3D SDK when on Travis-CI; normal install when on AppVeyor
     # Staged-install Urho3D SDK when on Travis-CI; normal install when on AppVeyor
     ENV['DESTDIR'] = ENV['HOME'] || Dir.home unless ENV['APPVEYOR']
     ENV['DESTDIR'] = ENV['HOME'] || Dir.home unless ENV['APPVEYOR']
-    system 'touch enabled_time_check.log' if ENV['XCODE']
-    if wait_for_block("Installing Urho3D SDK to #{ENV['DESTDIR'] ? "#{ENV['DESTDIR']}/usr/local" : 'default system-wide location'}...") { system "bash -c 'rake make target=install >/dev/null'"; Thread.current[:exit_code] = $?.exitstatus } != 0
+    if !wait_for_block("Installing Urho3D SDK to #{ENV['DESTDIR'] ? "#{ENV['DESTDIR']}/usr/local" : 'default system-wide location'}...") { system "bash -c 'rake make target=install >/dev/null'" }
       abort 'Failed to install Urho3D SDK' unless File.exists?('already_timeup.log')
       abort 'Failed to install Urho3D SDK' unless File.exists?('already_timeup.log')
       $stderr.puts "Skipped the rest of the CI processes due to insufficient time"
       $stderr.puts "Skipped the rest of the CI processes due to insufficient time"
       next
       next
     end
     end
-    File.delete 'enabled_time_check.log' if ENV['XCODE']
     # Alternate to use in-the-source build tree for test coverage
     # Alternate to use in-the-source build tree for test coverage
     ENV['build_tree'] = '.' unless ENV['APPVEYOR']
     ENV['build_tree'] = '.' unless ENV['APPVEYOR']
     # Ensure the following variables are auto-discovered during scaffolding test
     # Ensure the following variables are auto-discovered during scaffolding test
@@ -394,7 +389,7 @@ task :ci do
     next if timeup
     next if timeup
     # Second test - create a new project on the fly that uses newly built Urho3D library in the build tree
     # Second test - create a new project on the fly that uses newly built Urho3D library in the build tree
     Dir.chdir scaffolding "#{ENV['APPVEYOR'] ? '' : '../Build/'}UsingBuildTree" do
     Dir.chdir scaffolding "#{ENV['APPVEYOR'] ? '' : '../Build/'}UsingBuildTree" do
-      puts "\nConfiguring downstream project using Urho3D library in its build tree...\n\n"; $stdout.flush
+      puts "Configuring downstream project using Urho3D library in its build tree...\n\n"; $stdout.flush
       system "bash -c 'rake cmake #{generator} URHO3D_HOME=#{ENV['APPVEYOR'] ? '../../Build' : '..'} URHO3D_LUA=1 && rake make #{test}'" or abort 'Failed to configure/build/test temporary downstream project using Urho3D as external library'
       system "bash -c 'rake cmake #{generator} URHO3D_HOME=#{ENV['APPVEYOR'] ? '../../Build' : '..'} URHO3D_LUA=1 && rake make #{test}'" or abort 'Failed to configure/build/test temporary downstream project using Urho3D as external library'
     end
     end
   end
   end
@@ -651,14 +646,8 @@ task :ci_timer do
   timeup
   timeup
 end
 end
 
 
-# Usage: NOT Intended to be used manually
-desc 'Check if the time is up when the time check is enabled'
-task :ci_timeup do
-  abort "Time up!" if File.exists?('enabled_time_check.log') && timeup(true)
-end
-
 # Always call this function last in the multiple conditional check so that the checkpoint message does not being echoed unnecessarily
 # Always call this function last in the multiple conditional check so that the checkpoint message does not being echoed unnecessarily
-def timeup quiet = false
+def timeup quiet = false, cutoff_time = 40.0
   unless File.exists?('start_time.log')
   unless File.exists?('start_time.log')
     system 'touch start_time.log split_time.log'
     system 'touch start_time.log split_time.log'
     return nil
     return nil
@@ -670,7 +659,7 @@ def timeup quiet = false
     system 'touch split_time.log'
     system 'touch split_time.log'
     puts "\n=== elapsed time: #{elapsed_time.to_i} minutes #{((elapsed_time - elapsed_time.to_i) * 60.0).round} seconds, lap time: #{lap_time.to_i} minutes #{((lap_time - lap_time.to_i) * 60.0).round} seconds ===\n\n" unless File.exists?('already_timeup.log'); $stdout.flush
     puts "\n=== elapsed time: #{elapsed_time.to_i} minutes #{((elapsed_time - elapsed_time.to_i) * 60.0).round} seconds, lap time: #{lap_time.to_i} minutes #{((lap_time - lap_time.to_i) * 60.0).round} seconds ===\n\n" unless File.exists?('already_timeup.log'); $stdout.flush
   end
   end
-  return system('touch already_timeup.log') if elapsed_time > 40.0
+  return system('touch already_timeup.log') if elapsed_time > cutoff_time
 end
 end
 
 
 def scaffolding dir, project = 'Scaffolding', target = 'Main'
 def scaffolding dir, project = 'Scaffolding', target = 'Main'
@@ -831,24 +820,32 @@ EOF") { |stdout| echo = false; while output = stdout.gets do if echo && /#\s#/ !
   end
   end
 end
 end
 
 
-# Usage: wait_for_block("This is a long function call...") { Thread.current[:exit_code] = call_a_func } or abort
-#        wait_for_block("This is a long system call...") { system "do_something"; Thread.current[:exit_code] = $?.exitstatus } or abort
-def wait_for_block comment = '', retries = -1, retry_interval = 60, exit_code_sym = 'exit_code', &block
+# Usage: wait_for_block('This is a long function call...') { call_a_func } or abort
+#        wait_for_block('This is a long system call...') { system 'do_something' } or abort
+def wait_for_block comment = '', retries = -1, retry_interval = 60
+  # When not using Xcode, execute the code block in full speed
+  unless ENV['XCODE']
+    puts comment; $stdout.flush
+    return yield
+  end
+
   # Wait until the code block is completed or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
   # Wait until the code block is completed or it is killed externally by user via Ctrl+C or when it exceeds the number of retries (if the retries parameter is provided)
-  thread = Thread.new &block
+  thread = Thread.new { rc = yield; Thread.main.wakeup; rc }
+  thread.priority = 1   # Make the worker thread has higher priority than the main thread
   str = comment
   str = comment
   retries = retries * 60 / retry_interval unless retries == -1
   retries = retries * 60 / retry_interval unless retries == -1
-  until retries == 0
-    if thread.status == false
-      thread.join
+  until thread.status == false
+    if retries == 0 || timeup(true, 45.0)
+      thread.kill   # TODO: also kill the child subproceses spawned by the worker thread
       break
       break
     end
     end
     print str; str = '.'; $stdout.flush   # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
     print str; str = '.'; $stdout.flush   # Flush the standard output stream in case it is buffered to prevent Travis-CI into thinking that the build/test has stalled
-    sleep retry_interval
     retries -= 1 if retries > 0
     retries -= 1 if retries > 0
+    sleep retry_interval
   end
   end
   puts "\n" if str == '.'; $stdout.flush
   puts "\n" if str == '.'; $stdout.flush
-  return retries == 0 ? nil : (exit_code_sym ? thread[exit_code_sym] : 0)
+  thread.join
+  return thread.value
 end
 end
 
 
 def append_new_release release, filename = '../urho3d.github.io/_data/urho3d.json'
 def append_new_release release, filename = '../urho3d.github.io/_data/urho3d.json'

+ 36 - 0
Source/Urho3D/AngelScript/ScriptFile.cpp

@@ -769,6 +769,42 @@ void ScriptFile::SetParameters(asIScriptContext* context, asIScriptFunction* fun
                     context->SetArgObject(i, (void*)&parameters[i].GetString());
                     context->SetArgObject(i, (void*)&parameters[i].GetString());
                     break;
                     break;
 
 
+                case VAR_VARIANTMAP:
+                    context->SetArgObject(i, (void*)&parameters[i].GetVariantMap());
+                    break;
+
+                case VAR_INTRECT:
+                    context->SetArgObject(i, (void*)&parameters[i].GetIntRect());
+                    break;
+
+                case VAR_INTVECTOR2:
+                    context->SetArgObject(i, (void*)&parameters[i].GetIntVector2());
+                    break;
+
+                case VAR_COLOR:
+                    context->SetArgObject(i, (void*)&parameters[i].GetColor());
+                    break;
+
+                case VAR_MATRIX3:
+                    context->SetArgObject(i, (void*)&parameters[i].GetMatrix3());
+                    break;
+
+                case VAR_MATRIX3X4:
+                    context->SetArgObject(i, (void*)&parameters[i].GetMatrix3x4());
+                    break;
+
+                case VAR_MATRIX4:
+                    context->SetArgObject(i, (void*)&parameters[i].GetMatrix4());
+                    break;
+
+                case VAR_RESOURCEREF:
+                    context->SetArgObject(i, (void*)&parameters[i].GetResourceRef());
+                    break;
+
+                case VAR_RESOURCEREFLIST:
+                    context->SetArgObject(i, (void*)&parameters[i].GetResourceRefList());
+                    break;
+
                 case VAR_VOIDPTR:
                 case VAR_VOIDPTR:
                     context->SetArgObject(i, parameters[i].GetVoidPtr());
                     context->SetArgObject(i, parameters[i].GetVoidPtr());
                     break;
                     break;

+ 3 - 3
Source/Urho3D/Graphics/Light.h

@@ -195,7 +195,7 @@ public:
     void SetShadowCascade(const CascadeParameters& parameters);
     void SetShadowCascade(const CascadeParameters& parameters);
     /// Set shadow map focusing parameters.
     /// Set shadow map focusing parameters.
     void SetShadowFocus(const FocusParameters& parameters);
     void SetShadowFocus(const FocusParameters& parameters);
-    /// Set shadow intensity between 0.0 - 1.0. 0.0 (the default) gives fully dark shadows.
+    /// Set light intensity in shadow between 0.0 - 1.0. 0.0 (the default) gives fully dark shadows.
     void SetShadowIntensity(float intensity);
     void SetShadowIntensity(float intensity);
     /// Set shadow resolution between 0.25 - 1.0. Determines the shadow map to use.
     /// Set shadow resolution between 0.25 - 1.0. Determines the shadow map to use.
     void SetShadowResolution(float resolution);
     void SetShadowResolution(float resolution);
@@ -251,7 +251,7 @@ public:
     /// Return shadow map focus parameters.
     /// Return shadow map focus parameters.
     const FocusParameters& GetShadowFocus() const { return shadowFocus_; }
     const FocusParameters& GetShadowFocus() const { return shadowFocus_; }
 
 
-    /// Return shadow intensity.
+    /// Return light intensity in shadow.
     float GetShadowIntensity() const { return shadowIntensity_; }
     float GetShadowIntensity() const { return shadowIntensity_; }
 
 
     /// Return shadow resolution.
     /// Return shadow resolution.
@@ -338,7 +338,7 @@ private:
     float fadeDistance_;
     float fadeDistance_;
     /// Shadow fade start distance.
     /// Shadow fade start distance.
     float shadowFadeDistance_;
     float shadowFadeDistance_;
-    /// Shadow intensity.
+    /// Light intensity in shadow.
     float shadowIntensity_;
     float shadowIntensity_;
     /// Shadow resolution.
     /// Shadow resolution.
     float shadowResolution_;
     float shadowResolution_;

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

@@ -2468,6 +2468,9 @@ void Graphics::Restore()
             URHO3D_LOGERROR("OpenGL 2.0 is required");
             URHO3D_LOGERROR("OpenGL 2.0 is required");
             return;
             return;
         }
         }
+
+        // Enable seamless cubemap if possible
+        glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
 #endif
 #endif
 
 
         // Set up texture data read/write alignment. It is important that this is done before uploading any texture data
         // Set up texture data read/write alignment. It is important that this is done before uploading any texture data

+ 60 - 52
Source/Urho3D/Graphics/Renderer.cpp

@@ -639,60 +639,17 @@ void Renderer::Update(float timeStep)
     for (unsigned i = viewports_.Size() - 1; i < viewports_.Size(); --i)
     for (unsigned i = viewports_.Size() - 1; i < viewports_.Size(); --i)
         QueueViewport(0, viewports_[i]);
         QueueViewport(0, viewports_[i]);
 
 
-    // Gather other render surfaces that are autoupdated
-    SendEvent(E_RENDERSURFACEUPDATE);
-
-    // Process gathered views. This may queue further views (render surfaces that are only updated when visible)
-    for (unsigned i = 0; i < queuedViewports_.Size(); ++i)
-    {
-        WeakPtr<RenderSurface>& renderTarget = queuedViewports_[i].first_;
-        WeakPtr<Viewport>& viewport = queuedViewports_[i].second_;
-
-        // Null pointer means backbuffer view. Differentiate between that and an expired rendersurface
-        if ((renderTarget.NotNull() && renderTarget.Expired()) || viewport.Expired())
-            continue;
-
-        // (Re)allocate the view structure if necessary
-        if (!viewport->GetView() || resetViews_)
-            viewport->AllocateView();
-
-        View* view = viewport->GetView();
-        assert(view);
-        // Check if view can be defined successfully (has either valid scene, camera and octree, or no scene passes)
-        if (!view->Define(renderTarget, viewport))
-            continue;
+    // Update main viewports. This may queue further views
+    unsigned numMainViewports = queuedViewports_.Size();
+    for (unsigned i = 0; i < numMainViewports; ++i)
+        UpdateQueuedViewport(i);
 
 
-        views_.Push(WeakPtr<View>(view));
-
-        const IntRect& viewRect = viewport->GetRect();
-        Scene* scene = viewport->GetScene();
-        if (!scene)
-            continue;
-
-        Octree* octree = scene->GetComponent<Octree>();
-
-        // Update octree (perform early update for drawables which need that, and reinsert moved drawables.)
-        // However, if the same scene is viewed from multiple cameras, update the octree only once
-        if (!updatedOctrees_.Contains(octree))
-        {
-            frame_.camera_ = viewport->GetCamera();
-            frame_.viewSize_ = viewRect.Size();
-            if (frame_.viewSize_ == IntVector2::ZERO)
-                frame_.viewSize_ = IntVector2(graphics_->GetWidth(), graphics_->GetHeight());
-            octree->Update(frame_);
-            updatedOctrees_.Insert(octree);
-
-            // Set also the view for the debug renderer already here, so that it can use culling
-            /// \todo May result in incorrect debug geometry culling if the same scene is drawn from multiple viewports
-            DebugRenderer* debug = scene->GetComponent<DebugRenderer>();
-            if (debug && viewport->GetDrawDebug())
-                debug->SetView(viewport->GetCamera());
-        }
+    // Gather queued & autoupdated render surfaces
+    SendEvent(E_RENDERSURFACEUPDATE);
 
 
-        // Update view. This may queue further views. View will send update begin/end events once its state is set
-        ResetShadowMapAllocations(); // Each view can reuse the same shadow maps
-        view->Update(frame_);
-    }
+    // Update viewports that were added as result of the event above
+    for (unsigned i = numMainViewports; i < queuedViewports_.Size(); ++i)
+        UpdateQueuedViewport(i);
 
 
     queuedViewports_.Clear();
     queuedViewports_.Clear();
     resetViews_ = false;
     resetViews_ = false;
@@ -1471,6 +1428,57 @@ const Rect& Renderer::GetLightScissor(Light* light, Camera* camera)
     }
     }
 }
 }
 
 
+void Renderer::UpdateQueuedViewport(unsigned index)
+{
+    WeakPtr<RenderSurface>& renderTarget = queuedViewports_[index].first_;
+    WeakPtr<Viewport>& viewport = queuedViewports_[index].second_;
+
+    // Null pointer means backbuffer view. Differentiate between that and an expired rendersurface
+    if ((renderTarget.NotNull() && renderTarget.Expired()) || viewport.Expired())
+        return;
+
+    // (Re)allocate the view structure if necessary
+    if (!viewport->GetView() || resetViews_)
+        viewport->AllocateView();
+
+    View* view = viewport->GetView();
+    assert(view);
+    // Check if view can be defined successfully (has either valid scene, camera and octree, or no scene passes)
+    if (!view->Define(renderTarget, viewport))
+        return;
+
+    views_.Push(WeakPtr<View>(view));
+
+    const IntRect& viewRect = viewport->GetRect();
+    Scene* scene = viewport->GetScene();
+    if (!scene)
+        return;
+
+    Octree* octree = scene->GetComponent<Octree>();
+
+    // Update octree (perform early update for drawables which need that, and reinsert moved drawables.)
+    // However, if the same scene is viewed from multiple cameras, update the octree only once
+    if (!updatedOctrees_.Contains(octree))
+    {
+        frame_.camera_ = viewport->GetCamera();
+        frame_.viewSize_ = viewRect.Size();
+        if (frame_.viewSize_ == IntVector2::ZERO)
+            frame_.viewSize_ = IntVector2(graphics_->GetWidth(), graphics_->GetHeight());
+        octree->Update(frame_);
+        updatedOctrees_.Insert(octree);
+
+        // Set also the view for the debug renderer already here, so that it can use culling
+        /// \todo May result in incorrect debug geometry culling if the same scene is drawn from multiple viewports
+        DebugRenderer* debug = scene->GetComponent<DebugRenderer>();
+        if (debug && viewport->GetDrawDebug())
+            debug->SetView(viewport->GetCamera());
+    }
+
+    // Update view. This may queue further views. View will send update begin/end events once its state is set
+    ResetShadowMapAllocations(); // Each view can reuse the same shadow maps
+    view->Update(frame_);
+}
+
 void Renderer::PrepareViewRender()
 void Renderer::PrepareViewRender()
 {
 {
     ResetScreenBufferAllocations();
     ResetScreenBufferAllocations();

+ 3 - 1
Source/Urho3D/Graphics/Renderer.h

@@ -411,6 +411,8 @@ private:
     void CreateInstancingBuffer();
     void CreateInstancingBuffer();
     /// Create point light shadow indirection texture data.
     /// Create point light shadow indirection texture data.
     void SetIndirectionTextureData();
     void SetIndirectionTextureData();
+    /// Update a queued viewport for rendering.
+    void UpdateQueuedViewport(unsigned index);
     /// Prepare for rendering of a new view.
     /// Prepare for rendering of a new view.
     void PrepareViewRender();
     void PrepareViewRender();
     /// Remove unused occlusion and screen buffers.
     /// Remove unused occlusion and screen buffers.
@@ -429,7 +431,7 @@ private:
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     /// Handle render update event.
     /// Handle render update event.
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
-    /// Blur the shadow map
+    /// Blur the shadow map.
     void BlurShadowMap(View* view, Texture2D* shadowMap);
     void BlurShadowMap(View* view, Texture2D* shadowMap);
 
 
     /// Graphics subsystem.
     /// Graphics subsystem.

+ 51 - 62
bin/CoreData/Shaders/GLSL/IBL.glsl

@@ -1,39 +1,40 @@
 #line 10001
 #line 10001
 #ifdef COMPILEPS
 #ifdef COMPILEPS
-    #define PBRFAST
-
     vec3 ImportanceSampleSimple(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N)
     vec3 ImportanceSampleSimple(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N)
     {
     {
-      float a = roughness * roughness;
-      mat3 tbn = mat3(T, B, N);
-      #ifdef PBRFAST
-          const float blurFactor = 0.0;
-      #else
-          const float blurFactor = 5.0;
-      #endif
-      vec3 Xi3 = mix(vec3(0,0,1), normalize(vec3(Xi.xy * blurFactor , 1)), a);
-      vec3 XiWS = tbn * Xi3;
-      return normalize(N + XiWS);
+        float a = roughness * roughness;
+        mat3 tbn = mat3(T, B, N);
+        #ifdef IBLFAST
+            const float blurFactor = 0.0;
+        #else
+            const float blurFactor = 5.0;
+        #endif
+        vec2 xx = Xi.xy * blurFactor;
+        xx = xx - 1.0 * trunc(xx/1.0); // hlsl style modulo
+        vec3 Xi3 = mix(vec3(0,0,1), normalize(vec3(xx, 1.0)), a);
+        vec3 XiWS = tbn * Xi3;
+        return normalize(N + XiWS);
     }
     }
 
 
     // Karis '13
     // Karis '13
-    vec3 ImportanceSampleGGX(in vec2 Xi, in float roughness, in vec3 N)
+    vec3 ImportanceSampleGGX(in vec2 Xi, in float roughness, in vec3 T, in vec3 B, in vec3 N)
     {
     {
-       float a = roughness * roughness;
-       float Phi = 2.0 * M_PI * Xi.x;
-       float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
-       float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
-       vec3 H = vec3(0,0,0);
-       H.x = SinTheta * cos(Phi);
-       H.y = SinTheta * sin(Phi);
-       H.z = CosTheta;
-
-       vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
-       vec3 TangentX = normalize(cross(UpVector, N));
-       vec3 TangentY = cross(N, TangentX);
-       // Tangent to world space
-       return TangentX * H.x + TangentY * H.y + N * H.z;
+        float a = roughness * roughness;
+        float Phi = 2.0 * M_PI * Xi.x;
+        float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));
+        float SinTheta = sqrt(1.0 - CosTheta * CosTheta);
+        vec3 H = vec3(0,0,0);
+        H.x = SinTheta * cos(Phi);
+        H.y = SinTheta * sin(Phi);
+        H.z = CosTheta;
+
+        vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+        vec3 TangentX = normalize(cross(UpVector, N));
+        vec3 TangentY = cross(N, TangentX);
+        // Tangent to world space
+        return TangentX * H.x + TangentY * H.y + N * H.z;
     }
     }
+
     /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector
     /// Determine reflection vector based on surface roughness, rougher uses closer to the normal and smoother uses closer to the reflection vector
     ///     normal: surface normal
     ///     normal: surface normal
     ///     reflection: vector of reflection off of the surface
     ///     reflection: vector of reflection off of the surface
@@ -45,8 +46,14 @@
         return mix(normal, reflection, lerpFactor);
         return mix(normal, reflection, lerpFactor);
     }
     }
 
 
-    #define IMPORTANCE_SAMPLES 16
-    vec2 IMPORTANCE_KERNEL[IMPORTANCE_SAMPLES] = vec2[] (
+    #ifdef IBLFAST
+        #define IMPORTANCE_SAMPLES 1
+    #else
+        #define IMPORTANCE_SAMPLES 4
+    #endif
+
+    #define IMPORTANCE_KERNEL_SIZE 16
+    vec2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] = vec2[] (
         vec2(-0.0780436, 0.0558389),
         vec2(-0.0780436, 0.0558389),
         vec2(0.034318, -0.0635879),
         vec2(0.034318, -0.0635879),
         vec2(0.00230821, 0.0807279),
         vec2(0.00230821, 0.0807279),
@@ -110,15 +117,12 @@
                 float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
                 float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
                 float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
                 float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
 
 
-                //if (ndl > 0.0)
-                {
-                    vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb;
+                vec3 sampledColor = textureLod(sZoneCubeMap, L, mipLevel).rgb;
 
 
-                    vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
-                    vec3 lightTerm = sampledColor;
+                vec3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+                vec3 lightTerm = sampledColor;
 
 
-                    diffuseFactor = lightTerm * diffuseTerm;
-                }
+                diffuseFactor = lightTerm * diffuseTerm;
             }
             }
 
 
             {
             {
@@ -134,30 +138,15 @@
                 float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
                 float ndh = clamp(abs(dot(N, H)), 0.0, 1.0);
                 float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
                 float ndl = clamp(abs(dot(N, L)), 0.0, 1.0);
 
 
-                vec3 specularTerm = vec3(0,0,0);
-                float pdf = 1.0;
-                vec3 lightTerm = vec3(0,0,0);
-
-                if (ndl > 0.05)
-                {
-                    vec3 fresnelTerm = Fresnel(specColor, vdh);
-                    float distTerm = 1.0; // Optimization, this term is mathematically cancelled out  -- Distribution(ndh, roughness);
-                    float visTerm = Visibility(ndl, ndv, rough);
-
-                    lightTerm = sampledColor * ndl;
-                    specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
-                    pdf = ImportanceSamplePDF(distTerm, ndh, vdh);
-                }
-                else // reduce artifacts at extreme grazing angles
-                {
-                    vec3 fresnelTerm = Fresnel(specColor, vdh);
-                    float distTerm = 1.0;//Distribution(ndh_, roughness);
-                    float visTerm = Visibility(ndl, ndv, rough);
-
-                    lightTerm = sampledColor * ndl;
-                    specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndl);
-                    pdf = 4.0;//ImportanceSamplePDF(distTerm, ndh, vdh);
-                }
+                vec3 fresnelTerm = Fresnel(specColor, vdh);
+                float distTerm = 1.0; // Optimization, this term is mathematically cancelled out  -- Distribution(ndh, roughness);
+                float visTerm = Visibility(ndl, ndv, rough);
+
+                vec3 lightTerm = sampledColor * ndl;
+
+                float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles
+
+                vec3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
 
 
                 // energy conservation:
                 // energy conservation:
                 // Specular conservation:
                 // Specular conservation:
@@ -201,7 +190,7 @@
                 const float rough = 1.0;
                 const float rough = 1.0;
                 const float mipLevel = 9.0;
                 const float mipLevel = 9.0;
 
 
-                vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, wsNormal);
+                vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal);
                 vec3 sampleVec = wsNormal + perturb; //perturb by the sample vector
                 vec3 sampleVec = wsNormal + perturb; //perturb by the sample vector
 
 
                 vec3 sampledColor = textureLod(sZoneCubeMap, sampleVec, mipLevel).rgb;
                 vec3 sampledColor = textureLod(sZoneCubeMap, sampleVec, mipLevel).rgb;
@@ -218,7 +207,7 @@
                 float rough = roughness;
                 float rough = roughness;
                 float mipLevel =  GetMipFromRougness(rough);
                 float mipLevel =  GetMipFromRougness(rough);
 
 
-                vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, reflectVec);
+                vec3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec);
                 vec3 sampleVec = reflectVec + perturb; //perturb by the sample vector
                 vec3 sampleVec = reflectVec + perturb; //perturb by the sample vector
 
 
                 vec3 sampledColor = textureCube(sZoneCubeMap, sampleVec, mipLevel).rgb;
                 vec3 sampledColor = textureCube(sZoneCubeMap, sampleVec, mipLevel).rgb;

+ 9 - 9
bin/CoreData/Shaders/GLSL/PBRDeferred.glsl

@@ -73,11 +73,11 @@ void PS()
         vec4 specularInput = texture2DProj(sSpecMap, vScreenPos);
         vec4 specularInput = texture2DProj(sSpecMap, vScreenPos);
     #endif
     #endif
 
 
-    vec3 normal = normalize(normalInput.rgb);
-    float roughness = depthInput.a;//length(normal);
-    //normal = normalize(normal);
+    vec3 normal = normalInput.rgb;
+    float roughness = length(normal);
+    normal = normalize(normal);
 
 
-    vec3 specColor = vec3(specularInput.a, albedoInput.a, normalInput.a);
+    vec3 specColor = specularInput.rgb;
 
 
     vec4 projWorldPos = vec4(worldPos, 1.0);
     vec4 projWorldPos = vec4(worldPos, 1.0);
 
 
@@ -99,13 +99,13 @@ void PS()
     #endif
     #endif
 
 
     vec3 toCamera = normalize(-worldPos);
     vec3 toCamera = normalize(-worldPos);
-    vec3 lightVec = lightDir;
+    vec3 lightVec = normalize(lightDir);
 
 
     vec3 Hn = normalize(toCamera + lightVec);
     vec3 Hn = normalize(toCamera + lightVec);
-    float vdh = max(M_EPSILON, dot(toCamera, Hn));
-    float ndh = max(M_EPSILON, dot(normal, Hn));
-    float ndl = max(M_EPSILON, dot(normal, lightVec));
-    float ndv = max(M_EPSILON, dot(normal, toCamera));
+    float vdh = clamp(abs(dot(toCamera, Hn)), M_EPSILON, 1.0);
+    float ndh = clamp(abs(dot(normal, Hn)), M_EPSILON, 1.0);
+    float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+    float ndv = clamp(abs(dot(normal, toCamera)), M_EPSILON, 1.0);
 
 
     vec3 diffuseFactor = BurleyDiffuse(albedoInput.rgb, roughness, ndv, ndl, vdh);
     vec3 diffuseFactor = BurleyDiffuse(albedoInput.rgb, roughness, ndv, ndl, vdh);
     vec3 specularFactor = vec3(0,0,0);
     vec3 specularFactor = vec3(0,0,0);

+ 10 - 9
bin/CoreData/Shaders/GLSL/PBRLitSolid.glsl

@@ -178,12 +178,13 @@ void PS()
         #endif
         #endif
 
 
         vec3 toCamera = normalize(cCameraPosPS - vWorldPos.xyz);
         vec3 toCamera = normalize(cCameraPosPS - vWorldPos.xyz);
+        vec3 lightVec = normalize(lightDir);
 
 
         vec3 Hn = normalize(toCamera + lightDir);
         vec3 Hn = normalize(toCamera + lightDir);
-        float vdh = max(M_EPSILON, dot(toCamera, Hn));
-        float ndh = max(M_EPSILON, dot(normal, Hn));
-        float ndl = max(M_EPSILON, dot(normal, lightDir));
-        float ndv = max(M_EPSILON, dot(normal, toCamera));
+        float vdh = clamp(abs(dot(toCamera, Hn)), M_EPSILON, 1.0);
+        float ndh = clamp(abs(dot(normal, Hn)), M_EPSILON, 1.0);
+        float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+        float ndv = clamp(abs(dot(normal, toCamera)), M_EPSILON, 1.0);
 
 
         vec3 diffuseFactor = BurleyDiffuse(diffColor.rgb, roughness, ndv, ndl, vdh);
         vec3 diffuseFactor = BurleyDiffuse(diffColor.rgb, roughness, ndv, ndl, vdh);
         vec3 specularFactor = vec3(0,0,0);
         vec3 specularFactor = vec3(0,0,0);
@@ -206,12 +207,12 @@ void PS()
             gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
             gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
         #endif
         #endif
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
-        // Fill deferred G-buffer'
+        // Fill deferred G-buffer
         const vec3 spareData = vec3(0,0,0); // Can be used to pass more data to deferred renderer
         const vec3 spareData = vec3(0,0,0); // Can be used to pass more data to deferred renderer
-        gl_FragData[0] = vec4(spareData, specColor.r);
-        gl_FragData[1] = vec4(diffColor.rgb, specColor.g);
-        gl_FragData[2] = vec4(normal, specColor.b);
-        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), roughness);
+        gl_FragData[0] = vec4(specColor, spareData.r);
+        gl_FragData[1] = vec4(diffColor.rgb, spareData.g);
+        gl_FragData[2] = vec4(normal * roughness, spareData.b);
+        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0);
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
         vec3 finalColor = vVertexLight * diffColor.rgb;
         vec3 finalColor = vVertexLight * diffColor.rgb;

+ 29 - 41
bin/CoreData/Shaders/HLSL/IBL.hlsl

@@ -1,20 +1,22 @@
 #ifdef COMPILEPS
 #ifdef COMPILEPS
+    //#define IBLFAST
+
     float3 ImportanceSampleSimple(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N)
     float3 ImportanceSampleSimple(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N)
     {
     {
         const float a = roughness * roughness;
         const float a = roughness * roughness;
         const float3x3 tbn = float3x3(T, B, N);
         const float3x3 tbn = float3x3(T, B, N);
-        #if defined(PBRFAST)
+        #ifdef IBLFAST
             const float blurFactor = 0.0;
             const float blurFactor = 0.0;
         #else
         #else
             const float blurFactor = 5.0;
             const float blurFactor = 5.0;
         #endif
         #endif
-        const float3 Xi3 = lerp(float3(0,0,1), normalize(float3(Xi.xy * blurFactor , 1)), a);
+        const float3 Xi3 = lerp(float3(0,0,1), normalize(float3(Xi.xy * blurFactor % 1.0 , 1.0)), a);
         const float3 XiWS = mul(Xi3, tbn);
         const float3 XiWS = mul(Xi3, tbn);
         return normalize(N + XiWS);
         return normalize(N + XiWS);
     }
     }
 
 
     // Karis '13
     // Karis '13
-    float3 ImportanceSampleGGX(in float2 Xi, in float roughness, in float3 N)
+    float3 ImportanceSampleGGX(in float2 Xi, in float roughness, in float3 T, in float3 B, in float3 N)
     {
     {
         float a = roughness * roughness;
         float a = roughness * roughness;
         float Phi = 2.0 * M_PI * Xi.x;
         float Phi = 2.0 * M_PI * Xi.x;
@@ -43,8 +45,14 @@
         return lerp(normal, reflection, lerpFactor);
         return lerp(normal, reflection, lerpFactor);
     }
     }
 
 
-    #define IMPORTANCE_SAMPLES 16
-    static const float2 IMPORTANCE_KERNEL[IMPORTANCE_SAMPLES] =
+    #ifdef IBLFAST
+        #define IMPORTANCE_SAMPLES 1
+    #else
+        #define IMPORTANCE_SAMPLES 16
+    #endif
+
+    #define IMPORTANCE_KERNEL_SIZE 16
+    static const float2 IMPORTANCE_KERNEL[IMPORTANCE_KERNEL_SIZE] =
     {
     {
         float2(-0.0780436, 0.0558389),
         float2(-0.0780436, 0.0558389),
         float2(0.034318, -0.0635879),
         float2(0.034318, -0.0635879),
@@ -110,15 +118,12 @@
                 const float ndh = saturate(abs(dot(N, H)));
                 const float ndh = saturate(abs(dot(N, H)));
                 const float ndl = saturate(abs(dot(N, L)));
                 const float ndl = saturate(abs(dot(N, L)));
 
 
-                //if (ndl > 0.0)
-                {
-                    const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel));
+                const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(L, mipLevel));
 
 
-                    const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
-                    const float3 lightTerm = sampledColor;
+                const float3 diffuseTerm = Diffuse(diffColor, rough, ndv, ndl, vdh);
+                const float3 lightTerm = sampledColor;
 
 
-                    diffuseFactor = lightTerm * diffuseTerm;
-                }
+                diffuseFactor = lightTerm * diffuseTerm;
             }
             }
 
 
             {
             {
@@ -134,38 +139,21 @@
                 const float ndh = saturate(abs(dot(N, H)));
                 const float ndh = saturate(abs(dot(N, H)));
                 const float ndl = saturate(abs(dot(N, L)));
                 const float ndl = saturate(abs(dot(N, L)));
 
 
-                float3 specularTerm = 0.0;
-                float pdf = 1.0;
-                float3 lightTerm = 0.0;
-
-                if (ndl > 0.05)
-                {
-                    const float3 fresnelTerm = Fresnel(specColor, vdh);
-                    const float distTerm = 1.0; // Optimization, this term is mathematically cancelled out  -- Distribution(ndh, roughness);
-                    const float visTerm = Visibility(ndl, ndv, rough);
-
-                    lightTerm = sampledColor * ndl;
-                    specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
-                    pdf = ImportanceSamplePDF(distTerm, ndh, vdh);
-                }
-                else // reduce artifacts at extreme grazing angles
-                {
-                    const float3 fresnelTerm = Fresnel(specColor, vdh);
-                    const float distTerm = 1.0;//Distribution(ndh_, roughness);
-                    const float visTerm = Visibility(ndl, ndv, rough);
-
-                    lightTerm = sampledColor * ndl;
-                    specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndl);
-                    pdf = 4.0;//ImportanceSamplePDF(distTerm, ndh, vdh);
-                }
-
-                // energy conservation:
+                const float3 fresnelTerm = Fresnel(specColor, vdh);
+                const float distTerm = 1.0;//Distribution(ndh_, roughness);
+                const float visTerm = Visibility(ndl, ndv, rough);
+                const float3 lightTerm = sampledColor * ndl;
+
+                const float pdf = ndl > 0.05 ? ImportanceSamplePDF(distTerm, ndh, vdh) : 4.0; // reduce artifacts at extreme grazing angles
+
+                const float3 specularTerm = SpecularBRDF(distTerm, fresnelTerm, visTerm, ndl, ndv);
+
+                // Energy conservation:
                 // Specular conservation:
                 // Specular conservation:
                 specularFactor = lightTerm * specularTerm / pdf;
                 specularFactor = lightTerm * specularTerm / pdf;
                 specularFactor = max(saturate(normalize(specularFactor) * (length(sampledColor * specColor))), specularFactor);
                 specularFactor = max(saturate(normalize(specularFactor) * (length(sampledColor * specColor))), specularFactor);
 
 
                 // Diffuse conservation:
                 // Diffuse conservation:
-                //kd = (sampledColor * specColor)/specularFactor; //energy conservation
                 kd = 1.0 - specularFactor;
                 kd = 1.0 - specularFactor;
             }
             }
 
 
@@ -199,7 +187,7 @@
                 const float rough = 1.0;
                 const float rough = 1.0;
                 const float mipLevel = 9.0;
                 const float mipLevel = 9.0;
 
 
-                const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, wsNormal);
+                const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, wsNormal);
                 const float3 sampleVec = wsNormal + perturb; //perturb by the sample vector
                 const float3 sampleVec = wsNormal + perturb; //perturb by the sample vector
 
 
                 const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));
                 const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));
@@ -216,7 +204,7 @@
                 const float rough = roughness;
                 const float rough = roughness;
                 const float mipLevel =  GetMipFromRougness(rough);
                 const float mipLevel =  GetMipFromRougness(rough);
 
 
-                const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, reflectVec);
+                const float3 perturb = ImportanceSampleGGX(IMPORTANCE_KERNEL[i].xy, rough, tangent, bitangent, reflectVec);
                 const float3 sampleVec = reflectVec + perturb; //perturb by the sample vector
                 const float3 sampleVec = reflectVec + perturb; //perturb by the sample vector
 
 
                 const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));
                 const float3 sampledColor = SampleCubeLOD(ZoneCubeMap, float4(sampleVec, mipLevel));

+ 5 - 5
bin/CoreData/Shaders/HLSL/PBRDeferred.hlsl

@@ -84,7 +84,7 @@ void PS(
     const float roughness = length(normal);
     const float roughness = length(normal);
     normal = normalize(normal);
     normal = normalize(normal);
 
 
-    const float3 specColor = float3(specularInput.a, albedoInput.a, normalInput.a);
+    const float3 specColor = specularInput.rgb;
 
 
     const float4 projWorldPos = float4(worldPos, 1.0);
     const float4 projWorldPos = float4(worldPos, 1.0);
 
 
@@ -108,10 +108,10 @@ void PS(
     const float3 lightVec = normalize(lightDir);
     const float3 lightVec = normalize(lightDir);
 
 
     const float3 Hn = normalize(toCamera + lightVec);
     const float3 Hn = normalize(toCamera + lightVec);
-    const float vdh = max(M_EPSILON, dot(toCamera, Hn));
-    const float ndh = max(M_EPSILON, dot(normal, Hn));
-    const float ndl = max(M_EPSILON, dot(normal, lightVec));
-    const float ndv = max(M_EPSILON, dot(normal, toCamera));
+    const float vdh = clamp(abs(dot(toCamera, Hn)), M_EPSILON, 1.0);
+    const float ndh = clamp(abs(dot(normal, Hn)), M_EPSILON, 1.0);
+    const float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+    const float ndv = clamp(abs(dot(normal, toCamera)), M_EPSILON, 1.0);
 
 
     const float3 diffuseFactor = BurleyDiffuse(albedoInput.rgb, roughness, ndv, ndl, vdh);
     const float3 diffuseFactor = BurleyDiffuse(albedoInput.rgb, roughness, ndv, ndl, vdh);
     float3 specularFactor = 0;
     float3 specularFactor = 0;

+ 8 - 7
bin/CoreData/Shaders/HLSL/PBRLitSolid.hlsl

@@ -263,12 +263,13 @@ void PS(
         #endif
         #endif
 
 
         const float3 toCamera = normalize(cCameraPosPS - iWorldPos.xyz);
         const float3 toCamera = normalize(cCameraPosPS - iWorldPos.xyz);
+        const float3 lightVec = normalize(lightDir);
 
 
         const float3 Hn = normalize(toCamera + lightDir);
         const float3 Hn = normalize(toCamera + lightDir);
-        const float vdh = max(M_EPSILON, dot(toCamera, Hn));
-        const float ndh = max(M_EPSILON, dot(normal, Hn));
-        const float ndl = max(M_EPSILON, dot(normal, lightDir));
-        const float ndv = max(M_EPSILON, dot(normal, toCamera));
+        const float vdh = clamp(abs(dot(toCamera, Hn)), M_EPSILON, 1.0);
+        const float ndh = clamp(abs(dot(normal, Hn)), M_EPSILON, 1.0);
+        const float ndl = clamp(abs(dot(normal, lightVec)), M_EPSILON, 1.0);
+        const float ndv = clamp(abs(dot(normal, toCamera)), M_EPSILON, 1.0);
 
 
         const float3 diffuseFactor = BurleyDiffuse(diffColor.rgb, roughness, ndv, ndl, vdh);
         const float3 diffuseFactor = BurleyDiffuse(diffColor.rgb, roughness, ndv, ndl, vdh);
         float3 specularFactor = 0;
         float3 specularFactor = 0;
@@ -293,9 +294,9 @@ void PS(
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         // Fill deferred G-buffer
         // Fill deferred G-buffer
         const float3 spareData = 0; // Can be used to pass more data to deferred renderer
         const float3 spareData = 0; // Can be used to pass more data to deferred renderer
-        oColor = float4(spareData, specColor.r);
-        oAlbedo = float4(diffColor.rgb, specColor.g);
-        oNormal = float4(normalize(normal) * roughness, specColor.b);
+        oColor = float4(specColor, spareData.r);
+        oAlbedo = float4(diffColor.rgb, spareData.g);
+        oNormal = float4(normalize(normal) * roughness, spareData.b);
         oDepth = iWorldPos.w;
         oDepth = iWorldPos.w;
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting

+ 5 - 6
bin/CoreData/Techniques/PBR/DiffNormalSpecEmissive.xml

@@ -1,9 +1,8 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP">
-    <pass name="base" psdefines="EMISSIVEMAP" />
-    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP SPECMAP" depthtest="equal" depthwrite="false" blend="add" />
-    <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP SPECMAP" />
-    <pass name="material" psdefines="MATERIAL SPECMAP EMISSIVEMAP" depthtest="equal" depthwrite="false" />
-    <pass name="deferred" vsdefines="NORMALMAP" psdefines="DEFERRED NORMALMAP SPECMAP EMISSIVEMAP" />
+<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP NORMALMAP SPECMAP EMISSIVEMAP">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />>
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 3 - 3
bin/CoreData/Techniques/PBR/DiffNormalSpecEmissiveAlpha.xml

@@ -1,5 +1,5 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP">
-    <pass name="alpha" psdefines="EMISSIVEMAP" depthwrite="false" blend="alpha" />
-    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP SPECMAP" depthwrite="false" blend="addalpha" />
+<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP SPECMAP EMISSIVEMAP NORMALMAP">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 2 - 2
bin/CoreData/Techniques/PBR/PBRDiffNormal.xml

@@ -1,6 +1,6 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP PBR IBL">
     <pass name="base" />
     <pass name="base" />
-    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
     <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
     <pass name="deferred" psdefines="DEFERRED" blend="add" />
     <pass name="deferred" psdefines="DEFERRED" blend="add" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />

+ 2 - 2
bin/CoreData/Techniques/PBR/PBRDiffNormalAlpha.xml

@@ -1,5 +1,5 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP PBR IBL">
     <pass name="alpha" depthwrite="false" blend="alpha" />
     <pass name="alpha" depthwrite="false" blend="alpha" />
-    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthwrite="false" blend="addalpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 4 - 4
bin/CoreData/Techniques/PBR/PBRDiffNormalEmissive.xml

@@ -1,7 +1,7 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
-    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
-    <pass name="material" psdefines="MATERIAL EMISSIVEMAP" depthtest="equal" depthwrite="false" />
-    <pass name="deferred" psdefines="DEFERRED EMISSIVEMAP" blend="add" />
+<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL">
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 3 - 3
bin/CoreData/Techniques/PBR/PBRDiffNormalEmissiveAlpha.xml

@@ -1,5 +1,5 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP PBR IBL">
-    <pass name="alpha" psdefines="EMISSIVEMAP" depthwrite="false" blend="alpha" />
-    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthwrite="false" blend="addalpha" />
+<technique vs="PBRLitSolid" ps="PBRLitSolid"  vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 2 - 2
bin/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpec.xml

@@ -1,7 +1,7 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="NORMALMAP IBL" psdefines="NORMALMAP DIFFMAP METALLIC ROUGHNESS PBR IBL">
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="NORMALMAP DIFFMAP METALLIC ROUGHNESS PBR IBL">
     <pass name="base" />
     <pass name="base" />
     <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
-    <pass name="material" psdefines="MATERIAL NORMALMAP" depthtest="equal" depthwrite="false" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
     <pass name="deferred" psdefines="DEFERRED" blend="add"/>
     <pass name="deferred" psdefines="DEFERRED" blend="add"/>
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />

+ 5 - 5
bin/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissive.xml

@@ -1,8 +1,8 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="NORMALMAP IBL" psdefines="NORMALMAP DIFFMAP METALLIC ROUGHNESS PBR IBL">
-    <pass name="base" psdefines="EMISSIVEMAP"/>
-    <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
-    <pass name="material" psdefines="MATERIAL EMISSIVEMAP NORMALMAP" depthtest="equal" depthwrite="false" />
-    <pass name="deferred" psdefines="DEFERRED EMISSIVEMAP NORMALMAP" blend="add"/>
+<technique vs="PBRLitSolid" ps="PBRLitSolid" vsdefines="IBL" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP METALLIC ROUGHNESS PBR IBL">
+    <pass name="base" />
+    <pass name="light" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="material" psdefines="MATERIAL" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" psdefines="DEFERRED" blend="add"/>
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 3 - 3
bin/CoreData/Techniques/PBR/PBRMetallicRoughDiffNormalSpecEmissiveAlpha.xml

@@ -1,5 +1,5 @@
-<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP PBR IBL METALLIC ROUGHNESS">
-    <pass name="alpha" psdefines="EMISSIVEMAP" depthwrite="false" blend="alpha" />
-    <pass name="litalpha" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthwrite="false" blend="addalpha" />
+<technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP NORMALMAP EMISSIVEMAP PBR IBL METALLIC ROUGHNESS">
+    <pass name="alpha" depthwrite="false" blend="alpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>

+ 1 - 1
bin/CoreData/Techniques/PBR/PBRMetallicRoughDiffSpecAlpha.xml

@@ -1,5 +1,5 @@
 <technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP PBR IBL METALLIC ROUGHNESS">
 <technique vs="PBRLitSolid" ps="PBRLitSolid" psdefines="DIFFMAP PBR IBL METALLIC ROUGHNESS">
     <pass name="alpha" depthwrite="false" blend="alpha" />
     <pass name="alpha" depthwrite="false" blend="alpha" />
-    <pass name="litalpha" psdefines="METALLIC ROUGHNESS" depthwrite="false" blend="addalpha" />
+    <pass name="litalpha" depthwrite="false" blend="addalpha" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
 </technique>
 </technique>