Browse Source

Refactored & unified viewport handling. Now RenderSurfaces also set a viewport. Exposed Viewport struct to script.
Fixed missing auxiliary view rendering if camera is the same as in another view.
DebugRenderer takes a pointer to Pipeline when it's time to render, instead of storing subsystem pointers permanently.
Removed unnecessary includes.
Fixed profiling block names.

Lasse Öörni 15 years ago
parent
commit
cbbd044d95

+ 17 - 4
Bin/Data/Scripts/GraphicsTest.as

@@ -378,9 +378,22 @@ void createCamera()
     cameraLight.setRampTexture(cache.getResource("Texture2D", "Textures/RampWide.png"));
     cameraLight.setSpotTexture(cache.getResource("Texture2D", "Textures/SpotWide.png"));
     camera.addChild(cameraLight);
-    
-    // Set zero screen rect -> follow the window size
-    pipeline.setViewport(0, testScene, camera, IntRect(0, 0, 0, 0));
+
+    pipeline.setViewport(0, Viewport(testScene, camera));
+
+    /*
+    // Auxiliary view test
+    const int D3DFMT_A8R8G8B8 = 21;
+
+    Texture2D@ rtTex = Texture2D(TEXTURE_RENDERTARGET, "RTT");
+    rtTex.setSize(512, 512, D3DFMT_A8R8G8B8);
+    rtTex.getRenderSurface().setViewport(Viewport(testScene, camera));
+    rtTex.setBackupTexture(cache.getResource("Texture2D", "Textures/Diffuse.dds"));
+
+    Material@ mat = cache.getResource("Material", "Materials/Test.xml");
+    MaterialTechnique@ tech = mat.getTechnique(0);
+    tech.setTexture(TU_DIFFUSE, rtTex);
+    */
 }
 
 void handleUpdate(StringHash eventType, VariantMap& eventData)
@@ -496,7 +509,7 @@ void handleUpdate(StringHash eventType, VariantMap& eventData)
         {
             drawdebug++;
             if (drawdebug > 2) 
-                drawdebug = 0;                        
+                drawdebug = 0;
             pipeline.setDrawDebugGeometry(drawdebug == 1);
             testScene.getPhysicsWorld().setDrawDebugGeometry(drawdebug == 2);
         }

+ 5 - 2
Bin/Data/Scripts/NinjaSnowWar.as

@@ -100,9 +100,12 @@ void createCamera()
     gameCamera.setFarClip(16000.0);
     gameCamera.setPosition(Vector3(0, 200, -1000));
 
-    // Set zero screen rect -> follow the window size
     if (!engine.isHeadless())
-        pipeline.setViewport(0, gameScene, gameCamera, IntRect(0, 0, 0, 0));
+    {
+        pipeline.setNumViewports(2);
+        pipeline.setViewport(0, Viewport(gameScene, gameCamera));
+        pipeline.setViewport(1, Viewport(gameScene, gameCamera, IntRect(10, 10, 330, 210)));
+    }
 }
 
 void createOverlays()

+ 0 - 1
Engine/Common/EventListener.cpp

@@ -22,7 +22,6 @@
 //
 
 #include "Precompiled.h"
-#include "EventListener.h"
 #include "Log.h"
 #include "Profiler.h"
 #include "StringUtils.h"

+ 0 - 1
Engine/Engine/Console.cpp

@@ -22,7 +22,6 @@
 //
 
 #include "Precompiled.h"
-#include "BorderImage.h"
 #include "Console.h"
 #include "Engine.h"
 #include "Font.h"

+ 1 - 1
Engine/Engine/Engine.cpp

