Procházet zdrojové kódy

- SSLR improvements
- Collision additions

Panagiotis Christopoulos Charitos před 11 roky
rodič
revize
01386e2260

+ 2 - 1
include/anki/Collision.h

@@ -1,7 +1,7 @@
 #ifndef ANKI_COLLISION_H
 #define ANKI_COLLISION_H
 
-/// @defgroup Collision Collision detection module
+/// @defgroup collision Collision detection module
 
 #include "anki/collision/Plane.h"
 #include "anki/collision/Sphere.h"
@@ -10,6 +10,7 @@
 #include "anki/collision/LineSegment.h"
 #include "anki/collision/Frustum.h"
 #include "anki/collision/Aabb.h"
+#include "anki/collision/CompoundShape.h"
 
 #include "anki/collision/Functions.h"
 

+ 3 - 30
include/anki/collision/Aabb.h

@@ -6,7 +6,7 @@
 
 namespace anki {
 
-/// @addtogroup Collision
+/// @addtogroup collision
 /// @{
 
 /// Axis align bounding box collision shape
@@ -112,8 +112,8 @@ public:
 	Aabb getCompoundShape(const Aabb& b) const;
 
 	/// Calculate from a set of points
-	template<typename Container>
-	void set(const Container& container);
+	void setFromPointCloud(
+		const void* buff, U count, PtrSize stride, PtrSize buffSize);
 
 private:
 	/// @name Data
@@ -124,33 +124,6 @@ private:
 };
 /// @}
 
-//==============================================================================
-template<typename Container>
-void Aabb::set(const Container& container)
-{
-	ANKI_ASSERT(container.size() >= 1);
-
-	m_min = container.front();
-	m_max = m_min;
-
-	// for all the Vec3s calc the max and min
-	typename Container::const_iterator it = container.begin() + 1;
-	for(; it != container.end(); ++it)
-	{
-		for(U j = 0; j < 3; j++)
-		{
-			if((*it)[j] > m_max[j])
-			{
-				m_max[j] = (*it)[j];
-			}
-			else if((*it)[j] < m_min[j])
-			{
-				m_min[j] = (*it)[j];
-			}
-		}
-	}
-}
-
 } // end namespace anki
 
 #endif

+ 6 - 3
include/anki/collision/CollisionShape.h

@@ -1,5 +1,5 @@
-#ifndef ANKI_COLLISION_COLLISION_SHAPE
-#define ANKI_COLLISION_COLLISION_SHAPE
+#ifndef ANKI_COLLISION_COLLISION_SHAPE_H
+#define ANKI_COLLISION_COLLISION_SHAPE_H
 
 #include "anki/collision/Forward.h"
 #include "anki/collision/CollisionAlgorithms.h"
@@ -9,7 +9,7 @@
 
 namespace anki {
 
-/// @addtogroup Collision
+/// @addtogroup collision
 /// @{
 
 /// Abstract class for collision shapes. It also features a visitor for
@@ -27,6 +27,7 @@ public:
 		AABB,
 		OBB,
 		FRUSTUM,
+		COMPOUND
 	};
 
 	/// Generic mutable visitor
@@ -43,6 +44,7 @@ public:
 		virtual void visit(Ray&) = 0;
 		virtual void visit(Sphere&) = 0;
 		virtual void visit(Aabb&) = 0;
+		virtual void visit(CompoundShape&) = 0;
 	};
 
 	/// Generic const visitor
@@ -59,6 +61,7 @@ public:
 		virtual void visit(const Ray&) = 0;
 		virtual void visit(const Sphere&) = 0;
 		virtual void visit(const Aabb&) = 0;
+		virtual void visit(const CompoundShape&) = 0;
 	};
 
 	/// @name Constructors & destructor

+ 73 - 0
include/anki/collision/CompoundShape.h

