
com.gempukku.libgdx.graph.pipeline.producer.postprocessor.BloomPipelineNodeProducer Maven / Gradle / Ivy
package com.gempukku.libgdx.graph.pipeline.producer.postprocessor;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.JsonValue;
import com.badlogic.gdx.utils.ObjectMap;
import com.gempukku.libgdx.graph.pipeline.RenderPipeline;
import com.gempukku.libgdx.graph.pipeline.RenderPipelineBuffer;
import com.gempukku.libgdx.graph.pipeline.config.postprocessor.BloomPipelineNodeConfiguration;
import com.gempukku.libgdx.graph.pipeline.producer.BooleanFieldOutput;
import com.gempukku.libgdx.graph.pipeline.producer.FloatFieldOutput;
import com.gempukku.libgdx.graph.pipeline.producer.FullScreenRender;
import com.gempukku.libgdx.graph.pipeline.producer.PipelineRenderingContext;
import com.gempukku.libgdx.graph.pipeline.producer.node.OncePerFrameJobPipelineNode;
import com.gempukku.libgdx.graph.pipeline.producer.node.PipelineNode;
import com.gempukku.libgdx.graph.pipeline.producer.node.PipelineNodeProducerImpl;
import com.gempukku.libgdx.graph.pipeline.producer.node.PipelineRequirements;
public class BloomPipelineNodeProducer extends PipelineNodeProducerImpl {
public BloomPipelineNodeProducer() {
super(new BloomPipelineNodeConfiguration());
}
@Override
public PipelineNode createNodeForSingleInputs(JsonValue data, ObjectMap> inputFields) {
final ShaderProgram brightnessFilterPassProgram = new ShaderProgram(
Gdx.files.classpath("shader/viewToScreenCoords.vert"),
Gdx.files.classpath("shader/brightnessFilter.frag"));
if (!brightnessFilterPassProgram.isCompiled())
throw new IllegalArgumentException("Error compiling shader: " + brightnessFilterPassProgram.getLog());
final ShaderProgram gaussianBlurPassProgram = new ShaderProgram(
Gdx.files.classpath("shader/viewToScreenCoords.vert"),
Gdx.files.classpath("shader/gaussianBlur.frag"));
if (!gaussianBlurPassProgram.isCompiled())
throw new IllegalArgumentException("Error compiling shader: " + gaussianBlurPassProgram.getLog());
final ShaderProgram bloomSumProgram = new ShaderProgram(
Gdx.files.classpath("shader/viewToScreenCoords.vert"),
Gdx.files.classpath("shader/bloomSum.frag"));
if (!bloomSumProgram.isCompiled())
throw new IllegalArgumentException("Error compiling shader: " + bloomSumProgram.getLog());
PipelineNode.FieldOutput processorEnabled = (PipelineNode.FieldOutput) inputFields.get("enabled");
PipelineNode.FieldOutput bloomRadius = (PipelineNode.FieldOutput) inputFields.get("bloomRadius");
PipelineNode.FieldOutput minimalBrightness = (PipelineNode.FieldOutput) inputFields.get("minimalBrightness");
PipelineNode.FieldOutput bloomStrength = (PipelineNode.FieldOutput) inputFields.get("bloomStrength");
if (processorEnabled == null)
processorEnabled = new BooleanFieldOutput(true);
if (bloomRadius == null)
bloomRadius = new FloatFieldOutput(1f);
if (minimalBrightness == null)
minimalBrightness = new FloatFieldOutput(0.7f);
if (bloomStrength == null)
bloomStrength = new FloatFieldOutput(0f);
final PipelineNode.FieldOutput renderPipelineInput = (PipelineNode.FieldOutput) inputFields.get("input");
final PipelineNode.FieldOutput finalProcessorEnabled = processorEnabled;
final PipelineNode.FieldOutput finalBloomStrength = bloomStrength;
final PipelineNode.FieldOutput finalBloomRadius = bloomRadius;
final PipelineNode.FieldOutput finalMinimalBrightness = minimalBrightness;
return new OncePerFrameJobPipelineNode(configuration, inputFields) {
@Override
protected void executeJob(PipelineRenderingContext pipelineRenderingContext, PipelineRequirements pipelineRequirements, ObjectMap outputValues) {
RenderPipeline renderPipeline = renderPipelineInput.getValue(pipelineRenderingContext, pipelineRequirements);
boolean enabled = finalProcessorEnabled.getValue(pipelineRenderingContext, null);
float bloomStrengthValue = finalBloomStrength.getValue(pipelineRenderingContext, null);
int bloomRadiusValue = MathUtils.round(finalBloomRadius.getValue(pipelineRenderingContext, null));
if (enabled && bloomStrengthValue > 0 && bloomRadiusValue > 0) {
float minimalBrightnessValue = finalMinimalBrightness.getValue(pipelineRenderingContext, null);
RenderPipelineBuffer originalBuffer = renderPipeline.getDefaultBuffer();
RenderContext renderContext = pipelineRenderingContext.getRenderContext();
renderContext.setDepthTest(0);
renderContext.setDepthMask(false);
renderContext.setBlending(false, 0, 0);
renderContext.setCullFace(GL20.GL_BACK);
RenderPipelineBuffer brightnessFilterBuffer = runBrightnessPass(minimalBrightnessValue, renderPipeline, originalBuffer, brightnessFilterPassProgram, pipelineRenderingContext.getRenderContext(), pipelineRenderingContext.getFullScreenRender());
RenderPipelineBuffer gaussianBlur = applyGaussianBlur(bloomRadiusValue, renderPipeline,
brightnessFilterBuffer, gaussianBlurPassProgram,
pipelineRenderingContext.getRenderContext(), pipelineRenderingContext.getFullScreenRender());
renderPipeline.returnFrameBuffer(brightnessFilterBuffer);
RenderPipelineBuffer result = applyTheBloom(bloomStrengthValue, renderPipeline, originalBuffer, gaussianBlur, bloomSumProgram, pipelineRenderingContext.getRenderContext(), pipelineRenderingContext.getFullScreenRender());
renderPipeline.returnFrameBuffer(gaussianBlur);
renderPipeline.swapColorTextures(originalBuffer, result);
renderPipeline.returnFrameBuffer(result);
}
OutputValue output = outputValues.get("output");
if (output != null)
output.setValue(renderPipeline);
}
@Override
public void dispose() {
bloomSumProgram.dispose();
gaussianBlurPassProgram.dispose();
brightnessFilterPassProgram.dispose();
}
};
}
private RenderPipelineBuffer applyTheBloom(float bloomStrength, RenderPipeline renderPipeline, RenderPipelineBuffer sourceBuffer, RenderPipelineBuffer gaussianBlur,
ShaderProgram bloomSumProgram, RenderContext renderContext, FullScreenRender fullScreenRender) {
RenderPipelineBuffer result = renderPipeline.getNewFrameBuffer(sourceBuffer);
result.beginColor();
bloomSumProgram.bind();
bloomSumProgram.setUniformi("u_brightnessTexture", renderContext.textureBinder.bind(gaussianBlur.getColorBufferTexture()));
bloomSumProgram.setUniformi("u_sourceTexture", renderContext.textureBinder.bind(sourceBuffer.getColorBufferTexture()));
bloomSumProgram.setUniformf("u_bloomStrength", bloomStrength);
fullScreenRender.renderFullScreen(bloomSumProgram);
result.endColor();
return result;
}
private RenderPipelineBuffer applyGaussianBlur(int bloomRadius, RenderPipeline renderPipeline, RenderPipelineBuffer sourceBuffer,
ShaderProgram blurProgram, RenderContext renderContext, FullScreenRender fullScreenRender) {
float[] kernel = GaussianBlurKernel.getKernel(MathUtils.round(bloomRadius));
blurProgram.bind();
blurProgram.setUniformi("u_blurRadius", bloomRadius);
blurProgram.setUniformf("u_pixelSize", 1f / sourceBuffer.getWidth(), 1f / sourceBuffer.getHeight());
blurProgram.setUniform1fv("u_kernel", kernel, 0, kernel.length);
blurProgram.setUniformi("u_vertical", 1);
RenderPipelineBuffer tempBuffer = executeBlur(blurProgram, renderPipeline, sourceBuffer, renderContext, fullScreenRender);
blurProgram.setUniformi("u_vertical", 0);
RenderPipelineBuffer blurredBuffer = executeBlur(blurProgram, renderPipeline, tempBuffer, renderContext, fullScreenRender);
renderPipeline.returnFrameBuffer(tempBuffer);
return blurredBuffer;
}
private RenderPipelineBuffer executeBlur(ShaderProgram blurProgram, RenderPipeline renderPipeline, RenderPipelineBuffer sourceBuffer,
RenderContext renderContext, FullScreenRender fullScreenRender) {
RenderPipelineBuffer resultBuffer = renderPipeline.getNewFrameBuffer(sourceBuffer);
resultBuffer.beginColor();
blurProgram.setUniformi("u_sourceTexture", renderContext.textureBinder.bind(sourceBuffer.getColorBufferTexture()));
fullScreenRender.renderFullScreen(blurProgram);
resultBuffer.endColor();
return resultBuffer;
}
private RenderPipelineBuffer runBrightnessPass(float minimalBrightnessValue, RenderPipeline renderPipeline, RenderPipelineBuffer currentBuffer, ShaderProgram brightnessFilterPassProgram,
RenderContext renderContext, FullScreenRender fullScreenRender) {
RenderPipelineBuffer brightnessFilterBuffer = renderPipeline.getNewFrameBuffer(currentBuffer);
brightnessFilterBuffer.beginColor();
brightnessFilterPassProgram.bind();
brightnessFilterPassProgram.setUniformi("u_sourceTexture", renderContext.textureBinder.bind(currentBuffer.getColorBufferTexture()));
brightnessFilterPassProgram.setUniformf("u_minimalBrightness", minimalBrightnessValue);
fullScreenRender.renderFullScreen(brightnessFilterPassProgram);
brightnessFilterBuffer.endColor();
return brightnessFilterBuffer;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy