minecraft-src/net/minecraft/client/renderer/PostChain.java
2025-07-04 02:00:41 +03:00

159 lines
7 KiB
Java

package net.minecraft.client.renderer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableList.Builder;
import com.mojang.blaze3d.framegraph.FrameGraphBuilder;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.resource.GraphicsResourceAllocator;
import com.mojang.blaze3d.resource.RenderTargetDescriptor;
import com.mojang.blaze3d.resource.ResourceHandle;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.PostChain.TargetBundle.1;
import net.minecraft.client.renderer.texture.AbstractTexture;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
@Environment(EnvType.CLIENT)
public class PostChain {
public static final ResourceLocation MAIN_TARGET_ID = ResourceLocation.withDefaultNamespace("main");
private final List<PostPass> passes;
private final Map<ResourceLocation, PostChainConfig.InternalTarget> internalTargets;
private final Set<ResourceLocation> externalTargets;
private PostChain(List<PostPass> list, Map<ResourceLocation, PostChainConfig.InternalTarget> map, Set<ResourceLocation> set) {
this.passes = list;
this.internalTargets = map;
this.externalTargets = set;
}
public static PostChain load(PostChainConfig postChainConfig, TextureManager textureManager, ShaderManager shaderManager, Set<ResourceLocation> set) throws ShaderManager.CompilationException {
Stream<ResourceLocation> stream = postChainConfig.passes()
.stream()
.flatMap(passx -> passx.inputs().stream())
.flatMap(input -> input.referencedTargets().stream());
Set<ResourceLocation> set2 = (Set<ResourceLocation>)stream.filter(resourceLocation -> !postChainConfig.internalTargets().containsKey(resourceLocation))
.collect(Collectors.toSet());
Set<ResourceLocation> set3 = Sets.<ResourceLocation>difference(set2, set);
if (!set3.isEmpty()) {
throw new ShaderManager.CompilationException("Referenced external targets are not available in this context: " + set3);
} else {
Builder<PostPass> builder = ImmutableList.builder();
for (PostChainConfig.Pass pass : postChainConfig.passes()) {
builder.add(createPass(textureManager, shaderManager, pass));
}
return new PostChain(builder.build(), postChainConfig.internalTargets(), set2);
}
}
private static PostPass createPass(TextureManager textureManager, ShaderManager shaderManager, PostChainConfig.Pass pass) throws ShaderManager.CompilationException {
ResourceLocation resourceLocation = pass.program();
CompiledShaderProgram compiledShaderProgram = shaderManager.getProgramForLoading(
new ShaderProgram(resourceLocation, DefaultVertexFormat.POSITION, ShaderDefines.EMPTY)
);
for (PostChainConfig.Uniform uniform : pass.uniforms()) {
String string = uniform.name();
if (compiledShaderProgram.getUniform(string) == null) {
throw new ShaderManager.CompilationException("Uniform '" + string + "' does not exist for " + resourceLocation);
}
}
String string2 = resourceLocation.toString();
PostPass postPass = new PostPass(string2, compiledShaderProgram, pass.outputTarget(), pass.uniforms());
for (PostChainConfig.Input input : pass.inputs()) {
switch (input) {
case PostChainConfig.TextureInput(String var35, ResourceLocation var36, int var37, int var38, boolean var39):
AbstractTexture abstractTexture = textureManager.getTexture(var36.withPath((UnaryOperator<String>)(stringx -> "textures/effect/" + stringx + ".png")));
abstractTexture.setFilter(var39, false);
postPass.addInput(new PostPass.TextureInput(var35, abstractTexture, var37, var38));
break;
case PostChainConfig.TargetInput(String var22, ResourceLocation var41, boolean var42, boolean var43):
postPass.addInput(new PostPass.TargetInput(var22, var41, var42, var43));
break;
default:
throw new MatchException(null, null);
}
}
return postPass;
}
public void addToFrame(FrameGraphBuilder frameGraphBuilder, int i, int j, PostChain.TargetBundle targetBundle) {
Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, i, 0.0F, j, 0.1F, 1000.0F);
Map<ResourceLocation, ResourceHandle<RenderTarget>> map = new HashMap(this.internalTargets.size() + this.externalTargets.size());
for (ResourceLocation resourceLocation : this.externalTargets) {
map.put(resourceLocation, targetBundle.getOrThrow(resourceLocation));
}
for (Entry<ResourceLocation, PostChainConfig.InternalTarget> entry : this.internalTargets.entrySet()) {
ResourceLocation resourceLocation2 = (ResourceLocation)entry.getKey();
RenderTargetDescriptor renderTargetDescriptor = switch ((PostChainConfig.InternalTarget)entry.getValue()) {
case PostChainConfig.FixedSizedTarget(int var25, int var26) -> new RenderTargetDescriptor(var25, var26, true);
case PostChainConfig.FullScreenTarget var16 -> new RenderTargetDescriptor(i, j, true);
default -> throw new MatchException(null, null);
};
map.put(resourceLocation2, frameGraphBuilder.createInternal(resourceLocation2.toString(), renderTargetDescriptor));
}
for (PostPass postPass : this.passes) {
postPass.addToFrame(frameGraphBuilder, map, matrix4f);
}
for (ResourceLocation resourceLocation : this.externalTargets) {
targetBundle.replace(resourceLocation, (ResourceHandle<RenderTarget>)map.get(resourceLocation));
}
}
@Deprecated
public void process(RenderTarget renderTarget, GraphicsResourceAllocator graphicsResourceAllocator) {
FrameGraphBuilder frameGraphBuilder = new FrameGraphBuilder();
PostChain.TargetBundle targetBundle = PostChain.TargetBundle.of(MAIN_TARGET_ID, frameGraphBuilder.importExternal("main", renderTarget));
this.addToFrame(frameGraphBuilder, renderTarget.width, renderTarget.height, targetBundle);
frameGraphBuilder.execute(graphicsResourceAllocator);
}
public void setUniform(String name, float backgroundBlurriness) {
for (PostPass postPass : this.passes) {
postPass.getShader().safeGetUniform(name).set(backgroundBlurriness);
}
}
@Environment(EnvType.CLIENT)
public interface TargetBundle {
static PostChain.TargetBundle of(ResourceLocation resourceLocation, ResourceHandle<RenderTarget> resourceHandle) {
return new 1(resourceHandle, resourceLocation);
}
void replace(ResourceLocation resourceLocation, ResourceHandle<RenderTarget> resourceHandle);
@Nullable
ResourceHandle<RenderTarget> get(ResourceLocation resourceLocation);
default ResourceHandle<RenderTarget> getOrThrow(ResourceLocation resourceLocation) {
ResourceHandle<RenderTarget> resourceHandle = this.get(resourceLocation);
if (resourceHandle == null) {
throw new IllegalArgumentException("Missing target with id " + resourceLocation);
} else {
return resourceHandle;
}
}
}
}