@@ -0,0 +1,73 @@
+#ifndef ANKI_COLLISION_COMPOUND_SHAPE_H
+#define ANKI_COLLISION_COMPOUND_SHAPE_H
+
+#include "anki/collision/CollisionShape.h"
+#include "anki/util/NonCopyable.h"
+
+namespace anki {
+
+/// @addtogroup collision
+/// @{
+
+/// A shape that contains other shapes
+class CompoundShape: public CollisionShape, public NonCopyable
+{
+public:
+	/// @name Constructors
+	/// @{
+	CompoundShape();
+	/// @}
+
+	/// Implements CollisionShape::testPlane
+	F32 testPlane(const Plane& p) const;
+
+	/// Implements CollisionShape::transform
+	void transform(const Transform& trf);
+
+	/// Implements CollisionShape::computeAabb
+	void computeAabb(Aabb& b) const;
+
+	/// Implements CollisionShape::accept
+	void accept(MutableVisitor& v);
+
+	/// Implements CollisionShape::accept
+	void accept(ConstVisitor& v) const;
+
+	/// The compound shape will not take ownership of the object
+	void addShape(CollisionShape* shape);
+
+private:
+	static const U SHAPES_PER_CHUNK = 8;
+
+	Array<CollisionShape*, SHAPES_PER_CHUNK> m_dflt;
+
+	template<typename TFunc>
+	void iterateShapes(TFunc f)
+	{
+		U idx = 0;
+		while(m_dflt[idx])
+		{
+			f(*m_dflt[idx]);
+		}
+		ANKI_ASSERT(idx > 0 && "Empty CompoundShape");
+	}
+
+	template<typename TFunc>
+	void iterateShapes(TFunc f) const
+	{
+		U idx = 0;
+		while(m_dflt[idx])
+		{
+			f(*m_dflt[idx]);
+		}
+		ANKI_ASSERT(idx > 0 && "Empty CompoundShape");
+	}
+};
+
+/// @}
+
+} // end namespace anki
+
+#endif
+
+

+ 1 - 0
include/anki/collision/Forward.h

@@ -12,6 +12,7 @@ class Plane;
 class Ray;
 class Sphere;
 class Aabb;
+class CompoundShape;
 
 } // end namespace anki
 

+ 5 - 38
include/anki/collision/Obb.h

@@ -7,7 +7,7 @@
 
 namespace anki {
 
-/// @addtogroup Collision
+/// @addtogroup collision
 /// @{
 
 /// Object oriented bounding box
@@ -113,8 +113,8 @@ public:
 	Obb getCompoundShape(const Obb& b) const;
 
 	/// Calculate from a set of points
-	template<typename Container>
-	void set(const Container& container);
+	void setFromPointCloud(
+		const void* buff, U count, PtrSize stride, PtrSize buffSize);
 
 	/// Get extreme points in 3D space
 	void getExtremePoints(Array<Vec3, 8>& points) const;
@@ -129,42 +129,9 @@ public:
 	Vec3 m_extends;
 	/// @}
 };
-/// @}
-
-//==============================================================================
-template<typename Container>
-void Obb::set(const Container& container)
-{
-	ANKI_ASSERT(container.size() >= 1);
-
-	Vec3 min(container.front());
-	Vec3 max(container.front());
 
-	// for all the Vec3s calc the max and min
-	typename Container::const_iterator it = container.begin() + 1;
-	for(; it != container.end(); ++it)
-	{
-		const Vec3& v = *it;
-
-		for(U j = 0; j < 3; j++)
-		{
-			if(v[j] > max[j])
-			{
-				max[j] = v[j];
-			}
-			else if(v[j] < min[j])
-			{
-				min[j] = v[j];
-			}
-		}
-	}
-
-	// set the locals
-	m_center = (max + min) / 2.0;
-	m_rotation = Mat3::getIdentity();
-	m_extends = max - m_center;
-}
+/// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 3 - 0
include/anki/renderer/DebugDrawer.h

@@ -118,6 +118,9 @@ public:
 
 	void visit(const Aabb&);
 
+	void visit(const CompoundShape&)
+	{}
+
 private:
 	DebugDrawer* m_dbg; ///< The debug drawer
 };

+ 32 - 0
include/anki/renderer/RenderingPass.h

@@ -2,6 +2,9 @@
 #define ANKI_RENDERER_RENDERING_PASS_H
 
 #include "anki/util/StdTypes.h"
+#include "anki/Gl.h"
+#include "anki/resource/Resource.h"
+#include "anki/resource/ProgramResource.h"
 
 namespace anki {
 
@@ -64,6 +67,35 @@ protected:
 	Bool8 m_enabled = false;
 };
 
+/// Blurring pass
+class BlurringRenderingPass
+{
+protected:
+	U32 m_blurringIterationsCount = 1; ///< The blurring iterations
+
+	class Direction
+	{
+	public:
+		GlFramebufferHandle m_fb;
+		GlTextureHandle m_rt; 
+		ProgramResourcePointer m_frag;
+		GlProgramPipelineHandle m_ppline;
+	};
+
+	enum class DirectionEnum: U
+	{
+		VERTICAL,
+		HORIZONTAL
+	};
+
+	Array<Direction, 2> m_dirs;
+
+	void initBlurring(Renderer& r, U width, U height, U samples, 
+		F32 blurringDistance);
+
+	void runBlurring(Renderer& r, GlJobChainHandle& jobs);
+};
+
 /// @}
 
 } // end namespace anki

