Skip to content

Commit

Permalink
Prep for new render material
Browse files Browse the repository at this point in the history
  • Loading branch information
grondag committed Oct 20, 2020
1 parent 74325c0 commit 933cfdb
Show file tree
Hide file tree
Showing 5 changed files with 347 additions and 241 deletions.
7 changes: 3 additions & 4 deletions src/main/java/grondag/canvas/wip/encoding/WipImmediate.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import java.util.SortedMap;

import grondag.canvas.mixinterface.MultiPhaseExt;
import grondag.canvas.wip.state.AbstractStateFinder;
import grondag.canvas.wip.state.RenderContextState;
import grondag.canvas.wip.state.WipRenderState;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;

Expand All @@ -31,7 +31,7 @@ public VertexConsumer getBuffer(RenderLayer renderLayer) {
final WipVertexCollector result = collectors.get(((MultiPhaseExt) renderLayer).canvas_renderState());

if (result == null) {
assert WipRenderState.isExcluded(renderLayer) : "Unable to retrieve vertex collector for non-excluded render layer";
assert AbstractStateFinder.isExcluded(renderLayer) : "Unable to retrieve vertex collector for non-excluded render layer";

return super.getBuffer(renderLayer);
} else {
Expand Down Expand Up @@ -77,7 +77,7 @@ public void draw() {

@Override
public void draw(RenderLayer layer) {
if (WipRenderState.isExcluded(layer)) {
if (AbstractStateFinder.isExcluded(layer)) {
super.draw(layer);
} else {
final WipVertexCollectorImpl collector = collectors.getIfExists(((MultiPhaseExt) layer).canvas_renderState());
Expand All @@ -90,7 +90,6 @@ public void draw(RenderLayer layer) {

public static SortedMap<RenderLayer, BufferBuilder> entityBuilders() {
return Util.make(new Object2ObjectLinkedOpenHashMap<>(), (object2ObjectLinkedOpenHashMap) -> {

assignBufferBuilder(object2ObjectLinkedOpenHashMap, RenderLayer.getTranslucentNoCrumbling());
assignBufferBuilder(object2ObjectLinkedOpenHashMap, RenderLayer.getArmorGlint());
assignBufferBuilder(object2ObjectLinkedOpenHashMap, RenderLayer.getArmorEntityGlint());
Expand Down
112 changes: 112 additions & 0 deletions src/main/java/grondag/canvas/wip/state/AbstractRenderState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2019, 2020 grondag
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package grondag.canvas.wip.state;

import grondag.canvas.material.MaterialVertexFormats;
import grondag.canvas.wip.shader.WipMaterialShaderImpl;
import grondag.canvas.wip.shader.WipMaterialShaderManager;
import grondag.canvas.wip.state.property.WipDecal;
import grondag.canvas.wip.state.property.WipDepthTest;
import grondag.canvas.wip.state.property.WipFog;
import grondag.canvas.wip.state.property.WipTarget;
import grondag.canvas.wip.state.property.WipTextureState;
import grondag.canvas.wip.state.property.WipTransparency;
import grondag.canvas.wip.state.property.WipWriteMask;
import grondag.fermion.bits.BitPacker64;

@SuppressWarnings("rawtypes")
abstract class AbstractRenderState {
protected final long bits;

public final int index;

/**
* OpenGL primitive constant. Determines number of vertices.
*
* Currently used in vanilla are...
* GL_LINES
* GL_LINE_STRIP (currently GUI only)
* GL_TRIANGLE_STRIP (currently GUI only)
* GL_TRIANGLE_FAN (currently GUI only)
* GL_QUADS
*/
public final int primitive;

public final int vertexStrideInts;
public final WipTextureState texture;
public final boolean bilinear;
public final WipTransparency translucency;
public final WipDepthTest depthTest;
public final boolean cull;
public final WipWriteMask writeMask;
public final boolean enableLightmap;
public final WipDecal decal;
public final WipTarget target;
public final boolean lines;
public final WipFog fog;
public final WipMaterialShaderImpl shader;

/**
* True when translucent transparency and targets the terrain layer.
* Should not be rendered until that framebuffer is initialized in fabulous mode
* or should be delayed to render with other trasnslucent when not.
*/
public final boolean isTranslucentTerrain;

protected AbstractRenderState(int index, long bits) {
this.bits = bits;
this.index = index;
primitive = PRIMITIVE.getValue(bits);
texture = WipTextureState.fromIndex(TEXTURE.getValue(bits));
bilinear = BILINEAR.getValue(bits);
depthTest = DEPTH_TEST.getValue(bits);
cull = CULL.getValue(bits);
writeMask = WRITE_MASK.getValue(bits);
enableLightmap = ENABLE_LIGHTMAP.getValue(bits);
decal = DECAL.getValue(bits);
target = TARGET.getValue(bits);
lines = LINES.getValue(bits);
fog = FOG.getValue(bits);
vertexStrideInts = MaterialVertexFormats.POSITION_COLOR_TEXTURE_MATERIAL_LIGHT_NORMAL.vertexStrideInts;
translucency = TRANSPARENCY.getValue(bits);
shader = WipMaterialShaderManager.INSTANCE.find(VERTEX_SHADER.getValue(bits), FRAGMENT_SHADER.getValue(bits), translucency == WipTransparency.TRANSLUCENT ? WipProgramType.MATERIAL_VERTEX_LOGIC : WipProgramType.MATERIAL_UNIFORM_LOGIC);
isTranslucentTerrain = (target == WipTarget.MAIN || target == WipTarget.TRANSLUCENT) && translucency == WipTransparency.TRANSLUCENT;
}


static final BitPacker64<Void> PACKER = new BitPacker64<> (null, null);

// GL State comes first for sorting
static final BitPacker64.IntElement TEXTURE = PACKER.createIntElement(WipTextureState.MAX_TEXTURE_STATES);
static final BitPacker64.BooleanElement BILINEAR = PACKER.createBooleanElement();

static final BitPacker64<Void>.EnumElement<WipTransparency> TRANSPARENCY = PACKER.createEnumElement(WipTransparency.class);
static final BitPacker64<Void>.EnumElement<WipDepthTest> DEPTH_TEST = PACKER.createEnumElement(WipDepthTest.class);
static final BitPacker64.BooleanElement CULL = PACKER.createBooleanElement();
static final BitPacker64<Void>.EnumElement<WipWriteMask> WRITE_MASK = PACKER.createEnumElement(WipWriteMask.class);
static final BitPacker64.BooleanElement ENABLE_LIGHTMAP = PACKER.createBooleanElement();
static final BitPacker64<Void>.EnumElement<WipDecal> DECAL = PACKER.createEnumElement(WipDecal.class);
static final BitPacker64<Void>.EnumElement<WipTarget> TARGET = PACKER.createEnumElement(WipTarget.class);
static final BitPacker64.BooleanElement LINES = PACKER.createBooleanElement();
static final BitPacker64<Void>.EnumElement<WipFog> FOG = PACKER.createEnumElement(WipFog.class);

// These don't affect GL state but do affect encoding - must be buffered separately
static final BitPacker64.IntElement PRIMITIVE = PACKER.createIntElement(8);

static final BitPacker64.IntElement VERTEX_SHADER = PACKER.createIntElement(4096);
static final BitPacker64.IntElement FRAGMENT_SHADER = PACKER.createIntElement(4096);
}
204 changes: 204 additions & 0 deletions src/main/java/grondag/canvas/wip/state/AbstractStateFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* Copyright 2019, 2020 grondag
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package grondag.canvas.wip.state;

import grondag.canvas.mixin.AccessMultiPhaseParameters;
import grondag.canvas.mixin.AccessTexture;
import grondag.canvas.mixinterface.EntityRenderDispatcherExt;
import grondag.canvas.mixinterface.MultiPhaseExt;
import grondag.canvas.wip.shader.WipMaterialShaderManager;
import grondag.canvas.wip.shader.WipShaderData;
import grondag.canvas.wip.state.property.WipDecal;
import grondag.canvas.wip.state.property.WipDepthTest;
import grondag.canvas.wip.state.property.WipFog;
import grondag.canvas.wip.state.property.WipTarget;
import grondag.canvas.wip.state.property.WipTextureState;
import grondag.canvas.wip.state.property.WipTransparency;
import grondag.canvas.wip.state.property.WipWriteMask;
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GL11;

import static grondag.canvas.wip.state.AbstractRenderState.BILINEAR;
import static grondag.canvas.wip.state.AbstractRenderState.CULL;
import static grondag.canvas.wip.state.AbstractRenderState.DECAL;
import static grondag.canvas.wip.state.AbstractRenderState.DEPTH_TEST;
import static grondag.canvas.wip.state.AbstractRenderState.ENABLE_LIGHTMAP;
import static grondag.canvas.wip.state.AbstractRenderState.FOG;
import static grondag.canvas.wip.state.AbstractRenderState.FRAGMENT_SHADER;
import static grondag.canvas.wip.state.AbstractRenderState.LINES;
import static grondag.canvas.wip.state.AbstractRenderState.PACKER;
import static grondag.canvas.wip.state.AbstractRenderState.PRIMITIVE;
import static grondag.canvas.wip.state.AbstractRenderState.TARGET;
import static grondag.canvas.wip.state.AbstractRenderState.TEXTURE;
import static grondag.canvas.wip.state.AbstractRenderState.TRANSPARENCY;
import static grondag.canvas.wip.state.AbstractRenderState.VERTEX_SHADER;
import static grondag.canvas.wip.state.AbstractRenderState.WRITE_MASK;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderPhase;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.util.Identifier;

@SuppressWarnings("unchecked")
public abstract class AbstractStateFinder<T extends AbstractStateFinder<T, V>, V extends AbstractRenderState> {
protected long bits;

public T reset() {
bits = 0;
vertexShader(WipShaderData.DEFAULT_VERTEX_SOURCE);
fragmentShader(WipShaderData.DEFAULT_FRAGMENT_SOURCE);
return (T) this;
}

public T primitive(int primitive) {
assert primitive <= 7;
bits = PRIMITIVE.setValue(primitive, bits);
return (T) this;
}

// private static final Identifier EGREGIOUS_ENDERMAN_HACK = new Identifier("textures/entity/enderman/enderman.png");

public T texture(@Nullable Identifier id) {
final int val = id == null ? WipTextureState.NO_TEXTURE.index : WipTextureState.fromId(id).index;
bits = TEXTURE.setValue(val, bits);

// WIP2: put in proper material map hooks
// if (id != null && id.equals(EGREGIOUS_ENDERMAN_HACK)) {
// fragmentShader(new Identifier("canvas:shaders/wip/material/enderman.frag"));
// }

return (T) this;
}

public T bilinear(boolean bilinear) {
bits = BILINEAR.setValue(bilinear, bits);
return (T) this;
}

public T transparency(WipTransparency transparency) {
bits = TRANSPARENCY.setValue(transparency, bits);
return (T) this;
}

public T depthTest(WipDepthTest depthTest) {
bits = DEPTH_TEST.setValue(depthTest, bits);
return (T) this;
}

public T cull(boolean cull) {
bits = CULL.setValue(cull, bits);
return (T) this;
}

public T writeMask(WipWriteMask writeMask) {
bits = WRITE_MASK.setValue(writeMask, bits);
return (T) this;
}

public T enableLightmap(boolean enableLightmap) {
bits = ENABLE_LIGHTMAP.setValue(enableLightmap, bits);
return (T) this;
}

public T decal(WipDecal decal) {
bits = DECAL.setValue(decal, bits);
return (T) this;
}

public T target(WipTarget target) {
bits = TARGET.setValue(target, bits);
return (T) this;
}

public T lines(boolean lines) {
bits = LINES.setValue(lines, bits);
return (T) this;
}

public T fog(WipFog fog) {
bits = FOG.setValue(fog, bits);
return (T) this;
}

public T vertexShader(Identifier vertexSource) {
bits = VERTEX_SHADER.setValue(WipMaterialShaderManager.vertexIndex.toHandle(vertexSource), bits);
return (T) this;
}

public T fragmentShader(Identifier fragmentSource) {
bits = FRAGMENT_SHADER.setValue(WipMaterialShaderManager.fragmentIndex.toHandle(fragmentSource), bits);
return (T) this;
}

protected abstract V missing();

protected abstract V find();

public V copyFromLayer(RenderLayer layer) {
if (AbstractStateFinder.isExcluded(layer)) {
return missing();
}

final AccessMultiPhaseParameters params = ((MultiPhaseExt) layer).canvas_phases();
final AccessTexture tex = (AccessTexture) params.getTexture();

primitive(GL11.GL_QUADS);
texture(tex.getId().orElse(null));
transparency(WipTransparency.fromPhase(params.getTransparency()));
depthTest(WipDepthTest.fromPhase(params.getDepthTest()));
cull(params.getCull() == RenderPhase.ENABLE_CULLING);
writeMask(WipWriteMask.fromPhase(params.getWriteMaskState()));
enableLightmap(params.getLightmap() == RenderPhase.ENABLE_LIGHTMAP);
decal(WipDecal.fromPhase(params.getLayering()));
target(WipTarget.fromPhase(params.getTarget()));
lines(params.getLineWidth() != RenderPhase.FULL_LINE_WIDTH);
fog(WipFog.fromPhase(params.getFog()));

return find();
}

private static final ReferenceOpenHashSet<RenderLayer> EXCLUSIONS = new ReferenceOpenHashSet<>(64, Hash.VERY_FAST_LOAD_FACTOR);

static {
assert PACKER.bitLength() <= 56; // high eight bits saved for RenderMaterial aggregate

// entity shadows aren't worth
EXCLUSIONS.add(((EntityRenderDispatcherExt) MinecraftClient.getInstance().getEntityRenderDispatcher()).canvas_shadowLayer());

// FEAT: handle more of these with shaders
EXCLUSIONS.add(RenderLayer.getArmorGlint());
EXCLUSIONS.add(RenderLayer.getArmorEntityGlint());
EXCLUSIONS.add(RenderLayer.getGlint());
EXCLUSIONS.add(RenderLayer.getDirectGlint());
EXCLUSIONS.add(RenderLayer.method_30676());
EXCLUSIONS.add(RenderLayer.getEntityGlint());
EXCLUSIONS.add(RenderLayer.getDirectEntityGlint());
EXCLUSIONS.add(RenderLayer.getLines());
EXCLUSIONS.add(RenderLayer.getLightning());

ModelLoader.BLOCK_DESTRUCTION_RENDER_LAYERS.forEach((renderLayer) -> {
EXCLUSIONS.add(renderLayer);
});
}

public static boolean isExcluded(RenderLayer layer) {
return EXCLUSIONS.contains(layer);
}
}
16 changes: 16 additions & 0 deletions src/main/java/grondag/canvas/wip/state/RenderContextState.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright 2019, 2020 grondag
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package grondag.canvas.wip.state;

import org.jetbrains.annotations.Nullable;
Expand Down
Loading

0 comments on commit 933cfdb

Please sign in to comment.