2
0
Эх сурвалжийг харах

Added support for load/store textures
Better support for non-2D render textures
Better support for binding multisampled textures as shader resources
More work on C# camera implementation
(None of this tested or even compiled, WIP)

Marko Pintera 11 жил өмнө
parent
commit
350e767ebf
38 өөрчлөгдсөн 716 нэмэгдсэн , 131 устгасан
  1. 21 5
      BansheeCore/Include/BsCommonTypes.h
  2. 4 0
      BansheeCore/Include/BsCoreThreadAccessor.h
  3. 29 0
      BansheeCore/Include/BsGpuParam.h
  4. 32 0
      BansheeCore/Include/BsGpuParams.h
  5. 22 0
      BansheeCore/Include/BsMaterial.h
  6. 6 0
      BansheeCore/Include/BsRenderSystem.h
  7. 0 1
      BansheeCore/Include/BsRenderTarget.h
  8. 1 0
      BansheeCore/Include/BsTexture.h
  9. 7 0
      BansheeCore/Source/BsCoreThreadAccessor.cpp
  10. 32 0
      BansheeCore/Source/BsGpuParam.cpp
  11. 52 4
      BansheeCore/Source/BsGpuParams.cpp
  12. 20 0
      BansheeCore/Source/BsMaterial.cpp
  13. 2 2
      BansheeCore/Source/BsMultiRenderTexture.cpp
  14. 2 2
      BansheeCore/Source/BsRenderTexture.cpp
  15. 2 3
      BansheeCore/Source/BsShader.cpp
  16. 8 0
      BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h
  17. 7 0
      BansheeD3D11RenderSystem/Include/BsD3D11Texture.h
  18. 3 0
      BansheeD3D11RenderSystem/Source/BsD3D11HLSLParamParser.cpp
  19. 70 4
      BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp
  20. 11 2
      BansheeD3D11RenderSystem/Source/BsD3D11Texture.cpp
  21. 38 7
      BansheeD3D11RenderSystem/Source/BsD3D11TextureView.cpp
  22. 7 1
      BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h
  23. 17 6
      BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp
  24. 11 0
      BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp
  25. 2 6
      BansheeD3D9RenderSystem/Source/BsD3D9Texture.cpp
  26. 24 0
      BansheeEngine/Include/BsCameraHandler.h
  27. 28 0
      BansheeEngine/Source/BsCameraHandler.cpp
  28. 6 0
      BansheeGLRenderSystem/Include/BsGLRenderSystem.h
  29. 6 0
      BansheeGLRenderSystem/Include/BsGLTexture.h
  30. 21 8
      BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp
  31. 60 3
      BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp
  32. 19 5
      BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp
  33. 35 0
      BansheeGLRenderSystem/Source/BsGLSLParamParser.cpp
  34. 9 18
      BansheeGLRenderSystem/Source/BsGLTexture.cpp
  35. 4 2
      MBansheeEngine/Camera.cs
  36. 5 2
      SBansheeEngine/Include/BsScriptCamera.h
  37. 93 48
      SBansheeEngine/Source/BsScriptCamera.cpp
  38. 0 2
      SceneView.txt

+ 21 - 5
BansheeCore/Include/BsCommonTypes.h

@@ -259,13 +259,12 @@ namespace BansheeEngine
 		GPOT_SAMPLER2D = 2,
 		GPOT_SAMPLER3D = 3,
 		GPOT_SAMPLERCUBE = 4,
+		GPOT_SAMPLER2DMS = 5,
 		GPOT_TEXTURE1D = 11,
 		GPOT_TEXTURE2D = 12,
 		GPOT_TEXTURE3D = 13,
 		GPOT_TEXTURECUBE = 14,
-		GPOT_RWTEXTURE1D = 21,
-		GPOT_RWTEXTURE2D = 22,
-		GPOT_RWTEXTURE3D = 23,
+		GPOT_TEXTURE2DMS = 15,
 		GPOT_BYTE_BUFFER = 32,
 		GPOT_STRUCTURED_BUFFER = 33,
 		GPOT_RWTYPED_BUFFER = 41,
@@ -332,12 +331,29 @@ namespace BansheeEngine
 	};
 
 	/**
-	* @brief Represents a MAC (ethernet) address.
-	*/
+	 * @brief Represents a MAC (ethernet) address.
+	 */
 	struct MACAddress
 	{
 		UINT8 value[6];
 	};
     
+	/**
+	 * @brief	References a subset of surfaces within a texture
+	 */
+	struct TextureSurface
+	{
+		TextureSurface(UINT32 mipLevel = 0, UINT32 numMipLevels = 1, 
+			UINT32 arraySlice = 0, UINT32 numArraySlices = 1)
+			:mipLevel(mipLevel), numMipLevels(numMipLevels), 
+			arraySlice(arraySlice), numArraySlices(numArraySlices)
+		{ }
+
+		UINT32 mipLevel;
+		UINT32 numMipLevels;
+		UINT32 arraySlice;
+		UINT32 numArraySlices;
+	};
+
 	typedef Map<String, String> NameValuePairList;
 }

+ 4 - 0
BansheeCore/Include/BsCoreThreadAccessor.h

@@ -26,6 +26,10 @@ namespace BansheeEngine
 		/** @copydoc RenderSystem::setTexture() */
 		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
 
+		/** @copydoc RenderSystem::setLoadStoreTexture() */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+			UINT32 mipLevel = 0, UINT32 arraySlice = 0, UINT32 numSlices = 1);
+
 		/** @copydoc RenderSystem::setSamplerState() */
 		void setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState);
 

+ 29 - 0
BansheeCore/Include/BsGpuParam.h

@@ -279,6 +279,35 @@ namespace BansheeEngine
 		std::shared_ptr<GpuParamsInternalData> mInternalData;
 	};
 
+	/**
+	 * @copydoc GpuDataParamBase
+	 */
+	class BS_CORE_EXPORT GpuParamLoadStoreTexture
+	{
+	private:
+		friend class GpuParams;
+
+	public:
+		GpuParamLoadStoreTexture();
+
+		/**
+		 * @copydoc	GpuDataParamBase::set
+		 */
+		void set(const HTexture& texture, const TextureSurface& surface);
+
+		/**
+		 * @copydoc	GpuDataParamBase::get
+		 */
+		HTexture get();
+		
+	private:
+		GpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const std::shared_ptr<GpuParamsInternalData>& internalData);
+
+	private:
+		GpuParamObjectDesc* mParamDesc;
+		std::shared_ptr<GpuParamsInternalData> mInternalData;
+	};
+
 	/**
 	 * @copydoc GpuDataParamBase
 	 */

+ 32 - 0
BansheeCore/Include/BsGpuParams.h