+ 7 - 5
include/anki/renderer/Sslr.h

@@ -11,18 +11,20 @@ namespace anki {
 /// @{
 
 /// Screen space local reflections pass
-class Sslr: public OptionalRenderingPass
+class Sslr: public OptionalRenderingPass, public BlurringRenderingPass
 {
 	friend class Pps;
-	friend class MainRenderer;
+
+public:
+	GlTextureHandle& _getRt()
+	{
+		return m_dirs[(U)DirectionEnum::VERTICAL].m_rt;
+	}
 
 private:
 	U32 m_width;
 	U32 m_height;
 
-	GlFramebufferHandle m_fb;
-	GlTextureHandle m_rt;
-
 	// 1st pass
 	ProgramResourcePointer m_reflectionFrag;
 	GlProgramPipelineHandle m_reflectionPpline;

+ 5 - 0
include/anki/util/Vector.h

@@ -31,6 +31,11 @@ public:
 		ANKI_ASSERT(i < Base::size() && "Vector out of bounds");
 		return Base::operator[](i);
 	}
+
+	PtrSize getSizeInBytes() const
+	{
+		return Base::size() * sizeof(T);
+	}
 };
 
 /// @}

+ 22 - 35
shaders/PpsSslr.frag.glsl

@@ -70,15 +70,13 @@ void main()
 	vec3 r = reflect(eye, normal);
 
 #if 1
-	float t = -p0.z / (r.z + 0.000001);
+	// Let p1 be the intersection of p0+r to the near plane, then
+	// p1 = p0 + t*r or p1.x = p0.x + t*r.x, p1.y = p0.y + t*r.y and
+	// p1.z = p0.z + t*r.z (3)
+	// p1.z is known to ~0.0 so if we solve (3) t becomes:
+	float t = -p0.z / (r.z + 0.0000001);
 	vec3 p1 = p0 + r * t;
 
-	/*if(p1.z > 0.0)
-	{
-		outColor = vec3(1, 0.0, 1);
-		return;
-	}*/
-
 	vec2 pp0 = inTexCoords * 2.0 - 1.0;
 	vec3 pp1 = project(p1);
 
@@ -90,14 +88,14 @@ void main()
 
 	// XXX
 	float len = length(dir);
-	float stepD =  len / steps;
+	float stepInc =  len / steps;
 	dir /= len;
 
-	steps = min(steps, 400.0);
+	steps = min(steps, 300.0);
 
-	for(float i = 1.0; i < steps; i += 1.0)
+	for(float i = 10.0; i < steps; i += 1.5)
 	{
-		vec2 ndc = pp0 + dir * (i * stepD);
+		vec2 ndc = pp0 + dir * (i * stepInc);
 
 		vec2 comp = abs(ndc);
 		if(comp.x > 1.0 || comp.y > 1.0)
@@ -122,24 +120,18 @@ void main()
 
 		float diffDepth = depth - intersection.z;
 
-		/*if(i + 4.0 > 400.0)
-		{
-			outColor = vec3(pp1.zz, 0.0);
-			return;
-		}*/
-
 		if(diffDepth > 0.0)
 		{
-			if(diffDepth > 0.4)
+			if(diffDepth > 0.3)
 			{
-				//outColor = vec3(1.0);
+				outColor = vec3(0.01);
 				return;
 			}
 
 			float factor = 1.0 - length(ndc.xy);
 			factor *= 1.0 - length(pp0.xy);
 
-			outColor = textureRt(uIsRt, texCoord).rgb * (factor * specColor);
+			outColor = textureRt(uIsRt, texCoord).rgb * (factor * 1.1 /* specColor*/);
 
 			//outColor = vec3(1.0 - abs(pp0.xy), 0.0);
 			return;
@@ -148,26 +140,24 @@ void main()
 #endif
 
 #if 0
-	vec3 pos = posv;
-	int i;
-	for(i = 0; i < 200; i++)
+	vec3 pos = p0;
+	for(int i = 0; i < 200; i++)
 	{
 		pos += r * 0.1;
 
-		vec4 posNdc = uProjectionMatrix * vec4(pos, 1.0);
-		posNdc.xyz /= posNdc.w;
+		vec3 posNdc = project(pos);
 
-		if(posNdc.x > 1.0 || posNdc.x < -1.0
-			|| posNdc.y > 1.0 || posNdc.y < -1.0)
+		vec2 comp = abs(posNdc.xy);
+		if(comp.x > 1.0 || comp.y > 1.0)
 		{
-			break;
+			return;
 		}
 
-		vec3 posClip = posNdc.xyz * 0.5 + 0.5;
+		vec3 texCoord = posNdc.xyz * 0.5 + 0.5;
 
-		float depth = textureRt(uMsDepthRt, posClip.xy).r;
+		float depth = textureRt(uMsDepthRt, texCoord.xy).r;
 
-		float diffDepth = posClip.z - depth;
+		float diffDepth = texCoord.z - depth;
 
 		if(diffDepth > 0.0)
 		{
@@ -178,13 +168,10 @@ void main()
 
 			float factor = 1.0 - length(posNdc.xy);
 
-			outColor = textureRt(uIsRt, posClip.xy).rgb * (factor * specColor);
+			outColor = textureRt(uIsRt, texCoord.xy).rgb * (factor * specColor);
 			//outColor = vec3(diffDepth);
 			return;
 		}
 	}
-
-	outColor = vec3(0.0);
-	//outColor = vec3(float(i) / 100.0);
 #endif
 }

+ 37 - 0
src/collision/Aabb.cpp

@@ -77,4 +77,41 @@ Aabb Aabb::getCompoundShape(const Aabb& b) const
 	return out;
 }
 
