|
@@ -69,37 +69,28 @@ void Lf::initInternal(const RendererInitializer& initializer)
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- maxFlaresPerLight = initializer.pps.lf.maxFlaresPerLight;
|
|
|
|
|
- maxLightsWithFlares = initializer.pps.lf.maxLightsWithFlares;
|
|
|
|
|
-
|
|
|
|
|
- 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
|
|
// Load the shader
|
|
|
- std::string pps = "#define MAX_FLARES "
|
|
|
|
|
- + std::to_string(maxFlaresPerLight * maxLightsWithFlares) + "\n";
|
|
|
|
|
- std::string fname = ShaderProgramResource::createSrcCodeToCache(
|
|
|
|
|
- "shaders/PpsLfPass.glsl", pps.c_str());
|
|
|
|
|
- drawProg.load(fname.c_str());
|
|
|
|
|
|
|
+ std::string pps = "#define TEX_DIMENSIONS vec2("
|
|
|
|
|
+ + std::to_string(r->getPps().getHdr().getFai().getWidth()) + ".0, "
|
|
|
|
|
+ + std::to_string(r->getPps().getHdr().getFai().getHeight()) + ".0)\n";
|
|
|
|
|
|
|
|
- ublock = &drawProg->findUniformBlock("flaresBlock");
|
|
|
|
|
- ublock->setBinding(0);
|
|
|
|
|
|
|
+ drawProg.load(ShaderProgramResource::createSrcCodeToCache(
|
|
|
|
|
+ "shaders/PpsLfPass.glsl", pps.c_str()).c_str());
|
|
|
|
|
|
|
|
- PtrSize blockSize = sizeof(Flare) * maxFlaresPerLight * maxLightsWithFlares;
|
|
|
|
|
- if(ublock->getSize() != blockSize)
|
|
|
|
|
|
|
+ // Create the FAI
|
|
|
|
|
+ fai.create2dFai(r->getPps().getHdr().getFai().getWidth(),
|
|
|
|
|
+ r->getPps().getHdr().getFai().getHeight(),
|
|
|
|
|
+ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE);
|
|
|
|
|
+
|
|
|
|
|
+ fbo.create();
|
|
|
|
|
+ fbo.setColorAttachments({&fai});
|
|
|
|
|
+ if(!fbo.isComplete())
|
|
|
{
|
|
{
|
|
|
- throw ANKI_EXCEPTION("Incorrect block size");
|
|
|
|
|
|
|
+ throw ANKI_EXCEPTION("Fbo not complete");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Init UBO
|
|
|
|
|
- flareDataUbo.create(blockSize, nullptr);
|
|
|
|
|
|
|
+ // Textures
|
|
|
|
|
+ lensDirtTex.load("engine-rsrc/lens_dirt.ankitex");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
//==============================================================================
|
|
@@ -107,143 +98,20 @@ void Lf::run()
|
|
|
{
|
|
{
|
|
|
ANKI_ASSERT(enabled);
|
|
ANKI_ASSERT(enabled);
|
|
|
|
|
|
|
|
- // Retrieve some things
|
|
|
|
|
- SceneGraph& scene = r->getSceneGraph();
|
|
|
|
|
- Camera& cam = scene.getActiveCamera();
|
|
|
|
|
- VisibilityTestResults& vi = *cam.getVisibilityTestResults();
|
|
|
|
|
-
|
|
|
|
|
- //
|
|
|
|
|
- // Iterate the visible light and get those that have lens flare
|
|
|
|
|
- //
|
|
|
|
|
- Array<Light*, ANKI_MAX_LIGHTS_WITH_FLARE> lights;
|
|
|
|
|
- U lightsCount = 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[lightsCount % maxLightsWithFlares] = light;
|
|
|
|
|
- ++lightsCount;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Early exit
|
|
|
|
|
- if(lightsCount == 0)
|
|
|
|
|
- {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- lightsCount = lightsCount % (maxLightsWithFlares + 1);
|
|
|
|
|
-
|
|
|
|
|
- //
|
|
|
|
|
- // Sort the lights using their lens flare texture
|
|
|
|
|
- //
|
|
|
|
|
- std::sort(lights.begin(), lights.begin() + lightsCount, LightSortFunctor());
|
|
|
|
|
-
|
|
|
|
|
- //
|
|
|
|
|
- // Write the UBO and get the groups
|
|
|
|
|
- //
|
|
|
|
|
-
|
|
|
|
|
- Array<Flare, ANKI_MAX_FLARES> flares;
|
|
|
|
|
- U flaresCount = 0;
|
|
|
|
|
-
|
|
|
|
|
- // Contains the number of flares per flare texture
|
|
|
|
|
- Array<U, ANKI_MAX_LIGHTS_WITH_FLARE> groups;
|
|
|
|
|
- Array<const Texture*, ANKI_MAX_LIGHTS_WITH_FLARE> texes;
|
|
|
|
|
- U groupsCount = 0;
|
|
|
|
|
-
|
|
|
|
|
- GLuint lastTexId = 0;
|
|
|
|
|
-
|
|
|
|
|
- // Iterate all lights and update the flares as well as the groups
|
|
|
|
|
- while(lightsCount-- != 0)
|
|
|
|
|
- {
|
|
|
|
|
- Light& light = *lights[lightsCount];
|
|
|
|
|
- const Texture& tex = light.getLensFlareTexture();
|
|
|
|
|
- const U depth = tex.getDepth();
|
|
|
|
|
-
|
|
|
|
|
- // Transform
|
|
|
|
|
- Vec3 posWorld = light.getWorldTransform().getOrigin();
|
|
|
|
|
- Vec4 posClip = cam.getViewProjectionMatrix() * Vec4(posWorld, 1.0);
|
|
|
|
|
- Vec2 posNdc = posClip.xy() / posClip.w();
|
|
|
|
|
-
|
|
|
|
|
- Vec2 dir = -posNdc;
|
|
|
|
|
- F32 len = dir.getLength();
|
|
|
|
|
- dir /= len; // Normalize dir
|
|
|
|
|
-
|
|
|
|
|
- // New group?
|
|
|
|
|
- if(lastTexId != tex.getGlId())
|
|
|
|
|
- {
|
|
|
|
|
- texes[groupsCount] = &tex;
|
|
|
|
|
- groups[groupsCount] = 0;
|
|
|
|
|
- lastTexId = tex.getGlId();
|
|
|
|
|
-
|
|
|
|
|
- ++groupsCount;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // First flare
|
|
|
|
|
- flares[flaresCount].pos = posNdc;
|
|
|
|
|
- flares[flaresCount].scale =
|
|
|
|
|
- Vec2(0.1, r->getAspectRatio() * 0.1);
|
|
|
|
|
- flares[flaresCount].depth = 0.0;
|
|
|
|
|
- flares[flaresCount].alpha = 0.5;
|
|
|
|
|
- ++flaresCount;
|
|
|
|
|
- ++groups[groupsCount - 1];
|
|
|
|
|
-
|
|
|
|
|
- // The rest of the flares
|
|
|
|
|
- for(U d = 1; d < depth; d++)
|
|
|
|
|
- {
|
|
|
|
|
- // Write the "flares"
|
|
|
|
|
- F32 factor = d / ((F32)depth - 1.0);
|
|
|
|
|
-
|
|
|
|
|
- F32 flen = len * 2.0 * factor;
|
|
|
|
|
-
|
|
|
|
|
- flares[flaresCount].pos = posNdc + dir * flen;
|
|
|
|
|
-
|
|
|
|
|
- flares[flaresCount].scale =
|
|
|
|
|
- Vec2(0.1, r->getAspectRatio() * 0.1)
|
|
|
|
|
- * (len - flen) * 2.0;
|
|
|
|
|
-
|
|
|
|
|
- flares[flaresCount].depth = d;
|
|
|
|
|
-
|
|
|
|
|
- flares[flaresCount].alpha = 0.1;
|
|
|
|
|
-
|
|
|
|
|
- // Advance
|
|
|
|
|
- ++flaresCount;
|
|
|
|
|
- ++groups[groupsCount - 1];
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //
|
|
|
|
|
- // Time to render
|
|
|
|
|
- //
|
|
|
|
|
-
|
|
|
|
|
- // Write the buffer
|
|
|
|
|
- flareDataUbo.write(&flares[0], 0, sizeof(Flare) * flaresCount);
|
|
|
|
|
-
|
|
|
|
|
// Set the common state
|
|
// Set the common state
|
|
|
- drawProg->bind();
|
|
|
|
|
- GlStateSingleton::get().disable(GL_DEPTH_TEST);
|
|
|
|
|
- GlStateSingleton::get().enable(GL_BLEND);
|
|
|
|
|
- GlStateSingleton::get().setBlendFunctions(GL_ONE, GL_ONE);
|
|
|
|
|
-
|
|
|
|
|
- PtrSize offset = 0;
|
|
|
|
|
- for(U i = 0; i < groupsCount; i++)
|
|
|
|
|
- {
|
|
|
|
|
- const Texture& tex = *texes[i];
|
|
|
|
|
- U instances = groups[i];
|
|
|
|
|
- PtrSize buffSize = sizeof(Flare) * instances;
|
|
|
|
|
|
|
+ const Texture& inTex = r->getPps().getHdr().getFai();
|
|
|
|
|
|
|
|
- drawProg->findUniformVariable("images").set(tex);
|
|
|
|
|
|
|
+ fbo.bind();
|
|
|
|
|
+ drawProg->bind();
|
|
|
|
|
+ drawProg->findUniformVariable("tex").set(inTex);
|
|
|
|
|
+ drawProg->findUniformVariable("lensDirtTex").set(*lensDirtTex);
|
|
|
|
|
|
|
|
- flareDataUbo.setBindingRange(0, offset, buffSize);
|
|
|
|
|
-
|
|
|
|
|
- r->drawQuadInstanced(instances);
|
|
|
|
|
|
|
+ GlStateSingleton::get().setViewport(
|
|
|
|
|
+ 0, 0, inTex.getWidth(), inTex.getHeight());
|
|
|
|
|
+ GlStateSingleton::get().disable(GL_DEPTH_TEST);
|
|
|
|
|
+ GlStateSingleton::get().disable(GL_BLEND);
|
|
|
|
|
|
|
|
- offset += buffSize;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ r->drawQuad();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // end namespace anki
|
|
} // end namespace anki
|