@@ -7,6 +7,19 @@ namespace BansheeEngine
 {
 	struct GpuParamsInternalData;
 
+	/**
+	 * @brief	Stores information needed for binding a texture to the pipeline.
+	 */
+	struct BoundTextureInfo
+	{
+		BoundTextureInfo()
+			:isLoadStore(false)
+		{ }
+
+		bool isLoadStore;
+		TextureSurface surface;
+	};
+
 	/**
 	 * @brief	Contains descriptions for all parameters in a GPU program and also
 	 *			allows you to write and read those parameters. All parameter values
@@ -20,6 +33,7 @@ namespace BansheeEngine
 	class BS_CORE_EXPORT GpuParams
 	{
 		struct PrivatelyConstruct {};
+
 	public:
 		/**
 		 * @brief	Creates new GpuParams object using the specified parameter descriptions.
@@ -223,6 +237,11 @@ namespace BansheeEngine
 		 */
 		void getTextureParam(const String& name, GpuParamTexture& output) const;
 
+		/**
+		 * @copydoc	getParam(const String&, GpuDataParamBase<T>&)
+		 */
+		void getLoadStoreTextureParam(const String& name, GpuParamLoadStoreTexture& output) const;
+
 		/**
 		 * @copydoc	getParam(const String&, GpuDataParamBase<T>&)
 		 */
@@ -250,6 +269,18 @@ namespace BansheeEngine
 		 */
 		HSamplerState getSamplerState(UINT32 slot);
 
+		/**
+		 * @brief	Checks is the texture at the specified slot to be bound as
+		 *			random load/store texture instead of a normal sampled texture.
+		 */
+		bool isLoadStoreTexture(UINT32 slot) const;
+
+		/**
+		 * @brief	Returns information that determines which texture surfaces to bind
+		 *			as load/store parameters.
+		 */
+		const TextureSurface& getLoadStoreSurface(UINT32 slot) const;
+
 		/**
 		 * @brief	Updates all internal data from the provided copy. Copy must have the same
 		 *			number of parameters as this object. Internal buffer contents will also be copied
@@ -322,6 +353,7 @@ namespace BansheeEngine
 		GpuParamBlockPtr* mParamBlocks;
 		GpuParamBlockBufferPtr* mParamBlockBuffers;
 		HTexture* mTextures;
+		BoundTextureInfo* mTextureInfo;
 		HSamplerState* mSamplerStates;
 
 		bool mTransposeMatrices;

+ 22 - 0
BansheeCore/Include/BsMaterial.h

@@ -125,6 +125,15 @@ namespace BansheeEngine
 		/** @brief	Assigns a texture to the shader parameter with the specified name. */
 		void setTexture(const String& name, const HTexture& value) { return getParamTexture(name).set(value); }
 
+		/** 
+		 * @brief	Assigns a texture to be used for random load/store operations to the
+		 *			shader parameter with the specified name.
+		 */
+		void setLoadStoreTexture(const String& name, const HTexture& value, const TextureSurface& surface) 
+		{ 
+			return getParamLoadStoreTexture(name).set(value, surface); 
+		}
+
 		/** @brief	Assigns a sampler state to the shader parameter with the specified name. */
 		void setSamplerState(const String& name, const HSamplerState& value) { return getParamSamplerState(name).set(value); }
 
@@ -375,6 +384,19 @@ namespace BansheeEngine
 		 */
 		GpuParamTexture getParamTexture(const String& name) const;
 
+		/**
+		 * @brief	Returns a GPU parameter for binding a load/store texture. This parameter 
+		 *			may be used for more efficiently getting/setting GPU parameter values 
+		 *			than calling Material::get* / Material::set* methods. 
+		 *
+		 * @note	Expected behavior is that you would retrieve this parameter when
+		 * 			initially constructing the material, and then use it throughout material
+		 * 			lifetime to assign and retrieve parameter values.
+		 * 			
+		 *			If material shader changes this handle will be invalidated.
+		 */
+		GpuParamLoadStoreTexture getParamLoadStoreTexture(const String& name) const;
+
 		/**
 		 * @brief	Returns a sampler state GPU parameter. This parameter may be used for
 		 * 			more efficiently getting/setting GPU parameter values than calling

+ 6 - 0
BansheeCore/Include/BsRenderSystem.h

@@ -86,6 +86,12 @@ namespace BansheeEngine
 		*/
 		virtual void disableTextureUnit(GpuProgramType gptype, UINT16 texUnit);
 
+		/**
+		 * @brief	Binds a texture that can be used for random load/store operations from a GPU program.
+		 */
+		virtual void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, 
+			const TexturePtr& texPtr, const TextureSurface& surface) = 0;
+
 		/**
 		 * @brief	Signals that rendering for a specific viewport has started. Any draw calls
 		 *			need to be called between beginFrame and endFrame. You may not switch render targets

+ 0 - 1
BansheeCore/Include/BsRenderTarget.h

@@ -16,7 +16,6 @@ namespace BansheeEngine
 	{
 		TexturePtr texture;
 		UINT32 face;
-		UINT32 numFaces;
 		UINT32 mipLevel;
 	};
 

+ 1 - 0
BansheeCore/Include/BsTexture.h

@@ -17,6 +17,7 @@ namespace BansheeEngine
 		TU_DYNAMIC = GBU_DYNAMIC, /**< A regular texture that is often updated by the CPU. */
 		TU_RENDERTARGET = 0x200, /**< Texture used for rendering by the GPU. */
 		TU_DEPTHSTENCIL = 0x400, /**< Texture used as a depth/stencil buffer by the GPU. */
+		TU_LOADSTORE = 0x800, /**< Texture that allows load/store operations from the GPU program. */
 		TU_DEFAULT = TU_STATIC
     };
 

+ 7 - 0
BansheeCore/Source/BsCoreThreadAccessor.cpp

@@ -34,6 +34,13 @@ namespace BansheeEngine
 		mCommandQueue->queue(std::bind(&RenderSystem::setTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr));
 	}
 
+	void CoreThreadAccessorBase::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		UINT32 mipLevel, UINT32 arraySlice, UINT32 numSlices)
+	{
+		mCommandQueue->queue(std::bind(&RenderSystem::setLoadStoreTexture, RenderSystem::instancePtr(), gptype, unit, enabled, texPtr, 
+			mipLevel, arraySlice, numSlices));
+	}
+
 	void CoreThreadAccessorBase::setSamplerState(GpuProgramType gptype, UINT16 texUnit, const SamplerStatePtr& samplerState)
 	{
 		mCommandQueue->queue(std::bind(&RenderSystem::setSamplerState, RenderSystem::instancePtr(), gptype, texUnit, samplerState));

+ 32 - 0
BansheeCore/Source/BsGpuParam.cpp

@@ -131,6 +131,7 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
 
 		mInternalData->mTextures[mParamDesc->slot] = texture;
+		mInternalData->mTextureInfo[mParamDesc->slot].isLoadStore = false;
 		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF;
 	}
 
@@ -142,6 +143,37 @@ namespace BansheeEngine
 		return mInternalData->mTextures[mParamDesc->slot];
 	}
 
+	/************************************************************************/
+	/* 							LOAD/STORE TEXTURE		                    */
+	/************************************************************************/
+
+	GpuParamLoadStoreTexture::GpuParamLoadStoreTexture()
+		:mParamDesc(nullptr)
+	{ }
+
+	GpuParamLoadStoreTexture::GpuParamLoadStoreTexture(GpuParamObjectDesc* paramDesc, const std::shared_ptr<GpuParamsInternalData>& internalData)
+		: mParamDesc(paramDesc), mInternalData(internalData)
+	{ }
+
+	void GpuParamLoadStoreTexture::set(const HTexture& texture, const TextureSurface& surface)
+	{
+		if (mInternalData->mIsDestroyed)
+			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		mInternalData->mTextures[mParamDesc->slot] = texture;
+		mInternalData->mTextureInfo[mParamDesc->slot].isLoadStore = true;
+		mInternalData->mTextureInfo[mParamDesc->slot].surface = surface;
+		mInternalData->mCoreDirtyFlags = 0xFFFFFFFF;
+	}
+
+	HTexture GpuParamLoadStoreTexture::get()
+	{
+		if (mInternalData->mIsDestroyed)
+			BS_EXCEPT(InternalErrorException, "Trying to access a destroyed gpu parameter.");
+
+		return mInternalData->mTextures[mParamDesc->slot];
+	}
+
 	/************************************************************************/
 	/* 								SAMPLER STATE                      		*/
 	/************************************************************************/

+ 52 - 4
BansheeCore/Source/BsGpuParams.cpp

@@ -12,7 +12,7 @@ namespace BansheeEngine
 	GpuParamsInternalData::GpuParamsInternalData()
 		:mTransposeMatrices(false), mData(nullptr), mNumParamBlocks(0), mNumTextures(0), mNumSamplerStates(0), mFrameAlloc(nullptr),
 		mParamBlocks(nullptr), mParamBlockBuffers(nullptr), mTextures(nullptr), mSamplerStates(nullptr), mCoreDirtyFlags(0xFFFFFFFF),
-		mIsDestroyed(false)
+		mIsDestroyed(false), mTextureInfo(nullptr)
 	{ }
 
 	GpuParams::GpuParams(const GpuParamDescPtr& paramDesc, bool transposeMatrices)
@@ -62,6 +62,9 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
 			mInternalData->mTextures[i].~ResourceHandle();
 
+		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
+			mInternalData->mTextureInfo[i].~BoundTextureInfo();
+
 		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
 			mInternalData->mSamplerStates[i].~ResourceHandle();
 
@@ -162,6 +165,16 @@ namespace BansheeEngine
 		output = GpuParamTexture(&iterFind->second, mInternalData);
 	}
 
+	void GpuParams::getLoadStoreTextureParam(const String& name, GpuParamLoadStoreTexture& output) const
+	{
+		auto iterFind = mParamDesc->textures.find(name);
+
+		if (iterFind == mParamDesc->textures.end())
+			BS_EXCEPT(InvalidParametersException, "Cannot find texture parameter with the name '" + name + "'");
+
+		output = GpuParamLoadStoreTexture(&iterFind->second, mInternalData);
+	}
+
 	void GpuParams::getSamplerStateParam(const String& name, GpuParamSampState& output) const
 	{
 		auto iterFind = mParamDesc->samplers.find(name);
@@ -214,6 +227,28 @@ namespace BansheeEngine
 		return mInternalData->mSamplerStates[slot];
 	}
 
