Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
import com.gregtechceu.gtceu.client.util.RenderBufferHelper;

import net.irisshaders.iris.Iris;
import net.irisshaders.iris.shaderpack.materialmap.WorldRenderingSettings;
import net.irisshaders.iris.uniforms.CapturedRenderingState;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.TheEndPortalRenderer;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.textures.UnitTextureAtlasSprite;
Expand All @@ -24,6 +28,7 @@
import com.mojang.serialization.Codec;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.jetbrains.annotations.NotNull;

// @SuppressWarnings("unused")
Expand Down Expand Up @@ -154,9 +159,19 @@ private void renderCuboid(PoseStack stack, MultiBufferSource buffer, Direction u
if (GTCEu.isModLoaded(GTValues.MODID_OCULUS) && Iris.getCurrentPack().isPresent()) {
consumer = buffer.getBuffer(RenderType.entitySolid(TheEndPortalRenderer.END_PORTAL_LOCATION));
} else {
consumer = buffer.getBuffer(RenderType.endPortal());
consumer = buffer.getBuffer(MoniRenderTypes.END_PORTAL_COLORED);
}
RenderBufferHelper.renderCube(consumer, pose, 0xFFFFFF00, combinedLight, UnitTextureAtlasSprite.INSTANCE,
Iris.getCurrentPack().ifPresent(pack -> {
Object2IntMap<BlockState> stateIds = WorldRenderingSettings.INSTANCE.getBlockStateIds();
if (stateIds != null) {
CapturedRenderingState.INSTANCE
.setCurrentBlockEntity(stateIds.getOrDefault(Blocks.END_PORTAL.defaultBlockState(), -1));
CapturedRenderingState.INSTANCE.setCurrentEntity(6767); // Should be unclaimed hopefully :)
}
});

RenderBufferHelper.renderCube(consumer, pose, 0xFF0000FF,
combinedLight, UnitTextureAtlasSprite.INSTANCE,
minX, minY, minZ, maxX, maxY, maxZ);
stack.popPose();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderStateShard.ShaderStateShard;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.blockentity.TheEndPortalRenderer;

import com.mojang.blaze3d.vertex.DefaultVertexFormat;
Expand All @@ -23,4 +24,16 @@ public class MoniRenderTypes {
.add(TheEndPortalRenderer.END_SKY_LOCATION, false, false)
.add(TheEndPortalRenderer.END_PORTAL_LOCATION, false, false).build())
.createCompositeState(false));
public static RenderType END_PORTAL_COLORED = RenderType.create("end_portal_colored",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS, 256, false, false,
RenderType.CompositeState.builder()
.setShaderState(new ShaderStateShard(() -> {
ShaderInstance shader = MoniShaders.ENDPORTAL_COLORED_SHADER;
shader.safeGetUniform("EndPortalLayers").set(15);
return shader;
}))
.setTextureState(RenderStateShard.MultiTextureStateShard.builder()
.add(TheEndPortalRenderer.END_SKY_LOCATION, false, false)
.add(TheEndPortalRenderer.END_PORTAL_LOCATION, false, false).build())
.createCompositeState(false));
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@
public class MoniShaders {

public static ShaderInstance WORMHOLE_SHADER;
public static ShaderInstance ENDPORTAL_COLORED_SHADER;

@SubscribeEvent
public static void shaderRegistry(RegisterShadersEvent event) {
try {
event.registerShader(new ShaderInstance(event.getResourceProvider(),
MoniLabs.id("rendertype_wormhole"), DefaultVertexFormat.POSITION),
(shaderInstance -> WORMHOLE_SHADER = shaderInstance));

event.registerShader(new ShaderInstance(event.getResourceProvider(),
MoniLabs.id("rendertype_colored_endportal"), DefaultVertexFormat.POSITION_COLOR),
(shaderInstance -> ENDPORTAL_COLORED_SHADER = shaderInstance));
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package net.neganote.monilabs.client.render;

public record ShaderAnalysisResult(String firstWriteLine, String referencedVariable, boolean valid) {}
130 changes: 130 additions & 0 deletions src/main/java/net/neganote/monilabs/mixin/ProgramMixin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package net.neganote.monilabs.mixin;

import net.neganote.monilabs.MoniLabs;
import net.neganote.monilabs.client.render.ShaderAnalysisResult;

import com.mojang.blaze3d.shaders.Program;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Mixin(Program.class)
public class ProgramMixin {

@Unique
private static final Pattern MAIN_PATTERN = Pattern.compile("void\\s+main\\s*\\(\\s*\\)\\s*\\{([\\s\\S]*)}");
@Unique
private static final Pattern DECL_PATTERN = Pattern
.compile("\\b((?:[iu]?vec\\d|float|int|bool))\\b\\s+([\\w\\d_]+)");
@Unique
private static final Pattern TARGET_PATTERN = Pattern
.compile("layout\\s*\\(\\s*location\\s*=\\s*0\\s*\\)\\s*out\\s+vec4\\s+(\\w+)");
@Unique
private static final Pattern VAR_PATTERN = Pattern.compile("\\b([a-zA-Z_]\\w*)\\b");

// Works for all popular shaders
// Basically what this does is find the last write to the color variable before it gets actually written to the
// framebuffer
@Unique
private static ShaderAnalysisResult moniLabs$analyzeShaderForColorWrite(String content) {
Matcher mainMatcher = MAIN_PATTERN.matcher(content);
if (!mainMatcher.find()) return new ShaderAnalysisResult("", "", false);

String mainBody = mainMatcher.group(1);

Matcher targetMatcher = TARGET_PATTERN.matcher(content);
String targetOut = targetMatcher.find() ? targetMatcher.group(1) : "gl_FragColor";

Map<String, String> knownTypes = new HashMap<>();
String[] lines = mainBody.split("\n");

for (String line : lines) {
line = line.trim().replaceAll("//.*", "");
if (line.isEmpty()) {
continue;
}

Matcher declMatch = DECL_PATTERN.matcher(line);
while (declMatch.find()) {
knownTypes.put(declMatch.group(2), declMatch.group(1));
}

if (line.contains(targetOut) && line.contains("=")) {
String rightSide = line.substring(line.indexOf('=') + 1);
Matcher varMatch = VAR_PATTERN.matcher(rightSide);

while (varMatch.find()) {
String candidate = varMatch.group(1);
if (Character.isDigit(candidate.charAt(0))) continue;

if (knownTypes.containsKey(candidate)) {
return new ShaderAnalysisResult(line, candidate, true);
}
}
}
}
return new ShaderAnalysisResult("", "", false);
}

@Unique
private static String moniLabs$modifyShader(String code, ShaderAnalysisResult result) {
if (!result.valid()) {
MoniLabs.LOGGER.log(Level.ERROR,
"Could not successfully analyze current shader for colored ender portal inject");
return code;
}
String newSource = code.replace("void main", """
vec3 moni_rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 moni_hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void main""");

newSource = newSource.replace(result.firstWriteLine(), """
if (iris_entityInfo.x == 6767) {
vec3 _origHsv = moni_rgb2hsv(%s.rgb);
vec3 _destHsv = moni_rgb2hsv(iris_vertexColor.rgb);
//copy hue and saturation
_origHsv.x = _destHsv.x;
_origHsv.y = _destHsv.y;
%s.rgb = moni_hsv2rgb(_origHsv);
}
""".formatted(result.referencedVariable(), result.referencedVariable()) + "\n\t" +
result.firstWriteLine());
return newSource;
}

@Redirect(method = "compileShaderInternal",
at = @At(value = "INVOKE",
target = "Lorg/apache/commons/io/IOUtils;toString(Ljava/io/InputStream;Ljava/nio/charset/Charset;)Ljava/lang/String;"))
private static String moniLabs$modifyIrisEntityDiffuseShader(InputStream sw, Charset input, Program.Type type,
String name) throws IOException {
String original = IOUtils.toString(sw, input);
if (name.contains("block_entity_diffuse") && type == Program.Type.FRAGMENT) {
var analysisResult = moniLabs$analyzeShaderForColorWrite(original);
return moniLabs$modifyShader(original, analysisResult);
}

return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#version 150

#line 0 1
/*#version 150*/

mat2 mat2_rotate_z(float radians) {
return mat2(
cos(radians), -sin(radians),
sin(radians), cos(radians)
);
}
#line 3 0

uniform sampler2D Sampler0;
uniform sampler2D Sampler1;

uniform float GameTime;
uniform int EndPortalLayers;

in vec4 texProj0;
in vec3 vColor;

const vec3[] COLORS = vec3[](
vec3(0.022087, 0.098399, 0.110818),
vec3(0.011892, 0.095924, 0.089485),
vec3(0.027636, 0.101689, 0.100326),
vec3(0.046564, 0.109883, 0.114838),
vec3(0.064901, 0.117696, 0.097189),
vec3(0.063761, 0.086895, 0.123646),
vec3(0.084817, 0.111994, 0.166380),
vec3(0.097489, 0.154120, 0.091064),
vec3(0.106152, 0.131144, 0.195191),
vec3(0.097721, 0.110188, 0.187229),
vec3(0.133516, 0.138278, 0.148582),
vec3(0.070006, 0.243332, 0.235792),
vec3(0.196766, 0.142899, 0.214696),
vec3(0.047281, 0.315338, 0.321970),
vec3(0.204675, 0.390010, 0.302066),
vec3(0.080955, 0.314821, 0.661491)
);

const mat4 SCALE_TRANSLATE = mat4(
0.5, 0.0, 0.0, 0.25,
0.0, 0.5, 0.0, 0.25,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);

vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

mat4 end_portal_layer(float layer) {
mat4 translate = mat4(
1.0, 0.0, 0.0, 17.0 / layer,
0.0, 1.0, 0.0, (2.0 + layer / 1.5) * (GameTime * 1.5),
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
);

mat2 rotate = mat2_rotate_z(radians((layer * layer * 4321.0 + layer * 9.0) * 2.0));

mat2 scale = mat2((4.5 - layer / 4.0) * 2.0);

return mat4(scale * rotate) * translate * SCALE_TRANSLATE;
}

out vec4 fragColor;

void main() {
vec3 color = textureProj(Sampler0, texProj0).rgb * COLORS[0];
for (int i = 0; i < EndPortalLayers; i++) {
color += textureProj(Sampler1, texProj0 * end_portal_layer(float(i + 1))).rgb * COLORS[i];
}
vec3 origHsv = rgb2hsv(color);
vec3 destHsv = rgb2hsv(vColor);
//copy hue and saturation
origHsv.x = destHsv.x;
origHsv.y = destHsv.y;
color.rgb = hsv2rgb(origHsv);
fragColor = vec4(color, 1.0);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"blend": {
"func": "add",
"srcrgb": "srcalpha",
"dstrgb": "1-srcalpha"
},
"vertex": "monilabs:rendertype_colored_endportal",
"fragment": "monilabs:rendertype_colored_endportal",
"attributes": [],
"samplers": [
{ "name": "Sampler0" },
{ "name": "Sampler1" }
],
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "GameTime", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "EndPortalLayers", "type": "int", "count": 1, "values": [ 0.0 ] }
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#version 150

#line 0 1
/*#version 150*/

vec4 projection_from_position(vec4 position) {
vec4 projection = position * 0.5;
projection.xy = vec2(projection.x + projection.w, projection.y + projection.w);
projection.zw = position.zw;
return projection;
}
#line 3 0

in vec3 Position;
in vec3 Color;

uniform mat4 ModelViewMat;
uniform mat4 ProjMat;

out vec4 texProj0;
out vec3 vColor;

void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);

texProj0 = projection_from_position(gl_Position);
vColor = Color;
}
1 change: 1 addition & 0 deletions src/main/resources/monilabs.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"DefaultChunkRendererMixin",
"ShaderLoaderMixin",
"GameRendererMixin",
"ProgramMixin",
"accessor.TerrainRenderPassAccessor",
"accessor.ShaderChunkRendererAccessor"
],
Expand Down
Loading