170 lines
7.6 KiB
Java
170 lines
7.6 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.CompiledRenderPipeline;
|
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
|
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.shaders.UniformType;
|
|
import com.mojang.blaze3d.systems.RenderPass;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.Map.Entry;
|
|
import java.util.function.Consumer;
|
|
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> passes, Map<ResourceLocation, PostChainConfig.InternalTarget> internalTargets, Set<ResourceLocation> externalTargets) {
|
|
this.passes = passes;
|
|
this.internalTargets = internalTargets;
|
|
this.externalTargets = externalTargets;
|
|
}
|
|
|
|
public static PostChain load(PostChainConfig config, TextureManager textureManager, Set<ResourceLocation> externalTargets, ResourceLocation name) throws ShaderManager.CompilationException {
|
|
Stream<ResourceLocation> stream = config.passes().stream().flatMap(PostChainConfig.Pass::referencedTargets);
|
|
Set<ResourceLocation> set = (Set<ResourceLocation>)stream.filter(resourceLocation -> !config.internalTargets().containsKey(resourceLocation))
|
|
.collect(Collectors.toSet());
|
|
Set<ResourceLocation> set2 = Sets.<ResourceLocation>difference(set, externalTargets);
|
|
if (!set2.isEmpty()) {
|
|
throw new ShaderManager.CompilationException("Referenced external targets are not available in this context: " + set2);
|
|
} else {
|
|
Builder<PostPass> builder = ImmutableList.builder();
|
|
|
|
for (int i = 0; i < config.passes().size(); i++) {
|
|
PostChainConfig.Pass pass = (PostChainConfig.Pass)config.passes().get(i);
|
|
builder.add(createPass(textureManager, pass, name.withSuffix("/" + i)));
|
|
}
|
|
|
|
return new PostChain(builder.build(), config.internalTargets(), set);
|
|
}
|
|
}
|
|
|
|
private static PostPass createPass(TextureManager textureManager, PostChainConfig.Pass pass, ResourceLocation location) throws ShaderManager.CompilationException {
|
|
RenderPipeline.Builder builder = RenderPipeline.builder(RenderPipelines.POST_PROCESSING_SNIPPET)
|
|
.withFragmentShader(pass.fragmentShaderId())
|
|
.withVertexShader(pass.vertexShaderId())
|
|
.withLocation(location);
|
|
|
|
for (PostChainConfig.Input input : pass.inputs()) {
|
|
builder.withSampler(input.samplerName() + "Sampler");
|
|
builder.withUniform(input.samplerName() + "Size", UniformType.VEC2);
|
|
}
|
|
|
|
for (PostChainConfig.Uniform uniform : pass.uniforms()) {
|
|
builder.withUniform(uniform.name(), (UniformType)Objects.requireNonNull((UniformType)UniformType.CODEC.byName(uniform.type())));
|
|
}
|
|
|
|
RenderPipeline renderPipeline = builder.build();
|
|
CompiledRenderPipeline compiledRenderPipeline = RenderSystem.getDevice().precompilePipeline(renderPipeline);
|
|
|
|
for (PostChainConfig.Uniform uniform2 : pass.uniforms()) {
|
|
String string = uniform2.name();
|
|
if (!compiledRenderPipeline.containsUniform(string)) {
|
|
throw new ShaderManager.CompilationException("Uniform '" + string + "' does not exist for " + location);
|
|
}
|
|
}
|
|
|
|
PostPass postPass = new PostPass(renderPipeline, pass.outputTarget(), pass.uniforms());
|
|
|
|
for (PostChainConfig.Input input2 : pass.inputs()) {
|
|
switch (input2) {
|
|
case PostChainConfig.TextureInput(String var39, ResourceLocation var40, int var41, int var42, boolean var43):
|
|
AbstractTexture abstractTexture = textureManager.getTexture(var40.withPath((UnaryOperator<String>)(string -> "textures/effect/" + string + ".png")));
|
|
abstractTexture.setFilter(var43, false);
|
|
postPass.addInput(new PostPass.TextureInput(var39, abstractTexture, var41, var42));
|
|
break;
|
|
case PostChainConfig.TargetInput(String var22, ResourceLocation var45, boolean var46, boolean var47):
|
|
postPass.addInput(new PostPass.TargetInput(var22, var45, var46, var47));
|
|
break;
|
|
default:
|
|
throw new MatchException(null, null);
|
|
}
|
|
}
|
|
|
|
return postPass;
|
|
}
|
|
|
|
public void addToFrame(
|
|
FrameGraphBuilder frameGraphBuilder, int width, int height, PostChain.TargetBundle targetBundle, @Nullable Consumer<RenderPass> uniformSetter
|
|
) {
|
|
Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, width, 0.0F, height, 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 var26, int var27) -> new RenderTargetDescriptor(var26, var27, true, 0);
|
|
case PostChainConfig.FullScreenTarget var17 -> new RenderTargetDescriptor(width, height, true, 0);
|
|
default -> throw new MatchException(null, null);
|
|
};
|
|
map.put(resourceLocation2, frameGraphBuilder.createInternal(resourceLocation2.toString(), renderTargetDescriptor));
|
|
}
|
|
|
|
for (PostPass postPass : this.passes) {
|
|
postPass.addToFrame(frameGraphBuilder, map, matrix4f, uniformSetter);
|
|
}
|
|
|
|
for (ResourceLocation resourceLocation : this.externalTargets) {
|
|
targetBundle.replace(resourceLocation, (ResourceHandle<RenderTarget>)map.get(resourceLocation));
|
|
}
|
|
}
|
|
|
|
@Deprecated
|
|
public void process(RenderTarget renderTarget, GraphicsResourceAllocator allocator, @Nullable Consumer<RenderPass> uniformSetter) {
|
|
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, uniformSetter);
|
|
frameGraphBuilder.execute(allocator);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public interface TargetBundle {
|
|
static PostChain.TargetBundle of(ResourceLocation id, ResourceHandle<RenderTarget> handle) {
|
|
return new 1(handle, id);
|
|
}
|
|
|
|
void replace(ResourceLocation id, ResourceHandle<RenderTarget> handle);
|
|
|
|
@Nullable
|
|
ResourceHandle<RenderTarget> get(ResourceLocation id);
|
|
|
|
default ResourceHandle<RenderTarget> getOrThrow(ResourceLocation id) {
|
|
ResourceHandle<RenderTarget> resourceHandle = this.get(id);
|
|
if (resourceHandle == null) {
|
|
throw new IllegalArgumentException("Missing target with id " + id);
|
|
} else {
|
|
return resourceHandle;
|
|
}
|
|
}
|
|
}
|
|
}
|