Skip to content

Commit

Permalink
fix: Modernize shaders to use the new vanilla system
Browse files Browse the repository at this point in the history
Fixes #799?
  • Loading branch information
Kamefrede committed Dec 31, 2023
1 parent 9becc9d commit c3401be
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 295 deletions.
66 changes: 15 additions & 51 deletions src/main/java/vazkii/psi/client/core/handler/HUDHandler.java
Expand Up @@ -27,8 +27,6 @@
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;

import vazkii.psi.api.PsiAPI;
Expand All @@ -46,7 +44,6 @@
import vazkii.psi.common.lib.LibMisc;
import vazkii.psi.common.lib.LibResources;

import java.util.function.Consumer;
import java.util.regex.Pattern;

@Mod.EventBusSubscriber(value = Dist.CLIENT, modid = LibMisc.MOD_ID)
Expand All @@ -56,8 +53,6 @@ public final class HUDHandler {
private static final ResourceLocation psiBarMask = new ResourceLocation(LibResources.GUI_PSI_BAR_MASK);
private static final ResourceLocation psiBarShatter = new ResourceLocation(LibResources.GUI_PSI_BAR_SHATTER);

private static final int secondaryTextureUnit = 7;

private static boolean registeredMask = false;
private static final int maxRemainingTicks = 30;

Expand Down Expand Up @@ -161,14 +156,6 @@ public static void drawPsiBar(PoseStack ms, Window res, float pticks) {
int origY = y;
int v = 0;

int texture = 0;
boolean shaders = ShaderHandler.useShaders;

if (shaders) {
RenderSystem.activeTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
texture = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
}

RenderSystem.enableBlend();
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

Expand All @@ -180,8 +167,8 @@ public static void drawPsiBar(PoseStack ms, Window res, float pticks) {
v = origHeight - effHeight;
y = origY + v;

ShaderHandler.useShader(ShaderHandler.psiBar, generateCallback(a, d.shatter, data.overflowed));
GuiComponent.blit(ms, x, y, 32, v, width, height, 64, 256);
usePsiBarShader(a, d.shatter, data.overflowed);
GuiComponent.blit(poseStack, x, y, 32, v, width, height, 64, 256);
}

float textY = origY;
Expand All @@ -202,16 +189,8 @@ public static void drawPsiBar(PoseStack ms, Window res, float pticks) {
}

RenderSystem.setShaderColor(r, g, b, 1F);
ShaderHandler.useShader(ShaderHandler.psiBar, generateCallback(1F, false, data.overflowed));
GuiComponent.blit(ms, x, y, 32, v, width, height, 64, 256);
ShaderHandler.releaseShader();

if (shaders) {
RenderSystem.activeTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
RenderSystem.bindTexture(texture);
RenderSystem.activeTexture(ARBMultitexture.GL_TEXTURE0_ARB);
}

usePsiBarShader(1F, false, data.overflowed);
GuiComponent.blit(poseStack, x, y, 32, v, width, height, 64, 256);
RenderSystem.setShaderColor(1F, 1F, 1F, 1F);

ms.pushPose();
Expand All @@ -221,7 +200,7 @@ public static void drawPsiBar(PoseStack ms, Window res, float pticks) {

int storedPsi = cad.getStoredPsi(cadStack);

String s1 = storedPsi == -1 ? "\u221E" : "" + data.availablePsi;
String s1 = storedPsi == -1 ? "" : "" + data.availablePsi;
String s2 = "" + storedPsi;

int offBar = 22;
Expand Down Expand Up @@ -327,8 +306,8 @@ private static void renderRemainingItems(PoseStack ms, Window resolution, float
+ ChatFormatting.GRAY + max + ChatFormatting.RESET + "+" + ChatFormatting.YELLOW + rem
+ ChatFormatting.RESET + ")";
}
} else if (remainingCount == -1) {
text = "\u221E";
} else if(remainingCount == -1) {
text = "";
}

int color = 0x00FFFFFF | (int) (alpha * 0xFF) << 24;
Expand Down Expand Up @@ -371,28 +350,13 @@ public static void setRemaining(Player player, ItemStack displayStack, Pattern p
}

@OnlyIn(Dist.CLIENT)
private static Consumer<Integer> generateCallback(final float percentile, final boolean shatter, final boolean overflowed) {
Minecraft mc = Minecraft.getInstance();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "percentile");
int overflowedUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "overflowed");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");

RenderSystem.activeTexture(ARBMultitexture.GL_TEXTURE0_ARB);
RenderSystem.setShaderTexture(0, psiBar);
ARBShaderObjects.glUniform1iARB(imageUniform, 0);

RenderSystem.activeTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);

RenderSystem.enableTexture();

RenderSystem.setShaderTexture(1, shatter ? psiBarShatter : psiBarMask);
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit);

