diff --git a/src/main/java/com/jozufozu/flywheel/api/context/Context.java b/src/main/java/com/jozufozu/flywheel/api/context/Context.java index 3126030d7..40c4f51ea 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/Context.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/Context.java @@ -10,7 +10,7 @@ public interface Context { * * @param material The material about to be rendered. * @param shader The shader to prepare. - * @param textures Source of the textures to use. + * @param textureSource Source of the textures to use. */ - void prepare(Material material, Shader shader, Textures textures); + void prepare(Material material, Shader shader, TextureSource textureSource); } diff --git a/src/main/java/com/jozufozu/flywheel/api/context/Shader.java b/src/main/java/com/jozufozu/flywheel/api/context/Shader.java index b7dbe1069..e91a9f312 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/Shader.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/Shader.java @@ -1,8 +1,20 @@ package com.jozufozu.flywheel.api.context; +import org.joml.Matrix4fc; + import com.jozufozu.flywheel.api.BackendImplemented; @BackendImplemented public interface Shader { void setTexture(String glslName, Texture texture); + + void setFloat(String glslName, float value); + + void setVec2(String glslName, float x, float y); + + void setVec3(String glslName, float x, float y, float z); + + void setVec4(String glslName, float x, float y, float z, float w); + + void setMat4(String glslName, Matrix4fc matrix); } diff --git a/src/main/java/com/jozufozu/flywheel/api/context/Textures.java b/src/main/java/com/jozufozu/flywheel/api/context/TextureSource.java similarity index 94% rename from src/main/java/com/jozufozu/flywheel/api/context/Textures.java rename to src/main/java/com/jozufozu/flywheel/api/context/TextureSource.java index 65e859d33..152b087c7 100644 --- a/src/main/java/com/jozufozu/flywheel/api/context/Textures.java +++ b/src/main/java/com/jozufozu/flywheel/api/context/TextureSource.java @@ -5,7 +5,7 @@ import com.jozufozu.flywheel.api.BackendImplemented; import net.minecraft.resources.ResourceLocation; @BackendImplemented -public interface Textures { +public interface TextureSource { /** * Get a built-in texture by its resource location. * diff --git a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java index cdc5c3e31..29f99bb56 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java +++ b/src/main/java/com/jozufozu/flywheel/backend/compile/PipelineCompiler.java @@ -5,6 +5,7 @@ import java.util.List; import com.jozufozu.flywheel.backend.InternalVertex; import com.jozufozu.flywheel.backend.compile.core.CompilationHarness; import com.jozufozu.flywheel.backend.compile.core.Compile; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; import com.jozufozu.flywheel.backend.gl.shader.ShaderType; import com.jozufozu.flywheel.backend.glsl.ShaderSources; import com.jozufozu.flywheel.backend.glsl.SourceComponent; @@ -52,6 +53,14 @@ public class PipelineCompiler { .then((key, program) -> { program.setUniformBlockBinding("_FlwFrameUniforms", 0); program.setUniformBlockBinding("_FlwFogUniforms", 1); + + program.bind(); + + program.setSamplerBinding("_flw_diffuseTex", 0); + program.setSamplerBinding("_flw_overlayTex", 1); + program.setSamplerBinding("_flw_lightTex", 2); + + GlProgram.unbind(); }) .harness(pipeline.compilerMarker(), sources); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/MaterialRenderState.java b/src/main/java/com/jozufozu/flywheel/backend/engine/MaterialRenderState.java index 234e70e06..0eb1636a6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/MaterialRenderState.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/MaterialRenderState.java @@ -8,9 +8,13 @@ import com.jozufozu.flywheel.api.material.DepthTest; import com.jozufozu.flywheel.api.material.Material; import com.jozufozu.flywheel.api.material.Transparency; import com.jozufozu.flywheel.api.material.WriteMask; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.AbstractTexture; + public final class MaterialRenderState { public static final Comparator COMPARATOR = Comparator.comparing(Material::texture) .thenComparing(Material::blur) @@ -25,6 +29,7 @@ public final class MaterialRenderState { } public static void setup(Material material) { + setupTexture(material); setupBackfaceCulling(material.backfaceCulling()); setupPolygonOffset(material.polygonOffset()); setupDepthTest(material.depthTest()); @@ -32,6 +37,17 @@ public final class MaterialRenderState { setupWriteMask(material.writeMask()); } + private static void setupTexture(Material material) { + GlTextureUnit.T0.makeActive(); + AbstractTexture texture = Minecraft.getInstance() + .getTextureManager() + .getTexture(material.texture()); + texture.setFilter(material.blur(), material.mipmap()); + var textureId = texture.getId(); + RenderSystem.setShaderTexture(0, textureId); + RenderSystem.bindTexture(textureId); + } + private static void setupBackfaceCulling(boolean backfaceCulling) { if (backfaceCulling) { RenderSystem.enableCull(); @@ -125,6 +141,7 @@ public final class MaterialRenderState { } public static void reset() { + resetTexture(); resetBackfaceCulling(); resetPolygonOffset(); resetDepthTest(); @@ -132,6 +149,11 @@ public final class MaterialRenderState { resetWriteMask(); } + private static void resetTexture() { + GlTextureUnit.T0.makeActive(); + RenderSystem.setShaderTexture(0, 0); + } + private static void resetBackfaceCulling() { RenderSystem.enableCull(); } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java index 365035f68..53f5093e8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectCullingGroup.java @@ -26,7 +26,7 @@ import com.jozufozu.flywheel.api.model.Model; import com.jozufozu.flywheel.backend.compile.IndirectPrograms; import com.jozufozu.flywheel.backend.engine.MaterialRenderState; import com.jozufozu.flywheel.backend.engine.textures.TextureBinder; -import com.jozufozu.flywheel.backend.engine.textures.TexturesImpl; +import com.jozufozu.flywheel.backend.engine.textures.TextureSourceImpl; import com.jozufozu.flywheel.backend.engine.uniform.Uniforms; import com.jozufozu.flywheel.backend.gl.Driver; import com.jozufozu.flywheel.backend.gl.GlCompat; @@ -185,7 +185,7 @@ public class IndirectCullingGroup { hasNewDraws = true; } - public void submit(RenderStage stage, TexturesImpl textures) { + public void submit(RenderStage stage, TextureSourceImpl textures) { if (nothingToDo(stage)) { return; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java index a520bd073..0ad8985e0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectDrawManager.java @@ -23,7 +23,8 @@ import com.jozufozu.flywheel.backend.engine.InstancerKey; import com.jozufozu.flywheel.backend.engine.InstancerStorage; import com.jozufozu.flywheel.backend.engine.MaterialRenderState; import com.jozufozu.flywheel.backend.engine.textures.TextureBinder; -import com.jozufozu.flywheel.backend.engine.textures.TexturesImpl; +import com.jozufozu.flywheel.backend.engine.textures.TextureSourceImpl; +import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; import com.jozufozu.flywheel.lib.context.ContextShaders; @@ -39,7 +40,7 @@ import net.minecraft.client.resources.model.ModelBakery; public class IndirectDrawManager extends InstancerStorage> { private final IndirectPrograms programs; private final StagingBuffer stagingBuffer; - private final TexturesImpl textures = new TexturesImpl(); + private final TextureSourceImpl textures = new TextureSourceImpl(); private final Map, IndirectCullingGroup> cullingGroups = new HashMap<>(); private final GlBuffer crumblingDrawBuffer = new GlBuffer(); @@ -71,9 +72,14 @@ public class IndirectDrawManager extends InstancerStorage> } public void renderStage(RenderStage stage) { + TextureBinder.bindLightAndOverlay(); + for (var group : cullingGroups.values()) { group.submit(stage, textures); } + + MaterialRenderState.reset(); + TextureBinder.resetLightAndOverlay(); } @Override @@ -117,50 +123,56 @@ public class IndirectDrawManager extends InstancerStorage> return; } - var crumblingMaterial = SimpleMaterial.builder(); + try (var state = GlStateTracker.getRestoreState()) { + TextureBinder.bindLightAndOverlay(); - // Scratch memory for writing draw commands. - var block = MemoryBlock.malloc(IndirectBuffers.DRAW_COMMAND_STRIDE); + var crumblingMaterial = SimpleMaterial.builder(); - GlBufferType.DRAW_INDIRECT_BUFFER.bind(crumblingDrawBuffer.handle()); - glBindBufferRange(GL_SHADER_STORAGE_BUFFER, IndirectBuffers.DRAW_INDEX, crumblingDrawBuffer.handle(), 0, IndirectBuffers.DRAW_COMMAND_STRIDE); + // Scratch memory for writing draw commands. + var block = MemoryBlock.malloc(IndirectBuffers.DRAW_COMMAND_STRIDE); - for (var instanceTypeEntry : byType.entrySet()) { - var byProgress = instanceTypeEntry.getValue(); + GlBufferType.DRAW_INDIRECT_BUFFER.bind(crumblingDrawBuffer.handle()); + glBindBufferRange(GL_SHADER_STORAGE_BUFFER, IndirectBuffers.DRAW_INDEX, crumblingDrawBuffer.handle(), 0, IndirectBuffers.DRAW_COMMAND_STRIDE); - // Set up the crumbling program buffers. Nothing changes here between draws. - var program = cullingGroups.get(instanceTypeEntry.getKey()) - .bindWithContextShader(ContextShaders.CRUMBLING); + for (var instanceTypeEntry : byType.entrySet()) { + var byProgress = instanceTypeEntry.getValue(); - for (var progressEntry : byProgress.int2ObjectEntrySet()) { - for (var instanceHandlePair : progressEntry.getValue()) { - IndirectInstancer instancer = instanceHandlePair.first(); - int instanceIndex = instanceHandlePair.second().index; + // Set up the crumbling program buffers. Nothing changes here between draws. + var program = cullingGroups.get(instanceTypeEntry.getKey()) + .bindWithContextShader(ContextShaders.CRUMBLING); - for (IndirectDraw draw : instancer.draws()) { + for (var progressEntry : byProgress.int2ObjectEntrySet()) { + for (var instanceHandlePair : progressEntry.getValue()) { + IndirectInstancer instancer = instanceHandlePair.first(); + int instanceIndex = instanceHandlePair.second().index; - // Transform the material to be suited for crumbling. - CommonCrumbling.applyCrumblingProperties(crumblingMaterial, draw.material()); - Contexts.CRUMBLING.get(progressEntry.getIntKey()) - .prepare(crumblingMaterial, program, textures); + for (IndirectDraw draw : instancer.draws()) { - // Set up gl state for the draw. - MaterialRenderState.setup(crumblingMaterial); + // Transform the material to be suited for crumbling. + CommonCrumbling.applyCrumblingProperties(crumblingMaterial, draw.material()); + var context = Contexts.CRUMBLING.get(progressEntry.getIntKey()); - // Upload the draw command. - draw.writeWithOverrides(block.ptr(), instanceIndex, crumblingMaterial); - crumblingDrawBuffer.upload(block); + context.prepare(crumblingMaterial, program, textures); + MaterialRenderState.setup(crumblingMaterial); - // Submit! Everything is already bound by here. - glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); + // Upload the draw command. + draw.writeWithOverrides(block.ptr(), instanceIndex, crumblingMaterial); + crumblingDrawBuffer.upload(block); - TextureBinder.resetTextureBindings(); + // Submit! Everything is already bound by here. + glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0); + + TextureBinder.resetTextureBindings(); + } } } } - } - block.free(); + MaterialRenderState.reset(); + TextureBinder.resetLightAndOverlay(); + + block.free(); + } } private static Map, Int2ObjectMap, InstanceHandleImpl>>>> doCrumblingSort(List crumblingBlocks) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java index f022ad107..22385b430 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/indirect/IndirectEngine.java @@ -10,7 +10,6 @@ import com.jozufozu.flywheel.backend.compile.IndirectPrograms; import com.jozufozu.flywheel.backend.engine.AbstractEngine; import com.jozufozu.flywheel.backend.engine.AbstractInstancer; import com.jozufozu.flywheel.backend.engine.InstancerStorage; -import com.jozufozu.flywheel.backend.engine.MaterialRenderState; import com.jozufozu.flywheel.backend.engine.uniform.Uniforms; import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.lib.task.Flag; @@ -55,8 +54,6 @@ public class IndirectEngine extends AbstractEngine { try (var restoreState = GlStateTracker.getRestoreState()) { drawManager.renderStage(stage); - - MaterialRenderState.reset(); } } @@ -64,11 +61,7 @@ public class IndirectEngine extends AbstractEngine { public void renderCrumbling(TaskExecutor executor, RenderContext context, List crumblingBlocks) { executor.syncUntil(flushFlag::isRaised); - try (var restoreState = GlStateTracker.getRestoreState()) { - drawManager.renderCrumbling(crumblingBlocks); - - MaterialRenderState.reset(); - } + drawManager.renderCrumbling(crumblingBlocks); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedCrumbling.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedCrumbling.java index 51db84c77..62c1629d0 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedCrumbling.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancedCrumbling.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Map; import com.jozufozu.flywheel.api.backend.Engine; -import com.jozufozu.flywheel.api.context.Textures; +import com.jozufozu.flywheel.api.context.TextureSource; import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.backend.compile.InstancingPrograms; import com.jozufozu.flywheel.backend.engine.CommonCrumbling; @@ -24,7 +24,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import net.minecraft.client.resources.model.ModelBakery; public class InstancedCrumbling { - public static void render(List crumblingBlocks, InstancingPrograms programs, Textures textures) { + public static void render(List crumblingBlocks, InstancingPrograms programs, TextureSource textureSource) { // Sort draw calls into buckets, so we don't have to do as many shader binds. var byShaderState = doCrumblingSort(crumblingBlocks); @@ -35,6 +35,8 @@ public class InstancedCrumbling { var crumblingMaterial = SimpleMaterial.builder(); try (var state = GlStateTracker.getRestoreState()) { + TextureBinder.bindLightAndOverlay(); + for (var shaderStateEntry : byShaderState.entrySet()) { var byProgress = shaderStateEntry.getValue(); @@ -61,8 +63,8 @@ public class InstancedCrumbling { continue; } - Contexts.CRUMBLING.get(progressEntry.getIntKey()) - .prepare(crumblingMaterial, program, textures); + var context = Contexts.CRUMBLING.get(progressEntry.getIntKey()); + context.prepare(crumblingMaterial, program, textureSource); drawCalls.forEach(Runnable::run); @@ -71,6 +73,7 @@ public class InstancedCrumbling { } MaterialRenderState.reset(); + TextureBinder.resetLightAndOverlay(); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java index 51dd214a4..f7596922d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/instancing/InstancingEngine.java @@ -17,7 +17,7 @@ import com.jozufozu.flywheel.backend.engine.InstancerStorage; import com.jozufozu.flywheel.backend.engine.MaterialEncoder; import com.jozufozu.flywheel.backend.engine.MaterialRenderState; import com.jozufozu.flywheel.backend.engine.textures.TextureBinder; -import com.jozufozu.flywheel.backend.engine.textures.TexturesImpl; +import com.jozufozu.flywheel.backend.engine.textures.TextureSourceImpl; import com.jozufozu.flywheel.backend.engine.uniform.Uniforms; import com.jozufozu.flywheel.backend.gl.GlStateTracker; import com.jozufozu.flywheel.backend.gl.shader.GlProgram; @@ -27,7 +27,7 @@ import com.jozufozu.flywheel.lib.task.SyncedPlan; public class InstancingEngine extends AbstractEngine { private final InstancingPrograms programs; - private final TexturesImpl textures = new TexturesImpl(); + private final TextureSourceImpl textures = new TextureSourceImpl(); private final InstancedDrawManager drawManager = new InstancedDrawManager(); private final Flag flushFlag = new NamedFlag("flushed"); @@ -88,6 +88,8 @@ public class InstancingEngine extends AbstractEngine { } private void render(InstancedDrawManager.DrawSet drawSet) { + TextureBinder.bindLightAndOverlay(); + for (var entry : drawSet) { var shader = entry.getKey(); var drawCalls = entry.getValue(); @@ -98,16 +100,17 @@ public class InstancingEngine extends AbstractEngine { continue; } - var program = programs.get(shader.instanceType(), shader.context() - .contextShader()); + var context = shader.context(); + var material = shader.material(); + + var program = programs.get(shader.instanceType(), context.contextShader()); program.bind(); Uniforms.bindForDraw(); - uploadMaterialUniform(program, shader.material()); + uploadMaterialUniform(program, material); - shader.context() - .prepare(shader.material(), program, textures); - MaterialRenderState.setup(shader.material()); + context.prepare(material, program, textures); + MaterialRenderState.setup(material); for (var drawCall : drawCalls) { drawCall.render(); @@ -116,6 +119,7 @@ public class InstancingEngine extends AbstractEngine { } MaterialRenderState.reset(); + TextureBinder.resetLightAndOverlay(); } public static void uploadMaterialUniform(GlProgram program, Material material) { diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureBinder.java b/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureBinder.java index 982ee3341..6b7c2c2e9 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureBinder.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureBinder.java @@ -2,16 +2,23 @@ package com.jozufozu.flywheel.backend.engine.textures; import static org.lwjgl.opengl.GL13.GL_TEXTURE0; +import com.jozufozu.flywheel.backend.gl.GlTextureUnit; import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; import it.unimi.dsi.fastutil.ints.Int2IntMap; +import net.minecraft.client.Minecraft; public class TextureBinder { // TODO: some kind of cache eviction when the program changes // so we don't always reset and bind the light and overlay textures? private static final Int2IntMap texturesToSamplerUnits = new Int2IntArrayMap(); - private static int nextSamplerUnit = 0; + // 0 is reserved for diffuse + // 1 is overlay + // 2 is light + // 3..n are for whatever else the context needs + private static final int baseSamplerUnit = 3; + private static int nextSamplerUnit = baseSamplerUnit; /** * Binds the given texture to the next available texture unit, returning the unit it was bound to. @@ -29,7 +36,7 @@ public class TextureBinder { } public static void resetTextureBindings() { - nextSamplerUnit = 0; + nextSamplerUnit = baseSamplerUnit; for (Int2IntMap.Entry entry : texturesToSamplerUnits.int2IntEntrySet()) { RenderSystem.activeTexture(GL_TEXTURE0 + entry.getIntValue()); @@ -38,4 +45,26 @@ public class TextureBinder { texturesToSamplerUnits.clear(); } + + public static void bindLightAndOverlay() { + var gameRenderer = Minecraft.getInstance().gameRenderer; + gameRenderer.overlayTexture() + .setupOverlayColor(); + gameRenderer.lightTexture() + .turnOnLightLayer(); + + GlTextureUnit.T1.makeActive(); + RenderSystem.bindTexture(RenderSystem.getShaderTexture(1)); + GlTextureUnit.T2.makeActive(); + RenderSystem.bindTexture(RenderSystem.getShaderTexture(2)); + } + + public static void resetLightAndOverlay() { + var gameRenderer = Minecraft.getInstance().gameRenderer; + + gameRenderer.overlayTexture() + .teardownOverlayColor(); + gameRenderer.lightTexture() + .turnOffLightLayer(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TexturesImpl.java b/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureSourceImpl.java similarity index 92% rename from src/main/java/com/jozufozu/flywheel/backend/engine/textures/TexturesImpl.java rename to src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureSourceImpl.java index 0c4e52465..ad0e00d18 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TexturesImpl.java +++ b/src/main/java/com/jozufozu/flywheel/backend/engine/textures/TextureSourceImpl.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; import com.jozufozu.flywheel.api.context.Texture; -import com.jozufozu.flywheel.api.context.Textures; +import com.jozufozu.flywheel.api.context.TextureSource; import com.jozufozu.flywheel.backend.mixin.LightTextureAccessor; import com.jozufozu.flywheel.backend.mixin.OverlayTextureAccessor; @@ -12,13 +12,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.resources.ResourceLocation; -public class TexturesImpl implements Textures { +public class TextureSourceImpl implements TextureSource { private final DirectTexture lightTexture; private final DirectTexture overlayTexture; private final Map wrappers = new HashMap<>(); - public TexturesImpl() { + public TextureSourceImpl() { var gameRenderer = Minecraft.getInstance().gameRenderer; this.lightTexture = new DirectTexture(((LightTextureAccessor) gameRenderer.lightTexture()).flywheel$texture() diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java index 5c1665fd0..96ad85df7 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/shader/GlProgram.java @@ -2,11 +2,17 @@ package com.jozufozu.flywheel.backend.gl.shader; import static org.lwjgl.opengl.GL20.glDeleteProgram; import static org.lwjgl.opengl.GL20.glGetUniformLocation; +import static org.lwjgl.opengl.GL20.glUniform1f; import static org.lwjgl.opengl.GL20.glUniform1i; +import static org.lwjgl.opengl.GL20.glUniform2f; +import static org.lwjgl.opengl.GL20.glUniform3f; +import static org.lwjgl.opengl.GL20.glUniform4f; +import static org.lwjgl.opengl.GL20.glUniformMatrix4fv; import static org.lwjgl.opengl.GL31.GL_INVALID_INDEX; import static org.lwjgl.opengl.GL31.glGetUniformBlockIndex; import static org.lwjgl.opengl.GL31.glUniformBlockBinding; +import org.joml.Matrix4fc; import org.slf4j.Logger; import com.jozufozu.flywheel.api.context.Shader; @@ -39,6 +45,8 @@ public class GlProgram extends GlObject implements Shader { @Override public void setTexture(String glslName, Texture texture) { + throwIfReserved(glslName); + if (!(texture instanceof IdentifiedTexture identified)) { return; } @@ -55,6 +63,71 @@ public class GlProgram extends GlObject implements Shader { glUniform1i(uniform, binding); } + @Override + public void setFloat(String glslName, float value) { + throwIfReserved(glslName); + + int uniform = getUniformLocation(glslName); + + if (uniform < 0) { + return; + } + + glUniform1f(uniform, value); + } + + @Override + public void setVec2(String glslName, float x, float y) { + throwIfReserved(glslName); + + int uniform = getUniformLocation(glslName); + + if (uniform < 0) { + return; + } + + glUniform2f(uniform, x, y); + } + + @Override + public void setVec3(String glslName, float x, float y, float z) { + throwIfReserved(glslName); + + int uniform = getUniformLocation(glslName); + + if (uniform < 0) { + return; + } + + glUniform3f(uniform, x, y, z); + } + + @Override + public void setVec4(String glslName, float x, float y, float z, float w) { + throwIfReserved(glslName); + + int uniform = getUniformLocation(glslName); + + if (uniform < 0) { + return; + } + + glUniform4f(uniform, x, y, z, w); + } + + @Override + public void setMat4(String glslName, Matrix4fc matrix) { + throwIfReserved(glslName); + + int uniform = getUniformLocation(glslName); + + if (uniform < 0) { + return; + } + + glUniformMatrix4fv(uniform, false, matrix.get(new float[16])); + } + /** * Retrieves the index of the uniform with the given name. * @@ -101,4 +174,18 @@ public class GlProgram extends GlObject implements Shader { protected void deleteInternal(int handle) { glDeleteProgram(handle); } + + public static void throwIfReserved(String glslName) { + if (glslName.startsWith("flw_")) { + throw new IllegalArgumentException("Uniform names starting with flw_are reserved"); + } + + if (glslName.startsWith("_flw_")) { + throw new IllegalArgumentException("Uniform names starting with _flw_ are reserved for internal use"); + } + + if (glslName.startsWith("gl_")) { + throw new IllegalArgumentException("Uniform names cannot start with gl_"); + } + } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java b/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java index 523dd2729..60a227f59 100644 --- a/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java +++ b/src/main/java/com/jozufozu/flywheel/lib/context/Contexts.java @@ -1,10 +1,6 @@ package com.jozufozu.flywheel.lib.context; import com.jozufozu.flywheel.api.context.Context; -import com.jozufozu.flywheel.api.context.ContextShader; -import com.jozufozu.flywheel.api.context.Shader; -import com.jozufozu.flywheel.api.context.Textures; -import com.jozufozu.flywheel.api.material.Material; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -12,22 +8,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import net.minecraft.client.resources.model.ModelBakery; public final class Contexts { - public static final Context DEFAULT = new Context() { - @Override - public ContextShader contextShader() { - return ContextShaders.DEFAULT; - } - - @Override - public void prepare(Material material, Shader shader, Textures textures) { - var texture = textures.byName(material.texture()); - texture.filter(material.blur(), material.mipmap()); - shader.setTexture("_flw_diffuseTex", texture); - - shader.setTexture("_flw_overlayTex", textures.overlay()); - shader.setTexture("_flw_lightTex", textures.light()); - } - }; + public static final Context DEFAULT = SimpleContext.builder(ContextShaders.DEFAULT) + .build(); public static final Int2ObjectMap CRUMBLING; @@ -35,7 +17,12 @@ public final class Contexts { var map = new Int2ObjectArrayMap(); for (int i = 0; i < ModelBakery.BREAKING_LOCATIONS.size(); i++) { - map.put(i, new Crumbling(i)); + var crumblingLocation = ModelBakery.BREAKING_LOCATIONS.get(i); + map.put(i, SimpleContext.builder(ContextShaders.CRUMBLING) + .preparation((material, shader, textureSource) -> { + shader.setTexture("crumblingTex", textureSource.byName(crumblingLocation)); + }) + .build()); } CRUMBLING = Int2ObjectMaps.unmodifiable(map); @@ -43,21 +30,4 @@ public final class Contexts { private Contexts() { } - - private record Crumbling(int stage) implements Context { - @Override - public ContextShader contextShader() { - return ContextShaders.CRUMBLING; - } - - @Override - public void prepare(Material material, Shader shader, Textures textures) { - var texture = textures.byName(material.texture()); - texture.filter(material.blur(), material.mipmap()); - shader.setTexture("_flw_diffuseTex", texture); - - var crumblingTexture = textures.byName(ModelBakery.BREAKING_LOCATIONS.get(stage)); - shader.setTexture("_flw_crumblingTex", crumblingTexture); - } - } } diff --git a/src/main/java/com/jozufozu/flywheel/lib/context/SimpleContext.java b/src/main/java/com/jozufozu/flywheel/lib/context/SimpleContext.java new file mode 100644 index 000000000..ecb8a2092 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/lib/context/SimpleContext.java @@ -0,0 +1,61 @@ +package com.jozufozu.flywheel.lib.context; + +import org.jetbrains.annotations.Nullable; + +import com.jozufozu.flywheel.api.context.Context; +import com.jozufozu.flywheel.api.context.ContextShader; +import com.jozufozu.flywheel.api.context.Shader; +import com.jozufozu.flywheel.api.context.TextureSource; +import com.jozufozu.flywheel.api.material.Material; + +public class SimpleContext implements Context { + private final ContextShader contextShader; + private final Preparation preparation; + + public SimpleContext(ContextShader contextShader, Preparation preparation) { + this.contextShader = contextShader; + this.preparation = preparation; + } + + public static Builder builder(ContextShader contextShader) { + return new Builder(contextShader); + } + + @Override + public ContextShader contextShader() { + return contextShader; + } + + @Override + public void prepare(Material material, Shader shader, TextureSource textureSource) { + preparation.prepare(material, shader, textureSource); + } + + @FunctionalInterface + public interface Preparation { + void prepare(Material material, Shader shader, TextureSource textureSource); + } + + public static class Builder { + private final ContextShader contextShader; + @Nullable + private Preparation preparation; + + public Builder(ContextShader contextShader) { + this.contextShader = contextShader; + } + + public Builder preparation(Preparation preparation) { + this.preparation = preparation; + return this; + } + + public SimpleContext build() { + if (preparation == null) { + preparation = (material, shader, textureSource) -> { + }; + } + return new SimpleContext(contextShader, preparation); + } + } +} diff --git a/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag b/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag index a722816bb..b54238745 100644 --- a/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag +++ b/src/main/resources/assets/flywheel/flywheel/context/crumbling.frag @@ -1,4 +1,4 @@ -uniform sampler2D _flw_crumblingTex; +uniform sampler2D crumblingTex; in vec2 crumblingTexCoord; @@ -8,7 +8,7 @@ void flw_beginFragment() { } void flw_endFragment() { - crumblingSampleColor = texture(_flw_crumblingTex, crumblingTexCoord); + crumblingSampleColor = texture(crumblingTex, crumblingTexCoord); // Make the crumbling overlay transparent when the fragment color after the material shader is transparent. flw_fragColor.rgb = crumblingSampleColor.rgb;