Skip to content

Commit 09abf46

Browse files
committed
Blackhole shader WIP
1 parent 057c1a6 commit 09abf46

File tree

15 files changed

+428
-156
lines changed

15 files changed

+428
-156
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(17)
1515
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
1616
minecraft {
1717
mappings channel: 'parchment', version: "${mappings_version}-${mc_version}"
18-
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
18+
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
1919

2020
runs {
2121
client {

src/main/java/igentuman/nc/block/entity/kugelblitz/BlackHoleBE.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020

2121
import static igentuman.nc.block.kugelblitz.BlackHoleBlock.ACTIVE;
22+
import static igentuman.nc.client.renderer.DistortShader.blackhole;
2223
import static igentuman.nc.setup.registration.NCSounds.BLACKHOLE_IDLE;
2324
import static igentuman.nc.setup.registration.NCSounds.BLACKHOLE_SPAWN;
2425
import static net.minecraft.world.level.block.Blocks.AIR;
@@ -40,7 +41,12 @@ public BlackHoleBE(BlockPos pPos, BlockState pBlockState) {
4041
}
4142

4243
public void tickClient() {
43-
if(isRemoved()) return;
44+
if(isRemoved()) {
45+
blackhole.remove(getBlockPos());
46+
}
47+
if (!blackhole.contains(getBlockPos())) {
48+
blackhole.add(getBlockPos());
49+
}
4450
scale = 0.3f + spawnDelay/100f;
4551
if (spawnDelay < 1) {
4652
playSound(BLACKHOLE_IDLE, 0.7f);
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package igentuman.nc.client.renderer;
2+
3+
import com.mojang.blaze3d.platform.GlStateManager;
4+
import com.mojang.blaze3d.systems.RenderSystem;
5+
import com.mojang.blaze3d.vertex.BufferBuilder;
6+
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
7+
import com.mojang.blaze3d.vertex.Tesselator;
8+
import com.mojang.blaze3d.vertex.VertexFormat;
9+
import igentuman.nc.block.entity.kugelblitz.BlackHoleBE;
10+
import net.minecraft.client.Minecraft;
11+
import net.minecraft.client.renderer.EffectInstance;
12+
import net.minecraft.core.BlockPos;
13+
import net.minecraft.world.level.block.entity.BlockEntity;
14+
import net.minecraftforge.api.distmarker.Dist;
15+
import net.minecraftforge.client.event.RenderLevelStageEvent;
16+
import net.minecraftforge.common.MinecraftForge;
17+
import net.minecraftforge.eventbus.api.SubscribeEvent;
18+
import net.minecraftforge.fml.common.Mod;
19+
import org.joml.Matrix4f;
20+
21+
import java.util.Collections;
22+
import java.util.HashSet;
23+
import java.util.Set;
24+
25+
import static igentuman.nc.NuclearCraft.MODID;
26+
import static igentuman.nc.client.renderer.NCShaders.blackholePostEffect;
27+
import static igentuman.nc.multiblock.kugelblitz.KugelblitzRegistration.KUGELBLITZ_BLOCKS;
28+
29+
@Mod.EventBusSubscriber(modid = MODID, value = Dist.CLIENT)
30+
public class DistortShader {
31+
32+
private static int currentSize = 0;
33+
public static void register() {
34+
MinecraftForge.EVENT_BUS.register(DistortShader.class);
35+
}
36+
37+
public static final BlackholeRegistry blackhole = new BlackholeRegistry();
38+
39+
public static class BlackholeRegistry {
40+
private final Set<BlockPos> positions = new HashSet<>();
41+
42+
public boolean contains(BlockPos pos) { return positions.contains(pos); }
43+
public void add(BlockPos pos) { positions.add(pos); }
44+
public void remove(BlockPos pos) { positions.remove(pos); }
45+
public Set<BlockPos> getPositions() { return Collections.unmodifiableSet(positions); }
46+
}
47+
48+
private static boolean isBlackHoleBlock(net.minecraft.world.level.Level level, net.minecraft.core.BlockPos pos) {
49+
return level.getBlockState(pos).is(KUGELBLITZ_BLOCKS.get("black_hole").get());
50+
}
51+
52+
private static boolean processBlackHole(Minecraft mc, RenderLevelStageEvent event, EffectInstance effect, BlockPos pos) {
53+
BlockEntity be = mc.level.getExistingBlockEntity(pos);
54+
float scaleMult = 1;
55+
if(be instanceof BlackHoleBE blackHoleBE) {
56+
scaleMult = 0.3f / blackHoleBE.scale;
57+
} else {
58+
return false;
59+
}
60+
if(scaleMult != 1) {
61+
scaleMult = (float) Math.pow(scaleMult+0.375f, 5);
62+
}
63+
// Default values
64+
float blurX = 0.5f;
65+
float blurY = 0.5f;
66+
boolean blackholeVisible = false;
67+
float distanceFactor = 0.0f;
68+
69+
if (mc.level == null && mc.player == null) {
70+
return false;
71+
}
72+
// Get matrices
73+
Matrix4f viewMatrix = event.getPoseStack().last().pose();
74+
Matrix4f projectionMatrix = RenderSystem.getProjectionMatrix();
75+
76+
// Calculate distance to blackhole
77+
double distanceSq = mc.player.position().distanceToSqr(
78+
pos.getX() + 0.5,
79+
pos.getY() + 0.5,
80+
pos.getZ() + 0.5
81+
);
82+
double distance = Math.sqrt(distanceSq);
83+
84+
// Get camera position
85+
net.minecraft.client.Camera camera = mc.gameRenderer.getMainCamera();
86+
net.minecraft.world.phys.Vec3 cameraPos = camera.getPosition();
87+
88+
// World to screen projection
89+
float posX = (float)(pos.getX() + 0.5 - cameraPos.x());
90+
float posY = (float)(pos.getY() + 0.5 - cameraPos.y());
91+
float posZ = (float)(pos.getZ() + 0.5 - cameraPos.z());
92+
93+
// Create position vector
94+
org.joml.Vector4f pos1 = new org.joml.Vector4f(posX, posY, posZ, 1.0f);
95+
pos1.mul(viewMatrix);
96+
pos1.mul(projectionMatrix);
97+
98+
// Perspective division
99+
if (pos1.w != 0.0f) {
100+
pos1.x /= pos1.w;
101+
pos1.y /= pos1.w;
102+
pos1.z /= pos1.w;
103+
}
104+
105+
// Check if in front of camera
106+
if (pos1.z > -1.0f && pos1.z < 1.0f) {
107+
// Calculate screen coordinates
108+
blurX = (pos1.x * 0.5f + 0.5f);
109+
blurY = (pos1.y * 0.5f + 0.5f);
110+
111+
// Check if on screen (with margin)
112+
float margin = 0.1f;
113+
if (blurX >= -margin && blurX <= 1.0f + margin &&
114+
blurY >= -margin && blurY <= 1.0f + margin) {
115+
blackholeVisible = true;
116+
distanceFactor = (float) (7f/distance);
117+
}
118+
}
119+
120+
// Scale radius and magnification based on distance
121+
float baseRadius = blackholeVisible ? 150.0f : 0.0f;
122+
float radius = baseRadius * distanceFactor * scaleMult;
123+
float baseMagnification = blackholeVisible ? 5.8f : 0.1f;
124+
125+
effect.getUniform("BlurPos").set(blurX, blurY);
126+
effect.getUniform("Radius").set(radius, baseMagnification/scaleMult);
127+
return true;
128+
}
129+
130+
@SubscribeEvent
131+
public static void onRenderTick(RenderLevelStageEvent event) {
132+
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_CUTOUT_BLOCKS) return;
133+
Minecraft mc = Minecraft.getInstance();
134+
135+
if (blackholePostEffect != null) {
136+
EffectInstance effect = blackholePostEffect.passes.get(0).getEffect();
137+
138+
if(currentSize != mc.getWindow().getWidth() + mc.getWindow().getHeight()) {
139+
currentSize = mc.getWindow().getWidth() + mc.getWindow().getHeight();
140+
blackholePostEffect.resize(mc.getWindow().getWidth(), mc.getWindow().getHeight());
141+
effect.getUniform("BlurDir").set(0.2f, 0.0f);
142+
}
143+
144+
RenderSystem.depthMask(false);
145+
for (BlockPos pos : blackhole.getPositions()) {
146+
if(processBlackHole(mc, event, effect, pos)) {
147+
blackholePostEffect.process(mc.getFrameTime());
148+
}
149+
}
150+
mc.getMainRenderTarget().bindWrite(false);
151+
blackholePostEffect.passes.get(blackholePostEffect.passes.size()-1).outTarget.bindRead();
152+
RenderSystem.depthFunc(515);
153+
// Set up blending to preserve what's already in the framebuffer
154+
RenderSystem.enableBlend();
155+
RenderSystem.blendFuncSeparate(
156+
GlStateManager.SourceFactor.SRC_ALPHA,
157+
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA,
158+
GlStateManager.SourceFactor.ONE,
159+
GlStateManager.DestFactor.ZERO
160+
);
161+
162+
// Draw a fullscreen quad with the processed shader result
163+
Tesselator tesselator = Tesselator.getInstance();
164+
BufferBuilder bufferbuilder = tesselator.getBuilder();
165+
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
166+
bufferbuilder.vertex(0, mc.getMainRenderTarget().height, 0).uv(0, 0).endVertex();
167+
bufferbuilder.vertex(mc.getMainRenderTarget().width, mc.getMainRenderTarget().height, 0).uv(1, 0).endVertex();
168+
bufferbuilder.vertex(mc.getMainRenderTarget().width, 0, 0).uv(1, 1).endVertex();
169+
bufferbuilder.vertex(0, 0, 0).uv(0, 1).endVertex();
170+
tesselator.end();
171+
172+
RenderSystem.depthFunc(515);
173+
RenderSystem.depthMask(true);
174+
RenderSystem.disableBlend();
175+
}
176+
}
177+
}

src/main/java/igentuman/nc/client/renderer/DistortionEffectRenderer.java

Lines changed: 0 additions & 81 deletions
This file was deleted.

src/main/java/igentuman/nc/client/renderer/NCRenderType.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,4 @@ private NCRenderType(String name, VertexFormat format, VertexFormat.Mode mode, i
2727
return create("nc_blackhole", DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, true, true, state);
2828
});
2929

30-
public static final Function<ResourceLocation, RenderType> DISTORTION = Util.memoize(resourceLocation -> {
31-
RenderType.CompositeState state = RenderType.CompositeState.builder()
32-
.setShaderState(NCShaders.DISTORTION.shard)
33-
.setTextureState(new RenderStateShard.TextureStateShard(resourceLocation, false, false))
34-
.setOutputState(RenderType.MAIN_TARGET)
35-
.setTransparencyState(RenderStateShard.NO_TRANSPARENCY)
36-
.createCompositeState(true);
37-
return create("distortion", DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, true, true, state);
38-
});
3930
}

src/main/java/igentuman/nc/client/renderer/NCShaders.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
44
import com.mojang.blaze3d.vertex.VertexFormat;
5+
import net.minecraft.client.Minecraft;
6+
import net.minecraft.client.renderer.PostChain;
57
import net.minecraft.client.renderer.RenderStateShard;
68
import net.minecraft.client.renderer.ShaderInstance;
79
import net.minecraft.resources.ResourceLocation;
@@ -20,14 +22,17 @@
2022
public class NCShaders {
2123

2224
public static final ShaderTracker BLACKHOLE_COLOR = new ShaderTracker();
23-
public static final ShaderTracker DISTORTION = new ShaderTracker();
2425

25-
public static final RenderStateShard.ShaderStateShard ZUZUZ = new RenderStateShard.ShaderStateShard();
26+
public static PostChain blackholePostEffect;
2627

2728
@SubscribeEvent
2829
public static void shaderRegistry(RegisterShadersEvent event) throws IOException {
2930
registerShader(event, rl("rendertype_blackhole"), DefaultVertexFormat.POSITION_COLOR_TEX, BLACKHOLE_COLOR);
30-
registerShader(event, rl("distortion"), DefaultVertexFormat.POSITION_COLOR_TEX, DISTORTION);
31+
Minecraft mc = Minecraft.getInstance();
32+
33+
blackholePostEffect = new PostChain(mc.getTextureManager(), mc.getResourceManager(),
34+
mc.getMainRenderTarget(), rl("shaders/post/black_hole.json"));
35+
blackholePostEffect.resize(mc.getWindow().getWidth(), mc.getWindow().getHeight());
3136
}
3237

3338
private static void registerShader(RegisterShadersEvent event, ResourceLocation shaderLocation, VertexFormat vertexFormat, ShaderTracker tracker) throws IOException {

src/main/java/igentuman/nc/handler/event/client/BlockOverlayHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import igentuman.api.nc.SideModeToggleable;
66
import igentuman.nc.block.entity.NuclearCraftBE;
77
import igentuman.nc.block.entity.fusion.FusionCoreBE;
8+
import igentuman.nc.client.renderer.DistortShader;
89
import igentuman.nc.item.QNP;
910
import igentuman.nc.util.NCBlockPos;
1011
import net.minecraft.client.Camera;
@@ -63,7 +64,6 @@ public static void register(FMLClientSetupEvent event) {
6364
@SubscribeEvent
6465
public static void onRenderWorldEvent(RenderLevelStageEvent e) {
6566
final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
66-
6767
Player player = Minecraft.getInstance().player;
6868
if(e.getStage().equals(RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS)) {
6969
for(BlockPos pos: fusionReactors) {

src/main/java/igentuman/nc/setup/ClientSetup.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import igentuman.nc.client.particle.FusionBeamParticle;
1818
import igentuman.nc.client.particle.RadiationParticle;
1919
import igentuman.nc.client.gui.fission.FissionControllerScreen;
20-
import igentuman.nc.client.renderer.DistortionEffectRenderer;
20+
import igentuman.nc.client.renderer.DistortShader;
2121
import igentuman.nc.client.sound.SoundHandler;
2222
import igentuman.nc.content.energy.BatteryBlocks;
2323
import igentuman.nc.handler.event.client.*;
@@ -73,7 +73,7 @@ public class ClientSetup {
7373
public static void init(FMLClientSetupEvent event) {
7474
event.enqueueWork(() -> {
7575
MinecraftForge.EVENT_BUS.addListener(LOWEST, SoundHandler::onTilePlaySound);
76-
DistortionEffectRenderer.register();
76+
DistortShader.register();
7777
BlockEntityRenderers.register(FUSION_BE.get("fusion_core").get(), FusionCoreRenderer::new);
7878
BlockEntityRenderers.register(EXPL_BE.get(), EXPLRenderer::new);
7979
BlockEntityRenderers.register(TURBINE_BE.get("turbine_rotor_shaft").get(), TurbineRotorRenderer::new);

src/main/resources/META-INF/accesstransformer.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
public net.minecraft.client.KeyMapping f_90817_ # isDown
22

33
public-f net.minecraft.client.gui.screens.Screen m_6575_(Lnet/minecraft/client/Minecraft;II)V # init
4-
4+
public net.minecraft.client.renderer.PostChain f_110009_
55
#Client stuff that needs to be ATd to make "virtual" slots possible
66
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen f_97717_ # quickCraftingType
77
protected net.minecraft.client.gui.screens.inventory.AbstractContainerScreen f_97718_ # quickCraftingButton

0 commit comments

Comments
 (0)