+	bool GpuParams::isLoadStoreTexture(UINT32 slot) const
+	{
+		if (slot < 0 || slot >= mInternalData->mNumTextures)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mInternalData->mNumTextures - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mInternalData->mTextureInfo[slot].isLoadStore;
+	}
+
+	const TextureSurface& GpuParams::getLoadStoreSurface(UINT32 slot) const
+	{
+		if (slot < 0 || slot >= mInternalData->mNumTextures)
+		{
+			BS_EXCEPT(InvalidParametersException, "Index out of range: Valid range: 0 .. " +
+				toString(mInternalData->mNumTextures - 1) + ". Requested: " + toString(slot));
+		}
+
+		return mInternalData->mTextureInfo[slot].surface;
+	}
+
 	void GpuParams::updateHardwareBuffers()
 	{
 		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
@@ -235,6 +270,7 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
 		{
 			mInternalData->mTextures[i] = copy->mInternalData->mTextures[i];
+			mInternalData->mTextureInfo[i] = copy->mInternalData->mTextureInfo[i];
 		}
 
 		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
@@ -305,6 +341,7 @@ namespace BansheeEngine
 		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
 		{
 			myClone->mInternalData->mTextures[i] = mInternalData->mTextures[i];
+			myClone->mInternalData->mTextureInfo[i] = mInternalData->mTextureInfo[i];
 		}
 
 		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)
@@ -323,17 +360,20 @@ namespace BansheeEngine
 		UINT32 paramBlockBufferOffset = 0;
 		UINT32 textureOffset = 0;
 		UINT32 samplerStateOffset = 0;
+		UINT32 textureInfoOffset = 0;
 
 		UINT32 paramBlockBufferSize = mInternalData->mNumParamBlocks * sizeof(GpuParamBlockPtr);
 		UINT32 paramBlockBuffersBufferSize = mInternalData->mNumParamBlocks * sizeof(GpuParamBlockBufferPtr);
 		UINT32 textureBufferSize = mInternalData->mNumTextures * sizeof(HTexture);
+		UINT32 textureInfoBufferSize = mInternalData->mNumTextures * sizeof(BoundTextureInfo);
 		UINT32 samplerStateBufferSize = mInternalData->mNumSamplerStates * sizeof(HSamplerState);
 
-		bufferSize = paramBlockBufferSize + paramBlockBuffersBufferSize + textureBufferSize + samplerStateBufferSize;
+		bufferSize = paramBlockBufferSize + paramBlockBuffersBufferSize + textureBufferSize + samplerStateBufferSize + textureInfoBufferSize;
 		paramBlockOffset = 0;
 		paramBlockBufferOffset = paramBlockOffset + paramBlockBufferSize;
 		textureOffset = paramBlockBufferOffset + paramBlockBuffersBufferSize;
 		samplerStateOffset = textureOffset + textureBufferSize;
+		textureInfoOffset = samplerStateOffset + textureInfoBufferSize;
 
 		if (frameAlloc != nullptr)
 		{
@@ -350,6 +390,7 @@ namespace BansheeEngine
 		mInternalData->mParamBlockBuffers = (GpuParamBlockBufferPtr*)(mInternalData->mData + paramBlockBufferOffset);
 		mInternalData->mTextures = (HTexture*)(mInternalData->mData + textureOffset);
 		mInternalData->mSamplerStates = (HSamplerState*)(mInternalData->mData + samplerStateOffset);
+		mInternalData->mTextureInfo = (BoundTextureInfo*)(mInternalData->mData + textureInfoOffset);
 
 		// Ensure everything is constructed
 		for (UINT32 i = 0; i < mInternalData->mNumParamBlocks; i++)
@@ -367,8 +408,15 @@ namespace BansheeEngine
 
 		for (UINT32 i = 0; i < mInternalData->mNumTextures; i++)
 		{
-			HTexture* ptrToIdx = (&mInternalData->mTextures[i]);
-			ptrToIdx = new (&mInternalData->mTextures[i]) HTexture();
+			{
+				HTexture* ptrToIdx = (&mInternalData->mTextures[i]);
+				ptrToIdx = new (&mInternalData->mTextures[i]) HTexture();
+			}
+
+			{
+				BoundTextureInfo* ptrToIdx = (&mInternalData->mTextureInfo[i]);
+				ptrToIdx = new (&mInternalData->mTextureInfo[i]) BoundTextureInfo();
+			}
 		}
 
 		for (UINT32 i = 0; i < mInternalData->mNumSamplerStates; i++)

+ 20 - 0
BansheeCore/Source/BsMaterial.cpp

@@ -629,6 +629,26 @@ namespace BansheeEngine
 		return gpuParam;
 	}
 
+	GpuParamLoadStoreTexture Material::getParamLoadStoreTexture(const String& name) const
+	{
+		throwIfNotInitialized();
+
+		GpuParamLoadStoreTexture gpuParam;
+
+		auto iterFind = mValidParams.find(name);
+		if (iterFind == mValidParams.end())
+		{
+			LOGWRN("Material doesn't have a parameter named " + name);
+			return gpuParam;
+		}
+
+		const String& gpuVarName = iterFind->second;
+		GpuParamsPtr params = findTexWithName(gpuVarName);
+
+		params->getLoadStoreTextureParam(gpuVarName, gpuParam);
+		return gpuParam;
+	}
+
 	GpuParamSampState Material::getParamSamplerState(const String& name) const
 	{
 		throwIfNotInitialized();

+ 2 - 2
BansheeCore/Source/BsMultiRenderTexture.cpp

@@ -30,7 +30,7 @@ namespace BansheeEngine
 					BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
 				mColorSurfaces[i] = Texture::requestView(texture, desc.colorSurfaces[i].mipLevel, 1,
-					desc.colorSurfaces[i].face, desc.colorSurfaces[i].numFaces, GVU_RENDERTARGET);
+					desc.colorSurfaces[i].face, 1, GVU_RENDERTARGET);
 			}
 		}
 
@@ -42,7 +42,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
 			mDepthStencilSurface = Texture::requestView(texture, desc.depthStencilSurface.mipLevel, 1,
-				desc.depthStencilSurface.face, desc.depthStencilSurface.numFaces, GVU_DEPTHSTENCIL);
+				desc.depthStencilSurface.face, 1, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();

+ 2 - 2
BansheeCore/Source/BsRenderTexture.cpp

@@ -20,7 +20,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
 			mColorSurface = Texture::requestView(texture, colorSurfaceDesc.mipLevel, 1,
-				colorSurfaceDesc.face, colorSurfaceDesc.numFaces, GVU_RENDERTARGET);
+				colorSurfaceDesc.face, 1, GVU_RENDERTARGET);
 		}
 
 		if (depthStencilSurfaceDesc.texture != nullptr)
@@ -31,7 +31,7 @@ namespace BansheeEngine
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
 			mDepthStencilSurface = Texture::requestView(texture, depthStencilSurfaceDesc.mipLevel, 1,
-				depthStencilSurfaceDesc.face, depthStencilSurfaceDesc.numFaces, GVU_DEPTHSTENCIL);
+				depthStencilSurfaceDesc.face, 1, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();

+ 2 - 3
BansheeCore/Source/BsShader.cpp

@@ -220,6 +220,7 @@ namespace BansheeEngine
 			case GPOT_SAMPLER2D:
 			case GPOT_SAMPLER3D:
 			case GPOT_SAMPLERCUBE:
+			case GPOT_SAMPLER2DMS:
 				return true;
 		}
 
@@ -234,9 +235,7 @@ namespace BansheeEngine
 		case GPOT_TEXTURE2D:
 		case GPOT_TEXTURE3D:
 		case GPOT_TEXTURECUBE:
-		case GPOT_RWTEXTURE1D:
-		case GPOT_RWTEXTURE2D:
-		case GPOT_RWTEXTURE3D:
+		case GPOT_TEXTURE2DMS:
 			return true;
 		}
 

+ 8 - 0
BansheeD3D11RenderSystem/Include/BsD3D11RenderSystem.h

@@ -50,6 +50,12 @@ namespace BansheeEngine
 		 */
 		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
 
+		/**
+		 * @copydoc	RenderSystem::setLoadStoreTexture
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+			const TextureSurface& surface);
+
 		/**
 		 * @copydoc	RenderSystem::disableTextureUnit
 		 */
@@ -238,6 +244,8 @@ namespace BansheeEngine
 		D3D11HLSLProgramFactory* mHLSLFactory;
 		D3D11InputLayoutManager* mIAManager;
 
+		std::pair<TexturePtr, TextureViewPtr> mBoundUAVs[D3D11_PS_CS_UAV_REGISTER_COUNT];
+
 		UINT32 mStencilRef;
 		D3D11_VIEWPORT mViewport;
 		D3D11_RECT mScissorRect;

+ 7 - 0
BansheeD3D11RenderSystem/Include/BsD3D11Texture.h

