Browse Source

Merge pull request #47 from dariomanesku/master

Updates on 14-shadowvolumes.
Branimir Karadžić 12 years ago
parent
commit
722b85ab26

+ 155 - 141
examples/14-shadowvolumes/shadowvolumes.cpp

@@ -23,6 +23,9 @@ using namespace std::tr1;
 #include <unordered_map>
 #include <map>
 
+#define MAX_INSTANCE_COUNT 25
+#define MAX_LIGHTS_COUNT 5
+
 #define VIEWID_RANGE1_PASS0     1 
 #define VIEWID_RANGE1_RT_PASS1  2
 #define VIEWID_RANGE15_PASS2    3
@@ -92,9 +95,7 @@ static const uint16_t s_planeIndices[s_numPlaneIndices] =
 static const char* s_shaderPath = NULL;
 static bool s_flipV = false;
 
-static uint32_t s_clearMask = 0;
 static uint32_t s_viewMask = 0;
-static uint32_t s_rtMask = 0;
 
 static bgfx::UniformHandle u_texColor;
 static bgfx::UniformHandle u_texStencil;
@@ -670,32 +671,6 @@ struct ClearValues
 	uint8_t  m_clearStencil;
 };
 
-void clearView(uint8_t _id, uint8_t _flags, const ClearValues& _clearValues)
-{
-	bgfx::setViewClear(_id
-		, _flags
-		, _clearValues.m_clearRgba
-		, _clearValues.m_clearDepth
-		, _clearValues.m_clearStencil
-		);
-
-	// Keep track of cleared views.
-	s_clearMask |= 1 << _id;
-}
-
-void clearViewMask(uint32_t _viewMask, uint8_t _flags, const ClearValues& _clearValues)
-{
-	bgfx::setViewClearMask(_viewMask
-		, _flags
-		, _clearValues.m_clearRgba
-		, _clearValues.m_clearDepth
-		, _clearValues.m_clearStencil
-		);
-
-	// Keep track of cleared views.
-	s_clearMask |= _viewMask;
-}
-
 void submit(uint8_t _id, int32_t _depth = 0)
 {
 	bgfx::submit(_id, _depth);
@@ -712,14 +687,6 @@ void submitMask(uint32_t _viewMask, int32_t _depth = 0)
 	s_viewMask |= _viewMask;
 }
 
-void setViewRenderTarget(uint8_t _id, bgfx::RenderTargetHandle _handle)
-{
-	bgfx::setViewRenderTarget(_id, _handle);
-
-	// Keep track of render target view ids
-	s_rtMask |= 1 << _id;
-}
-
 struct Aabb
 {
 	float m_min[3];
@@ -1280,6 +1247,43 @@ struct Instance
 	Model* m_model;
 };
 
+struct ShadowVolumeAllocator
+{
+	ShadowVolumeAllocator()
+	{
+		m_mem = (uint8_t*)malloc(PAGE_SIZE*2);
+		m_ptr = m_mem;
+		m_firstPage = true;
+	}
+
+	~ShadowVolumeAllocator()
+	{
+		free(m_mem);
+	}
+
+	void* alloc(uint32_t _size)
+	{
+		void* ret = (void*)m_ptr;
+		m_ptr += _size;
+		BX_CHECK(m_ptr - m_mem < (m_firstPage ? PAGE_SIZE : 2 * PAGE_SIZE), "Buffer overflow!");
+		return ret;
+	}
+
+	void swap()
+	{
+		m_ptr = m_firstPage ? m_mem + PAGE_SIZE : m_mem;
+		m_firstPage = !m_firstPage;
+	}
+
+	uint8_t* m_mem;
+	uint8_t* m_ptr;
+	bool m_firstPage;
+	static const uint32_t SV_INSTANCE_MEM_SIZE = 1500 << 10;
+	static const uint32_t INSTANCE_COUNT = (25 > MAX_INSTANCE_COUNT) ? 25 : MAX_INSTANCE_COUNT; //max(25, MAX_INSTANCE_COUNT);
+	static const uint32_t PAGE_SIZE = SV_INSTANCE_MEM_SIZE * INSTANCE_COUNT * MAX_LIGHTS_COUNT;
+};
+static ShadowVolumeAllocator s_svAllocator;
+
 struct ShadowVolumeImpl
 {
 	enum Enum
@@ -1419,35 +1423,24 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 		float m_k;
 	};
 
