mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
Compare commits
12
Commits
master
...
1.0.0-beta66a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43c1749468 | ||
|
|
ffc7a9eedc | ||
|
|
0f101db163 | ||
|
|
c8dbf79ab9 | ||
|
|
e05d6cd9c5 | ||
|
|
53cb7e436a | ||
|
|
d9a3e8b609 | ||
|
|
1e458fa368 | ||
|
|
02736af5ec | ||
|
|
91c3cbeedb | ||
|
|
ae1605553c | ||
|
|
1cd270fdd0 |
No files matched your search
+1
-1
@@ -61,7 +61,7 @@ dependencies {
|
||||
|
||||
// Iris Shaders
|
||||
compileOnly('org.jetbrains:annotations:26.0.2')
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.6.40:dev")
|
||||
api("com.github.GTNewHorizons:GTNHLib:0.7.7:dev")
|
||||
shadowImplementation("org.anarres:jcpp:1.4.14") // Apache 2.0
|
||||
shadowImplementation("org.taumc:glsl-transformation-lib:0.2.0-4.g6b42bca") {
|
||||
exclude module: "antlr4" // we only want to shadow the runtime module
|
||||
|
||||
@@ -16,7 +16,7 @@ import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
name = "Angelica",
|
||||
version = Tags.VERSION,
|
||||
dependencies = """
|
||||
required-after:gtnhlib@[0.6.6,);\
|
||||
required-after:gtnhlib@[0.7.7,);\
|
||||
before:lwjgl3ify@[1.5.3,);\
|
||||
after:hodgepodge@[2.4.4,);\
|
||||
after:CodeChickenCore@[1.2.0,);\
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -161,6 +162,15 @@ public class BatchingFontRenderer {
|
||||
pushQuadIdx(vtxId);
|
||||
}
|
||||
|
||||
private void pushTexRect(float x, float y, float w, float h, float itOff, int rgba, float uStart, float vStart, float uSz, float vSz) {
|
||||
final int vtxId = vtxWriterIndex;
|
||||
pushVtx(x + itOff, y, rgba, uStart, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(x - itOff, y + h, rgba, uStart, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(x + itOff + w, y, rgba, uStart + uSz, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(x - itOff + w, y + h, rgba, uStart + uSz, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushQuadIdx(vtxId);
|
||||
}
|
||||
|
||||
private int pushQuadIdx(int startV) {
|
||||
final int idx = idxWriterIndex;
|
||||
batchIndices.put(idx, startV);
|
||||
@@ -268,6 +278,8 @@ public class BatchingFontRenderer {
|
||||
int fontAAModeLast = -1;
|
||||
int fontAAStrengthLast = -1;
|
||||
private void flushBatch() {
|
||||
final int prevProgram = GLStateManager.glGetInteger(GL20.GL_CURRENT_PROGRAM);
|
||||
|
||||
// Sort&Draw
|
||||
batchCommands.sort(FontDrawCmd.DRAW_ORDER_COMPARATOR);
|
||||
|
||||
@@ -282,10 +294,11 @@ public class BatchingFontRenderer {
|
||||
GLStateManager.tryBlendFuncSeparate(blendSrcRGB, blendDstRGB, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GLStateManager.glShadeModel(GL11.GL_FLAT);
|
||||
|
||||
if (FontConfig.fontAAMode != 0) {
|
||||
final boolean canUseAA = FontConfig.fontAAMode != 0 && prevProgram == 0;
|
||||
if (canUseAA) {
|
||||
GL20.glVertexAttribPointer(texBoundAttrLocation, 4, false, 0, batchVtxTexBounds);
|
||||
GL20.glEnableVertexAttribArray(texBoundAttrLocation);
|
||||
lastActiveProgram = GLStateManager.getActiveProgram();
|
||||
lastActiveProgram = prevProgram;
|
||||
GLStateManager.glUseProgram(fontShaderId);
|
||||
if (FontConfig.fontAAMode != fontAAModeLast) {
|
||||
fontAAModeLast = FontConfig.fontAAMode;
|
||||
@@ -296,6 +309,8 @@ public class BatchingFontRenderer {
|
||||
GL20.glUniform1f(AAStrength, FontConfig.fontAAStrength / 120.f);
|
||||
}
|
||||
}
|
||||
|
||||
GL13.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GL11.glTexCoordPointer(2, 0, batchVtxTexCoords);
|
||||
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
GL11.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 0, batchVtxColors);
|
||||
@@ -304,6 +319,9 @@ public class BatchingFontRenderer {
|
||||
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
|
||||
GL11.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Use plain for loop to avoid allocations
|
||||
final FontDrawCmd[] cmdsData = batchCommands.elements();
|
||||
final int cmdsSize = batchCommands.size();
|
||||
@@ -326,7 +344,7 @@ public class BatchingFontRenderer {
|
||||
|
||||
GL11.glDrawElements(GL11.GL_TRIANGLES, batchIndices);
|
||||
}
|
||||
if (FontConfig.fontAAMode != 0) {
|
||||
if (canUseAA) {
|
||||
GLStateManager.glUseProgram(lastActiveProgram);
|
||||
GL20.glDisableVertexAttribArray(texBoundAttrLocation);
|
||||
}
|
||||
@@ -509,49 +527,44 @@ public class BatchingFontRenderer {
|
||||
final float vSz = fontProvider.getVSize(chr);
|
||||
final float itOff = curItalic ? 1.0F : 0.0F; // italic offset
|
||||
final float shadowOffset = fontProvider.getShadowOffset();
|
||||
final int shadowCopies = FontConfig.shadowCopies;
|
||||
final int boldCopies = FontConfig.boldCopies;
|
||||
final ResourceLocation texture = fontProvider.getTexture(chr);
|
||||
|
||||
final int vtxId = vtxWriterIndex;
|
||||
final int idxId = idxWriterIndex;
|
||||
|
||||
int vtxCount = 0;
|
||||
|
||||
if (enableShadow) {
|
||||
pushVtx(curX + itOff + shadowOffset, heightNorth + shadowOffset, curShadowColor, uStart, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX - itOff + shadowOffset, heightNorth + heightSouth + shadowOffset, curShadowColor, uStart, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F + itOff + shadowOffset, heightNorth + shadowOffset, curShadowColor, uStart + uSz, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F - itOff + shadowOffset, heightNorth + heightSouth + shadowOffset, curShadowColor, uStart + uSz, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushQuadIdx(vtxId + vtxCount);
|
||||
vtxCount += 4;
|
||||
for (int n = 1; n <= shadowCopies; n++) {
|
||||
final float shadowOffsetPart = shadowOffset * ((float) n / shadowCopies);
|
||||
pushTexRect(curX + shadowOffsetPart, heightNorth + shadowOffsetPart, glyphW - 1.0f, heightSouth, itOff, curShadowColor, uStart, vStart, uSz, vSz);
|
||||
|
||||
if (curBold) {
|
||||
final float shadowOffset2 = 2.0f * shadowOffset;
|
||||
pushVtx(curX + itOff + shadowOffset2, heightNorth + shadowOffset, curShadowColor, uStart, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX - itOff + shadowOffset2, heightNorth + heightSouth + shadowOffset, curShadowColor, uStart, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F + itOff + shadowOffset2, heightNorth + shadowOffset, curShadowColor, uStart + uSz, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F - itOff + shadowOffset2, heightNorth + heightSouth + shadowOffset, curShadowColor, uStart + uSz, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushQuadIdx(vtxId + vtxCount);
|
||||
vtxCount += 4;
|
||||
if (curBold) {
|
||||
pushTexRect(curX + 2.0f * shadowOffsetPart, heightNorth + shadowOffsetPart, glyphW - 1.0f, heightSouth, itOff, curShadowColor, uStart, vStart, uSz, vSz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pushVtx(curX + itOff, heightNorth, curColor, uStart, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX - itOff, heightNorth + heightSouth, curColor, uStart, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F + itOff, heightNorth, curColor, uStart + uSz, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(curX + glyphW - 1.0F - itOff, heightNorth + heightSouth, curColor, uStart + uSz, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushQuadIdx(vtxId + vtxCount);
|
||||
vtxCount += 4;
|
||||
pushTexRect(curX, heightNorth, glyphW - 1.0f, heightSouth, itOff, curColor, uStart, vStart, uSz, vSz);
|
||||
|
||||
if (curBold) {
|
||||
pushVtx(shadowOffset + curX + itOff, heightNorth, curColor, uStart, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(shadowOffset + curX - itOff, heightNorth + heightSouth, curColor, uStart, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(shadowOffset + curX + glyphW - 1.0F + itOff, heightNorth, curColor, uStart + uSz, vStart, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushVtx(shadowOffset + curX + glyphW - 1.0F - itOff, heightNorth + heightSouth, curColor, uStart + uSz, vStart + vSz, uStart, uStart + uSz, vStart, vStart + vSz);
|
||||
pushQuadIdx(vtxId + vtxCount);
|
||||
vtxCount += 4;
|
||||
for (int n = 1; n <= boldCopies; n++) {
|
||||
final float shadowOffsetPart = shadowOffset * ((float) n / boldCopies);
|
||||
pushTexRect(curX + shadowOffsetPart, heightNorth, glyphW - 1.0f, heightSouth, itOff, curColor, uStart, vStart, uSz, vSz);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Vertex-per-char counts for different configurations
|
||||
default: 4
|
||||
shadow only: 4(1 + shadowCopies)
|
||||
bold only: 4(1 + boldCopies)
|
||||
both: 4(1 + 2 * shadowCopies + boldCopies)
|
||||
*/
|
||||
int charCount = 1;
|
||||
if (enableShadow) { charCount += shadowCopies * (curBold ? 2 : 1); }
|
||||
if (curBold) { charCount += boldCopies; }
|
||||
final int vtxCount = 4 * charCount;
|
||||
pushDrawCmd(idxId, vtxCount / 2 * 3, texture, chr > 255);
|
||||
|
||||
curX += (xAdvance + (curBold ? shadowOffset : 0.0f)) + getGlyphSpacing();
|
||||
underlineEndX = curX;
|
||||
strikethroughEndX = curX;
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.client.gui.GuiSlot;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.awt.Font;
|
||||
@@ -26,6 +27,8 @@ public class FontConfigScreen extends GuiScreen {
|
||||
private final GuiScreen parent;
|
||||
private final String title;
|
||||
private final String searchPrompt;
|
||||
private final String testAreaPrompt;
|
||||
private List<String> testAreaInfo;
|
||||
private String currentPrimaryFontName;
|
||||
private String currentFallbackFontName;
|
||||
private FontList fontList;
|
||||
@@ -33,10 +36,31 @@ public class FontConfigScreen extends GuiScreen {
|
||||
private int selectedFallbackFontListPos = -1;
|
||||
private ArrayList<Font> displayedFonts;
|
||||
private GuiTextField searchBox;
|
||||
private GuiTextField testArea;
|
||||
private int sliderPages = 0;
|
||||
private int displayedSliderPage = 0;
|
||||
private final int sliderWidth = 160;
|
||||
private final int sliderHeight = 20;
|
||||
|
||||
// need to save these separately
|
||||
private IrisButton fwdButton;
|
||||
private IrisButton backButton;
|
||||
|
||||
SliderClone.Option optFontQuality = new SliderClone.Option(6, 72, 6);
|
||||
SliderClone.Option optShadowOffset = new SliderClone.Option(0, 2, 0.05f);
|
||||
SliderClone.Option optShadowCopies = new SliderClone.Option(1, 8, 1);
|
||||
SliderClone.Option optBoldCopies = new SliderClone.Option(1, 8, 1);
|
||||
SliderClone.Option optGlyphAspect = new SliderClone.Option(-1, 1, 0.05f);
|
||||
SliderClone.Option optGlyphScale = new SliderClone.Option(0.1f, 3, 0.05f);
|
||||
SliderClone.Option optWhitespaceScale = new SliderClone.Option(0.1f, 3, 0.05f);
|
||||
SliderClone.Option optGlyphSpacing = new SliderClone.Option(-2f, 2f, 0.05f);
|
||||
SliderClone.Option optFontAAMode = new SliderClone.Option(0, 2, 1);
|
||||
SliderClone.Option optFontAAStrength = new SliderClone.Option(1, 24, 1);
|
||||
|
||||
public FontConfigScreen(GuiScreen parent) {
|
||||
this.title = I18n.format("options.angelica.fontconfig.title");
|
||||
this.searchPrompt = I18n.format("options.angelica.fontconfig.searchprompt");
|
||||
this.testAreaPrompt = I18n.format("options.angelica.fontconfig.testareaprompt");
|
||||
this.parent = parent;
|
||||
this.currentPrimaryFontName = FontConfig.customFontNamePrimary;
|
||||
this.currentFallbackFontName = FontConfig.customFontNameFallback;
|
||||
@@ -51,65 +75,175 @@ public class FontConfigScreen extends GuiScreen {
|
||||
}
|
||||
}
|
||||
|
||||
SliderClone.Option optFontQuality = new SliderClone.Option(6, 72, 6);
|
||||
SliderClone.Option optShadowOffset = new SliderClone.Option(0, 2, 0.05f);
|
||||
SliderClone.Option optGlyphAspect = new SliderClone.Option(-1, 1, 0.05f);
|
||||
SliderClone.Option optGlyphScale = new SliderClone.Option(0.1f, 3, 0.05f);
|
||||
SliderClone.Option optWhitespaceScale = new SliderClone.Option(0.1f, 3, 0.05f);
|
||||
SliderClone.Option optGlyphSpacing = new SliderClone.Option(-2f, 2f, 0.05f);
|
||||
SliderClone.Option optFontAAMode = new SliderClone.Option(0, 2, 1);
|
||||
SliderClone.Option optFontAAStrength = new SliderClone.Option(1, 24, 1);
|
||||
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
searchBox = new GuiTextField(this.fontRendererObj, this.width / 2 - 120, 24, 240, 20);
|
||||
searchBox.setMaxStringLength(64);
|
||||
fontList = new FontList();
|
||||
testArea = new GuiTextField(this.fontRendererObj, this.width * 5 / 6 - this.width / 7, 63 - 10, this.width * 2 / 7, 20);
|
||||
testArea.setMaxStringLength(512);
|
||||
testArea.setText(I18n.format("options.angelica.fontconfig.testareaexample"));
|
||||
initButtons();
|
||||
}
|
||||
|
||||
private void initButtons() {
|
||||
this.buttonList.add(new IrisButton(this.width / 2 - 81 - 165, this.height - 20 - 7, 162, 20,
|
||||
final int halfWidth = this.width / 2;
|
||||
final int sliderSpacing = 4;
|
||||
|
||||
final int x1 = halfWidth - sliderWidth - sliderSpacing;
|
||||
final int x2 = halfWidth;
|
||||
final int x3 = halfWidth + sliderWidth + sliderSpacing;
|
||||
final int y3 = this.height - 65 + 2 * (sliderHeight + sliderSpacing);
|
||||
|
||||
this.buttonList.add(new IrisButton(x1 - sliderWidth / 2, y3 - sliderHeight / 2, sliderWidth, sliderHeight,
|
||||
FontConfig.enableCustomFont ? I18n.format("options.angelica.fontconfig.disable_custom_font") :
|
||||
I18n.format("options.angelica.fontconfig.enable_custom_font"), this::toggleCustomFont));
|
||||
this.buttonList.add(new IrisButton(this.width / 2 - 80, this.height - 20 - 7, 160, 20,
|
||||
this.buttonList.add(new IrisButton(x2 - sliderWidth / 2, y3 - sliderHeight / 2, sliderWidth, sliderHeight,
|
||||
I18n.format("options.angelica.fontconfig.reset_values"), this::resetValues));
|
||||
this.buttonList.add(new IrisButton(this.width / 2 - 81 + 165, this.height - 20 - 7, 162, 20,
|
||||
this.buttonList.add(new IrisButton(x3 - sliderWidth / 2, y3 - sliderHeight / 2, sliderWidth, sliderHeight,
|
||||
I18n.format("gui.done"), button -> this.onClose()));
|
||||
|
||||
// might refactor later, feeling too lazy at the moment
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 - 186, this.height - 40 - 11, 120, 20,
|
||||
optFontQuality, FontConfig.customFontQuality, this::setFontQuality,
|
||||
value -> I18n.format("options.angelica.fontconfig.font_quality", String.format("%2.0f", value)),
|
||||
"options.angelica.fontconfig.font_quality.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 - 186, this.height - 60 - 15, 120, 20,
|
||||
optShadowOffset, FontConfig.fontShadowOffset, value -> FontConfig.fontShadowOffset = value,
|
||||
value -> I18n.format("options.angelica.fontconfig.shadow_offset", String.format("x%3.2f", value)),
|
||||
"options.angelica.fontconfig.shadow_offset.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 - 62, this.height - 40 - 11, 120, 20,
|
||||
optGlyphAspect, FontConfig.glyphAspect, value -> FontConfig.glyphAspect = value,
|
||||
value -> I18n.format("options.angelica.fontconfig.glyph_aspect", String.format("%3.2f", value)),
|
||||
"options.angelica.fontconfig.glyph_aspect.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 - 62, this.height - 60 - 15, 120, 20,
|
||||
optGlyphScale, FontConfig.glyphScale, value -> FontConfig.glyphScale = value,
|
||||
value -> I18n.format("options.angelica.fontconfig.glyph_scale", String.format("x%3.2f", value)),
|
||||
"options.angelica.fontconfig.glyph_scale.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 + 62, this.height - 40 - 11, 120, 20,
|
||||
optWhitespaceScale, FontConfig.whitespaceScale, value -> FontConfig.whitespaceScale = value,
|
||||
value -> I18n.format("options.angelica.fontconfig.whitespace_scale", String.format("x%3.2f", value)),
|
||||
"options.angelica.fontconfig.whitespace_scale.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 + 62, this.height - 60 - 15, 120, 20,
|
||||
optGlyphSpacing, FontConfig.glyphSpacing, value -> FontConfig.glyphSpacing = value,
|
||||
value -> I18n.format("options.angelica.fontconfig.glyph_spacing", String.format("%3.2f", value)),
|
||||
"options.angelica.fontconfig.glyph_spacing.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 + 186, this.height - 40 - 11, 120, 20,
|
||||
optFontAAStrength, FontConfig.fontAAStrength, value -> FontConfig.fontAAStrength = value.intValue(),
|
||||
value -> I18n.format("options.angelica.fontconfig.font_aa_strength", String.format("%.0f", value)),
|
||||
"options.angelica.fontconfig.font_aa_strength.tooltip"));
|
||||
this.buttonList.add(new SliderClone( this.width / 2 - 60 + 186, this.height - 60 - 15, 120, 20,
|
||||
optFontAAMode, FontConfig.fontAAMode, value -> FontConfig.fontAAMode = value.intValue(),
|
||||
this::fontAAModeFormat,
|
||||
"options.angelica.fontconfig.aamode.tooltip"));
|
||||
backButton = new IrisButton(halfWidth - 20 - 224, this.height - 89 - 10, 40, 20,
|
||||
"<", button -> this.switchPage(-1));
|
||||
fwdButton = new IrisButton(halfWidth - 20 + 224, this.height - 89 - 10, 40, 20,
|
||||
">", button -> this.switchPage(1));
|
||||
this.buttonList.add(fwdButton);
|
||||
this.buttonList.add(backButton);
|
||||
|
||||
initSliders();
|
||||
}
|
||||
|
||||
private void initSliders() {
|
||||
ArrayList<SliderClone> sliders = new ArrayList<>();
|
||||
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optFontQuality)
|
||||
.initialValue(FontConfig.customFontQuality)
|
||||
.setter(this::setFontQuality)
|
||||
.langKey("options.angelica.fontconfig.font_quality")
|
||||
.formatString("%2.0f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optShadowOffset)
|
||||
.initialValue(FontConfig.fontShadowOffset)
|
||||
.setter(value -> FontConfig.fontShadowOffset = value)
|
||||
.langKey("options.angelica.fontconfig.shadow_offset")
|
||||
.formatString("x%3.2f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optGlyphAspect)
|
||||
.initialValue(FontConfig.glyphAspect)
|
||||
.setter(value -> FontConfig.glyphAspect = value)
|
||||
.langKey("options.angelica.fontconfig.glyph_aspect")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optGlyphScale)
|
||||
.initialValue(FontConfig.glyphScale)
|
||||
.setter(value -> FontConfig.glyphScale = value)
|
||||
.langKey("options.angelica.fontconfig.glyph_scale")
|
||||
.formatString("x%3.2f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optFontAAStrength)
|
||||
.initialValue(FontConfig.fontAAStrength)
|
||||
.setter(value -> FontConfig.fontAAStrength = value.intValue())
|
||||
.langKey("options.angelica.fontconfig.font_aa_strength")
|
||||
.formatString("%.0f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optFontAAMode)
|
||||
.initialValue(FontConfig.fontAAMode)
|
||||
.setter(value -> FontConfig.fontAAMode = value.intValue())
|
||||
.formatter(this::fontAAModeFormat)
|
||||
.langKey("options.angelica.fontconfig.aamode")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optWhitespaceScale)
|
||||
.initialValue(FontConfig.whitespaceScale)
|
||||
.setter(value -> FontConfig.whitespaceScale = value)
|
||||
.langKey("options.angelica.fontconfig.whitespace_scale")
|
||||
.formatString("x%3.2f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optGlyphSpacing)
|
||||
.initialValue(FontConfig.glyphSpacing)
|
||||
.setter(value -> FontConfig.glyphSpacing = value)
|
||||
.langKey("options.angelica.fontconfig.glyph_spacing")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optShadowCopies)
|
||||
.initialValue(FontConfig.shadowCopies)
|
||||
.setter(value -> FontConfig.shadowCopies = value.intValue())
|
||||
.langKey("options.angelica.fontconfig.shadow_copies")
|
||||
.formatString("%.0f")
|
||||
.build()
|
||||
);
|
||||
sliders.add(new SliderClone.SliderCloneBuilder()
|
||||
.width(sliderWidth)
|
||||
.height(sliderHeight)
|
||||
.option(optBoldCopies)
|
||||
.initialValue(FontConfig.boldCopies)
|
||||
.setter(value -> FontConfig.boldCopies = value.intValue())
|
||||
.langKey("options.angelica.fontconfig.bold_copies")
|
||||
.formatString("%.0f")
|
||||
.build()
|
||||
);
|
||||
|
||||
final int halfWidth = this.width / 2;
|
||||
final int sliderSpacing = 4;
|
||||
|
||||
final int x1 = halfWidth - sliderWidth - sliderSpacing;
|
||||
final int x2 = halfWidth;
|
||||
final int x3 = halfWidth + sliderWidth + sliderSpacing;
|
||||
final int y1 = this.height - 65;
|
||||
final int y2 = this.height - 65 + sliderHeight + sliderSpacing;
|
||||
|
||||
this.sliderPages = sliders.size() / 6;
|
||||
this.displayedSliderPage = Math.min(this.displayedSliderPage, this.sliderPages);
|
||||
|
||||
this.backButton.enabled = (this.displayedSliderPage != 0);
|
||||
this.fwdButton.enabled = (this.displayedSliderPage != this.sliderPages);
|
||||
|
||||
final int start = 6 * this.displayedSliderPage;
|
||||
final int end = Math.min(6 * (this.displayedSliderPage + 1), sliders.size());
|
||||
List<SliderClone> s = sliders.subList(start, end);
|
||||
try {
|
||||
s.get(0).setCenterPosition(x1, y1);
|
||||
s.get(1).setCenterPosition(x1, y2);
|
||||
s.get(2).setCenterPosition(x2, y1);
|
||||
s.get(3).setCenterPosition(x2, y2);
|
||||
s.get(4).setCenterPosition(x3, y1);
|
||||
s.get(5).setCenterPosition(x3, y2);
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
// we're on the last page and it has less than 6 sliders to display
|
||||
}
|
||||
this.buttonList.addAll(s);
|
||||
}
|
||||
|
||||
private void onClose() {
|
||||
@@ -141,6 +275,8 @@ public class FontConfigScreen extends GuiScreen {
|
||||
} catch (ConfigException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
currentPrimaryFontName = null;
|
||||
currentFallbackFontName = null;
|
||||
selectedPrimaryFontListPos = -1;
|
||||
selectedFallbackFontListPos = -1;
|
||||
FontStrategist.customFontInUse = false;
|
||||
@@ -156,6 +292,12 @@ public class FontConfigScreen extends GuiScreen {
|
||||
I18n.format("options.angelica.fontconfig.enable_custom_font");
|
||||
}
|
||||
|
||||
private void switchPage(int offset) {
|
||||
this.displayedSliderPage = MathHelper.clamp_int(this.displayedSliderPage + offset, 0, this.sliderPages);
|
||||
this.buttonList.removeIf(guiButton -> guiButton instanceof SliderClone);
|
||||
this.initSliders();
|
||||
}
|
||||
|
||||
private int qualityLast = FontConfig.customFontQuality;
|
||||
|
||||
private void setFontQuality(float quality) {
|
||||
@@ -179,7 +321,7 @@ public class FontConfigScreen extends GuiScreen {
|
||||
private long lastStillTime = 0;
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float delta) {
|
||||
super.drawDefaultBackground();
|
||||
drawBackground(0);
|
||||
fontList.drawScreen(mouseX, mouseY, delta);
|
||||
searchBox.drawTextBox();
|
||||
// I bet you thought this was drawn inside the search box, not on top of it.
|
||||
@@ -191,6 +333,34 @@ public class FontConfigScreen extends GuiScreen {
|
||||
drawCenteredString(this.fontRendererObj, this.title, (int) (this.width * 0.5), 8, 0xFFFFFF);
|
||||
drawCenteredString(this.fontRendererObj, I18n.format("options.angelica.fontconfig.currentfonts",
|
||||
FontConfig.customFontNamePrimary, FontConfig.customFontNameFallback), (int) (this.width * 0.5), this.height - 92, 0xFFFFFF);
|
||||
|
||||
if (this.testAreaInfo == null) {
|
||||
this.testAreaInfo = this.fontRendererObj.listFormattedStringToWidth(
|
||||
I18n.format("options.angelica.fontconfig.testareainfo"), this.width / 4
|
||||
);
|
||||
}
|
||||
int cumulativeY = 73;
|
||||
for (String s : this.testAreaInfo) {
|
||||
drawCenteredString(this.fontRendererObj, s, this.width * 5 / 6, cumulativeY, 0xFFFFFF);
|
||||
cumulativeY += this.fontRendererObj.FONT_HEIGHT;
|
||||
}
|
||||
cumulativeY += 4;
|
||||
this.testArea.yPosition = cumulativeY;
|
||||
this.testArea.drawTextBox();
|
||||
if (!this.testArea.isFocused() && this.testArea.getText().isEmpty()) {
|
||||
this.drawCenteredString(this.fontRendererObj, this.testAreaPrompt,
|
||||
this.testArea.xPosition + this.fontRendererObj.getStringWidth(this.testAreaPrompt) / 2 + 4,
|
||||
this.testArea.yPosition + this.testArea.height / 2 - 4, 0xFFFFFF);
|
||||
}
|
||||
List<String> testText = this.fontRendererObj.listFormattedStringToWidth(
|
||||
this.testArea.getText().replace('&', '§'), this.width / 4
|
||||
);
|
||||
cumulativeY += this.testArea.height + 4;
|
||||
for (String s : testText) {
|
||||
drawCenteredString(this.fontRendererObj, s, this.width * 5 / 6, cumulativeY, 0xFFFFFF);
|
||||
cumulativeY += this.fontRendererObj.FONT_HEIGHT;
|
||||
}
|
||||
|
||||
super.drawScreen(mouseX, mouseY, delta);
|
||||
|
||||
for (GuiButton guiButton : buttonList) {
|
||||
@@ -235,10 +405,18 @@ public class FontConfigScreen extends GuiScreen {
|
||||
if (this.searchBox.isFocused()) {
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
this.searchBox.setFocused(false);
|
||||
return;
|
||||
}
|
||||
this.searchBox.textboxKeyTyped(typedChar, keyCode);
|
||||
this.displayedFonts = filterFonts(this.searchBox.getText().toLowerCase());
|
||||
}
|
||||
if (this.testArea.isFocused()) {
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
this.testArea.setFocused(false);
|
||||
return;
|
||||
}
|
||||
this.testArea.textboxKeyTyped(typedChar, keyCode);
|
||||
}
|
||||
if (keyCode == Keyboard.KEY_ESCAPE) {
|
||||
this.onClose();
|
||||
}
|
||||
@@ -248,12 +426,14 @@ public class FontConfigScreen extends GuiScreen {
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.searchBox.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.testArea.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.fontList.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
this.searchBox.updateCursorCounter();
|
||||
this.testArea.updateCursorCounter();
|
||||
}
|
||||
|
||||
// this could be more efficient, but it's good enough as is
|
||||
@@ -281,7 +461,7 @@ public class FontConfigScreen extends GuiScreen {
|
||||
class FontList extends GuiSlot {
|
||||
|
||||
public FontList() {
|
||||
super(FontConfigScreen.this.mc, FontConfigScreen.this.width, FontConfigScreen.this.height, 52, FontConfigScreen.this.height - 100, 18);
|
||||
super(FontConfigScreen.this.mc, FontConfigScreen.this.width * 2 / 3, FontConfigScreen.this.height, 52, FontConfigScreen.this.height - 102, 18);
|
||||
}
|
||||
|
||||
private void mouseClicked(int mouseX, int mouseY, int mouseButton) {
|
||||
@@ -328,7 +508,7 @@ public class FontConfigScreen extends GuiScreen {
|
||||
|
||||
@Override
|
||||
protected int getScrollBarX() {
|
||||
return this.width * 11 / 12 - 5;
|
||||
return this.width * 15 / 16 - 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -340,7 +520,7 @@ public class FontConfigScreen extends GuiScreen {
|
||||
protected void elementClicked(int index, boolean doubleClicked, int mouseX, int mouseY) {}
|
||||
|
||||
protected void drawBackground() {
|
||||
drawDefaultBackground();
|
||||
// do nothing, the font list doesn't occupy the entire screen
|
||||
}
|
||||
|
||||
protected void drawSlot(int index, int x, int y, int p_148126_4_, Tessellator tessellator, int p_148126_6_, int p_148126_7_) {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.gtnewhorizons.angelica.client.gui;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
@@ -43,6 +46,53 @@ public class SliderClone extends GuiButton {
|
||||
this.tooltipKey = tooltipKey;
|
||||
}
|
||||
|
||||
public static SliderCloneBuilder builder() {
|
||||
return new SliderCloneBuilder();
|
||||
}
|
||||
|
||||
public void setCenterPosition(int x, int y) {
|
||||
this.xPosition = x - this.width / 2;
|
||||
this.yPosition = y - this.height / 2;
|
||||
}
|
||||
|
||||
@Accessors(fluent = true) @Setter
|
||||
public static class SliderCloneBuilder {
|
||||
private int x = 0, y = 0; // center position, not a corner
|
||||
private int width = 144, height = 20;
|
||||
private Option option;
|
||||
private float initialValue;
|
||||
private Consumer<Float> setter;
|
||||
private String formatString = "%3.2f";
|
||||
private String langKey;
|
||||
|
||||
// overrides: if null, these get set to default values
|
||||
private String tooltipKey;
|
||||
private Function<Float, String> formatter;
|
||||
|
||||
public SliderClone build() {
|
||||
if (this.formatter == null) {
|
||||
this.formatter = value -> I18n.format(this.langKey, String.format(this.formatString, value));
|
||||
}
|
||||
|
||||
if (this.tooltipKey == null) {
|
||||
this.tooltipKey = this.langKey + ".tooltip";
|
||||
}
|
||||
|
||||
return new SliderClone(
|
||||
this.x - this.width / 2,
|
||||
this.y - this.height / 2,
|
||||
this.width,
|
||||
this.height,
|
||||
this.option,
|
||||
this.initialValue,
|
||||
this.setter,
|
||||
this.formatter,
|
||||
this.tooltipKey
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns 0 if the button is disabled, 1 if the mouse is NOT hovering over this button and 2 if it IS hovering over
|
||||
* this button.
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gtnewhorizons.angelica.compat.iris;
|
||||
|
||||
/**
|
||||
* Interface implemented by BiomeGenBase via mixin to cache biome category.
|
||||
* This avoids recomputing the category every frame for shader uniforms.
|
||||
*/
|
||||
public interface BiomeCategoryCache {
|
||||
/**
|
||||
* Gets the cached biome category ordinal, or -1 if not yet computed.
|
||||
*/
|
||||
int iris$getCachedCategory();
|
||||
|
||||
/**
|
||||
* Sets the cached biome category ordinal.
|
||||
*/
|
||||
void iris$setCachedCategory(int category);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.gtnewhorizons.angelica.compat.iris;
|
||||
|
||||
import net.coderbot.iris.parsing.BiomeCategories;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Detects and categorizes biomes from popular modded biome mods using cached class checks.
|
||||
* Currently supports: BiomesOPlenty (BOP), Realistic World Gen (RWG)
|
||||
*/
|
||||
public class ModdedBiomeDetector {
|
||||
private static boolean initialized = false;
|
||||
|
||||
// BiomesOPlenty (BOP) cache - dimension-specific base classes
|
||||
// BOP 1.7.10 hierarchy: BOPBiome -> BOPEndBiome/BOPNetherBiome/BOPOverworldBiome -> specific biomes
|
||||
private static Class<?> bopEndBiomeClass = null;
|
||||
private static Class<?> bopNetherBiomeClass = null;
|
||||
private static Class<?> bopOceanBiomeClass = null;
|
||||
|
||||
// Realistic World Gen (RWG) cache - base biome classes that extend BiomeGenBase
|
||||
// LinkedHashMap maintains insertion order for deterministic behavior
|
||||
private static final Map<Class<?>, BiomeCategories> rwgClassMap = new LinkedHashMap<>();
|
||||
|
||||
private static synchronized void initialize() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
|
||||
initializeBOP();
|
||||
initializeRWG();
|
||||
}
|
||||
|
||||
private static void initializeBOP() {
|
||||
try {
|
||||
bopEndBiomeClass = Class.forName("biomesoplenty.common.biome.BOPEndBiome");
|
||||
bopNetherBiomeClass = Class.forName("biomesoplenty.common.biome.BOPNetherBiome");
|
||||
bopOceanBiomeClass = Class.forName("biomesoplenty.common.biome.BOPOceanBiome");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
// BOP not installed
|
||||
}
|
||||
}
|
||||
|
||||
private static void initializeRWG() {
|
||||
// RWG adds actual BiomeGenBase subclasses in rwg.biomes.base package
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeOcean", BiomeCategories.OCEAN);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeRiver", BiomeCategories.RIVER);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomePlains", BiomeCategories.PLAINS);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeColdPlains", BiomeCategories.PLAINS);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeHotPlains", BiomeCategories.PLAINS);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeHotDesert", BiomeCategories.DESERT);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeSnowDesert", BiomeCategories.DESERT); // Cold desert, but still desert
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeJungle", BiomeCategories.JUNGLE);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeTropicalIsland", BiomeCategories.JUNGLE); // Tropical islands are jungle-like
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeRedwood", BiomeCategories.FOREST); // Redwood/Sequoia forests
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeTemperateForest", BiomeCategories.FOREST);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeColdForest", BiomeCategories.TAIGA); // Cold forests are taiga-like
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeHotForest", BiomeCategories.FOREST);
|
||||
tryAddRWGClass("rwg.biomes.base.BaseBiomeSnowForest", BiomeCategories.TAIGA); // Snow forests are taiga
|
||||
}
|
||||
|
||||
private static void tryAddRWGClass(String className, BiomeCategories category) {
|
||||
try {
|
||||
final Class<?> clazz = Class.forName(className);
|
||||
rwgClassMap.put(clazz, category);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
// Class not available, RWG not installed or different version
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to detect the biome category for modded biomes.
|
||||
* Returns null if no modded biome detection applies.
|
||||
*/
|
||||
public static BiomeCategories detectModdedBiome(BiomeGenBase biome) {
|
||||
if (!initialized) {
|
||||
initialize();
|
||||
}
|
||||
|
||||
// BiomesOPlenty detection - dimension-specific classes give us clear categories
|
||||
if (bopEndBiomeClass != null && bopEndBiomeClass.isInstance(biome)) {
|
||||
return BiomeCategories.THE_END;
|
||||
}
|
||||
if (bopNetherBiomeClass != null && bopNetherBiomeClass.isInstance(biome)) {
|
||||
return BiomeCategories.NETHER;
|
||||
}
|
||||
if (bopOceanBiomeClass != null && bopOceanBiomeClass.isInstance(biome)) {
|
||||
return BiomeCategories.OCEAN;
|
||||
}
|
||||
// For other BOP overworld biomes (e.g., Alps, Arctic, BambooForest),
|
||||
// fall through to name/property-based detection
|
||||
|
||||
// Realistic World Gen detection
|
||||
for (Map.Entry<Class<?>, BiomeCategories> entry : rwgClassMap.entrySet()) {
|
||||
if (entry.getKey().isInstance(biome)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -9,35 +9,62 @@ import net.minecraft.util.MathHelper;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Singleton camera instance that tracks the current camera position and orientation.
|
||||
*/
|
||||
@Getter
|
||||
public class Camera {
|
||||
final Vector3d pos = new Vector3d();
|
||||
final BlockPos blockPos = new BlockPos();
|
||||
float pitch;
|
||||
float yaw;
|
||||
EntityLivingBase entity;
|
||||
boolean thirdPerson;
|
||||
final float partialTicks;
|
||||
public static final Camera INSTANCE = new Camera();
|
||||
|
||||
public Camera(EntityLivingBase entity, float partialTicks) {
|
||||
private final Vector3d pos = new Vector3d();
|
||||
private final BlockPos blockPos = new BlockPos();
|
||||
private final Vector3f offset = new Vector3f();
|
||||
private final Matrix4f inverseModelView = new Matrix4f();
|
||||
|
||||
private float pitch;
|
||||
private float yaw;
|
||||
private EntityLivingBase entity;
|
||||
private boolean thirdPerson;
|
||||
private float partialTicks;
|
||||
|
||||
private Camera() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the camera position and orientation based on the current entity and partial ticks.
|
||||
*
|
||||
* @param entity The entity to track (usually the render view entity)
|
||||
* @param partialTicks The partial tick time for interpolation
|
||||
*/
|
||||
public void update(EntityLivingBase entity, float partialTicks) {
|
||||
this.partialTicks = partialTicks;
|
||||
final Vector4f offset = new Vector4f(); // third person offset
|
||||
final Matrix4f inverseModelView = new Matrix4f(RenderingState.INSTANCE.getModelViewMatrix()).invert();
|
||||
inverseModelView.transform(offset);
|
||||
|
||||
final double camX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks + offset.x;
|
||||
final double camY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks + offset.y;
|
||||
final double camZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks + offset.z;
|
||||
this.entity = entity;
|
||||
|
||||
// Entity position (interpolated, at feet level)
|
||||
final double entityX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks;
|
||||
final double entityY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks;
|
||||
final double entityZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks;
|
||||
final double eyeHeight = entity.getEyeHeight();
|
||||
|
||||
thirdPerson = Minecraft.getMinecraft().gameSettings.thirdPersonView > 0;
|
||||
|
||||
final double camX, camY, camZ;
|
||||
offset.set(0, 0, 0);
|
||||
|
||||
if (thirdPerson) {
|
||||
// Third person: use inverse modelview to find camera offset
|
||||
inverseModelView.set(RenderingState.INSTANCE.getModelViewMatrix()).invert();
|
||||
inverseModelView.transformPosition(offset);
|
||||
}
|
||||
camX = entityX + offset.x;
|
||||
camY = entityY + eyeHeight + offset.y;
|
||||
camZ = entityZ + offset.z;
|
||||
|
||||
pos.set(camX, camY, camZ);
|
||||
blockPos.set(MathHelper.floor_double(camX), MathHelper.floor_double(camY), MathHelper.floor_double(camZ));
|
||||
pitch = entity.cameraPitch;
|
||||
yaw = entity.rotationYaw;
|
||||
thirdPerson = Minecraft.getMinecraft().gameSettings.thirdPersonView == 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gtnewhorizons.angelica.compat.mojang;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
|
||||
public final class GameModeUtil {
|
||||
private GameModeUtil() {
|
||||
}
|
||||
|
||||
public static boolean isSpectator() {
|
||||
final PlayerControllerMP controller = Minecraft.getMinecraft().playerController;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return controller.currentGameType.getID() == 3;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,16 @@ public class FontConfig {
|
||||
@Config.RangeFloat(min = 0F, max = 2F)
|
||||
public static float fontShadowOffset;
|
||||
|
||||
@Config.Comment("The number of shadows to be drawn behind text at various offsets.")
|
||||
@Config.DefaultInt(1)
|
||||
@Config.RangeInt(min = 1, max = 8)
|
||||
public static int shadowCopies;
|
||||
|
||||
@Config.Comment("The number of bold copies to be drawn behind text at various offsets.")
|
||||
@Config.DefaultInt(2)
|
||||
@Config.RangeInt(min = 1, max = 8)
|
||||
public static int boldCopies;
|
||||
|
||||
@Config.Comment("Influences the aspect ratio of each glyph.")
|
||||
@Config.DefaultFloat(0F)
|
||||
@Config.RangeFloat(min = -1F, max = 1F)
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.gtnewhorizons.angelica.glsm.stacks.LightModelStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.LightStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MaterialStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MatrixModeStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.TextureBindingStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ViewPortStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ISettableState;
|
||||
@@ -66,7 +67,6 @@ import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GLContext;
|
||||
import org.lwjgl.opengl.KHRDebug;
|
||||
|
||||
import java.lang.Math;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -1513,8 +1513,8 @@ public class GLStateManager {
|
||||
GL11.glNewList(list, mode);
|
||||
|
||||
List<IStateStack<?>> stacks = Feature.maskToFeatures(GL11.GL_ALL_ATTRIB_BITS);
|
||||
int size = stacks.size();
|
||||
|
||||
final int size = stacks.size();
|
||||
//noinspection ForLoopReplaceableByForEach
|
||||
for(int i = 0; i < size; i++) {
|
||||
IStateStack<?> stack = stacks.get(i);
|
||||
|
||||
@@ -1525,6 +1525,12 @@ public class GLStateManager {
|
||||
if(glListMode == GL11.GL_COMPILE) {
|
||||
pushState(GL11.GL_ALL_ATTRIB_BITS);
|
||||
}
|
||||
|
||||
// Band-aid fix to prevent color & texture leaks
|
||||
color.setRed(-1);
|
||||
color.setGreen(-1);
|
||||
color.setBlue(-1);
|
||||
textures.getTextureUnitBindings(getActiveTextureUnit()).setBinding(-1);
|
||||
}
|
||||
|
||||
public static void glEndList() {
|
||||
@@ -1540,12 +1546,33 @@ public class GLStateManager {
|
||||
final Set<Map.Entry<IStateStack<?>, ISettableState<?>>> changedStates = new ObjectArraySet<>();
|
||||
for(Map.Entry<IStateStack<?>, ISettableState<?>> entry : glListStates.entrySet()) {
|
||||
// If the current stack state is different than the copy of the state at the start
|
||||
if(!((ISettableState<?>)entry.getKey()).sameAs(entry.getValue())) {
|
||||
if(!((ISettableState<?>)entry.getKey()).sameAs(entry.getValue())
|
||||
&& !(entry.getKey() instanceof TextureBinding)
|
||||
&& !(entry.getKey() instanceof Color4)) {
|
||||
// Then we want to put into the change set the stack and the copy of the state now
|
||||
changedStates.add(new AbstractMap.SimpleEntry<>(entry.getKey(), (ISettableState<?>) ((ISettableState<?>) entry.getKey()).copy()));
|
||||
}
|
||||
}
|
||||
if(changedStates.size() != 0) {
|
||||
|
||||
final TextureBindingStack activeBinding = textures.getTextureUnitBindings(getActiveTextureUnit());
|
||||
if (activeBinding.getBinding() != -1) {
|
||||
changedStates.add(new AbstractMap.SimpleEntry<>(
|
||||
activeBinding,
|
||||
activeBinding.copy()
|
||||
));
|
||||
} else {
|
||||
activeBinding.set(glListStates.get(activeBinding));
|
||||
}
|
||||
if (color.getRed() != -1 || color.getGreen() != -1 || color.getBlue() != -1) {
|
||||
changedStates.add(new AbstractMap.SimpleEntry<>(
|
||||
color,
|
||||
color.copy()
|
||||
));
|
||||
} else {
|
||||
color.set(glListStates.get(color));
|
||||
}
|
||||
|
||||
if(!changedStates.isEmpty()) {
|
||||
glListChanges.put(glListId, changedStates);
|
||||
}
|
||||
if(glListMode == GL11.GL_COMPILE) {
|
||||
@@ -1566,8 +1593,9 @@ public class GLStateManager {
|
||||
} else {
|
||||
trySyncProgram();
|
||||
GL11.glCallList(list);
|
||||
if(glListChanges.containsKey(list)) {
|
||||
for(Map.Entry<IStateStack<?>, ISettableState<?>> entry : glListChanges.get(list)) {
|
||||
final Set<Map.Entry<IStateStack<?>, ISettableState<?>>> changes = glListChanges.get(list);
|
||||
if(changes != null) {
|
||||
for(Map.Entry<IStateStack<?>, ISettableState<?>> entry : changes) {
|
||||
// Set the stack to the cached state at the end of the call list compilation
|
||||
((ISettableState<?>)entry.getKey()).set(entry.getValue());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
package com.gtnewhorizons.angelica.glsm.debug;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.ITextureObject;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -9,14 +26,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
// Adapted from https://github.com/makamys/CoreTweaks/blob/master/src/main/java/makamys/coretweaks/util/OpenGLDebugging.java;
|
||||
// originally from https://github.com/TheGreyGhost/MinecraftByExample/blob/1-8final/src/main/java/minecraftbyexample/usefultools/OpenGLdebugging.java
|
||||
|
||||
@@ -30,7 +39,7 @@ public class OpenGLDebugging {
|
||||
public static final String GL_GET_INTEGERV = "glGetIntegerv()";
|
||||
public static final String GL_GET_FLOATV = "glGetFloatv()";
|
||||
|
||||
public class GLproperty {
|
||||
public static class GLproperty {
|
||||
|
||||
public GLproperty(int glConstant, String name, String description, String category, String fetchCommand) {
|
||||
this.gLConstant = glConstant;
|
||||
@@ -445,11 +454,12 @@ public class OpenGLDebugging {
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkGLSM() {
|
||||
public static String getGLSMErrorLog() {
|
||||
StringBuilder error = new StringBuilder();
|
||||
boolean mismatch = false;
|
||||
for (int i = 0; i < instance.propertyList.length; ++i) {
|
||||
final GLproperty gLProperty = instance.propertyList[i];
|
||||
if(gLProperty.fetchCommand.equals(GL_GET_FLOATV) && gLProperty.name.endsWith("_MATRIX")) {
|
||||
if (gLProperty.fetchCommand.equals(GL_GET_FLOATV) && gLProperty.name.endsWith("_MATRIX")) {
|
||||
final Matrix4f cached = gLProperty.getAsMatrix4f(true);
|
||||
final Matrix4f uncached = gLProperty.getAsMatrix4f(false);
|
||||
// Some precision issues due to RAD vs degrees, and translated (vs f)
|
||||
@@ -461,14 +471,87 @@ public class OpenGLDebugging {
|
||||
final String cached = gLProperty.getAsString(true);
|
||||
final String uncached = gLProperty.getAsString(false);
|
||||
if (!cached.equals(uncached)) {
|
||||
LOGGER.error("GLSM mismatch: " + gLProperty.name + " cached: " + cached + " uncached: " + uncached);
|
||||
error.append("GLSM mismatch: " + gLProperty.name + " cached: " + cached + " uncached: " + uncached);
|
||||
error.append('\n');
|
||||
mismatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
final TextureUnitArray textureUnits = GLStateManager.getTextures();
|
||||
int currentActiveTexture = GLStateManager.getActiveTextureUnit();
|
||||
for (int i = 0; i < textureUnits.textureMatricies.length; i++) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + i);
|
||||
final boolean cached = GLStateManager.glIsEnabled(GL11.GL_TEXTURE_2D);
|
||||
final boolean uncached = GL11.glIsEnabled(GL11.GL_TEXTURE_2D);
|
||||
if (cached != uncached) {
|
||||
error.append("GLSM mismatch: " + "GL_TEXTURE_2D" + " cached: " + cached + " uncached: " + uncached + ", texture unit: GL_TEXTURE" + i);
|
||||
error.append('\n');
|
||||
mismatch = true;
|
||||
}
|
||||
}
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + currentActiveTexture);
|
||||
if (!mismatch) {
|
||||
return null;
|
||||
}
|
||||
return error.toString();
|
||||
}
|
||||
|
||||
public static void checkGLSM() {
|
||||
String output = getGLSMErrorLog();
|
||||
|
||||
if (output == null) {
|
||||
LOGGER.info("GLSM state matches!");
|
||||
} else {
|
||||
LOGGER.error(output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyTexture(ResourceLocation resource, File output) {
|
||||
Object object = Minecraft.getMinecraft().renderEngine.mapTextureObjects.get(resource);
|
||||
|
||||
if (object != null) {
|
||||
copyTexture(((ITextureObject) object).getGlTextureId(), output);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyTexture(int textureID, File output) {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
|
||||
|
||||
int width = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
|
||||
int height = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT);
|
||||
|
||||
BufferedImage bufferedimage = new BufferedImage(width, height, 1);
|
||||
final int[] pixelValues = ((DataBufferInt) bufferedimage.getRaster().getDataBuffer()).getData();
|
||||
IntBuffer pixelBuffer = BufferUtils.createIntBuffer(pixelValues.length);
|
||||
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, pixelBuffer);
|
||||
pixelBuffer.get(pixelValues);
|
||||
|
||||
// Flip texture
|
||||
final int halfHeight = height / 2;
|
||||
final int[] rowBuffer = new int[width];
|
||||
for (int y = 0; y < halfHeight; y++) {
|
||||
final int top = y * width;
|
||||
final int bottom = (height - 1 - y) * width;
|
||||
|
||||
System.arraycopy(pixelValues, top, rowBuffer, 0, width);
|
||||
System.arraycopy(pixelValues, bottom, pixelValues, top, width);
|
||||
System.arraycopy(rowBuffer, 0, pixelValues, bottom, width);
|
||||
}
|
||||
|
||||
File dir = output.getParentFile();
|
||||
dir.mkdirs();
|
||||
copyBufferedImageToFile(bufferedimage, output);
|
||||
bufferedimage.flush();
|
||||
}
|
||||
|
||||
|
||||
private static void copyBufferedImageToFile(BufferedImage image, File file) {
|
||||
try {
|
||||
ImageIO.write(image, "png", file);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package com.gtnewhorizons.angelica.proxy;
|
||||
import static com.gtnewhorizons.angelica.loading.AngelicaTweaker.LOGGER;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.bettercrashes.BetterCrashesCompat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
@@ -12,15 +10,13 @@ import com.gtnewhorizons.angelica.config.CompatConfig;
|
||||
import com.gtnewhorizons.angelica.debug.F3Direction;
|
||||
import com.gtnewhorizons.angelica.debug.FrametimeGraph;
|
||||
import com.gtnewhorizons.angelica.debug.TPSGraph;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
|
||||
import com.gtnewhorizons.angelica.dynamiclights.DynamicLights;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.debug.OpenGLDebugging;
|
||||
import com.gtnewhorizons.angelica.hudcaching.HUDCaching;
|
||||
import com.gtnewhorizons.angelica.models.VanillaModels;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IGameSettingsExt;
|
||||
import com.gtnewhorizons.angelica.render.CloudRenderer;
|
||||
import com.gtnewhorizons.angelica.rendering.AngelicaBlockSafetyRegistry;
|
||||
import com.gtnewhorizons.angelica.utils.AssetLoader;
|
||||
import com.gtnewhorizons.angelica.zoom.Zoom;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
@@ -39,7 +35,6 @@ import jss.notfine.core.Settings;
|
||||
import me.jellysquid.mods.sodium.client.SodiumDebugScreenHandler;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.client.IrisDebugScreenHandler;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
@@ -76,7 +71,6 @@ public class ClientProxy extends CommonProxy {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
|
||||
AssetLoader.load();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -114,23 +108,6 @@ public class ClientProxy extends CommonProxy {
|
||||
Iris.INSTANCE.fmlInitEvent();
|
||||
FMLCommonHandler.instance().bus().register(Iris.INSTANCE);
|
||||
MinecraftForge.EVENT_BUS.register(Iris.INSTANCE);
|
||||
|
||||
VertexFormat.registerSetupBufferStateOverride((vertexFormat, l) -> {
|
||||
if (vertexFormat == DefaultVertexFormat.POSITION_COLOR_TEXTURE_LIGHT_NORMAL
|
||||
|| vertexFormat == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) {
|
||||
IrisVertexFormats.TERRAIN.setupBufferState(l);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
VertexFormat.registerClearBufferStateOverride(vertexFormat -> {
|
||||
if (vertexFormat == DefaultVertexFormat.POSITION_COLOR_TEXTURE_LIGHT_NORMAL
|
||||
|| vertexFormat == DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP) {
|
||||
IrisVertexFormats.TERRAIN.clearBufferState();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
@@ -139,8 +116,6 @@ public class ClientProxy extends CommonProxy {
|
||||
glsmKeyBinding = new KeyBinding("Print GLSM Debug", Keyboard.KEY_NONE, "Angelica");
|
||||
ClientRegistry.registerKeyBinding(glsmKeyBinding);
|
||||
|
||||
VanillaModels.init();
|
||||
|
||||
if (ModStatus.isBetterCrashesLoaded) {
|
||||
BetterCrashesCompat.init();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ package com.gtnewhorizons.angelica.render;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vbo.VBOManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vbo.VertexBuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
@@ -60,7 +59,6 @@ public class CloudRenderer implements IResourceManagerReloadListener {
|
||||
private final Minecraft mc = Minecraft.getMinecraft();
|
||||
private final ResourceLocation texture = new ResourceLocation("textures/environment/clouds.png");
|
||||
|
||||
private int displayList = -1;
|
||||
private VertexBuffer vbo;
|
||||
private int cloudMode = -1;
|
||||
private int renderDistance = -1;
|
||||
@@ -68,6 +66,7 @@ public class CloudRenderer implements IResourceManagerReloadListener {
|
||||
private int scaleMult = -1;
|
||||
|
||||
private DynamicTexture COLOR_TEX = null;
|
||||
private int texColor;
|
||||
|
||||
private int texW;
|
||||
private int texH;
|
||||
@@ -224,10 +223,7 @@ public class CloudRenderer implements IResourceManagerReloadListener {
|
||||
|
||||
vertices(tess);
|
||||
|
||||
if(displayList == -1) {
|
||||
this.displayList = VBOManager.generateDisplayLists(1);
|
||||
}
|
||||
this.vbo = VBOManager.registerVBO(this.displayList, TessellatorManager.stopCapturingToVBO(FORMAT));
|
||||
this.vbo = TessellatorManager.stopCapturingToVBO(FORMAT);
|
||||
}
|
||||
|
||||
private int fullCoord(double coord, int scale) { // Corrects misalignment of UV offset when on negative coords.
|
||||
@@ -305,7 +301,7 @@ public class CloudRenderer implements IResourceManagerReloadListener {
|
||||
|
||||
// Translate the texture.
|
||||
GLStateManager.glMatrixMode(GL11.GL_TEXTURE);
|
||||
GLStateManager.glTranslated(offU * PX_SIZE, offV * PX_SIZE, 0);
|
||||
GLStateManager.glTranslatef(offU * PX_SIZE, offV * PX_SIZE, 0);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
|
||||
GLStateManager.disableCull();
|
||||
@@ -328,15 +324,19 @@ public class CloudRenderer implements IResourceManagerReloadListener {
|
||||
b = tempB;
|
||||
}
|
||||
|
||||
if (COLOR_TEX == null)
|
||||
COLOR_TEX = new DynamicTexture(1, 1);
|
||||
|
||||
// Apply a color multiplier through a texture upload if shaders aren't supported.
|
||||
COLOR_TEX.getTextureData()[0] = 255 << 24
|
||||
final int newColor = 0xFF000000
|
||||
| ((int) (r * 255)) << 16
|
||||
| ((int) (g * 255)) << 8
|
||||
| (int) (b * 255);
|
||||
COLOR_TEX.updateDynamicTexture();
|
||||
if (texColor != newColor) {
|
||||
if (COLOR_TEX == null) {
|
||||
COLOR_TEX = new DynamicTexture(1, 1);
|
||||
}
|
||||
COLOR_TEX.getTextureData()[0] = newColor;
|
||||
COLOR_TEX.updateDynamicTexture();
|
||||
texColor = newColor;
|
||||
}
|
||||
|
||||
GLStateManager.glActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, COLOR_TEX.getGlTextureId());
|
||||
|
||||
@@ -4,19 +4,30 @@ package jss.notfine.render;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vbo.VBOManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import jss.notfine.core.Settings;
|
||||
import jss.util.RandomXoshiro256StarStar;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class RenderStars {
|
||||
|
||||
//private static final ResourceLocation locationStarsPng = new ResourceLocation("textures/colormap/stars.png");
|
||||
|
||||
public static void reloadStarRenderList(RenderGlobal render) {
|
||||
TessellatorManager.startCapturing();
|
||||
renderStars();
|
||||
VBOManager.registerVBO(render.starGLCallList, TessellatorManager.stopCapturingToVBO(DefaultVertexFormat.POSITION));
|
||||
|
||||
if(AngelicaConfig.enableVBO) {
|
||||
TessellatorManager.startCapturing();
|
||||
renderStars();
|
||||
VBOManager.registerVBO(render.starGLCallList, TessellatorManager.stopCapturingToVBO(DefaultVertexFormat.POSITION));
|
||||
} else {
|
||||
GL11.glPushMatrix();
|
||||
GL11.glNewList(render.starGLCallList, GL11.GL_COMPILE);
|
||||
renderStars();
|
||||
GL11.glEndList();
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public static void renderStars() {
|
||||
|
||||
@@ -16,7 +16,8 @@ public abstract class Type {
|
||||
public static final Primitive[] AllPrimitives = {Type.Boolean, Type.Int, Type.Float};
|
||||
|
||||
public static UniformType convert(Type type) {
|
||||
if (type == Type.Int || type == Type.Boolean) return UniformType.INT;
|
||||
if (type == Type.Int) return UniformType.INT;
|
||||
else if (type == Type.Boolean) return UniformType.INT;
|
||||
else if (type == Type.Float) return UniformType.FLOAT;
|
||||
else if (type == VectorType.VEC2) return UniformType.VEC2;
|
||||
else if (type == VectorType.VEC3) return UniformType.VEC3;
|
||||
|
||||
@@ -28,6 +28,7 @@ import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCache
|
||||
import me.jellysquid.mods.sodium.client.util.math.FrustumExtended;
|
||||
import me.jellysquid.mods.sodium.common.util.ListUtil;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.gl.shader.ProgramCreator;
|
||||
import net.coderbot.iris.layer.GbufferPrograms;
|
||||
import net.coderbot.iris.pipeline.ShadowRenderer;
|
||||
import net.coderbot.iris.shadows.ShadowRenderingState;
|
||||
@@ -51,6 +52,7 @@ import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import org.joml.Vector3d;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -359,6 +361,9 @@ public class SodiumWorldRenderer {
|
||||
if(AngelicaConfig.enableIris) {
|
||||
final Block block = tileEntity.getWorldObj().getBlock(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);
|
||||
CapturedRenderingState.INSTANCE.setCurrentBlockEntity(Block.getIdFromBlock(block));
|
||||
GL20.glVertexAttrib2s(ProgramCreator.MC_ENTITY, (short)-1, (short)-1);
|
||||
GL20.glVertexAttrib2f(ProgramCreator.MC_MID_TEX_COORD, 0.5f, 0.5f);
|
||||
GL20.glVertexAttrib4f(ProgramCreator.AT_TANGENT, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
GbufferPrograms.beginBlockEntities();
|
||||
}
|
||||
TileEntityRendererDispatcher.instance.renderTileEntity(tileEntity, partialTicks);
|
||||
|
||||
@@ -203,43 +203,45 @@ public class ProgramUniforms {
|
||||
final int size = sizeType.get(0);
|
||||
final int type = sizeType.get(1);
|
||||
|
||||
UniformType provided = uniformNames.get(name);
|
||||
final UniformType provided = uniformNames.get(name);
|
||||
final UniformType expected = getExpectedType(type);
|
||||
|
||||
if (provided == null && !name.startsWith("gl_")) {
|
||||
final String typeName = getTypeName(type);
|
||||
if(AngelicaConfig.enableHardcodedCustomUniforms) {
|
||||
// Legacy Checks from hardcoded custom uniforms
|
||||
if (provided == null && !name.startsWith("gl_")) {
|
||||
final String typeName = getTypeName(type);
|
||||
|
||||
if (isSampler(type) || isImage(type)) {
|
||||
// don't print a warning, samplers and images are managed elsewhere.
|
||||
// TODO: Detect unsupported samplers/images?
|
||||
continue;
|
||||
}
|
||||
if (isSampler(type) || isImage(type)) {
|
||||
// don't print a warning, samplers and images are managed elsewhere.
|
||||
continue;
|
||||
}
|
||||
|
||||
final UniformType externalProvided = externalUniformNames.get(name);
|
||||
final UniformType externalProvided = externalUniformNames.get(name);
|
||||
|
||||
if (externalProvided != null) {
|
||||
if (externalProvided != expected) {
|
||||
String expectedName;
|
||||
if (externalProvided != null) {
|
||||
if (externalProvided != expected) {
|
||||
final String expectedName;
|
||||
|
||||
if (expected != null) {
|
||||
expectedName = expected.toString();
|
||||
} else {
|
||||
expectedName = "(unsupported type: " + getTypeName(type) + ")";
|
||||
if (expected != null) {
|
||||
expectedName = expected.toString();
|
||||
} else {
|
||||
expectedName = "(unsupported type: " + getTypeName(type) + ")";
|
||||
}
|
||||
|
||||
Iris.logger.error("[" + this.name + "] Wrong uniform type for externally-managed uniform " + name + ": " + externalProvided + " is provided but the program expects " + expectedName + ".");
|
||||
}
|
||||
|
||||
Iris.logger.error("[" + this.name + "] Wrong uniform type for externally-managed uniform " + name + ": " + externalProvided + " is provided but the program expects " + expectedName + ".");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + typeName + " " + name);
|
||||
} else {
|
||||
Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + name + " of size " + size + " and type " + typeName);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + typeName + " " + name);
|
||||
} else {
|
||||
Iris.logger.warn("[" + this.name + "] Unsupported uniform: " + name + " of size " + size + " and type " + typeName);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (provided != null && provided != expected) {
|
||||
@@ -291,6 +293,7 @@ public class ProgramUniforms {
|
||||
return switch(type) {
|
||||
case GL11.GL_FLOAT -> "float";
|
||||
case GL11.GL_INT -> "int";
|
||||
case GL20.GL_BOOL -> "bool";
|
||||
case GL20.GL_FLOAT_MAT4 -> "mat4";
|
||||
case GL20.GL_FLOAT_VEC4 -> "vec4";
|
||||
case GL20.GL_FLOAT_MAT3 -> "mat3";
|
||||
@@ -316,12 +319,13 @@ public class ProgramUniforms {
|
||||
return switch (type) {
|
||||
case GL11.GL_FLOAT -> UniformType.FLOAT;
|
||||
case GL11.GL_INT -> UniformType.INT;
|
||||
case GL20.GL_BOOL -> UniformType.INT;
|
||||
case GL20.GL_FLOAT_MAT4 -> UniformType.MAT4;
|
||||
case GL20.GL_FLOAT_VEC4 -> UniformType.VEC4;
|
||||
case GL20.GL_INT_VEC4 -> UniformType.VEC4I;
|
||||
case GL20.GL_FLOAT_VEC3 -> UniformType.VEC3;
|
||||
case GL20.GL_FLOAT_MAT3 -> null;
|
||||
case GL20.GL_INT_VEC3 -> null;
|
||||
case GL20.GL_FLOAT_MAT3 -> UniformType.MAT3;
|
||||
case GL20.GL_INT_VEC3 -> UniformType.VEC3I;
|
||||
case GL20.GL_FLOAT_MAT2 -> null;
|
||||
case GL20.GL_FLOAT_VEC2 -> UniformType.VEC2;
|
||||
case GL20.GL_INT_VEC2 -> UniformType.VEC2I;
|
||||
|
||||
@@ -11,16 +11,22 @@ import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.KHRDebug;
|
||||
|
||||
public class ProgramCreator {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(ProgramCreator.class);
|
||||
|
||||
public static final int MC_ENTITY = 11;
|
||||
public static final int MC_MID_TEX_COORD = 12;
|
||||
public static final int AT_TANGENT = 13;
|
||||
public static final int AT_MIDBLOCK = 14;
|
||||
|
||||
public static int create(String name, GlShader... shaders) {
|
||||
int program = GL20.glCreateProgram();
|
||||
|
||||
// TODO: This is *really* hardcoded, we need to refactor this to support external calls to glBindAttribLocation
|
||||
RenderSystem.bindAttributeLocation(program, 11, "mc_Entity");
|
||||
RenderSystem.bindAttributeLocation(program, 12, "mc_midTexCoord");
|
||||
RenderSystem.bindAttributeLocation(program, 13, "at_tangent");
|
||||
RenderSystem.bindAttributeLocation(program, 14, "at_midBlock");
|
||||
RenderSystem.bindAttributeLocation(program, MC_ENTITY, "mc_Entity");
|
||||
RenderSystem.bindAttributeLocation(program, MC_MID_TEX_COORD, "mc_midTexCoord");
|
||||
RenderSystem.bindAttributeLocation(program, AT_TANGENT, "at_tangent");
|
||||
RenderSystem.bindAttributeLocation(program, AT_MIDBLOCK, "at_midBlock");
|
||||
|
||||
for (GlShader shader : shaders) {
|
||||
GL20.glAttachShader(program, shader.getHandle());
|
||||
|
||||
@@ -3,11 +3,13 @@ package net.coderbot.iris.gl.shader;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.gtnewhorizons.angelica.Tags;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import net.coderbot.iris.parsing.BiomeCategories;
|
||||
import net.coderbot.iris.pipeline.HandRenderer;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPhase;
|
||||
import net.coderbot.iris.shaderpack.StringPair;
|
||||
import net.coderbot.iris.texture.format.TextureFormat;
|
||||
import net.coderbot.iris.texture.format.TextureFormatLoader;
|
||||
import net.coderbot.iris.uniforms.VanillaBiomeList;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
@@ -88,6 +90,9 @@ public class StandardMacros {
|
||||
define(standardDefines, irisDefine);
|
||||
}
|
||||
|
||||
getBiomeCategoryDefines().forEach((category, ordinal) -> define(standardDefines, category, ordinal));
|
||||
getVanillaBiomeDefines().forEach((biome, id) -> define(standardDefines, biome, id));
|
||||
|
||||
return ImmutableList.copyOf(standardDefines);
|
||||
}
|
||||
|
||||
@@ -98,7 +103,7 @@ public class StandardMacros {
|
||||
* @see <a href="https://github.com/sp614x/optifine/blob/9c6a5b5326558ccc57c6490b66b3be3b2dc8cbef/OptiFineDoc/doc/shaders.txt#L696-L699">Optifine Doc</a>
|
||||
*/
|
||||
public static String getMcVersion() {
|
||||
final String version = Loader.MC_VERSION;;
|
||||
final String version = Loader.MC_VERSION;
|
||||
|
||||
String[] splitVersion = version.split("\\.");
|
||||
|
||||
@@ -117,10 +122,10 @@ public class StandardMacros {
|
||||
}
|
||||
|
||||
if (minor.length() == 1) {
|
||||
minor = 0 + minor;
|
||||
minor = "0" + minor;
|
||||
}
|
||||
if (bugfix.length() == 1) {
|
||||
bugfix = 0 + bugfix;
|
||||
bugfix = "0" + bugfix;
|
||||
}
|
||||
|
||||
return major + minor + bugfix;
|
||||
@@ -283,4 +288,47 @@ public class StandardMacros {
|
||||
|
||||
return defines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns biome category defines for use in shaders.
|
||||
* Generates #define CAT_<CATEGORY_NAME> <ordinal> for each BiomeCategories enum value.
|
||||
*
|
||||
* @return Map of biome category defines and their ordinal values
|
||||
*/
|
||||
public static Map<String, String> getBiomeCategoryDefines() {
|
||||
Map<String, String> defines = new HashMap<>();
|
||||
for (BiomeCategories category : BiomeCategories.values()) {
|
||||
defines.put("CAT_" + category.name(), String.valueOf(category.ordinal()));
|
||||
}
|
||||
return defines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns vanilla biome ID defines for use in shaders.
|
||||
* Generates #define BIOME_<BIOME_NAME> <biomeID> for all vanilla biomes.
|
||||
*
|
||||
* @return Map of vanilla biome defines and their IDs
|
||||
*/
|
||||
public static Map<String, String> getVanillaBiomeDefines() {
|
||||
final Map<String, String> defines = new HashMap<>();
|
||||
|
||||
for (VanillaBiomeList.BiomeEntry entry : VanillaBiomeList.getVanillaBiomes()) {
|
||||
if (entry.biome != null) {
|
||||
defines.put("BIOME_" + entry.name, String.valueOf(entry.biome.biomeID));
|
||||
}
|
||||
}
|
||||
|
||||
// Modern biomes that don't exist in 1.7.10 - add dummy IDs that will never match
|
||||
// This allows shader expressions to parse without errors while always evaluating to false/0
|
||||
// Using negative IDs to avoid conflicts with actual biome IDs
|
||||
defines.put("BIOME_NETHER_WASTES", "-1000");
|
||||
defines.put("BIOME_SOUL_SAND_VALLEY", "-1001");
|
||||
defines.put("BIOME_CRIMSON_FOREST", "-1002");
|
||||
defines.put("BIOME_WARPED_FOREST", "-1003");
|
||||
defines.put("BIOME_BASALT_DELTAS", "-1004");
|
||||
defines.put("BIOME_LUSH_CAVES", "-1005");
|
||||
defines.put("BIOME_PALE_GARDEN", "-1006");
|
||||
|
||||
return defines;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package net.coderbot.iris.gl.uniform;
|
||||
|
||||
public enum UniformType {
|
||||
INT,
|
||||
BOOL,
|
||||
FLOAT,
|
||||
MAT3,
|
||||
MAT4,
|
||||
VEC2,
|
||||
VEC2I,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.coderbot.iris.pipeline;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.InteractionHand;
|
||||
import com.gtnewhorizons.angelica.compat.toremove.RenderLayer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
@@ -26,7 +27,7 @@ public class HandRenderer {
|
||||
public static final float DEPTH = 0.125F;
|
||||
|
||||
private void setupGlState(RenderGlobal gameRenderer, Camera camera, float tickDelta) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
GL11.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GL11.glLoadIdentity();
|
||||
@@ -72,8 +73,7 @@ public class HandRenderer {
|
||||
mc.gameSettings.thirdPersonView == 0 &&
|
||||
!camera.getEntity().isPlayerSleeping() &&
|
||||
!mc.gameSettings.hideGUI &&
|
||||
// TODO: SPECTATOR
|
||||
// mc.playerController.currentGameType
|
||||
!GameModeUtil.isSpectator() &&
|
||||
!mc.playerController.enableEverythingIsScrewedUpMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import net.coderbot.iris.pipeline.transform.TransformPatcher;
|
||||
import net.coderbot.iris.shaderpack.ProgramSet;
|
||||
import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.uniforms.CommonUniforms;
|
||||
import net.coderbot.iris.uniforms.ExternallyManagedUniforms;
|
||||
import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
|
||||
@@ -143,6 +144,8 @@ public class SodiumTerrainPipeline {
|
||||
CommonUniforms.addDynamicUniforms(uniforms);
|
||||
customUniforms.assignTo(uniforms);
|
||||
|
||||
ExternallyManagedUniforms.addExternallyManagedUniforms116(uniforms);
|
||||
|
||||
BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniforms);
|
||||
return uniforms;
|
||||
}
|
||||
|
||||
@@ -18,13 +18,17 @@ import net.coderbot.iris.gl.blending.BlendModeFunction;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendInformation;
|
||||
import net.coderbot.iris.gl.texture.TextureScaleOverride;
|
||||
import net.coderbot.iris.pipeline.PatchedShaderPrinter;
|
||||
import net.coderbot.iris.shaderpack.option.ShaderPackOptions;
|
||||
import net.coderbot.iris.shaderpack.preprocessor.PropertiesPreprocessor;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
@@ -98,6 +102,15 @@ public class ShaderProperties {
|
||||
public ShaderProperties(String contents, ShaderPackOptions shaderPackOptions, Iterable<StringPair> environmentDefines) {
|
||||
final String preprocessedContents = PropertiesPreprocessor.preprocessSource(contents, shaderPackOptions, environmentDefines);
|
||||
|
||||
if (PatchedShaderPrinter.prettyPrintShaders) {
|
||||
try {
|
||||
Files.write(Minecraft.getMinecraft().mcDataDir.toPath().resolve("preprocessed.properties"), preprocessedContents.getBytes(StandardCharsets.UTF_8));
|
||||
Files.write(Minecraft.getMinecraft().mcDataDir.toPath().resolve("original.properties"), contents.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
final Properties preprocessed = new OrderBackedProperties();
|
||||
final Properties original = new OrderBackedProperties();
|
||||
try {
|
||||
@@ -181,7 +194,7 @@ public class ShaderProperties {
|
||||
});
|
||||
|
||||
handlePassDirective("alphaTest.", key, value, pass -> {
|
||||
if ("off".equals(value)) {
|
||||
if ("off".equals(value) || "false".equals(value)) {
|
||||
alphaTestOverrides.put(pass, AlphaTestOverride.OFF);
|
||||
return;
|
||||
}
|
||||
|
||||
+20
-14
@@ -6,6 +6,7 @@ import net.coderbot.iris.shaderpack.option.ShaderPackOptions;
|
||||
import org.anarres.cpp.Feature;
|
||||
import org.anarres.cpp.LexerException;
|
||||
import org.anarres.cpp.Preprocessor;
|
||||
import org.anarres.cpp.PreprocessorCommand;
|
||||
import org.anarres.cpp.StringLexerSource;
|
||||
import org.anarres.cpp.Token;
|
||||
|
||||
@@ -14,18 +15,19 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PropertiesPreprocessor {
|
||||
// Derived from ShaderProcessor.glslPreprocessSource, which is derived from GlShader from Canvas, licenced under LGPL
|
||||
public static String preprocessSource(String source, ShaderPackOptions shaderPackOptions, Iterable<StringPair> environmentDefines) {
|
||||
if (source.contains(PropertyCollectingListener.PROPERTY_MARKER)) {
|
||||
if (source.contains(PropertyCollectingListener.PROPERTY_MARKER) || source.contains("IRIS_PASSTHROUGHBACKSLASH")) {
|
||||
throw new RuntimeException("Some shader author is trying to exploit internal Iris implementation details, stop!");
|
||||
}
|
||||
|
||||
List<String> booleanValues = getBooleanValues(shaderPackOptions);
|
||||
Map<String, String> stringValues = getStringValues(shaderPackOptions);
|
||||
final List<String> booleanValues = getBooleanValues(shaderPackOptions);
|
||||
final Map<String, String> stringValues = getStringValues(shaderPackOptions);
|
||||
|
||||
try (Preprocessor pp = new Preprocessor()) {
|
||||
for (String value : booleanValues) {
|
||||
@@ -57,7 +59,7 @@ public class PropertiesPreprocessor {
|
||||
throw new RuntimeException("Some shader author is trying to exploit internal Iris implementation details, stop!");
|
||||
}
|
||||
|
||||
Preprocessor preprocessor = new Preprocessor();
|
||||
final Preprocessor preprocessor = new Preprocessor();
|
||||
|
||||
try {
|
||||
for (StringPair envDefine : environmentDefines) {
|
||||
@@ -78,19 +80,23 @@ public class PropertiesPreprocessor {
|
||||
// Not super efficient, but this removes trailing whitespace on lines, fixing an issue with whitespace after
|
||||
// line continuations (see PreprocessorTest#testWeirdPropertiesLineContinuation)
|
||||
// Required for Voyager Shader
|
||||
source = Arrays.stream(source.split("\\R")).map(String::trim)
|
||||
source = Arrays.stream(source.split("\\R")).map(String::trim).filter(s -> !s.isEmpty())
|
||||
.map(line -> {
|
||||
if (line.startsWith("#")) {
|
||||
// In PropertyCollectingListener we suppress "unknown preprocessor directive errors" and
|
||||
// assume the line to be a comment, since in .properties files `#` also functions as a comment
|
||||
// marker.
|
||||
return line;
|
||||
} else {
|
||||
// This is a hack to ensure that non-macro lines don't have any preprocessing applied...
|
||||
// In properties files, we don't substitute #define values except on macro lines.
|
||||
return "#warning IRIS_PASSTHROUGH " + line;
|
||||
for (PreprocessorCommand command : PreprocessorCommand.values()) {
|
||||
if (line.startsWith("#" + (command.name().replace("PP_", "").toLowerCase(Locale.ROOT)))) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
// In PropertyCollectingListener we suppress "unknown preprocessor directive errors" and
|
||||
// assume the line to be a comment, since in .properties files `#` also functions as a comment
|
||||
// marker.
|
||||
return line.replace("#", "");
|
||||
}).collect(Collectors.joining("\n")) + "\n";
|
||||
// TODO: This is a horrible fix to trick the preprocessor into not seeing the backslashes during processing. We need a better way to do this.
|
||||
source = source.replace("\\", "IRIS_PASSTHROUGHBACKSLASH");
|
||||
|
||||
preprocessor.addInput(new StringLexerSource(source, true));
|
||||
preprocessor.addFeature(Feature.KEEPCOMMENTS);
|
||||
@@ -110,7 +116,7 @@ public class PropertiesPreprocessor {
|
||||
|
||||
source = builder.toString();
|
||||
|
||||
return listener.collectLines() + source;
|
||||
return (listener.collectLines() + source).replace("IRIS_PASSTHROUGHBACKSLASH", "\\");
|
||||
}
|
||||
|
||||
private static List<String> getBooleanValues(ShaderPackOptions shaderPackOptions) {
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferWriterNio;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.util.Norm3b;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class EntityVertexBufferWriterNio extends VertexBufferWriterNio implements QuadVertexSink, GlyphVertexSink {
|
||||
private static final int STRIDE = IrisVertexFormats.ENTITY.getVertexSize();
|
||||
|
||||
private final QuadViewEntity.QuadViewEntityNio quad = new QuadViewEntity.QuadViewEntityNio();
|
||||
private final Vector3f saveNormal = new Vector3f();
|
||||
|
||||
private int vertexCount;
|
||||
private float uSum;
|
||||
private float vSum;
|
||||
|
||||
public EntityVertexBufferWriterNio(VertexBufferView backingBuffer) {
|
||||
super(backingBuffer, ExtendedQuadVertexType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) {
|
||||
int i = this.writeOffset;
|
||||
ByteBuffer buffer = this.byteBuffer;
|
||||
|
||||
vertexCount++;
|
||||
uSum += u;
|
||||
vSum += v;
|
||||
|
||||
buffer.putFloat(i, x);
|
||||
buffer.putFloat(i + 4, y);
|
||||
buffer.putFloat(i + 8, z);
|
||||
buffer.putInt(i + 12, color);
|
||||
buffer.putFloat(i + 16, u);
|
||||
buffer.putFloat(i + 20, v);
|
||||
buffer.putInt(i + 24, overlay);
|
||||
buffer.putInt(i + 28, light);
|
||||
|
||||
if (vertexCount == 4) {
|
||||
this.endQuad(normal);
|
||||
}
|
||||
|
||||
this.advance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeGlyph(float x, float y, float z, int color, float u, float v, int light) {
|
||||
writeQuad(x, y, z, color, u, v, light, 0, 0);
|
||||
}
|
||||
|
||||
private void endQuad(int normal) {
|
||||
this.vertexCount = 0;
|
||||
|
||||
int i = this.writeOffset;
|
||||
ByteBuffer buffer = this.byteBuffer;
|
||||
|
||||
uSum *= 0.25;
|
||||
vSum *= 0.25;
|
||||
|
||||
quad.setup(buffer, i, STRIDE);
|
||||
|
||||
float normalX, normalY, normalZ;
|
||||
|
||||
if (normal == 0) {
|
||||
NormalHelper.computeFaceNormal(saveNormal, quad);
|
||||
normalX = saveNormal.x;
|
||||
normalY = saveNormal.y;
|
||||
normalZ = saveNormal.z;
|
||||
normal = NormalHelper.packNormal(saveNormal, 0.0F);
|
||||
} else {
|
||||
normalX = Norm3b.unpackX(normal);
|
||||
normalY = Norm3b.unpackY(normal);
|
||||
normalZ = Norm3b.unpackZ(normal);
|
||||
}
|
||||
|
||||
int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad);
|
||||
|
||||
for (int vertex = 0; vertex < 4; vertex++) {
|
||||
buffer.putFloat(i + 36 - STRIDE * vertex, uSum);
|
||||
buffer.putFloat(i + 40 - STRIDE * vertex, vSum);
|
||||
buffer.putInt(i + 32 - STRIDE * vertex, normal);
|
||||
buffer.putInt(i + 44 - STRIDE * vertex, tangent);
|
||||
}
|
||||
|
||||
uSum = 0;
|
||||
vSum = 0;
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.*;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferWriterUnsafe;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.util.Norm3b;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class EntityVertexBufferWriterUnsafe extends VertexBufferWriterUnsafe implements QuadVertexSink, GlyphVertexSink {
|
||||
private static final int STRIDE = IrisVertexFormats.ENTITY.getVertexSize();
|
||||
|
||||
private final QuadViewEntity.QuadViewEntityUnsafe quad = new QuadViewEntity.QuadViewEntityUnsafe();
|
||||
private final Vector3f saveNormal = new Vector3f();
|
||||
|
||||
private int vertexCount;
|
||||
private float uSum;
|
||||
private float vSum;
|
||||
|
||||
public EntityVertexBufferWriterUnsafe(VertexBufferView backingBuffer) {
|
||||
super(backingBuffer, ExtendedQuadVertexType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) {
|
||||
long i = this.writePointer;
|
||||
|
||||
vertexCount++;
|
||||
uSum += u;
|
||||
vSum += v;
|
||||
|
||||
memPutFloat(i, x);
|
||||
memPutFloat(i + 4, y);
|
||||
memPutFloat(i + 8, z);
|
||||
memPutInt(i + 12, color);
|
||||
memPutFloat(i + 16, u);
|
||||
memPutFloat(i + 20, v);
|
||||
memPutInt(i + 24, overlay);
|
||||
memPutInt(i + 28, light);
|
||||
|
||||
if (vertexCount == 4) {
|
||||
this.endQuad(normal);
|
||||
}
|
||||
|
||||
this.advance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeGlyph(float x, float y, float z, int color, float u, float v, int light) {
|
||||
writeQuad(x, y, z, color, u, v, light, 0, 0);
|
||||
}
|
||||
|
||||
private void endQuad(int normal) {
|
||||
this.vertexCount = 0;
|
||||
|
||||
long i = this.writePointer;
|
||||
|
||||
uSum *= 0.25;
|
||||
vSum *= 0.25;
|
||||
|
||||
quad.setup(writePointer, STRIDE);
|
||||
|
||||
float normalX, normalY, normalZ;
|
||||
|
||||
if (normal == 0) {
|
||||
NormalHelper.computeFaceNormal(saveNormal, quad);
|
||||
normalX = saveNormal.x;
|
||||
normalY = saveNormal.y;
|
||||
normalZ = saveNormal.z;
|
||||
normal = NormalHelper.packNormal(saveNormal, 0.0F);
|
||||
} else {
|
||||
normalX = Norm3b.unpackX(normal);
|
||||
normalY = Norm3b.unpackY(normal);
|
||||
normalZ = Norm3b.unpackZ(normal);
|
||||
}
|
||||
|
||||
int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad);
|
||||
|
||||
for (long vertex = 0; vertex < 4; vertex++) {
|
||||
memPutFloat(i + 36 - STRIDE * vertex, uSum);
|
||||
memPutFloat(i + 40 - STRIDE * vertex, vSum);
|
||||
memPutInt(i + 32 - STRIDE * vertex, normal);
|
||||
memPutInt(i + 44 - STRIDE * vertex, tangent);
|
||||
}
|
||||
|
||||
uSum = 0;
|
||||
vSum = 0;
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.compat.toremove.VertexConsumer;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.writer.GlyphVertexWriterFallback;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.type.BlittableVertexType;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.type.VanillaVertexType;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
|
||||
public class ExtendedGlyphVertexType implements VanillaVertexType<GlyphVertexSink>, BlittableVertexType<GlyphVertexSink> {
|
||||
public static final ExtendedGlyphVertexType INSTANCE = new ExtendedGlyphVertexType();
|
||||
|
||||
@Override
|
||||
public GlyphVertexSink createFallbackWriter(VertexConsumer vertexConsumer) {
|
||||
return new GlyphVertexWriterFallback(vertexConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GlyphVertexSink createBufferWriter(VertexBufferView buffer, boolean direct) {
|
||||
return direct ? new GlyphVertexBufferWriterUnsafe(buffer) : new GlyphVertexBufferWriterNio(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat getVertexFormat() {
|
||||
return IrisVertexFormats.TERRAIN;
|
||||
}
|
||||
|
||||
public BlittableVertexType<GlyphVertexSink> asBlittable() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.compat.toremove.VertexConsumer;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.writer.QuadVertexWriterFallback;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.type.BlittableVertexType;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.type.VanillaVertexType;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
|
||||
public class ExtendedQuadVertexType implements VanillaVertexType<QuadVertexSink>, BlittableVertexType<QuadVertexSink> {
|
||||
public static final ExtendedQuadVertexType INSTANCE = new ExtendedQuadVertexType();
|
||||
|
||||
@Override
|
||||
public QuadVertexSink createFallbackWriter(VertexConsumer vertexConsumer) {
|
||||
return new QuadVertexWriterFallback(vertexConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuadVertexSink createBufferWriter(VertexBufferView buffer, boolean direct) {
|
||||
return direct ? new EntityVertexBufferWriterUnsafe(buffer) : new EntityVertexBufferWriterNio(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexFormat getVertexFormat() {
|
||||
return IrisVertexFormats.ENTITY;
|
||||
}
|
||||
|
||||
public BlittableVertexType<QuadVertexSink> asBlittable() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferWriterNio;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.util.Norm3b;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class GlyphVertexBufferWriterNio extends VertexBufferWriterNio implements QuadVertexSink, GlyphVertexSink {
|
||||
private static final int STRIDE = IrisVertexFormats.TERRAIN.getVertexSize();
|
||||
|
||||
private final QuadViewEntity.QuadViewEntityNio quad = new QuadViewEntity.QuadViewEntityNio();
|
||||
private final Vector3f saveNormal = new Vector3f();
|
||||
|
||||
private int vertexCount;
|
||||
private float uSum;
|
||||
private float vSum;
|
||||
|
||||
public GlyphVertexBufferWriterNio(VertexBufferView backingBuffer) {
|
||||
super(backingBuffer, ExtendedGlyphVertexType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) {
|
||||
int i = this.writeOffset;
|
||||
ByteBuffer buffer = this.byteBuffer;
|
||||
|
||||
vertexCount++;
|
||||
uSum += u;
|
||||
vSum += v;
|
||||
|
||||
buffer.putFloat(i, x);
|
||||
buffer.putFloat(i + 4, y);
|
||||
buffer.putFloat(i + 8, z);
|
||||
buffer.putInt(i + 12, color);
|
||||
buffer.putFloat(i + 16, u);
|
||||
buffer.putFloat(i + 20, v);
|
||||
buffer.putInt(i + 24, light);
|
||||
|
||||
if (vertexCount == 4) {
|
||||
this.endQuad(normal);
|
||||
}
|
||||
|
||||
this.advance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeGlyph(float x, float y, float z, int color, float u, float v, int light) {
|
||||
writeQuad(x, y, z, color, u, v, light, 0, 0);
|
||||
}
|
||||
|
||||
private void endQuad(int normal) {
|
||||
this.vertexCount = 0;
|
||||
|
||||
int i = this.writeOffset;
|
||||
ByteBuffer buffer = this.byteBuffer;
|
||||
|
||||
uSum *= 0.25;
|
||||
vSum *= 0.25;
|
||||
|
||||
quad.setup(byteBuffer, writeOffset, STRIDE);
|
||||
|
||||
float normalX, normalY, normalZ;
|
||||
|
||||
if (normal == 0) {
|
||||
NormalHelper.computeFaceNormal(saveNormal, quad);
|
||||
normalX = saveNormal.x;
|
||||
normalY = saveNormal.y;
|
||||
normalZ = saveNormal.z;
|
||||
normal = NormalHelper.packNormal(saveNormal, 0.0F);
|
||||
} else {
|
||||
normalX = Norm3b.unpackX(normal);
|
||||
normalY = Norm3b.unpackY(normal);
|
||||
normalZ = Norm3b.unpackZ(normal);
|
||||
}
|
||||
|
||||
int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad);
|
||||
|
||||
for (int vertex = 0; vertex < 4; vertex++) {
|
||||
buffer.putFloat(i + 36 - STRIDE * vertex, uSum);
|
||||
buffer.putFloat(i + 40 - STRIDE * vertex, vSum);
|
||||
buffer.putInt(i + 28 - STRIDE * vertex, normal);
|
||||
buffer.putInt(i + 44 - STRIDE * vertex, tangent);
|
||||
}
|
||||
|
||||
uSum = 0;
|
||||
vSum = 0;
|
||||
}
|
||||
}
|
||||
-92
@@ -1,92 +0,0 @@
|
||||
package net.coderbot.iris.sodium.vertex_format.entity_xhfp;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.*;
|
||||
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferView;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.buffer.VertexBufferWriterUnsafe;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.glyph.GlyphVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.model.vertex.formats.quad.QuadVertexSink;
|
||||
import me.jellysquid.mods.sodium.client.util.Norm3b;
|
||||
import net.coderbot.iris.vertices.IrisVertexFormats;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class GlyphVertexBufferWriterUnsafe extends VertexBufferWriterUnsafe implements QuadVertexSink, GlyphVertexSink {
|
||||
private static final int STRIDE = IrisVertexFormats.TERRAIN.getVertexSize();
|
||||
|
||||
private final QuadViewEntity.QuadViewEntityUnsafe quad = new QuadViewEntity.QuadViewEntityUnsafe();
|
||||
private final Vector3f saveNormal = new Vector3f();
|
||||
|
||||
private int vertexCount;
|
||||
private float uSum;
|
||||
private float vSum;
|
||||
|
||||
public GlyphVertexBufferWriterUnsafe(VertexBufferView backingBuffer) {
|
||||
super(backingBuffer, ExtendedGlyphVertexType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeQuad(float x, float y, float z, int color, float u, float v, int light, int overlay, int normal) {
|
||||
long i = this.writePointer;
|
||||
|
||||
vertexCount++;
|
||||
uSum += u;
|
||||
vSum += v;
|
||||
|
||||
memPutFloat(i, x);
|
||||
memPutFloat(i + 4, y);
|
||||
memPutFloat(i + 8, z);
|
||||
memPutInt(i + 12, color);
|
||||
memPutFloat(i + 16, u);
|
||||
memPutFloat(i + 20, v);
|
||||
memPutInt(i + 24, light);
|
||||
|
||||
if (vertexCount == 4) {
|
||||
this.endQuad(normal);
|
||||
}
|
||||
|
||||
this.advance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeGlyph(float x, float y, float z, int color, float u, float v, int light) {
|
||||
writeQuad(x, y, z, color, u, v, light, 0, 0);
|
||||
}
|
||||
|
||||
private void endQuad(int normal) {
|
||||
this.vertexCount = 0;
|
||||
|
||||
long i = this.writePointer;
|
||||
|
||||
uSum *= 0.25;
|
||||
vSum *= 0.25;
|
||||
|
||||
quad.setup(writePointer, STRIDE);
|
||||
|
||||
float normalX, normalY, normalZ;
|
||||
|
||||
if (normal == 0) {
|
||||
NormalHelper.computeFaceNormal(saveNormal, quad);
|
||||
normalX = saveNormal.x;
|
||||
normalY = saveNormal.y;
|
||||
normalZ = saveNormal.z;
|
||||
normal = NormalHelper.packNormal(saveNormal, 0.0F);
|
||||
} else {
|
||||
normalX = Norm3b.unpackX(normal);
|
||||
normalY = Norm3b.unpackY(normal);
|
||||
normalZ = Norm3b.unpackZ(normal);
|
||||
}
|
||||
|
||||
int tangent = NormalHelper.computeTangent(normalX, normalY, normalZ, quad);
|
||||
|
||||
for (long vertex = 0; vertex < 4; vertex++) {
|
||||
memPutFloat(i + 36 - STRIDE * vertex, uSum);
|
||||
memPutFloat(i + 40 - STRIDE * vertex, vSum);
|
||||
memPutInt(i + 28 - STRIDE * vertex, normal);
|
||||
memPutInt(i + 44 - STRIDE * vertex, tangent);
|
||||
}
|
||||
|
||||
uSum = 0;
|
||||
vSum = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.coderbot.iris.texture.pbr;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -32,13 +32,13 @@ public enum PBRType {
|
||||
public ResourceLocation appendToFileLocation(ResourceLocation location) {
|
||||
String domain = location.getResourceDomain();
|
||||
String path = location.getResourcePath();
|
||||
String newPath;
|
||||
|
||||
try {
|
||||
URI uri = new URI(null, null, path, null);
|
||||
String cleanPath = uri.getPath();
|
||||
String newPath;
|
||||
|
||||
int extensionIndex = FilenameUtils.indexOfExtension(cleanPath);
|
||||
int extensionIndex = safeIndexOfExtension(cleanPath);
|
||||
if (extensionIndex != -1) {
|
||||
newPath = cleanPath.substring(0, extensionIndex) + suffix + cleanPath.substring(extensionIndex);
|
||||
} else {
|
||||
@@ -48,17 +48,11 @@ public enum PBRType {
|
||||
URI newUri = new URI(null, null, newPath, null);
|
||||
newPath = newUri.getPath();
|
||||
|
||||
return new ResourceLocation(domain, newPath);
|
||||
} catch (URISyntaxException e) {
|
||||
String fallback = path.replace(':', '/');
|
||||
int extensionIndex = FilenameUtils.indexOfExtension(fallback);
|
||||
if (extensionIndex != -1) {
|
||||
newPath = fallback.substring(0, extensionIndex) + suffix + fallback.substring(extensionIndex);
|
||||
} else {
|
||||
newPath = fallback + suffix;
|
||||
}
|
||||
Iris.logger.error("Failed to append PBR suffix to resource location for " + path, e);
|
||||
return location;
|
||||
}
|
||||
|
||||
return new ResourceLocation(domain, newPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,4 +70,19 @@ public enum PBRType {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper method to safely find the index of the file extension
|
||||
// Using this to avoid issues with ':' in paths (any block with meta).
|
||||
private static int safeIndexOfExtension(String input) {
|
||||
if (input == null) return -1;
|
||||
|
||||
// Avoid dots in directory names or leading/trailing dots
|
||||
int lastSlash = Math.max(input.lastIndexOf('/'), input.lastIndexOf('\\'));
|
||||
int nameStart = lastSlash + 1;
|
||||
int lastDot = input.lastIndexOf('.');
|
||||
if (lastDot == -1 || lastDot <= nameStart || lastDot == input.length() - 1) {
|
||||
return -1;
|
||||
}
|
||||
return lastDot;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.iris.BiomeCategoryCache;
|
||||
import com.gtnewhorizons.angelica.compat.iris.ModdedBiomeDetector;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.coderbot.iris.parsing.BiomeCategories;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraft.world.biome.BiomeGenBeach;
|
||||
import net.minecraft.world.biome.BiomeGenDesert;
|
||||
import net.minecraft.world.biome.BiomeGenEnd;
|
||||
import net.minecraft.world.biome.BiomeGenForest;
|
||||
import net.minecraft.world.biome.BiomeGenHell;
|
||||
import net.minecraft.world.biome.BiomeGenHills;
|
||||
import net.minecraft.world.biome.BiomeGenJungle;
|
||||
import net.minecraft.world.biome.BiomeGenMesa;
|
||||
import net.minecraft.world.biome.BiomeGenMushroomIsland;
|
||||
import net.minecraft.world.biome.BiomeGenMutated;
|
||||
import net.minecraft.world.biome.BiomeGenOcean;
|
||||
import net.minecraft.world.biome.BiomeGenPlains;
|
||||
import net.minecraft.world.biome.BiomeGenRiver;
|
||||
import net.minecraft.world.biome.BiomeGenSavanna;
|
||||
import net.minecraft.world.biome.BiomeGenSnow;
|
||||
import net.minecraft.world.biome.BiomeGenStoneBeach;
|
||||
import net.minecraft.world.biome.BiomeGenSwamp;
|
||||
import net.minecraft.world.biome.BiomeGenTaiga;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.coderbot.iris.gl.uniform.UniformUpdateFrequency.PER_TICK;
|
||||
|
||||
public class BiomeUniforms {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("BiomeUniforms");
|
||||
private static final Minecraft client = Minecraft.getMinecraft();
|
||||
|
||||
// Cache to avoid multiple biome lookups per tick
|
||||
private static BiomeGenBase cachedBiome = null;
|
||||
private static long cachedWorldTime = -1;
|
||||
private static int cachedPlayerX = Integer.MIN_VALUE;
|
||||
private static int cachedPlayerZ = Integer.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Adds biome-related uniforms that change based on the player's current biome.
|
||||
*/
|
||||
public static void addBiomeUniforms(UniformHolder uniforms) {
|
||||
uniforms.uniform1i(PER_TICK, "biome", BiomeUniforms::getBiomeId)
|
||||
.uniform1i(PER_TICK, "biome_category", BiomeUniforms::getBiomeCategory)
|
||||
.uniform1i(PER_TICK, "biome_precipitation", BiomeUniforms::getBiomePrecipitation)
|
||||
.uniform1f(PER_TICK, "rainfall", BiomeUniforms::getBiomeRainfall)
|
||||
.uniform1f(PER_TICK, "temperature", BiomeUniforms::getBiomeTemperature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current biome, with caching to avoid repeated lookups within the same tick.
|
||||
* Returns null if player or world is not available.
|
||||
*/
|
||||
private static BiomeGenBase getCachedBiome() {
|
||||
if (client.thePlayer == null || client.theWorld == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final long worldTime = client.theWorld.getTotalWorldTime();
|
||||
final int playerX = MathHelper.floor_double(client.thePlayer.posX);
|
||||
final int playerZ = MathHelper.floor_double(client.thePlayer.posZ);
|
||||
|
||||
// Invalidate cache if time or position changed
|
||||
if (cachedBiome == null || cachedWorldTime != worldTime || cachedPlayerX != playerX || cachedPlayerZ != playerZ) {
|
||||
cachedBiome = client.theWorld.getBiomeGenForCoords(playerX, playerZ);
|
||||
cachedWorldTime = worldTime;
|
||||
cachedPlayerX = playerX;
|
||||
cachedPlayerZ = playerZ;
|
||||
}
|
||||
|
||||
return cachedBiome;
|
||||
}
|
||||
|
||||
public static int getBiomePrecipitation() {
|
||||
final BiomeGenBase biome = getCachedBiome();
|
||||
if (biome == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!biome.enableRain && !biome.enableSnow) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final float temp = biome.getFloatTemperature(
|
||||
MathHelper.floor_double(client.thePlayer.posX),
|
||||
MathHelper.floor_double(client.thePlayer.posY),
|
||||
MathHelper.floor_double(client.thePlayer.posZ));
|
||||
|
||||
return temp > 0.15F ? 1 : 2;
|
||||
}
|
||||
|
||||
public static float getBiomeRainfall() {
|
||||
final BiomeGenBase biome = getCachedBiome();
|
||||
return biome != null ? biome.rainfall : 0.0F;
|
||||
}
|
||||
|
||||
public static float getBiomeTemperature() {
|
||||
final BiomeGenBase biome = getCachedBiome();
|
||||
return biome != null ? biome.temperature : 0.0F;
|
||||
}
|
||||
|
||||
public static int getBiomeId() {
|
||||
final BiomeGenBase biome = getCachedBiome();
|
||||
return biome != null ? biome.biomeID : 0;
|
||||
}
|
||||
|
||||
public static int getBiomeCategory() {
|
||||
final BiomeGenBase biome = getCachedBiome();
|
||||
if (biome == null) {
|
||||
return BiomeCategories.NONE.ordinal();
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
if (biome instanceof BiomeCategoryCache cache) {
|
||||
final int cached = cache.iris$getCachedCategory();
|
||||
if (cached != -1) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
// Not cached yet, determine and cache it
|
||||
final int category = determineBiomeCategory(biome);
|
||||
cache.iris$setCachedCategory(category);
|
||||
final BiomeCategories[] categories = BiomeCategories.values();
|
||||
final String categoryName = (category >= 0 && category < categories.length)
|
||||
? categories[category].name()
|
||||
: "INVALID(" + category + ")";
|
||||
LOGGER.debug("Cached biome category for '{}': {}", biome.biomeName, categoryName);
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
// Fallback if mixin didn't apply (shouldn't happen)
|
||||
return determineBiomeCategory(biome);
|
||||
}
|
||||
|
||||
private static int determineBiomeCategory(BiomeGenBase biome) {
|
||||
// Tier 1: Hardcoded vanilla biome IDs
|
||||
BiomeGenBase lookupBiome = biome;
|
||||
if (biome instanceof BiomeGenMutated mutated && mutated.baseBiome != null) {
|
||||
lookupBiome = mutated.baseBiome;
|
||||
}
|
||||
|
||||
BiomeCategories category = getVanillaBiomeCategory(lookupBiome.biomeID);
|
||||
if (category != null) {
|
||||
return category.ordinal();
|
||||
}
|
||||
|
||||
// Tier 2: Class-based detection for vanilla biome types
|
||||
category = detectVanillaBiomeByClass(biome);
|
||||
if (category != null) {
|
||||
return category.ordinal();
|
||||
}
|
||||
|
||||
// Tier 3: Modded biome detection (BiomesOPlenty, Realistic World Gen)
|
||||
category = detectModdedBiome(biome);
|
||||
if (category != null) {
|
||||
return category.ordinal();
|
||||
}
|
||||
|
||||
// Tier 4: Name pattern matching
|
||||
category = detectBiomeByName(biome);
|
||||
if (category != null) {
|
||||
return category.ordinal();
|
||||
}
|
||||
|
||||
// Tier 5: Temperature/rainfall heuristics
|
||||
category = detectBiomeByProperties(biome);
|
||||
if (category != null) {
|
||||
return category.ordinal();
|
||||
}
|
||||
|
||||
// Default: NONE
|
||||
return BiomeCategories.NONE.ordinal();
|
||||
}
|
||||
|
||||
private static BiomeCategories getVanillaBiomeCategory(int biomeID) {
|
||||
return switch (biomeID) {
|
||||
// OCEAN
|
||||
case 0, 10, 24 -> BiomeCategories.OCEAN; // ocean, frozenOcean, deepOcean
|
||||
|
||||
// PLAINS
|
||||
case 1 -> BiomeCategories.PLAINS; // plains
|
||||
|
||||
// DESERT
|
||||
case 2, 17 -> BiomeCategories.DESERT; // desert, desertHills
|
||||
|
||||
// EXTREME_HILLS (Vanilla mountains)
|
||||
case 3, 20, 34 -> BiomeCategories.EXTREME_HILLS; // extremeHills, extremeHillsEdge, extremeHillsPlus
|
||||
|
||||
// FOREST
|
||||
case 4, 18, 27, 28, 29 ->
|
||||
BiomeCategories.FOREST; // forest, forestHills, birchForest, birchForestHills, roofedForest
|
||||
|
||||
// TAIGA
|
||||
case 5, 19, 30, 31, 32, 33 ->
|
||||
BiomeCategories.TAIGA; // taiga, taigaHills, coldTaiga, coldTaigaHills, megaTaiga, megaTaigaHills
|
||||
|
||||
// SWAMP
|
||||
case 6 -> BiomeCategories.SWAMP; // swampland
|
||||
|
||||
// RIVER
|
||||
case 7, 11 -> BiomeCategories.RIVER; // river, frozenRiver
|
||||
|
||||
// NETHER
|
||||
case 8 -> BiomeCategories.NETHER; // hell
|
||||
|
||||
// THE_END
|
||||
case 9 -> BiomeCategories.THE_END; // sky
|
||||
|
||||
// ICY
|
||||
case 12, 13 -> BiomeCategories.ICY; // icePlains, iceMountains
|
||||
|
||||
// MUSHROOM
|
||||
case 14, 15 -> BiomeCategories.MUSHROOM; // mushroomIsland, mushroomIslandShore
|
||||
|
||||
// BEACH
|
||||
case 16, 25, 26 -> BiomeCategories.BEACH; // beach, stoneBeach, coldBeach
|
||||
|
||||
// JUNGLE
|
||||
case 21, 22, 23 -> BiomeCategories.JUNGLE; // jungle, jungleHills, jungleEdge
|
||||
|
||||
// SAVANNA
|
||||
case 35, 36 -> BiomeCategories.SAVANNA; // savanna, savannaPlateau
|
||||
|
||||
// MESA
|
||||
case 37, 38, 39 -> BiomeCategories.MESA; // mesa, mesaPlateau_F, mesaPlateau
|
||||
|
||||
default -> null; // Not a vanilla biome or unknown
|
||||
};
|
||||
}
|
||||
|
||||
private static final Map<Class<? extends BiomeGenBase>, BiomeCategories> VANILLA_CLASS_MAP = createVanillaClassMap();
|
||||
|
||||
private static Map<Class<? extends BiomeGenBase>, BiomeCategories> createVanillaClassMap() {
|
||||
final Map<Class<? extends BiomeGenBase>, BiomeCategories> map = new HashMap<>();
|
||||
// Most specific first (subclasses before superclasses)
|
||||
map.put(BiomeGenStoneBeach.class, BiomeCategories.BEACH);
|
||||
map.put(BiomeGenBeach.class, BiomeCategories.BEACH);
|
||||
map.put(BiomeGenMushroomIsland.class, BiomeCategories.MUSHROOM);
|
||||
map.put(BiomeGenOcean.class, BiomeCategories.OCEAN);
|
||||
map.put(BiomeGenPlains.class, BiomeCategories.PLAINS);
|
||||
map.put(BiomeGenDesert.class, BiomeCategories.DESERT);
|
||||
map.put(BiomeGenHills.class, BiomeCategories.EXTREME_HILLS);
|
||||
map.put(BiomeGenForest.class, BiomeCategories.FOREST);
|
||||
map.put(BiomeGenTaiga.class, BiomeCategories.TAIGA);
|
||||
map.put(BiomeGenSwamp.class, BiomeCategories.SWAMP);
|
||||
map.put(BiomeGenRiver.class, BiomeCategories.RIVER);
|
||||
map.put(BiomeGenHell.class, BiomeCategories.NETHER);
|
||||
map.put(BiomeGenEnd.class, BiomeCategories.THE_END);
|
||||
map.put(BiomeGenSnow.class, BiomeCategories.ICY);
|
||||
map.put(BiomeGenJungle.class, BiomeCategories.JUNGLE);
|
||||
map.put(BiomeGenSavanna.class, BiomeCategories.SAVANNA);
|
||||
map.put(BiomeGenMesa.class, BiomeCategories.MESA);
|
||||
return map;
|
||||
}
|
||||
|
||||
private static BiomeCategories detectVanillaBiomeByClass(BiomeGenBase biome) {
|
||||
// Direct class lookup (O(1) for exact matches)
|
||||
final BiomeCategories direct = VANILLA_CLASS_MAP.get(biome.getClass());
|
||||
if (direct != null) {
|
||||
return direct;
|
||||
}
|
||||
|
||||
// Fallback: instanceof checks for subclasses (modded biomes extending vanilla)
|
||||
for (Map.Entry<Class<? extends BiomeGenBase>, BiomeCategories> entry : VANILLA_CLASS_MAP.entrySet()) {
|
||||
if (entry.getKey().isInstance(biome)) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BiomeCategories detectModdedBiome(BiomeGenBase biome) {
|
||||
return ModdedBiomeDetector.detectModdedBiome(biome);
|
||||
}
|
||||
|
||||
private static BiomeCategories detectBiomeByName(BiomeGenBase biome) {
|
||||
if (biome.biomeName == null) return null;
|
||||
|
||||
final String name = biome.biomeName.toLowerCase();
|
||||
|
||||
// Check for keywords in biome names
|
||||
// Priority order matters - check more specific terms first
|
||||
|
||||
if (name.contains("nether")) return BiomeCategories.NETHER;
|
||||
if (name.contains("end")) return BiomeCategories.THE_END;
|
||||
|
||||
if (name.contains("ocean") || name.contains("sea")) return BiomeCategories.OCEAN;
|
||||
if (name.contains("river") || name.contains("stream")) return BiomeCategories.RIVER;
|
||||
if (name.contains("beach") || name.contains("shore") || name.contains("coast")) return BiomeCategories.BEACH;
|
||||
|
||||
if (name.contains("mushroom")) return BiomeCategories.MUSHROOM;
|
||||
if (name.contains("swamp") || name.contains("marsh") || name.contains("bog")) return BiomeCategories.SWAMP;
|
||||
|
||||
if (name.contains("jungle")) return BiomeCategories.JUNGLE;
|
||||
if (name.contains("savanna") || name.contains("savannah")) return BiomeCategories.SAVANNA;
|
||||
if (name.contains("mesa") || name.contains("badlands")) return BiomeCategories.MESA;
|
||||
if (name.contains("desert")) return BiomeCategories.DESERT;
|
||||
|
||||
// Mountain detection - for modded biomes
|
||||
if (name.contains("mountain") || name.contains("peak") || name.contains("alpine") ||
|
||||
name.contains("cliff") || name.contains("crag")) return BiomeCategories.MOUNTAIN;
|
||||
|
||||
// Ice/Snow detection
|
||||
if (name.contains("ice") || name.contains("frozen") || name.contains("snow") ||
|
||||
name.contains("arctic") || name.contains("tundra") || name.contains("glacier")) return BiomeCategories.ICY;
|
||||
|
||||
if (name.contains("taiga") || name.contains("boreal") || name.contains("conifer")) return BiomeCategories.TAIGA;
|
||||
|
||||
if (name.contains("forest") || name.contains("wood") || name.contains("grove") ||
|
||||
name.contains("thicket")) return BiomeCategories.FOREST;
|
||||
|
||||
if (name.contains("plain") || name.contains("field") || name.contains("meadow") ||
|
||||
name.contains("grassland") || name.contains("prairie")) return BiomeCategories.PLAINS;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BiomeCategories detectBiomeByProperties(BiomeGenBase biome) {
|
||||
final float temp = biome.temperature;
|
||||
final float rain = biome.rainfall;
|
||||
|
||||
// Very cold biomes with snow
|
||||
if (temp <= 0.0F && biome.enableSnow) {
|
||||
return BiomeCategories.ICY;
|
||||
}
|
||||
|
||||
// Hot, dry biomes
|
||||
if (temp >= 2.0F && !biome.enableRain) {
|
||||
return BiomeCategories.DESERT;
|
||||
}
|
||||
|
||||
// Warm, dry biomes (savanna-like)
|
||||
if (temp >= 1.0F && rain <= 0.1F && !biome.enableRain) {
|
||||
return BiomeCategories.SAVANNA;
|
||||
}
|
||||
|
||||
// Wet biomes with high rainfall
|
||||
if (rain >= 0.85F && temp >= 0.5F && temp <= 1.0F) {
|
||||
return BiomeCategories.SWAMP;
|
||||
}
|
||||
|
||||
// Cold forested biomes
|
||||
if (temp >= 0.0F && temp <= 0.4F && rain >= 0.4F) {
|
||||
return BiomeCategories.TAIGA;
|
||||
}
|
||||
|
||||
// Temperate forested biomes
|
||||
if (temp >= 0.4F && temp <= 0.9F && rain >= 0.5F) {
|
||||
return BiomeCategories.FOREST;
|
||||
}
|
||||
|
||||
// Default to plains for temperate, moderate biomes
|
||||
if (temp >= 0.4F && temp <= 1.0F && rain >= 0.3F && rain <= 0.6F) {
|
||||
return BiomeCategories.PLAINS;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,11 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.texture.AbstractTexture;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import org.joml.Math;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2i;
|
||||
@@ -53,6 +50,7 @@ public final class CommonUniforms {
|
||||
ViewportUniforms.addViewportUniforms(uniforms);
|
||||
WorldTimeUniforms.addWorldTimeUniforms(uniforms);
|
||||
SystemTimeUniforms.addSystemTimeUniforms(uniforms);
|
||||
BiomeUniforms.addBiomeUniforms(uniforms);
|
||||
new CelestialUniforms(directives.getSunPathRotation()).addCelestialUniforms(uniforms);
|
||||
IrisExclusiveUniforms.addIrisExclusiveUniforms(uniforms);
|
||||
IdMapUniforms.addIdMapUniforms(updateNotifier, uniforms, idMap, directives.isOldHandLight());
|
||||
@@ -67,6 +65,7 @@ public final class CommonUniforms {
|
||||
|
||||
// Needs to use a LocationalUniformHolder as we need it for the common uniforms
|
||||
public static void addDynamicUniforms(DynamicUniformHolder uniforms) {
|
||||
ExternallyManagedUniforms.addExternallyManagedUniforms116(uniforms);
|
||||
IdMapUniforms.addEntityIdMapUniforms(uniforms);
|
||||
FogUniforms.addFogUniforms(uniforms);
|
||||
|
||||
@@ -113,6 +112,7 @@ public final class CommonUniforms {
|
||||
|
||||
uniforms
|
||||
.uniform1f(ONCE, "darknessFactor", () -> 0.0F) // This is PER_FRAME in modern, it is an effect added by The Warden. We're just setting to 0 because 1.7.10 doesn't have it.
|
||||
.uniform1f(ONCE, "darknessLightFactor", () -> 0.0F) // Warden darkness current light factor - 1.7.10 doesn't have it so hardcode to 0
|
||||
.uniform1b(PER_FRAME, "hideGUI", () -> client.gameSettings.hideGUI)
|
||||
.uniform1i(PER_FRAME, "isEyeInWater", CommonUniforms::isEyeInWater)
|
||||
.uniform1f(PER_FRAME, "blindness", CommonUniforms::getBlindness)
|
||||
@@ -137,11 +137,7 @@ public final class CommonUniforms {
|
||||
.uniform1f(PER_TICK, "rainStrength", CommonUniforms::getRainStrength)
|
||||
.uniform1f(PER_TICK, "wetness", new SmoothedFloat(directives.getWetnessHalfLife(), directives.getDrynessHalfLife(), CommonUniforms::getRainStrength, updateNotifier))
|
||||
.uniform3d(PER_FRAME, "skyColor", CommonUniforms::getSkyColor)
|
||||
.uniform3d(PER_FRAME, "fogColor", GLStateManager::getFogColor)
|
||||
|
||||
.uniform1i(PER_TICK, "biome_precipitation", CommonUniforms::getBiomePrecipitation)
|
||||
.uniform1f(PER_TICK, "rainfall", CommonUniforms::getBiomeRainfall)
|
||||
.uniform1f(PER_TICK, "temperature", CommonUniforms::getBiomeTemperature);
|
||||
.uniform3d(PER_FRAME, "fogColor", GLStateManager::getFogColor);
|
||||
}
|
||||
|
||||
private static boolean isOnGround() {
|
||||
@@ -153,38 +149,7 @@ public final class CommonUniforms {
|
||||
return (client.thePlayer != null && client.thePlayer.hurtTime > 0);
|
||||
}
|
||||
|
||||
private static BiomeGenBase getBiome() {
|
||||
return client.theWorld.getBiomeGenForCoords(MathHelper.floor_double(client.thePlayer.posX), MathHelper.floor_double(client.thePlayer.posZ));
|
||||
}
|
||||
|
||||
private static int getBiomePrecipitation() {
|
||||
if (client.thePlayer == null || client.theWorld == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BiomeGenBase biome = getBiome();
|
||||
float temp = biome.getFloatTemperature(MathHelper.floor_double(client.thePlayer.posX), MathHelper.floor_double(client.thePlayer.posY), MathHelper.floor_double(client.thePlayer.posZ));
|
||||
|
||||
if (!biome.enableRain && !biome.enableSnow) {
|
||||
return 0;
|
||||
} else if (temp > 0.15F) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static float getBiomeRainfall() {
|
||||
if (client.thePlayer == null || client.theWorld == null) return 0.0F;
|
||||
return getBiome().rainfall;
|
||||
}
|
||||
|
||||
private static float getBiomeTemperature() {
|
||||
if (client.thePlayer == null || client.theWorld == null) return 0.0F;
|
||||
return getBiome().temperature;
|
||||
}
|
||||
|
||||
private static boolean isInvisible() {
|
||||
private static boolean isInvisible() {
|
||||
return (client.thePlayer != null && client.thePlayer.isInvisible());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ public class ExternallyManagedUniforms {
|
||||
addMat4(uniformHolder, "iris_ModelViewMatrix");
|
||||
addMat4(uniformHolder, "u_ModelViewProjectionMatrix");
|
||||
addMat4(uniformHolder, "iris_NormalMatrix");
|
||||
// Exclusive to pre-1.19
|
||||
addFloat(uniformHolder, "darknessFactor");
|
||||
addFloat(uniformHolder, "darknessLightFactor");
|
||||
|
||||
// 1.21.6+
|
||||
uniformHolder.externallyManagedUniform("heavyFog", UniformType.BOOL);
|
||||
}
|
||||
|
||||
public static void addExternallyManagedUniforms116(UniformHolder uniformHolder) {
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import net.coderbot.iris.gl.uniform.UniformHolder;
|
||||
import net.coderbot.iris.gl.uniform.UniformUpdateFrequency;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.effect.EntityLightningBolt;
|
||||
import org.joml.Math;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3dc;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class IrisExclusiveUniforms {
|
||||
// Reusable vectors to avoid allocations every frame
|
||||
private static final Vector3d eyePositionCache = new Vector3d();
|
||||
private static final Vector3d relativeEyePositionCache = new Vector3d();
|
||||
private static final Vector4f lightningBoltPositionCache = new Vector4f();
|
||||
private static final Vector4f ZERO_VECTOR_4f = new Vector4f(0, 0, 0, 0);
|
||||
|
||||
public static void addIrisExclusiveUniforms(UniformHolder uniforms) {
|
||||
WorldInfoUniforms.addWorldInfoUniforms(uniforms);
|
||||
|
||||
@@ -24,20 +36,10 @@ public class IrisExclusiveUniforms {
|
||||
uniforms.uniform1f(UniformUpdateFrequency.PER_TICK, "maxPlayerAir", IrisExclusiveUniforms::getMaxAir);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_FRAME, "firstPersonCamera", IrisExclusiveUniforms::isFirstPersonCamera);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "isSpectator", IrisExclusiveUniforms::isSpectator);
|
||||
uniforms.uniform1b(UniformUpdateFrequency.PER_TICK, "isRightHanded", () -> true); // 1.7.10 doesn't support left-handed mode
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "eyePosition", IrisExclusiveUniforms::getEyePosition);
|
||||
// TODO: Iris Shaders
|
||||
// Vector4f zero = new Vector4f(0, 0, 0, 0);
|
||||
// uniforms.uniform4f(UniformUpdateFrequency.PER_TICK, "lightningBoltPosition", () -> {
|
||||
// if (Minecraft.getMinecraft().theWorld != null) {
|
||||
// return StreamSupport.stream(Minecraft.getMinecraft().theWorld.entitiesForRendering().spliterator(), false).filter(bolt -> bolt instanceof LightningBolt).findAny().map(bolt -> {
|
||||
// Vector3d unshiftedCameraPosition = CameraUniforms.getUnshiftedCameraPosition();
|
||||
// Vec3 vec3 = bolt.getPosition(Minecraft.getMinecraft().getDeltaFrameTime());
|
||||
// return new Vector4f((float) (vec3.x - unshiftedCameraPosition.x), (float) (vec3.y - unshiftedCameraPosition.y), (float) (vec3.z - unshiftedCameraPosition.z), 1);
|
||||
// }).orElse(zero);
|
||||
// } else {
|
||||
// return zero;
|
||||
// }
|
||||
// });
|
||||
uniforms.uniform3d(UniformUpdateFrequency.PER_FRAME, "relativeEyePosition", IrisExclusiveUniforms::getRelativeEyePosition);
|
||||
uniforms.uniform4f(UniformUpdateFrequency.PER_TICK, "lightningBoltPosition", IrisExclusiveUniforms::getLightningBoltPosition);
|
||||
}
|
||||
|
||||
private static float getThunderStrength() {
|
||||
@@ -88,21 +90,40 @@ public class IrisExclusiveUniforms {
|
||||
|
||||
private static boolean isFirstPersonCamera() {
|
||||
// If camera type is not explicitly third-person, assume it's first-person.
|
||||
return (Minecraft.getMinecraft().gameSettings.thirdPersonView == 1);
|
||||
return !Camera.INSTANCE.isThirdPerson();
|
||||
}
|
||||
|
||||
private static boolean isSpectator() {
|
||||
final PlayerControllerMP controller = Minecraft.getMinecraft().playerController;
|
||||
if(controller == null)
|
||||
return false;
|
||||
return controller.currentGameType.getID() == 3;
|
||||
return GameModeUtil.isSpectator();
|
||||
}
|
||||
|
||||
private static Vector3d getEyePosition() {
|
||||
// Objects.requireNonNull(Minecraft.getMinecraft().getCameraEntity());
|
||||
// return new Vector3d(Minecraft.getMinecraft().getCameraEntity().getX(), Minecraft.getMinecraft().getCameraEntity().getEyeY(), Minecraft.getMinecraft().getCameraEntity().getZ());
|
||||
final EntityLivingBase eye = Minecraft.getMinecraft().renderViewEntity;
|
||||
return new Vector3d(eye.posX, eye.posY, eye.posZ);
|
||||
return eyePositionCache.set(eye.posX, eye.posY + eye.getEyeHeight(), eye.posZ);
|
||||
}
|
||||
|
||||
private static Vector3d getRelativeEyePosition() {
|
||||
final Vector3dc cameraPos = CameraUniforms.getUnshiftedCameraPosition();
|
||||
final Vector3d eyePos = getEyePosition();
|
||||
return relativeEyePositionCache.set(eyePos).sub(cameraPos);
|
||||
}
|
||||
|
||||
private static Vector4f getLightningBoltPosition() {
|
||||
if (Minecraft.getMinecraft().theWorld != null) {
|
||||
final List<Entity> weatherEffects = Minecraft.getMinecraft().theWorld.weatherEffects;
|
||||
for (Entity entity : weatherEffects) {
|
||||
if (entity instanceof EntityLightningBolt bolt) {
|
||||
final Vector3dc cameraPos = CameraUniforms.getUnshiftedCameraPosition();
|
||||
return lightningBoltPositionCache.set(
|
||||
(float)(bolt.posX - cameraPos.x()),
|
||||
(float)(bolt.posY - cameraPos.y()),
|
||||
(float)(bolt.posZ - cameraPos.z()),
|
||||
1.0f
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ZERO_VECTOR_4f;
|
||||
}
|
||||
|
||||
public static class WorldInfoUniforms {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package net.coderbot.iris.uniforms;
|
||||
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class VanillaBiomeList {
|
||||
public static class BiomeEntry {
|
||||
public final BiomeGenBase biome;
|
||||
public final String name;
|
||||
|
||||
public BiomeEntry(BiomeGenBase biome, String name) {
|
||||
this.biome = biome;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static final List<BiomeEntry> VANILLA_BIOMES = createVanillaBiomeList();
|
||||
|
||||
private static List<BiomeEntry> createVanillaBiomeList() {
|
||||
final List<BiomeEntry> biomes = new ArrayList<>();
|
||||
|
||||
// Vanilla biomes from BiomeGenBase static fields (IDs 0-39)
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.ocean, "OCEAN"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.plains, "PLAINS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.desert, "DESERT"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.extremeHills, "EXTREME_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.forest, "FOREST"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.taiga, "TAIGA"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.swampland, "SWAMPLAND"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.river, "RIVER"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.hell, "HELL"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "SKY"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.frozenOcean, "FROZEN_OCEAN"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.frozenRiver, "FROZEN_RIVER"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.icePlains, "ICE_PLAINS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.iceMountains, "ICE_MOUNTAINS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mushroomIsland, "MUSHROOM_ISLAND"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mushroomIslandShore, "MUSHROOM_ISLAND_SHORE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.beach, "BEACH"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.desertHills, "DESERT_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.forestHills, "FOREST_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.taigaHills, "TAIGA_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.extremeHillsEdge, "EXTREME_HILLS_EDGE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.jungle, "JUNGLE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.jungleHills, "JUNGLE_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.jungleEdge, "JUNGLE_EDGE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.deepOcean, "DEEP_OCEAN"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.stoneBeach, "STONE_BEACH"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.coldBeach, "COLD_BEACH"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.birchForest, "BIRCH_FOREST"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.birchForestHills, "BIRCH_FOREST_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.roofedForest, "ROOFED_FOREST"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.coldTaiga, "COLD_TAIGA"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.coldTaigaHills, "COLD_TAIGA_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.megaTaiga, "MEGA_TAIGA"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.megaTaigaHills, "MEGA_TAIGA_HILLS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.extremeHillsPlus, "EXTREME_HILLS_PLUS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.savanna, "SAVANNA"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.savannaPlateau, "SAVANNA_PLATEAU"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mesa, "MESA"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mesaPlateau_F, "MESA_PLATEAU_F"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mesaPlateau, "MESA_PLATEAU"));
|
||||
|
||||
// Modern End biome variants (1.9+) - all map to the single End biome in 1.7.10
|
||||
// This allows shaders expecting these constants to work
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "THE_END"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "SMALL_END_ISLANDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_MIDLANDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_HIGHLANDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_BARRENS"));
|
||||
|
||||
return Collections.unmodifiableList(biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached list of all vanilla biomes with their shader-friendly names.
|
||||
* The list is immutable and created once during class initialization.
|
||||
*/
|
||||
public static List<BiomeEntry> getVanillaBiomes() {
|
||||
return VANILLA_BIOMES;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package net.coderbot.iris.vertices;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
|
||||
public class IrisVertexFormats {
|
||||
public static final VertexFormatElement ENTITY_ELEMENT;
|
||||
public static final VertexFormatElement MID_TEXTURE_ELEMENT;
|
||||
public static final VertexFormatElement TANGENT_ELEMENT;
|
||||
public static final VertexFormatElement MID_BLOCK_ELEMENT;
|
||||
|
||||
public static final VertexFormat TERRAIN;
|
||||
public static final VertexFormat ENTITY;
|
||||
|
||||
static {
|
||||
ENTITY_ELEMENT = new VertexFormatElement(11, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.GENERIC, 2);
|
||||
MID_TEXTURE_ELEMENT = new VertexFormatElement(12, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.GENERIC, 2);
|
||||
TANGENT_ELEMENT = new VertexFormatElement(13, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 4);
|
||||
MID_BLOCK_ELEMENT = new VertexFormatElement(14, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, 3);
|
||||
|
||||
ImmutableList.Builder<VertexFormatElement> terrainElements = ImmutableList.builder();
|
||||
ImmutableList.Builder<VertexFormatElement> entityElements = ImmutableList.builder();
|
||||
|
||||
terrainElements.add(DefaultVertexFormat.POSITION_ELEMENT); // 12
|
||||
terrainElements.add(DefaultVertexFormat.COLOR_ELEMENT); // 16
|
||||
terrainElements.add(DefaultVertexFormat.TEXTURE_ELEMENT); // 24
|
||||
terrainElements.add(DefaultVertexFormat.LIGHT_ELEMENT); // 28
|
||||
terrainElements.add(DefaultVertexFormat.NORMAL_ELEMENT); // 31
|
||||
terrainElements.add(DefaultVertexFormat.PADDING_ELEMENT); // 32
|
||||
terrainElements.add(ENTITY_ELEMENT); // 36
|
||||
terrainElements.add(MID_TEXTURE_ELEMENT); // 44
|
||||
terrainElements.add(TANGENT_ELEMENT); // 48
|
||||
terrainElements.add(MID_BLOCK_ELEMENT); // 51
|
||||
terrainElements.add(DefaultVertexFormat.PADDING_ELEMENT); // 52
|
||||
|
||||
entityElements.add(DefaultVertexFormat.POSITION_ELEMENT); // 12
|
||||
entityElements.add(DefaultVertexFormat.COLOR_ELEMENT); // 16
|
||||
entityElements.add(DefaultVertexFormat.TEXTURE_ELEMENT); // 24
|
||||
entityElements.add(DefaultVertexFormat.LIGHT_ELEMENT); // 28
|
||||
entityElements.add(DefaultVertexFormat.NORMAL_ELEMENT); // 31
|
||||
entityElements.add(DefaultVertexFormat.PADDING_ELEMENT); // 32
|
||||
entityElements.add(MID_TEXTURE_ELEMENT); // 40
|
||||
entityElements.add(TANGENT_ELEMENT); // 44
|
||||
|
||||
TERRAIN = new VertexFormat(terrainElements.build());
|
||||
ENTITY = new VertexFormat(entityElements.build());
|
||||
}
|
||||
}
|
||||
@@ -86,3 +86,4 @@ public net.minecraft.block.material.Material field_76240_I # isTranslucent
|
||||
|
||||
public net.minecraft.world.biome.BiomeGenBase field_76765_S # enableRain
|
||||
public net.minecraft.world.biome.BiomeGenBase field_76766_R # enableSnow
|
||||
public net.minecraft.world.biome.BiomeGenMutated field_150611_aD # baseBiome
|
||||
@@ -139,11 +139,16 @@ options.angelica.fontconfig=Font Configuration...
|
||||
options.angelica.fontconfig.title=Font Configuration
|
||||
options.angelica.fontconfig.currentfonts=Primary font: §e%s§r Fallback font: §b%s
|
||||
options.angelica.fontconfig.searchprompt=§7§oSearch fonts...
|
||||
options.angelica.fontconfig.testareaprompt=§7§oTest area...
|
||||
options.angelica.fontconfig.testareainfo=Enter text below to see how it renders. Use & for formatting.
|
||||
options.angelica.fontconfig.testareaexample=&d&lHerobrine&r was &7&m&oNOT&r &nhere
|
||||
options.angelica.fontconfig.disable_custom_font=Disable Custom Font
|
||||
options.angelica.fontconfig.enable_custom_font=Enable Custom Font
|
||||
options.angelica.fontconfig.reset_values=Reset Values
|
||||
options.angelica.fontconfig.font_quality=Custom Font Quality: %s
|
||||
options.angelica.fontconfig.shadow_offset=Shadow Offset: %s
|
||||
options.angelica.fontconfig.shadow_copies=Shadow Copies: %s
|
||||
options.angelica.fontconfig.bold_copies=Bold Copies: %s
|
||||
options.angelica.fontconfig.glyph_scale=Glyph Scale: %s
|
||||
options.angelica.fontconfig.glyph_aspect=Glyph Aspect: %s
|
||||
options.angelica.fontconfig.whitespace_scale=Whitespace Size: %s
|
||||
@@ -153,7 +158,9 @@ options.angelica.fontconfig.aamode.aa_none=Font AA: OFF
|
||||
options.angelica.fontconfig.aamode.aa_4x=Font AA: 4x MSAA
|
||||
options.angelica.fontconfig.aamode.aa_16x=Font AA: 16x MSAA
|
||||
options.angelica.fontconfig.font_quality.tooltip=The quality at which custom fonts are rendered, making them less pixelated at the expense of some performance and memory.
|
||||
options.angelica.fontconfig.shadow_offset.tooltip=The distance at which the fonts' shadows are drawn. Also affects the way §lbold§r text is drawn; turn this down if you see double text.
|
||||
options.angelica.fontconfig.shadow_offset.tooltip=The distance at which the fonts' shadows are drawn. Also affects the way §lbold§r text is drawn.
|
||||
options.angelica.fontconfig.shadow_copies.tooltip=The number of shadows to be drawn behind text, all offset so as to provide a fake 3D effect.
|
||||
options.angelica.fontconfig.bold_copies.tooltip=The number of text copies drawn when rendering bold text. Can improve the appearance of bold text with thinner custom fonts.
|
||||
options.angelica.fontconfig.glyph_scale.tooltip=The scale of each individual glyph. Extreme values might make your game unplayable.
|
||||
options.angelica.fontconfig.glyph_aspect.tooltip=The aspect ratio of each individual glyph.
|
||||
options.angelica.fontconfig.whitespace_scale.tooltip=The scaling factor of blank characters like spaces.
|
||||
|
||||
@@ -2,6 +2,8 @@ options.button.shader=光影包……
|
||||
|
||||
options.chunks=%s 区块
|
||||
options.entityShadows=实体阴影
|
||||
options.droppedItems=%s 个物品
|
||||
options.droppedItems.max=无限制
|
||||
sodium.option_impact.low=低
|
||||
sodium.option_impact.medium=中
|
||||
sodium.option_impact.high=高
|
||||
@@ -29,6 +31,8 @@ sodium.options.leaves_quality.name=树叶质量
|
||||
sodium.options.leaves_quality.tooltip=控制树叶的渲染质量。
|
||||
sodium.options.grass_quality.name=草方块质量
|
||||
sodium.options.grass_quality.tooltip=控制草方块侧面的质量。
|
||||
sodium.options.sodium_smooth_lighting.name=Sodium平滑光照
|
||||
sodium.options.sodium_smooth_lighting.tooltip=如果启用,将调用钠模组的平滑光照,此选项仅在平滑光照启用时生效。
|
||||
sodium.options.particle_quality.name=粒子效果
|
||||
sodium.options.particle_quality.tooltip=控制可同时在画面上渲染的最大粒子数量。
|
||||
sodium.options.smooth_lighting.tooltip=控制方块是否平滑光照和渲染。这会略微增加重新加载区块所需的时间,但不会影响帧率(FPS)。
|
||||
@@ -38,7 +42,7 @@ sodium.options.entity_distance.tooltip=实体渲染的距离修正乘数。更
|
||||
sodium.options.entity_shadows.tooltip=如果启用,将在生物和其他实体下方渲染简单的阴影。
|
||||
sodium.options.vignette.name=晕影
|
||||
sodium.options.vignette.tooltip=如果启用,将在玩家的画面上显示晕影效果。除非你的显卡像素填充率有限,否则这不太可能对帧率产生影响。
|
||||
sodium.options.mipmap_levels.tooltip=控制将用于方块模型纹理的MipMap的数量。较高的值可以更好地渲染远处的方块,但可能会对许多纹理动画的性能产生不利影响。
|
||||
sodium.options.mipmap_levels.tooltip=控制多级纹理的生成等级。较高的等级可以更好地渲染远处的方块,但可能会对许多纹理动画的性能产生不利影响。
|
||||
sodium.options.use_chunk_multidraw.name=使用区块多重绘制
|
||||
sodium.options.use_chunk_multidraw.tooltip=多重绘制允许通过更少的绘制请求来进行多区块渲染,在大大减少了渲染世界时的CPU负载的同时也可能提高了GPU利用率。此选项可能会让一些图形驱动程序出现问题,因此如果遇到相关问题,应尝试禁用它。
|
||||
sodium.options.use_vertex_objects.name=使用顶点数组对象
|
||||
@@ -61,7 +65,7 @@ sodium.options.cpu_render_ahead_limit.name=CPU 预渲染限制
|
||||
sodium.options.cpu_render_ahead_limit.tooltip=指定CPU可以在GPU上等待完成渲染的最大帧数。非常低或非常高的值都可能会导致帧率(FPS)不稳定。
|
||||
sodium.options.cpu_render_ahead_limit.value=%s 帧
|
||||
sodium.options.allow_direct_memory_access.name=允许直接内存访问
|
||||
sodium.options.allow_direct_memory_access.tooltip=如果启用,将允许某些关键代码路径使用直接内存访问来提高性能。这通常会大大减少区块和实体渲染的 CPU 开销,但会使诊断某些错误和崩溃变得更加困难。只有您被要求这么做或知道在做什么时,才应该禁用它。
|
||||
sodium.options.allow_direct_memory_access.tooltip=如果启用,一些关键代码将被允许通过直接读写内存来提高性能。这通常会大大减少区块和实体渲染的CPU开销,但会使诊断某些错误和崩溃变得更加困难。只有您被要求这么做或知道在做什么时,才应该禁用它。
|
||||
sodium.options.ignore_driver_blacklist.name=忽略驱动程序冲突
|
||||
sodium.options.ignore_driver_blacklist.tooltip=如果启用,已知的硬件/驱动程序配置不兼容性将被忽略,以允许您启用那些可能导致游戏问题的配置.请勿更改此项除非您确切知道您在做什么.更改此选项后,必须保存、关闭,然后重新打开设置菜单。
|
||||
sodium.options.enable_memory_tracing.name=启用内存跟踪
|
||||
@@ -78,10 +82,10 @@ sodium.options.chunk_update_threads.tooltip=指定用于区块构建的线程数
|
||||
sodium.options.always_defer_chunk_updates.name=始终推迟区块更新
|
||||
sodium.options.always_defer_chunk_updates.tooltip=如果启用,渲染将永远不会等待区块更新完成,即使它们很重要。这在某些情况下可以极大地提高帧率(FPS),但可能会在游戏时产生明显的视觉滞后。
|
||||
sodium.options.use_no_error_context.name=使用禁用错误检查的上下文
|
||||
sodium.options.use_no_error_context.tooltip=如果启用,OpenGL上下文将在禁用错误检查的情况下创建。这可能会略微提高性能,但也会增加游戏崩溃的风险,而不会优雅地处理OpenGL错误。如果遇到无法解释的突然崩溃,则应禁用此选项。
|
||||
sodium.options.use_no_error_context.tooltip=如果启用,OpenGL日志将不包含详细错误信息。这可能略微提高性能,但也可能因为无法精确处理OpenGL错误而导致游戏崩溃。如遇到不明原因的突然崩溃,则应禁用此选项。
|
||||
sodium.options.threads.value=%s 线程
|
||||
sodium.options.use_gl_state_cache.name=使用GL状态缓存
|
||||
sodium.options.use_gl_state_cache.tooltip=如果启用,OpenGL状态缓存将减少冗余状态更改的次数.这可以提高性能,但也可能导致一些模组出现问题.每次重启游戏时此项将重置.
|
||||
sodium.options.use_gl_state_cache.name=启用GL状态缓存
|
||||
sodium.options.use_gl_state_cache.tooltip=如果启用,OpenGL状态缓存将减少冗余状态更改的次数。这可以提高性能,但也可能导致一些模组出现问题。每次重启游戏时此项将重置。
|
||||
sodium.options.default=默认
|
||||
sodium.options.buttons.undo=撤销
|
||||
sodium.options.buttons.apply=应用
|
||||
@@ -89,7 +93,7 @@ sodium.options.buttons.donate=给JellySquid买杯咖啡!
|
||||
options.dynamic_fov=动态视场
|
||||
options.dynamic_fov.tooltip=如果启用,游戏视场将根据玩家速度发生变化.
|
||||
options.framerate=%s FPS
|
||||
iris.shaders.toggled=光影包已切换到 %s!
|
||||
iris.shaders.toggled=光影包已切换为 %s!
|
||||
iris.shaders.disabled=光影包已禁用!
|
||||
options.iris.apply=应用
|
||||
options.iris.refresh=刷新
|
||||
@@ -122,12 +126,48 @@ options.iris.setToDefault=将选项设为默认值?
|
||||
options.iris.profile=配置文件
|
||||
options.iris.profile.custom=自定义
|
||||
options.iris.shadowDistance=最大阴影距离
|
||||
options.iris.shadowDistance.sodium_tooltip=最大阴影距离
|
||||
options.iris.shadowDistance.enabled=更改渲染阴影的最远距离。超出此距离的地形和实体不会投射出阴影。减少阴影渲染距离可以显著提高性能。
|
||||
options.iris.shadowDistance.disabled=当前光影包已重设阴影渲染距离,无法更改.
|
||||
options.iris.shadowDistance.disabled=当前光影包已重设阴影渲染距离,无法更改
|
||||
options.iris.gui.hide=隐藏 GUI
|
||||
options.iris.gui.show=显示 GUI
|
||||
options.dynamic_lights=动态光源
|
||||
options.dynamic_lights.tooltip=启用动态光源. 模式选择: OFF - 关闭, FASTEST - 500ms延迟, FAST - 250ms延迟, FANCY - 无延迟. 如果正在使用光影则此功能被禁用.
|
||||
options.dynamic_lights.tooltip=启用动态光源,模式选择:OFF-关闭,FASTEST-500ms延迟,FAST-250ms延迟,FANCY-无延迟
|
||||
options.dynamic_lights_shader_force=强制启用动态光源
|
||||
options.dynamic_lights_shader_force.tooltip=启用-启用光影时仍显示动态光源;禁用-启用光影时禁用动态光源。
|
||||
options.angelica.fontconfig=字体配置...
|
||||
options.angelica.fontconfig.title=字体配置
|
||||
options.angelica.fontconfig.currentfonts=主字体:§e%s§r 备用字体:§b%s
|
||||
options.angelica.fontconfig.searchprompt=§7§o搜索字体...
|
||||
options.angelica.fontconfig.disable_custom_font=禁用自定义字体
|
||||
options.angelica.fontconfig.enable_custom_font=启用自定义字体
|
||||
options.angelica.fontconfig.reset_values=恢复默认配置
|
||||
options.angelica.fontconfig.font_quality=字体渲染质量:%s
|
||||
options.angelica.fontconfig.shadow_offset=阴影偏移:%s
|
||||
options.angelica.fontconfig.glyph_scale=字体缩放:%s
|
||||
options.angelica.fontconfig.glyph_aspect=字体宽高比:%s
|
||||
options.angelica.fontconfig.whitespace_scale=空白字符大小:%s
|
||||
options.angelica.fontconfig.glyph_spacing=字符间距:%s
|
||||
options.angelica.fontconfig.font_aa_strength=字体抗锯齿强度:%s
|
||||
options.angelica.fontconfig.aamode.aa_none=抗锯齿:关闭
|
||||
options.angelica.fontconfig.aamode.aa_4x=抗锯齿:4x MSAA
|
||||
options.angelica.fontconfig.aamode.aa_16x=抗锯齿:16x MSAA
|
||||
options.angelica.fontconfig.font_quality.tooltip=自定义字体渲染质量,使其不那么像素化,但会牺牲一些性能与内存占用。
|
||||
options.angelica.fontconfig.shadow_offset.tooltip=字体衬底阴影偏移的距离。同时影响§l粗体§r文本的绘制方式;如果看到重影的文本,请调低此值。
|
||||
options.angelica.fontconfig.glyph_scale.tooltip=字体大小的缩放比例。极端值可能使游戏难以游玩。
|
||||
options.angelica.fontconfig.glyph_aspect.tooltip=字体的的宽高比例
|
||||
options.angelica.fontconfig.whitespace_scale.tooltip=空白字符(如空格)的缩放比例
|
||||
options.angelica.fontconfig.glyph_spacing.tooltip=字符之间的间距
|
||||
options.angelica.fontconfig.font_aa_strength.tooltip=抗锯齿所使用的采样间距。过大可能导致字体看起来模糊,过小可能导致锯齿。请根据您的实际情况选择最佳值。
|
||||
options.angelica.fontconfig.aamode.tooltip=抗锯齿模式。可以显著改善缩放或斜角观看文本的外观和可读性,但会牺牲一些性能。
|
||||
options.angelica.droppedItemLimit=掉落物渲染数量上限
|
||||
options.angelica.droppedItemLimit.tooltip=将被渲染的掉落物的最大数量。较小的值可以提高性能。
|
||||
options.angelica.mobSpawnerRenderDistance=刷怪笼渲染距离
|
||||
options.angelica.mobSpawnerRenderDistance.tooltip=刷怪笼内旋转实体的渲染距离
|
||||
options.angelica.itemdisplaylistcount=物品渲染器缓存限制
|
||||
options.angelica.itemdisplaylistcount.tooltip=优化物品渲染器中的缓存数量上限。较高的值将显著提高性能,但可能导致显存占用增加
|
||||
options.angelica.sleepbeforeswap=备用FPS限制器
|
||||
options.angelica.sleepbeforeswap.tooltip=切换到备用FPS限制器,可以降低帧波动,但会略微增加延迟。最多只会造成一帧的延迟,且在较高帧率下影响较小。
|
||||
pack.iris.select.title=选择
|
||||
pack.iris.configure.title=配置
|
||||
label.iris.true=开启
|
||||
|
||||
+9
-5
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
||||
import com.gtnewhorizons.angelica.rendering.RenderingState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -19,15 +20,18 @@ public abstract class MixinEntityRenderer implements EntityRendererAccessor {
|
||||
@Invoker
|
||||
public abstract float invokeGetNightVisionBrightness(EntityPlayer entityPlayer, float partialTicks);
|
||||
|
||||
@Inject(method = "setupCameraTransform", at = @At(value = "TAIL"))
|
||||
private void angelica$captureCameraMatrix(float partialTicks, int startTime, CallbackInfo ci) {
|
||||
@Inject(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ActiveRenderInfo;updateRenderInfo(Lnet/minecraft/entity/player/EntityPlayer;Z)V", shift = At.Shift.AFTER))
|
||||
private void angelica$captureCameraMatrix(float partialTicks, long finishTimeNano, CallbackInfo ci) {
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
final EntityLivingBase viewEntity = mc.renderViewEntity;
|
||||
|
||||
Camera.INSTANCE.update(viewEntity, partialTicks);
|
||||
|
||||
// Set RenderingState to use the correct camera position
|
||||
RenderingState.INSTANCE.setCameraPosition(
|
||||
viewEntity.lastTickPosX + (viewEntity.posX - viewEntity.lastTickPosX) * partialTicks,
|
||||
viewEntity.lastTickPosY + (viewEntity.posY - viewEntity.lastTickPosY) * partialTicks,
|
||||
viewEntity.lastTickPosZ + (viewEntity.posZ - viewEntity.lastTickPosZ) * partialTicks
|
||||
Camera.INSTANCE.getPos().x,
|
||||
Camera.INSTANCE.getPos().y,
|
||||
Camera.INSTANCE.getPos().z
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+3
-23
@@ -1,16 +1,10 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.angelica.animation;
|
||||
|
||||
import com.gtnewhorizons.angelica.utils.AnimationsRenderUtils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.texture.TextureMap;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.IBlockAccess;
|
||||
import net.minecraftforge.fluids.RenderBlockFluid;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
@@ -18,26 +12,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
@Mixin(value = RenderBlockFluid.class, remap = false)
|
||||
public abstract class MixinRenderBlockFluid {
|
||||
|
||||
@Unique
|
||||
private IBlockAccess currentBlockAccess;
|
||||
|
||||
@Inject(method = "renderWorldBlock", at = @At(value = "HEAD"))
|
||||
private void angelica$saveCurrentBlockAccess(IBlockAccess world, int x, int y, int z, Block block, int modelId,
|
||||
RenderBlocks renderer, CallbackInfoReturnable<Boolean> cir) {
|
||||
currentBlockAccess = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author laetansky
|
||||
* @reason mark texture for update
|
||||
*/
|
||||
@Overwrite
|
||||
private IIcon getIcon(IIcon icon) {
|
||||
if (icon != null) {
|
||||
AnimationsRenderUtils.markBlockTextureForUpdate(icon, currentBlockAccess);
|
||||
return icon;
|
||||
}
|
||||
return ((TextureMap) Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture))
|
||||
.getAtlasSprite("missingno");
|
||||
@Inject(method = "getIcon", at = @At(value = "RETURN", ordinal = 0))
|
||||
private void angelica$updateTexture(IIcon icon, CallbackInfoReturnable<IIcon> cir) {
|
||||
AnimationsRenderUtils.markBlockTextureForUpdate(icon, Minecraft.getMinecraft().theWorld);
|
||||
}
|
||||
}
|
||||
+3
-8
@@ -17,19 +17,16 @@ public class MixinRenderGlobal_ItemRenderDist {
|
||||
|
||||
@Unique private static final int[] sodium$entityItemCount = new int[256];
|
||||
@Unique private static int sodium$itemRenderDist = 255;
|
||||
@Unique private static int sodium$itemRenderedCount;
|
||||
@Unique private static int sodium$itemLimit = Integer.MAX_VALUE;
|
||||
|
||||
@Inject(method = "renderEntities", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/RenderGlobal;countEntitiesRendered:I", ordinal = 0))
|
||||
private void sodium$resetEntitycount(CallbackInfo ci) {
|
||||
sodium$itemRenderedCount = 0;
|
||||
int entityCount = 0;
|
||||
boolean reachedLimit = false;
|
||||
sodium$itemLimit = AngelicaConfig.droppedItemLimit == 2048 ? Integer.MAX_VALUE : AngelicaConfig.droppedItemLimit;
|
||||
final int itemLimit = AngelicaConfig.droppedItemLimit == 2048 ? Integer.MAX_VALUE : AngelicaConfig.droppedItemLimit;
|
||||
for (int i = 0; i < sodium$entityItemCount.length; i++) {
|
||||
entityCount += sodium$entityItemCount[i];
|
||||
sodium$entityItemCount[i] = 0;
|
||||
if (!reachedLimit && entityCount > sodium$itemLimit) {
|
||||
if (!reachedLimit && entityCount > itemLimit) {
|
||||
reachedLimit = true;
|
||||
sodium$itemRenderDist = i == 0 ? 1 : i;
|
||||
}
|
||||
@@ -48,9 +45,7 @@ public class MixinRenderGlobal_ItemRenderDist {
|
||||
if (flag && entity instanceof EntityItem) {
|
||||
final int i = Math.min((int) (entity.getDistanceSq(d0, d1, d2) / 4.0D), 255);
|
||||
sodium$entityItemCount[i]++;
|
||||
final boolean doRender = i <= sodium$itemRenderDist && sodium$itemRenderedCount < sodium$itemLimit;
|
||||
if (doRender) sodium$itemRenderedCount++;
|
||||
return doRender;
|
||||
return i <= sodium$itemRenderDist;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
+2
-4
@@ -49,8 +49,7 @@ public abstract class MixinEntityRenderer implements IResourceManagerReloadListe
|
||||
@Inject(method = "renderWorld(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/client/ForgeHooksClient;dispatchRenderLast(Lnet/minecraft/client/renderer/RenderGlobal;F)V", remap = false))
|
||||
private void iris$endLevelRender(float partialTicks, long limitTime, CallbackInfo callback, @Share("pipeline") LocalRef<WorldRenderingPipeline> pipeline) {
|
||||
// TODO: Iris
|
||||
final Camera camera = new Camera(mc.renderViewEntity, partialTicks);
|
||||
HandRenderer.INSTANCE.renderTranslucent(partialTicks, camera, mc.renderGlobal, pipeline.get());
|
||||
HandRenderer.INSTANCE.renderTranslucent(partialTicks, Camera.INSTANCE, mc.renderGlobal, pipeline.get());
|
||||
Minecraft.getMinecraft().mcProfiler.endStartSection("iris_final");
|
||||
pipeline.get().finalizeLevelRendering();
|
||||
pipeline.set(null);
|
||||
@@ -67,8 +66,7 @@ public abstract class MixinEntityRenderer implements IResourceManagerReloadListe
|
||||
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;clipRenderersByFrustum(Lnet/minecraft/client/renderer/culling/ICamera;F)V", shift = At.Shift.AFTER), method = "renderWorld(FJ)V")
|
||||
private void iris$beginEntities(float partialTicks, long startTime, CallbackInfo ci, @Share("pipeline") LocalRef<WorldRenderingPipeline> pipeline) {
|
||||
final Camera camera = new Camera(mc.renderViewEntity, partialTicks);
|
||||
pipeline.get().renderShadows((EntityRenderer) (Object) this, camera);
|
||||
pipeline.get().renderShadows((EntityRenderer) (Object) this, Camera.INSTANCE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+16
-3
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.sodium;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.iris.BiomeCategoryCache;
|
||||
import com.gtnewhorizons.angelica.utils.EventUtils;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraftforge.event.terraingen.BiomeEvent;
|
||||
@@ -9,9 +10,11 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(BiomeGenBase.class)
|
||||
public class MixinBiomeGenBase {
|
||||
private final ThreadLocal<BiomeEvent.GetWaterColor> waterColorEventLocal = ThreadLocal.withInitial(() -> new BiomeEvent.GetWaterColor((BiomeGenBase)(Object)this, 0));;
|
||||
private final ThreadLocal<BiomeEvent.GetGrassColor> grassColorEventLocal = ThreadLocal.withInitial(() -> new BiomeEvent.GetGrassColor((BiomeGenBase)(Object)this, 0));;
|
||||
public class MixinBiomeGenBase implements BiomeCategoryCache {
|
||||
@Unique
|
||||
private int cachedBiomeCategory = -1;
|
||||
private final ThreadLocal<BiomeEvent.GetWaterColor> waterColorEventLocal = ThreadLocal.withInitial(() -> new BiomeEvent.GetWaterColor((BiomeGenBase)(Object)this, 0));
|
||||
private final ThreadLocal<BiomeEvent.GetGrassColor> grassColorEventLocal = ThreadLocal.withInitial(() -> new BiomeEvent.GetGrassColor((BiomeGenBase)(Object)this, 0));
|
||||
private final ThreadLocal<BiomeEvent.GetFoliageColor> foliageColorEventLocal = ThreadLocal.withInitial(() -> new BiomeEvent.GetFoliageColor((BiomeGenBase)(Object)this, 0));
|
||||
|
||||
@Unique
|
||||
@@ -41,4 +44,14 @@ public class MixinBiomeGenBase {
|
||||
prepareEvent(event, original);
|
||||
return event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int iris$getCachedCategory() {
|
||||
return cachedBiomeCategory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void iris$setCachedCategory(int category) {
|
||||
this.cachedBiomeCategory = category;
|
||||
}
|
||||
}
|
||||
+5
-11
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.mixins.early.sodium;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.mojang.Camera;
|
||||
import com.gtnewhorizons.angelica.compat.mojang.GameModeUtil;
|
||||
import com.gtnewhorizons.angelica.compat.toremove.MatrixStack;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.IRenderGlobalExt;
|
||||
@@ -20,7 +21,6 @@ import net.coderbot.iris.pipeline.WorldRenderingPhase;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.uniforms.CapturedRenderingState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.PlayerControllerMP;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.RenderGlobal;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
@@ -162,10 +162,8 @@ public class MixinRenderGlobal implements IRenderGlobalExt {
|
||||
if(pass == 0) {
|
||||
pipeline.setPhase(WorldRenderingPhase.TERRAIN_CUTOUT);
|
||||
} else if(pass == 1) {
|
||||
final Camera camera = new Camera(mc.renderViewEntity, (float) partialTicks);
|
||||
|
||||
if (!ShadowRenderer.ACTIVE) {
|
||||
iris$beginTranslucents(pipeline, camera);
|
||||
iris$beginTranslucents(pipeline, Camera.INSTANCE);
|
||||
}
|
||||
|
||||
pipeline.setPhase(WorldRenderingPhase.TERRAIN_TRANSLUCENT);
|
||||
@@ -204,10 +202,7 @@ public class MixinRenderGlobal implements IRenderGlobalExt {
|
||||
}
|
||||
|
||||
private boolean isSpectatorMode() {
|
||||
final PlayerControllerMP controller = Minecraft.getMinecraft().playerController;
|
||||
if(controller == null)
|
||||
return false;
|
||||
return controller.currentGameType.getID() == 3;
|
||||
return GameModeUtil.isSpectator();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,11 +217,10 @@ public class MixinRenderGlobal implements IRenderGlobalExt {
|
||||
final Frustrum frustum = (Frustrum) frustrum;
|
||||
boolean hasForcedFrustum = false;
|
||||
boolean spectator = isSpectatorMode();
|
||||
Camera camera = new Camera(mc.renderViewEntity, partialTicks);
|
||||
frustum.setPosition(camera.getPos().x, camera.getPos().y, camera.getPos().z);
|
||||
frustum.setPosition(Camera.INSTANCE.getPos().x, Camera.INSTANCE.getPos().y, Camera.INSTANCE.getPos().z);
|
||||
|
||||
try {
|
||||
this.renderer.updateChunks(camera, frustum, hasForcedFrustum, sodium$frame++, spectator);
|
||||
this.renderer.updateChunks(Camera.INSTANCE, frustum, hasForcedFrustum, sodium$frame++, spectator);
|
||||
} finally {
|
||||
RenderDevice.exitManagedCode();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user