@@ -23,6 +23,13 @@ namespace BansheeEngine
 		 */
 		ID3D11ShaderResourceView* getSRV() const { return mShaderResourceView; }
 
+		/**
+		 * @brief	Returns unordered access view associated with the texture.
+		 *
+		 * @note	Used for random read/write operations from GPU programs.
+		 */
+		ID3D11UnorderedAccessView* getUAV() const { return mUnorderedAccessView; }
+
 		/**
 		 * @brief	Returns DXGI pixel format used by the texture.
 		 */

+ 3 - 0
BansheeD3D11RenderSystem/Source/BsD3D11HLSLParamParser.cpp

@@ -120,6 +120,9 @@ namespace BansheeEngine
 					case D3D_SRV_DIMENSION_TEXTURECUBE:
 						memberDesc.type = GPOT_TEXTURECUBE;
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE2DMS:
+						memberDesc.type = GPOT_TEXTURE2DMS;
+						break;
 					default:
 						LOGWRN("Skipping texture because it has unsupported dimension: " + toString(resourceDesc.Dimension));
 					}

+ 70 - 4
BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp

@@ -18,6 +18,7 @@
 #include "BsD3D11RenderStateManager.h"
 #include "BsD3D11GpuParamBlockBuffer.h"
 #include "BsD3D11InputLayoutManager.h"
+#include "BsD3D11TextureView.h"
 #include "BsD3D11RenderUtility.h"
 #include "BsGpuParams.h"
 #include "BsCoreThread.h"
@@ -141,6 +142,12 @@ namespace BansheeEngine
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		for (auto& boundUAV : mBoundUAVs)
+		{
+			if (boundUAV.second != nullptr)
+				boundUAV.first->releaseView(boundUAV.second);
+		}
+
 		QueryManager::shutDown();
 		D3D11RenderUtility::shutDown();
 
@@ -255,7 +262,6 @@ namespace BansheeEngine
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		// TODO - Set up UAVs?
 		// TODO - I'm setting up views one by one, it might be more efficient to hold them in an array
 		//  and then set them all up at once before rendering? Needs testing
 
@@ -295,6 +301,54 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumTextureBinds);
 	}
 
+	void D3D11RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - This hasn't bee tested and might be incorrect. I might need to set UAVs together with render targets,
+		// especially considering DX11 expects number of UAVs to match number of render targets.
+
+		ID3D11UnorderedAccessView* viewArray[1];
+		if (texPtr != nullptr && enabled)
+		{
+			D3D11Texture* d3d11Texture = static_cast<D3D11Texture*>(texPtr.get());
+			TextureViewPtr texView = Texture::requestView(texPtr, surface.mipLevel, 1, 
+				surface.arraySlice, surface.numArraySlices, GVU_RANDOMWRITE);
+
+			D3D11TextureView* d3d11texView = static_cast<D3D11TextureView*>(texView.get());
+			viewArray[0] = d3d11texView->getUAV();
+
+			if (mBoundUAVs[unit].second != nullptr)
+				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+
+			mBoundUAVs[unit] = std::make_pair(texPtr, texView);
+		}
+		else
+		{
+			viewArray[0] = nullptr;
+
+			if (mBoundUAVs[unit].second != nullptr)
+				mBoundUAVs[unit].first->releaseView(mBoundUAVs[unit].second);
+
+			mBoundUAVs[unit] = std::pair<TexturePtr, TextureViewPtr>();
+		}
+
+		if (gptype == GPT_FRAGMENT_PROGRAM)
+		{
+			mDevice->getImmediateContext()->OMSetRenderTargetsAndUnorderedAccessViews(
+				D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, unit, 1, viewArray, nullptr);
+		}
+		else if (gptype == GPT_COMPUTE_PROGRAM)
+		{
+			mDevice->getImmediateContext()->CSSetUnorderedAccessViews(unit, 1, viewArray, nullptr);
+		}
+		else
+			BS_EXCEPT(InvalidParametersException, "Unsupported gpu program type: " + toString(gptype));
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
 	void D3D11RenderSystem::disableTextureUnit(GpuProgramType gptype, UINT16 texUnit)
 	{
 		THROW_IF_NOT_CORE_THREAD;
@@ -509,10 +563,22 @@ namespace BansheeEngine
 		{
 			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
-			if(!texture.isLoaded())
-				setTexture(gptype, iter->second.slot, false, nullptr);
+			if (!bindableParams->isLoadStoreTexture(iter->second.slot))
+			{
+				if (!texture.isLoaded())
+					setTexture(gptype, iter->second.slot, false, nullptr);
+				else
+					setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+			}
 			else
-				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+			{
+				const TextureSurface& surface = bindableParams->getLoadStoreSurface(iter->second.slot);
+
+				if (!texture.isLoaded())
+					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
+				else
+					setLoadStoreTexture(gptype, iter->second.slot, true, texture.getInternalPtr(), surface);
+			}
 		}
 
 		// TODO - I assign constant buffers one by one but it might be more efficient to do them all at once?

+ 11 - 2
BansheeD3D11RenderSystem/Source/BsD3D11Texture.cpp

@@ -175,13 +175,13 @@ namespace BansheeEngine
 		if (mMultisampleCount > 0)
 			BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
 
-		if(mUsage == TU_DYNAMIC)
+		if((mUsage & TU_DYNAMIC) != 0)
 		{
 			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
 			PixelUtil::bulkPixelConversion(src, myData);
 			unlock();
 		}
-		else if(mUsage == TU_STATIC || mUsage == TU_RENDERTARGET || mUsage == TU_DEPTHSTENCIL)
+		else if ((mUsage & TU_DEPTHSTENCIL) == 0)
 		{
 			mipLevel = Math::clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
 			face = Math::clamp(face, (UINT32)0, mDepth - 1);
@@ -257,6 +257,9 @@ namespace BansheeEngine
 			desc.MipLevels		= numMips;
 		}
 
+		if ((mUsage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
 		// Create the texture
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
@@ -384,6 +387,9 @@ namespace BansheeEngine
             desc.ArraySize       = 6;
         }
 
+		if ((mUsage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
 		// Create the texture
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
@@ -519,6 +525,9 @@ namespace BansheeEngine
 			desc.MipLevels		= numMips;
 		}
 
+		if ((mUsage & TU_LOADSTORE) != 0)
+			desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+
 		// Create the texture
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();

+ 38 - 7
BansheeD3D11RenderSystem/Source/BsD3D11TextureView.cpp

@@ -56,12 +56,16 @@ namespace BansheeEngine
 			desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			desc.Texture2D.MipLevels = numMips;
-			desc.Texture2D.MostDetailedMip = mostDetailMip;
-			if(texture->getMultisampleCount() > 0)
+			if (texture->getMultisampleCount() > 0)
+			{
 				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+			}
 			else
+			{
 				desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+				desc.Texture2D.MipLevels = numMips;
+				desc.Texture2D.MostDetailedMip = mostDetailMip;
+			}
 			break;
 		case TEX_TYPE_3D:
 			desc.Texture3D.MipLevels = numMips;
@@ -106,11 +110,15 @@ namespace BansheeEngine
 			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			desc.Texture2D.MipSlice = mipSlice;
-			if(texture->getMultisampleCount() > 0)
+			if (texture->getMultisampleCount() > 0)
+			{
 				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+			}
 			else
+			{
 				desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+				desc.Texture2D.MipSlice = mipSlice;
+			}
 			break;
 		case TEX_TYPE_3D:
 			desc.Texture3D.MipSlice = mipSlice;
@@ -118,6 +126,12 @@ namespace BansheeEngine
 			desc.Texture3D.WSize = numArraySlices;
 			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
 			break;
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
 		}
@@ -160,6 +174,12 @@ namespace BansheeEngine
 			desc.Texture3D.WSize = numArraySlices;
 			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
 			break;
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");
 		}
@@ -193,11 +213,22 @@ namespace BansheeEngine
 			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
 			break;
 		case TEX_TYPE_2D:
-			desc.Texture2D.MipSlice = mipSlice;
-			if(texture->getMultisampleCount() > 0)
+			if (texture->getMultisampleCount() > 0)
+			{
 				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+			}
 			else
+			{
+				desc.Texture2D.MipSlice = mipSlice;
 				desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+			}
+			break;
+		case TEX_TYPE_3D:
+		case TEX_TYPE_CUBE_MAP:
+			desc.Texture2DArray.FirstArraySlice = firstArraySlice;
+			desc.Texture2DArray.ArraySize = numArraySlices;
+			desc.Texture2DArray.MipSlice = mipSlice;
+			desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
 			break;
 		default:
 			BS_EXCEPT(InvalidParametersException, "Invalid texture type for this view type.");

+ 7 - 1
BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h

@@ -71,10 +71,16 @@ namespace BansheeEngine
 		void setDrawOperation(DrawOperationType op);
 
 		/**
-		 * @copydoc RenderSystem::setSamplerState()
+		 * @copydoc RenderSystem::setTexture()
 		 */
 		void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &texPtr);
 
