Procházet zdrojové kódy

Fixing an issue with UAV reads of a particular format not being supported on some hardware

BearishSun před 8 roky
rodič
revize
7f2ad317de

+ 7 - 3
Data/Raw/Engine/Includes/PerCameraData.bslinc

@@ -25,7 +25,9 @@ Parameters =
 	
 	// xy - (Viewport size in pixels / 2) / Target size in pixels
 	// zw - (Viewport offset in pixels + (Viewport size in pixels / 2) + Optional pixel center offset) / Target size in pixels	
-	float4 		gClipToUVScaleOffset : auto("ClipToUVScaleOffset");		
+	float4 		gClipToUVScaleOffset : auto("ClipToUVScaleOffset");	
+
+	float		gAmbientFactor;
 };
 
 Blocks =
@@ -55,7 +57,8 @@ Technique : base("PerCameraData") =
 				float2	 gNDCZToWorldZ;
 				float2	 gNearFar;
 				int4 	 gViewportRectangle;
-				float4 	 gClipToUVScaleOffset;				
+				float4 	 gClipToUVScaleOffset;	
+				float	gAmbientFactor;
 			}
 			
 			/** Converts Z value in range [0,1] into Z value in view space. */
@@ -89,7 +92,8 @@ Technique : base("PerCameraData") =
 				vec2 gNDCZToWorldZ;
 				vec2 gNearFar;
 				ivec4 gViewportRectangle;
-				vec4 gClipToUVScaleOffset;				
+				vec4 gClipToUVScaleOffset;
+				float gAmbientFactor;
 			};
 			
 			/** Converts Z value in range [0,1] into Z value in view space. */

+ 2 - 2
Data/Raw/Engine/Shaders/Default.bsl

@@ -35,8 +35,8 @@ Technique : base("Surface") =
 		Fragment =
 		{
 			layout(location = 0) in vec2 uv0;
-			layout(location = 1) in vec3 tangentToWorldZ;
-			layout(location = 2) in vec4 tangentToWorldX;	
+			layout(location = 2) in vec3 tangentToWorldZ;
+			layout(location = 3) in vec4 tangentToWorldX;	
 		
 			layout(location = 0) out vec4[3] fragColor;
 		

+ 0 - 14
Data/Raw/Engine/Shaders/FlatFramebufferToTexture.bsl

@@ -7,13 +7,6 @@ Technique =
 		DepthRead = false;
 		DepthWrite = false;
 		
-		Target = 
-		{
-			Blend = true;
-			Color = { ONE, ONE, ADD };
-			WriteMask = RGB;
-		};		
-	
 		Common = 
 		{
 			struct VStoFS
@@ -77,13 +70,6 @@ Technique =
 		DepthRead = false;
 		DepthWrite = false;
 		
-		Target = 
-		{
-			Blend = true;
-			Color = { ONE, ONE, ADD };
-			WriteMask = RGB;
-		};		
-		
 		Vertex =
 		{
 			layout(location = 0) in vec2 bs_position;

+ 21 - 2
Data/Raw/Engine/Shaders/Skybox.bsl

@@ -36,12 +36,21 @@ Technique : inherits("PerCameraData") =
 			TextureCube gSkyTex : register(t0);
 			SamplerState gSkySamp : register(s0);
 		
+			cbuffer Params : register(b0)
+			{
+				float4 gClearColor;
+			}
+		
 			float4 main(
 				in float4 inPos : SV_Position, 
 				in float3 dir : TEXCOORD0) : SV_Target
 			{
-				return gSkyTex.Sample(gSkySamp, dir);
-			}
+				#ifdef SOLID_COLOR
+					return gClearColor;
+				#else
+					return gSkyTex.Sample(gSkySamp, dir);
+				#endif
+				}
 		};	
 	};
 };
@@ -79,12 +88,22 @@ Technique : inherits("PerCameraData") =
 		Fragment =
 		{
 			layout(location = 0) in vec3 dir;		
+			
 			layout(binding = 1) uniform samplerCube gSkyTex;
+			layout(binding = 2, std140) uniform Params
+			{
+				vec4 gClearColor;
+			};
+			
 			layout(location = 0) out vec4 fragColor;
 			
 			void main()
 			{
+			#ifdef SOLID_COLOR
+				fragColor = gClearColor;
+			#else
 				fragColor = texture(gSkyTex, dir);
+			#endif
 			}	
 		};
 	};

