Explorar el Código

Add multi texture to ScenePicking for normals

marco.bellan hace 9 años
padre
commit
250e02772f

+ 14 - 0
Source/BansheeCore/Include/BsMultiRenderTexture.h

@@ -121,6 +121,20 @@ namespace BansheeEngine
 		/** Returns properties that describe the render texture. */
 		/** Returns properties that describe the render texture. */
 		const MultiRenderTextureProperties& getProperties() const;
 		const MultiRenderTextureProperties& getProperties() const;
 
 
+		/**
+		* Returns a depth/stencil surface texture you may bind as an input to an GPU program.
+		*
+		* @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		*/
+		const SPtr<TextureView> getBindableDepthStencilTexture() const { return mDepthStencilSurface; }
+
+		/**
+		* Returns a color surface texture you may bind as an input to an GPU program.
+		*
+		* @note	Be aware that you cannot bind a render texture for reading and writing at the same time.
+		*/
+		const SPtr<TextureView>& getBindableColorTexture(UINT32 idx) const { return mColorSurfaces[idx]; }
+
 		/** @copydoc	TextureManager::createMultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC&) */
 		/** @copydoc	TextureManager::createMultiRenderTexture(const MULTI_RENDER_TEXTURE_DESC&) */
 		static SPtr<MultiRenderTextureCore> create(const MULTI_RENDER_TEXTURE_CORE_DESC& desc);
 		static SPtr<MultiRenderTextureCore> create(const MULTI_RENDER_TEXTURE_CORE_DESC& desc);
 
 

+ 8 - 4
Source/BansheeEditor/Include/BsScenePicking.h

@@ -14,7 +14,7 @@ namespace BansheeEngine
 	 */
 	 */
 
 
 	 /** Contains the data of a scene picking action. */
 	 /** Contains the data of a scene picking action. */
-	struct PickData
+	struct SnapData
 	{
 	{
 		Vector3 normal;
 		Vector3 normal;
 		Vector3 pickPosition;
 		Vector3 pickPosition;
@@ -24,7 +24,7 @@ namespace BansheeEngine
 	struct PickResults
 	struct PickResults
 	{
 	{
 		Vector<UINT32> objects;
 		Vector<UINT32> objects;
-		PickData data;
+		SnapData data;
 	};
 	};
 
 
 	class ScenePickingCore;
 	class ScenePickingCore;
@@ -54,10 +54,11 @@ namespace BansheeEngine
 		 * @param[in]	position	Pointer position relative to the camera viewport, in pixels.
 		 * @param[in]	position	Pointer position relative to the camera viewport, in pixels.
 		 * @param[in]	area		Width/height of the checked area in pixels. Use (1, 1) if you want the exact position
 		 * @param[in]	area		Width/height of the checked area in pixels. Use (1, 1) if you want the exact position
 		 *							under the pointer.
 		 *							under the pointer.
+		 * @param[in]	ignoreRenderables		A list of objects that should not be rendered during scene picking.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @return					Nearest SceneObject under the provided area, or an empty handle if no object is found.
 		 * @return					Nearest SceneObject under the provided area, or an empty handle if no object is found.
 		 */
 		 */
-		HSceneObject pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, PickData& data);
+		HSceneObject pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables);
 
 
 		/**
 		/**
 		 * Attempts to find all scene objects under the provided position and area. This does not mean objects occluded by
 		 * Attempts to find all scene objects under the provided position and area. This does not mean objects occluded by
@@ -67,10 +68,11 @@ namespace BansheeEngine
 		 * @param[in]	position	Pointer position relative to the camera viewport, in pixels.
 		 * @param[in]	position	Pointer position relative to the camera viewport, in pixels.
 		 * @param[in]	area		Width/height of the checked area in pixels. Use (1, 1) if you want the exact position
 		 * @param[in]	area		Width/height of the checked area in pixels. Use (1, 1) if you want the exact position
 		 *							under the pointer.
 		 *							under the pointer.
+		 * @param[in]	ignoreRenderables		A list of objects that should not be rendered during scene picking.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @param[out]	data		Picking data regarding position and normal.
 		 * @return					A list of SceneObject%s under the provided area.
 		 * @return					A list of SceneObject%s under the provided area.
 		 */
 		 */
-		Vector<HSceneObject> pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, PickData& data);
+		Vector<HSceneObject> pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables);
 
 
 	private:
 	private:
 		friend class ScenePickingCore;
 		friend class ScenePickingCore;
@@ -150,6 +152,8 @@ namespace BansheeEngine
 	private:
 	private:
 		friend class ScenePicking;
 		friend class ScenePicking;
 
 
+		SPtr<MultiRenderTextureCore> mNormalsTexture;
+
 		static const float ALPHA_CUTOFF;
 		static const float ALPHA_CUTOFF;
 
 
 		MaterialData mMaterialData[3];
 		MaterialData mMaterialData[3];

+ 58 - 9
Source/BansheeEditor/Source/BsScenePicking.cpp

@@ -19,6 +19,7 @@
 #include "BsDepthStencilState.h"
 #include "BsDepthStencilState.h"
 #include "BsRasterizerState.h"
 #include "BsRasterizerState.h"
 #include "BsRenderTarget.h"
 #include "BsRenderTarget.h"