-	struct Index3us
-	{
-		Index3us()
-		{
-		}
-
-		Index3us(uint16_t _i0, uint16_t _i1, uint16_t _i2)
-			: m_i0(_i0)
-			, m_i1(_i1)
-			, m_i2(_i2)
-		{
-		}
+	bool cap = (ShadowVolumeImpl::DepthFail == _impl);
 
-		uint16_t m_i0;
-		uint16_t m_i1;
-		uint16_t m_i2;
-	};
+	VertexData* verticesSide    = (VertexData*) s_svAllocator.alloc (20000 * sizeof(VertexData) );
+	uint16_t*   indicesSide     = (uint16_t*)   s_svAllocator.alloc (20000 * 3*sizeof(uint16_t) );
+	uint16_t*   indicesFrontCap = 0;
+	uint16_t*   indicesBackCap  = 0;
 
-	VertexData* verticesSide    = (VertexData*) malloc (100000 * sizeof(VertexData) );
-	Index3us*   indicesSide		= (Index3us*)   malloc (100000 * sizeof(Index3us) );
-	Index3us*   indicesFrontCap	= (Index3us*)   malloc (100000 * sizeof(Index3us) );
-	Index3us*   indicesBackCap	= (Index3us*)   malloc (100000 * sizeof(Index3us) );
+	if (cap)
+	{
+		indicesFrontCap = (uint16_t*)s_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
+		indicesBackCap  = (uint16_t*)s_svAllocator.alloc(80000 * 3*sizeof(uint16_t) );
+	}
 
-	uint16_t vsideI    = 0;
-	uint16_t sideI     = 0;
-	uint16_t frontCapI = 0;
-	uint16_t backCapI  = 0;
+	uint32_t vsideI    = 0;
+	uint32_t sideI     = 0;
+	uint32_t frontCapI = 0;
+	uint32_t backCapI  = 0;
 
-	bool cap = (ShadowVolumeImpl::DepthFail == _impl);
 	uint16_t indexSide = 0;
 
 	if (ShadowVolumeAlgorithm::FaceBased == _algo)
@@ -1455,7 +1448,6 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 		for (FaceArray::const_iterator iter = faces.begin(), end = faces.end(); iter != end; ++iter)
 		{
 			const Face& face = *iter;
-			const uint16_t* indices = face.m_i;
 
 			bool frontFacing = false;
 			float f = vec3Dot(face.m_plane, _light) + face.m_plane[3];
@@ -1464,9 +1456,9 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 				frontFacing = true;
 				uint16_t triangleEdges[3][2] = 
 				{
-					{ indices[0], indices[1] },
-					{ indices[1], indices[2] },
-					{ indices[2], indices[0] },
+					{ face.m_i[0], face.m_i[1] },
+					{ face.m_i[1], face.m_i[2] },
+					{ face.m_i[2], face.m_i[0] },
 				};
 
 				for (uint8_t ii = 0; ii < 3; ++ii)
@@ -1485,11 +1477,15 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 			{
 				if (frontFacing)
 				{
-					indicesFrontCap[frontCapI++] = *(Index3us*)face.m_i;
+					indicesFrontCap[frontCapI++] = face.m_i[0];
+					indicesFrontCap[frontCapI++] = face.m_i[1];
+					indicesFrontCap[frontCapI++] = face.m_i[2];
 				}
 				else
 				{
-					indicesBackCap[backCapI++] = *(Index3us*)face.m_i; 
+					indicesBackCap[backCapI++] = face.m_i[0];
+					indicesBackCap[backCapI++] = face.m_i[1];
+					indicesBackCap[backCapI++] = face.m_i[2];
 				}
 
 				/**
@@ -1499,8 +1495,9 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 				 * bool condition1 = !frontFacing && !_useFrontFacingFacesAsBackCap;
 				 * if (condition0 || condition1)
 				 * {
-				 *		const Index3us tmp = { indices[0], indices[1+condition0], indices[2-condition0] }; //winding regarding condition0 
-				 *		indicesBackCap.push_back(tmp);
+				 *      indicesBackCap[backCapI++] = face.m_i[0];
+				 *      indicesBackCap[backCapI++] = face.m_i[1+condition0];
+				 *      indicesBackCap[backCapI++] = face.m_i[2-condition0];
 				 * }
 				 */
 			}
@@ -1523,8 +1520,13 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 				verticesSide[vsideI++] = VertexData(v1, 0.0f);
 				verticesSide[vsideI++] = VertexData(v1, 1.0f);
 
-				indicesSide[sideI++] = Index3us(indexSide+0, indexSide+1, indexSide+2); 
-				indicesSide[sideI++] = Index3us(indexSide+2, indexSide+1, indexSide+3);
+				indicesSide[sideI++] = indexSide+0;
+				indicesSide[sideI++] = indexSide+1;
+				indicesSide[sideI++] = indexSide+2;
+
+				indicesSide[sideI++] = indexSide+2;
+				indicesSide[sideI++] = indexSide+1;
+				indicesSide[sideI++] = indexSide+3;
 
 				indexSide += 4;
 			}