+ 9 - 10
Data/Raw/Engine/Shaders/TiledDeferredLighting.bsl

@@ -164,7 +164,8 @@ Technique
                         uint lightIdx = sLightIndices[i];
                         lightAccumulator += getSpotLightContribution(worldPosition, surfaceData, gLights[lightIdx]);
                     }
-
+					
+					lightAccumulator += surfaceData.albedo * gAmbientFactor;
 					alpha = 1.0f;
 				}
 				
@@ -361,7 +362,7 @@ Technique
 					
 					#else
 					float4 lighting = getLighting(clipSpacePos.xy, surfaceData[0]);
-					gOutput[pixelPos] = float4(gOutput[pixelPos].rgb + lighting.rgb, lighting.a);
+					gOutput[pixelPos] = lighting;
 					#endif
 				}
 			}
@@ -467,6 +468,7 @@ Technique
 				// Assumed directional lights start at 0
 				// x - offset to point lights, y - offset to spot lights, z - total number of lights
 				uvec3 gLightOffsets;
+				uvec2 gFramebufferSize;
 			};
 			
 			shared uint sTileMinZ;
@@ -510,6 +512,7 @@ Technique
                         lightAccumulator += getSpotLightContribution(worldPosition, surfaceData, lightData);
                     }
 					
+					lightAccumulator += surfaceData.albedo.rgb * gAmbientFactor;
 					alpha = 1.0f;
 				}
 				
@@ -644,8 +647,7 @@ Technique
 				{
 					#if MSAA_COUNT > 1
 					vec4 lighting = getLighting(clipSpacePos.xy, surfaceData[0]);
-					vec4 existingValue = imageLoad(gOutput, pixelPos, 0);
-					imageStore(gOutput, pixelPos, 0, vec4(existingValue.rgb + lighting.rgb, lighting.a));
+					imageStore(gOutput, pixelPos, 0, lighting);
 
 					bool doPerSampleShading = needsPerSampleShading(surfaceData);
 					if(doPerSampleShading)
@@ -653,21 +655,18 @@ Technique
 						for(int i = 1; i < MSAA_COUNT; ++i)
 						{
 							lighting = getLighting(clipSpacePos.xy, surfaceData[i]);
-							existingValue = imageLoad(gOutput, pixelPos, i);
-							imageStore(gOutput, pixelPos, i, vec4(existingValue.rgb + lighting.rgb, lighting.a));
+							imageStore(gOutput, pixelPos, i, lighting);
 						}
 					}
 					else // Splat same information to all samples
 					{
 						for(int i = 1; i < MSAA_COUNT; ++i)
-							imageStore(gOutput, pixelPos, i, vec4(existingValue.rgb + lighting.rgb, lighting.a));
+							imageStore(gOutput, pixelPos, i, lighting);
 					}
 					
 					#else
 					vec4 lighting = getLighting(clipSpacePos.xy, surfaceData[0]);
-					
-					vec4 existingValue = imageLoad(gOutput, pixelPos);
-					imageStore(gOutput, pixelPos, vec4(existingValue.rgb + lighting.rgb, lighting.a));
+					imageStore(gOutput, pixelPos, lighting);
 					#endif
 				}
 			}

+ 4 - 0
Data/Raw/Engine/Shaders/Transparent.bsl

@@ -94,6 +94,8 @@ Technique
 					lightAccumulator += getSpotLightContribution(input.worldPosition, surfaceData, lightData);
 				}
 				
+				lightAccumulator += surfaceData.albedo.xyz * gAmbientFactor;
+				
 				float3 diffuse = surfaceData.albedo.xyz / PI;
 				return float4(diffuse * lightAccumulator, gOpacity); // TODO - Add better lighting model later
 			}	
@@ -184,6 +186,8 @@ Technique
 					lightAccumulator += getSpotLightContribution(worldPosition, surfaceData, lightData);
 				}
 				
+				lightAccumulator += surfaceData.albedo.xyz * gAmbientFactor;
+				
 				vec3 diffuse = surfaceData.albedo.xyz / PI; // TODO - Add better lighting model later
 				fragColor = vec4(diffuse * lightAccumulator, gOpacity); 
 			}	

+ 7 - 2
Source/BansheeCore/Include/BsCamera.h

