mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
223 lines
9.5 KiB
Java
223 lines
9.5 KiB
Java
package net.coderbot.iris.compat.dh;
|
|
|
|
import com.google.common.primitives.Ints;
|
|
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
|
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
|
import com.seibel.distanthorizons.api.DhApi;
|
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
|
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
|
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
|
import net.coderbot.iris.gl.program.ProgramImages;
|
|
import net.coderbot.iris.gl.program.ProgramSamplers;
|
|
import net.coderbot.iris.gl.program.ProgramUniforms;
|
|
import net.coderbot.iris.gl.shader.GlShader;
|
|
import net.coderbot.iris.gl.shader.ShaderType;
|
|
import net.coderbot.iris.gl.state.FogMode;
|
|
import net.coderbot.iris.gl.texture.TextureType;
|
|
import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
|
|
import net.coderbot.iris.pipeline.PatchedShaderPrinter;
|
|
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
|
import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
|
import net.coderbot.iris.samplers.IrisSamplers;
|
|
import net.coderbot.iris.shaderpack.ProgramSource;
|
|
import net.coderbot.iris.uniforms.CommonUniforms;
|
|
import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
|
|
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.renderer.texture.DynamicTexture;
|
|
import org.joml.Matrix4fc;
|
|
import org.lwjgl.opengl.GL11;
|
|
import org.lwjgl.opengl.GL13;
|
|
import org.lwjgl.opengl.GL20;
|
|
import org.lwjgl.opengl.GL32;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
public class IrisLodRenderProgram {
|
|
// Uniforms
|
|
public final int modelOffsetUniform;
|
|
public final int worldYOffsetUniform;
|
|
public final int mircoOffsetUniform;
|
|
// Fog/Clip Uniforms
|
|
public final int clipDistanceUniform;
|
|
private final int id;
|
|
private final ProgramUniforms uniforms;
|
|
private final CustomUniforms customUniforms;
|
|
private final ProgramSamplers samplers;
|
|
private final ProgramImages images;
|
|
private final BlendModeOverride blend;
|
|
private final BufferBlendOverride[] bufferBlendOverrides;
|
|
|
|
// This will bind AbstractVertexAttribute
|
|
private IrisLodRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, DeferredWorldRenderingPipeline pipeline) {
|
|
id = GLStateManager.glCreateProgram();
|
|
|
|
GLStateManager.glBindAttribLocation(this.id, 0, "vPosition");
|
|
GLStateManager.glBindAttribLocation(this.id, 1, "iris_color");
|
|
GLStateManager.glBindAttribLocation(this.id, 2, "irisExtra");
|
|
|
|
this.bufferBlendOverrides = bufferBlendOverrides;
|
|
|
|
GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex);
|
|
GLStateManager.glAttachShader(id, vert.getHandle());
|
|
|
|
GlShader tessCont = null;
|
|
if (tessControl != null) {
|
|
tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl);
|
|
GLStateManager.glAttachShader(id, tessCont.getHandle());
|
|
}
|
|
|
|
GlShader tessE = null;
|
|
if (tessEval != null) {
|
|
tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval);
|
|
GLStateManager.glAttachShader(id, tessE.getHandle());
|
|
}
|
|
|
|
GlShader geom = null;
|
|
if (geometry != null) {
|
|
geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry);
|
|
GLStateManager.glAttachShader(id, geom.getHandle());
|
|
}
|
|
|
|
GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment);
|
|
GLStateManager.glAttachShader(id, frag.getHandle());
|
|
|
|
GLStateManager.glLinkProgram(this.id);
|
|
int status = GLStateManager.glGetProgrami(this.id, GL20.GL_LINK_STATUS);
|
|
if (status != 1) {
|
|
String message = "Shader link error in Iris DH program! Details: " + GLStateManager.glGetProgramInfoLog(this.id, 9999);
|
|
this.free();
|
|
throw new RuntimeException(message);
|
|
} else {
|
|
GLStateManager.glUseProgram(this.id);
|
|
}
|
|
|
|
vert.destroy();
|
|
frag.destroy();
|
|
|
|
if (tessCont != null) tessCont.destroy();
|
|
if (tessE != null) tessE.destroy();
|
|
if (geom != null) geom.destroy();
|
|
|
|
blend = override;
|
|
ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id);
|
|
ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS);
|
|
CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX);
|
|
customUniforms.assignTo(uniformBuilder);
|
|
BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder);
|
|
ProgramImages.Builder builder = ProgramImages.builder(id);
|
|
pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder,
|
|
isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(),
|
|
isShadowPass, false, true, false);
|
|
customUniforms.mapholderToPass(uniformBuilder, this);
|
|
this.uniforms = uniformBuilder.buildUniforms();
|
|
this.customUniforms = customUniforms;
|
|
samplers = samplerBuilder.build();
|
|
images = builder.build();
|
|
|
|
modelOffsetUniform = tryGetUniformLocation2("modelOffset");
|
|
worldYOffsetUniform = tryGetUniformLocation2("worldYOffset");
|
|
mircoOffsetUniform = tryGetUniformLocation2("mircoOffset");
|
|
|
|
// Fog/Clip Uniforms
|
|
clipDistanceUniform = tryGetUniformLocation2("clipDistance");
|
|
}
|
|
|
|
public static IrisLodRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, DeferredWorldRenderingPipeline pipeline) {
|
|
Map<PatchShaderType, String> transformed = TransformPatcher.patchDHTerrain(
|
|
name,
|
|
source.getVertexSource().orElseThrow(RuntimeException::new),
|
|
source.getTessControlSource().orElse(null),
|
|
source.getTessEvalSource().orElse(null),
|
|
source.getGeometrySource().orElse(null),
|
|
source.getFragmentSource().orElseThrow(RuntimeException::new),
|
|
pipeline.getTextureMap());
|
|
String vertex = transformed.get(PatchShaderType.VERTEX);
|
|
String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);
|
|
String tessEval = transformed.get(PatchShaderType.TESS_EVAL);
|
|
String geometry = transformed.get(PatchShaderType.GEOMETRY);
|
|
String fragment = transformed.get(PatchShaderType.FRAGMENT);
|
|
PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, tessControl, tessEval, fragment);
|
|
|
|
List<BufferBlendOverride> bufferOverrides = new ArrayList<>();
|
|
|
|
source.getDirectives().getBufferBlendOverrides().forEach(information -> {
|
|
int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
|
|
if (index > -1) {
|
|
bufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
|
|
}
|
|
});
|
|
|
|
return new IrisLodRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline);
|
|
}
|
|
|
|
// Noise Uniforms
|
|
|
|
public int tryGetUniformLocation2(CharSequence name) {
|
|
return GLStateManager.glGetUniformLocation(this.id, name);
|
|
}
|
|
|
|
// Override ShaderProgram.bind()
|
|
public void bind() {
|
|
GLStateManager.glUseProgram(id);
|
|
if (blend != null) blend.apply();
|
|
|
|
for (BufferBlendOverride override : bufferBlendOverrides) {
|
|
override.apply();
|
|
}
|
|
}
|
|
|
|
public void unbind() {
|
|
GLStateManager.glUseProgram(0);
|
|
ProgramUniforms.clearActiveUniforms();
|
|
ProgramSamplers.clearActiveSamplers();
|
|
BlendModeOverride.restore();
|
|
}
|
|
|
|
public void free() {
|
|
GLStateManager.glDeleteProgram(id);
|
|
}
|
|
|
|
public void fillUniformData(Matrix4fc projection, Matrix4fc modelView, int worldYOffset, float partialTicks) {
|
|
GLStateManager.glUseProgram(id);
|
|
|
|
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + IrisSamplers.LIGHTMAP_TEXTURE_UNIT);
|
|
DynamicTexture lightmapTexture = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapTexture();
|
|
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture.getGlTextureId());
|
|
|
|
LodRendererEvents.pushDhMatrices(projection, modelView);
|
|
|
|
setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset
|
|
|
|
// setUniform(skyLightUniform, skyLight);
|
|
|
|
if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) worldYOffset);
|
|
|
|
// Fog/Clip Uniforms
|
|
float dhNearClipDistance = DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(partialTicks);
|
|
setUniform(clipDistanceUniform, dhNearClipDistance);
|
|
|
|
samplers.update();
|
|
uniforms.update();
|
|
|
|
customUniforms.push(this);
|
|
|
|
images.update();
|
|
}
|
|
|
|
private void setUniform(int index, float value) {
|
|
GLStateManager.glUniform1f(index, value);
|
|
}
|
|
|
|
public void setModelPos(DhApiVec3f modelPos) {
|
|
setUniform(modelOffsetUniform, modelPos);
|
|
}
|
|
|
|
private void setUniform(int index, DhApiVec3f pos) {
|
|
GLStateManager.glUniform3f(index, pos.x, pos.y, pos.z);
|
|
}
|
|
|
|
}
|