/*
* 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());
}
}