Materials and You: Volume 3

- Add material properties
  - depthTest
  - useOverlay
- Rename some material properties
  - mip -> mipmap
  - backfaceCull -> backfaceCulling
  - lighting -> useLight
- Fix InstancingEngine and IndirectEngine not binding overlay texture
and setting unnecessary render state
- Fix indirect internal shaders applying light twice
- Fix internal shaders using removed ALPHA_CUTOFF define
- Rename some variables and functions in shader files
- Separate MaterialUtil into MaterialRenderState and MaterialEncoder
- Delete unused Textures class
This commit is contained in:
PepperCode1 2023-12-03 18:13:39 -08:00
parent 473e5e852f
commit dfd27fc968
31 changed files with 791 additions and 600 deletions

View file

@ -0,0 +1,13 @@
package com.jozufozu.flywheel.api.material;
public enum DepthTest {
OFF,
NEVER,
LESS,
EQUAL,
LEQUAL,
GREATER,
NOTEQUAL,
GEQUAL,
ALWAYS,
}

View file

@ -10,22 +10,12 @@ public interface Material {
MaterialShaders shaders();
FogShader fog();
CutoutShader cutout();
ResourceLocation baseTexture();
/**
* Should this material be rendered with diffuse lighting?
*
* @return {@code true} if this material should be rendered with diffuse lighting.
*/
boolean diffuse();
/**
* Should this material be rendered with block/sky lighting?
*
* @return {@code true} if this material should be rendered with block/sky lighting.
*/
boolean lighting();
/**
* Should this material have linear filtering applied to the diffuse sampler?
*
@ -33,22 +23,36 @@ public interface Material {
*/
boolean blur();
boolean mipmap();
/**
* Should this material be rendered with backface culling?
*
* @return {@code true} if this material should be rendered with backface culling.
*/
boolean backfaceCull();
boolean backfaceCulling();
boolean polygonOffset();
boolean mip();
FogShader fog();
CutoutShader cutout();
DepthTest depthTest();
Transparency transparency();
WriteMask writeMask();
boolean useOverlay();
/**
* Should this material be rendered with block/sky lighting?
*
* @return {@code true} if this material should be rendered with block/sky lighting.
*/
boolean useLight();
/**
* Should this material be rendered with diffuse lighting?
*
* @return {@code true} if this material should be rendered with diffuse lighting.
*/
boolean diffuse();
}

View file

@ -0,0 +1,84 @@
package com.jozufozu.flywheel.backend;
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 net.minecraft.util.Mth;
// Materials are unpacked in "flywheel:flywheel/internal/material.glsl"
public final class MaterialEncoder {
// The number of bits each property takes up
private static final int BLUR_LENGTH = 1;
private static final int MIPMAP_LENGTH = 1;
private static final int BACKFACE_CULLING_LENGTH = 1;
private static final int POLYGON_OFFSET_LENGTH = 1;
private static final int DEPTH_TEST_LENGTH = Mth.ceillog2(DepthTest.values().length);
private static final int TRANSPARENCY_LENGTH = Mth.ceillog2(Transparency.values().length);
private static final int WRITE_MASK_LENGTH = Mth.ceillog2(WriteMask.values().length);
private static final int USE_OVERLAY_LENGTH = 1;
private static final int USE_LIGHT_LENGTH = 1;
private static final int DIFFUSE_LENGTH = 1;
// The bit offset of each property
private static final int BLUR_OFFSET = 0;
private static final int MIPMAP_OFFSET = BLUR_OFFSET + BLUR_LENGTH;
private static final int BACKFACE_CULLING_OFFSET = MIPMAP_OFFSET + MIPMAP_LENGTH;
private static final int POLYGON_OFFSET_OFFSET = BACKFACE_CULLING_OFFSET + BACKFACE_CULLING_LENGTH;
private static final int DEPTH_TEST_OFFSET = POLYGON_OFFSET_OFFSET + POLYGON_OFFSET_LENGTH;
private static final int TRANSPARENCY_OFFSET = DEPTH_TEST_OFFSET + DEPTH_TEST_LENGTH;
private static final int WRITE_MASK_OFFSET = TRANSPARENCY_OFFSET + TRANSPARENCY_LENGTH;
private static final int USE_OVERLAY_OFFSET = WRITE_MASK_OFFSET + WRITE_MASK_LENGTH;
private static final int USE_LIGHT_OFFSET = USE_OVERLAY_OFFSET + USE_OVERLAY_LENGTH;
private static final int DIFFUSE_OFFSET = USE_LIGHT_OFFSET + USE_LIGHT_LENGTH;
// The bit mask for each property
private static final int BLUR_MASK = bitMask(BLUR_LENGTH, BLUR_OFFSET);
private static final int MIPMAP_MASK = bitMask(MIPMAP_LENGTH, MIPMAP_OFFSET);
private static final int BACKFACE_CULLING_MASK = bitMask(BACKFACE_CULLING_LENGTH, BACKFACE_CULLING_OFFSET);
private static final int POLYGON_OFFSET_MASK = bitMask(POLYGON_OFFSET_LENGTH, POLYGON_OFFSET_OFFSET);
private static final int DEPTH_TEST_MASK = bitMask(DEPTH_TEST_LENGTH, DEPTH_TEST_OFFSET);
private static final int TRANSPARENCY_MASK = bitMask(TRANSPARENCY_LENGTH, TRANSPARENCY_OFFSET);
private static final int WRITE_MASK_MASK = bitMask(WRITE_MASK_LENGTH, WRITE_MASK_OFFSET);
private static final int USE_OVERLAY_MASK = bitMask(USE_OVERLAY_LENGTH, USE_OVERLAY_OFFSET);
private static final int USE_LIGHT_MASK = bitMask(USE_LIGHT_LENGTH, USE_LIGHT_OFFSET);
private static final int DIFFUSE_MASK = bitMask(DIFFUSE_LENGTH, DIFFUSE_OFFSET);
private MaterialEncoder() {
}
private static int bitMask(int bitLength, int bitOffset) {
return ((1 << bitLength) - 1) << bitOffset;
}
public static int packFogAndCutout(Material material) {
var fog = ShaderIndices.fog()
.index(material.fog()
.source());
var cutout = ShaderIndices.cutout()
.index(material.cutout()
.source());
return fog & 0xFFFF | (cutout & 0xFFFF) << 16;
}
// Packed format:
// diffuse[1] | useOverlay[1] | useLight[1] | writeMask[2] | transparency[3] | depthTest[4] | polygonOffset[1] | backfaceCulling[1] | mipmap[1] | blur[1]
public static int packProperties(Material material) {
int bits = 0;
if (material.blur()) bits |= BLUR_MASK;
if (material.mipmap()) bits |= MIPMAP_MASK;
if (material.backfaceCulling()) bits |= BACKFACE_CULLING_MASK;
if (material.polygonOffset()) bits |= POLYGON_OFFSET_MASK;
bits |= (material.depthTest().ordinal() << DEPTH_TEST_OFFSET) & DEPTH_TEST_MASK;
bits |= (material.transparency().ordinal() << TRANSPARENCY_OFFSET) & TRANSPARENCY_MASK;
bits |= (material.writeMask().ordinal() << WRITE_MASK_OFFSET) & WRITE_MASK_MASK;
if (material.useOverlay()) bits |= USE_OVERLAY_MASK;
if (material.useLight()) bits |= USE_LIGHT_MASK;
if (material.diffuse()) bits |= DIFFUSE_MASK;
return bits;
}
}

View file