ARBShaderObjects.glUniform1fARB(percentileUniform, percentile);
ARBShaderObjects.glUniform1iARB(overflowedUniform, overflowed ? 1 : 0);
};
public static void usePsiBarShader(final float percentile, final boolean shatter, final boolean overflowed) {
var psiBarShader = ShaderHandler.getPsiBarShader();
RenderSystem.setShader(ShaderHandler::getPsiBarShader);
RenderSystem.setShaderTexture(0, psiBar);
RenderSystem.setShaderTexture(1, shatter ? psiBarShatter : psiBarMask);
psiBarShader.safeGetUniform("GameTime").set(RenderSystem.getShaderGameTime());
psiBarShader.safeGetUniform("PsiBarPercentile").set(percentile);
psiBarShader.safeGetUniform("PsiBarOverflowed").set(overflowed ? 1 : 0);
}

}
168 changes: 17 additions & 151 deletions src/main/java/vazkii/psi/client/core/handler/ShaderHandler.java
Expand Up @@ -8,164 +8,30 @@
*/
package vazkii.psi.client.core.handler;

import com.google.common.io.CharStreams;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;

import org.lwjgl.opengl.ARBFragmentShader;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.ARBVertexShader;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RegisterShadersEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import vazkii.psi.common.Psi;
import vazkii.psi.common.core.handler.ConfigHandler;
import vazkii.psi.common.lib.LibMisc;
import vazkii.psi.common.lib.LibResources;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
import java.io.IOException;

@Mod.EventBusSubscriber(modid = LibMisc.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class ShaderHandler {

private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
public static boolean useShaders = false;
private static ShaderInstance psiBarShader;

private static final int VERT = 1;
private static final int FRAG = 2;

private static final String VERT_EXTENSION = ".vsh";
private static final String FRAG_EXTENSION = ".fsh";

public static int rawColor;
public static int psiBar;
public static int simpleBloom;

public static void init() {
useShaders = canUseShaders();
if (!useShaders) {
return;
}
Psi.logger.info("Initializing Psi shaders!");

rawColor = createProgram(LibResources.SHADER_RAW_COLOR, FRAG);
psiBar = createProgram(LibResources.SHADER_PSI_BAR, FRAG);
simpleBloom = createProgram(LibResources.SHADER_SIMPLE_BLOOM, FRAG);
}

public static void useShader(int shader, Consumer<Integer> callback) {
if (!useShaders) {
return;
}

ARBShaderObjects.glUseProgramObjectARB(shader);

if (shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientTickHandler.ticksInGame);

if (callback != null) {
callback.accept(shader);
}
}
}

public static void useShader(int shader) {
useShader(shader, null);
}

public static void releaseShader() {
useShader(0);
}

public static boolean canUseShaders() {
RenderSystem.assertOnRenderThread();
return ConfigHandler.CLIENT.useShaders.get() && ((GL.getCapabilities().OpenGL14 && (GL.getCapabilities().GL_ARB_framebuffer_object || GL.getCapabilities().GL_EXT_framebuffer_object || GL.getCapabilities().OpenGL30))
&& (GL.getCapabilities().OpenGL21 || GL.getCapabilities().GL_ARB_fragment_shader && GL.getCapabilities().GL_ARB_fragment_shader && GL.getCapabilities().GL_ARB_shader_objects));
}

private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;

return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}

// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL

private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if (vert != null) {
vertId = createShader(vert, VERT_ST);
}
if (frag != null) {
fragId = createShader(frag, FRAG_ST);
}

program = ARBShaderObjects.glCreateProgramObjectARB();
if (program == 0) {
return 0;
}

if (vert != null) {
ARBShaderObjects.glAttachObjectARB(program, vertId);
}
if (frag != null) {
ARBShaderObjects.glAttachObjectARB(program, fragId);
}

ARBShaderObjects.glLinkProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
Psi.logger.error(getLogInfo(program));
return 0;
}

ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
Psi.logger.error(getLogInfo(program));
return 0;
}

return program;
}

private static int createShader(String filename, int shaderType) {
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);

if (shader == 0) {
return 0;
}

ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);

if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE) {
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
}

return shader;
} catch (Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}

private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}

