-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
347 additions
and
241 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
src/main/java/grondag/canvas/wip/state/AbstractRenderState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
204
src/main/java/grondag/canvas/wip/state/AbstractStateFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
16
src/main/java/grondag/canvas/wip/state/RenderContextState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.