+//==============================================================================
+void Aabb::setFromPointCloud(
+	const void* buff, U count, PtrSize stride, PtrSize buffSize)
+{
+	ANKI_ASSERT(buff);
+	ANKI_ASSERT(count > 1);
+	ANKI_ASSERT(stride >= sizeof(Vec3));
+	ANKI_ASSERT(buffSize >= stride * count);
+
+	const U8* ptr = (const U8*)buff;
+	const Vec3* pos = (const Vec3*)(ptr);
+	m_min = *pos;
+	m_max = m_min;
+	--count;
+
+	while(count-- != 0)
+	{
+		ANKI_ASSERT(
+			(((PtrSize)ptr + sizeof(Vec3)) - (PtrSize)buff) <= buffSize);
+		const Vec3* pos = (const Vec3*)(ptr);
+
+		for(U j = 0; j < 3; j++)
+		{
+			if((*pos)[j] > m_max[j])
+			{
+				m_max[j] = (*pos)[j];
+			}
+			else if((*pos)[j] < m_min[j])
+			{
+				m_min[j] = (*pos)[j];
+			}
+		}
+
+		ptr += stride;
+	}
+}
+
 } // namespace anki

+ 88 - 0
src/collision/CompoundShape.cpp

@@ -0,0 +1,88 @@
+#include "anki/collision/CompoundShape.h"
+#include "anki/collision/Aabb.h"
+#include <cstring>
+
+namespace anki {
+
+//==============================================================================
+CompoundShape::CompoundShape()
+	: CollisionShape(Type::COMPOUND)
+{
+	memset(&m_dflt[0], 0, sizeof(m_dflt));
+}
+
+//==============================================================================
+F32 CompoundShape::testPlane(const Plane& p) const
+{
+	F32 min = MAX_F32;
+	F32 max = MIN_F32;
+
+	iterateShapes([&](CollisionShape& cs)
+	{
+		F32 a = cs.testPlane(p);
+		min = std::min(min, a);
+		max = std::max(max, a);
+	});
+
+	if(min > 0.0 && max > 0.0)
+	{
+		return std::min(min, max);
+	}
+	else if(min < 0.0 && max < 0.0)
+	{
+		return std::max(min, max);
+	}
+	
+	return 0.0;
+}
+
+//==============================================================================
+void CompoundShape::accept(MutableVisitor& v)
+{
+	iterateShapes([&](CollisionShape& cs)
+	{
+		cs.accept(v);
+	});
+}
+
+//==============================================================================
+void CompoundShape::accept(ConstVisitor& v) const
+{
+	iterateShapes([&](CollisionShape& cs)
+	{
+		cs.accept(v);
+	});
+}
+
+//==============================================================================
+void CompoundShape::transform(const Transform& trf)
+{
+	iterateShapes([&](CollisionShape& cs)
+	{
+		cs.transform(trf);
+	});
+}
+
+//==============================================================================
+void CompoundShape::computeAabb(Aabb& out) const
+{
+	Vec3 min(MAX_F32), max(MIN_F32);
+
+	iterateShapes([&](CollisionShape& cs)
+	{
+		Aabb aabb;
+		cs.computeAabb(aabb);
+
+		for(U i = 0; i < 3; i++)
+		{
+			min[i] = std::min(min[i], aabb.getMin()[i]);
+			max[i] = std::max(max[i], aabb.getMax()[i]);
+		}
+	});
+
+	out.setMin(min);
+	out.setMax(max);
+}
+
+} // end namespace anki
+

