Moved SSAO to the new AbstractShader thing

This commit is contained in:
coolGi
2023-06-24 23:17:58 +09:30
parent 1dad6fd83f
commit d04b4c0d55
8 changed files with 262 additions and 224 deletions
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer;
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAORenderer;
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -244,7 +244,7 @@ public class LodRenderer
bufferHandler.renderOpaque(this);
if (Config.Client.Advanced.Graphics.Quality.ssao.get()) {
SSAORenderer.INSTANCE.render(partialTicks);
SSAOShader.INSTANCE.render(partialTicks);
}
//======================//
@@ -0,0 +1,152 @@
package com.seibel.distanthorizons.core.render.renderer.shaders;
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public abstract class AbstractShaderRenderer {
protected static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final float[] box_vertices = {
-1, -1,
1, -1,
1, 1,
-1, -1,
1, 1,
-1, 1,
};
protected final ShaderProgram shader;
protected final ShaderProgram applyShader;
protected GLVertexBuffer boxBuffer;
protected VertexAttribute va;
boolean init = false;
private int width = -1;
private int height = -1;
private int framebuffer = -1;
private int shaderTexture = -1;
protected AbstractShaderRenderer(ShaderProgram shader) {
this(shader, null);
}
protected AbstractShaderRenderer(ShaderProgram shader, ShaderProgram applyShader) {
this.shader = shader;
this.applyShader = applyShader;
}
private void init() {
if (init) return;
init = true;
va = VertexAttribute.create();
va.bind();
// Pos
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
va.completeAndCheck(Float.BYTES * 2);
// Some shader stuff needs to be set a bit later than
this.postInit();
// Framebuffer
createBuffer();
}
/** Overwrite this to apply uniforms to the shader */
void setShaderUniforms(float partialTicks) {};
/** Overwrite this to apply uniforms to the apply shader */
void setApplyShaderUniforms(float partialTicks) {};
/** Overwrite if you need to run something on runtime */
void postInit() {};
public void render(float partialTicks) {
GLState state = new GLState();
init();
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
if (this.width != width || this.height != height) {
this.width = width;
this.height = height;
createFramebuffer(width, height);
}
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer);
GL32.glViewport(0, 0, width, height);
GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDisable(GL32.GL_BLEND);
GL32.glDisable(GL32.GL_SCISSOR_TEST);
shader.bind();
this.setShaderUniforms(partialTicks);
va.bind();
va.bindBufferToAllBindingPoint(boxBuffer.getId());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
if (applyShader != null) {
applyShader.bind();
this.setApplyShaderUniforms(partialTicks);
}
GL32.glEnable(GL11.GL_BLEND);
GL32.glBlendFunc(GL32.GL_ZERO, GL32.GL_SRC_ALPHA);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
state.restore();
}
private void createFramebuffer(int width, int height) {
if (framebuffer != -1) {
GL32.glDeleteFramebuffers(framebuffer);
framebuffer = -1;
}
if (shaderTexture != -1) {
GL32.glDeleteTextures(shaderTexture);
shaderTexture = -1;
}
framebuffer = GL32.glGenFramebuffers();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, framebuffer);
shaderTexture = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, shaderTexture);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, shaderTexture, 0);
}
private void createBuffer() {
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(box_vertices);
buffer.rewind();
boxBuffer = new GLVertexBuffer(false);
boxBuffer.bind();
boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
}
}
@@ -1,194 +0,0 @@
package com.seibel.distanthorizons.core.render.renderer.shaders;
import com.seibel.distanthorizons.api.enums.config.EGpuUploadMethod;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class SSAORenderer {
public static SSAORenderer INSTANCE = new SSAORenderer();
public SSAORenderer() {
}
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
private static final float[] box_vertices = {
-1, -1,
1, -1,
1, 1,
-1, -1,
1, 1,
-1, 1,
};
ShaderProgram ssaoShader;
ShaderProgram applyShader;
GLVertexBuffer boxBuffer;
VertexAttribute va;
boolean init = false;
private static final int MAX_KERNEL_SIZE = 32;
private float[] kernel = new float[MAX_KERNEL_SIZE * 3];
public void init() {
if (init) return;
init = true;
va = VertexAttribute.create();
va.bind();
// Pos
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
va.completeAndCheck(Float.BYTES * 2);
ssaoShader = new ShaderProgram("shaders/ssao/ao-vert.vert", "shaders/ssao/ao-frag.frag",
"fragColor", new String[]{"vPosition"});
applyShader = new ShaderProgram("shaders/ssao/ao-vert.vert", "shaders/ssao/apply-frag.frag",
"fragColor", new String[]{"vPosition"});
// Generate kernel
kernel = genKernel();
// Framebuffer
createBuffer();
}
private int width = -1;
private int height = -1;
private int ssaoFramebuffer = -1;
private int ssaoTexture = -1;
private void createFramebuffer(int width, int height) {
if (ssaoFramebuffer != -1) {
GL32.glDeleteFramebuffers(ssaoFramebuffer);
ssaoFramebuffer = -1;
}
if (ssaoTexture != -1) {
GL32.glDeleteTextures(ssaoTexture);
ssaoTexture = -1;
}
ssaoFramebuffer = GL32.glGenFramebuffers();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer);
ssaoTexture = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, ssaoTexture, 0);
}
private void createBuffer() {
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(box_vertices);
buffer.rewind();
boxBuffer = new GLVertexBuffer(false);
boxBuffer.bind();
boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
}
private static float[] genKernel() {
float[] kernel = new float[MAX_KERNEL_SIZE * 3];
for (int i = 0; i < MAX_KERNEL_SIZE; i++) {
float sampleX = (float) (Math.random() * 2.0 - 1.0);
float sampleY = (float) (Math.random() * 2.0 - 1.0);
float sampleZ = (float) Math.random();
// Normalize
float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2));
sampleX /= magnitude;
sampleY /= magnitude;
sampleZ /= magnitude;
float scale = i / (float) MAX_KERNEL_SIZE;
float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9));
sampleX *= interpolatedScale;
sampleY *= interpolatedScale;
sampleZ *= interpolatedScale;
kernel[i * 3] = sampleX;
kernel[i * 3 + 1] = sampleY;
kernel[i * 3 + 2] = sampleZ;
}
return kernel;
}
public void render(float partialTicks) {
GLState state = new GLState();
init();
//GL32.glDepthMask(false);
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
if (this.width != width || this.height != height) {
this.width = width;
this.height = height;
createFramebuffer(width, height);
}
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer);
GL32.glViewport(0, 0, width, height);
GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDisable(GL32.GL_BLEND);
GL32.glDisable(GL32.GL_SCISSOR_TEST);
Mat4f perspective = Mat4f.perspective(
(float) MC_RENDER.getFov(partialTicks),
MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(),
RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks),
(float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)));
ssaoShader.bind();
ssaoShader.setUniform(ssaoShader.getUniformLocation("gProj"), perspective);
ssaoShader.setUniform(ssaoShader.getUniformLocation("gSampleRad"), 3.0f);
ssaoShader.setUniform(ssaoShader.getUniformLocation("gFactor"), 0.8f);
ssaoShader.setUniform(ssaoShader.getUniformLocation("gPower"), 1.0f);
va.bind();
va.bindBufferToAllBindingPoint(boxBuffer.getId());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
GL32.glUniform3fv(ssaoShader.getUniformLocation("gKernel"), kernel);
GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
applyShader.bind();
GL32.glEnable(GL11.GL_BLEND);
GL32.glBlendFunc(GL32.GL_ZERO, GL32.GL_SRC_ALPHA);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
//GL32.glBindFramebuffer(GL32.GL_READ_FRAMEBUFFER, ssaoFramebuffer);
//GL32.glBindFramebuffer(GL32.GL_DRAW_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
//GL32.glBlitFramebuffer(
// 0, 0, width, height,
// 0, 0, width, height,
// GL11.GL_COLOR_BUFFER_BIT,
// GL11.GL_NEAREST
//);
state.restore();
}
}
@@ -0,0 +1,75 @@
package com.seibel.distanthorizons.core.render.renderer.shaders;
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderUtil;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
import org.lwjgl.opengl.GL32;
public class SSAOShader extends AbstractShaderRenderer {
public static SSAOShader INSTANCE = new SSAOShader();
private static final int MAX_KERNEL_SIZE = 32;
private float[] kernel = new float[MAX_KERNEL_SIZE * 3];
public SSAOShader() {
super(
new ShaderProgram("shaders/ssao/ao.vert", "shaders/ssao/ao.frag",
"fragColor", new String[]{"vPos"}),
new ShaderProgram("shaders/ssao/ao.vert", "shaders/ssao/apply-frag.frag",
"fragColor", new String[]{"vPos"})
);
}
@Override
void postInit() {
// Generate kernel
kernel = genKernel();
}
@Override
void setShaderUniforms(float partialTicks) {
Mat4f perspective = Mat4f.perspective(
(float) MC_RENDER.getFov(partialTicks),
MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(),
RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks),
(float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)));
this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective);
this.shader.setUniform(this.shader.getUniformLocation("gSampleRad"), 3.0f);
this.shader.setUniform(this.shader.getUniformLocation("gFactor"), 0.8f);
this.shader.setUniform(this.shader.getUniformLocation("gPower"), 1.0f);
GL32.glUniform3fv(this.shader.getUniformLocation("gKernel"), kernel);
GL32.glUniform1i(this.shader.getUniformLocation("gDepthMap"), 0);
}
private static float[] genKernel() {
float[] kernel = new float[MAX_KERNEL_SIZE * 3];
for (int i = 0; i < MAX_KERNEL_SIZE; i++) {
float sampleX = (float) (Math.random() * 2.0 - 1.0);
float sampleY = (float) (Math.random() * 2.0 - 1.0);
float sampleZ = (float) Math.random();
// Normalize
float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2));
sampleX /= magnitude;
sampleY /= magnitude;
sampleZ /= magnitude;
float scale = i / (float) MAX_KERNEL_SIZE;
float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9));
sampleX *= interpolatedScale;
sampleY *= interpolatedScale;
sampleZ *= interpolatedScale;
kernel[i * 3] = sampleX;
kernel[i * 3 + 1] = sampleY;
kernel[i * 3 + 2] = sampleZ;
}
return kernel;
}
}
@@ -5,9 +5,8 @@ in vec4 vPos;
in vec3 vertexWorldPos;
out vec4 fragColor;
uniform float fogScale;
uniform float distanceScale;
uniform bool noiseEnabled;
uniform int noiseSteps;
uniform float noiseIntensity;
uniform float noiseDropoff;
@@ -67,25 +66,26 @@ void main() {
// Modifies the color
// A value of 0 on the randomValue will result in the original color, while a value of 1 will result in a fully bright color
vec3 newCol = vertexColor.rgb + (vec3(1.0) - vertexColor.rgb) * randomValue;
vec3 newCol = (vec3(1.0) - vertexColor.rgb) * randomValue;
// Clamps it and turns it back into a vec4
fragColor = mix(
vec4(
clamp(newCol.r, 0., 1.),
clamp(newCol.g, 0., 1.),
clamp(newCol.b, 0., 1.),
vertexColor.w
), vertexColor,
clamp(length(vertexWorldPos) * fogScale * noiseDropoff, 0., 1.) // The further away it gets, the less noise gets applied
fragColor = vec4(
clamp(newCol.r, 0., 1.),
clamp(newCol.g, 0., 1.),
clamp(newCol.b, 0., 1.),
clamp(length(vertexWorldPos) * distanceScale * noiseDropoff, 0., 1.) // The further away it gets, the less noise gets applied
);
fragColor = vec4(
0f, 0f, 0f,
randomValue // The further away it gets, the less noise gets applied
);
// For testing
// if (vertexColor.r != 69420.) {
// fragColor = vec4(
// mod(fixedVPos.x, 1),
// mod(fixedVPos.y, 1),
// mod(fixedVPos.z, 1),
// vertexColor.w);
// }
if (vertexColor.r != 69420.) {
fragColor = vec4(
mod(fixedVPos.x, 1),
mod(fixedVPos.y, 1),
mod(fixedVPos.z, 1),
1f);
}
}
@@ -1,10 +0,0 @@
#version 150 core
in vec2 vPosition;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(vPosition, 1.0, 1.0);
TexCoord = vPosition.xy * 0.5 + 0.5;
}
@@ -0,0 +1,15 @@
#version 150 core
in vec2 vPos;
out vec2 TexCoord;
out vec4 vertexColor;
out vec3 vertexWorldPos;
out float vertexYPos;
void main()
{
gl_Position = vec4(vPos, 1.0, 1.0);
TexCoord = vPos.xy * 0.5 + 0.5;
}