@@ -1572,17 +1574,13 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 			uint16_t winding = uint16_t(k > 0);
 			for (uint8_t ii = 0, end = abs(k); ii < end; ++ii)
 			{
-				indicesSide[sideI++] =
-					Index3us(uint16_t(indexSide)
-						, uint16_t(indexSide + 2 - winding)
-						, uint16_t(indexSide + 1 + winding)
-						);
+				indicesSide[sideI++] = indexSide;
+				indicesSide[sideI++] = indexSide + 2 - winding;
+				indicesSide[sideI++] = indexSide + 1 + winding;
 
-				indicesSide[sideI++] =
-					Index3us(uint16_t(indexSide + 2)
-						, uint16_t(indexSide + 3 - winding*2)
-						, uint16_t(indexSide + 1 + winding*2) 
-						);
+				indicesSide[sideI++] = indexSide + 2;
+				indicesSide[sideI++] = indexSide + 3 - winding*2;
+				indicesSide[sideI++] = indexSide + 1 + winding*2;
 			}
 
 			indexSide += 4;
@@ -1602,11 +1600,15 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 				{
 					if (frontFacing)
 					{
-						indicesFrontCap[frontCapI++] = *(Index3us*)face.m_i; 
+						indicesFrontCap[frontCapI++] = face.m_i[0];
+						indicesFrontCap[frontCapI++] = face.m_i[1];
+						indicesFrontCap[frontCapI++] = face.m_i[2];
 					}
 					else
 					{
-						indicesBackCap[backCapI++] = *(Index3us*)face.m_i; 
+						indicesBackCap[backCapI++] = face.m_i[0];
+						indicesBackCap[backCapI++] = face.m_i[1];
+						indicesBackCap[backCapI++] = face.m_i[2];
 					}
 				}
 			}
@@ -1630,14 +1632,12 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 
 	//sides
 	uint32_t vsize = vsideI * 5*sizeof(float);
-	uint32_t isize = sideI * 3*sizeof(uint16_t);
+	uint32_t isize = sideI * sizeof(uint16_t);
 
-	mem = bgfx::alloc(vsize);
-	memcpy(mem->data, verticesSide, vsize);
+	mem = bgfx::makeRef(verticesSide, vsize);
 	_shadowVolume.m_vbSides = bgfx::createVertexBuffer(mem, decl);
 
-	mem = bgfx::alloc(isize);
-	memcpy(mem->data, indicesSide, isize);
+	mem = bgfx::makeRef(indicesSide, isize);
 	_shadowVolume.m_ibSides = bgfx::createIndexBuffer(mem);
 
 	// bgfx::destroy*Buffer doesn't actually destroy buffers now.
