Skip to content

Commit

Permalink
feat: experimental post processing pipeline with FXAA
Browse files Browse the repository at this point in the history
  • Loading branch information
vinceh121 committed Dec 26, 2023
1 parent 9f15851 commit ac1476c
Show file tree
Hide file tree
Showing 13 changed files with 1,543 additions and 6 deletions.
1,178 changes: 1,178 additions & 0 deletions android/assets/shaders/fxaa.glsl

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions core/src/me/vinceh121/wanderer/GraphicsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import me.vinceh121.wanderer.glx.SkyboxRenderer;
import me.vinceh121.wanderer.glx.WandererParticleShader;
import me.vinceh121.wanderer.glx.WandererShader;
import me.vinceh121.wanderer.glx.post.PostProcessManager;

public class GraphicsManager extends ApplicationAdapter {
private ScreenViewport viewportUi;
Expand All @@ -44,6 +45,7 @@ public class GraphicsManager extends ApplicationAdapter {
private Stage stage;
private ParticleSystem particleSystem;
private BillboardParticleBatch particleBatch;
private PostProcessManager postProcessManager;

private SkyboxRenderer skybox;

Expand Down Expand Up @@ -97,6 +99,8 @@ protected Shader getShader(final Renderable renderable) {
this.env.set(this.skybox.getAmbiantLight());
this.env.add(this.skybox.getSunLight());
this.env.shadowMap = this.skybox.getSunLight();

this.postProcessManager = new PostProcessManager(this);
}

public void apply() {
Expand All @@ -113,6 +117,12 @@ public void begin() {
this.modelBatch.begin(this.cam);
}

public void beginPostProcess() {
if (this.isPostProcessing()) {
this.postProcessManager.begin();
}
}

public void renderParticles(final float delta) {
this.particleSystem.update(Gdx.graphics.getDeltaTime());
this.particleSystem.begin();
Expand All @@ -125,6 +135,12 @@ public void end() {
this.modelBatch.end();
}

public void endPostProcess() {
if (this.isPostProcessing()) {
this.postProcessManager.end();
}
}

public void renderUI() {
this.modelBatch.begin(this.viewportUi.getCamera()); // allows the rendering of 3D objects in the UI viewport
this.stage.act(Gdx.graphics.getDeltaTime());
Expand Down Expand Up @@ -166,6 +182,10 @@ public void removeParticle(final ParticleEmitter effect) {
this.particleSystem.remove(effect.getDelegate());
}

public boolean isPostProcessing() {
return false; // FIXME post pro and FXAA
}

/**
* @return the cam
*/
Expand Down
14 changes: 10 additions & 4 deletions core/src/me/vinceh121/wanderer/Wanderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ public void render() {
this.processCameraShake(delta);

this.graphicsManager.clear();
this.graphicsManager.renderSkybox(this.timeOfDay);

final Vector3 sunCenter;

Expand All @@ -370,6 +369,9 @@ public void render() {
this.graphicsManager.getShadowBatch().end();
this.graphicsManager.getSkybox().getSunLight().end();

this.graphicsManager.beginPostProcess();
this.graphicsManager.renderSkybox(this.timeOfDay);

this.graphicsManager.begin();
for (int i = 0; i < this.entities.size; i++) {
final AbstractEntity entity = this.entities.get(i);
Expand All @@ -387,6 +389,8 @@ public void render() {
this.physicsManager.getDebugDrawer().end();
}

this.graphicsManager.endPostProcess();

this.scriptManager.update();

this.graphicsManager.renderUI();
Expand Down Expand Up @@ -419,8 +423,9 @@ protected void flushEntityQueue() {

protected void controlledDeathTest() {
if (this.controlledEntity instanceof ILivingEntity && ((ILivingEntity) this.controlledEntity).isDead()) {
final Optional<CharacterW> optChar =
this.findEntitiesByClass(CharacterW.class).filter(c -> c.getClan() == this.getPlayerClan()).findFirst();
final Optional<CharacterW> optChar = this.findEntitiesByClass(CharacterW.class)
.filter(c -> c.getClan() == this.getPlayerClan())
.findFirst();

if (optChar.isPresent()) {
this.controlEntity(optChar.get());
Expand Down Expand Up @@ -450,7 +455,8 @@ private void processCameraShake(final float delta) {

final PerspectiveCamera cam = this.graphicsManager.getCamera();

final EllipsePath path = new EllipsePath(0f, 0f, 0.5f * this.cameraShakeIntensity, 0.2f * this.cameraShakeIntensity);
final EllipsePath path =
new EllipsePath(0f, 0f, 0.5f * this.cameraShakeIntensity, 0.2f * this.cameraShakeIntensity);
path.y = path.height / 2;
final Vector2 shakeVec2 = path.valueAt(new Vector2(), this.cameraShakeTime / this.cameraShakeRevolutionTime);
final Vector3 shakeVec3 = new Vector3(shakeVec2, 0);
Expand Down
19 changes: 19 additions & 0 deletions core/src/me/vinceh121/wanderer/glx/post/FxaaPostProcessEffect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.vinceh121.wanderer.glx.post;

import com.badlogic.gdx.graphics.Texture;

import me.vinceh121.wanderer.GraphicsManager;
import me.vinceh121.wanderer.platform.glx.IFXAAShader;

public class FxaaPostProcessEffect implements IPostProcessEffect {
private final IFXAAShader shader;

public FxaaPostProcessEffect(IFXAAShader shader) {
this.shader = shader;
}

@Override
public Texture process(GraphicsManager glx, Texture tex) {
return this.shader.run(glx.getModelBatch().getRenderContext(), tex);
}
}
13 changes: 13 additions & 0 deletions core/src/me/vinceh121/wanderer/glx/post/IPostProcessEffect.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package me.vinceh121.wanderer.glx.post;

import com.badlogic.gdx.graphics.Texture;

import me.vinceh121.wanderer.GraphicsManager;

public interface IPostProcessEffect {
Texture process(GraphicsManager glx, Texture tex);

default boolean isInPlace() {
return true;
}
}
77 changes: 77 additions & 0 deletions core/src/me/vinceh121/wanderer/glx/post/PostProcessManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package me.vinceh121.wanderer.glx.post;

import java.util.LinkedList;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;

import me.vinceh121.wanderer.GraphicsManager;
import me.vinceh121.wanderer.platform.glx.IComputeShaderProvider;

public class PostProcessManager {
private final GraphicsManager glx;
private final LinkedList<IPostProcessEffect> effects = new LinkedList<>();
private FrameBuffer fbo;

public PostProcessManager(GraphicsManager glx) {
this.glx = glx;

this.effects.add(new FxaaPostProcessEffect(
IComputeShaderProvider.get().buildFxaa(Gdx.files.internal("shaders/fxaa.glsl"))));
}

public void addEffectFirst(IPostProcessEffect effect) {
this.effects.addFirst(effect);
}

public void addEffectLast(IPostProcessEffect effect) {
this.effects.addLast(effect);
}

public void begin() {
assert this.fbo == null;

this.fbo = new FrameBuffer(Format.RGB888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
this.fbo.begin();
}

public Texture end() {
this.fbo.end();
Texture tex = this.fbo.getColorBufferTexture();

for (final IPostProcessEffect fx : this.effects) {
final Texture newTex = fx.process(this.glx, tex);

if (!fx.isInPlace()) {
tex.dispose();
}

tex = newTex;
}

Gdx.gl30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, this.fbo.getFramebufferHandle());
Gdx.gl30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0);
Gdx.gl30.glBlitFramebuffer(0,
0,
tex.getWidth(),
tex.getHeight(),
0,
0,
tex.getWidth(),
tex.getHeight(),
GL30.GL_COLOR_BUFFER_BIT,
GL30.GL_NEAREST);

this.fbo.dispose();
this.fbo = null;

return null;
}

public LinkedList<IPostProcessEffect> getEffects() {
return effects;
}
}
20 changes: 20 additions & 0 deletions core/src/me/vinceh121/wanderer/platform/glx/IComputeShader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package me.vinceh121.wanderer.platform.glx;

import com.badlogic.gdx.utils.Disposable;

public interface IComputeShader extends Disposable {
void bind();

void dispatch(int x, int y, int z);

int getUniformLocation(String name);

void setUniform1i(int location, int value);

void setUniform2f(int location, float v0, float v1);

int getProgramHandle();

int getShaderHandle();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.vinceh121.wanderer.platform.glx;

import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;

public interface IComputeShaderProvider {
public static IComputeShaderProvider get() {
try {
final Class<?> cls;

if (Gdx.app.getType() == ApplicationType.Desktop) {
cls = Class.forName("me.vinceh121.wanderer.desktop.glx.LWJGLComputeShaderProvider");
} else {
throw new UnsupportedOperationException(
"Platform not supported for compute shader provider: " + Gdx.app.getType());
}

return (IComputeShaderProvider) cls.getConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

IComputeShader build(FileHandle source);

IComputeShader build(String source);

IFXAAShader buildFxaa(FileHandle source);
}
16 changes: 16 additions & 0 deletions core/src/me/vinceh121/wanderer/platform/glx/IFXAAShader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package me.vinceh121.wanderer.platform.glx;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g3d.utils.RenderContext;

public interface IFXAAShader extends IComputeShader {

void setInputImage(RenderContext ctx, int texUnit);

void setOutputImage(RenderContext ctx, int texUnit);

void setInvResolution(float width, float height);

Texture run(RenderContext ctx, Texture tex);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.badlogic.gdx.Graphics.DisplayMode;
import com.badlogic.gdx.Graphics.Monitor;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration.GLEmulation;
import com.electronwill.nightconfig.core.CommentedConfig;

import me.vinceh121.wanderer.ApplicationMultiplexer;
Expand Down Expand Up @@ -50,7 +51,10 @@ private static void main0(final String[] args) {

final Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
Configuration.DEBUG.set(debug);

config.setOpenGLEmulation(GLEmulation.GL30, 4, 3);
config.setTitle("Wanderer");

if (debug) {
config.enableGLDebugOutput(debug, System.err);
}
Expand All @@ -76,8 +80,9 @@ private static Monitor getMonitor(final String name) { // FIXME duplicate code w
.orElse(null);
}

private static DisplayMode getDisplayMode(final Monitor monitor, final String displayMode) { // FIXME duplicate code with
// GraphicsUtilities
private static DisplayMode getDisplayMode(final Monitor monitor, final String displayMode) { // FIXME duplicate code
// with
// GraphicsUtilities
return Arrays.stream(Lwjgl3ApplicationConfiguration.getDisplayModes(monitor))
.filter(d -> displayMode.equals(d.toString()))
.findFirst()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package me.vinceh121.wanderer.desktop.glx;

import org.lwjgl.opengl.GL43;

import me.vinceh121.wanderer.platform.glx.IComputeShader;

public class LWJGLComputeShader implements IComputeShader {
private final int shaderHandle, programHandle;

public LWJGLComputeShader(int shaderHandle, int programHandle) {
this.shaderHandle = shaderHandle;
this.programHandle = programHandle;
}

@Override
public void bind() {
GL43.glUseProgram(this.programHandle);
}

@Override
public void dispatch(int x, int y, int z) {
GL43.glDispatchCompute(x, y, z);
}

@Override
public int getUniformLocation(String name) {
return GL43.glGetUniformLocation(this.programHandle, name);
}

@Override
public void setUniform1i(int location, int value) {
GL43.glUniform1i(location, value);
}

@Override
public void setUniform2f(int location, float v0, float v1) {
GL43.glUniform2f(location, v0, v1);
}

@Override
public int getShaderHandle() {
return shaderHandle;
}

@Override
public int getProgramHandle() {
return programHandle;
}

@Override
public void dispose() {
GL43.glDeleteProgram(this.programHandle);
GL43.glDeleteShader(this.shaderHandle);
}
}
Loading

0 comments on commit ac1476c

Please sign in to comment.