+#include "BsMultiRenderTexture.h"
 #include "BsPixelData.h"
 #include "BsPixelData.h"
 #include "BsGpuParams.h"
 #include "BsGpuParams.h"
 #include "BsBuiltinEditorResources.h"
 #include "BsBuiltinEditorResources.h"
@@ -54,16 +55,20 @@ namespace BansheeEngine
 		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
 		gCoreAccessor().queueCommand(std::bind(&ScenePickingCore::destroy, mCore));
 	}
 	}
 
 
-	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, PickData& data)
+	HSceneObject ScenePicking::pickClosestObject(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables)
 	{
 	{
-		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area, data);
+		Vector<HSceneObject> selectedObjects = pickObjects(cam, position, area, data, ignoreRenderables);
 		if (selectedObjects.size() == 0)
 		if (selectedObjects.size() == 0)
 			return HSceneObject();
 			return HSceneObject();
-
+		Matrix3 rotation;
+		selectedObjects[0]->getWorldRotation().toRotationMatrix(rotation);
+		data.normal = rotation.inverse().transpose().transform(data.normal);
+		LOGWRN("Pos: " + toString(data.pickPosition.x) + " & " + toString(data.pickPosition.y) + " & " + toString(data.pickPosition.z));
+		LOGWRN("Norm: " + toString(data.normal.x) + " & " + toString(data.normal.y) + " & " + toString(data.normal.z));
 		return selectedObjects[0];
 		return selectedObjects[0];
 	}
 	}
 
 