@@ -44,13 +44,18 @@ namespace bs
 		 * buffer or multi-sampled render targets. Such cameras will not render any scene objects. This can improve
 		 * performance and memory usage. 
 		 */
-		Overlay = 1,
+		Overlay = 1 << 0,
 		/** 
 		 * High dynamic range allows light intensity to be more correctly recorded when rendering by allowing for a larger
 		 * range of values. The stored light is then converted into visible color range using exposure and a tone mapping 
 		 * operator.
 		 */
-		HDR = 2
+		HDR = 1 << 1,
+		/** 
+		 * Specify that no lighting should be applied to scene objects and everything should be rendered using their
+		 * albedo texture.
+		 */
+		NoLighting = 1 << 2
 	};
 
 	typedef Flags<CameraFlag> CameraFlags;

+ 1 - 0
Source/MBansheeEditor/Windows/Scene/SceneCamera.cs

@@ -136,6 +136,7 @@ namespace BansheeEditor
         private void OnReset()
         {
             camera = SceneObject.GetComponent<Camera>();
+            camera.NoLighting = true;
 
             moveForwardBtn = new VirtualButton(MoveForwardBinding);
             moveLeftBtn = new VirtualButton(MoveLeftBinding);

+ 11 - 0
Source/MBansheeEngine/Interop/NativeCamera.cs

@@ -131,6 +131,12 @@ namespace BansheeEngine
             set { Internal_SetHDR(mCachedPtr, value); }
         }
 
+        internal bool noLighting
+        {
+            get { return Internal_GetNoLighting(mCachedPtr); }
+            set { Internal_SetNoLighting(mCachedPtr, value); }
+        }
+
         public TextureCube skybox
         {
             get { return Internal_GetSkybox(mCachedPtr); }
@@ -441,6 +447,11 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetHDR(IntPtr instance, bool value);
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_GetNoLighting(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetNoLighting(IntPtr instance, bool value);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern TextureCube Internal_GetSkybox(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 12 - 0
Source/MBansheeEngine/Rendering/Camera.cs

@@ -167,6 +167,16 @@ namespace BansheeEngine
             set { native.HDR = value; serializableData.HDR = value; }
         }
 
+        /// <summary>
+        /// If enabled no lighting will be applied to scene objects and everything should be rendered using their
+        /// albedo texture.
+        /// </summary>
+        public bool NoLighting
+        {
+            get { return native.noLighting; }
+            set { native.noLighting = value; serializableData.noLighting = value; }
+        }
+
         /// <summary>
         /// Texture that will be used for rendering areas of the camera's render target not covered by any geometry. 
         /// If not set a clear color will be used instead.
@@ -436,6 +446,7 @@ namespace BansheeEngine
             native.priority = serializableData.priority;
             native.layers = serializableData.layers;
             native.main = serializableData.main;
+            native.noLighting = serializableData.noLighting;
 
             // TODO - Make RenderTexture a resource so I can save/restore it?
         }
@@ -474,6 +485,7 @@ namespace BansheeEngine
             public ClearFlags clearFlags = ClearFlags.Color | ClearFlags.Depth | ClearFlags.Stencil;
             public int priority;
             public bool HDR = true;
+            public bool noLighting;
             public PostProcessSettings postProcessSettings;
             public ulong layers = 0xFFFFFFFFFFFFFFFF;
             public bool main;

+ 1 - 1
Source/RenderBeast/Include/BsLightGrid.h

@@ -99,7 +99,7 @@ namespace bs { namespace ct
 		LightGrid();
 
 		/** Updates the light grid from the provided view. */
-		void updateGrid(const RendererCamera& view, const GPULightData& lightData);
+		void updateGrid(const RendererCamera& view, const GPULightData& lightData, bool noLighting);
 
 		/** 
 		 * Returns the buffers containing light indices per grid cell and global grid parameters. 

+ 4 - 3
Source/RenderBeast/Include/BsLightRendering.h

@@ -82,7 +82,7 @@ namespace bs { namespace ct
 		TiledDeferredLighting(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet, UINT32 sampleCount);
 
 		/** Binds the material for rendering, sets up parameters and executes it. */
-		void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera);
+		void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting);
 
 		/** Binds all the active lights. */
 		void setLights(const GPULightData& lightData);