+ 2 - 1
src/collision/Frustum.cpp

@@ -126,7 +126,8 @@ void PerspectiveFrustum::computeAabb(Aabb& aabb) const
 {
 	Array<Vec3, 5> points = {{
 		m_dirs[0], m_dirs[1], m_dirs[2], m_dirs[3], Vec3(0.0)}};
-	aabb.set(points);
+	aabb.setFromPointCloud(&points[0], points.size(), sizeof(Vec3), 
+		points.size() * sizeof(Vec3));
 	aabb.getMin() += m_eye;
 	aabb.getMax() += m_eye;
 }

+ 45 - 1
src/collision/Obb.cpp

@@ -85,7 +85,8 @@ Obb Obb::getCompoundShape(const Obb& b) const
 		points[i + 8] = points1[i];
 	}
 
-	out.set(points);
+	out.setFromPointCloud(&points[0], points.size(), sizeof(Vec3), 
+		sizeof(Vec3) * points.size());
 	return out;
 }
 
@@ -146,4 +147,47 @@ void Obb::computeAabb(Aabb& aabb) const
 		m_center + newE + Vec3(getEpsilon<F32>() * 100.0));
 }
 
+//==============================================================================
+void Obb::setFromPointCloud(
+	const void* buff, U count, PtrSize stride, PtrSize buffSize)
+{
+	ANKI_ASSERT(buff);
+	ANKI_ASSERT(count > 1);
+	ANKI_ASSERT(stride >= sizeof(Vec3));
+	ANKI_ASSERT(buffSize >= stride * count);
+
+	// Calc min/max
+	const U8* ptr = (const U8*)buff;
+	const Vec3* pos = (const Vec3*)(ptr);
+	Vec3 min = *pos;
+	Vec3 max = min;
+	--count;
+
+	while(count-- != 0)
+	{
+		ANKI_ASSERT(
+			(((PtrSize)ptr + sizeof(Vec3)) - (PtrSize)buff) <= buffSize);
+		const Vec3* pos = (const Vec3*)(ptr);
+
+		for(U j = 0; j < 3; j++)
+		{
+			if((*pos)[j] > max[j])
+			{
+				max[j] = (*pos)[j];
+			}
+			else if((*pos)[j] < min[j])
+			{
+				min[j] = (*pos)[j];
+			}
+		}
+
+		ptr += stride;
+	}
+
+	// Set the locals
+	m_center = (max + min) / 2.0;
+	m_rotation = Mat3::getIdentity();
+	m_extends = max - m_center;
+}
+
 } // end namespace anki

+ 2 - 2
src/gl/GlJobChain.cpp

@@ -76,8 +76,8 @@ GlGlobalHeapAllocator<U8> GlJobChain::getGlobalAllocator() const
 //==============================================================================
 void GlJobChain::executeAllJobs()
 {
-	ANKI_ASSERT(m_firstJob != nullptr);
-	ANKI_ASSERT(m_lastJob != nullptr);
+	ANKI_ASSERT(m_firstJob != nullptr && "Empty job chain");
+	ANKI_ASSERT(m_lastJob != nullptr && "Empty job chain");
 #if ANKI_DEBUG
 	m_executed = true;
 #endif

+ 1 - 1
src/renderer/Hdr.cpp

@@ -22,7 +22,7 @@ void Hdr::initFb(GlFramebufferHandle& fb, GlTextureHandle& rt)
 
 	// Create FB
 	fb = GlFramebufferHandle(jobs, {{rt, GL_COLOR_ATTACHMENT0}});
-	jobs.flush();
+	jobs.finish();
 }
 
 //==============================================================================

+ 1 - 1
src/renderer/MainRenderer.cpp

@@ -76,7 +76,7 @@ void MainRenderer::render(SceneGraph& scene)
 			rt = &getIs()._getRt();
 		}
 