+		/**
+		 * @copydoc RenderSystem::setLoadStoreTexture()
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+			const TextureSurface& surface);
+
 		/**
 		 * @copydoc RenderSystem::setSamplerState()
 		 */

+ 17 - 6
BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp

@@ -14,9 +14,14 @@ namespace BansheeEngine
 			if (mColorSurfaces[i] != nullptr)
 			{
 				D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurfaces[i]->getTexture().get());
-				D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
-					d3d9texture->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, mColorSurfaces[i]->getDesc().mostDetailMip).get());
-				mDX9ColorSurfaces[i] = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+				if (d3d9texture->getTextureType() != TEX_TYPE_3D)
+				{
+					D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
+						d3d9texture->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, mColorSurfaces[i]->getDesc().mostDetailMip).get());
+					mDX9ColorSurfaces[i] = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+				}
+				else
+					mDX9ColorSurfaces[i] = nullptr;
 			}
 			else
 			{
@@ -27,9 +32,15 @@ namespace BansheeEngine
 		if (mDepthStencilSurface != nullptr)
 		{
 			D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
-			D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
-				d3d9DepthStencil->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, mDepthStencilSurface->getDesc().mostDetailMip).get());
-			mDX9DepthStencilSurface = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+
+			if (d3d9DepthStencil->getTextureType() != TEX_TYPE_3D)
+			{
+				D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
+					d3d9DepthStencil->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, mDepthStencilSurface->getDesc().mostDetailMip).get());
+				mDX9DepthStencilSurface = pixelBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
+			}
+			else
+				mDX9DepthStencilSurface = nullptr;
 		}
 		else
 		{

+ 11 - 0
BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp

@@ -287,6 +287,9 @@ namespace BansheeEngine
 
 		for(auto iter = paramDesc.textures.begin(); iter != paramDesc.textures.end(); ++iter)
 		{
+			if (bindableParams->isLoadStoreTexture(iter->second.slot))
+				continue; // Not supported by DX9
+
 			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
 			if(!texture.isLoaded())
@@ -509,6 +512,14 @@ namespace BansheeEngine
 		}
 	}
 
+	void D3D9RenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		LOGWRN("Texture random load/store not supported on DX9.");
+	}
+
 	void D3D9RenderSystem::setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerStatePtr& state)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 2 - 6
BansheeD3D9RenderSystem/Source/BsD3D9Texture.cpp