private static String readFileAsString(String filename) throws Exception {
try (InputStream in = ShaderHandler.class.getResourceAsStream(filename)) {
if (in == null) {
return "";
}

return CharStreams.toString(new InputStreamReader(in, StandardCharsets.UTF_8));
}
@SubscribeEvent
static void registerShaders(RegisterShadersEvent event) throws IOException {
event.registerShader(
new ShaderInstance(event.getResourceManager(), new ResourceLocation(LibMisc.MOD_ID, LibResources.SHADER_PSI_BAR), DefaultVertexFormat.POSITION_TEX_COLOR),
shader -> psiBarShader = shader
);
}
}
8 changes: 5 additions & 3 deletions src/main/java/vazkii/psi/client/core/proxy/ClientProxy.java
Expand Up @@ -42,7 +42,6 @@
import vazkii.psi.client.core.handler.ClientTickHandler;
import vazkii.psi.client.core.handler.ColorHandler;
import vazkii.psi.client.core.handler.KeybindHandler;
import vazkii.psi.client.core.handler.ShaderHandler;
import vazkii.psi.client.fx.SparkleParticleData;
import vazkii.psi.client.fx.WispParticleData;
import vazkii.psi.client.gui.GuiProgrammer;
Expand All @@ -55,7 +54,11 @@
import vazkii.psi.common.block.base.ModBlocks;
import vazkii.psi.common.block.tile.TileProgrammer;
import vazkii.psi.common.core.proxy.IProxy;
import vazkii.psi.common.entity.*;
import vazkii.psi.common.entity.EntitySpellCharge;
import vazkii.psi.common.entity.EntitySpellCircle;
import vazkii.psi.common.entity.EntitySpellGrenade;
import vazkii.psi.common.entity.EntitySpellMine;
import vazkii.psi.common.entity.EntitySpellProjectile;
import vazkii.psi.common.item.base.ModItems;
import vazkii.psi.common.lib.LibItemNames;
import vazkii.psi.common.lib.LibMisc;
Expand Down Expand Up @@ -106,7 +109,6 @@ private void loadComplete(FMLLoadCompleteEvent event) {
map.put(layer, new BufferBuilder(layer.bufferSize()));
map.put(GuiProgrammer.LAYER, new BufferBuilder(GuiProgrammer.LAYER.bufferSize()));
ColorHandler.init();
ShaderHandler.init();
});
}

Expand Down
6 changes: 1 addition & 5 deletions src/main/java/vazkii/psi/common/lib/LibResources.java
Expand Up @@ -15,15 +15,11 @@ public class LibResources {
public static final String PREFIX_MOD = "psi:";
public static final ResourceLocation PATCHOULI_BOOK = new ResourceLocation(LibMisc.MOD_ID, "encyclopaedia_psionica");

public static final String PREFIX_SHADER = "/assets/psi/shaders/";
public static final String PREFIX_GUI = PREFIX_MOD + "textures/gui/";
public static final String PREFIX_MODEL = PREFIX_MOD + "textures/model/";
public static final String PREFIX_MISC = PREFIX_MOD + "textures/misc/";

public static final String SHADER_RAW_COLOR = PREFIX_SHADER + "raw_color";
public static final String SHADER_PSI_BAR = PREFIX_SHADER + "psi_bar";
public static final String SHADER_SIMPLE_BLOOM = PREFIX_SHADER + "simple_bloom";

public static final String SHADER_PSI_BAR = "psi_bar";
public static final String GUI_CREATIVE = "psi.png";
public static final String GUI_CAD_ASSEMBLER = PREFIX_GUI + "cad_assembler.png";
public static final String GUI_PSI_BAR = PREFIX_GUI + "psi_bar.png";
Expand Down
43 changes: 43 additions & 0 deletions src/main/resources/assets/psi/shaders/core/psi_bar.fsh
@@ -0,0 +1,43 @@
#version 150

uniform float PsiBarPercentile;
uniform int PsiBarOverflowed;

in vec2 texCoord0;
in vec4 textureColor;
in vec4 maskColor;
in vec4 vertexColor;
in float timeTicks;

out vec4 fragColor;

void main() {
float maskgs = (maskColor.r + maskColor.g + maskColor.b) / 3.0;

float r = textureColor.r * vertexColor.r;
float g = textureColor.g * vertexColor.g;
float b = textureColor.b * vertexColor.b;
float a = textureColor.a;

float exr1 = sin(texCoord0.x * 2 + texCoord0.y * 10 + timeTicks * 0.035);
float exr2 = sin(texCoord0.x * 20 + texCoord0.y * 2 + timeTicks * 0.15);
float exr3 = sin(texCoord0.x * 1 + texCoord0.y * 90 + timeTicks * 0.75);

float w1 = (cos(timeTicks * 0.1) + 1) * 0.5;
float w2 = (sin(timeTicks * 0.08) + 1) * 0.5;
float w3 = (cos(timeTicks * 0.001) + 1) * 0.5;

float w = w1 + w2 + w3;
float exr = (exr1 * w1 + exr2 * w2 + exr3 * w3) / w * 0.1;

r = PsiBarOverflowed == 1 ? 1.0 : r + exr;
g -= exr;
b = PsiBarOverflowed == 1 ? b - 0.2 : b;

r = max(0, min(1, r));
g = max(0, min(1, g));
b = max(0, min(1, b));
a = maskgs <= PsiBarPercentile ? a : 0;

fragColor = vec4(r, g, b, a);
}

0 comments on commit c3401be

Please sign in to comment.