-		rt = &getPps().getSslr().m_rt;
+		rt = &getPps().getSslr()._getRt();
 		rt = &getMs()._getRt0();
 
 		rt->setFilter(lastJobs, GlTextureHandle::Filter::LINEAR);

+ 3 - 2
src/renderer/Renderer.cpp

@@ -43,13 +43,14 @@ RendererInitializer::RendererInitializer()
 
 	newOption("pps.ssao.enabled", true);
 	newOption("pps.ssao.renderingQuality", 0.3);
-	newOption("pps.ssao.blurringIterationsNum", 2);
+	newOption("pps.ssao.blurringIterationsCount", 1);
 
 	newOption("pps.sslr.enabled", true);
 	newOption("pps.sslr.renderingQuality", 0.2);
+	newOption("pps.sslr.blurringIterationsCount", 1);
 
 	newOption("pps.bl.enabled", true);
-	newOption("pps.bl.blurringIterationsNum", 2);
+	newOption("pps.bl.blurringIterationsCount", 1);
 	newOption("pps.bl.sideBlurFactor", 1.0);
 
 	newOption("pps.lf.enabled", true);

+ 75 - 0
src/renderer/RenderingPass.cpp

@@ -0,0 +1,75 @@
+#include "anki/renderer/RenderingPass.h"
+#include "anki/renderer/Renderer.h"
+#include <sstream>
+
+namespace anki {
+
+//==============================================================================
+void BlurringRenderingPass::initBlurring(
+	Renderer& r, U width, U height, U samples, F32 blurringDistance)
+{
+	GlManager& gl = GlManagerSingleton::get();
+	GlJobChainHandle jobs(&gl);
+
+	Array<std::stringstream, 2> pps;
+
+	pps[1] << "#define HPASS\n"
+		"#define COL_RGB\n"
+		"#define BLURRING_DIST float(" << blurringDistance << ")\n"
+		"#define IMG_DIMENSION " << height << "\n"
+		"#define SAMPLES " << samples << "\n";
+
+	pps[0] << "#define VPASS\n"
+		"#define COL_RGB\n"
+		"#define BLURRING_DIST float(" << blurringDistance << ")\n"
+		"#define IMG_DIMENSION " << width << "\n"
+		"#define SAMPLES " << samples << "\n";
+
+	for(U i = 0; i < 2; i++)
+	{
+		Direction& dir = m_dirs[i];
+
+		r.createRenderTarget(width, height, GL_RGB8, GL_RGB, 
+			GL_UNSIGNED_BYTE, 1, dir.m_rt);
+
+		// Set to bilinear because the blurring techniques take advantage of 
+		// that
+		dir.m_rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
+
+		// Create FB
+		dir.m_fb = GlFramebufferHandle(
+			jobs, {{dir.m_rt, GL_COLOR_ATTACHMENT0}});
+
+		dir.m_frag.load(ProgramResource::createSrcCodeToCache(
+			"shaders/VariableSamplingBlurGeneric.frag.glsl", 
+			pps[i].str().c_str(), "r_").c_str());
+
+		dir.m_ppline = 
+			r.createDrawQuadProgramPipeline(dir.m_frag->getGlProgram());
+	}
+
+	jobs.finish();
+}
+
+//==============================================================================
+void BlurringRenderingPass::runBlurring(Renderer& r, GlJobChainHandle& jobs)
+{
+	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(jobs, 1); // H pass input
+	m_dirs[(U)DirectionEnum::HORIZONTAL].m_rt.bind(jobs, 0); // V pass input
+
+	for(U32 i = 0; i < m_blurringIterationsCount; i++)
+	{
+		// hpass
+		m_dirs[(U)DirectionEnum::HORIZONTAL].m_fb.bind(jobs, true);
+		m_dirs[(U)DirectionEnum::HORIZONTAL].m_ppline.bind(jobs);
+		r.drawQuad(jobs);
+
+		// vpass
+		m_dirs[(U)DirectionEnum::VERTICAL].m_fb.bind(jobs, true);
+		m_dirs[(U)DirectionEnum::VERTICAL].m_ppline.bind(jobs);
+		r.drawQuad(jobs);
+	}
+}
+
+} // end namespace anki
+

+ 1 - 1
src/renderer/Ssao.cpp

@@ -90,7 +90,7 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 	}
 
 	m_blurringIterationsCount = 