@@ -309,7 +309,7 @@ SharedPtr<Scene> Engine::createScene(const std::string& name, const BoundingBox&
     // Add debug rendering if not headless
     if (!mHeadless)
     {
-        DebugRenderer* debug = new DebugRenderer(mRenderer, mCache);
+        DebugRenderer* debug = new DebugRenderer();
         scene->addExtension(debug);
     }
     

+ 0 - 1
Engine/Engine/RegisterAudio.cpp

@@ -23,7 +23,6 @@
 
 #include "Precompiled.h"
 #include "Audio.h"
-#include "Engine.h"
 #include "PositionalChannel.h"
 #include "RegisterTemplates.h"
 #include "Song.h"

+ 0 - 1
Engine/Engine/RegisterEngine.cpp

@@ -27,7 +27,6 @@
 #include "Console.h"
 #include "Connection.h"
 #include "DebugHud.h"
-#include "Engine.h"
 #include "ParticleEmitter.h"
 #include "RegisterTemplates.h"
 #include "Scene.h"

+ 0 - 1
Engine/Engine/RegisterInput.cpp

@@ -23,7 +23,6 @@
 
 #include "Precompiled.h"
 #include "Controls.h"
-#include "Engine.h"
 #include "Input.h"
 #include "RegisterTemplates.h"
 

+ 62 - 10
Engine/Engine/RegisterRenderer.cpp

@@ -27,7 +27,6 @@
 #include "AnimationState.h"
 #include "BillboardSet.h"
 #include "DebugRenderer.h"
-#include "Engine.h"
 #include "InstancedModel.h"
 #include "Light.h"
 #include "Material.h"
@@ -98,7 +97,6 @@ static void registerCamera(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Camera", "Vector3 getUpVector()", asMETHOD(Camera, getUpVector), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "float getDistance(const Vector3& in)", asMETHOD(Camera, getDistance), asCALL_THISCALL);
     engine->RegisterObjectMethod("Camera", "float getDistanceSquared(const Vector3& in)", asMETHOD(Camera, getDistanceSquared), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Camera", "bool isInView(uint) const", asMETHOD(Camera, isInView), asCALL_THISCALL);
     registerRefCasts<Component, Camera>(engine, "Component", "Camera");
     registerRefCasts<Node, Camera>(engine, "Node", "Camera");
 }
@@ -127,6 +125,51 @@ static void registerSkeleton(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Skeleton", "Bone@+ getBone(const string& in) const", asMETHODPR(Skeleton, getBone, (const std::string&) const, Bone*), asCALL_THISCALL);
 }
 
+static void ConstructViewport(Viewport* ptr)
+{
+    new(ptr) Viewport();
+}
+
+static void ConstructViewportCopy(const Viewport& viewport, Viewport* ptr)
+{
+    new(ptr) Viewport(viewport);
+}
+
+static void ConstructViewportSceneCamera(Scene* scene, Camera* camera, Viewport* ptr)
+{
+    new(ptr) Viewport(scene, camera);
+}
+
+static void ConstructViewportSceneCameraRect(Scene* scene, Camera* camera, const IntRect& rect, Viewport* ptr)
+{
+    new(ptr) Viewport(scene, camera, rect);
+}
+
+static void DestructViewport(Viewport* ptr)
+{
+    ptr->~Viewport();
+}
+
+static void ViewportSetScene(Scene* scene, Viewport* ptr)
+{
+    ptr->mScene = scene;
+}
+
+static void ViewportSetCamera(Camera* camera, Viewport* ptr)
+{
+    ptr->mCamera = camera;
+}
+
+static Scene* ViewportGetScene(Viewport* ptr)
+{
+    return ptr->mScene;
+}
+
+static Camera* ViewportGetCamera(Viewport* ptr)
+{
+    return ptr->mCamera;
+}
+
 static Texture2D* ConstructTexture2D(TextureUsage usage, const std::string& name)
 {
     TRY_CONSTRUCT(new Texture2D(getEngine()->getRenderer(), usage, name));
@@ -194,17 +237,30 @@ static void registerTexture(asIScriptEngine* engine)
     registerTexture<Texture>(engine, "Texture");
     registerRefCasts<Resource, Texture>(engine, "Resource", "Texture");
     
+    engine->RegisterObjectType("Viewport", sizeof(Viewport), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
+    engine->RegisterObjectBehaviour("Viewport", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructViewport), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Viewport", asBEHAVE_CONSTRUCT, "void f(const Viewport& in)", asFUNCTION(ConstructViewportCopy), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Viewport", asBEHAVE_CONSTRUCT, "void f(Scene@+, Camera@+)", asFUNCTION(ConstructViewportSceneCamera), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Viewport", asBEHAVE_CONSTRUCT, "void f(Scene@+, Camera@+, const IntRect& in)", asFUNCTION(ConstructViewportSceneCameraRect), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Viewport", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructViewport), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Viewport", "Viewport &opAssign(const Viewport& in)", asMETHOD(Viewport, operator =), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Viewport", "void set_scene(Scene@+)", asFUNCTION(ViewportSetScene), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Viewport", "void set_camera(Camera@+)", asFUNCTION(ViewportSetCamera), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Viewport", "Scene@+ get_scene() const", asFUNCTION(ViewportGetScene), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Viewport", "Camera@+ get_camera() const", asFUNCTION(ViewportGetCamera), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectProperty("Viewport", "IntRect rect", offsetof(Viewport, mRect));
+    
     engine->RegisterObjectType("RenderSurface", 0, asOBJ_REF);
     engine->RegisterObjectBehaviour("RenderSurface", asBEHAVE_ADDREF, "void f()", asMETHOD(RenderSurface, addRef), asCALL_THISCALL);
     engine->RegisterObjectBehaviour("RenderSurface", asBEHAVE_RELEASE, "void f()", asMETHOD(RenderSurface, releaseRef), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RenderSurface", "void setCamera(Camera@+)", asMETHOD(RenderSurface, setCamera), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RenderSurface", "void setViewport(const Viewport& in)", asMETHOD(RenderSurface, setViewport), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "void setLinkedRenderTarget(RenderSurface@+)", asMETHOD(RenderSurface, setLinkedRenderTarget), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "void setLinkedDepthBuffer(RenderSurface@+)", asMETHOD(RenderSurface, setLinkedDepthBuffer), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "Texture@+ getParentTexture() const", asMETHOD(RenderSurface, getParentTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "int getWidth() const", asMETHOD(RenderSurface, getWidth), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "int getHeight() const", asMETHOD(RenderSurface, getHeight), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "TextureUsage getUsage() const", asMETHOD(RenderSurface, getUsage), asCALL_THISCALL);
-    engine->RegisterObjectMethod("RenderSurface", "Camera@+ getCamera() const", asMETHOD(RenderSurface, getCamera), asCALL_THISCALL);
+    engine->RegisterObjectMethod("RenderSurface", "const Viewport& getViewport() const", asMETHOD(RenderSurface, getViewport), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "RenderSurface@+ getLinkedRenderTarget() const", asMETHOD(RenderSurface, getLinkedRenderTarget), asCALL_THISCALL);
     engine->RegisterObjectMethod("RenderSurface", "RenderSurface@+ getLinkedDepthBuffer() const", asMETHOD(RenderSurface, getLinkedDepthBuffer), asCALL_THISCALL);
     
@@ -803,9 +859,7 @@ static void registerPipeline(asIScriptEngine* engine)
     engine->RegisterObjectBehaviour("Pipeline", asBEHAVE_ADDREF, "void f()", asMETHOD(Pipeline, addRef), asCALL_THISCALL);
     engine->RegisterObjectBehaviour("Pipeline", asBEHAVE_RELEASE, "void f()", asMETHOD(Pipeline, releaseRef), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "void setNumViewports(uint)", asMETHOD(Pipeline, setNumViewports), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "void setViewport(uint, Scene@+, Camera@+, const IntRect& in)", asMETHOD(Pipeline, setViewport), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "void setViewportCamera(uint, Camera@+)", asMETHOD(Pipeline, setViewportCamera), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "void setViewportScreenRect(uint, const IntRect& in)", asMETHOD(Pipeline, setViewportScreenRect), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Pipeline", "void setViewport(uint, const Viewport& in)", asMETHOD(Pipeline, setViewport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "void setSpecularLighting(bool)", asMETHOD(Pipeline, setSpecularLighting), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "void setDrawShadows(bool)", asMETHOD(Pipeline, setDrawShadows), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "void setTextureAnisotropy(int)", asMETHOD(Pipeline, setTextureAnisotropy), asCALL_THISCALL);
@@ -821,9 +875,7 @@ static void registerPipeline(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Pipeline", "void setEdgeFilter(const EdgeFilterParameters& in)", asMETHOD(Pipeline, setEdgeFilter), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "void setDrawDebugGeometry(bool)", asMETHOD(Pipeline, setDrawDebugGeometry), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "uint getNumViewports() const", asMETHOD(Pipeline, getNumViewports), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "Scene@+ getViewportScene(uint) const", asMETHOD(Pipeline, getViewportScene), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "Camera@+ getViewportCamera(uint) const", asMETHOD(Pipeline, getViewportCamera), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Pipeline", "IntRect getViewportScreenRect(uint) const", asMETHOD(Pipeline, getViewportScreenRect), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Pipeline", "const Viewport& getViewport(uint) const", asMETHOD(Pipeline, getViewport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "uint getFrameNumber() const", asMETHOD(Pipeline, getFrameNumber), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "float getElapsedTime() const", asMETHOD(Pipeline, getElapsedTime), asCALL_THISCALL);
     engine->RegisterObjectMethod("Pipeline", "bool getSpecularLighting() const", asMETHOD(Pipeline, getSpecularLighting), asCALL_THISCALL);

+ 0 - 1
Engine/Engine/RegisterResource.cpp

@@ -22,7 +22,6 @@
 //
 
 #include "Precompiled.h"
-#include "Engine.h"
 #include "Log.h"
 #include "RegisterTemplates.h"
 #include "ScriptInstance.h"

+ 0 - 1
Engine/Engine/RegisterScript.cpp

@@ -22,7 +22,6 @@
 //
 
 #include "Precompiled.h"
-#include "Engine.h"
 #include "Entity.h"
 #include "Log.h"
 #include "RegisterTemplates.h"

+ 0 - 4
Engine/Engine/RegisterUI.cpp

@@ -22,19 +22,15 @@
 //
 
 #include "Precompiled.h"
-#include "Button.h"
 #include "CheckBox.h"
 #include "Cursor.h"
 #include "DropDownList.h"
-#include "Engine.h"
 #include "FileSelector.h"
 #include "Font.h"
 #include "LineEdit.h"
 #include "ListView.h"
-#include "Menu.h"
 #include "RegisterTemplates.h"
 #include "ScrollBar.h"
-#include "ScrollView.h"
 #include "Slider.h"
 #include "Text.h"
 #include "UI.h"

+ 0 - 3
Engine/Physics/PhysicsWorld.cpp

@@ -23,7 +23,6 @@
 
 #include "Precompiled.h"
 #include "DebugRenderer.h"
-#include "Entity.h"
 #include "Log.h"
 #include "PhysicsEvents.h"
 #include "PhysicsWorld.h"
@@ -33,8 +32,6 @@
 #include "Scene.h"
 #include "SceneEvents.h"
 #include "StringUtils.h"
-#include "VectorBuffer.h"
-#include "XMLElement.h"
 
 #include <ode/ode.h>
 #include <algorithm>

+ 0 - 6
Engine/Renderer/Camera.cpp

@@ -52,7 +52,6 @@ Camera::Camera(const std::string& name) :
     mLightDetailLevelOverride(QUALITY_MAX),
     mMaterialQualityOverride(QUALITY_MAX),
     mMaxOccluderTrianglesOverride(M_MAX_INT),
-    mInViewFrameNumber(M_MAX_UNSIGNED),
     mInverseWorldTransformDirty(true),
     mFrustumDirty(true),
     mProjectionDirty(true),
@@ -507,11 +506,6 @@ float Camera::getLodDistance(float distance, float scale, float bias) const
         return mOrthoSize / d;
 }
 
-void Camera::markInView(unsigned frameNumber)
-{
-    mInViewFrameNumber = frameNumber;
-}
-
 void Camera::onMarkedDirty()
 {
     mInverseWorldTransformDirty = true;

+ 0 - 5
Engine/Renderer/Camera.h

@@ -148,11 +148,6 @@ public:
     //! Return a scene node's LOD scaled distance
     float getLodDistance(float distance, float scale, float bias) const;
     
-    //! Mark in view this frame. Called by View
-    void markInView(unsigned frameNumber);
-    //! Return whether is in view this frame
-    bool isInView(unsigned frameNumber) const { return mInViewFrameNumber == frameNumber; }
-    
 protected:
     //! Transform has changed. Mark frustum and projection to need updating
     virtual void onMarkedDirty();

+ 25 - 37
Engine/Renderer/DebugRenderer.cpp

@@ -24,62 +24,50 @@
 #include "Precompiled.h"
 #include "AnimatedModel.h"
 #include "DebugRenderer.h"
-#include "Exception.h"
 #include "Light.h"
-#include "Log.h"
 #include "PixelShader.h"
+#include "Pipeline.h"
 #include "Profiler.h"
 #include "Renderer.h"
 #include "RendererEvents.h"
-#include "RendererImpl.h"
 #include "ResourceCache.h"
 #include "VertexShader.h"
 
 #include "DebugNew.h"
 
-DebugRenderer::DebugRenderer(Renderer* renderer, ResourceCache* cache) :
-    mRenderer(renderer),
-    mCache(cache)
+DebugRenderer::DebugRenderer()
 {
-    if (!mRenderer)
-        EXCEPTION("Null renderer for DebugRenderer");
-    
-    mDebugVS = mCache->getResource<VertexShader>("Shaders/SM2/Basic_VCol.vs2");
-    mDebugPS = mCache->getResource<PixelShader>("Shaders/SM2/Basic_VCol.ps2");
-    
     subscribeToEvent(EVENT_ENDFRAME, EVENT_HANDLER(DebugRenderer, handleEndFrame));
 }
 
-DebugRenderer::~DebugRenderer()
-{
-}
-
-void DebugRenderer::render(Camera* camera)
+void DebugRenderer::render(Pipeline* pipeline, Camera* camera)
 {
     if ((!camera) || ((!mLines.size()) && (!mNoDepthLines.size())))
         return;
     
     PROFILE(DebugGeometry_Render);
     
-    mRenderer->setAlphaTest(false);
-    mRenderer->setBlendMode(BLEND_REPLACE);
-    mRenderer->setColorWrite(true);
-    mRenderer->setCullMode(CULL_NONE);
-    mRenderer->setDepthWrite(true);
-    mRenderer->setDepthTest(CMP_LESSEQUAL);
-    mRenderer->setFillMode(FILL_SOLID);
-    mRenderer->setScissorTest(false);
-    mRenderer->setStencilTest(false);
-    mRenderer->setVertexShader(mDebugVS);
-    mRenderer->setPixelShader(mDebugPS);
-    mRenderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), camera->getProjection() * camera->getInverseWorldTransform());
-    mRenderer->setPixelShaderConstant(getPSRegister(PSP_MATDIFFCOLOR), Color(1.0f, 1.0f, 1.0f, 1.0f));
+    Renderer* renderer = pipeline->getRenderer();
+    
+    renderer->setAlphaTest(false);
+    renderer->setBlendMode(BLEND_REPLACE);
+    renderer->setColorWrite(true);
+    renderer->setCullMode(CULL_NONE);
+    renderer->setDepthWrite(true);
+    renderer->setDepthTest(CMP_LESSEQUAL);
+    renderer->setFillMode(FILL_SOLID);
+    renderer->setScissorTest(false);
+    renderer->setStencilTest(false);
+    renderer->setVertexShader(pipeline->getVertexShader("Basic_VCol"));
+    renderer->setPixelShader(pipeline->getPixelShader("Basic_VCol"));
+    renderer->setVertexShaderConstant(getVSRegister(VSP_MODELVIEWPROJ), camera->getProjection() * camera->getInverseWorldTransform());
+    renderer->setPixelShaderConstant(getPSRegister(PSP_MATDIFFCOLOR), Color(1.0f, 1.0f, 1.0f, 1.0f));
     
     // Draw all line geometry with depth testing
     if (mLines.size())
     {
-        mRenderer->beginImmediate(LINE_LIST, mLines.size() * 2, MASK_POSITION | MASK_COLOR);
-        float* dest = (float*)mRenderer->getImmediateDataPtr();
+        renderer->beginImmediate(LINE_LIST, mLines.size() * 2, MASK_POSITION | MASK_COLOR);
+        float* dest = (float*)renderer->getImmediateDataPtr();
         
         for (unsigned i = 0; i < mLines.size(); ++i)
         {
@@ -92,15 +80,15 @@ void DebugRenderer::render(Camera* camera)
             *((unsigned*)dest) = line.mColor; dest++;
         }
         
-        mRenderer->endImmediate();
+        renderer->endImmediate();
     }
     
     // Draw all line geometry without depth testing
-    mRenderer->setDepthTest(CMP_ALWAYS);
+    renderer->setDepthTest(CMP_ALWAYS);
     if (mNoDepthLines.size())
     {
-        mRenderer->beginImmediate(LINE_LIST, mNoDepthLines.size() * 2, MASK_POSITION | MASK_COLOR);
-        float* dest = (float*)mRenderer->getImmediateDataPtr();
+        renderer->beginImmediate(LINE_LIST, mNoDepthLines.size() * 2, MASK_POSITION | MASK_COLOR);
+        float* dest = (float*)renderer->getImmediateDataPtr();
         
         for (unsigned i = 0; i < mNoDepthLines.size(); ++i)
         {
@@ -113,7 +101,7 @@ void DebugRenderer::render(Camera* camera)
             *((unsigned*)dest) = line.mColor; dest++;
         }
         
-        mRenderer->endImmediate();
+        renderer->endImmediate();
     }
 }
 

+ 4 - 19
Engine/Renderer/DebugRenderer.h

@@ -38,12 +38,8 @@ class Frustum;
 class GeometryNode;
 class Light;
 class Matrix4x3;
-class PixelShader;
-class Renderer;
-class ResourceCache;
+class Pipeline;
 class Skeleton;
-class Texture;
-class VertexShader;
 
 //! Debug rendering line
 struct DebugLine
@@ -75,10 +71,8 @@ class DebugRenderer : public SceneExtension, public EventListener
     DEFINE_TYPE(DebugRenderer);
     
 public:
-    //! Construct with Renderer and ResourceCache pointers
-    DebugRenderer(Renderer* renderer, ResourceCache* cache);
-    //! Destruct
-    virtual ~DebugRenderer();
+    //! Construct
+    DebugRenderer();
     
     //! Add a line
     void addLine(const Vector3& start, const Vector3& end, const Color& color, bool depthTest = true);
@@ -91,21 +85,12 @@ public:
     //! Add a skeleton
     void addSkeleton(const Skeleton& skeleton, const Color& color, bool depthTest = true);
     //! Render all debug lines from a specific camera. The viewport and rendertarget should be set before
-    void render(Camera* camera);
+    void render(Pipeline* pipeline, Camera* camera);
     
 private:
     //! Handle end of frame. Clear debug geometry
     void handleEndFrame(StringHash eventType, VariantMap& eventData);
     
-    //! Renderer subsystem
-    SharedPtr<Renderer> mRenderer;
-    //! Resource cache
-    SharedPtr<ResourceCache> mCache;
-    //! Debug geometry vertex shader
-    SharedPtr<VertexShader> mDebugVS;
-    //! Debug geometry pixel shader
-    SharedPtr<PixelShader> mDebugPS;
-    
     //! Lines rendered with depth test
     std::vector<DebugLine> mLines;
     //! Lines rendered without depth test

+ 1 - 1
Engine/Renderer/DeferredView.cpp

@@ -156,7 +156,7 @@ void View::getBatchesDeferred()
     
     // Go through lights
     {
-        PROFILE_MULTIPLE(Pipeline_GetLightBatches, mLights.size());
+        PROFILE_MULTIPLE(View_GetLightBatches, mLights.size());
         
         unsigned lightQueueCount = 0;
         for (unsigned i = 0; i < mLights.size(); ++i)

+ 1 - 1
Engine/Renderer/ForwardView.cpp

@@ -103,7 +103,7 @@ void View::getBatchesForward()
     
     // Go through lights
     {
-        PROFILE_MULTIPLE(Pipeline_GetLightBatches, mLights.size());
+        PROFILE_MULTIPLE(View_GetLightBatches, mLights.size());
         
         unsigned lightQueueCount = 0;
         for (unsigned i = 0; i < mLights.size(); ++i)

+ 33 - 75
Engine/Renderer/Pipeline.cpp

@@ -333,7 +333,7 @@ void Pipeline::setNumViewports(unsigned num)
     mViewports.resize(num);
 }
 
-void Pipeline::setViewport(unsigned index, Scene* scene, Camera* camera, const IntRect& screenRect)
+void Pipeline::setViewport(unsigned index, const Viewport& viewport)
 {
     if (index >= mViewports.size())
     {
@@ -341,35 +341,9 @@ void Pipeline::setViewport(unsigned index, Scene* scene, Camera* camera, const I
         return;
     }
     
-    Viewport& viewport = mViewports[index];
-    viewport.mScene = scene;
-    viewport.mCamera = camera;
-    viewport.mScreenRect = screenRect;
+    mViewports[index] = viewport;
 }
 
-void Pipeline::setViewportCamera(unsigned index, Camera* camera)
-{
-    if (index >= mViewports.size())
-    {
-        LOGERROR("Illegal viewport index");
-        return;
-    }
-    
-    mViewports[index].mCamera = camera;
-}
-
-void Pipeline::setViewportScreenRect(unsigned index, const IntRect& screenRect)
-{
-    if (index >= mViewports.size())
-    {
-        LOGERROR("Illegal viewport index");
-        return;
-    }
-    
-    mViewports[index].mScreenRect = screenRect;
-}
-
-
 void Pipeline::setSpecularLighting(bool enable)
 {
     mSpecularLighting = enable;
@@ -465,28 +439,14 @@ void Pipeline::setDrawDebugGeometry(bool enable)
     mDrawDebugGeometry = enable;
 }
 
-Scene* Pipeline::getViewportScene(unsigned index) const
-{
-    if (index >= mViewports.size())
-        return 0;
-    else
-        return mViewports[index].mScene;
-}
-
-Camera* Pipeline::getViewportCamera(unsigned index) const
-{
-    if (index >= mViewports.size())
-        return 0;
-    else
-        return mViewports[index].mCamera;
-}
-
-IntRect Pipeline::getViewportScreenRect(unsigned index) const
+const Viewport& Pipeline::getViewport(unsigned index) const
 {
+    static const Viewport emptyViewport;
+    
     if (index >= mViewports.size())
-        return IntRect::sZero;
+        return emptyViewport;
     else
-        return mViewports[index].mScreenRect;
+        return mViewports[index];
 }
 
 VertexShader* Pipeline::getVertexShader(const std::string& name, bool checkExists) const
@@ -619,39 +579,22 @@ bool Pipeline::update(float timeStep)
     // view dependencies correctly
     for (unsigned i = mViewports.size() - 1; i < mViewports.size(); --i)
     {
+        unsigned mainView = mNumViews;
         Viewport& viewport = mViewports[i];
-        
-        // Check for valid scene, camera and octree, and that the scene is not asynchronously loading and thus incomplete
-        Scene* scene = viewport.mScene;
-        Camera* camera = viewport.mCamera;
-        if ((!scene) || (!camera) || (scene->isAsyncLoading()))
-            continue;
-        Octree* octree = scene->getExtension<Octree>();
-        if (!octree)
+        if (!addView(0, viewport))
             continue;
         
-        // If viewport has zero size defined, follow the window size
-        IntRect screenRect = viewport.mScreenRect;
-        if (screenRect == IntRect::sZero)
-            screenRect = IntRect(0, 0, mRenderer->getWidth(), mRenderer->getHeight());
-        
-        mFrame.mCamera = camera;
-        
-        // Update octree. Perform early update for nodes which need that, and reinsert moved nodes
+        // Update octree (perform early update for nodes which need that, and reinsert moved nodes.)
         // However, if the same scene is viewed from multiple cameras, update the octree only once
+        Octree* octree = viewport.mScene->getExtension<Octree>();
         if (mUpdatedOctrees.find(octree) == mUpdatedOctrees.end())
         {
             octree->updateOctree(mFrame);
             mUpdatedOctrees.insert(octree);
         }
         
-        // Add and process this viewport's main view
-        unsigned mainView = mNumViews;
-        addView(octree, camera, 0, screenRect);
-        mViews[mainView]->update(mFrame);
-        
-        // Process any auxiliary views that were found during the main view processing
-        for (unsigned i = mainView + 1; i < mNumViews; ++i)
+        // Update the viewport's main view and any auxiliary views it creates
+        for (unsigned i = mainView; i < mNumViews; ++i)
             mViews[i]->update(mFrame);
     }
     
@@ -705,7 +648,7 @@ void Pipeline::drawDebugGeometry()
     {
         // Make sure it's a main view, and process each node only once
         View* view = mViews[i];
-        if ((!view) || (view->getRenderTarget()))
+        if (view->getRenderTarget())
             continue;
         Octree* octree = view->getOctree();
         if (!octree)
@@ -764,15 +707,30 @@ void Pipeline::resetViews()
     mNumViews = 0;
 }
 
-void Pipeline::addView(Octree* octree, Camera* camera, RenderSurface* renderTarget, const IntRect& screenRect)
+bool Pipeline::addView(RenderSurface* renderTarget, const Viewport& viewport)
 {
+    // If using a render target texture, make sure it will not be rendered to multiple times
+    if (renderTarget)
+    {
+        for (unsigned i = 0; i < mNumViews; ++i)
+        {
+            if (mViews[i]->getRenderTarget() == renderTarget)
+                return false;
+        }
+    }
+    
     if (mViews.size() <= mNumViews)
         mViews.resize(mNumViews + 1);
     if (!mViews[mNumViews])
         mViews[mNumViews] = new View(this);
     
-    mViews[mNumViews]->define(octree, camera, renderTarget, screenRect);
-    ++mNumViews;
+    if (mViews[mNumViews]->define(renderTarget, viewport))
+    {
+        ++mNumViews;
+        return true;
+    }
+    else
+        return false;
 }
 
 OcclusionBuffer* Pipeline::getOrCreateOcclusionBuffer(Camera& camera, int maxOccluderTriangles, bool halfResolution)
@@ -1128,7 +1086,7 @@ void Pipeline::loadMaterialPassShaders(MaterialTechnique* technique, PassType pa
             if ((variation == LPS_SHADOW) || (variation == LPS_SHADOWSPEC))
             {
                 if (allowShadows)
-                    pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j] + 
+                    pixelShaders[j] = getPixelShader(pixelShaderName + deferredLightPSVariations[j] +
                         shadowPSVariations[hwShadows]);
                 else
                     pixelShaders[j].reset();

+ 6 - 38
Engine/Renderer/Pipeline.h

@@ -25,12 +25,10 @@
 #define RENDERER_PIPELINE_H
 
 #include "Batch.h"
-#include "Camera.h"
 #include "Color.h"
 #include "EventListener.h"
+#include "RenderSurface.h"
 #include "ShaderDefs.h"
-#include "Rect.h"
-#include "SharedPtr.h"
 #include "Zone.h"
 
 #include <map>
@@ -46,15 +44,10 @@ class MaterialPass;
 class MaterialTechnique;
 class Octree;
 class Renderer;
-class RenderSurface;
 class ResourceCache;
-class Scene;
 class Skeleton;
 class OcclusionBuffer;
-class Texture;
 class Texture2D;
-class TextureCube;
-class TiXmlElement;
 class View;
 
 static const int SHADOW_MIN_PIXELS = 64;
@@ -90,23 +83,6 @@ struct EdgeFilterParameters
     float mMaxScale;
 };
 
-//! Viewport definition
-struct Viewport
-{
-    //! Construct
-    Viewport() :
-        mScreenRect(IntRect::sZero)
-    {
-    }
-    
-    //! Scene pointer
-    WeakPtr<Scene> mScene;
-    //! Camera pointer
-    WeakPtr<Camera> mCamera;
-    //! Viewport screen rectangle
-    IntRect mScreenRect;
-};
-
 //! High-level rendering pipeline
 class Pipeline : public RefCounted, public EventListener
 {
@@ -121,11 +97,7 @@ public:
     //! Set number of viewports to render
     void setNumViewports(unsigned num);
     //! Set a viewport
-    void setViewport(unsigned index, Scene* scene, Camera* camera, const IntRect& screenRect = IntRect::sZero);
-    //! Set a viewport's camera only
-    void setViewportCamera(unsigned index, Camera* camera);
-    //! Set a viewport's screen rect only
-    void setViewportScreenRect(unsigned index, const IntRect& screenRect);
+    void setViewport(unsigned index, const Viewport& viewport);
     //! Set specular lighting on/off
     void setSpecularLighting(bool enable);
     //! Set shadows on/off
@@ -157,12 +129,8 @@ public:
     
     //! Return number of viewports
     unsigned getNumViewports() const { return mViewports.size(); }
-    //! Return viewport scene
-    Scene* getViewportScene(unsigned index) const;
-    //! Return viewport camera
-    Camera* getViewportCamera(unsigned index) const;
-    //! Return viewport screen rectangle
-    IntRect getViewportScreenRect(unsigned index) const;
+    //! Return viewport
+    const Viewport& getViewport(unsigned index) const;
     //! Return current frame number
     unsigned getFrameNumber() const { return mFrameNumber; }
     //! Return elapsed time
@@ -234,8 +202,8 @@ private:
     void beginFrame(float timeStep);
     //! Clear views from previous frame
     void resetViews();
-    //! Add a view
-    void addView(Octree* octree, Camera* camera, RenderSurface* renderTarget, const IntRect& screenRect);
+    //! Add a view. Return true if successful
+    bool addView(RenderSurface* renderTarget, const Viewport& viewport);
     //! Return an occlusion buffer for use
     OcclusionBuffer* getOrCreateOcclusionBuffer(Camera& camera, int maxOccluderTriangles, bool halfResolution = false);
     //! Return a material technique for a scene node, considering material LOD

+ 23 - 2
Engine/Renderer/RenderSurface.cpp

@@ -27,9 +27,30 @@
 #include "Renderer.h"
 #include "RendererImpl.h"
 #include "RenderSurface.h"
+#include "Scene.h"
+#include "Texture.h"
 
 #include "DebugNew.h"
 
+Viewport::Viewport() :
+    mRect(IntRect::sZero)
+{
+}
+
+Viewport::Viewport(Scene* scene, Camera* camera) :
+    mScene(scene),
+    mCamera(camera),
+    mRect(IntRect::sZero)
+{
+}
+
+Viewport::Viewport(Scene* scene, Camera* camera, const IntRect& rect) :
+    mScene(scene),
+    mCamera(camera),
+    mRect(rect)
+{
+}
+
 RenderSurface::RenderSurface(Texture* parentTexture) :
     mParentTexture(parentTexture),
     mSurface(0)
@@ -41,9 +62,9 @@ RenderSurface::~RenderSurface()
     release();
 }
 
-void RenderSurface::setCamera(Camera* camera)
+void RenderSurface::setViewport(const Viewport& viewport)
 {
-    mCamera = camera;
+    mViewport = viewport;
 }
 
 void RenderSurface::setLinkedRenderTarget(RenderSurface* renderTarget)

+ 28 - 8
Engine/Renderer/RenderSurface.h

@@ -24,11 +24,31 @@
 #ifndef RENDERER_RENDERSURFACE_H
 #define RENDERER_RENDERSURFACE_H
 
+#include "Rect.h"
+#include "RendererDefs.h"
 #include "SharedPtr.h"
-#include "Texture.h"
 
 class Camera;
-class Renderer;
+class Scene;
+class Texture;
+
+//! A viewport definition either for a texture or the backbuffer
+struct Viewport
+{
+    //! Construct with defaults
+    Viewport();
+    //! Construct with a full rectangle
+    Viewport(Scene* scene, Camera* camera);
+    //! Construct with a specified rectangle
+    Viewport(Scene* scene, Camera* camera, const IntRect& rect);
+    
+    //! Scene pointer
+    WeakPtr<Scene> mScene;
+    //! Camera pointer
+    WeakPtr<Camera> mCamera;
+    //! Viewport rectangle
+    IntRect mRect;
+};
 
 //! A renderable color or depth stencil surface
 class RenderSurface : public RefCounted
@@ -42,8 +62,8 @@ public:
     //! Destruct
     ~RenderSurface();
     
-    //! Set camera to use in auxiliary view rendering
-    void setCamera(Camera* camera);
+    //! Set viewport for auxiliary view rendering
+    void setViewport(const Viewport& viewport);
     //! Set linked color buffer
     void setLinkedRenderTarget(RenderSurface* renderTarget);
     //! Set linked depth buffer
@@ -61,8 +81,8 @@ public:
     int getHeight() const;
     //! Return usage
     TextureUsage getUsage() const;
-    //! Return camera to use in auxiliary view rendering
-    Camera* getCamera() const { return mCamera; }
+    //! Return auxiliary view rendering viewport
+    const Viewport& getViewport() const { return mViewport; }
     //! Return linked color buffer
     RenderSurface* getLinkedRenderTarget() const { return mLinkedRenderTarget; }
     //! Return linked depth buffer
@@ -73,8 +93,8 @@ private:
     Texture* mParentTexture;
     //! Direct3D surface
     void* mSurface;
-    //! Auxiliary view rendering camera
-    WeakPtr<Camera> mCamera;
+    //! Viewport
+    Viewport mViewport;
     //! Linked color buffer
     WeakPtr<RenderSurface> mLinkedRenderTarget;
     //! Linked depth buffer

+ 9 - 0
Engine/Renderer/RendererDefs.h

@@ -159,6 +159,15 @@ enum TextureCoordinate
     MAX_COORDS
 };
 
+//! Texture usage types
+enum TextureUsage
+{
+    TEXTURE_STATIC = 0,
+    TEXTURE_DYNAMIC,
+    TEXTURE_RENDERTARGET,
+    TEXTURE_DEPTHSTENCIL
+};
+
 //! Rendering passes
 enum PassType
 {

+ 0 - 9
Engine/Renderer/Texture.h

@@ -34,15 +34,6 @@ static const int MAX_TEXTURE_QUALITY_LEVELS = 3;
 
 class XMLFile;
 
-//! Texture usage types
-enum TextureUsage
-{
-    TEXTURE_STATIC = 0,
-    TEXTURE_DYNAMIC,
-    TEXTURE_RENDERTARGET,
-    TEXTURE_DEPTHSTENCIL
-};
-
 //! Base class for texture resources
 class Texture : public Resource, public GPUObject
 {

+ 1 - 1
Engine/Renderer/Texture2D.h

@@ -37,7 +37,7 @@ class Texture2D : public Texture
     
 public:
     //! Construct with renderer subsystem pointer, texture usage type and name
-    Texture2D(Renderer*, TextureUsage usage, const std::string& name = std::string());
+    Texture2D(Renderer* renderer, TextureUsage usage, const std::string& name = std::string());
     //! Destruct
     virtual ~Texture2D();
     

+ 41 - 33
Engine/Renderer/View.cpp

@@ -71,13 +71,18 @@ View::~View()
 {
 }
 
-void View::define(Octree* octree, Camera* camera, RenderSurface* renderTarget, IntRect screenRect)
+bool View::define(RenderSurface* renderTarget, const Viewport& viewport)
 {
-    if ((!octree) || (!camera))
-    {
-        LOGERROR("Null octree or camera for View");
-        return;
-    }
+    if ((!viewport.mScene) || (!viewport.mCamera))
+        return false;
+    
+    // If scene is loading asynchronously, it is incomplete and should not be rendered
+    if (viewport.mScene->isAsyncLoading())
+        return false;
+    
+    Octree* octree = viewport.mScene->getExtension<Octree>();
+    if (!octree)
+        return false;
     
     Renderer* renderer = mPipeline->getRenderer();
     
@@ -91,14 +96,14 @@ void View::define(Octree* octree, Camera* camera, RenderSurface* renderTarget, I
             if (errorDisplayed.find(renderTarget) == errorDisplayed.end())
             {
                 errorDisplayed.insert(renderTarget);
-                LOGERROR("Render texture is larger than the G-buffer, can not add view");
+                LOGERROR("Render texture is larger than the G-buffer, can not render");
             }
-            return;
+            return false;
         }
     }
     
     mOctree = octree;
-    mCamera = camera;
+    mCamera = viewport.mCamera;
     mRenderTarget = renderTarget;
     
     if (renderTarget)
@@ -107,20 +112,26 @@ void View::define(Octree* octree, Camera* camera, RenderSurface* renderTarget, I
         mDepthStencil = 0;
     mZone = &sDefaultZone;
     
-    // Validate the rect and calculate size
-    screenRect.mLeft = clamp(screenRect.mLeft, 0, renderer->getWidth() - 1);
-    screenRect.mTop = clamp(screenRect.mTop, 0, renderer->getHeight() - 1);
-    screenRect.mRight = clamp(screenRect.mRight, screenRect.mLeft + 1, renderer->getWidth());
-    screenRect.mBottom = clamp(screenRect.mBottom, screenRect.mTop + 1, renderer->getHeight());
-    mScreenRect = screenRect;
-    mWidth = screenRect.mRight - screenRect.mLeft;
-    mHeight = screenRect.mBottom - screenRect.mTop;
+    // Validate the rect and calculate size. If zero rect, use whole render target size
+    int rtWidth = renderTarget ? renderTarget->getWidth() : renderer->getWidth();
+    int rtHeight = renderTarget ? renderTarget->getHeight() : renderer->getHeight();
+    if (viewport.mRect != IntRect::sZero)
+    {
+        mScreenRect.mLeft = clamp(viewport.mRect.mLeft, 0, rtWidth - 1);
+        mScreenRect.mTop = clamp(viewport.mRect.mTop, 0, rtHeight - 1);
+        mScreenRect.mRight = clamp(viewport.mRect.mRight, mScreenRect.mLeft + 1, rtWidth);
+        mScreenRect.mBottom = clamp(viewport.mRect.mBottom, mScreenRect.mTop + 1, rtHeight);
+    }
+    else
+        mScreenRect = IntRect(0, 0, rtWidth, rtHeight);
+    mWidth = mScreenRect.mRight - mScreenRect.mLeft;
+    mHeight = mScreenRect.mBottom - mScreenRect.mTop;
     
     // Set possible quality overrides from the camera
-    mDrawShadows = mPipeline->getDrawShadows() && (camera->getDrawShadowsOverride());
-    mLightDetailLevel = min(mPipeline->getLightDetailLevel(), camera->getLightDetailLevelOverride());
-    mMaterialQuality = min(mPipeline->getMaterialQuality(), camera->getMaterialQualityOverride());
-    mMaxOccluderTriangles = min(mPipeline->getMaxOccluderTriangles(), camera->getMaxOccluderTrianglesOverride());
+    mDrawShadows = mPipeline->getDrawShadows() && (mCamera->getDrawShadowsOverride());
+    mLightDetailLevel = min(mPipeline->getLightDetailLevel(), mCamera->getLightDetailLevelOverride());
+    mMaterialQuality = min(mPipeline->getMaterialQuality(), mCamera->getMaterialQualityOverride());
+    mMaxOccluderTriangles = min(mPipeline->getMaxOccluderTriangles(), mCamera->getMaxOccluderTrianglesOverride());
     
     // Clear light scissor cache, geometry, light, occluder & batch lists
     mLightScissorCache.clear();
@@ -138,6 +149,8 @@ void View::define(Octree* octree, Camera* camera, RenderSurface* renderTarget, I
     mPostOpaqueQueue.clear();
     mTransparentQueue.clear();
     mLightQueues.clear();
+    
+    return true;
 }
 
 void View::update(const FrameInfo& frame)
@@ -145,8 +158,6 @@ void View::update(const FrameInfo& frame)
     if ((!mCamera) || (!mOctree))
         return;
     
-    PROFILE(Pipeline_UpdateView);
-    
     mFrame.mCamera = mCamera;
     mFrame.mTimeStep = frame.mTimeStep;
     mFrame.mFrameNumber = frame.mFrameNumber;
@@ -155,7 +166,6 @@ void View::update(const FrameInfo& frame)
     if (mCamera->getAutoAspectRatio())
         mCamera->setAspectRatio((float)(mScreenRect.mRight - mScreenRect.mLeft) / (float)(mScreenRect.mBottom - mScreenRect.mTop));
     
-    mCamera->markInView(mFrame.mFrameNumber);
     getNodes();
     
     if (mPipeline->getRenderer()->getRenderMode() != RENDER_FORWARD)
@@ -220,7 +230,7 @@ void View::render()
         {
             DebugRenderer* debug = mOctree->getScene()->getExtension<DebugRenderer>();
             if (debug)
-                debug->render(mCamera);
+                debug->render(mPipeline, mCamera);
         }
     }
     
@@ -1215,10 +1225,9 @@ void View::checkTechniqueForAuxView(MaterialTechnique* technique)
                 RenderSurface* target = tex2D->getRenderSurface();
                 if (target)
                 {
-                    // Add the view only if it has not been added already
-                    Camera* camera = target->getCamera();
-                    if ((camera) && (!camera->isInView(mFrame.mFrameNumber)))
-                        mPipeline->addView(mOctree, camera, target, IntRect(0, 0, tex2D->getWidth(), tex2D->getHeight()));
+                    const Viewport& viewport = target->getViewport();
+                    if ((viewport.mScene) && (viewport.mCamera))
+                        mPipeline->addView(target, viewport);
                 }
             }
             else if (texture->getType() == TextureCube::getTypeStatic())
@@ -1229,10 +1238,9 @@ void View::checkTechniqueForAuxView(MaterialTechnique* technique)
                     RenderSurface* target = texCube->getRenderSurface((CubeMapFace)j);
                     if (target)
                     {
-                        // Add the view only if it has not been added already
-                        Camera* camera = target->getCamera();
-                        if ((camera) && (!camera->isInView(mFrame.mFrameNumber)))
-                            mPipeline->addView(mOctree, camera, target, IntRect(0, 0, texCube->getWidth(), texCube->getHeight()));
+                        const Viewport& viewport = target->getViewport();
+                        if ((viewport.mScene) && (viewport.mCamera))
+                            mPipeline->addView(target, viewport);
                     }
                 }
             }

+ 4 - 3
Engine/Renderer/View.h

@@ -34,6 +34,7 @@ class GeometryNode;
 class OcclusionBuffer;
 class RenderSurface;
 class Zone;
+struct Viewport;
 
 static const int MAX_LIGHT_SPLITS = 6;
 
@@ -70,8 +71,8 @@ public:
     //! Destruct
     virtual ~View();
     
-    //! Define with octree, camera and render target pointers and a viewport rectangle
-    void define(Octree* octree, Camera* camera, RenderSurface* renderTarget, IntRect screenRect);
+    //! Define with rendertarget and viewport. Return true if successful
+    bool define(RenderSurface* renderTarget, const Viewport& viewport);
     //! Update culling and construct rendering batches
     void update(const FrameInfo& frame);
     //! Render batches
@@ -155,7 +156,7 @@ private:
     RenderSurface* mRenderTarget;
     //! Depth buffer to use
     RenderSurface* mDepthStencil;
-    //! Screen rectangle. For texture render targets it is the full texture size
+    //! Screen rectangle
     IntRect mScreenRect;
     //! Render target width
     int mWidth;

+ 0 - 1
Engine/Script/ScriptEngine.cpp

@@ -22,7 +22,6 @@
 //
 
 #include "Precompiled.h"
-#include "Exception.h"
 #include "Log.h"
 #include "Profiler.h"
 #include "RegisterArray.h"

+ 0 - 3
Engine/UI/BaseUIElementFactory.cpp

@@ -23,15 +23,12 @@
 
 #include "Precompiled.h"
 #include "BaseUIElementFactory.h"
-#include "Button.h"
 #include "CheckBox.h"
 #include "Cursor.h"
 #include "DropDownList.h"
 #include "LineEdit.h"
 #include "ListView.h"
-#include "Menu.h"
 #include "ScrollBar.h"
-#include "ScrollView.h"
 #include "Slider.h"
 #include "Text.h"
 #include "Window.h"

+ 0 - 1
Engine/UI/FileSelector.cpp

@@ -23,7 +23,6 @@
 
 #include "Precompiled.h"
 #include "DropDownList.h"
-#include "Exception.h"
 #include "File.h"
 #include "FileSelector.h"
 #include "InputEvents.h"

+ 10 - 20
Examples/NinjaSnowWar/Game.cpp

@@ -230,10 +230,6 @@ void Game::init()
         mClient->connect(address, 1234, mUserName);
     }
     
-    // Configure the viewport
-    if (!runServer)
-        mEngine->getPipeline()->setViewport(0, mScene, mCamera);
-    
     startGame();
 }
 
@@ -324,6 +320,9 @@ void Game::createCamera()
     
     mCamera->setNearClip(GameConfig::getReal("Engine/ViewStart"));
     mCamera->setFarClip(GameConfig::getReal("Engine/ViewEnd"));
+    
+    // Configure the viewport
+    mEngine->getPipeline()->setViewport(0, Viewport(mScene, mCamera));
 }
 
 void Game::startGame()
@@ -1052,25 +1051,16 @@ void Game::updateCamera()
     if (mServer)
         return;
     
-    Camera* camera = 0;
-    if (mCamera.isExpired())
+    if (!mCamera)
     {
-        // Reacquire the camera pointer if necessary
+        // Reacquire the camera pointer if necessary, then reconfigure the viewport
         Entity* cameraEntity = mScene->getEntity("Camera");
         if (cameraEntity)
-        {
             mCamera = cameraEntity->getComponent<Camera>();
-            camera = mCamera.getPtr();
-        }
+        if (!mCamera)
+            return;
+        mEngine->getPipeline()->setViewport(0, Viewport(mScene, mCamera));
     }
-    else
-        camera = mCamera.getPtr();
-    
-    if (!camera)
-        return;
-    
-    // Make sure the pipeline has the updated camera pointer
-    mEngine->getPipeline()->setViewportCamera(0, camera);
     
     // Player tracking
     Entity* playerEntity = 0;
@@ -1115,8 +1105,8 @@ void Game::updateCamera()
     if (result.size())
         rayDistance = min(rayDistance, result[0].mDistance - mCameraSafetyDist);
     
-    camera->setPosition(minDist + rayDir * rayDistance);
-    camera->setRotation(dir);
+    mCamera->setPosition(minDist + rayDir * rayDistance);
+    mCamera->setRotation(dir);
     
     Audio* audio = mEngine->getAudio();
     if (audio)