/* * Copyright 2016 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.rendering.dag.nodes; import org.terasology.assets.ResourceUrn; import org.terasology.config.Config; import org.terasology.config.RenderingConfig; import org.terasology.monitoring.PerformanceMonitor; import org.terasology.registry.In; import org.terasology.rendering.assets.material.Material; import org.terasology.rendering.dag.ConditionDependentNode; import org.terasology.rendering.dag.stateChanges.BindFBO; import org.terasology.rendering.dag.stateChanges.EnableMaterial; import org.terasology.rendering.dag.stateChanges.SetViewportToSizeOf; import org.terasology.rendering.opengl.FBO; import org.terasology.rendering.opengl.FBOConfig; import static org.terasology.rendering.opengl.ScalingFactors.FULL_SCALE; import org.terasology.rendering.opengl.FBOManagerSubscriber; import org.terasology.rendering.opengl.fbms.DisplayResolutionDependentFBOs; import org.terasology.rendering.world.WorldRenderer; import static org.terasology.rendering.opengl.OpenGLUtils.renderFullscreenQuad; /** * Instances of this node work in tandem with instances of the BlurredAmbientOcclusionNode class. * Together they constitute an ambient occlusion pass. * * This particular node generates a first, sharper ambient occlusion output. Subsequently that's * used by the BlurredAmbientOcclusionNode to make it softer. * * At this stage only the output of BlurredAmbientOcclusionNode is used to enhance the image eventually * shown on screen to the user. It is currently not possible to use the sharper output produced by * this node alone, i.e. to have lower quality but faster ambient occlusions. * * Ambient occlusion is a subtle visual effect that makes the rendering of the world more pleasing * at the cost of some additional milliseconds per frame. Disabling it may lead to increased frame * rate while the gameplay remains unaffected. * * See http://en.wikipedia.org/wiki/Ambient_occlusion for more information on this technique. */ public class AmbientOcclusionNode extends ConditionDependentNode implements FBOManagerSubscriber { public static final ResourceUrn SSAO_FBO = new ResourceUrn("engine:ssao"); private static final ResourceUrn SSAO_MATERIAL = new ResourceUrn("engine:prog.ssao"); private static final float NOISE_TEXEL_SIZE = 0.25f; @In private DisplayResolutionDependentFBOs displayResolutionDependentFBOs; @In private WorldRenderer worldRenderer; @In private Config config; private Material ssaoMaterial; private float outputFboWidth; private float outputFboHeight; /** * This method must be called once shortly after instantiation to fully initialize the node * and make it ready for rendering. */ @Override public void initialise() { RenderingConfig renderingConfig = config.getRendering(); renderingConfig.subscribe(RenderingConfig.SSAO, this); requiresCondition(renderingConfig::isSsao); addDesiredStateChange(new EnableMaterial(SSAO_MATERIAL.toString())); ssaoMaterial = getMaterial(SSAO_MATERIAL); requiresFBO(new FBOConfig(SSAO_FBO, FULL_SCALE, FBO.Type.DEFAULT), displayResolutionDependentFBOs); addDesiredStateChange(new BindFBO(SSAO_FBO, displayResolutionDependentFBOs)); addDesiredStateChange(new SetViewportToSizeOf(SSAO_FBO, displayResolutionDependentFBOs)); displayResolutionDependentFBOs.subscribe(this); update(); // initializing ssaoBufferWidth/ssaoBufferHeight // TODO: check for input textures brought in by the material } /** * If Ambient Occlusion is enabled in the render settings, this method generates and * stores the necessary images into their own FBOs. The stored images are eventually * combined with others. * <p> * For further information on Ambient Occlusion see: http://en.wikipedia.org/wiki/Ambient_occlusion */ @Override public void process() { PerformanceMonitor.startActivity("rendering/ambientOcclusion"); ssaoMaterial.setFloat2("texelSize", 1.0f / outputFboWidth, 1.0f / outputFboHeight, true); ssaoMaterial.setFloat2("noiseTexelSize", NOISE_TEXEL_SIZE, NOISE_TEXEL_SIZE, true); renderFullscreenQuad(); PerformanceMonitor.endActivity(); } @Override public void update() { FBO ssaoFBO = displayResolutionDependentFBOs.get(SSAO_FBO); outputFboWidth = ssaoFBO.width(); outputFboHeight = ssaoFBO.height(); } }