@ -0,0 +1,180 @@
package com.jozufozu.flywheel.backend;
import java.util.Comparator;
import org.lwjgl.opengl.GL11;
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.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<Material> COMPARATOR = Comparator.comparing(Material::baseTexture)
.thenComparing(Material::blur)
.thenComparing(Material::mipmap)
.thenComparing(Material::backfaceCulling)
.thenComparing(Material::polygonOffset)
.thenComparing(Material::depthTest)
.thenComparing(Material::transparency)
.thenComparing(Material::writeMask);
private MaterialRenderState() {
}
public static void setup(Material material) {
setupTexture(material);
setupBackfaceCulling(material.backfaceCulling());
setupPolygonOffset(material.polygonOffset());
setupDepthTest(material.depthTest());
setupTransparency(material.transparency());
setupWriteMask(material.writeMask());
}
private static void setupTexture(Material material) {
GlTextureUnit.T0.makeActive();
AbstractTexture texture = Minecraft.getInstance()
.getTextureManager()
.getTexture(material.baseTexture());
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();
} else {
RenderSystem.disableCull();
}
}
private static void setupPolygonOffset(boolean polygonOffset) {
if (polygonOffset) {
RenderSystem.polygonOffset(-1.0F, -10.0F);
RenderSystem.enablePolygonOffset();
} else {
RenderSystem.polygonOffset(0.0F, 0.0F);
RenderSystem.enablePolygonOffset();
}
}
private static void setupDepthTest(DepthTest depthTest) {
switch (depthTest) {
case OFF -> {
RenderSystem.disableDepthTest();
}
case NEVER -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_NEVER);
}
case LESS -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_LESS);
}
case EQUAL -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_EQUAL);
}
case LEQUAL -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_LEQUAL);
}
case GREATER -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_GREATER);
}
case NOTEQUAL -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_NOTEQUAL);
}
case GEQUAL -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_GEQUAL);
}
case ALWAYS -> {
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL11.GL_ALWAYS);
}
}
}
private static void setupTransparency(Transparency transparency) {
switch (transparency) {
case OPAQUE -> {
RenderSystem.disableBlend();
}
case ADDITIVE -> {
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
}
case LIGHTING -> {
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE);
}
case GLINT -> {
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_COLOR, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
}
case CRUMBLING -> {
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.DST_COLOR, GlStateManager.DestFactor.SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
}
case TRANSLUCENT -> {
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
}
}
}
private static void setupWriteMask(WriteMask mask) {
RenderSystem.depthMask(mask.depth());
boolean writeColor = mask.color();
RenderSystem.colorMask(writeColor, writeColor, writeColor, writeColor);
}
public static void reset() {
resetTexture();
resetBackfaceCulling();
resetPolygonOffset();
resetDepthTest();
resetTransparency();
resetWriteMask();
}
private static void resetTexture() {
GlTextureUnit.T0.makeActive();
RenderSystem.setShaderTexture(0, 0);
}
private static void resetBackfaceCulling() {
RenderSystem.enableCull();
}
private static void resetPolygonOffset() {
RenderSystem.polygonOffset(0.0F, 0.0F);
RenderSystem.disablePolygonOffset();
}
private static void resetDepthTest() {
RenderSystem.disableDepthTest();
RenderSystem.depthFunc(GL11.GL_LEQUAL);
}
private static void resetTransparency() {
RenderSystem.disableBlend();
RenderSystem.defaultBlendFunc();
}
private static void resetWriteMask() {
RenderSystem.depthMask(true);
RenderSystem.colorMask(true, true, true, true);
}
}

View file

@ -1,147 +0,0 @@
package com.jozufozu.flywheel.backend;
import java.util.Comparator;
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.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 class MaterialUtil {
public static final Comparator<Material> BY_STATE = Comparator.comparing(Material::baseTexture)
.thenComparing(Material::mip)
.thenComparing(Material::blur)
.thenComparing(Material::backfaceCull)
.thenComparing(Material::polygonOffset)
.thenComparing(Material::writeMask);
public static void setup(Material material) {
setupTexture(material);
setupBackfaceCull(material.backfaceCull());
setupTransparency(material.transparency());
setupWriteMask(material.writeMask());
setupPolygonOffset(material.polygonOffset());
}
private static void setupPolygonOffset(boolean polygonOffset) {
if (polygonOffset) {
RenderSystem.polygonOffset(-1.0F, -10.0F);
RenderSystem.enablePolygonOffset();
}
}
private static void setupWriteMask(WriteMask mask) {
RenderSystem.depthMask(mask.depth());
boolean writeColor = mask.color();
RenderSystem.colorMask(writeColor, writeColor, writeColor, writeColor);
}
private static void setupTransparency(Transparency transparency) {
if (transparency != Transparency.OPAQUE) {
RenderSystem.enableBlend();
}
switch (transparency) {
case ADDITIVE -> RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE);
case LIGHTING -> RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE);
case GLINT ->
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_COLOR, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
case CRUMBLING ->
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.DST_COLOR, GlStateManager.DestFactor.SRC_COLOR, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO);
case TRANSLUCENT ->
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
}
}
private static void setupBackfaceCull(boolean backfaceCull) {
if (!backfaceCull) {
RenderSystem.disableCull();
}
}
private static void setupTexture(Material material) {
GlTextureUnit.T0.makeActive();
AbstractTexture texture = Minecraft.getInstance()
.getTextureManager()
.getTexture(material.baseTexture());
var textureId = texture.getId();
texture.setFilter(material.blur(), material.mip());
RenderSystem.setShaderTexture(0, textureId);
RenderSystem.bindTexture(textureId);
}
public static void reset() {
resetDiffuse();
resetBackfaceCull();
resetTransparency();
resetWriteMask();
resetPolygonOffset();
}
private static void resetPolygonOffset() {
RenderSystem.polygonOffset(0.0F, 0.0F);
RenderSystem.disablePolygonOffset();
}
private static void resetWriteMask() {
RenderSystem.depthMask(true);
RenderSystem.colorMask(true, true, true, true);
}
private static void resetTransparency() {
RenderSystem.disableBlend();
RenderSystem.defaultBlendFunc();
}
private static void resetBackfaceCull() {
RenderSystem.enableCull();
}
private static void resetDiffuse() {
GlTextureUnit.T0.makeActive();
RenderSystem.setShaderTexture(0, 0);
}
public static final int DIFFUSE_MASK = 1;
public static final int LIGHTING_MASK = 1 << 1;
public static final int BLUR_MASK = 1 << 2;
public static final int BACKFACE_CULL_MASK = 1 << 3;
public static final int POLYGON_OFFSET_MASK = 1 << 4;
public static final int MIP_MASK = 1 << 5;
public static int packProperties(Material material) {
int out = 0;
if (material.diffuse()) out |= DIFFUSE_MASK;
if (material.lighting()) out |= LIGHTING_MASK;
if (material.blur()) out |= BLUR_MASK;
if (material.backfaceCull()) out |= BACKFACE_CULL_MASK;
if (material.polygonOffset()) out |= POLYGON_OFFSET_MASK;
if (material.mip()) out |= MIP_MASK;
out |= (material.writeMask()
.ordinal() & 0x3) << 6;
out |= (material.transparency()
.ordinal() & 0x7) << 8;
return out;
}
public static int packFogAndCutout(Material material) {
var fog = ShaderIndices.fog()
.index(material.fog()
.source());
var cutout = ShaderIndices.cutout()
.index(material.cutout()
.source());
return fog & 0xFFFF | (cutout & 0xFFFF) << 16;
}
}

View file