@@ -1648,29 +1648,21 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 	if (cap)
 	{
 		//front cap
-		isize = frontCapI * 3*sizeof(uint16_t); 
-		mem = bgfx::alloc(isize);
-		memcpy(mem->data, indicesFrontCap, isize);
+		isize = frontCapI * sizeof(uint16_t);
+		mem = bgfx::makeRef(indicesFrontCap, isize);
 		_shadowVolume.m_ibFrontCap = bgfx::createIndexBuffer(mem);
 
 		//gets destroyed after the end of the next frame
 		bgfx::destroyIndexBuffer(_shadowVolume.m_ibFrontCap);
 
 		//back cap
-		isize = backCapI * 3*sizeof(uint16_t); 
-		mem = bgfx::alloc(isize);
-		memcpy(mem->data, indicesBackCap, isize);
+		isize = backCapI * sizeof(uint16_t);
+		mem = bgfx::makeRef(indicesBackCap, isize);
 		_shadowVolume.m_ibBackCap = bgfx::createIndexBuffer(mem);
 
 		//gets destroyed after the end of the next frame
 		bgfx::destroyIndexBuffer(_shadowVolume.m_ibBackCap);
 	}
-
-	//release resources
-	free(verticesSide);
-	free(indicesSide);
-	free(indicesFrontCap);
-	free(indicesBackCap);
 }
 
 void createNearClipVolume(float* __restrict _outPlanes24f
@@ -1884,8 +1876,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 	s_stencilRt  = bgfx::createRenderTarget(viewState.m_width, viewState.m_height, BGFX_RENDER_TARGET_COLOR_RGBA8 | BGFX_RENDER_TARGET_DEPTH);
 
-	u_texColor   = bgfx::createUniform("u_texColor",            bgfx::UniformType::Uniform1iv);
-	u_texStencil = bgfx::createUniform("u_texStencil",          bgfx::UniformType::Uniform1iv);
+	u_texColor   = bgfx::createUniform("u_texColor",   bgfx::UniformType::Uniform1iv);
+	u_texStencil = bgfx::createUniform("u_texStencil", bgfx::UniformType::Uniform1iv);
 
 	bgfx::ProgramHandle programTextureLightning = loadProgram("vs_shadowvolume_texture_lightning", "fs_shadowvolume_texture_lightning");
 	bgfx::ProgramHandle programColorLightning   = loadProgram("vs_shadowvolume_color_lightning",   "fs_shadowvolume_color_lightning"  );
@@ -1977,9 +1969,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 	vplaneModel.m_program = programColorTexture;
 	vplaneModel.m_texture = flareTex;
 
-	//setup lights
-	const uint8_t MAX_NUM_LIGHTS = 5;
-	const float rgbInnerR[MAX_NUM_LIGHTS][4] =
+	// Setup lights.
+	const float rgbInnerR[MAX_LIGHTS_COUNT][4] =
 	{
 		{ 1.0f, 0.7f, 0.2f, 0.0f }, //yellow
 		{ 0.7f, 0.2f, 1.0f, 0.0f }, //purple
@@ -1988,10 +1979,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		{ 0.7f, 0.7f, 0.7f, 0.0f }, //white
 	};
 
-	float lightRgbInnerR[MAX_NUM_LIGHTS][4];
-	for (uint8_t ii = 0, jj = 0; ii < MAX_NUM_LIGHTS; ++ii, ++jj)
+	float lightRgbInnerR[MAX_LIGHTS_COUNT][4];
+	for (uint8_t ii = 0, jj = 0; ii < MAX_LIGHTS_COUNT; ++ii, ++jj)
 	{
-		const uint8_t index = jj%MAX_NUM_LIGHTS;
+		const uint8_t index = jj%MAX_LIGHTS_COUNT;
 		lightRgbInnerR[ii][0] = rgbInnerR[index][0];
 		lightRgbInnerR[ii][1] = rgbInnerR[index][1];
 		lightRgbInnerR[ii][2] = rgbInnerR[index][2];
@@ -2066,8 +2057,11 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		}
 
 		//set view and projection matrices
-		const float aspect = float(viewState.m_width)/float(viewState.m_height);
-		mtxProj(viewState.m_proj, 60.0f, aspect, 1.0f, 1000.0f);
+		const float fov       = 60.0f;
+		const float aspect    = float(viewState.m_width)/float(viewState.m_height);
+		const float nearPlane = 1.0f;
+		const float farPlane  = 1000.0f;
+		mtxProj(viewState.m_proj, fov, aspect, nearPlane, farPlane);
 		float at[3] = { 3.0f, 5.0f, 0.0f };
 		float eye[3] = { 3.0f, 20.0f, -58.0f };
 		mtxLookAt(viewState.m_view, eye, at);
@@ -2104,7 +2098,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			currentScene = Scene1;
 		}
 
