mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 23:47:38 +01:00
Fix projection matrix bug
- Copy the projection matrix when vanilla would be uploading it to GL. - This should account for just about everything. Unrelated to the fix: - Shader programs now have more flexibility in specialization. - Accomplished with IMultiProgram. - Remove unnecessary SHADER_DEBUG_OUTPUT boolean.
This commit is contained in:
parent
edb1b59f41
commit
f2c6afdcb3
12 changed files with 127 additions and 88 deletions
|
@ -186,7 +186,6 @@ public class ClientEvents {
|
||||||
ms.pop();
|
ms.pop();
|
||||||
|
|
||||||
RenderWork.runAll();
|
RenderWork.runAll();
|
||||||
FastRenderDispatcher.endFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class RenderHooksMixin {
|
||||||
Matrix4f viewProjection = stack.peek()
|
Matrix4f viewProjection = stack.peek()
|
||||||
.getModel()
|
.getModel()
|
||||||
.copy();
|
.copy();
|
||||||
viewProjection.multiplyBackward(FastRenderDispatcher.getProjectionMatrix());
|
viewProjection.multiplyBackward(Backend.projectionMatrix);
|
||||||
|
|
||||||
FastRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ);
|
FastRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.simibubi.create.foundation.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.backend.Backend;
|
||||||
|
|
||||||
|
@Mixin(GameRenderer.class)
|
||||||
|
public class StoreProjectionMatrixMixin {
|
||||||
|
|
||||||
|
@Inject(method = "loadProjectionMatrix", at = @At("TAIL"))
|
||||||
|
private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) {
|
||||||
|
Backend.projectionMatrix = projection.copy();
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ import org.lwjgl.opengl.GLCapabilities;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
|
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramGroup;
|
import com.simibubi.create.foundation.render.backend.gl.shader.IMultiProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec;
|
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat;
|
||||||
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
|
||||||
|
@ -20,13 +20,17 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
import net.minecraft.resources.IResourceManager;
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.vector.Matrix4f;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
import net.minecraftforge.resource.ISelectiveResourceReloadListener;
|
||||||
|
|
||||||
public class Backend {
|
public class Backend {
|
||||||
public static final Boolean SHADER_DEBUG_OUTPUT = true;
|
|
||||||
|
|
||||||
public static final Logger log = LogManager.getLogger(Backend.class);
|
public static final Logger log = LogManager.getLogger(Backend.class);
|
||||||
|
|
||||||
|
public static final ShaderLoader shaderLoader = new ShaderLoader();
|
||||||
|
|
||||||
|
public static Matrix4f projectionMatrix = new Matrix4f();
|
||||||
|
|
||||||
public static GLCapabilities capabilities;
|
public static GLCapabilities capabilities;
|
||||||
public static GlCompat compat;
|
public static GlCompat compat;
|
||||||
|
|
||||||
|
@ -34,7 +38,7 @@ public class Backend {
|
||||||
private static boolean enabled;
|
private static boolean enabled;
|
||||||
|
|
||||||
static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
static final Map<ResourceLocation, ProgramSpec<?>> registry = new HashMap<>();
|
||||||
static final Map<ProgramSpec<?>, ProgramGroup<?>> programs = new HashMap<>();
|
static final Map<ProgramSpec<?>, IMultiProgram<?>> programs = new HashMap<>();
|
||||||
|
|
||||||
public Backend() {
|
public Backend() {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
@ -54,7 +58,7 @@ public class Backend {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <P extends GlProgram, S extends ProgramSpec<P>> P getProgram(S spec) {
|
public static <P extends GlProgram, S extends ProgramSpec<P>> P getProgram(S spec) {
|
||||||
return (P) programs.get(spec).get(GlFog.getFogMode());
|
return (P) programs.get(spec).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isFlywheelWorld(World world) {
|
public static boolean isFlywheelWorld(World world) {
|
||||||
|
@ -89,7 +93,7 @@ public class Backend {
|
||||||
IResourceManager manager = mc.getResourceManager();
|
IResourceManager manager = mc.getResourceManager();
|
||||||
|
|
||||||
if (manager instanceof IReloadableResourceManager) {
|
if (manager instanceof IReloadableResourceManager) {
|
||||||
ISelectiveResourceReloadListener listener = ShaderLoader::onResourceManagerReload;
|
ISelectiveResourceReloadListener listener = shaderLoader::onResourceManagerReload;
|
||||||
((IReloadableResourceManager) manager).addReloadListener(listener);
|
((IReloadableResourceManager) manager).addReloadListener(listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,6 @@ public class FastRenderDispatcher {
|
||||||
|
|
||||||
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet);
|
public static WorldAttached<ConcurrentHashMap.KeySetView<TileEntity, Boolean>> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet);
|
||||||
|
|
||||||
private static Matrix4f projectionMatrixThisFrame = null;
|
|
||||||
|
|
||||||
public static void endFrame() {
|
|
||||||
projectionMatrixThisFrame = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enqueueUpdate(TileEntity te) {
|
public static void enqueueUpdate(TileEntity te) {
|
||||||
queuedUpdates.get(te.getWorld()).add(te);
|
queuedUpdates.get(te.getWorld()).add(te);
|
||||||
}
|
}
|
||||||
|
@ -82,45 +76,4 @@ public class FastRenderDispatcher {
|
||||||
|
|
||||||
layer.endDrawing();
|
layer.endDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
// copied from GameRenderer.renderWorld
|
|
||||||
public static Matrix4f getProjectionMatrix() {
|
|
||||||
if (projectionMatrixThisFrame != null) return projectionMatrixThisFrame;
|
|
||||||
|
|
||||||
float partialTicks = AnimationTickHolder.getPartialTicks();
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
|
||||||
GameRenderer gameRenderer = mc.gameRenderer;
|
|
||||||
ClientPlayerEntity player = mc.player;
|
|
||||||
|
|
||||||
MatrixStack matrixstack = new MatrixStack();
|
|
||||||
matrixstack.peek()
|
|
||||||
.getModel()
|
|
||||||
.multiply(gameRenderer.getBasicProjectionMatrix(gameRenderer.getActiveRenderInfo(), partialTicks, true));
|
|
||||||
gameRenderer.bobViewWhenHurt(matrixstack, partialTicks);
|
|
||||||
if (mc.gameSettings.viewBobbing) {
|
|
||||||
gameRenderer.bobView(matrixstack, partialTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
float portalTime = MathHelper.lerp(partialTicks, player.prevTimeInPortal, player.timeInPortal);
|
|
||||||
if (portalTime > 0.0F) {
|
|
||||||
int i = 20;
|
|
||||||
if (player.isPotionActive(Effects.NAUSEA)) {
|
|
||||||
i = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
float f1 = 5.0F / (portalTime * portalTime + 5.0F) - portalTime * 0.04F;
|
|
||||||
f1 = f1 * f1;
|
|
||||||
Vector3f vector3f = new Vector3f(0.0F, MathHelper.SQRT_2 / 2.0F, MathHelper.SQRT_2 / 2.0F);
|
|
||||||
matrixstack.multiply(vector3f.getDegreesQuaternion(((float)gameRenderer.rendererUpdateCount + partialTicks) * (float)i));
|
|
||||||
matrixstack.scale(1.0F / f1, 1.0F, 1.0F);
|
|
||||||
float f2 = -((float)gameRenderer.rendererUpdateCount + partialTicks) * (float)i;
|
|
||||||
matrixstack.multiply(vector3f.getDegreesQuaternion(f2));
|
|
||||||
}
|
|
||||||
|
|
||||||
Matrix4f matrix4f = matrixstack.peek().getModel();
|
|
||||||
gameRenderer.loadProjectionMatrix(matrix4f);
|
|
||||||
|
|
||||||
projectionMatrixThisFrame = matrix4f;
|
|
||||||
return projectionMatrixThisFrame;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,11 @@ import org.lwjgl.system.MemoryUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
||||||
|
import com.simibubi.create.foundation.render.backend.gl.shader.SingleProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
|
import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.GlShader;
|
import com.simibubi.create.foundation.render.backend.gl.shader.GlShader;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramGroup;
|
import com.simibubi.create.foundation.render.backend.gl.shader.FogSensitiveProgram;
|
||||||
|
import com.simibubi.create.foundation.render.backend.gl.shader.IMultiProgram;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec;
|
import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants;
|
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderType;
|
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderType;
|
||||||
|
@ -45,9 +47,12 @@ public class ShaderLoader {
|
||||||
public static final String SHADER_DIR = "flywheel/shaders/";
|
public static final String SHADER_DIR = "flywheel/shaders/";
|
||||||
public static final ArrayList<String> EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl");
|
public static final ArrayList<String> EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl");
|
||||||
|
|
||||||
static final Map<ResourceLocation, String> shaderSource = new HashMap<>();
|
// #flwinclude <"valid_namespace:valid/path_to_file.glsl">
|
||||||
|
private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">");
|
||||||
|
|
||||||
static void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
final Map<ResourceLocation, String> shaderSource = new HashMap<>();
|
||||||
|
|
||||||
|
void onResourceManagerReload(IResourceManager manager, Predicate<IResourceType> predicate) {
|
||||||
if (predicate.test(VanillaResourceType.SHADERS)) {
|
if (predicate.test(VanillaResourceType.SHADERS)) {
|
||||||
OptifineHandler.refresh();
|
OptifineHandler.refresh();
|
||||||
Backend.refresh();
|
Backend.refresh();
|
||||||
|
@ -56,16 +61,16 @@ public class ShaderLoader {
|
||||||
shaderSource.clear();
|
shaderSource.clear();
|
||||||
loadShaderSources(manager);
|
loadShaderSources(manager);
|
||||||
|
|
||||||
Backend.programs.values().forEach(ProgramGroup::delete);
|
Backend.programs.values().forEach(IMultiProgram::delete);
|
||||||
Backend.programs.clear();
|
Backend.programs.clear();
|
||||||
Backend.registry.values().forEach(ShaderLoader::loadProgram);
|
Backend.registry.values().forEach(this::loadProgramFromSpec);
|
||||||
|
|
||||||
Backend.log.info("Loaded all shader programs.");
|
Backend.log.info("Loaded all shader programs.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadShaderSources(IResourceManager manager){
|
private void loadShaderSources(IResourceManager manager){
|
||||||
Collection<ResourceLocation> allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> {
|
Collection<ResourceLocation> allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> {
|
||||||
for (String ext : EXTENSIONS) {
|
for (String ext : EXTENSIONS) {
|
||||||
if (s.endsWith(ext)) return true;
|
if (s.endsWith(ext)) return true;
|
||||||
|
@ -89,19 +94,26 @@ public class ShaderLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static <P extends GlProgram, S extends ProgramSpec<P>> void loadProgram(S programSpec) {
|
private <P extends GlProgram, S extends ProgramSpec<P>> void loadProgramFromSpec(S programSpec) {
|
||||||
Map<GlFogMode, P> programGroup = new EnumMap<>(GlFogMode.class);
|
|
||||||
|
|
||||||
for (GlFogMode fogMode : GlFogMode.values()) {
|
if (programSpec.fogSensitive) {
|
||||||
programGroup.put(fogMode, loadProgram(programSpec, fogMode));
|
Map<GlFogMode, P> programGroup = new EnumMap<>(GlFogMode.class);
|
||||||
|
|
||||||
|
for (GlFogMode fogMode : GlFogMode.values()) {
|
||||||
|
programGroup.put(fogMode, loadProgram(programSpec, fogMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend.programs.put(programSpec, new FogSensitiveProgram<>(programGroup));
|
||||||
|
} else {
|
||||||
|
P program = loadProgram(programSpec, GlFogMode.NONE);
|
||||||
|
|
||||||
|
Backend.programs.put(programSpec, new SingleProgram<>(program));
|
||||||
}
|
}
|
||||||
|
|
||||||
Backend.programs.put(programSpec, new ProgramGroup<>(programGroup));
|
|
||||||
|
|
||||||
Backend.log.debug("Loaded program {}", programSpec.name);
|
Backend.log.debug("Loaded program {}", programSpec.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <P extends GlProgram, S extends ProgramSpec<P>> P loadProgram(S programSpec, GlFogMode fogMode) {
|
private <P extends GlProgram, S extends ProgramSpec<P>> P loadProgram(S programSpec, GlFogMode fogMode) {
|
||||||
GlShader vert = null;
|
GlShader vert = null;
|
||||||
GlShader frag = null;
|
GlShader frag = null;
|
||||||
try {
|
try {
|
||||||
|
@ -124,16 +136,14 @@ public class ShaderLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">");
|
private String processIncludes(ResourceLocation baseName, String source) {
|
||||||
|
|
||||||
private static String processIncludes(ResourceLocation baseName, String source) {
|
|
||||||
HashSet<ResourceLocation> seen = new HashSet<>();
|
HashSet<ResourceLocation> seen = new HashSet<>();
|
||||||
seen.add(baseName);
|
seen.add(baseName);
|
||||||
|
|
||||||
return includeRecursive(source, seen).collect(Collectors.joining("\n"));
|
return includeRecursive(source, seen).collect(Collectors.joining("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<String> includeRecursive(String source, Set<ResourceLocation> seen) {
|
private Stream<String> includeRecursive(String source, Set<ResourceLocation> seen) {
|
||||||
return new BufferedReader(new StringReader(source)).lines().flatMap(line -> {
|
return new BufferedReader(new StringReader(source)).lines().flatMap(line -> {
|
||||||
|
|
||||||
Matcher matcher = includePattern.matcher(line);
|
Matcher matcher = includePattern.matcher(line);
|
||||||
|
@ -156,7 +166,7 @@ public class ShaderLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) {
|
private GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) {
|
||||||
String source = shaderSource.get(name);
|
String source = shaderSource.get(name);
|
||||||
|
|
||||||
source = processIncludes(name, source);
|
source = processIncludes(name, source);
|
||||||
|
@ -168,7 +178,7 @@ public class ShaderLoader {
|
||||||
return new GlShader(type, name, source);
|
return new GlShader(type, name, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readToString(InputStream is) {
|
public String readToString(InputStream is) {
|
||||||
RenderSystem.assertThread(RenderSystem::isOnRenderThread);
|
RenderSystem.assertThread(RenderSystem::isOnRenderThread);
|
||||||
ByteBuffer bytebuffer = null;
|
ByteBuffer bytebuffer = null;
|
||||||
|
|
||||||
|
@ -189,7 +199,7 @@ public class ShaderLoader {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer readToBuffer(InputStream is) throws IOException {
|
public ByteBuffer readToBuffer(InputStream is) throws IOException {
|
||||||
ByteBuffer bytebuffer;
|
ByteBuffer bytebuffer;
|
||||||
if (is instanceof FileInputStream) {
|
if (is instanceof FileInputStream) {
|
||||||
FileInputStream fileinputstream = (FileInputStream)is;
|
FileInputStream fileinputstream = (FileInputStream)is;
|
||||||
|
|
|
@ -2,21 +2,25 @@ package com.simibubi.create.foundation.render.backend.gl.shader;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.render.backend.gl.GlFog;
|
||||||
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
|
||||||
|
|
||||||
public class ProgramGroup<P extends GlProgram> {
|
public class FogSensitiveProgram<P extends GlProgram> implements IMultiProgram<P> {
|
||||||
|
|
||||||
private final Map<GlFogMode, P> programs;
|
private final Map<GlFogMode, P> programs;
|
||||||
|
|
||||||
public ProgramGroup(Map<GlFogMode, P> programs) {
|
public FogSensitiveProgram(Map<GlFogMode, P> programs) {
|
||||||
this.programs = programs;
|
this.programs = programs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public P get(GlFogMode fogMode) {
|
@Override
|
||||||
return programs.get(fogMode);
|
public P get() {
|
||||||
|
return programs.get(GlFog.getFogMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void delete() {
|
public void delete() {
|
||||||
programs.values().forEach(GlProgram::delete);
|
programs.values().forEach(GlProgram::delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -38,7 +38,7 @@ public abstract class GlProgram extends GlObject {
|
||||||
public int getUniformLocation(String uniform) {
|
public int getUniformLocation(String uniform) {
|
||||||
int index = GL20.glGetUniformLocation(this.handle(), uniform);
|
int index = GL20.glGetUniformLocation(this.handle(), uniform);
|
||||||
|
|
||||||
if (index < 0 && Backend.SHADER_DEBUG_OUTPUT) {
|
if (index < 0) {
|
||||||
Backend.log.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name);
|
Backend.log.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ public abstract class GlProgram extends GlObject {
|
||||||
|
|
||||||
String log = GL20.glGetProgramInfoLog(this.program);
|
String log = GL20.glGetProgramInfoLog(this.program);
|
||||||
|
|
||||||
if (!log.isEmpty() && Backend.SHADER_DEBUG_OUTPUT) {
|
if (!log.isEmpty()) {
|
||||||
Backend.log.debug("Program link log for " + this.name + ": " + log);
|
Backend.log.debug("Program link log for " + this.name + ": " + log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.simibubi.create.foundation.render.backend.gl.shader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates any number of shader programs for use in similar contexts.
|
||||||
|
* Allows the implementor to choose which shader program to use based on arbitrary state.
|
||||||
|
*
|
||||||
|
* @param <P>
|
||||||
|
*/
|
||||||
|
public interface IMultiProgram<P extends GlProgram> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the shader program most suited for the current game state.
|
||||||
|
* @return The one true program.
|
||||||
|
*/
|
||||||
|
P get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all shader programs encapsulated by your implementation.
|
||||||
|
*/
|
||||||
|
void delete();
|
||||||
|
}
|
|
@ -20,6 +20,8 @@ public class ProgramSpec<P extends GlProgram> {
|
||||||
|
|
||||||
public final ArrayList<IVertexAttrib> attributes;
|
public final ArrayList<IVertexAttrib> attributes;
|
||||||
|
|
||||||
|
public final boolean fogSensitive;
|
||||||
|
|
||||||
public static <P extends GlProgram> Builder<P> builder(String name, GlProgram.ProgramFactory<P> factory) {
|
public static <P extends GlProgram> Builder<P> builder(String name, GlProgram.ProgramFactory<P> factory) {
|
||||||
return builder(new ResourceLocation(Create.ID, name), factory);
|
return builder(new ResourceLocation(Create.ID, name), factory);
|
||||||
}
|
}
|
||||||
|
@ -28,16 +30,16 @@ public class ProgramSpec<P extends GlProgram> {
|
||||||
return new Builder<>(name, factory);
|
return new Builder<>(name, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag, GlProgram.ProgramFactory<P> factory, ShaderConstants defines, ArrayList<IVertexAttrib> attributes) {
|
public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag, GlProgram.ProgramFactory<P> factory, ShaderConstants defines, ArrayList<IVertexAttrib> attributes, boolean fogSensitive) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.vert = vert;
|
this.vert = vert;
|
||||||
this.frag = frag;
|
this.frag = frag;
|
||||||
this.defines = defines;
|
this.defines = defines;
|
||||||
|
|
||||||
|
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
}
|
this.fogSensitive = fogSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
public ResourceLocation getVert() {
|
public ResourceLocation getVert() {
|
||||||
return vert;
|
return vert;
|
||||||
|
@ -51,6 +53,7 @@ public class ProgramSpec<P extends GlProgram> {
|
||||||
private ResourceLocation vert;
|
private ResourceLocation vert;
|
||||||
private ResourceLocation frag;
|
private ResourceLocation frag;
|
||||||
private ShaderConstants defines = ShaderConstants.EMPTY;
|
private ShaderConstants defines = ShaderConstants.EMPTY;
|
||||||
|
private boolean fogSensitive = true;
|
||||||
|
|
||||||
private final ResourceLocation name;
|
private final ResourceLocation name;
|
||||||
private final GlProgram.ProgramFactory<P> factory;
|
private final GlProgram.ProgramFactory<P> factory;
|
||||||
|
@ -77,13 +80,18 @@ public class ProgramSpec<P extends GlProgram> {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <A extends Enum<A> & IVertexAttrib> Builder<P> addAttributes(Class<A> attributeEnum) {
|
public Builder<P> setFogSensitive(boolean fogSensitive) {
|
||||||
|
this.fogSensitive = fogSensitive;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <A extends Enum<A> & IVertexAttrib> Builder<P> addAttributes(Class<A> attributeEnum) {
|
||||||
attributes.addAll(Arrays.asList(attributeEnum.getEnumConstants()));
|
attributes.addAll(Arrays.asList(attributeEnum.getEnumConstants()));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramSpec<P> createProgramSpec() {
|
public ProgramSpec<P> createProgramSpec() {
|
||||||
return new ProgramSpec<>(name, vert, frag, factory, defines, attributes);
|
return new ProgramSpec<>(name, vert, frag, factory, defines, attributes, fogSensitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.simibubi.create.foundation.render.backend.gl.shader;
|
||||||
|
|
||||||
|
public class SingleProgram<P extends GlProgram> implements IMultiProgram<P> {
|
||||||
|
final P program;
|
||||||
|
|
||||||
|
public SingleProgram(P program) {
|
||||||
|
this.program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public P get() {
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
program.delete();
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,10 +13,11 @@
|
||||||
"RenderHooksMixin",
|
"RenderHooksMixin",
|
||||||
"ShaderCloseMixin",
|
"ShaderCloseMixin",
|
||||||
"TileRemoveMixin",
|
"TileRemoveMixin",
|
||||||
"EntityContraptionInteractionMixin"
|
"EntityContraptionInteractionMixin",
|
||||||
|
"StoreProjectionMatrixMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"minVersion": "0.8"
|
"minVersion": "0.8"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue