mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-04 23:38:10 +07:00
Switched to arc bloom
This commit is contained in:
@ -1,382 +0,0 @@
|
|||||||
package mindustry.graphics;
|
|
||||||
|
|
||||||
import arc.Core;
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.graphics.Pixmap.Format;
|
|
||||||
import arc.graphics.VertexAttributes.Usage;
|
|
||||||
import arc.graphics.gl.FrameBuffer;
|
|
||||||
import arc.graphics.gl.Shader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bloomlib allow easy but efficient way to add bloom effect as post process
|
|
||||||
* effect
|
|
||||||
*
|
|
||||||
* @author kalle_h
|
|
||||||
*/
|
|
||||||
public class Bloom{
|
|
||||||
/**
|
|
||||||
* To use implement bloom more like a glow. Texture alpha channel can be
|
|
||||||
* used as mask which part are glowing and which are not. see more info at:
|
|
||||||
* http://www.gamasutra.com/view/feature/2107/realtime_glow.php
|
|
||||||
* <p>
|
|
||||||
* NOTE: need to be set before bloom instance is created. After that this
|
|
||||||
* does nothing.
|
|
||||||
*/
|
|
||||||
public static boolean useAlphaChannelAsMask = false;
|
|
||||||
|
|
||||||
/** how many blur pass */
|
|
||||||
public int blurPasses = 1;
|
|
||||||
|
|
||||||
private Shader tresholdShader;
|
|
||||||
private Shader bloomShader;
|
|
||||||
|
|
||||||
private Mesh fullScreenQuad;
|
|
||||||
|
|
||||||
private Texture pingPongTex1;
|
|
||||||
private Texture pingPongTex2;
|
|
||||||
private Texture original;
|
|
||||||
|
|
||||||
private FrameBuffer frameBuffer;
|
|
||||||
private FrameBuffer pingPongBuffer1;
|
|
||||||
private FrameBuffer pingPongBuffer2;
|
|
||||||
|
|
||||||
private Shader blurShader;
|
|
||||||
|
|
||||||
private float bloomIntensity;
|
|
||||||
private float originalIntensity;
|
|
||||||
private float threshold;
|
|
||||||
private int w;
|
|
||||||
private int h;
|
|
||||||
private boolean blending = false;
|
|
||||||
private boolean capturing = false;
|
|
||||||
private float r = 0f;
|
|
||||||
private float g = 0f;
|
|
||||||
private float b = 0f;
|
|
||||||
private float a = 1f;
|
|
||||||
private boolean disposeFBO = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IMPORTANT NOTE CALL THIS WHEN RESUMING
|
|
||||||
*/
|
|
||||||
public void resume(){
|
|
||||||
bloomShader.begin();
|
|
||||||
bloomShader.setUniformi("u_texture0", 0);
|
|
||||||
bloomShader.setUniformi("u_texture1", 1);
|
|
||||||
bloomShader.end();
|
|
||||||
|
|
||||||
setSize(w, h);
|
|
||||||
setThreshold(threshold);
|
|
||||||
setBloomIntesity(bloomIntensity);
|
|
||||||
setOriginalIntesity(originalIntensity);
|
|
||||||
|
|
||||||
original = frameBuffer.getTexture();
|
|
||||||
pingPongTex1 = pingPongBuffer1.getTexture();
|
|
||||||
pingPongTex2 = pingPongBuffer2.getTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize bloom class that capsulate original scene capturate,
|
|
||||||
* tresholding, gaussian blurring and blending. Default values: depth = true
|
|
||||||
* blending = false 32bits = true
|
|
||||||
*/
|
|
||||||
public Bloom(){
|
|
||||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, null, false, false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bloom(boolean useBlending){
|
|
||||||
initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, null, false, useBlending, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize bloom class that capsulate original scene capturate,
|
|
||||||
* tresholding, gaussian blurring and blending.
|
|
||||||
*
|
|
||||||
* @param FBO_W
|
|
||||||
* @param FBO_H how big fbo is used for bloom texture, smaller = more blur and
|
|
||||||
* lot faster but aliasing can be problem
|
|
||||||
* @param hasDepth do rendering need depth buffer
|
|
||||||
* @param useBlending does fbo need alpha channel and is blending enabled when final
|
|
||||||
* image is rendered. This allow to combine background graphics
|
|
||||||
* and only do blooming on certain objects param use32bitFBO does
|
|
||||||
* fbo use higher precision than 16bits.
|
|
||||||
*/
|
|
||||||
public Bloom(int FBO_W, int FBO_H, boolean hasDepth, boolean useBlending, boolean use32bitFBO){
|
|
||||||
initialize(FBO_W, FBO_H, null, hasDepth, useBlending, use32bitFBO);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EXPERT FUNCTIONALITY. no error checking. Use this only if you know what
|
|
||||||
* you are doing. Remember that bloom.capture() clear the screen so use
|
|
||||||
* continue instead if that is a problem.
|
|
||||||
* <p>
|
|
||||||
* Initialize bloom class that capsulate original scene capturate,
|
|
||||||
* tresholding, gaussian blurring and blending.
|
|
||||||
* <p>
|
|
||||||
* * @param sceneIsCapturedHere diposing is user responsibility.
|
|
||||||
*
|
|
||||||
* @param FBO_W
|
|
||||||
* @param FBO_H how big fbo is used for bloom texture, smaller = more blur and
|
|
||||||
* lot faster but aliasing can be problem
|
|
||||||
* @param useBlending does fbo need alpha channel and is blending enabled when final
|
|
||||||
* image is rendered. This allow to combine background graphics
|
|
||||||
* and only do blooming on certain objects param use32bitFBO does
|
|
||||||
* fbo use higher precision than 16bits.
|
|
||||||
*/
|
|
||||||
public Bloom(int FBO_W, int FBO_H, FrameBuffer sceneIsCapturedHere, boolean useBlending, boolean use32bitFBO){
|
|
||||||
initialize(FBO_W, FBO_H, sceneIsCapturedHere, false, useBlending, use32bitFBO);
|
|
||||||
disposeFBO = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialize(int FBO_W, int FBO_H, FrameBuffer fbo, boolean hasDepth, boolean useBlending, boolean use32bitFBO){
|
|
||||||
blending = useBlending;
|
|
||||||
Format format;
|
|
||||||
|
|
||||||
if(use32bitFBO){
|
|
||||||
if(useBlending){
|
|
||||||
format = Format.RGBA8888;
|
|
||||||
}else{
|
|
||||||
format = Format.RGB888;
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
if(useBlending){
|
|
||||||
format = Format.RGBA4444;
|
|
||||||
}else{
|
|
||||||
format = Format.RGB565;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(fbo == null){
|
|
||||||
frameBuffer = new FrameBuffer(format, Core.graphics.getWidth(), Core.graphics.getHeight(), hasDepth);
|
|
||||||
}else{
|
|
||||||
frameBuffer = fbo;
|
|
||||||
}
|
|
||||||
|
|
||||||
pingPongBuffer1 = new FrameBuffer(format, FBO_W, FBO_H, false);
|
|
||||||
|
|
||||||
pingPongBuffer2 = new FrameBuffer(format, FBO_W, FBO_H, false);
|
|
||||||
|
|
||||||
original = frameBuffer.getTexture();
|
|
||||||
pingPongTex1 = pingPongBuffer1.getTexture();
|
|
||||||
pingPongTex2 = pingPongBuffer2.getTexture();
|
|
||||||
|
|
||||||
fullScreenQuad = createFullScreenQuad();
|
|
||||||
final String alpha = useBlending ? "alpha_" : "";
|
|
||||||
|
|
||||||
bloomShader = createShader("screenspace", alpha + "bloom");
|
|
||||||
|
|
||||||
if(useAlphaChannelAsMask){
|
|
||||||
tresholdShader = createShader("screenspace", "maskedtreshold");
|
|
||||||
}else{
|
|
||||||
tresholdShader = createShader("screenspace", alpha + "threshold");
|
|
||||||
}
|
|
||||||
|
|
||||||
blurShader = createShader("blurspace", alpha + "gaussian");
|
|
||||||
|
|
||||||
setSize(FBO_W, FBO_H);
|
|
||||||
setBloomIntesity(2.5f);
|
|
||||||
setOriginalIntesity(0.8f);
|
|
||||||
setThreshold(0.5f);
|
|
||||||
|
|
||||||
bloomShader.begin();
|
|
||||||
bloomShader.setUniformi("u_texture0", 0);
|
|
||||||
bloomShader.setUniformi("u_texture1", 1);
|
|
||||||
bloomShader.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set clearing color for capturing buffer
|
|
||||||
*
|
|
||||||
* @param r
|
|
||||||
* @param g
|
|
||||||
* @param b
|
|
||||||
* @param a
|
|
||||||
*/
|
|
||||||
public void setClearColor(float r, float g, float b, float a){
|
|
||||||
this.r = r;
|
|
||||||
this.g = g;
|
|
||||||
this.b = b;
|
|
||||||
this.a = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this before rendering scene.
|
|
||||||
*/
|
|
||||||
public void capture(){
|
|
||||||
if(!capturing){
|
|
||||||
capturing = true;
|
|
||||||
frameBuffer.begin();
|
|
||||||
Gl.clearColor(r, g, b, a);
|
|
||||||
Gl.clear(Gl.colorBufferBit);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause capturing to fbo.
|
|
||||||
*/
|
|
||||||
public void capturePause(){
|
|
||||||
if(capturing){
|
|
||||||
capturing = false;
|
|
||||||
frameBuffer.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Start capturing again after pause, no clearing is done to framebuffer */
|
|
||||||
public void captureContinue(){
|
|
||||||
if(!capturing){
|
|
||||||
capturing = true;
|
|
||||||
frameBuffer.begin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this after scene. Renders the bloomed scene.
|
|
||||||
*/
|
|
||||||
public void render(){
|
|
||||||
if(capturing){
|
|
||||||
capturing = false;
|
|
||||||
frameBuffer.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
Gl.disable(Gl.blend);
|
|
||||||
Gl.disable(Gl.depthTest);
|
|
||||||
Gl.depthMask(false);
|
|
||||||
|
|
||||||
gaussianBlur();
|
|
||||||
|
|
||||||
if(blending){
|
|
||||||
Gl.enable(Gl.blend);
|
|
||||||
Gl.blendFunc(Gl.srcAlpha, Gl.oneMinusSrcAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
pingPongTex1.bind(1);
|
|
||||||
original.bind(0);
|
|
||||||
|
|
||||||
bloomShader.begin();
|
|
||||||
fullScreenQuad.render(bloomShader, Gl.triangleFan);
|
|
||||||
bloomShader.end();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void gaussianBlur(){
|
|
||||||
|
|
||||||
// cut bright areas of the picture and blit to smaller fbo
|
|
||||||
|
|
||||||
original.bind(0);
|
|
||||||
pingPongBuffer1.begin();
|
|
||||||
tresholdShader.begin();
|
|
||||||
fullScreenQuad.render(tresholdShader, Gl.triangleFan, 0, 4);
|
|
||||||
tresholdShader.end();
|
|
||||||
pingPongBuffer1.end();
|
|
||||||
|
|
||||||
for(int i = 0; i < blurPasses; i++){
|
|
||||||
|
|
||||||
pingPongTex1.bind(0);
|
|
||||||
|
|
||||||
// horizontal
|
|
||||||
pingPongBuffer2.begin();
|
|
||||||
blurShader.begin();
|
|
||||||
blurShader.setUniformf("dir", 1f, 0f);
|
|
||||||
fullScreenQuad.render(blurShader, Gl.triangleFan, 0, 4);
|
|
||||||
blurShader.end();
|
|
||||||
pingPongBuffer2.end();
|
|
||||||
|
|
||||||
pingPongTex2.bind(0);
|
|
||||||
// vertical
|
|
||||||
pingPongBuffer1.begin();
|
|
||||||
blurShader.begin();
|
|
||||||
blurShader.setUniformf("dir", 0f, 1f);
|
|
||||||
fullScreenQuad.render(blurShader, Gl.triangleFan, 0, 4);
|
|
||||||
blurShader.end();
|
|
||||||
pingPongBuffer1.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set intensity for bloom. higher mean more brightening for spots that are
|
|
||||||
* over threshold
|
|
||||||
*
|
|
||||||
* @param intensity multiplier for blurred texture in combining phase. must be
|
|
||||||
* positive.
|
|
||||||
*/
|
|
||||||
public void setBloomIntesity(float intensity){
|
|
||||||
bloomIntensity = intensity;
|
|
||||||
bloomShader.begin();
|
|
||||||
bloomShader.setUniformf("BloomIntensity", intensity);
|
|
||||||
bloomShader.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set intensity for original scene. under 1 mean darkening and over 1 means
|
|
||||||
* lightening
|
|
||||||
*
|
|
||||||
* @param intensity multiplier for captured texture in combining phase. must be
|
|
||||||
* positive.
|
|
||||||
*/
|
|
||||||
public void setOriginalIntesity(float intensity){
|
|
||||||
originalIntensity = intensity;
|
|
||||||
bloomShader.begin();
|
|
||||||
bloomShader.setUniformf("OriginalIntensity", intensity);
|
|
||||||
bloomShader.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treshold for bright parts. everything under threshold is clamped to 0
|
|
||||||
*
|
|
||||||
* @param threshold must be in range 0..1
|
|
||||||
*/
|
|
||||||
public void setThreshold(float threshold){
|
|
||||||
this.threshold = threshold;
|
|
||||||
tresholdShader.begin();
|
|
||||||
tresholdShader.setUniformf("threshold", threshold, 1f / (1 - threshold));
|
|
||||||
tresholdShader.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSize(int FBO_W, int FBO_H){
|
|
||||||
w = FBO_W;
|
|
||||||
h = FBO_H;
|
|
||||||
blurShader.begin();
|
|
||||||
blurShader.setUniformf("size", FBO_W, FBO_H);
|
|
||||||
blurShader.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this when application is exiting.
|
|
||||||
*/
|
|
||||||
public void dispose(){
|
|
||||||
try{
|
|
||||||
if(disposeFBO) frameBuffer.dispose();
|
|
||||||
|
|
||||||
fullScreenQuad.dispose();
|
|
||||||
|
|
||||||
pingPongBuffer1.dispose();
|
|
||||||
pingPongBuffer2.dispose();
|
|
||||||
|
|
||||||
blurShader.dispose();
|
|
||||||
bloomShader.dispose();
|
|
||||||
tresholdShader.dispose();
|
|
||||||
}catch(Throwable ignored){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Mesh createFullScreenQuad(){
|
|
||||||
float[] verts = {-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1};
|
|
||||||
Mesh tmpMesh = new Mesh(true, 4, 0,
|
|
||||||
new VertexAttribute(Usage.position, 2, "a_position"),
|
|
||||||
new VertexAttribute(Usage.textureCoordinates, 2, "a_texCoord0")
|
|
||||||
);
|
|
||||||
|
|
||||||
tmpMesh.setVertices(verts);
|
|
||||||
return tmpMesh;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Shader createShader(String vertexName, String fragmentName){
|
|
||||||
String vertexShader = Core.files.internal("bloomshaders/" + vertexName + ".vertex.glsl").readString();
|
|
||||||
String fragmentShader = Core.files.internal("bloomshaders/" + fragmentName + ".fragment.glsl").readString();
|
|
||||||
return new Shader(vertexShader, fragmentShader);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=08a81cd6c5cb0348667dce7ada2e6a47d31692f8
|
archash=8c7b7cbef40a0cc546cace77364c88f3f6ee5ed7
|
||||||
|
Reference in New Issue
Block a user