-		imguiSlider("Lights", &settings_numLights, 1.0f, 5.0f, 1.0f);
+		imguiSlider("Lights", &settings_numLights, 1.0f, float(MAX_LIGHTS_COUNT), 1.0f);
 
 		if (imguiCheck("Update lights", settings_updateLights) )
 		{
@@ -2170,7 +2164,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 		if (Scene1 == currentScene)
 		{
-			imguiSlider("Instance count", &settings_instanceCount, 1.0f, 49.0f, 1.0f);
+			imguiSlider("Instance count", &settings_instanceCount, 1.0f, float(MAX_INSTANCE_COUNT), 1.0f);
 		}
 
 		imguiLabel("CPU Time: %7.1f [ms]", double(profTime)*toMs);
@@ -2224,7 +2218,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		}
 
 		//setup light positions
-		float lightPosRadius[MAX_NUM_LIGHTS][4];
+		float lightPosRadius[MAX_LIGHTS_COUNT][4];
 		if (LightPattern0 == lightPattern)
 		{
 			for (uint8_t ii = 0; ii < settings_numLights; ++ii)
@@ -2417,13 +2411,12 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		{
 			enum Direction
 			{
-				Left = 0,
-				Down,
-				Right,
-				Up,
-
-				DirectionCount,
+				Left  = 0x0,
+				Down  = 0x1,
+				Right = 0x2,
+				Up    = 0x3,
 			};
+			const uint8_t directionMask = 0x3;
 
 			uint8_t currentDirection = Left;
 			float currX = 0.0f;
@@ -2431,7 +2424,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 			const float stepX = 20.0f;
 			const float stepY = 20.0f;
 			uint8_t stateStep = 0;
-			float stateChange = 1.0f;
+			uint8_t stateChange = 1;
 
 			for (uint8_t ii = 0; ii < settings_instanceCount; ++ii)
 			{
@@ -2447,12 +2440,12 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				inst.m_pos[2]      = currY;
 				inst.m_model       = bunnyModel;
 
-				stateStep++;
-				if (stateStep >= floor(stateChange/2.0f) )
+				++stateStep;
+				if (stateStep >= ( (stateChange & ~0x1) >> 1) )
 				{
-					currentDirection = (currentDirection+1)%DirectionCount;
+					currentDirection = (++currentDirection) & directionMask;
 					stateStep = 0;
-					stateChange += 1.0f;
+					++stateChange;
 				}
 
 				switch (currentDirection)
@@ -2461,7 +2454,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				case Down:  currY -= stepY; break;
 				case Right: currX += stepX; break;
 				case Up:    currY += stepY; break;
-				default: break;
 				}
 			}
 		}
@@ -2482,7 +2474,15 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		}
 
 		// Make sure at the beginning everything gets cleared.