@@ -97,6 +97,7 @@ namespace bs { namespace ct
 		GpuParamTexture mGBufferB;
 		GpuParamTexture mGBufferDepth;
 
+		Vector3I mLightOffsets;
 		GpuParamBuffer mLightBufferParam;
 		GpuParamLoadStoreTexture mOutputTextureParam;
 		GpuParamBuffer mOutputBufferParam;
@@ -111,7 +112,7 @@ namespace bs { namespace ct
 		virtual ~ITiledDeferredLightingMat() {}
 
 		/** Binds the material for rendering, sets up parameters and executes it. */
-		virtual void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera) = 0;
+		virtual void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting) = 0;
 
 		/** Binds all the active lights. */
 		virtual void setLights(const GPULightData& lightData) = 0;
@@ -127,7 +128,7 @@ namespace bs { namespace ct
 		TTiledDeferredLightingMat();
 
 		/** Binds the material for rendering, sets up parameters and executes it. */
-		void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera) override;
+		void execute(const SPtr<RenderTargets>& gbuffer, const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting) override;
 
 		/** Binds all the active lights. */
 		void setLights(const GPULightData& lightData) override;

+ 2 - 1
Source/RenderBeast/Include/BsRenderBeast.h

@@ -220,7 +220,8 @@ namespace bs
 		DefaultMaterial* mDefaultMaterial;
 		ITiledDeferredLightingMat* mTiledDeferredLightingMats[4];
 		FlatFramebufferToTextureMat* mFlatFramebufferToTextureMat;
-		SkyboxMat* mSkyboxMat;
+		SkyboxMat<false>* mSkyboxMat;
+		SkyboxMat<true>* mSkyboxSolidColorMat;
 
 		GPULightData* mGPULightData;
 		LightGrid* mLightGrid;

+ 20 - 4
Source/RenderBeast/Include/BsRendererCamera.h

