/* * 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.monitoring.PerformanceMonitor; 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.BaseFBOsManager; import org.terasology.rendering.opengl.FBO; import org.terasology.rendering.opengl.FBOConfig; import org.terasology.rendering.opengl.FBOManagerSubscriber; import static org.terasology.rendering.opengl.OpenGLUtils.renderFullscreenQuad; /** * A BlurNode takes the content of the color buffer attached to the input FBO and generates * a blurred version of it in the color buffer attached to the output FBO. */ public class BlurNode extends ConditionDependentNode implements FBOManagerSubscriber { protected float blurRadius; private Material blurMaterial; private String performanceMonitorLabel; private BaseFBOsManager fboManager; private FBOConfig inputFBOConfig; private FBOConfig outputFBOConfig; private FBO inputFBO; private FBO outputFBO; /** * Throws a RuntimeException if invoked. Use initialise(...) instead. */ @Override public void initialise() { throw new RuntimeException("Please do not use initialise(). For this class use initialise(...) instead."); } /** * Initializes the BlurNode instance. * * @param inputConfig an FBOConfig instance describing the input FBO, to be retrieved from the FBO manager * @param outputConfig an FBOConfig instance describing the output FBO, to be retrieved from the FBO manager * @param anfboManager the FBO manager from which to retrieve -both- FBOs. * @param aRadius the blur radius: higher values cause higher blur. The shader's default is 16.0f. * @param aLabel a String to label the instance's entry in output generated by the PerformanceMonitor */ public void initialise(FBOConfig inputConfig, FBOConfig outputConfig, BaseFBOsManager anfboManager, float aRadius, String aLabel) { this.inputFBOConfig = inputConfig; this.outputFBOConfig = outputConfig; this.fboManager = anfboManager; requiresFBO(inputFBOConfig, fboManager); requiresFBO(outputFBOConfig, fboManager); addDesiredStateChange(new BindFBO(outputFBOConfig.getName(), fboManager)); addDesiredStateChange(new SetViewportToSizeOf(outputFBOConfig.getName(), fboManager)); inputFBO = fboManager.get(inputFBOConfig.getName()); outputFBO = fboManager.get(outputFBOConfig.getName()); fboManager.subscribe(this); setupConditions(); addDesiredStateChange(new EnableMaterial("engine:prog.blur")); this.blurMaterial = getMaterial(new ResourceUrn("engine:prog.blur")); this.blurRadius = aRadius; this.performanceMonitorLabel = aLabel; } /** * This method does nothing. It is meant to be overridden by inheriting classes if needed. * On the other hand, there might be situations in which the blur should always occur, * in which case this BlurNode class is good as it is. */ protected void setupConditions() { } /** * Performs the blur. */ @Override public void process() { PerformanceMonitor.startActivity("rendering/" + performanceMonitorLabel); // TODO: these shader-related operations should go in their own StateChange implementations blurMaterial.setFloat("radius", blurRadius, true); blurMaterial.setFloat2("texelSize", 1.0f / outputFBO.width(), 1.0f / outputFBO.height(), true); // TODO: binding the color buffer of an FBO should also be done in its own StateChange implementation inputFBO.bindTexture(); renderFullscreenQuad(); PerformanceMonitor.endActivity(); } @Override public void update() { inputFBO = fboManager.get(inputFBOConfig.getName()); outputFBO = fboManager.get(outputFBOConfig.getName()); } }