@ -19,8 +19,8 @@ import net.minecraft.resources.ResourceLocation;
public final class ShaderIndices {
private static Index vertexShaders;
private static Index fragmentShaders;
private static Index cutoutShaders;
private static Index fogShaders;
private static Index cutoutShaders;
private ShaderIndices() {
}
@ -39,13 +39,6 @@ public final class ShaderIndices {
return fragmentShaders;
}
public static Index cutout() {
if (cutoutShaders == null) {
throw new IllegalStateException("Not initialized!");
}
return cutoutShaders;
}
public static Index fog() {
if (fogShaders == null) {
throw new IllegalStateException("Not initialized!");
@ -53,12 +46,11 @@ public final class ShaderIndices {
return fogShaders;
}
public static int getCutoutShaderIndex(CutoutShader cutoutShader) {
return cutout().index(cutoutShader.source());
}
public static int getFogShaderIndex(FogShader fogShader) {
return fog().index(fogShader.source());
public static Index cutout() {
if (cutoutShaders == null) {
throw new IllegalStateException("Not initialized!");
}
return cutoutShaders;
}
public static int getVertexShaderIndex(MaterialShaders shaders) {
@ -69,6 +61,14 @@ public final class ShaderIndices {
return materialFragment().index(shaders.fragmentShader());
}
public static int getFogShaderIndex(FogShader fogShader) {
return fog().index(fogShader.source());
}
public static int getCutoutShaderIndex(CutoutShader cutoutShader) {
return cutout().index(cutoutShader.source());
}
private static void initMaterialShaders() {
int amount = MaterialShaders.REGISTRY.getAll()
.size();
@ -85,19 +85,6 @@ public final class ShaderIndices {
ShaderIndices.fragmentShaders = fragmentShaders.build();
}
private static void initCutoutShaders() {
int amount = CutoutShader.REGISTRY.getAll()
.size();
var cutout = new IndexBuilder(amount);
for (CutoutShader shaders : CutoutShader.REGISTRY) {
cutout.add(shaders.source());
}
ShaderIndices.cutoutShaders = cutout.build();
}
private static void initFogShaders() {
int amount = FogShader.REGISTRY.getAll()
.size();
@ -111,10 +98,23 @@ public final class ShaderIndices {
ShaderIndices.fogShaders = fog.build();
}
private static void initCutoutShaders() {
int amount = CutoutShader.REGISTRY.getAll()
.size();
var cutout = new IndexBuilder(amount);
for (CutoutShader shaders : CutoutShader.REGISTRY) {
cutout.add(shaders.source());
}
ShaderIndices.cutoutShaders = cutout.build();
}
public static void init() {
MaterialShaders.REGISTRY.addFreezeCallback(ShaderIndices::initMaterialShaders);
CutoutShader.REGISTRY.addFreezeCallback(ShaderIndices::initCutoutShaders);
FogShader.REGISTRY.addFreezeCallback(ShaderIndices::initFogShaders);
CutoutShader.REGISTRY.addFreezeCallback(ShaderIndices::initCutoutShaders);
}
public static class Index {
@ -163,21 +163,3 @@ public final class ShaderIndices {
}
}
}

View file

@ -6,7 +6,6 @@ import org.joml.Vector3f;
import org.joml.Vector4f;
import com.jozufozu.flywheel.api.vertex.MutableVertexList;
import com.jozufozu.flywheel.api.vertex.ReusableVertexList;
import com.jozufozu.flywheel.lib.vertex.VertexTransformations;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
@ -31,7 +30,7 @@ public class BatchingTransforms {
*
* @param vertexList The vertex list to apply the transformations to.
*/
public static void applyDecalUVs(ReusableVertexList vertexList) {
public static void applyDecalUVs(MutableVertexList vertexList) {
Vector3f normal = new Vector3f();
Vector4f pos = new Vector4f();

View file

@ -5,7 +5,7 @@ import org.lwjgl.system.MemoryUtil;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.MaterialUtil;
import com.jozufozu.flywheel.backend.MaterialEncoder;
import com.jozufozu.flywheel.backend.ShaderIndices;
public class IndirectDraw<I extends Instance> {
@ -30,8 +30,8 @@ public class IndirectDraw<I extends Instance> {
this.vertexMaterialID = ShaderIndices.getVertexShaderIndex(material.shaders());
this.fragmentMaterialID = ShaderIndices.getFragmentShaderIndex(material.shaders());
this.packedFogAndCutout = MaterialUtil.packFogAndCutout(material);
this.packedMaterialProperties = MaterialUtil.packProperties(material);
this.packedFogAndCutout = MaterialEncoder.packFogAndCutout(material);
this.packedMaterialProperties = MaterialEncoder.packProperties(material);
}
public IndirectInstancer<I> instancer() {

View file

@ -13,7 +13,7 @@ import java.util.Map;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.backend.MaterialUtil;
import com.jozufozu.flywheel.backend.MaterialRenderState;
public class IndirectDrawSet<I extends Instance> {
@ -42,14 +42,13 @@ public class IndirectDrawSet<I extends Instance> {
for (var multiDraw : multiDraws.get(stage)) {
multiDraw.submit();
}
MaterialUtil.reset();
}
public void determineMultiDraws() {
multiDraws.clear();
// sort by stage, then material
indirectDraws.sort(Comparator.comparing(IndirectDraw<I>::stage)
.thenComparing(IndirectDraw::material, MaterialUtil.BY_STATE));
.thenComparing(IndirectDraw::material, MaterialRenderState.COMPARATOR));
for (int start = 0, i = 0; i < indirectDraws.size(); i++) {
var draw = indirectDraws.get(i);
@ -73,7 +72,7 @@ public class IndirectDrawSet<I extends Instance> {
private record MultiDraw(Material material, int start, int end) {
void submit() {
MaterialUtil.setup(material);
MaterialRenderState.setup(material);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, start * IndirectBuffers.DRAW_COMMAND_STRIDE, end - start, (int) IndirectBuffers.DRAW_COMMAND_STRIDE);
}
}

View file

@ -2,12 +2,11 @@ package com.jozufozu.flywheel.backend.engine.indirect;
import java.util.List;
import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.event.RenderContext;
import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.MaterialRenderState;
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
import com.jozufozu.flywheel.backend.engine.AbstractInstancer;
import com.jozufozu.flywheel.backend.engine.InstancerStorage;
@ -16,6 +15,7 @@ import com.jozufozu.flywheel.gl.GlTextureUnit;
import com.jozufozu.flywheel.lib.task.Flag;
import com.jozufozu.flywheel.lib.task.NamedFlag;
import com.jozufozu.flywheel.lib.task.SyncedPlan;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
@ -47,35 +47,37 @@ public class IndirectEngine extends AbstractEngine {
flushFlag.lower();
}
if (!drawManager.hasStage(stage)) {
return;
}
if (!drawManager.hasStage(stage)) {
return;
}
try (var restoreState = GlStateTracker.getRestoreState()) {
setup();
try (var restoreState = GlStateTracker.getRestoreState()) {
int prevActiveTexture = GlStateManager._getActiveTexture();
Minecraft.getInstance().gameRenderer.overlayTexture().setupOverlayColor();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
for (var list : drawManager.renderLists.values()) {
list.submit(stage);
}
}
}
GlTextureUnit.T1.makeActive();
RenderSystem.bindTexture(RenderSystem.getShaderTexture(1));
GlTextureUnit.T2.makeActive();
RenderSystem.bindTexture(RenderSystem.getShaderTexture(2));
for (var list : drawManager.renderLists.values()) {
list.submit(stage);
}
MaterialRenderState.reset();
Minecraft.getInstance().gameRenderer.overlayTexture().teardownOverlayColor();
Minecraft.getInstance().gameRenderer.lightTexture().turnOffLightLayer();
GlStateManager._activeTexture(prevActiveTexture);
}
}
@Override
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
// TODO: implement
}
private void setup() {
GlTextureUnit.T2.makeActive();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
RenderSystem.depthMask(true);
RenderSystem.colorMask(true, true, true, true);
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL32.GL_LEQUAL);
RenderSystem.enableCull();
}
@Override
protected InstancerStorage<? extends AbstractInstancer<?>> getStorage() {
return drawManager;

View file

@ -1,20 +0,0 @@
package com.jozufozu.flywheel.backend.engine.indirect;
import org.lwjgl.opengl.GL32;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.renderer.RenderType;
public class Textures {
/**
* Call this after calling {@link RenderType#setupRenderState()}.
*/
public static void bindActiveTextures() {
for (int i = 0; i < 12; i++) {
int shaderTexture = RenderSystem.getShaderTexture(i);
RenderSystem.activeTexture(GL32.GL_TEXTURE0 + i);
RenderSystem.bindTexture(shaderTexture);
}
}
}

View file

@ -12,7 +12,7 @@ import com.jozufozu.flywheel.api.instance.Instance;
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.MaterialUtil;
import com.jozufozu.flywheel.backend.MaterialRenderState;
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
import com.jozufozu.flywheel.backend.engine.InstanceHandleImpl;
import com.jozufozu.flywheel.backend.engine.UniformBuffer;
@ -50,17 +50,19 @@ public class InstancedCrumbling {
var baseMaterial = shader.material();
int diffuseTexture = getDiffuseTexture(baseMaterial);
var crumblingMaterial = SimpleMaterial.from(baseMaterial)
var crumblingMaterial = SimpleMaterial.builderOf(baseMaterial)
.cutout(CutoutShaders.OFF)
.polygonOffset(true)
.transparency(Transparency.CRUMBLING)
.writeMask(WriteMask.COLOR)
.polygonOffset(true)
.cutout(CutoutShaders.OFF);
.useOverlay(false)
.useLight(false);
var program = InstancingPrograms.get()
.get(shader.vertexType(), shader.instanceType(), Contexts.CRUMBLING);
UniformBuffer.syncAndBind(program);
InstancingEngine.uploadMaterialIDUniform(program, crumblingMaterial);
InstancingEngine.uploadMaterialUniform(program, crumblingMaterial);
for (Int2ObjectMap.Entry<List<Runnable>> progressEntry : byProgress.int2ObjectEntrySet()) {
var drawCalls = progressEntry.getValue();
@ -71,17 +73,17 @@ public class InstancedCrumbling {
crumblingMaterial.baseTexture(ModelBakery.BREAKING_LOCATIONS.get(progressEntry.getIntKey()));
MaterialUtil.setup(crumblingMaterial);
MaterialRenderState.setup(crumblingMaterial);
RenderSystem.setShaderTexture(1, diffuseTexture);
GlTextureUnit.T1.makeActive();
RenderSystem.setShaderTexture(1, diffuseTexture);
RenderSystem.bindTexture(diffuseTexture);
drawCalls.forEach(Runnable::run);
}
}
MaterialUtil.reset();
MaterialRenderState.reset();
}
}

View file

@ -9,7 +9,8 @@ import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.task.Plan;
import com.jozufozu.flywheel.api.task.TaskExecutor;
import com.jozufozu.flywheel.backend.MaterialUtil;
import com.jozufozu.flywheel.backend.MaterialEncoder;
import com.jozufozu.flywheel.backend.MaterialRenderState;
import com.jozufozu.flywheel.backend.ShaderIndices;
import com.jozufozu.flywheel.backend.compile.InstancingPrograms;
import com.jozufozu.flywheel.backend.engine.AbstractEngine;
@ -23,6 +24,7 @@ import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.task.Flag;
import com.jozufozu.flywheel.lib.task.NamedFlag;
import com.jozufozu.flywheel.lib.task.SyncedPlan;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
@ -34,7 +36,7 @@ public class InstancingEngine extends AbstractEngine {
public InstancingEngine(int maxOriginDistance) {
super(maxOriginDistance);
}
}
@Override
public Plan<RenderContext> createFramePlan() {
@ -57,16 +59,27 @@ public class InstancingEngine extends AbstractEngine {
var drawSet = drawManager.get(stage);
if (drawSet.isEmpty()) {
return;
}
if (drawSet.isEmpty()) {
return;
}
try (var state = GlStateTracker.getRestoreState()) {
setup();
try (var state = GlStateTracker.getRestoreState()) {
int prevActiveTexture = GlStateManager._getActiveTexture();
Minecraft.getInstance().gameRenderer.overlayTexture().setupOverlayColor();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
render(drawSet);
}
}
GlTextureUnit.T1.makeActive();
RenderSystem.bindTexture(RenderSystem.getShaderTexture(1));
GlTextureUnit.T2.makeActive();
RenderSystem.bindTexture(RenderSystem.getShaderTexture(2));
render(drawSet);
Minecraft.getInstance().gameRenderer.overlayTexture().teardownOverlayColor();
Minecraft.getInstance().gameRenderer.lightTexture().turnOffLightLayer();
GlStateManager._activeTexture(prevActiveTexture);
}
}
@Override
public void renderCrumbling(TaskExecutor executor, RenderContext context, List<CrumblingBlock> crumblingBlocks) {
@ -86,17 +99,6 @@ public class InstancingEngine extends AbstractEngine {
drawManager.invalidate();
}
private void setup() {
GlTextureUnit.T2.makeActive();
Minecraft.getInstance().gameRenderer.lightTexture().turnOnLightLayer();
RenderSystem.depthMask(true);
RenderSystem.colorMask(true, true, true, true);
RenderSystem.enableDepthTest();
RenderSystem.depthFunc(GL32.GL_LEQUAL);
RenderSystem.enableCull();
}
private void render(InstancedDrawManager.DrawSet drawSet) {
for (var entry : drawSet) {
var shader = entry.getKey();
@ -112,24 +114,24 @@ public class InstancingEngine extends AbstractEngine {
.get(shader.vertexType(), shader.instanceType(), Contexts.WORLD);
UniformBuffer.syncAndBind(program);
uploadMaterialIDUniform(program, shader.material());
uploadMaterialUniform(program, shader.material());
MaterialUtil.setup(shader.material());
MaterialRenderState.setup(shader.material());
for (var drawCall : drawCalls) {
drawCall.render();
}
MaterialUtil.reset();
}
MaterialRenderState.reset();
}
public static void uploadMaterialIDUniform(GlProgram program, Material material) {
int materialIDUniform = program.getUniformLocation("_flw_material_instancing");
int vertexID = ShaderIndices.getVertexShaderIndex(material.shaders());
int fragmentID = ShaderIndices.getFragmentShaderIndex(material.shaders());
int packedFogAndCutout = MaterialUtil.packFogAndCutout(material);
int packedMaterialProperties = MaterialUtil.packProperties(material);
GL32.glUniform4ui(materialIDUniform, vertexID, fragmentID, packedFogAndCutout, packedMaterialProperties);
public static void uploadMaterialUniform(GlProgram program, Material material) {
int uniformLocation = program.getUniformLocation("_flw_packedMaterial");
int vertexIndex = ShaderIndices.getVertexShaderIndex(material.shaders());
int fragmentIndex = ShaderIndices.getFragmentShaderIndex(material.shaders());
int packedFogAndCutout = MaterialEncoder.packFogAndCutout(material);
int packedMaterialProperties = MaterialEncoder.packProperties(material);
GL32.glUniform4ui(uniformLocation, vertexIndex, fragmentIndex, packedFogAndCutout, packedMaterialProperties);
}
}

View file

@ -79,5 +79,4 @@ public class GlProgram extends GlObject {
protected void deleteInternal(int handle) {
glDeleteProgram(handle);
}
}

View file

@ -11,16 +11,16 @@ import net.minecraft.resources.ResourceLocation;
public final class Contexts {
public static final SimpleContext WORLD = Context.REGISTRY.registerAndGet(new SimpleContext(Files.WORLD_VERTEX, Files.WORLD_FRAGMENT, program -> {
program.bind();
program.setSamplerBinding("flw_diffuseTex", 0);
program.setSamplerBinding("flw_overlayTex", 1);
program.setSamplerBinding("flw_lightTex", 2);
program.setSamplerBinding("_flw_diffuseTex", 0);
program.setSamplerBinding("_flw_overlayTex", 1);
program.setSamplerBinding("_flw_lightTex", 2);
GlProgram.unbind();
}));
public static final SimpleContext CRUMBLING = Context.REGISTRY.registerAndGet(new SimpleContext(Files.CRUMBLING_VERTEX, Files.CRUMBLING_FRAGMENT, program -> {
program.bind();
program.setSamplerBinding("flw_crumblingTex", 0);
program.setSamplerBinding("flw_diffuseTex", 1);
program.setSamplerBinding("_flw_crumblingTex", 0);
program.setSamplerBinding("_flw_diffuseTex", 1);
GlProgram.unbind();
}));

View file

@ -28,81 +28,91 @@ public final class Materials {
private static final ResourceLocation MINECART_LOCATION = new ResourceLocation("textures/entity/minecart.png");
public static final Material CHUNK_SOLID_SHADED = SimpleMaterial.builder()
.useOverlay(false)
.fallbackRenderType(RenderType.solid())
.vertexTransformer(SHADING_TRANSFORMER)
.build();
public static final Material CHUNK_SOLID_UNSHADED = SimpleMaterial.builder()
.useOverlay(false)
.diffuse(false)
.fallbackRenderType(RenderType.solid())
.build();
public static final Material CHUNK_CUTOUT_MIPPED_SHADED = SimpleMaterial.builder()
.cutout(CutoutShaders.EPSILON)
.useOverlay(false)
.fallbackRenderType(RenderType.cutoutMipped())
.vertexTransformer(SHADING_TRANSFORMER)
.build();
public static final Material CHUNK_CUTOUT_MIPPED_UNSHADED = SimpleMaterial.builder()
.diffuse(false)
.cutout(CutoutShaders.EPSILON)
.useOverlay(false)
.diffuse(false)
.fallbackRenderType(RenderType.cutoutMipped())
.build();
public static final Material CHUNK_CUTOUT_SHADED = SimpleMaterial.builder()
.mip(false)
.cutout(CutoutShaders.EPSILON)
.mipmap(false)
.useOverlay(false)
.fallbackRenderType(RenderType.cutout())
.vertexTransformer(SHADING_TRANSFORMER)
.build();
public static final Material CHUNK_CUTOUT_UNSHADED = SimpleMaterial.builder()
.diffuse(false)
.mip(false)
.cutout(CutoutShaders.EPSILON)
.mipmap(false)
.useOverlay(false)
.diffuse(false)
.fallbackRenderType(RenderType.cutout())
.build();
public static final Material CHUNK_TRANSLUCENT_SHADED = SimpleMaterial.builder()
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.fallbackRenderType(RenderType.translucent())
.vertexTransformer(SHADING_TRANSFORMER)
.build();
public static final Material CHUNK_TRANSLUCENT_UNSHADED = SimpleMaterial.builder()
.diffuse(false)
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.diffuse(false)
.fallbackRenderType(RenderType.translucent())
.build();
public static final Material CHUNK_TRIPWIRE_SHADED = SimpleMaterial.builder()
.transparency(Transparency.TRANSLUCENT)
.cutout(CutoutShaders.EPSILON)
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.fallbackRenderType(RenderType.tripwire())
.vertexTransformer(SHADING_TRANSFORMER)
.build();
public static final Material CHUNK_TRIPWIRE_UNSHADED = SimpleMaterial.builder()
.diffuse(false)
.transparency(Transparency.TRANSLUCENT)
.cutout(CutoutShaders.EPSILON)
.transparency(Transparency.TRANSLUCENT)
.useOverlay(false)
.diffuse(false)
.fallbackRenderType(RenderType.tripwire())
.build();
public static final Material CHEST = SimpleMaterial.builder()
.baseTexture(Sheets.CHEST_SHEET)
.mip(false)
.mipmap(false)
.fallbackRenderType(Sheets.chestSheet())
.build();
public static final Material SHULKER = SimpleMaterial.builder()
.baseTexture(Sheets.SHULKER_SHEET)
.mip(false)
.backfaceCull(false)
.cutout(CutoutShaders.EPSILON)
.baseTexture(Sheets.SHULKER_SHEET)
.mipmap(false)
.backfaceCulling(false)
.fallbackRenderType(Sheets.shulkerBoxSheet())
.build();
public static final Material BELL = SimpleMaterial.builder()
.mip(false)
.mipmap(false)
.fallbackRenderType(Sheets.solidBlockSheet())
.build();
public static final Material MINECART = SimpleMaterial.builder()
.baseTexture(MINECART_LOCATION)
.mip(false)
.mipmap(false)
.fallbackRenderType(RenderType.entitySolid(MINECART_LOCATION))
.build();

View file

@ -1,6 +1,7 @@
package com.jozufozu.flywheel.lib.material;
import com.jozufozu.flywheel.api.material.CutoutShader;
import com.jozufozu.flywheel.api.material.DepthTest;
import com.jozufozu.flywheel.api.material.FogShader;
import com.jozufozu.flywheel.api.material.Material;
import com.jozufozu.flywheel.api.material.MaterialShaders;
@ -13,52 +14,54 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.InventoryMenu;
public class SimpleMaterial implements Material {
protected final MaterialShaders shaders;
protected final RenderType fallbackRenderType;
protected final MaterialVertexTransformer vertexTransformer;
protected final ResourceLocation baseTexture;
protected final boolean diffuse;
protected final boolean lighting;
protected final boolean blur;
protected final boolean backfaceCull;
protected final boolean polygonOffset;
protected final boolean mip;
protected final MaterialShaders shaders;
protected final FogShader fog;
protected final Transparency transparency;
protected final CutoutShader cutout;
protected final ResourceLocation baseTexture;
protected final boolean blur;
protected final boolean mipmap;
protected final boolean backfaceCulling;
protected final boolean polygonOffset;
protected final DepthTest depthTest;
protected final Transparency transparency;
protected final WriteMask writeMask;
protected final boolean useOverlay;
protected final boolean useLight;
protected final boolean diffuse;
protected SimpleMaterial(Builder builder) {
this.shaders = builder.shaders;
this.fallbackRenderType = builder.fallbackRenderType;
this.vertexTransformer = builder.vertexTransformer;
this.baseTexture = builder.baseTexture;
this.diffuse = builder.diffuse;
this.lighting = builder.lighting;
this.blur = builder.blur;
this.backfaceCull = builder.backfaceCull;
this.polygonOffset = builder.polygonOffset;
this.mip = builder.mip;
this.fog = builder.fog;
this.transparency = builder.transparency;
this.cutout = builder.cutout;
this.writeMask = builder.writeMask;
fallbackRenderType = builder.getFallbackRenderType();
vertexTransformer = builder.getVertexTransformer();
shaders = builder.shaders();
fog = builder.fog();
cutout = builder.cutout();
baseTexture = builder.baseTexture();
blur = builder.blur();
mipmap = builder.mipmap();
backfaceCulling = builder.backfaceCulling();
polygonOffset = builder.polygonOffset();
depthTest = builder.depthTest();
transparency = builder.transparency();
writeMask = builder.writeMask();
useOverlay = builder.useOverlay();
useLight = builder.useLight();
diffuse = builder.diffuse();
}
public static Builder builder() {
return new Builder();
}
public static Builder from(Material material) {
public static Builder builderOf(Material material) {
return new Builder(material);
}
@Override
public MaterialShaders shaders() {
return shaders;
}
@Override
public RenderType getFallbackRenderType() {
return fallbackRenderType;
@ -70,38 +73,8 @@ public class SimpleMaterial implements Material {
}
@Override
public ResourceLocation baseTexture() {
return baseTexture;
}
@Override
public boolean diffuse() {
return diffuse;
}
@Override
public boolean lighting() {
return lighting;
}
@Override
public boolean blur() {
return blur;
}
@Override
public boolean backfaceCull() {
return backfaceCull;
}
@Override
public boolean polygonOffset() {
return polygonOffset;
}
@Override
public boolean mip() {
return mip;
public MaterialShaders shaders() {
return shaders;
}
@Override
@ -110,13 +83,43 @@ public class SimpleMaterial implements Material {
}
@Override
public Transparency transparency() {
return transparency;
public CutoutShader cutout() {
return cutout;
}
@Override
public CutoutShader cutout() {
return cutout;
public ResourceLocation baseTexture() {
return baseTexture;
}
@Override
public boolean blur() {
return blur;
}
@Override
public boolean mipmap() {
return mipmap;
}
@Override
public boolean backfaceCulling() {
return backfaceCulling;
}
@Override
public boolean polygonOffset() {
return polygonOffset;
}
@Override
public DepthTest depthTest() {
return depthTest;
}
@Override
public Transparency transparency() {
return transparency;
}
@Override
@ -124,55 +127,85 @@ public class SimpleMaterial implements Material {
return writeMask;
}
@Override
public boolean useOverlay() {
return useOverlay;
}
@Override
public boolean useLight() {
return useLight;
}
@Override
public boolean diffuse() {
return diffuse;
}
public static class Builder implements Material {
protected RenderType fallbackRenderType;
protected MaterialVertexTransformer vertexTransformer;
protected MaterialShaders shaders;
protected ResourceLocation baseTexture;
protected boolean diffuse;
protected boolean lighting;
protected boolean blur;
protected boolean backfaceCull;
protected boolean polygonOffset;
protected boolean mip;
protected FogShader fog;
protected Transparency transparency;
protected CutoutShader cutout;
protected ResourceLocation baseTexture;
protected boolean blur;
protected boolean mipmap;
protected boolean backfaceCulling;
protected boolean polygonOffset;
protected DepthTest depthTest;
protected Transparency transparency;
protected WriteMask writeMask;
protected boolean useOverlay;
protected boolean useLight;
protected boolean diffuse;
public Builder() {
fallbackRenderType = RenderType.solid();
vertexTransformer = (vertexList, level) -> {
};
shaders = StandardMaterialShaders.DEFAULT;
baseTexture = InventoryMenu.BLOCK_ATLAS;
diffuse = true;
lighting = true;
blur = false;
backfaceCull = true;
polygonOffset = false;
mip = true;
fog = FogShaders.LINEAR;
transparency = Transparency.OPAQUE;
cutout = CutoutShaders.OFF;
baseTexture = InventoryMenu.BLOCK_ATLAS;
blur = false;
mipmap = true;
backfaceCulling = true;
polygonOffset = false;
depthTest = DepthTest.LEQUAL;
transparency = Transparency.OPAQUE;
writeMask = WriteMask.BOTH;
useOverlay = true;
useLight = true;
diffuse = true;
}
public Builder(Material material) {
copyFrom(material);
}
public Builder copyFrom(Material material) {
fallbackRenderType = material.getFallbackRenderType();
vertexTransformer = material.getVertexTransformer();
shaders = material.shaders();
baseTexture = material.baseTexture();
diffuse = material.diffuse();
lighting = material.lighting();
blur = material.blur();
backfaceCull = material.backfaceCull();
polygonOffset = material.polygonOffset();
mip = material.mip();
fog = material.fog();
transparency = material.transparency();
cutout = material.cutout();
baseTexture = material.baseTexture();
blur = material.blur();
mipmap = material.mipmap();
backfaceCulling = material.backfaceCulling();
polygonOffset = material.polygonOffset();
depthTest = material.depthTest();
transparency = material.transparency();
writeMask = material.writeMask();
useOverlay = material.useOverlay();
useLight = material.useLight();
diffuse = material.diffuse();
return this;
}
public Builder fallbackRenderType(RenderType type) {
@ -190,64 +223,69 @@ public class SimpleMaterial implements Material {
return this;
}
public Builder baseTexture(ResourceLocation value) {
this.baseTexture = value;
return this;
}
public Builder diffuse(boolean value) {
this.diffuse = value;
return this;
}
public Builder lighting(boolean value) {
this.lighting = value;
return this;
}
public Builder blur(boolean value) {
this.blur = value;
return this;
}
public Builder backfaceCull(boolean value) {
this.backfaceCull = value;
return this;
}
public Builder polygonOffset(boolean value) {
this.polygonOffset = value;
return this;
}
public Builder mip(boolean value) {
this.mip = value;
return this;
}
public Builder fog(FogShader value) {
this.fog = value;
return this;
}
public Builder transparency(Transparency value) {
this.transparency = value;
return this;
}
public Builder cutout(CutoutShader value) {
this.cutout = value;
return this;
}
public Builder baseTexture(ResourceLocation value) {
this.baseTexture = value;
return this;
}
public Builder blur(boolean value) {
this.blur = value;
return this;
}
public Builder mipmap(boolean value) {
this.mipmap = value;
return this;
}
public Builder backfaceCulling(boolean value) {
this.backfaceCulling = value;
return this;
}
public Builder polygonOffset(boolean value) {
this.polygonOffset = value;
return this;
}
public Builder depthTest(DepthTest value) {
this.depthTest = value;
return this;
}
public Builder transparency(Transparency value) {
this.transparency = value;
return this;
}
public Builder writeMask(WriteMask value) {
this.writeMask = value;
return this;
}
@Override
public MaterialShaders shaders() {
return shaders;
public Builder useOverlay(boolean value) {
this.useOverlay = value;
return this;
}
public Builder useLight(boolean value) {
this.useLight = value;
return this;
}
public Builder diffuse(boolean value) {
this.diffuse = value;
return this;
}
@Override
@ -261,38 +299,8 @@ public class SimpleMaterial implements Material {
}
@Override
public ResourceLocation baseTexture() {
return baseTexture;
}
@Override
public boolean diffuse() {
return diffuse;
}
@Override
public boolean lighting() {
return lighting;
}
@Override
public boolean blur() {
return blur;
}
@Override
public boolean backfaceCull() {
return backfaceCull;
}
@Override
public boolean polygonOffset() {
return polygonOffset;
}
@Override
public boolean mip() {
return mip;
public MaterialShaders shaders() {
return shaders;
}
@Override
@ -301,13 +309,43 @@ public class SimpleMaterial implements Material {
}
@Override
public Transparency transparency() {
return transparency;
public CutoutShader cutout() {
return cutout;
}
@Override
public CutoutShader cutout() {
return cutout;
public ResourceLocation baseTexture() {
return baseTexture;
}
@Override
public boolean blur() {
return blur;
}
@Override
public boolean mipmap() {
return mipmap;
}
@Override
public boolean backfaceCulling() {
return backfaceCulling;
}
@Override
public boolean polygonOffset() {
return polygonOffset;
}
@Override
public DepthTest depthTest() {
return depthTest;
}
@Override
public Transparency transparency() {
return transparency;
}
@Override
@ -315,6 +353,21 @@ public class SimpleMaterial implements Material {
return writeMask;
}
@Override
public boolean useOverlay() {
return useOverlay;
}
@Override
public boolean useLight() {
return useLight;
}
@Override
public boolean diffuse() {
return diffuse;
}
public SimpleMaterial build() {
return new SimpleMaterial(this);
}

View file

@ -14,10 +14,10 @@
/*const*/ vec4 flw_var2;
/*const*/ vec4 flw_var3;
/*const*/ vec4 flw_sampleColor;
/*const*/ FlwMaterial flw_material;
/*const*/ vec4 flw_sampleColor;
vec4 flw_fragColor;
ivec2 flw_fragOverlay;
vec2 flw_fragLight;

View file

@ -1,22 +1,33 @@
const uint FLW_TRANSPARENCY_OPAQUE = 0u;
const uint FLW_TRANSPARENCY_ADDITIVE = 1u;
const uint FLW_TRANSPARENCY_LIGHTING = 2u;
const uint FLW_TRANSPARENCY_GLINT = 3u;
const uint FLW_TRANSPARENCY_CRUMBLING = 4u;
const uint FLW_TRANSPARENCY_TRANSLUCENT = 5u;
const uint FLW_MAT_DEPTH_TEST_OFF = 0u;
const uint FLW_MAT_DEPTH_TEST_NEVER = 1u;
const uint FLW_MAT_DEPTH_TEST_LESS = 2u;
const uint FLW_MAT_DEPTH_TEST_EQUAL = 3u;
const uint FLW_MAT_DEPTH_TEST_LEQUAL = 4u;
const uint FLW_MAT_DEPTH_TEST_GREATER = 5u;
const uint FLW_MAT_DEPTH_TEST_NOTEQUAL = 6u;
const uint FLW_MAT_DEPTH_TEST_GEQUAL = 7u;
const uint FLW_MAT_DEPTH_TEST_ALWAYS = 8u;
const uint FLW_WRITE_MASK_BOTH = 0u;
const uint FLW_WRITE_MASK_COLOR = 1u;
const uint FLW_WRITE_MASK_DEPTH = 2u;
const uint FLW_MAT_TRANSPARENCY_OPAQUE = 0u;
const uint FLW_MAT_TRANSPARENCY_ADDITIVE = 1u;
const uint FLW_MAT_TRANSPARENCY_LIGHTING = 2u;
const uint FLW_MAT_TRANSPARENCY_GLINT = 3u;
const uint FLW_MAT_TRANSPARENCY_CRUMBLING = 4u;
const uint FLW_MAT_TRANSPARENCY_TRANSLUCENT = 5u;
const uint FLW_MAT_WRITE_MASK_BOTH = 0u;
const uint FLW_MAT_WRITE_MASK_COLOR = 1u;
const uint FLW_MAT_WRITE_MASK_DEPTH = 2u;
struct FlwMaterial {
bool diffuse;
bool lighting;
bool blur;
bool backfaceCull;
bool mipmap;
bool backfaceCulling;
bool polygonOffset;
bool mip;
uint writeMask;
uint depthTest;
uint transparency;
uint writeMask;
bool useOverlay;
bool useLight;
bool diffuse;
};

View file

@ -1,22 +1,22 @@
#include "flywheel:api/fragment.glsl"
uniform sampler2D flw_crumblingTex;
uniform sampler2D _flw_crumblingTex;
in vec2 _flw_crumblingTexCoord;
in vec2 crumblingTexCoord;
vec4 flw_crumblingSampleColor;
vec4 crumblingSampleColor;
void flw_beginFragment() {
flw_crumblingSampleColor = texture(flw_crumblingTex, _flw_crumblingTexCoord);
crumblingSampleColor = texture(_flw_crumblingTex, crumblingTexCoord);
// Make the crumbling overlay transparent when the diffuse layer is transparent.
flw_crumblingSampleColor.a *= flw_fragColor.a;
crumblingSampleColor.a *= flw_fragColor.a;
if (flw_crumblingSampleColor.a < 0.01) {
if (crumblingSampleColor.a < 0.01) {
discard;
}
}
void flw_endFragment() {
flw_fragColor = flw_crumblingSampleColor;
flw_fragColor = crumblingSampleColor;
}

View file

@ -1,7 +1,7 @@
#include "flywheel:api/vertex.glsl"
#include "flywheel:util/fog.glsl"
out vec2 _flw_crumblingTexCoord;
out vec2 crumblingTexCoord;
const int DOWN = 0;
const int UP = 1;
@ -66,9 +66,8 @@ vec2 getCrumblingTexCoord() {
}
void flw_beginVertex() {
// no-op
}
void flw_endVertex() {
_flw_crumblingTexCoord = getCrumblingTexCoord();
crumblingTexCoord = getCrumblingTexCoord();
}

View file

@ -1,9 +1,7 @@
#include "flywheel:api/fragment.glsl"
void flw_beginFragment() {
}
void flw_endFragment() {
}

View file

@ -2,9 +2,7 @@
#include "flywheel:util/fog.glsl"
void flw_beginVertex() {
// noop
}
void flw_endVertex() {
}

View file

@ -17,14 +17,14 @@ in vec4 flw_var1;
in vec4 flw_var2;
in vec4 flw_var3;
FlwMaterial flw_material;
vec4 flw_sampleColor;
vec4 flw_fragColor;
ivec2 flw_fragOverlay;
vec2 flw_fragLight;
FlwMaterial flw_material;
vec4 flw_fogFilter(vec4 color);
bool flw_discardPredicate(vec4 finalColor);

View file

@ -2,27 +2,25 @@
#include "flywheel:internal/material.glsl"
// optimize discard usage
#ifdef ALPHA_DISCARD
#ifdef GL_ARB_conservative_depth
layout (depth_greater) out float gl_FragDepth;
#endif
#endif
uniform sampler2D flw_diffuseTex;
uniform sampler2D flw_overlayTex;
uniform sampler2D flw_lightTex;
uniform sampler2D _flw_diffuseTex;
uniform sampler2D _flw_overlayTex;
uniform sampler2D _flw_lightTex;
flat in uvec3 _flw_material;
out vec4 fragColor;
out vec4 _flw_fragColor;
void main() {
_flw_materialFragmentID = _flw_material.x;
_flw_unpackUint2x16(_flw_material.y, _flw_cutoutID, _flw_fogID);
_flw_unpackMaterial(_flw_material.z, flw_material);
_flw_unpackMaterialProperties(_flw_material.z, flw_material);
flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord);
flw_sampleColor = texture(_flw_diffuseTex, flw_vertexTexCoord);
flw_fragColor = flw_vertexColor * flw_sampleColor;
flw_fragOverlay = flw_vertexOverlay;
flw_fragLight = flw_vertexLight;
@ -31,17 +29,15 @@ void main() {
flw_materialFragment();
flw_endFragment();
vec4 overlayColor = texelFetch(flw_overlayTex, flw_fragOverlay, 0);
vec4 lightColor = texture(flw_lightTex, (flw_fragLight * 15.0 + 0.5) / 16.0);
vec4 color = flw_fragColor;
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
if (flw_material.lighting) {
color *= lightColor;
if (flw_material.useOverlay) {
vec4 overlayColor = texelFetch(_flw_overlayTex, flw_fragOverlay, 0);
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
}
if (flw_material.lighting) {
if (flw_material.useLight) {
vec4 lightColor = texture(_flw_lightTex, (flw_fragLight * 15.0 + 0.5) / 16.0);
color *= lightColor;
}
@ -49,5 +45,5 @@ void main() {
discard;
}
fragColor = flw_fogFilter(color);
_flw_fragColor = flw_fogFilter(color);
}

View file

@ -30,7 +30,7 @@ void main() {
_flw_materialVertexID = drawCommands[batchID].vertexMaterialID;
uint p = drawCommands[batchID].packedMaterialProperties;
_flw_unpackMaterial(p, flw_material);
_flw_unpackMaterialProperties(p, flw_material);
_flw_material = uvec3(drawCommands[batchID].fragmentMaterialID, drawCommands[batchID].packedFogAndCutout, p);
flw_layoutVertex();

View file

@ -2,27 +2,25 @@
#include "flywheel:internal/material.glsl"
// optimize discard usage
#ifdef ALPHA_DISCARD
#ifdef GL_ARB_conservative_depth
layout (depth_greater) out float gl_FragDepth;
#endif
#endif
uniform sampler2D flw_diffuseTex;
uniform sampler2D flw_overlayTex;
uniform sampler2D flw_lightTex;
uniform sampler2D _flw_diffuseTex;
uniform sampler2D _flw_overlayTex;
uniform sampler2D _flw_lightTex;
uniform uvec4 _flw_material_instancing;
uniform uvec4 _flw_packedMaterial;
out vec4 fragColor;
out vec4 _flw_fragColor;
void main() {
_flw_materialFragmentID = _flw_material_instancing.y;
_flw_materialFragmentID = _flw_packedMaterial.y;
_flw_unpackUint2x16(_flw_material_instancing.z, _flw_cutoutID, _flw_fogID);
_flw_unpackMaterial(_flw_material_instancing.w, flw_material);
_flw_unpackUint2x16(_flw_packedMaterial.z, _flw_cutoutID, _flw_fogID);
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
flw_sampleColor = texture(flw_diffuseTex, flw_vertexTexCoord);
flw_sampleColor = texture(_flw_diffuseTex, flw_vertexTexCoord);
flw_fragColor = flw_vertexColor * flw_sampleColor;
flw_fragOverlay = flw_vertexOverlay;
flw_fragLight = flw_vertexLight;
@ -31,13 +29,15 @@ void main() {
flw_materialFragment();
flw_endFragment();
vec4 overlayColor = texelFetch(flw_overlayTex, flw_fragOverlay, 0);
vec4 lightColor = texture(flw_lightTex, (flw_fragLight * 15.0 + 0.5) / 16.0);
vec4 color = flw_fragColor;
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
if (flw_material.lighting) {
if (flw_material.useOverlay) {
vec4 overlayColor = texelFetch(_flw_overlayTex, flw_fragOverlay, 0);
color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a);
}
if (flw_material.useLight) {
vec4 lightColor = texture(_flw_lightTex, (flw_fragLight * 15.0 + 0.5) / 16.0);
color *= lightColor;
}
@ -45,5 +45,5 @@ void main() {
discard;
}
fragColor = flw_fogFilter(color);
_flw_fragColor = flw_fogFilter(color);
}

View file

@ -2,12 +2,12 @@
#include "flywheel:internal/material.glsl"
#include "flywheel:util/diffuse.glsl"
uniform uvec4 _flw_material_instancing;
uniform uvec4 _flw_packedMaterial;
void main() {
_flw_materialVertexID = _flw_material_instancing.x;
_flw_materialVertexID = _flw_packedMaterial.x;
_flw_unpackMaterial(_flw_material_instancing.w, flw_material);
_flw_unpackMaterialProperties(_flw_packedMaterial.w, flw_material);
FlwInstance i = _flw_unpackInstance();

View file

@ -1,27 +1,54 @@
#include "flywheel:api/material.glsl"
// The number of bits each property takes up
const uint _FLW_BLUR_LENGTH = 1u;
const uint _FLW_MIPMAP_LENGTH = 1u;
const uint _FLW_BACKFACE_CULLING_LENGTH = 1u;
const uint _FLW_POLYGON_OFFSET_LENGTH = 1u;
const uint _FLW_DEPTH_TEST_LENGTH = 4u;
const uint _FLW_TRANSPARENCY_LENGTH = 3u;
const uint _FLW_WRITE_MASK_LENGTH = 2u;
const uint _FLW_USE_OVERLAY_LENGTH = 1u;
const uint _FLW_USE_LIGHT_LENGTH = 1u;
const uint _FLW_DIFFUSE_LENGTH = 1u;
// The bit offset of each property
const uint _FLW_BLUR_OFFSET = 0u;
const uint _FLW_MIPMAP_OFFSET = _FLW_BLUR_OFFSET + _FLW_BLUR_LENGTH;
const uint _FLW_BACKFACE_CULLING_OFFSET = _FLW_MIPMAP_OFFSET + _FLW_MIPMAP_LENGTH;
const uint _FLW_POLYGON_OFFSET_OFFSET = _FLW_BACKFACE_CULLING_OFFSET + _FLW_BACKFACE_CULLING_LENGTH;
const uint _FLW_DEPTH_TEST_OFFSET = _FLW_POLYGON_OFFSET_OFFSET + _FLW_POLYGON_OFFSET_LENGTH;
const uint _FLW_TRANSPARENCY_OFFSET = _FLW_DEPTH_TEST_OFFSET + _FLW_DEPTH_TEST_LENGTH;
const uint _FLW_WRITE_MASK_OFFSET = _FLW_TRANSPARENCY_OFFSET + _FLW_TRANSPARENCY_LENGTH;
const uint _FLW_USE_OVERLAY_OFFSET = _FLW_WRITE_MASK_OFFSET + _FLW_WRITE_MASK_LENGTH;
const uint _FLW_USE_LIGHT_OFFSET = _FLW_USE_OVERLAY_OFFSET + _FLW_USE_OVERLAY_LENGTH;
const uint _FLW_DIFFUSE_OFFSET = _FLW_USE_LIGHT_OFFSET + _FLW_USE_LIGHT_LENGTH;
// The bit mask for each property
const uint _FLW_BLUR_MASK = ((1u << _FLW_BLUR_LENGTH) - 1u) << _FLW_BLUR_OFFSET;
const uint _FLW_MIPMAP_MASK = ((1u << _FLW_MIPMAP_LENGTH) - 1u) << _FLW_MIPMAP_OFFSET;
const uint _FLW_BACKFACE_CULLING_MASK = ((1u << _FLW_BACKFACE_CULLING_LENGTH) - 1u) << _FLW_BACKFACE_CULLING_OFFSET;
const uint _FLW_POLYGON_OFFSET_MASK = ((1u << _FLW_POLYGON_OFFSET_LENGTH) - 1u) << _FLW_POLYGON_OFFSET_OFFSET;
const uint _FLW_DEPTH_TEST_MASK = ((1u << _FLW_DEPTH_TEST_LENGTH) - 1u) << _FLW_DEPTH_TEST_OFFSET;
const uint _FLW_TRANSPARENCY_MASK = ((1u << _FLW_TRANSPARENCY_LENGTH) - 1u) << _FLW_TRANSPARENCY_OFFSET;
const uint _FLW_WRITE_MASK_MASK = ((1u << _FLW_WRITE_MASK_LENGTH) - 1u) << _FLW_WRITE_MASK_OFFSET;
const uint _FLW_USE_OVERLAY_MASK = ((1u << _FLW_USE_OVERLAY_LENGTH) - 1u) << _FLW_USE_OVERLAY_OFFSET;
const uint _FLW_USE_LIGHT_MASK = ((1u << _FLW_USE_LIGHT_LENGTH) - 1u) << _FLW_USE_LIGHT_OFFSET;
const uint _FLW_DIFFUSE_MASK = ((1u << _FLW_DIFFUSE_LENGTH) - 1u) << _FLW_DIFFUSE_OFFSET;
// Packed format:
// transparency[3] | writeMask[2] | mip[1] | polygonOffset[1] | backfaceCull[1] | blur[1] | lighting[1] | diffuse[1]
const uint DIFFUSE_MASK = 1u;
const uint LIGHTING_MASK = 1u << 1u;
const uint BLUR_MASK = 1u << 2u;
const uint BACKFACE_CULL_MASK = 1u << 3u;
const uint POLYGON_OFFSET_MASK = 1u << 4u;
const uint MIP_MASK = 1u << 5u;
const uint WRITE_MASK_MASK = 3u << 6u;
const uint TRANSPARENCY_MASK = 7u << 8u;
void _flw_unpackMaterial(uint m, out FlwMaterial o) {
o.diffuse = (m & DIFFUSE_MASK) != 0u;
o.lighting = (m & LIGHTING_MASK) != 0u;
o.blur = (m & BLUR_MASK) != 0u;
o.backfaceCull = (m & BACKFACE_CULL_MASK) != 0u;
o.polygonOffset = (m & POLYGON_OFFSET_MASK) != 0u;
o.mip = (m & MIP_MASK) != 0u;
o.writeMask = (m & WRITE_MASK_MASK) >> 6;
o.transparency = (m & TRANSPARENCY_MASK) >> 8;
// diffuse[1] | useOverlay[1] | useLight[1] | writeMask[2] | transparency[3] | depthTest[4] | polygonOffset[1] | backfaceCulling[1] | mipmap[1] | blur[1]
void _flw_unpackMaterialProperties(uint p, out FlwMaterial m) {
m.blur = (p & _FLW_BLUR_MASK) != 0u;
m.mipmap = (p & _FLW_MIPMAP_MASK) != 0u;
m.backfaceCulling = (p & _FLW_BACKFACE_CULLING_MASK) != 0u;
m.polygonOffset = (p & _FLW_POLYGON_OFFSET_MASK) != 0u;
m.depthTest = (p & _FLW_DEPTH_TEST_MASK) >> _FLW_DEPTH_TEST_OFFSET;
m.transparency = (p & _FLW_TRANSPARENCY_MASK) >> _FLW_TRANSPARENCY_OFFSET;
m.writeMask = (p & _FLW_WRITE_MASK_MASK) >> _FLW_WRITE_MASK_OFFSET;
m.useOverlay = (p & _FLW_USE_OVERLAY_MASK) != 0u;
m.useLight = (p & _FLW_USE_LIGHT_MASK) != 0u;
m.diffuse = (p & _FLW_DIFFUSE_MASK) != 0u;
}
void _flw_unpackUint2x16(uint s, out uint hi, out uint lo) {

View file

@ -1,16 +1,16 @@
#include "flywheel:api/vertex.glsl"
layout(location = 0) in vec3 _flw_v_pos;
layout(location = 1) in vec4 _flw_v_color;
layout(location = 2) in vec2 _flw_v_texCoord;
layout(location = 3) in ivec2 _flw_v_light;
layout(location = 4) in vec3 _flw_v_normal;
layout(location = 0) in vec3 v_pos;
layout(location = 1) in vec4 v_color;
layout(location = 2) in vec2 v_texCoord;
layout(location = 3) in ivec2 v_light;
layout(location = 4) in vec3 v_normal;
void flw_layoutVertex() {
flw_vertexPos = vec4(_flw_v_pos, 1.0);
flw_vertexColor = _flw_v_color;
flw_vertexTexCoord = _flw_v_texCoord;
flw_vertexPos = vec4(v_pos, 1.0);
flw_vertexColor = v_color;
flw_vertexTexCoord = v_texCoord;
flw_vertexOverlay = ivec2(0, 10);
flw_vertexLight = _flw_v_light / 15.0;
flw_vertexNormal = _flw_v_normal;
flw_vertexLight = v_light / 15.0;
flw_vertexNormal = v_normal;
}

View file

@ -1,14 +1,14 @@
#include "flywheel:api/vertex.glsl"
layout(location = 0) in vec3 _flw_v_pos;
layout(location = 1) in vec2 _flw_v_texCoord;
layout(location = 2) in vec3 _flw_v_normal;
layout(location = 0) in vec3 v_pos;
layout(location = 1) in vec2 v_texCoord;
layout(location = 2) in vec3 v_normal;
void flw_layoutVertex() {
flw_vertexPos = vec4(_flw_v_pos, 1.0);
flw_vertexPos = vec4(v_pos, 1.0);
flw_vertexColor = vec4(1.0);
flw_vertexTexCoord = _flw_v_texCoord;
flw_vertexTexCoord = v_texCoord;
flw_vertexOverlay = ivec2(0, 10);
flw_vertexLight = vec2(1.0);
flw_vertexNormal = _flw_v_normal;
flw_vertexNormal = v_normal;
}