minecraft-src/com/mojang/blaze3d/pipeline/RenderPipeline.java
2025-07-04 03:45:38 +03:00

488 lines
14 KiB
Java

package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.DontObfuscate;
import com.mojang.blaze3d.platform.DepthTestFunction;
import com.mojang.blaze3d.platform.LogicOp;
import com.mojang.blaze3d.platform.PolygonMode;
import com.mojang.blaze3d.shaders.UniformType;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Map.Entry;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.ShaderDefines;
import net.minecraft.resources.ResourceLocation;
@Environment(EnvType.CLIENT)
@DontObfuscate
public class RenderPipeline {
private final ResourceLocation location;
private final ResourceLocation vertexShader;
private final ResourceLocation fragmentShader;
private final ShaderDefines shaderDefines;
private final List<String> samplers;
private final List<RenderPipeline.UniformDescription> uniforms;
private final DepthTestFunction depthTestFunction;
private final PolygonMode polygonMode;
private final boolean cull;
private final LogicOp colorLogic;
private final Optional<BlendFunction> blendFunction;
private final boolean writeColor;
private final boolean writeAlpha;
private final boolean writeDepth;
private final VertexFormat vertexFormat;
private final VertexFormat.Mode vertexFormatMode;
private final float depthBiasScaleFactor;
private final float depthBiasConstant;
protected RenderPipeline(
ResourceLocation resourceLocation,
ResourceLocation resourceLocation2,
ResourceLocation resourceLocation3,
ShaderDefines shaderDefines,
List<String> list,
List<RenderPipeline.UniformDescription> list2,
Optional<BlendFunction> optional,
DepthTestFunction depthTestFunction,
PolygonMode polygonMode,
boolean bl,
boolean bl2,
boolean bl3,
boolean bl4,
LogicOp logicOp,
VertexFormat vertexFormat,
VertexFormat.Mode mode,
float f,
float g
) {
this.location = resourceLocation;
this.vertexShader = resourceLocation2;
this.fragmentShader = resourceLocation3;
this.shaderDefines = shaderDefines;
this.samplers = list;
this.uniforms = list2;
this.depthTestFunction = depthTestFunction;
this.polygonMode = polygonMode;
this.cull = bl;
this.blendFunction = optional;
this.writeColor = bl2;
this.writeAlpha = bl3;
this.writeDepth = bl4;
this.colorLogic = logicOp;
this.vertexFormat = vertexFormat;
this.vertexFormatMode = mode;
this.depthBiasScaleFactor = f;
this.depthBiasConstant = g;
}
public String toString() {
return this.location.toString();
}
public DepthTestFunction getDepthTestFunction() {
return this.depthTestFunction;
}
public PolygonMode getPolygonMode() {
return this.polygonMode;
}
public boolean isCull() {
return this.cull;
}
public LogicOp getColorLogic() {
return this.colorLogic;
}
public Optional<BlendFunction> getBlendFunction() {
return this.blendFunction;
}
public boolean isWriteColor() {
return this.writeColor;
}
public boolean isWriteAlpha() {
return this.writeAlpha;
}
public boolean isWriteDepth() {
return this.writeDepth;
}
public float getDepthBiasScaleFactor() {
return this.depthBiasScaleFactor;
}
public float getDepthBiasConstant() {
return this.depthBiasConstant;
}
public ResourceLocation getLocation() {
return this.location;
}
public VertexFormat getVertexFormat() {
return this.vertexFormat;
}
public VertexFormat.Mode getVertexFormatMode() {
return this.vertexFormatMode;
}
public ResourceLocation getVertexShader() {
return this.vertexShader;
}
public ResourceLocation getFragmentShader() {
return this.fragmentShader;
}
public ShaderDefines getShaderDefines() {
return this.shaderDefines;
}
public List<String> getSamplers() {
return this.samplers;
}
public List<RenderPipeline.UniformDescription> getUniforms() {
return this.uniforms;
}
public boolean wantsDepthTexture() {
return this.depthTestFunction != DepthTestFunction.NO_DEPTH_TEST || this.depthBiasConstant != 0.0F || this.depthBiasScaleFactor != 0.0F || this.writeDepth;
}
public static RenderPipeline.Builder builder(RenderPipeline.Snippet... snippets) {
RenderPipeline.Builder builder = new RenderPipeline.Builder();
for (RenderPipeline.Snippet snippet : snippets) {
builder.withSnippet(snippet);
}
return builder;
}
@Environment(EnvType.CLIENT)
@DontObfuscate
public static class Builder {
private Optional<ResourceLocation> location = Optional.empty();
private Optional<ResourceLocation> fragmentShader = Optional.empty();
private Optional<ResourceLocation> vertexShader = Optional.empty();
private Optional<ShaderDefines.Builder> definesBuilder = Optional.empty();
private Optional<List<String>> samplers = Optional.empty();
private Optional<List<RenderPipeline.UniformDescription>> uniforms = Optional.empty();
private Optional<DepthTestFunction> depthTestFunction = Optional.empty();
private Optional<PolygonMode> polygonMode = Optional.empty();
private Optional<Boolean> cull = Optional.empty();
private Optional<Boolean> writeColor = Optional.empty();
private Optional<Boolean> writeAlpha = Optional.empty();
private Optional<Boolean> writeDepth = Optional.empty();
private Optional<LogicOp> colorLogic = Optional.empty();
private Optional<BlendFunction> blendFunction = Optional.empty();
private Optional<VertexFormat> vertexFormat = Optional.empty();
private Optional<VertexFormat.Mode> vertexFormatMode = Optional.empty();
private float depthBiasScaleFactor;
private float depthBiasConstant;
Builder() {
}
public RenderPipeline.Builder withLocation(String string) {
this.location = Optional.of(ResourceLocation.withDefaultNamespace(string));
return this;
}
public RenderPipeline.Builder withLocation(ResourceLocation resourceLocation) {
this.location = Optional.of(resourceLocation);
return this;
}
public RenderPipeline.Builder withFragmentShader(String string) {
this.fragmentShader = Optional.of(ResourceLocation.withDefaultNamespace(string));
return this;
}
public RenderPipeline.Builder withFragmentShader(ResourceLocation resourceLocation) {
this.fragmentShader = Optional.of(resourceLocation);
return this;
}
public RenderPipeline.Builder withVertexShader(String string) {
this.vertexShader = Optional.of(ResourceLocation.withDefaultNamespace(string));
return this;
}
public RenderPipeline.Builder withVertexShader(ResourceLocation resourceLocation) {
this.vertexShader = Optional.of(resourceLocation);
return this;
}
public RenderPipeline.Builder withShaderDefine(String string) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
((ShaderDefines.Builder)this.definesBuilder.get()).define(string);
return this;
}
public RenderPipeline.Builder withShaderDefine(String string, int i) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
((ShaderDefines.Builder)this.definesBuilder.get()).define(string, i);
return this;
}
public RenderPipeline.Builder withShaderDefine(String string, float f) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
((ShaderDefines.Builder)this.definesBuilder.get()).define(string, f);
return this;
}
public RenderPipeline.Builder withSampler(String string) {
if (this.samplers.isEmpty()) {
this.samplers = Optional.of(new ArrayList());
}
((List)this.samplers.get()).add(string);
return this;
}
public RenderPipeline.Builder withUniform(String string, UniformType uniformType) {
if (this.uniforms.isEmpty()) {
this.uniforms = Optional.of(new ArrayList());
}
((List)this.uniforms.get()).add(new RenderPipeline.UniformDescription(string, uniformType));
return this;
}
public RenderPipeline.Builder withDepthTestFunction(DepthTestFunction depthTestFunction) {
this.depthTestFunction = Optional.of(depthTestFunction);
return this;
}
public RenderPipeline.Builder withPolygonMode(PolygonMode polygonMode) {
this.polygonMode = Optional.of(polygonMode);
return this;
}
public RenderPipeline.Builder withCull(boolean bl) {
this.cull = Optional.of(bl);
return this;
}
public RenderPipeline.Builder withBlend(BlendFunction blendFunction) {
this.blendFunction = Optional.of(blendFunction);
return this;
}
public RenderPipeline.Builder withoutBlend() {
this.blendFunction = Optional.empty();
return this;
}
public RenderPipeline.Builder withColorWrite(boolean bl) {
this.writeColor = Optional.of(bl);
this.writeAlpha = Optional.of(bl);
return this;
}
public RenderPipeline.Builder withColorWrite(boolean bl, boolean bl2) {
this.writeColor = Optional.of(bl);
this.writeAlpha = Optional.of(bl2);
return this;
}
public RenderPipeline.Builder withDepthWrite(boolean bl) {
this.writeDepth = Optional.of(bl);
return this;
}
public RenderPipeline.Builder withColorLogic(LogicOp logicOp) {
this.colorLogic = Optional.of(logicOp);
return this;
}
public RenderPipeline.Builder withVertexFormat(VertexFormat vertexFormat, VertexFormat.Mode mode) {
this.vertexFormat = Optional.of(vertexFormat);
this.vertexFormatMode = Optional.of(mode);
return this;
}
public RenderPipeline.Builder withDepthBias(float f, float g) {
this.depthBiasScaleFactor = f;
this.depthBiasConstant = g;
return this;
}
void withSnippet(RenderPipeline.Snippet snippet) {
if (snippet.vertexShader.isPresent()) {
this.vertexShader = snippet.vertexShader;
}
if (snippet.fragmentShader.isPresent()) {
this.fragmentShader = snippet.fragmentShader;
}
if (snippet.shaderDefines.isPresent()) {
if (this.definesBuilder.isEmpty()) {
this.definesBuilder = Optional.of(ShaderDefines.builder());
}
ShaderDefines shaderDefines = (ShaderDefines)snippet.shaderDefines.get();
for (Entry<String, String> entry : shaderDefines.values().entrySet()) {
((ShaderDefines.Builder)this.definesBuilder.get()).define((String)entry.getKey(), (String)entry.getValue());
}
for (String string : shaderDefines.flags()) {
((ShaderDefines.Builder)this.definesBuilder.get()).define(string);
}
}
snippet.samplers.ifPresent(list -> {
if (this.samplers.isPresent()) {
((List)this.samplers.get()).addAll(list);
} else {
this.samplers = Optional.of(new ArrayList(list));
}
});
snippet.uniforms.ifPresent(list -> {
if (this.uniforms.isPresent()) {
((List)this.uniforms.get()).addAll(list);
} else {
this.uniforms = Optional.of(new ArrayList(list));
}
});
if (snippet.depthTestFunction.isPresent()) {
this.depthTestFunction = snippet.depthTestFunction;
}
if (snippet.cull.isPresent()) {
this.cull = snippet.cull;
}
if (snippet.writeColor.isPresent()) {
this.writeColor = snippet.writeColor;
}
if (snippet.writeAlpha.isPresent()) {
this.writeAlpha = snippet.writeAlpha;
}
if (snippet.writeDepth.isPresent()) {
this.writeDepth = snippet.writeDepth;
}
if (snippet.colorLogic.isPresent()) {
this.colorLogic = snippet.colorLogic;
}
if (snippet.blendFunction.isPresent()) {
this.blendFunction = snippet.blendFunction;
}
if (snippet.vertexFormat.isPresent()) {
this.vertexFormat = snippet.vertexFormat;
}
if (snippet.vertexFormatMode.isPresent()) {
this.vertexFormatMode = snippet.vertexFormatMode;
}
}
public RenderPipeline.Snippet buildSnippet() {
return new RenderPipeline.Snippet(
this.vertexShader,
this.fragmentShader,
this.definesBuilder.map(ShaderDefines.Builder::build),
this.samplers.map(Collections::unmodifiableList),
this.uniforms.map(Collections::unmodifiableList),
this.blendFunction,
this.depthTestFunction,
this.polygonMode,
this.cull,
this.writeColor,
this.writeAlpha,
this.writeDepth,
this.colorLogic,
this.vertexFormat,
this.vertexFormatMode
);
}
public RenderPipeline build() {
if (this.location.isEmpty()) {
throw new IllegalStateException("Missing location");
} else if (this.vertexShader.isEmpty()) {
throw new IllegalStateException("Missing vertex shader");
} else if (this.fragmentShader.isEmpty()) {
throw new IllegalStateException("Missing fragment shader");
} else if (this.vertexFormat.isEmpty()) {
throw new IllegalStateException("Missing vertex buffer format");
} else if (this.vertexFormatMode.isEmpty()) {
throw new IllegalStateException("Missing vertex mode");
} else {
return new RenderPipeline(
(ResourceLocation)this.location.get(),
(ResourceLocation)this.vertexShader.get(),
(ResourceLocation)this.fragmentShader.get(),
((ShaderDefines.Builder)this.definesBuilder.orElse(ShaderDefines.builder())).build(),
List.copyOf((Collection)this.samplers.orElse(new ArrayList())),
(List<RenderPipeline.UniformDescription>)this.uniforms.orElse(Collections.emptyList()),
this.blendFunction,
(DepthTestFunction)this.depthTestFunction.orElse(DepthTestFunction.LEQUAL_DEPTH_TEST),
(PolygonMode)this.polygonMode.orElse(PolygonMode.FILL),
(Boolean)this.cull.orElse(true),
(Boolean)this.writeColor.orElse(true),
(Boolean)this.writeAlpha.orElse(true),
(Boolean)this.writeDepth.orElse(true),
(LogicOp)this.colorLogic.orElse(LogicOp.NONE),
(VertexFormat)this.vertexFormat.get(),
(VertexFormat.Mode)this.vertexFormatMode.get(),
this.depthBiasScaleFactor,
this.depthBiasConstant
);
}
}
}
@Environment(EnvType.CLIENT)
@DontObfuscate
public record Snippet(
Optional<ResourceLocation> vertexShader,
Optional<ResourceLocation> fragmentShader,
Optional<ShaderDefines> shaderDefines,
Optional<List<String>> samplers,
Optional<List<RenderPipeline.UniformDescription>> uniforms,
Optional<BlendFunction> blendFunction,
Optional<DepthTestFunction> depthTestFunction,
Optional<PolygonMode> polygonMode,
Optional<Boolean> cull,
Optional<Boolean> writeColor,
Optional<Boolean> writeAlpha,
Optional<Boolean> writeDepth,
Optional<LogicOp> colorLogic,
Optional<VertexFormat> vertexFormat,
Optional<VertexFormat.Mode> vertexFormatMode
) {
}
@Environment(EnvType.CLIENT)
@DontObfuscate
public record UniformDescription(String name, UniformType type) {
}
}