-		initializer.get("pps.ssao.blurringIterationsNum");
+		initializer.get("pps.ssao.blurringIterationsCount");
 
 	//
 	// Init the widths/heights

+ 36 - 13
src/renderer/Sslr.cpp

@@ -14,11 +14,10 @@ void Sslr::init(const RendererInitializer& initializer)
 		return;
 	}
 
-	GlManager& gl = GlManagerSingleton::get();
-	GlJobChainHandle jobs(&gl);
-
 	// Size
 	const F32 quality = initializer.get("pps.sslr.renderingQuality");
+	m_blurringIterationsCount = 
+		initializer.get("pps.sslr.blurringIterationsCount");
 
 	m_width = quality * (F32)m_r->getWidth();
 	alignRoundUp(16, m_width);
@@ -38,19 +37,36 @@ void Sslr::init(const RendererInitializer& initializer)
 	m_reflectionPpline = m_r->createDrawQuadProgramPipeline(
 		m_reflectionFrag->getGlProgram());
 
-	// Fb
-	m_r->createRenderTarget(m_width, m_height, GL_RGB8, GL_RGB, 
-		GL_UNSIGNED_BYTE, 1, m_rt);
-	m_rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
-
-	m_fb = GlFramebufferHandle(jobs, {{m_rt, GL_COLOR_ATTACHMENT0}});
-
 	// Blit
 	m_blitFrag.load("shaders/Blit.frag.glsl");
 	m_blitPpline = m_r->createDrawQuadProgramPipeline(
 		m_blitFrag->getGlProgram());
 
-	jobs.finish();
+	// Init FBOs and RTs and blurring
+	if(m_blurringIterationsCount > 0)
+	{
+		initBlurring(*m_r, m_width, m_height, 7, 0.5);
+	}
+	else
+	{
+		GlManager& gl = GlManagerSingleton::get();
+		GlJobChainHandle jobs(&gl);
+
+		Direction& dir = m_dirs[(U)DirectionEnum::VERTICAL];
+
+		m_r->createRenderTarget(m_width, m_height, GL_RGB8, GL_RGB, 
+			GL_UNSIGNED_BYTE, 1, dir.m_rt);
+
+		// Set to bilinear because the blurring techniques take advantage of 
+		// that
+		dir.m_rt.setFilter(jobs, GlTextureHandle::Filter::LINEAR);
+
+		// Create FB
+		dir.m_fb = GlFramebufferHandle(
+			jobs, {{dir.m_rt, GL_COLOR_ATTACHMENT0}});
+
+		jobs.finish();
+	}
 }
 
 //==============================================================================
@@ -60,7 +76,7 @@ void Sslr::run(GlJobChainHandle& jobs)
 
 	// Compute the reflection
 	//
-	m_fb.bind(jobs, true);
+	m_dirs[(U)DirectionEnum::VERTICAL].m_fb.bind(jobs, true);
 	jobs.setViewport(0, 0, m_width, m_height);
 
 	m_reflectionPpline.bind(jobs);
@@ -71,6 +87,13 @@ void Sslr::run(GlJobChainHandle& jobs)
 
 	m_r->drawQuad(jobs);
 
+	// Blurring
+	//
+	if(m_blurringIterationsCount > 0)
+	{
+		runBlurring(*m_r, jobs);
+	}
+
 	// Write the reflection back to IS RT
 	//
 	m_r->getIs().m_fb.bind(jobs, false);
@@ -79,7 +102,7 @@ void Sslr::run(GlJobChainHandle& jobs)
 	jobs.enableBlend(true);
 	jobs.setBlendFunctions(GL_ONE, GL_ONE);
 
-	m_rt.bind(jobs, 0);
+	m_dirs[(U)DirectionEnum::VERTICAL].m_rt.bind(jobs, 0);
 
 	m_blitPpline.bind(jobs);
 	m_r->drawQuad(jobs);

+ 12 - 3
src/resource/Mesh.cpp

@@ -25,7 +25,10 @@ void Mesh::load(const char* filename)
 		MeshLoader loader(filename);
 
 		m_indicesCount = loader.getIndices().size();
-		m_obb.set(loader.getPositions());
+
+		const auto& positions = loader.getPositions();
+		m_obb.setFromPointCloud(&positions[0], positions.size(),
+			sizeof(Vec3), positions.getSizeInBytes());
 		ANKI_ASSERT(m_indicesCount > 0);
 		ANKI_ASSERT(m_indicesCount % 3 == 0 && "Expecting triangles");
 
