Browse Source

Working on lens flare

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
486bed7396
4 changed files with 105 additions and 19 deletions
  1. 4 3
      include/anki/renderer/Lf.h
  2. 2 2
      include/anki/renderer/Renderer.h
  3. 2 1
      shaders/PpsLfPass.glsl
  4. 97 13
      src/renderer/Lf.cpp

+ 4 - 3
include/anki/renderer/Lf.h

@@ -25,11 +25,12 @@ public:
 private:
 	ShaderProgramResourcePointer drawProg;
 	Ubo flareDataUbo;
+	const ShaderProgramUniformBlock* ublock;
 
-	U8 maxLensFlareCount;
-	U8 maxLightsWidthFlaresCount;
+	U8 maxFlaresPerLight;
+	U8 maxLightsWithFlares;
 
-	TextureResourcePointer tex;
+	void initInternal(const RendererInitializer& initializer);
 };
 
 } // end namespace anki

+ 2 - 2
include/anki/renderer/Renderer.h

@@ -82,8 +82,8 @@ struct RendererInitializer
 		struct Lf
 		{
 			Bool enabled = true;
-			U8 maxLensFlareCount = 8;
-			U8 maxLightsWidthFlaresCount = 4;
+			U8 maxFlaresPerLight = 8;
+			U8 maxLightsWithFlares = 4;
 		} lf;
 
 		Bool enabled = false;

+ 2 - 1
shaders/PpsLfPass.glsl

@@ -6,10 +6,11 @@
 struct Flare
 {
 	vec4 posAndScale; // xy: Position, z: Scale, w: Scale again
+	vec4 alphaComponent; // x: alpha
 };
 
 // The block contains data for all flares
-layout(std140) uniform FlaresBlock
+layout(std140) uniform flaresBlock
 {
 	Flare flares[MAX_FLARES];
 };

+ 97 - 13
src/renderer/Lf.cpp

@@ -11,12 +11,33 @@ namespace anki {
 // Misc                                                                        =
 //==============================================================================
 
+// Some constants
+#define ANKI_MAX_LIGHTS_WITH_FLARE 16
+#define ANKI_MAX_FLARES_PER_LIGHT 8
+#define ANKI_MAX_FLARES (ANKI_MAX_LIGHTS_WITH_FLARE * ANKI_MAX_FLARES_PER_LIGHT)
+
 //==============================================================================
 struct Flare
 {
 	Vec2 pos; ///< Position in NDC
 	Vec2 scale; ///< Scale of the quad
-	//F32 alpha; ///< Difference in alpha
+	F32 alpha; ///< Alpha value
+	U32 padding[3];
+};
+
+//==============================================================================
+struct LightSortFunctor
+{
+	Bool operator()(const SceneNode* lightA, const SceneNode* lightB)
+	{
+		ANKI_ASSERT(lightA && lightB);
+		ANKI_ASSERT(lightA->getLight() && lightB->getLight());
+		ANKI_ASSERT(lightA->getLight()->hasLensFlare() 
+			&& lightB->getLight()->hasLensFlare());
+
+		return lightA->getLight()->getLensFlareTexture().getGlId() < 
+			lightB->getLight()->getLensFlareTexture().getGlId();
+	}
 };
 
 //==============================================================================
@@ -29,6 +50,19 @@ Lf::~Lf()
 
 //==============================================================================
 void Lf::init(const RendererInitializer& initializer)
+{
+	try
+	{
+		initInternal(initializer);
+	}
+	catch(const std::exception& e)
+	{
+		throw ANKI_EXCEPTION("Failed to init LF") << e;
+	}
+}
+
+//==============================================================================
+void Lf::initInternal(const RendererInitializer& initializer)
 {
 	enabled = initializer.pps.lf.enabled;
 	if(!enabled)
@@ -36,22 +70,37 @@ void Lf::init(const RendererInitializer& initializer)
 		return;
 	}
 
-	tex.load("data/textures/lens_flare/flares0.ankitex");
+	maxFlaresPerLight = initializer.pps.lf.maxFlaresPerLight;
+	maxLightsWithFlares = initializer.pps.lf.maxLightsWithFlares;
 
-	maxLensFlareCount = initializer.pps.lf.maxLensFlareCount;
-	maxLightsWidthFlaresCount = initializer.pps.lf.maxLightsWidthFlaresCount;
+	if(maxLightsWithFlares > ANKI_MAX_LIGHTS_WITH_FLARE)
+	{
+		throw ANKI_EXCEPTION("Too big maxLightsWithFlares");
+	}
+
+	if(maxFlaresPerLight > ANKI_MAX_FLARES_PER_LIGHT)
+	{
+		throw ANKI_EXCEPTION("Too big maxFlaresPerLight");
+	}
 
 	// Load the shader
 	std::string pps = "#define MAX_FLARES " 
-		+ std::to_string(initializer.pps.lf.maxLensFlareCount) + "\n";
+		+ std::to_string(maxFlaresPerLight * maxLightsWithFlares) + "\n";
 	std::string fname = ShaderProgramResource::createSrcCodeToCache(
 		"shaders/PpsLfPass.glsl", pps.c_str());
 	drawProg.load(fname.c_str());
 
+	ublock = &drawProg->findUniformBlock("flaresBlock");
+	ublock->setBinding(0);
+
+	PtrSize blockSize = sizeof(Flare) * maxFlaresPerLight * maxLightsWithFlares;
+	if(ublock->getSize() != blockSize)
+	{
+		throw ANKI_EXCEPTION("Incorrect block size");
+	}
+
 	// Init UBO
-	flareDataUbo.create(
-		sizeof(Flare) * maxLensFlareCount * maxLightsWidthFlaresCount,
-		nullptr);
+	flareDataUbo.create(blockSize, nullptr);
 }
 
 //==============================================================================
