Browse Source

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 năm trước cách đây
mục cha
commit
350e767ebf
38 tập tin đã thay đổi với 716 bổ sung131 xóa
  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++