-		::clearView(0, BGFX_CLEAR_COLOR_BIT | BGFX_CLEAR_DEPTH_BIT | BGFX_CLEAR_STENCIL_BIT, clearValues);
+		bgfx::setViewClear(0
+				, BGFX_CLEAR_COLOR_BIT
+				| BGFX_CLEAR_DEPTH_BIT
+				| BGFX_CLEAR_STENCIL_BIT
+				, clearValues.m_clearRgba
+				, clearValues.m_clearDepth
+				, clearValues.m_clearStencil
+				);
+
 		::submit(0);
 
 		// Draw ambient only.
@@ -2512,9 +2512,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// Using stencil texture requires rendering to separate render target. first pass is building depth buffer.
 		if (settings_useStencilTexture)
 		{
-			ClearValues cv = { 0x00000000, 1.0f, 0 };
-			::clearView(VIEWID_RANGE1_RT_PASS1, BGFX_CLEAR_DEPTH_BIT, cv);
-			::setViewRenderTarget(VIEWID_RANGE1_RT_PASS1, s_stencilRt);
+			bgfx::setViewClear(VIEWID_RANGE1_RT_PASS1, BGFX_CLEAR_DEPTH_BIT, 0x00000000, 1.0f, 0);
+			bgfx::setViewRenderTarget(VIEWID_RANGE1_RT_PASS1, s_stencilRt);
 
 			const RenderState& renderState = s_renderStates[RenderState::ShadowVolume_UsingStencilTexture_BuildDepth]; 
 
@@ -2546,13 +2545,26 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 
 			if (settings_useStencilTexture)
 			{
-				ClearValues cv = { 0x00000000, 1.0f, 0 };
-				::clearView(viewId, BGFX_CLEAR_COLOR_BIT, cv);
-				::setViewRenderTarget(viewId, s_stencilRt);
+				bgfx::setViewRenderTarget(viewId, s_stencilRt);
+
+				bgfx::setViewClear(viewId
+						, BGFX_CLEAR_COLOR_BIT
+						, 0x00000000
+						, 1.0f
+						, 0
+						);
 			}
 			else
 			{
-				::clearView(viewId, BGFX_CLEAR_STENCIL_BIT, clearValues);
+				const bgfx::RenderTargetHandle invalidRt = BGFX_INVALID_HANDLE;
+				bgfx::setViewRenderTarget(viewId, invalidRt);
+
+				bgfx::setViewClear(viewId
+						, BGFX_CLEAR_STENCIL_BIT
+						, clearValues.m_clearRgba
+						, clearValues.m_clearDepth
+						, clearValues.m_clearStencil
+						);
 			}
 
 			// Create near clip volume for current light.
@@ -2564,7 +2576,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 				pointLight[1] = lightPos[1];
 				pointLight[2] = lightPos[2];
 				pointLight[3] = 1.0f;
-				createNearClipVolume(nearClipVolume, pointLight, viewState.m_view, 60.0f, 16.0f/9.0f, 0.1f);
+				createNearClipVolume(nearClipVolume, pointLight, viewState.m_view, fov, aspect, nearPlane);
 			}
 
 			for (uint8_t jj = 0; jj < shadowCastersCount[currentScene]; ++jj)
@@ -2749,14 +2761,16 @@ int _main_(int /*_argc*/, char** /*_argv*/)
 		// process submitted rendering primitives.
 		bgfx::frame();
 
-		// Reset clear values on used views.
-		clearViewMask(s_clearMask, BGFX_CLEAR_NONE, clearValues);
-		s_clearMask = 0;
+		// Swap memory pages.
+		s_svAllocator.swap();
 
-		// Reset assigned render target views.
-		const bgfx::RenderTargetHandle invalidHandle = BGFX_INVALID_HANDLE;
-		bgfx::setViewRenderTargetMask(s_rtMask, invalidHandle);
-		s_rtMask = 0;
+		// Reset clear values.
+		bgfx::setViewClearMask(UINT32_MAX
+			, BGFX_CLEAR_NONE
+			, clearValues.m_clearRgba
+			, clearValues.m_clearDepth
+			, clearValues.m_clearStencil
+			);
 	}
 
 	// Cleanup

BIN
examples/runtime/meshes/bunny_decimated.bin


BIN
examples/runtime/meshes/bunny_patched.bin