@@ -30,12 +30,20 @@ namespace bs { namespace ct
 		BS_PARAM_BLOCK_ENTRY(Vector2, gNearFar)
 		BS_PARAM_BLOCK_ENTRY(Vector4I, gViewportRectangle)
 		BS_PARAM_BLOCK_ENTRY(Vector4, gClipToUVScaleOffset)
+		BS_PARAM_BLOCK_ENTRY(float, gAmbientFactor)
 	BS_PARAM_BLOCK_END
 
 	extern PerCameraParamDef gPerCameraParamDef;
 
-	/** Shader that renders a skybox using a cubemap. */
-	class SkyboxMat : public RendererMaterial<SkyboxMat>
+	BS_PARAM_BLOCK_BEGIN(SkyboxParamDef)
+		BS_PARAM_BLOCK_ENTRY(Color, gClearColor)
+	BS_PARAM_BLOCK_END
+
+	extern SkyboxParamDef gSkyboxParamDef;
+
+	/** Shader that renders a skybox using a cubemap or a solid color. */
+	template<bool SOLID_COLOR>
+	class SkyboxMat : public RendererMaterial<SkyboxMat<SOLID_COLOR>>
 	{
 		RMAT_DEF("Skybox.bsl");
 
@@ -45,10 +53,11 @@ namespace bs { namespace ct
 		/** Binds the material for rendering and sets up any global parameters. */
 		void bind(const SPtr<GpuParamBlockBuffer>& perCamera);
 
-		/** Updates the skybox texture used by the material. */
-		void setParams(const SPtr<Texture>& texture);
+		/** Updates the skybox texture & solid color used by the material. */
+		void setParams(const SPtr<Texture>& texture, const Color& solidColor);
 	private:
 		GpuParamTexture mSkyTextureParam;
+		SPtr<GpuParamBlockBuffer> mParamBuffer;
 	};
 
 	/** Set of properties describing the output render target used by a renderer view. */
@@ -83,6 +92,7 @@ namespace bs { namespace ct
 
 		bool isOverlay : 1;
 		bool isHDR : 1;
+		bool noLighting : 1;
 		bool triggerCallbacks : 1;
 		bool runPostProcessing : 1;
 
@@ -150,6 +160,9 @@ namespace bs { namespace ct
 		/** Returns true if this view only renders overlay, and not scene objects. */
 		bool isOverlay() const { return mViewDesc.isOverlay; }
 
+		/** Returns true if the view should be rendered with no lighting. */
+		bool renderWithNoLighting() const { return mViewDesc.noLighting; }
+
 		/** Returns the texture to use for the skybox (if any). */
 		SPtr<Texture> getSkybox() const { return mViewDesc.skyboxTexture; }
 
@@ -162,6 +175,9 @@ namespace bs { namespace ct
 		/** Returns true if the resulting render target should be flipped vertically. */
 		bool getFlipView() const { return mViewDesc.flipView; }
 
+		/** Returns the color to clear the non-rendered areas of the scene color target to. */
+		Color getClearColor() const { return mViewDesc.target.clearColor; }
+
 		/** Returns the number of samples per pixel to render. */
 		UINT32 getNumSamples() const { return mViewDesc.target.numSamples; }
 

+ 13 - 4
Source/RenderBeast/Source/BsLightGrid.cpp

@@ -193,7 +193,7 @@ namespace bs { namespace ct
 		mGridParamBuffer = gLightGridParamDefDef.createBuffer();
 	}
 
-	void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData)
+	void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData, bool noLighting)
 	{
 		UINT32 width = view.getRenderTargets()->getWidth();
 		UINT32 height = view.getRenderTargets()->getHeight();
@@ -204,9 +204,18 @@ namespace bs { namespace ct
 		gridSize[2] = NUM_Z_SUBDIVIDES;
 
 		Vector3I lightOffsets;
-		lightOffsets[0] = lightData.getNumDirLights();
-		lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
-		lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
+		if (!noLighting)
+		{
+			lightOffsets[0] = lightData.getNumDirLights();
+			lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
+			lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
+		}
+		else
+		{
+			lightOffsets[0] = 0;
+			lightOffsets[1] = 1;
+			lightOffsets[2] = 2;
+		}
 
 		UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
 

+ 20 - 10
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -86,7 +86,7 @@ namespace bs { namespace ct
 
 	TiledDeferredLighting::TiledDeferredLighting(const SPtr<Material>& material, const SPtr<GpuParamsSet>& paramsSet, 
 												 UINT32 sampleCount)
-		:mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet)
+		:mSampleCount(sampleCount), mMaterial(material), mParamsSet(paramsSet), mLightOffsets()
 	{
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 
@@ -114,13 +114,26 @@ namespace bs { namespace ct
 	}
 
 	void TiledDeferredLighting::execute(const SPtr<RenderTargets>& gbuffer,
-										const SPtr<GpuParamBlockBuffer>& perCamera)
+										const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting)
 	{
 		Vector2I framebufferSize;
 		framebufferSize[0] = gbuffer->getWidth();
 		framebufferSize[1] = gbuffer->getHeight();
 		gTiledLightingParamDef.gFramebufferSize.set(mParamBuffer, framebufferSize);
 
+		if (noLighting)
+		{
+			Vector3I lightOffsets;
+			lightOffsets[0] = 0;
+			lightOffsets[1] = 0;
+			lightOffsets[2] = 0;
+
+			gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, lightOffsets);
+		}
+		else
+		{
+			gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, mLightOffsets);
+		}
 		mParamBuffer->flushToGPU();
 
 		mGBufferA.set(gbuffer->getTextureA());
@@ -157,12 +170,9 @@ namespace bs { namespace ct
 	{
 		mLightBufferParam.set(lightData.getLightBuffer());
 
-		Vector3I lightOffsets;
-		lightOffsets[0] = lightData.getNumDirLights();
-		lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
-		lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
-
-		gTiledLightingParamDef.gLightOffsets.set(mParamBuffer, lightOffsets);
+		mLightOffsets[0] = lightData.getNumDirLights();
+		mLightOffsets[1] = mLightOffsets[0] + lightData.getNumRadialLights();
+		mLightOffsets[2] = mLightOffsets[1] + lightData.getNumSpotLights();
 	}
 
 	template<int MSAA_COUNT>
@@ -181,9 +191,9 @@ namespace bs { namespace ct
 
 	template<int MSAA_COUNT>
 	void TTiledDeferredLightingMat<MSAA_COUNT>::execute(const SPtr<RenderTargets>& gbuffer,
-													const SPtr<GpuParamBlockBuffer>& perCamera)
+													const SPtr<GpuParamBlockBuffer>& perCamera, bool noLighting)
 	{
-		mInternal.execute(gbuffer, perCamera);
+		mInternal.execute(gbuffer, perCamera, noLighting);
 	}
 
 	template<int MSAA_COUNT>

+ 23 - 11
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -41,8 +41,8 @@ namespace bs { namespace ct
 {
 	RenderBeast::RenderBeast()
 		: mDefaultMaterial(nullptr), mTiledDeferredLightingMats(), mFlatFramebufferToTextureMat(nullptr)
-		, mSkyboxMat(nullptr), mGPULightData(nullptr), mLightGrid(nullptr), mObjectRenderer(nullptr)
-		, mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
+		, mSkyboxMat(nullptr), mSkyboxSolidColorMat(nullptr), mGPULightData(nullptr), mLightGrid(nullptr)
+		, mObjectRenderer(nullptr), mOptions(bs_shared_ptr_new<RenderBeastOptions>()), mOptionsDirty(true)
 	{ }
 
 	const StringID& RenderBeast::getName() const
@@ -74,7 +74,8 @@ namespace bs { namespace ct
 		mObjectRenderer = bs_new<ObjectRenderer>();
 
 		mDefaultMaterial = bs_new<DefaultMaterial>();
-		mSkyboxMat = bs_new<SkyboxMat>();
+		mSkyboxMat = bs_new<SkyboxMat<false>>();
+		mSkyboxSolidColorMat = bs_new<SkyboxMat<true>>();
 		mFlatFramebufferToTextureMat = bs_new<FlatFramebufferToTextureMat>();
 
 		mTiledDeferredLightingMats[0] = bs_new<TTiledDeferredLightingMat<1>>();
@@ -110,6 +111,7 @@ namespace bs { namespace ct
 
 		bs_delete(mDefaultMaterial);
 		bs_delete(mSkyboxMat);
+		bs_delete(mSkyboxSolidColorMat);
 		bs_delete(mGPULightData);
 		bs_delete(mLightGrid);
 		bs_delete(mFlatFramebufferToTextureMat);
@@ -509,6 +511,7 @@ namespace bs { namespace ct
 
 			viewDesc.isOverlay = camera->getFlags().isSet(CameraFlag::Overlay);
 			viewDesc.isHDR = camera->getFlags().isSet(CameraFlag::HDR);
+			viewDesc.noLighting = camera->getFlags().isSet(CameraFlag::NoLighting);
 			viewDesc.triggerCallbacks = true;
 			viewDesc.runPostProcessing = true;
 
@@ -795,7 +798,7 @@ namespace bs { namespace ct
 		viewInfo->beginRendering(true);
 
 		// Prepare light grid required for transparent object rendering
-		mLightGrid->updateGrid(*viewInfo, *mGPULightData);
+		mLightGrid->updateGrid(*viewInfo, *mGPULightData, viewInfo->renderWithNoLighting());
 
 		SPtr<GpuParamBlockBuffer> gridParams;
 		SPtr<GpuBuffer> gridOffsetsAndSize, gridLightIndices;
@@ -871,7 +874,8 @@ namespace bs { namespace ct
 			}
 		}
 
-		renderTargets->bindSceneColor(true);
+		RenderAPI& rapi = RenderAPI::instance();
+		rapi.setRenderTarget(nullptr);
 
 		// Render light pass
 		ITiledDeferredLightingMat* lightingMat;
@@ -895,11 +899,13 @@ namespace bs { namespace ct
 		}
 
 		lightingMat->setLights(*mGPULightData);
-		lightingMat->execute(renderTargets, perCameraBuffer);
+		lightingMat->execute(renderTargets, perCameraBuffer, viewInfo->renderWithNoLighting());
 
 		const RenderAPIInfo& rapiInfo = RenderAPI::instance().getAPIInfo();
 		bool usingFlattenedFB = numSamples > 1 && !rapiInfo.isFlagSet(RenderAPIFeatureFlag::MSAAImageStores);
 
+		renderTargets->bindSceneColor(true);
+
 		// If we're using flattened framebuffer for MSAA we need to copy its contents to the MSAA scene texture before
 		// continuing
 		if(usingFlattenedFB)
@@ -911,15 +917,21 @@ namespace bs { namespace ct
 		// Render skybox (if any)
 		SPtr<Texture> skyTexture = viewInfo->getSkybox();
 		if (skyTexture != nullptr && skyTexture->getProperties().getTextureType() == TEX_TYPE_CUBE_MAP)
-		//if (dbgSkyTex != nullptr)
 		{
 			mSkyboxMat->bind(perCameraBuffer);
-			mSkyboxMat->setParams(skyTexture);
+			mSkyboxMat->setParams(skyTexture, Color::White);
+		}
+		else
+		{
+			Color clearColor = viewInfo->getClearColor();
 
-			SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
-			gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+			mSkyboxSolidColorMat->bind(perCameraBuffer);
+			mSkyboxSolidColorMat->setParams(nullptr, clearColor);
 		}
 
+		SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
+		gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
+
 		renderTargets->bindSceneColor(false);
 
 		// Render transparent objects
@@ -947,7 +959,6 @@ namespace bs { namespace ct
 		}
 
 		// Post-processing and final resolve
-		RenderAPI& rapi = RenderAPI::instance();
 		Rect2 viewportArea = viewInfo->getViewportRect();
 
 		if (viewInfo->checkRunPostProcessing())
@@ -1100,6 +1111,7 @@ namespace bs { namespace ct
 
 		viewDesc.isOverlay = false;
 		viewDesc.isHDR = hdr;
+		viewDesc.noLighting = false;
 		viewDesc.triggerCallbacks = false;
 		viewDesc.runPostProcessing = false;
 

+ 4 - 4
Source/RenderBeast/Source/BsRenderTargets.cpp

@@ -13,7 +13,7 @@ namespace bs { namespace ct
 		:mViewTarget(view), mHDR(hdr), mWidth(view.targetWidth), mHeight(view.targetHeight)
 	{
 		// Note: Consider customizable HDR format via options? e.g. smaller PF_FLOAT_R11G11B10 or larger 32-bit format
-		mSceneColorFormat = hdr ? PF_FLOAT16_RGBA : PF_R8G8B8A8;
+		mSceneColorFormat = PF_FLOAT16_RGBA;
 		mAlbedoFormat = PF_R8G8B8A8; // Note: Also consider customizable format (e.g. 16-bit float?)
 		mNormalFormat = PF_UNORM_R10G10B10A2; // Note: Also consider customizable format (e.g. 16-bit float?)
 	}
@@ -137,15 +137,15 @@ namespace bs { namespace ct
 		Rect2 area(0.0f, 0.0f, 1.0f, 1.0f);
 		rapi.setViewport(area);
 
-		// Clear scene color, depth, stencil according to user defined values
-		UINT32 clearFlags = mViewTarget.clearFlags;
+		// Clear depth & stencil according to user defined values, don't clear color as all values will get written to
+		UINT32 clearFlags = mViewTarget.clearFlags & ~FBT_COLOR;
 		if (clearFlags != 0)
 		{
 			RenderAPI::instance().clearViewport(clearFlags, mViewTarget.clearColor,
 												mViewTarget.clearDepthValue, mViewTarget.clearStencilValue, 0x01);
 		}
 
-		// Clear all others
+		// Clear all non primary targets (Note: I could perhaps clear all but albedo, since it stores a per-pixel write mask)
 		RenderAPI::instance().clearViewport(FBT_COLOR, Color::ZERO, 1.0f, 0, 0xFF & ~0x01);
 	}
 

+ 34 - 6
Source/RenderBeast/Source/BsRendererCamera.cpp

@@ -12,29 +12,45 @@
 namespace bs { namespace ct
 {
 	PerCameraParamDef gPerCameraParamDef;
+	SkyboxParamDef gSkyboxParamDef;
 
-	SkyboxMat::SkyboxMat()
+	template<bool SOLID_COLOR>
+	SkyboxMat<SOLID_COLOR>::SkyboxMat()
 	{
 		SPtr<GpuParams> params = mParamsSet->getGpuParams();
 
-		params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gSkyTex", mSkyTextureParam);
+		if(params->hasTexture(GPT_FRAGMENT_PROGRAM, "gSkyTex"))
+			params->getTextureParam(GPT_FRAGMENT_PROGRAM, "gSkyTex", mSkyTextureParam);
+
+		mParamBuffer = gSkyboxParamDef.createBuffer();
+
+		if(params->hasParamBlock(GPT_FRAGMENT_PROGRAM, "Params"))
+			mParamsSet->setParamBlockBuffer("Params", mParamBuffer, true);
 	}
 
-	void SkyboxMat::_initDefines(ShaderDefines& defines)
+	template<bool SOLID_COLOR>
+	void SkyboxMat<SOLID_COLOR>::_initDefines(ShaderDefines& defines)
 	{
-		// Do nothing
+		if (SOLID_COLOR)
+			defines.set("SOLID_COLOR", 1);
 	}
 
-	void SkyboxMat::bind(const SPtr<GpuParamBlockBuffer>& perCamera)
+	template<bool SOLID_COLOR>
+	void SkyboxMat<SOLID_COLOR>::bind(const SPtr<GpuParamBlockBuffer>& perCamera)
 	{
 		mParamsSet->setParamBlockBuffer("PerCamera", perCamera, true);
 
 		gRendererUtility().setPass(mMaterial, 0);
 	}
 
-	void SkyboxMat::setParams(const SPtr<Texture>& texture)
+	template<bool SOLID_COLOR>
+	void SkyboxMat<SOLID_COLOR>::setParams(const SPtr<Texture>& texture, const Color& solidColor)
 	{
 		mSkyTextureParam.set(texture, TextureSurface(1, 1, 0, 0));
+
+		gSkyboxParamDef.gClearColor.set(mParamBuffer, solidColor);
+		mParamBuffer->flushToGPU();
+
 		gRendererUtility().setPassParams(mParamsSet);
 	}
 
@@ -89,6 +105,10 @@ namespace bs { namespace ct
 
 	void RendererCamera::setView(const RENDERER_VIEW_DESC& desc)
 	{
+		if (mViewDesc.target.targetWidth != desc.target.targetWidth ||
+			mViewDesc.target.targetHeight != desc.target.targetHeight)
+			mRenderTargets = nullptr;
+
 		mViewDesc = desc;
 
 		setStateReductionMode(desc.stateReduction);
@@ -353,5 +373,13 @@ namespace bs { namespace ct
 			clipToUVScaleOffset.y = -clipToUVScaleOffset.y;
 
 		gPerCameraParamDef.gClipToUVScaleOffset.set(mParamBuffer, clipToUVScaleOffset);
+
+		if (mViewDesc.noLighting)
+			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 100.0f);
+		else
+			gPerCameraParamDef.gAmbientFactor.set(mParamBuffer, 0.0f);
 	}
+
+	template class SkyboxMat<true>;
+	template class SkyboxMat<false>;
 }}

+ 3 - 0
Source/SBansheeEngine/Include/BsScriptCamera.h

@@ -90,6 +90,9 @@ namespace bs
 		static bool internal_GetHDR(ScriptCamera* instance);
 		static void internal_SetHDR(ScriptCamera* instance, bool value);
 
+		static bool internal_GetNoLighting(ScriptCamera* instance);
+		static void internal_SetNoLighting(ScriptCamera* instance, bool value);
+
 		static MonoObject* internal_GetSkybox(ScriptCamera* instance);
 		static void internal_SetSkybox(ScriptCamera* instance, ScriptTextureCube* value);
 

+ 13 - 0
Source/SBansheeEngine/Source/BsScriptCamera.cpp

@@ -78,6 +78,9 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_GetHDR", &ScriptCamera::internal_GetHDR);
 		metaData.scriptClass->addInternalCall("Internal_SetHDR", &ScriptCamera::internal_SetHDR);
 
+		metaData.scriptClass->addInternalCall("Internal_GetNoLighting", &ScriptCamera::internal_GetNoLighting);
+		metaData.scriptClass->addInternalCall("Internal_SetNoLighting", &ScriptCamera::internal_SetNoLighting);
+
 		metaData.scriptClass->addInternalCall("Internal_GetSkybox", &ScriptCamera::internal_GetSkybox);
 		metaData.scriptClass->addInternalCall("Internal_SetSkybox", &ScriptCamera::internal_SetSkybox);
 
@@ -306,6 +309,16 @@ namespace bs
 		instance->mCamera->setFlag(CameraFlag::HDR, value);
 	}
 
+	bool ScriptCamera::internal_GetNoLighting(ScriptCamera* instance)
+	{
+		return instance->mCamera->getFlags().isSet(CameraFlag::NoLighting);
+	}
+
+	void ScriptCamera::internal_SetNoLighting(ScriptCamera* instance, bool value)
+	{
+		instance->mCamera->setFlag(CameraFlag::NoLighting, value);
+	}
+
 	MonoObject* ScriptCamera::internal_GetSkybox(ScriptCamera* instance)
 	{
 		HTexture texture = instance->mCamera->getSkybox();