@@ -64,13 +113,46 @@ void Lf::run()
 	Camera& cam = scene.getActiveCamera();
 	VisibilityTestResults& vi = *cam.getVisibilityTestResults();
 
-	// Iterate the lights and update the UBO
-	Array<Flare, 256> flareBuff; // XXX 256?
-	ANKI_ASSERT(
-		maxLensFlareCount * maxLightsWidthFlaresCount < flareBuff.size());
+	//
+	// Iterate the visible light and get those that have lens flare
+	//
+	Array<SceneNode*, ANKI_MAX_LIGHTS_WITH_FLARE> lights;
 
-	U count = 0;
+	U lightCount = 0;
+	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
+	{
+		SceneNode& sn = *(*it).node;
+		ANKI_ASSERT(sn.getLight());
+		Light& light = *sn.getLight();
 
+		if(light.hasLensFlare())
+		{
+			lights[lightCount % maxLightsWithFlares] = &light;
+			++lightCount;
+		}
+	}
+
+	lightCount = lightCount % (maxLightsWithFlares + 1);
+
+	//
+	// Sort the lights using the lens flare texture
+	//
+	std::sort(lights.begin(), lights.begin() + lightCount, LightSortFunctor());
+
+	//
+	// Write the UBO and get the groups
+	//
+
+	Array<Flare, ANKI_MAX_FLARES> flareBuff;
+	Array<U, ANKI_MAX_LIGHTS_WITH_FLARE> groups;
+	U groupsCount = 0;
+
+	while(lightCount-- != 0)
+	{
+		Light& light = *lights[lightCount]->getLight();
+	}
+
+#if 0
 	for(auto it = vi.getLightsBegin(); it != vi.getLightsEnd(); ++it)
 	{
 		SceneNode& sn = *(*it).node;
@@ -112,6 +194,8 @@ void Lf::run()
 	GlStateSingleton::get().enable(GL_BLEND);
 	GlStateSingleton::get().setBlendFunctions(GL_ONE, GL_ONE);
 	r->drawQuadInstanced(tex->getDepth());
+
+#endif
 }
 
 } // end namespace anki