-	Vector<HSceneObject> ScenePicking::pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, PickData& data)
+	Vector<HSceneObject> ScenePicking::pickObjects(const SPtr<Camera>& cam, const Vector2I& position, const Vector2I& area, SnapData& data, Vector<HSceneObject> ignoreRenderables)
 	{
 	{
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		auto comparePickElement = [&] (const ScenePicking::RenderablePickData& a, const ScenePicking::RenderablePickData& b)
 		{
 		{
@@ -97,6 +102,18 @@ namespace BansheeEngine
 			if (!mesh.isLoaded())
 			if (!mesh.isLoaded())
 				continue;
 				continue;
 
 
+			bool found = false;
+			for (int i = 0; i < ignoreRenderables.size(); i++)
+			{
+				if (ignoreRenderables[i] == so)
+				{
+					found = true;
+					break;
+				}
+			}
+			if (found)
+				continue;
+
 			Bounds worldBounds = mesh->getProperties().getBounds();
 			Bounds worldBounds = mesh->getProperties().getBounds();
 			Matrix4 worldTransform = so->getWorldTfrm();
 			Matrix4 worldTransform = so->getWorldTfrm();
 			worldBounds.transformAffine(worldTransform);
 			worldBounds.transformAffine(worldTransform);
@@ -187,6 +204,7 @@ namespace BansheeEngine
 		pos = cam->viewToWorldPoint(worldPoint3D);
 		pos = cam->viewToWorldPoint(worldPoint3D);
 		data = returnValue.data;
 		data = returnValue.data;
 		data.pickPosition = pos;
 		data.pickPosition = pos;
+		//Todo: camera to world ray if object is too far
 
 
 		Vector<UINT32> selectedObjects = returnValue.objects;
 		Vector<UINT32> selectedObjects = returnValue.objects;
 		Vector<HSceneObject> results;
 		Vector<HSceneObject> results;
@@ -280,8 +298,28 @@ namespace BansheeEngine
 	{
 	{
 		RenderAPICore& rs = RenderAPICore::instance();
 		RenderAPICore& rs = RenderAPICore::instance();
 
 
+		SPtr<RenderTextureCore> rtt = std::static_pointer_cast<RenderTextureCore>(target);
+		SPtr<TextureCore> outputTexture = rtt->getBindableColorTexture();
+		TextureProperties outputTextureProperties = outputTexture->getProperties();
+		SPtr<TextureCore> depthTexture = rtt->getBindableDepthStencilTexture();
+
+		MULTI_RENDER_TEXTURE_CORE_DESC multiTextureDescription;
+		multiTextureDescription.colorSurfaces.resize(2);
+		multiTextureDescription.colorSurfaces[0].face = 0;
+		multiTextureDescription.colorSurfaces[0].texture = outputTexture;
+		multiTextureDescription.colorSurfaces[1].face = 0;
+		SPtr<TextureCore> core = TextureCore::create(TextureType::TEX_TYPE_2D, outputTextureProperties.getWidth(),
+			outputTextureProperties.getHeight(), 0, PixelFormat::PF_R8G8B8A8, TU_RENDERTARGET, false, 1);
+		multiTextureDescription.colorSurfaces[1].texture = core;
+		RENDER_SURFACE_CORE_DESC depthStencilDescription;
+		depthStencilDescription.face = 0;
+		depthStencilDescription.texture = depthTexture;
+		multiTextureDescription.depthStencilSurface = depthStencilDescription;
+		
+		mNormalsTexture = MultiRenderTextureCore::create(multiTextureDescription);
+
 		rs.beginFrame();
 		rs.beginFrame();
-		rs.setRenderTarget(target);
+		rs.setRenderTarget(mNormalsTexture);
 		rs.setViewport(viewportArea);
 		rs.setViewport(viewportArea);
 		rs.clearRenderTarget(FBT_COLOR | FBT_DEPTH | FBT_STENCIL, Color::White);
 		rs.clearRenderTarget(FBT_COLOR | FBT_DEPTH | FBT_STENCIL, Color::White);
 		rs.setScissorRect(position.x, position.y, position.x + area.x, position.y + area.y);
 		rs.setScissorRect(position.x, position.y, position.x + area.x, position.y + area.y);
@@ -346,9 +384,9 @@ namespace BansheeEngine
 			BS_EXCEPT(NotImplementedException, "Picking is not supported on render windows as framebuffer readback methods aren't implemented");
 			BS_EXCEPT(NotImplementedException, "Picking is not supported on render windows as framebuffer readback methods aren't implemented");
 		}
 		}
 
 
-		SPtr<RenderTextureCore> rtt = std::static_pointer_cast<RenderTextureCore>(target);
-		SPtr<TextureCore> outputTexture = rtt->getBindableColorTexture();
-		SPtr<TextureCore> depthTexture = rtt->getBindableDepthStencilTexture();
+		SPtr<TextureCore> outputTexture = mNormalsTexture->getBindableColorTexture(0)->getTexture();
+		SPtr<TextureCore> normalsTexture = mNormalsTexture->getBindableColorTexture(1)->getTexture();
+		SPtr<TextureCore> depthTexture = mNormalsTexture->getBindableDepthStencilTexture()->getTexture();
 
 
 		if (position.x < 0 || position.x >= (INT32)outputTexture->getProperties().getWidth() ||
 		if (position.x < 0 || position.x >= (INT32)outputTexture->getProperties().getWidth() ||
 			position.y < 0 || position.y >= (INT32)outputTexture->getProperties().getHeight())
 			position.y < 0 || position.y >= (INT32)outputTexture->getProperties().getHeight())
@@ -358,6 +396,7 @@ namespace BansheeEngine
 		}
 		}
 
 
 		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocateSubresourceBuffer(0);
 		SPtr<PixelData> outputPixelData = outputTexture->getProperties().allocateSubresourceBuffer(0);
+		SPtr<PixelData> normalsPixelData = normalsTexture->getProperties().allocateSubresourceBuffer(0);
 		SPtr<PixelData> depthPixelData = depthTexture->getProperties().allocateSubresourceBuffer(0);
 		SPtr<PixelData> depthPixelData = depthTexture->getProperties().allocateSubresourceBuffer(0);
 
 
 		outputTexture->readSubresource(0, *outputPixelData);
 		outputTexture->readSubresource(0, *outputPixelData);
@@ -431,19 +470,29 @@ namespace BansheeEngine
 			objects.push_back(selectedObject.index);
 			objects.push_back(selectedObject.index);
 		
 		
 		depthTexture->readSubresource(0, *depthPixelData);
 		depthTexture->readSubresource(0, *depthPixelData);
+		normalsTexture->readSubresource(0, *normalsPixelData);
 		float depth;
 		float depth;
+		Color normal;
 		if (rtProps.requiresTextureFlipping())
 		if (rtProps.requiresTextureFlipping())
+		{
 			depth = depthPixelData->getDepthAt(position.x, depthPixelData->getHeight() - position.y);
 			depth = depthPixelData->getDepthAt(position.x, depthPixelData->getHeight() - position.y);
+			normal = normalsPixelData->getColorAt(position.x, depthPixelData->getHeight() - position.y);
+		}
 		else
 		else
+		{
 			depth = depthPixelData->getDepthAt(position.x, position.y);
 			depth = depthPixelData->getDepthAt(position.x, position.y);
+			normal = normalsPixelData->getColorAt(position.x, position.y);
+		}
 
 
 		PickResults result;
 		PickResults result;
-		PickData data;
+		SnapData data;
 		result.objects = objects;
 		result.objects = objects;
 		const RenderAPIInfo& rapiInfo = rs.getAPIInfo();
 		const RenderAPIInfo& rapiInfo = rs.getAPIInfo();
 		depth = depth * Math::abs(rapiInfo.getMinimumDepthInputValue() - rapiInfo.getMinimumDepthInputValue()) + rapiInfo.getMinimumDepthInputValue();
 		depth = depth * Math::abs(rapiInfo.getMinimumDepthInputValue() - rapiInfo.getMinimumDepthInputValue()) + rapiInfo.getMinimumDepthInputValue();
 		data.pickPosition = Vector3(position.x, position.y, depth);
 		data.pickPosition = Vector3(position.x, position.y, depth);
+		data.normal = Vector3((normal.r * 2) - 1, (normal.g * 2) - 1, (normal.b * 2) - 1);
 		result.data = data;
 		result.data = data;
 		asyncOp._completeOperation(result);
 		asyncOp._completeOperation(result);
+		mNormalsTexture = nullptr;
 	}
 	}
 }
 }