@@ -513,12 +513,6 @@ namespace BansheeEngine
 	{
 		assert(mWidth > 0 || mHeight > 0);
 
-		if (mUsage & TU_RENDERTARGET)
-			BS_EXCEPT(RenderingAPIException, "D3D9 Cube texture can not be created as render target !!");
-
-		if (mUsage & TU_DEPTHSTENCIL)
-			BS_EXCEPT(RenderingAPIException, "D3D9 Cube texture can not be created as a depth stencil target !!");
-
 		D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
 		if(mFormat != D3D9Mappings::_getPF(d3dPF))
 		{
@@ -527,6 +521,8 @@ namespace BansheeEngine
 
 		// Use D3DX to help us create the texture, this way it can adjust any relevant sizes
 		DWORD usage = (mUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
+		usage |= (mUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
+
 		UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ? D3DX_DEFAULT : mNumMipmaps + 1;
 
 		// Check dynamic textures

+ 24 - 0
BansheeEngine/Include/BsCameraHandler.h

@@ -159,6 +159,13 @@ namespace BansheeEngine
 		 */
         virtual const Matrix4& getProjectionMatrixRS() const;
 
+		/** 
+		 * @brief	Returns the inverse of the render-system specific projection matrix.
+		 *
+		 * @see		getProjectionMatrixRS
+		 */
+        virtual const Matrix4& getProjectionMatrixRSInv() const;
+
 		/** 
 		 * @brief	Returns the standard projection matrix that determines how are 3D points
 		 *			projected to two dimensions. Returned matrix is standard following right-hand
@@ -169,11 +176,25 @@ namespace BansheeEngine
          */
         virtual const Matrix4& getProjectionMatrix() const;
 
+		/** 
+		 * @brief	Returns the inverse of the projection matrix.
+		 *
+		 * @see		getProjectionMatrix
+		 */
+        virtual const Matrix4& getProjectionMatrixInv() const;
+
 		/** 
 		 * @brief	Gets the camera view matrix. Used for positioning/orienting the camera.
          */
         virtual const Matrix4& getViewMatrix() const;
 
+		/** 
+		 * @brief	Returns the inverse of the view matrix.
+		 *
+		 * @see		getViewMatrix
+		 */
+		virtual const Matrix4& getViewMatrixInv() const;
+
 		/** 
 		 * @brief	Sets whether the camera should use the custom view matrix.
 		 *			When this is enabled camera will no longer calculate its view matrix
@@ -498,6 +519,9 @@ namespace BansheeEngine
 		mutable Matrix4 mProjMatrixRS; /**< Cached render-system specific projection matrix. */
 		mutable Matrix4 mProjMatrix; /**< Cached projection matrix that determines how are 3D points projected to a 2D viewport. */
 		mutable Matrix4 mViewMatrix; /**< Cached view matrix that determines camera position/orientation. */
+		mutable Matrix4 mProjMatrixRSInv;
+		mutable Matrix4 mProjMatrixInv;
+		mutable Matrix4 mViewMatrixInv;
 
 		mutable ConvexVolume mFrustum; /**< Main clipping planes describing cameras visible area. */
 		mutable bool mRecalcFrustum; /**< Should frustum be recalculated. */

+ 28 - 0
BansheeEngine/Source/BsCameraHandler.cpp

@@ -24,6 +24,9 @@ namespace BansheeEngine
 	{
 		mViewMatrix = Matrix4::ZERO;
 		mProjMatrixRS = Matrix4::ZERO;
+		mViewMatrixInv = Matrix4::ZERO;
+		mProjMatrixRSInv = Matrix4::ZERO;
+		mProjMatrixInv = Matrix4::ZERO;
 
 		invalidateFrustum();
 
@@ -83,6 +86,13 @@ namespace BansheeEngine
 		return mProjMatrix;
 	}
 
+	const Matrix4& CameraHandler::getProjectionMatrixInv() const
+	{
+		updateFrustum();
+
+		return mProjMatrixInv;
+	}
+
 	const Matrix4& CameraHandler::getProjectionMatrixRS() const
 	{
 		updateFrustum();
@@ -90,6 +100,13 @@ namespace BansheeEngine
 		return mProjMatrixRS;
 	}
 
+	const Matrix4& CameraHandler::getProjectionMatrixRSInv() const
+	{
+		updateFrustum();
+
+		return mProjMatrixRSInv;
+	}
+
 	const Matrix4& CameraHandler::getViewMatrix() const
 	{
 		updateView();
@@ -97,6 +114,13 @@ namespace BansheeEngine
 		return mViewMatrix;
 	}
 
+	const Matrix4& CameraHandler::getViewMatrixInv() const
+	{
+		updateView();
+
+		return mViewMatrixInv;
+	}
+
 	const ConvexVolume& CameraHandler::getFrustum() const
 	{
 		// Make any pending updates to the calculated frustum planes
@@ -261,6 +285,8 @@ namespace BansheeEngine
 
 			RenderSystem* renderSystem = BansheeEngine::RenderSystem::instancePtr();
 			renderSystem->convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
+			mProjMatrixInv = mProjMatrix.inverse();
+			mProjMatrixRSInv = mProjMatrixRS.inverse();
 
 			// Calculate bounding box (local)
 			// Box is from 0, down -Z, max dimensions as determined from far plane
@@ -305,6 +331,7 @@ namespace BansheeEngine
 		if (!mCustomViewMatrix && mRecalcView)
 		{
 			mViewMatrix.makeView(mPosition, mRotation);
+			mViewMatrixInv = mViewMatrix.inverseAffine();
 			mRecalcView = false;
 		}
 	}
@@ -397,6 +424,7 @@ namespace BansheeEngine
 		{
 			assert(viewMatrix.isAffine());
 			mViewMatrix = viewMatrix;
+			mViewMatrixInv = mViewMatrix.inverseAffine();
 		}
 
 		markCoreDirty();

+ 6 - 0
BansheeGLRenderSystem/Include/BsGLRenderSystem.h

@@ -62,6 +62,12 @@ namespace BansheeEngine
 		 * @copydoc RenderSystem::setTexture()
 		 */
         void setTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr &tex);
+
+		/**
+		 * @copydoc	RenderSystem::setLoadStoreTexture
+		 */
+		void setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+			const TextureSurface& surface);
         
 		/**
 		 * @copydoc RenderSystem::setSamplerState()

+ 6 - 0
BansheeGLRenderSystem/Include/BsGLTexture.h

@@ -25,6 +25,11 @@ namespace BansheeEngine
 		 * @brief	Returns internal OpenGL texture handle.
 		 */
         GLuint getGLID() const;
+
+		/**
+		 * @brief	Returns the internal OpenGL format used by the texture.
+		 */
+		GLenum getGLFormat() const { return mGLFormat; }
 		
 		/**
 		 * @brief	Returns a hardware pixel buffer for a certain face and level of the texture.
@@ -85,6 +90,7 @@ namespace BansheeEngine
 
     private:
         GLuint mTextureID;
+		GLenum mGLFormat;
         GLSupport& mGLSupport;
 		std::shared_ptr<GLPixelBuffer> mLockedBuffer;
 		

+ 21 - 8
BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp

@@ -16,13 +16,22 @@ namespace BansheeEngine
 			if (mColorSurfaces[i] != nullptr)
 			{
 				GLTexture* glColorSurface = static_cast<GLTexture*>(mColorSurfaces[i]->getTexture().get());
-				GLPixelBufferPtr colorBuffer =
-					glColorSurface->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice,
-					mColorSurfaces[i]->getDesc().mostDetailMip);
-
+				GLPixelBufferPtr colorBuffer = nullptr;
 				GLSurfaceDesc surfaceDesc;
+
+				if (glColorSurface->getTextureType() != TEX_TYPE_3D)
+				{
+					surfaceDesc.zoffset = 0;
+					colorBuffer = glColorSurface->getBuffer(mColorSurfaces[i]->getFirstArraySlice,
+						mColorSurfaces[i]->getMostDetailedMip);
+				}
+				else
+				{
+					surfaceDesc.zoffset = mColorSurfaces[i]->getFirstArraySlice;
+					colorBuffer = glColorSurface->getBuffer(0, mColorSurfaces[i]->getMostDetailedMip);
+				}
+				
 				surfaceDesc.numSamples = getProperties().getMultisampleCount();
-				surfaceDesc.zoffset = 0;
 				surfaceDesc.buffer = colorBuffer;
 
 				mFB->bindSurface((UINT32)i, surfaceDesc);
@@ -36,9 +45,13 @@ namespace BansheeEngine
 		if (mDepthStencilSurface != nullptr)
 		{
 			GLTexture* glDepthStencilSurface = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-			GLPixelBufferPtr depthStencilBuffer =
-				glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice,
-				mDepthStencilSurface->getDesc().mostDetailMip);
+			GLPixelBufferPtr depthStencilBuffer = nullptr;
+
+			if (glDepthStencilSurface->getTextureType() != TEX_TYPE_3D)
+			{
+				depthStencilBuffer = glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice,
+					mDepthStencilSurface->getDesc().mostDetailMip);
+			}
 
 			mFB->bindDepthStencil(depthStencilBuffer);
 		}

+ 60 - 3
BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp

@@ -253,10 +253,22 @@ namespace BansheeEngine
 		{
 			HTexture texture = bindableParams->getTexture(iter->second.slot);
 
-			if(!texture.isLoaded())
-				setTexture(gptype, iter->second.slot, false, nullptr);
+			if (!bindableParams->isLoadStoreTexture(iter->second.slot))
+			{
+				if (!texture.isLoaded())
+					setTexture(gptype, iter->second.slot, false, nullptr);
+				else
+					setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+			}
 			else
-				setTexture(gptype, iter->second.slot, true, texture.getInternalPtr());
+			{
+				const TextureSurface& surface = bindableParams->getLoadStoreSurface(iter->second.slot);
+
+				if (!texture.isLoaded())
+					setLoadStoreTexture(gptype, iter->second.slot, false, nullptr, surface);
+				else
+					setLoadStoreTexture(gptype, iter->second.slot, true, texture.getInternalPtr(), surface);
+			}
 		}
 
 		for(auto iter = paramDesc.samplers.begin(); iter != paramDesc.samplers.end(); ++iter)
@@ -453,6 +465,51 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT(NumSamplerBinds);
 	}
 
+	void GLRenderSystem::setLoadStoreTexture(GpuProgramType gptype, UINT16 unit, bool enabled, const TexturePtr& texPtr,
+		const TextureSurface& surface)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		// TODO - OpenGL can't bind a certain subset of faces like DX11, only zero, one or all, so I'm ignoring numSlices parameter
+		if (texPtr != nullptr)
+		{
+			GLTexturePtr tex = std::static_pointer_cast<GLTexture>(texPtr);
+			glBindImageTexture(unit, tex->getGLID(), surface.mipLevel, surface.numArraySlices > 1, 
+				surface.arraySlice, tex->getGLFormat(), GL_READ_WRITE);
+		}
+		else
+			glBindImageTexture(unit, 0, 0, false, 0, 0, GL_READ_WRITE);
+
+		BS_INC_RENDER_STAT(NumTextureBinds);
+	}
+
+	void GLRenderSystem::setSamplerState(GpuProgramType gptype, UINT16 unit, const SamplerStatePtr& state)
+	{
+		THROW_IF_NOT_CORE_THREAD;
+
+		unit = getGLTextureUnit(gptype, unit);
+
+		// Set texture layer filtering
+		setTextureFiltering(unit, FT_MIN, state->getTextureFiltering(FT_MIN));
+		setTextureFiltering(unit, FT_MAG, state->getTextureFiltering(FT_MAG));
+		setTextureFiltering(unit, FT_MIP, state->getTextureFiltering(FT_MIP));
+
+		// Set texture anisotropy
+		setTextureAnisotropy(unit, state->getTextureAnisotropy());
+
+		// Set mipmap biasing
+		setTextureMipmapBias(unit, state->getTextureMipmapBias());
+
+		// Texture addressing mode
+		const UVWAddressingMode& uvw = state->getTextureAddressingMode();
+		setTextureAddressingMode(unit, uvw);
+
+		// Set border color
+		setTextureBorderColor(unit, state->getBorderColor());
+
+		BS_INC_RENDER_STAT(NumSamplerBinds);
+	}
+
 	void GLRenderSystem::setBlendState(const BlendStatePtr& blendState)
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 19 - 5
BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp

@@ -32,18 +32,32 @@ namespace BansheeEngine
 
 		mFB = bs_new<GLFrameBufferObject, PoolAlloc>();
 
+		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
+
 		GLSurfaceDesc surfaceDesc;
 		surfaceDesc.numSamples = properties->getMultisampleCount();
-		surfaceDesc.zoffset = 0;
 
-		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
-		surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
+		if (glTexture->getTextureType() != TEX_TYPE_3D)
+		{
+			surfaceDesc.zoffset = 0;
+			surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
+		}
+		else
+		{
+			surfaceDesc.zoffset = mColorSurface->getFirstArraySlice();
+			surfaceDesc.buffer = glTexture->getBuffer(0, mColorSurface->getMostDetailedMip());
+		}
 
 		mFB->bindSurface(0, surfaceDesc);
 
 		GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-		GLPixelBufferPtr depthStencilBuffer =
-			glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip());
+		GLPixelBufferPtr depthStencilBuffer = nullptr;
+
+		if (glDepthStencilTexture->getTextureType() != TEX_TYPE_3D)
+		{
+			depthStencilBuffer = glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), 
+				mDepthStencilSurface->getMostDetailedMip());
+		}
 
 		mFB->bindDepthStencil(depthStencilBuffer);
 	}

+ 35 - 0
BansheeGLRenderSystem/Source/BsGLSLParamParser.cpp

@@ -261,13 +261,23 @@ namespace BansheeEngine
 			glGetActiveUniformsiv(glProgram, 1, &index, GL_UNIFORM_TYPE, &uniformType);
 
 			bool isSampler = false;
+			bool isImage = false;
 			switch (uniformType)
 			{
 			case GL_SAMPLER_1D:
 			case GL_SAMPLER_2D:
 			case GL_SAMPLER_3D:
+			case GL_SAMPLER_2D_MULTISAMPLE:
 			case GL_SAMPLER_CUBE:
 				isSampler = true;
+				break;
+			case GL_IMAGE_1D:
+			case GL_IMAGE_2D:
+			case GL_IMAGE_3D:
+			case GL_IMAGE_CUBE:
+			case GL_IMAGE_2D_MULTISAMPLE:
+				isImage = true;
+				break;
 			}
 
 			if (isSampler)
@@ -298,11 +308,36 @@ namespace BansheeEngine
 					samplerParam.type = GPOT_SAMPLERCUBE;
 					textureParam.type = GPOT_TEXTURECUBE;
 					break;
+				case GL_SAMPLER_2D_MULTISAMPLE:
+					samplerParam.type = GPOT_SAMPLER2DMS;
+					textureParam.type = GPOT_TEXTURE2DMS;
+					break;
 				}
 
 				returnParamDesc.samplers.insert(std::make_pair(paramName, samplerParam));
 				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
 			}
+			else if (isImage)
+			{
+				GpuParamObjectDesc textureParam;
+				textureParam.name = paramName;
+				textureParam.slot = glGetUniformLocation(glProgram, uniformName);
+
+				switch (uniformType)
+				{
+				case GL_IMAGE_1D:
+					textureParam.type = GPOT_TEXTURE1D;
+					break;
+				case GL_IMAGE_2D:
+					textureParam.type = GPOT_TEXTURE2D;
+					break;
+				case GL_IMAGE_3D:
+					textureParam.type = GPOT_TEXTURE3D;
+					break;
+				}
+
+				returnParamDesc.textures.insert(std::make_pair(paramName, textureParam));
+			}
 			else
 			{
 				// If array index is larger than 0 and uniform is not a part of a struct,

+ 9 - 18
BansheeGLRenderSystem/Source/BsGLTexture.cpp

@@ -12,7 +12,7 @@
 namespace BansheeEngine 
 {
     GLTexture::GLTexture(GLSupport& support) 
-        : Texture(), mTextureID(0), mGLSupport(support)
+		: Texture(), mTextureID(0), mGLSupport(support), mGLFormat(0)
     { }
 
     GLTexture::~GLTexture()
@@ -49,17 +49,8 @@ namespace BansheeEngine
 		// This needs to be set otherwise the texture doesn't get rendered
 		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps);
 
-		// Set some misc default parameters so NVidia won't complain, these can of course be changed later
-		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		if (GLEW_VERSION_1_2)
-		{
-			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		}
-
 		// Allocate internal buffer so that glTexSubImageXD can be used
-		GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
+		mGLFormat = GLPixelUtil::getClosestGLInternalFormat(mFormat, mHwGamma);
 		UINT32 width = mWidth;
 		UINT32 height = mHeight;
 		UINT32 depth = mDepth;
@@ -75,20 +66,20 @@ namespace BansheeEngine
 
 		if((mUsage & TU_RENDERTARGET) != 0 && mTextureType == TEX_TYPE_2D && mMultisampleCount > 0)
 		{
-			glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, format, width, height, GL_FALSE);
+			glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, mGLFormat, width, height, GL_FALSE);
 		}
 		else if((mUsage & TU_DEPTHSTENCIL) != 0)
 		{
 			if(mMultisampleCount > 0)
 			{
-				glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, format,
+				glTexImage2DMultisample(GL_TEXTURE_2D, mMultisampleCount, mGLFormat,
 					width, height, GL_FALSE);
 			}
 			else
 			{
 				GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(mFormat);
 
-				glTexImage2D(GL_TEXTURE_2D, 0, format,
+				glTexImage2D(GL_TEXTURE_2D, 0, mGLFormat,
 					width, height, 0, 
 					GL_DEPTH_STENCIL, depthStencilFormat, nullptr);
 			}
@@ -104,22 +95,22 @@ namespace BansheeEngine
 				switch(mTextureType)
 				{
 				case TEX_TYPE_1D:
-					glTexImage1D(GL_TEXTURE_1D, mip, format, width, 0, 
+					glTexImage1D(GL_TEXTURE_1D, mip, mGLFormat, width, 0,
 						baseFormat, baseDataType, nullptr);
 
 					break;
 				case TEX_TYPE_2D:
-					glTexImage2D(GL_TEXTURE_2D, mip, format,
+					glTexImage2D(GL_TEXTURE_2D, mip, mGLFormat,
 						width, height, 0, baseFormat, baseDataType, nullptr);
 					break;
 				case TEX_TYPE_3D:
-					glTexImage3D(GL_TEXTURE_3D, mip, format, width, height, 
+					glTexImage3D(GL_TEXTURE_3D, mip, mGLFormat, width, height,
 						depth, 0, baseFormat, baseDataType, nullptr);
 					break;
 				case TEX_TYPE_CUBE_MAP:
 					for(UINT32 face = 0; face < 6; face++) 
 					{
-						glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
+						glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, mGLFormat,
 							width, height, 0, baseFormat, baseDataType, nullptr);
 					}
 					break;

+ 4 - 2
MBansheeEngine/Camera.cs

@@ -6,11 +6,13 @@ using System.Text;
 
 namespace BansheeEngine
 {
+    // Don't reorder, used by native code
     public enum ProjectionType
     {
         Orthographic, Perspective
     }
 
+    // Don't reorder, used by native code
     [Flags]
     public enum ClearFlags
     {
@@ -203,9 +205,9 @@ namespace BansheeEngine
         private static extern void Internal_SetDepthClearValue(IntPtr instance, int value);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern byte Internal_GetStencilClearValue(IntPtr instance);
+        private static extern UInt16 Internal_GetStencilClearValue(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetStencilClearValue(IntPtr instance, byte value);
+        private static extern void Internal_SetStencilClearValue(IntPtr instance, UInt16 value);
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern ClearFlags Internal_GetClearFlags(IntPtr instance);

+ 5 - 2
SBansheeEngine/Include/BsScriptCamera.h

@@ -50,8 +50,8 @@ namespace BansheeEngine
 		static int internal_GetDepthClearValue(ScriptCamera* instance);
 		static void internal_SetDepthClearValue(ScriptCamera* instance, int value);
 
-		static UINT8 internal_GetStencilClearValue(ScriptCamera* instance);
-		static void internal_SetStencilClearValue(ScriptCamera* instance, UINT8 value);
+		static UINT16 internal_GetStencilClearValue(ScriptCamera* instance);
+		static void internal_SetStencilClearValue(ScriptCamera* instance, UINT16 value);
 
 		static UINT32 internal_GetClearFlags(ScriptCamera* instance);
 		static void internal_SetClearFlags(ScriptCamera* instance, UINT32 value);
@@ -91,6 +91,9 @@ namespace BansheeEngine
 		static Vector3 internal_ProjectPoint(ScriptCamera* instance, Vector3 value);
 		static Vector3 internal_UnprojectPoint(ScriptCamera* instance, Vector3 value);
 
+		static MonoObject* internal_GetRenderTexture(ScriptCamera* instance);
+		static void internal_SetRenderTexture(ScriptCamera* instance, MonoObject* textureObj);
+
 		CameraHandler* mCameraHandler;
 	};
 }

+ 93 - 48
SBansheeEngine/Source/BsScriptCamera.cpp

@@ -4,18 +4,22 @@
 #include "BsMonoClass.h"
 #include "BsMonoManager.h"
 #include "BsMonoUtil.h"
+#include "BsApplication.h"
+#include "BsCameraHandler.h"
 
 namespace BansheeEngine
 {
 	ScriptCamera::ScriptCamera(MonoObject* managedInstance)
-		:ScriptObject(managedInstance)
+		:ScriptObject(managedInstance), mCameraHandler(nullptr)
 	{ 
-		// TODO - Create handler
+		ViewportPtr primaryViewport = gApplication().getPrimaryViewport();
+
+		mCameraHandler = bs_new<CameraHandler>(primaryViewport->getTarget());
 	}
 
 	ScriptCamera::~ScriptCamera()
 	{
-		// TODO - Delete handler
+		bs_delete(mCameraHandler);
 	}
 
 	void ScriptCamera::initRuntimeData()
@@ -88,245 +92,286 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_ScreenToWorldRay", &ScriptCamera::internal_GetAspect);
 		metaData.scriptClass->addInternalCall("Internal_ProjectPoint", &ScriptCamera::internal_GetAspect);
 		metaData.scriptClass->addInternalCall("Internal_UnprojectPoint", &ScriptCamera::internal_GetAspect);
+
+		// TODO
+		// metaData.scriptClass->addInternalCall("Internal_SetRenderTexture", &ScriptCamera::internal_SetRenderTexture);
+		// metaData.scriptClass->addInternalCall("Internal_GetRenderTexture", &ScriptCamera::internal_GetRenderTexture);
 	}
 
 	float ScriptCamera::internal_GetAspect(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getAspectRatio();
 	}
 
 	void ScriptCamera::internal_SetAspect(ScriptCamera* instance, float value)
 	{
-
+		instance->mCameraHandler->setAspectRatio(value);
 	}
 
 	float ScriptCamera::internal_GetNearClip(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getNearClipDistance();
 	}
 
 	void ScriptCamera::internal_SetNearClip(ScriptCamera* instance, float value)
 	{
-
+		instance->mCameraHandler->setNearClipDistance(value);
 	}
 
 	float ScriptCamera::internal_GetFarClip(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getFarClipDistance();
 	}
 
 	void ScriptCamera::internal_SetFarClip(ScriptCamera* instance, float value)
 	{
-
+		instance->mCameraHandler->setFarClipDistance(value);
 	}
 
 	Degree ScriptCamera::internal_GetFieldOfView(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getHorzFOV();
 	}
 
 	void ScriptCamera::internal_SetFieldOfView(ScriptCamera* instance, Degree value)
 	{
-
+		instance->mCameraHandler->setHorzFOV(value);
 	}
 
 	Rect2 ScriptCamera::internal_GetViewportRect(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewport()->getNormArea();
 	}
 
 	void ScriptCamera::internal_SetViewportRect(ScriptCamera* instance, Rect2 value)
 	{
-
+		instance->mCameraHandler->getViewport()->setArea(value.x, value.y, value.width, value.height);
 	}
 
 	UINT32 ScriptCamera::internal_GetProjectionType(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getProjectionType();
 	}
 
 	void ScriptCamera::internal_SetProjectionType(ScriptCamera* instance, UINT32 value)
 	{
-
+		instance->mCameraHandler->setProjectionType((ProjectionType)value);
 	}
 
 	float ScriptCamera::internal_GetOrthographicHeight(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getOrthoWindowHeight();
 	}
 
 	void ScriptCamera::internal_SetOrthographicHeight(ScriptCamera* instance, float value)
 	{
-
+		instance->mCameraHandler->setOrthoWindowHeight(value);
 	}
 
 	float ScriptCamera::internal_GetOrthographicWidth(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getOrthoWindowWidth();
 	}
 
 	Color ScriptCamera::internal_GetClearColor(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewport()->getClearColor();
 	}
 
 	void ScriptCamera::internal_SetClearColor(ScriptCamera* instance, Color value)
 	{
-
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
+		vp->setClearValues(value, vp->getClearDepthValue(), vp->getClearStencilValue());
 	}
 
 	int ScriptCamera::internal_GetDepthClearValue(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewport()->getClearDepthValue();
 	}
 
 	void ScriptCamera::internal_SetDepthClearValue(ScriptCamera* instance, int value)
 	{
-
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
+		vp->setClearValues(vp->getClearColor(), value, vp->getClearStencilValue());
 	}
 
-	UINT8 ScriptCamera::internal_GetStencilClearValue(ScriptCamera* instance)
+	UINT16 ScriptCamera::internal_GetStencilClearValue(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewport()->getClearStencilValue();
 	}
 
-	void ScriptCamera::internal_SetStencilClearValue(ScriptCamera* instance, UINT8 value)
+	void ScriptCamera::internal_SetStencilClearValue(ScriptCamera* instance, UINT16 value)
 	{
-
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
+		vp->setClearValues(vp->getClearColor(), vp->getClearDepthValue(), value);
 	}
 
 	UINT32 ScriptCamera::internal_GetClearFlags(ScriptCamera* instance)
 	{
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
+		UINT32 clearFlags = 0;
 
+		clearFlags |= vp->getRequiresColorClear() ? 0x01 : 0;
+		clearFlags |= vp->getRequiresDepthClear() ? 0x02 : 0;
+		clearFlags |= vp->getRequiresStencilClear() ? 0x04 : 0;
+
+		return clearFlags;
 	}
 
 	void ScriptCamera::internal_SetClearFlags(ScriptCamera* instance, UINT32 value)
 	{
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
 
+		vp->setRequiresClear((value & 0x01) != 0,
+			(value & 0x02) != 0, (value & 0x04) != 0);
 	}
 
 	int ScriptCamera::internal_GetPriority(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getPriority();
 	}
 
 	void ScriptCamera::internal_SetPriority(ScriptCamera* instance, int value)
 	{
-
+		instance->mCameraHandler->setPriority(value);
 	}
 
 	UINT64 ScriptCamera::internal_GetLayers(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getLayers();
 	}
 
 	void ScriptCamera::internal_SetLayers(ScriptCamera* instance, UINT64 value)
 	{
-
+		instance->mCameraHandler->setLayers(value);
 	}
 
 	Matrix4 ScriptCamera::internal_GetProjMatrix(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getProjectionMatrixRS();
 	}
 
 	Matrix4 ScriptCamera::internal_GetProjMatrixInv(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getProjectionMatrixRSInv();
 	}
 
 	Matrix4 ScriptCamera::internal_GetViewMatrix(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewMatrix();
 	}
 
 	Matrix4 ScriptCamera::internal_GetViewMatrixInv(ScriptCamera* instance)
 	{
-
+		return instance->mCameraHandler->getViewMatrixInv();
 	}
 
 	int ScriptCamera::internal_GetWidthPixels(ScriptCamera* instance)
 	{
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
 
+		return vp->getWidth();
 	}
 
 	int ScriptCamera::internal_GetHeightPixels(ScriptCamera* instance)
 	{
+		ViewportPtr vp = instance->mCameraHandler->getViewport();
 
+		return vp->getHeight();
 	}
 
 	Vector2I ScriptCamera::internal_WorldToScreen(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->worldToScreenPoint(value);
 	}
 
 	Vector2 ScriptCamera::internal_WorldToClip(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->worldToClipPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_WorldToView(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->worldToViewPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_ScreenToWorld(ScriptCamera* instance, Vector2I value)
 	{
-
+		return instance->mCameraHandler->screenToWorldPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_ScreenToView(ScriptCamera* instance, Vector2I value)
 	{
-
+		return instance->mCameraHandler->screenToViewPoint(value);
 	}
 
 	Vector2 ScriptCamera::internal_ScreenToClip(ScriptCamera* instance, Vector2I value)
 	{
-
+		return instance->mCameraHandler->screenToClipPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_ViewToWorld(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->viewToWorldPoint(value);
 	}
 
 	Vector2I ScriptCamera::internal_ViewToScreen(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->viewToScreenPoint(value);
 	}
 
 	Vector2 ScriptCamera::internal_ViewToClip(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->viewToClipPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_ClipToWorld(ScriptCamera* instance, Vector2 value)
 	{
-
+		return instance->mCameraHandler->clipToWorldPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_ClipToView(ScriptCamera* instance, Vector2 value)
 	{
-
+		return instance->mCameraHandler->clipToViewPoint(value);
 	}
 
 	Vector2I ScriptCamera::internal_ClipToScreen(ScriptCamera* instance, Vector2 value)
 	{
-
+		return instance->mCameraHandler->clipToScreenPoint(value);
 	}
 
 	Ray ScriptCamera::internal_ScreenToWorldRay(ScriptCamera* instance, Vector2I value)
 	{
-
+		return instance->mCameraHandler->screenPointToRay(value);
 	}
 
 	Vector3 ScriptCamera::internal_ProjectPoint(ScriptCamera* instance, Vector3 value)
 	{
-
+		return instance->mCameraHandler->projectPoint(value);
 	}
 
 	Vector3 ScriptCamera::internal_UnprojectPoint(ScriptCamera* instance, Vector3 value)
 	{
+		return instance->mCameraHandler->unprojectPoint(value);
+	}
+
+	MonoObject* ScriptCamera::internal_GetRenderTexture(ScriptCamera* instance)
+	{
+		// TODO - Not implemented
+		return nullptr;
+	}
+
+	void ScriptCamera::internal_SetRenderTexture(ScriptCamera* instance, MonoObject* textureObj)
+	{
+		if (textureObj == nullptr)
+		{
+			ViewportPtr primaryViewport = gApplication().getPrimaryViewport();
 
+			instance->mCameraHandler->getViewport()->setTarget(primaryViewport->getTarget());
+		}
+		else
+		{
+			// TODO - Not implemented
+		}
 	}
 }

+ 0 - 2
SceneView.txt

@@ -23,7 +23,6 @@ AFTER I have scene widget in C#:
  - Implement free move handle and remaining handles
  - Test custom handles from C#
 
-
 IMPLEMENT SELECTION RENDERING
 
 IMPROVE SceneGrid LOOK
@@ -88,7 +87,6 @@ Draw that same mesh with either a wireframe or a grayed out shader with a slight
 
 ---------------------------------------------------------------------
 Render textures in C#:
- - Extend C++ code so I can render to a 2D texture, face of a cube map, slice of a volume texture or entry in a 2D texture array.
  - In C# have Texture2D, TextureCube, TextureVolume, Texture2DArray. They should have a common Texture base.
    - Each of those can be created with a Renderable flag
  - Render textures mirror what we have in C++