|
|
@@ -10,67 +10,52 @@ namespace anki {
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
|
-struct PointLightUniformBlock
|
|
|
+// Shader struct and block representations
|
|
|
+
|
|
|
+struct ShaderLight
|
|
|
{
|
|
|
Vec4 posAndRadius; ///< xyz: Light pos in eye space. w: The radius
|
|
|
Vec4 diffuseColor;
|
|
|
Vec4 specularColor;
|
|
|
};
|
|
|
|
|
|
-struct SpotLightUniformBlock: PointLightUniformBlock
|
|
|
+typedef ShaderLight ShaderPointLight;
|
|
|
+
|
|
|
+struct ShaderSpotLight: ShaderLight
|
|
|
{
|
|
|
Mat4 texProjectionMat;
|
|
|
};
|
|
|
|
|
|
-struct GeneralUniformBlock
|
|
|
+struct ShaderPointLights
|
|
|
{
|
|
|
- Vec4 nearPlanes;
|
|
|
- Vec4 limitsOfNearPlane;
|
|
|
- PointLightUniformBlock light;
|
|
|
+ ShaderPointLight lights[Is::MAX_LIGHTS];
|
|
|
};
|
|
|
|
|
|
-//==============================================================================
|
|
|
-void Is::initTiles()
|
|
|
+struct ShaderSpotLights
|
|
|
{
|
|
|
- // FBO
|
|
|
- Renderer::createFai(TILES_X_COUNT, TILES_Y_COUNT, GL_RGB32F, GL_RGB,
|
|
|
- GL_FLOAT, minMaxFai);
|
|
|
- minMaxTilerFbo.create();
|
|
|
- minMaxTilerFbo.setColorAttachments({&minMaxFai});
|
|
|
- if(!minMaxTilerFbo.isComplete())
|
|
|
- {
|
|
|
- throw ANKI_EXCEPTION("minMaxTilerFbo creation failed");
|
|
|
- }
|
|
|
-
|
|
|
- // Shader program
|
|
|
- std::string preproc =
|
|
|
- "#define TILES_X_COUNT " + std::to_string(TILES_X_COUNT) + "\n"
|
|
|
- "#define TILES_Y_COUNT " + std::to_string(TILES_Y_COUNT) + "\n";
|
|
|
- std::string filename = ShaderProgramResource::createSrcCodeToCache(
|
|
|
- "shaders/IsMinMax.glsl",
|
|
|
- preproc.c_str());
|
|
|
- minMaxPassSprog.load(filename.c_str());
|
|
|
+ ShaderSpotLight lights[Is::MAX_LIGHTS];
|
|
|
+};
|
|
|
|
|
|
- // Tiles
|
|
|
- F32 tileWidth = 1.0 / TILES_X_COUNT;
|
|
|
- F32 tileHeight = 1.0 / TILES_Y_COUNT;
|
|
|
+struct ShaderTile
|
|
|
+{
|
|
|
+ U32 lightsCount;
|
|
|
+ U32 lightIndices[Is::MAX_LIGHTS_PER_TILE];
|
|
|
+};
|
|
|
|
|
|
- for(U i = 0; i < TILES_X_COUNT; i++)
|
|
|
- {
|
|
|
- for(U j = 0; j < TILES_Y_COUNT; j++)
|
|
|
- {
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+struct ShaderTiles
|
|
|
+{
|
|
|
+ ShaderTile tile[Is::TILES_X_COUNT * Is::TILES_X_COUNT];
|
|
|
+};
|
|
|
|
|
|
-//==============================================================================
|
|
|
-void Is::minMaxPass()
|
|
|
+struct ShaderCommonUniforms
|
|
|
{
|
|
|
-}
|
|
|
+ Vec4 nearPlanes;
|
|
|
+ Vec4 limitsOfNearPlane;
|
|
|
+};
|
|
|
|
|
|
//==============================================================================
|
|
|
Is::Is(Renderer* r_)
|
|
|
- : RenderingPass(r_), smo(r_), sm(r_)
|
|
|
+ : RenderingPass(r_), sm(r_)
|
|
|
{}
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -82,251 +67,174 @@ void Is::init(const RendererInitializer& initializer)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- // Init the passes
|
|
|
- //
|
|
|
- smo.init(initializer);
|
|
|
- sm.init(initializer);
|
|
|
-
|
|
|
- // Load the programs
|
|
|
- //
|
|
|
-
|
|
|
- // Ambient pass
|
|
|
- ambientPassSProg.load("shaders/IsAp.glsl");
|
|
|
-
|
|
|
- // point light
|
|
|
- pointLightSProg.load(ShaderProgramResource::createSrcCodeToCache(
|
|
|
- "shaders/IsLpGeneric.glsl", "#define POINT_LIGHT 1\n").c_str());
|
|
|
-
|
|
|
- // spot light no shadow
|
|
|
- spotLightNoShadowSProg.load(
|
|
|
- ShaderProgramResource::createSrcCodeToCache(
|
|
|
- "shaders/IsLpGeneric.glsl", "#define SPOT_LIGHT 1\n").c_str());
|
|
|
-
|
|
|
- // spot light w/t shadow
|
|
|
- std::string pps = std::string("#define SPOT_LIGHT 1\n"
|
|
|
- "#define SHADOW 1\n");
|
|
|
- if(/*sm.isPcfEnabled()*/ 1) // XXX
|
|
|
- {
|
|
|
- pps += "#define PCF 1\n";
|
|
|
- }
|
|
|
- spotLightShadowSProg.load(ShaderProgramResource::createSrcCodeToCache(
|
|
|
- "shaders/IsLpGeneric.glsl", pps.c_str()).c_str());
|
|
|
-
|
|
|
- // Create FBO
|
|
|
- //
|
|
|
- Renderer::createFai(r->getWidth(), r->getHeight(), GL_RGB8,
|
|
|
- GL_RGB, GL_UNSIGNED_INT, fai);
|
|
|
- fbo.create();
|
|
|
- fbo.setColorAttachments({&fai});
|
|
|
- fbo.setOtherAttachment(GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
- r->getMs().getDepthFai());
|
|
|
-
|
|
|
- if(!fbo.isComplete())
|
|
|
- {
|
|
|
- throw ANKI_EXCEPTION("Fbo not complete");
|
|
|
- }
|
|
|
-
|
|
|
- // Create UBOs
|
|
|
- //
|
|
|
-
|
|
|
- // General UBO
|
|
|
- const ShaderProgramUniformBlock& block =
|
|
|
- pointLightSProg->findUniformBlock("generalBlock");
|
|
|
-
|
|
|
- if(block.getSize() != sizeof(GeneralUniformBlock))
|
|
|
- {
|
|
|
- throw ANKI_EXCEPTION("Uniform block size is not the expected");
|
|
|
- }
|
|
|
-
|
|
|
- generalUbo.create(GL_UNIFORM_BUFFER, sizeof(GeneralUniformBlock),
|
|
|
- nullptr, GL_DYNAMIC_DRAW);
|
|
|
-
|
|
|
- generalUbo.setBinding(0);
|
|
|
+ initInternal(initializer);
|
|
|
}
|
|
|
catch(const std::exception& e)
|
|
|
{
|
|
|
- throw ANKI_EXCEPTION("Failed to create IS stage") << e;
|
|
|
+ throw ANKI_EXCEPTION("Failed to init IS") << e;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-void Is::ambientPass(const Vec3& color)
|
|
|
+void Is::initInternal(const RendererInitializer& initializer)
|
|
|
{
|
|
|
- // set the shader
|
|
|
- ambientPassSProg->bind();
|
|
|
-
|
|
|
- // set the uniforms
|
|
|
- ambientPassSProg->findUniformVariable("ambientCol").set(color);
|
|
|
- ambientPassSProg->findUniformVariable("msFai0").set(
|
|
|
- r->getMs().getFai0());
|
|
|
-
|
|
|
- // Draw quad
|
|
|
- r->drawQuad();
|
|
|
-}
|
|
|
-
|
|
|
-//==============================================================================
|
|
|
-void Is::pointLightPass(PointLight& light)
|
|
|
-{
|
|
|
- const Camera& cam = r->getScene().getActiveCamera();
|
|
|
-
|
|
|
- /// XXX write the UBO async before calling SMO
|
|
|
+ //
|
|
|
+ // Init the passes
|
|
|
+ //
|
|
|
+ sm.init(initializer);
|
|
|
+
|
|
|
+ //
|
|
|
+ // Load the programs
|
|
|
+ //
|
|
|
+ std::string pps;
|
|
|
+
|
|
|
+ // point light
|
|
|
+ lightSProgs[LST_POINT].load(ShaderProgramResource::createSrcCodeToCache(
|
|
|
+ "shaders/IsLpGeneric.glsl", "#define POINT_LIGHT 1\n").c_str());
|
|
|
+
|
|
|
+ // spot light no shadow
|
|
|
+ lightSProgs[LST_SPOT].load(
|
|
|
+ ShaderProgramResource::createSrcCodeToCache(
|
|
|
+ "shaders/IsLpGeneric.glsl", "#define SPOT_LIGHT 1\n").c_str());
|
|
|
+
|
|
|
+ // spot light w/t shadow
|
|
|
+ pps = std::string("#define SPOT_LIGHT 1\n"
|
|
|
+ "#define SHADOW 1\n");
|
|
|
+ if(/*sm.isPcfEnabled()*/ 1) // XXX
|
|
|
+ {
|
|
|
+ pps += "#define PCF 1\n";
|
|
|
+ }
|
|
|
+ lightSProgs[LST_SPOT_SHADOW].load(
|
|
|
+ ShaderProgramResource::createSrcCodeToCache(
|
|
|
+ "shaders/IsLpGeneric.glsl", pps.c_str()).c_str());
|
|
|
|
|
|
- // SMO
|
|
|
- smo.run(light);
|
|
|
- GlStateSingleton::get().disable(GL_DEPTH_TEST);
|
|
|
+ // Min max
|
|
|
+ pps =
|
|
|
+ "#define TILES_X_COUNT " + std::to_string(TILES_X_COUNT) + "\n"
|
|
|
+ "#define TILES_Y_COUNT " + std::to_string(TILES_Y_COUNT) + "\n"
|
|
|
+ "#define RENDERER_WIDTH " + std::to_string(r->getWidth()) + "\n"
|
|
|
+ "#define RENDERER_HEIGHT " + std::to_string(r->getWidth()) + "\n";
|
|
|
+ std::string filename = ShaderProgramResource::createSrcCodeToCache(
|
|
|
+ "shaders/IsMinMax.glsl",
|
|
|
+ pps.c_str());
|
|
|
+ minMaxPassSprog.load(filename.c_str());
|
|
|
|
|
|
- // shader prog
|
|
|
- const ShaderProgram& shader = *pointLightSProg; // ensure the const-ness
|
|
|
- shader.bind();
|
|
|
+ //
|
|
|
+ // Create FBOs
|
|
|
+ //
|
|
|
|
|
|
- shader.findUniformVariable("msFai0").set(r->getMs().getFai0());
|
|
|
- shader.findUniformVariable("msDepthFai").set(
|
|
|
+ // IS FBO
|
|
|
+ Renderer::createFai(r->getWidth(), r->getHeight(), GL_RGB8,
|
|
|
+ GL_RGB, GL_UNSIGNED_INT, fai);
|
|
|
+ fbo.create();
|
|
|
+ fbo.setColorAttachments({&fai});
|
|
|
+ fbo.setOtherAttachment(GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
r->getMs().getDepthFai());
|
|
|
|
|
|
- GeneralUniformBlock blk;
|
|
|
- blk.nearPlanes = Vec4(cam.getNear(), 0.0, r->getPlanes().x(),
|
|
|
- r->getPlanes().y());
|
|
|
- blk.limitsOfNearPlane = Vec4(r->getLimitsOfNearPlane(),
|
|
|
- r->getLimitsOfNearPlane2());
|
|
|
-
|
|
|
- Vec3 pos = light.getWorldTransform().getOrigin().getTransformed(
|
|
|
- cam.getViewMatrix());
|
|
|
- blk.light.posAndRadius = Vec4(pos, light.getRadius());
|
|
|
- blk.light.diffuseColor = light.getDiffuseColor();
|
|
|
- blk.light.specularColor = light.getSpecularColor();;
|
|
|
-
|
|
|
- generalUbo.write(&blk, 0, sizeof(GeneralUniformBlock));
|
|
|
+ if(!fbo.isComplete())
|
|
|
+ {
|
|
|
+ throw ANKI_EXCEPTION("Fbo not complete");
|
|
|
+ }
|
|
|
|
|
|
- // render quad
|
|
|
- r->drawQuad();
|
|
|
-}
|
|
|
+ // min max FBO
|
|
|
+ Renderer::createFai(TILES_X_COUNT, TILES_Y_COUNT, GL_RG32F, GL_RG,
|
|
|
+ GL_FLOAT, minMaxFai);
|
|
|
+ minMaxFai.setFiltering(Texture::TFT_NEAREST);
|
|
|
+ minMaxTilerFbo.create();
|
|
|
+ minMaxTilerFbo.setColorAttachments({&minMaxFai});
|
|
|
+ if(!minMaxTilerFbo.isComplete())
|
|
|
+ {
|
|
|
+ throw ANKI_EXCEPTION("minMaxTilerFbo not complete");
|
|
|
+ }
|
|
|
|
|
|
-//==============================================================================
|
|
|
-void Is::spotLightPass(SpotLight& light)
|
|
|
-{
|
|
|
-#if 0
|
|
|
- const Camera& cam = r->getScene().getActiveCamera();
|
|
|
- const ShaderProgram* shdr;
|
|
|
- //bool withShadow = light.getShadowEnabled() && sm.getEnabled();
|
|
|
- bool withShadow = false;
|
|
|
+ //
|
|
|
+ // Create UBOs
|
|
|
+ //
|
|
|
|
|
|
- // shadow mapping
|
|
|
- if(withShadow)
|
|
|
- {
|
|
|
- /*Vec3 zAxis = light.getWorldTransform().getRotation().getColumn(2);
|
|
|
- LineSegment seg(light.getWorldTransform().getOrigin(),
|
|
|
- -zAxis * light.getCamera().getZFar());
|
|
|
+ // Common UBO
|
|
|
+ /*const ShaderProgramUniformBlock& block =
|
|
|
+ lightSProgs[LST_POINT]->findUniformBlock("commonBlock");*/
|
|
|
|
|
|
- const Plane& plane = cam.getWSpaceFrustumPlane(Camera::FP_NEAR);
|
|
|
+ commonUbo.create(sizeof(ShaderCommonUniforms), nullptr);
|
|
|
+ commonUbo.setBinding(0);
|
|
|
|
|
|
- float dist = seg.testPlane(plane);
|
|
|
+ // lights UBO
|
|
|
+ lightsUbo.create(sizeof(ShaderSpotLights), nullptr);
|
|
|
+ commonUbo.setBinding(1);
|
|
|
|
|
|
- sm.run(light, dist);
|
|
|
+ // lightIndices UBO
|
|
|
+ lightIndicesUbo.create(sizeof(ShaderTiles), nullptr);
|
|
|
+ commonUbo.setBinding(2);
|
|
|
|
|
|
- // restore the IS FBO
|
|
|
- fbo.bind();
|
|
|
+ //
|
|
|
+ // Init tiles
|
|
|
+ //
|
|
|
+ F32 tileWidth = 1.0 / TILES_X_COUNT;
|
|
|
+ F32 tileHeight = 1.0 / TILES_Y_COUNT;
|
|
|
|
|
|
- // and restore blending and depth test
|
|
|
- GlStateMachineSingleton::get().enable(GL_BLEND, BLEND_ENABLE);
|
|
|
- glBlendFunc(GL_ONE, GL_ONE);
|
|
|
- GlStateMachineSingleton::get().enable(GL_DEPTH_TEST, false);
|
|
|
- GlStateMachineSingleton::get().setViewport(0, 0,
|
|
|
- r.getWidth(), r.getHeight());*/
|
|
|
- shdr = spotLightShadowSProg.get();
|
|
|
- }
|
|
|
- else
|
|
|
+ for(U i = 0; i < TILES_X_COUNT; i++)
|
|
|
{
|
|
|
- shdr = spotLightNoShadowSProg.get();
|
|
|
+ for(U j = 0; j < TILES_Y_COUNT; j++)
|
|
|
+ {
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- // stencil optimization
|
|
|
- smo.run(light);
|
|
|
- GlStateSingleton::get().enable(GL_DEPTH_TEST, false);
|
|
|
-
|
|
|
- shdr->bind();
|
|
|
-
|
|
|
- // the block
|
|
|
- UniformBlockData data;
|
|
|
- data.planes = Vec4(r->getPlanes(), 0.0, 0.0);
|
|
|
- data.limitsOfNearPlane = Vec4(r->getLimitsOfNearPlane(),
|
|
|
- r->getLimitsOfNearPlane2());
|
|
|
- data.zNearLightRadius = Vec4(cam.getNear(), light.getDistance(), 0.0, 0.0);
|
|
|
- Vec3 lightPosEyeSpace = light.getWorldTransform().getOrigin().
|
|
|
- getTransformed(cam.getViewMatrix());
|
|
|
- data.lightPos = Vec4(lightPosEyeSpace, 0.0);
|
|
|
- data.lightDiffuseCol = light.getDiffuseColor();
|
|
|
- data.lightSpecularCol = light.getSpecularColor();
|
|
|
-
|
|
|
- // set texture matrix for texture & shadowmap projection
|
|
|
- // Bias * P_light * V_light * inv(V_cam)
|
|
|
- static const Mat4 biasMat4(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0,
|
|
|
- 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
|
|
|
- data.texProjectionMat = biasMat4 * light.getProjectionMatrix() *
|
|
|
- Mat4::combineTransformations(light.getViewMatrix(),
|
|
|
- Mat4(cam.getWorldTransform()));
|
|
|
-
|
|
|
- ubo.write(&data, 0, sizeof(UniformBlockData));
|
|
|
-
|
|
|
- // bind the FAIs
|
|
|
- shdr->findUniformVariable("msFai0").set(r->getMs().getFai0());
|
|
|
- shdr->findUniformVariable("msDepthFai").set(r->getMs().getDepthFai());
|
|
|
- shdr->findUniformVariable("lightTex").set(light.getTexture());
|
|
|
-
|
|
|
- // the shadowmap
|
|
|
- /*if(withShadow)
|
|
|
- {
|
|
|
- shdr->findUniformVariable("shadowMap").set(sm.getShadowMap());
|
|
|
- }*/
|
|
|
+//==============================================================================
|
|
|
+void Is::projectShape(const Mat4& projectionMat,
|
|
|
+ const Sphere& sphere, Vec2& circleCenter, F32& circleRadius)
|
|
|
+{
|
|
|
|
|
|
- // render quad
|
|
|
- r->drawQuad();
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
//==============================================================================
|
|
|
-void Is::run()
|
|
|
+void Is::minMaxPass()
|
|
|
{
|
|
|
- fbo.bind();
|
|
|
- GlStateSingleton::get().setViewport(0, 0, r->getWidth(), r->getHeight());
|
|
|
+ // Do the pass
|
|
|
+ //
|
|
|
const Camera& cam = r->getScene().getActiveCamera();
|
|
|
|
|
|
- // Ambient pass
|
|
|
- GlStateSingleton::get().disable(GL_BLEND);
|
|
|
GlStateSingleton::get().disable(GL_DEPTH_TEST);
|
|
|
- glDepthMask(GL_FALSE);
|
|
|
- ambientPass(r->getScene().getAmbientColor());
|
|
|
-
|
|
|
-#if BLEND_ENABLE
|
|
|
- GlStateSingleton::get().enable(GL_BLEND);
|
|
|
- glBlendFunc(GL_ONE, GL_ONE);
|
|
|
-#else
|
|
|
- GlStateSingleton::get().disable(GL_BLEND);
|
|
|
+
|
|
|
+ minMaxTilerFbo.bind();
|
|
|
+ minMaxPassSprog->bind();
|
|
|
+ GlStateSingleton::get().setViewport(0, 0, TILES_X_COUNT, TILES_Y_COUNT);
|
|
|
+#if 1
|
|
|
+ minMaxPassSprog->findUniformVariable("nearFar").set(
|
|
|
+ Vec2(cam.getNear(), cam.getFar()));
|
|
|
+ minMaxPassSprog->findUniformVariable("depthMap").set(
|
|
|
+ r->getMs().getDepthFai());
|
|
|
#endif
|
|
|
|
|
|
- GlStateSingleton::get().enable(GL_STENCIL_TEST);
|
|
|
+ r->drawQuad();
|
|
|
+
|
|
|
+ // Update the tiles
|
|
|
+ //
|
|
|
+ F32 pixels[TILES_X_COUNT][TILES_Y_COUNT][2];
|
|
|
|
|
|
- VisibilityInfo& vi =
|
|
|
- r->getScene().getActiveCamera().getFrustumable()->getVisibilityInfo();
|
|
|
- for(auto it = vi.getLightsBegin();
|
|
|
- it != vi.getLightsEnd(); ++it)
|
|
|
+ minMaxFai.readPixels(pixels);
|
|
|
+
|
|
|
+ for(U i = 0; i < TILES_X_COUNT; i++)
|
|
|
{
|
|
|
- Light& light = *(*it);
|
|
|
- switch(light.getLightType())
|
|
|
+ for(U j = 0; j < TILES_Y_COUNT; j++)
|
|
|
{
|
|
|
- case Light::LT_SPOT:
|
|
|
- spotLightPass(static_cast<SpotLight&>(light));
|
|
|
- break;
|
|
|
- case Light::LT_POINT:
|
|
|
- pointLightPass(static_cast<PointLight&>(light));
|
|
|
- break;
|
|
|
- default:
|
|
|
- ANKI_ASSERT(0);
|
|
|
- break;
|
|
|
+ Tile& tile = tiles[i][j];
|
|
|
+ tile.depth = Vec2(pixels[i][j][0], pixels[i][j][1]);
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- GlStateSingleton::get().disable(GL_STENCIL_TEST);
|
|
|
- glDepthMask(GL_TRUE);
|
|
|
+//==============================================================================
|
|
|
+void Is::run()
|
|
|
+{
|
|
|
+ /*fbo.bind();
|
|
|
+ GlStateSingleton::get().setViewport(0, 0, r->getWidth(), r->getHeight());
|
|
|
+ const Camera& cam = r->getScene().getActiveCamera();*/
|
|
|
+
|
|
|
+ //minMaxPass();
|
|
|
+
|
|
|
+ fbo.bind();
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT);
|
|
|
}
|
|
|
|
|
|
} // end namespace anki
|