@@ -287,7 +290,10 @@ void BucketMesh::load(const char* filename)
 
 			submesh.m_indicesCount = loader->getIndices().size();
 			submesh.m_indicesOffset = m_indicesCount * sizeof(U16);
-			submesh.m_obb.set(loader->getPositions());
+
+			const auto& positions = loader->getPositions();
+			submesh.m_obb.setFromPointCloud(&positions[0], positions.size(),
+				sizeof(Vec3), positions.getSizeInBytes());
 
 			m_subMeshes.push_back(submesh);
 
@@ -302,7 +308,10 @@ void BucketMesh::load(const char* filename)
 
 		// Create the bucket mesh
 		createBuffers(fullLoader);
-		m_obb.set(fullLoader.getPositions());
+
+		const auto& positions = fullLoader.getPositions();
+		m_obb.setFromPointCloud(&positions[0], positions.size(),
+			sizeof(Vec3), positions.getSizeInBytes());
 	}
 	catch(std::exception& e)
 	{

+ 17 - 10
testapp/Main.cpp

@@ -27,6 +27,7 @@
 #include "anki/core/NativeWindow.h"
 #include "anki/Scene.h"
 #include "anki/event/LightEvent.h"
+#include "anki/event/AnimationEvent.h"
 #include "anki/event/MoveEvent.h"
 #include "anki/core/Counters.h"
 
@@ -164,7 +165,7 @@ void init()
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec3(8.27936, 5.86285, 1.85526),
 		Mat3(Quat(-0.125117, 0.620465, 0.154831, 0.758544)), 1.0));
-	spot->setDiffuseColor(Vec4(2.0));
+	spot->setDiffuseColor(Vec4(1.0));
 	spot->setSpecularColor(Vec4(-1.0));
 	spot->setDistance(30.0);
 	spot->setShadowEnabled(true);
@@ -266,9 +267,9 @@ void init()
 		0.7));
 
 
-	horse = scene.newSceneNode<ModelNode>("crate", "models/crate0/crate0.ankimdl");
-	horse->setLocalTransform(Transform(Vec3(2, 10.0, 0), Mat3::getIdentity(),
-		1.0));
+	//horse = scene.newSceneNode<ModelNode>("crate", "models/crate0/crate0.ankimdl");
+	//horse->setLocalTransform(Transform(Vec3(2, 10.0, 0), Mat3::getIdentity(),
+	//	1.0));
 
 	// barrel
 	/*ModelNode* redBarrel = new ModelNode(
@@ -296,6 +297,11 @@ void init()
 
 	initPhysics();
 
+	/*AnimationResourcePointer anim;
+	anim.load("maps/sponza/unnamed_0.ankianim");
+	AnimationEvent* event;
+	scene.getEventManager().newEvent(event, anim, cam);*/
+
 	// Sectors
 #if 0
 	SectorGroup& sgroup = scene.getSectorGroup();
@@ -352,10 +358,10 @@ void execStdinScpripts()
 //==============================================================================
 void mainLoopExtra()
 {
-	F32 dist = 0.2;
-	F32 ang = toRad(3.0);
+	F32 dist = 0.1;
+	F32 ang = toRad(1.5);
 	F32 scale = 0.01;
-	F32 mouseSensivity = 9.0;
+	F32 mouseSensivity = 6.0;
 
 	// move the camera
 	static MoveComponent* mover = 
@@ -640,12 +646,13 @@ void initSubsystems(int argc, char* argv[])
 	initializer.set("pps.hdr.exposure", 8.0);
 	initializer.set("pps.hdr.samples", 9);
 	initializer.set("pps.sslr.enabled", true);
-	initializer.set("pps.sslr.renderingQuality", 0.5);
-	initializer.set("pps.ssao.blurringIterationsNum", 1);
+	initializer.set("pps.sslr.renderingQuality", 0.35);
+	initializer.set("pps.sslr.blurringIterationsCount", 1);
+	initializer.set("pps.ssao.blurringIterationsCount", 1);
 	initializer.set("pps.ssao.enabled", true);
 	initializer.set("pps.ssao.renderingQuality", 0.35);
 	initializer.set("pps.bl.enabled", true);
-	initializer.set("pps.bl.blurringIterationsNum", 2);
+	initializer.set("pps.bl.blurringIterationsCount", 2);
 	initializer.set("pps.bl.sideBlurFactor", 1.0);
 	initializer.set("pps.lf.enabled", true);
 	initializer.set("pps.sharpen", true);