Shader Pipeline
Shader Pipeline
Section titled “Shader Pipeline”The shader pipeline system in Minecraft 26.1 manages compilation, loading, and execution of shader programs. This guide covers how to work with shaders and integrate them into your custom rendering code.
Overview
Section titled “Overview”The shader pipeline consists of:
- Shader compilation and caching managed by
ShaderManager - Preprocessing system that handles custom directives
- Pipeline configuration for complete rendering setups
- Uniform management for shader parameters
Core Components
Section titled “Core Components”ShaderManager
Section titled “ShaderManager”The ShaderManager handles the complete shader lifecycle:
public class ShaderManager { private final Map<String, ShaderInstance> shaders = new HashMap<>(); private final GlslPreprocessor preprocessor;
public ShaderInstance getShader(String name) { return shaders.computeIfAbsent(name, this::loadShader); }
private ShaderInstance loadShader(String name) { // Load and compile shader files // Apply preprocessing // Cache the result }}GLSL Preprocessor
Section titled “GLSL Preprocessor”The preprocessor handles custom Minecraft-specific directives:
public class GlslPreprocessor { public String process(String source, Map<String, String> defines) { // Process #moj_import directives // Handle #define substitutions // Apply version management return processedSource; }}Shader Structure
Section titled “Shader Structure”Vertex Shaders
Section titled “Vertex Shaders”Vertex shaders transform vertex positions and pass data to fragment shaders:
// Example: Basic vertex shader#version 330 core
#moj_import <minecraft:common>
in vec3 Position;in vec4 Color;in vec2 UV0;
uniform mat4 ModelViewMat;uniform mat4 ProjMat;uniform vec3 Light0_Direction;
out vec4 vertexColor;out vec2 texCoord0;
void main() { gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); vertexColor = Color; texCoord0 = UV0;}Fragment Shaders
Section titled “Fragment Shaders”Fragment shaders determine the final color of pixels:
// Example: Basic fragment shader#version 330 core
#moj_import <minecraft:common>
in vec4 vertexColor;in vec2 texCoord0;
uniform sampler2D Sampler0;
out vec4 fragColor;
void main() { vec4 textureColor = texture(Sampler0, texCoord0); fragColor = vertexColor * textureColor;}Working with Shaders
Section titled “Working with Shaders”Loading and Using Shaders
Section titled “Loading and Using Shaders”// Example: Loading and using a custom shaderpublic class CustomShaderRenderer { private ShaderInstance customShader;
public void initialize() { // Load shader from resources this.customShader = Minecraft.getInstance().getShaderManager() .getShader("custom_shader"); }
public void render(PoseStack poseStack, MultiBufferSource bufferSource) { // Set shader uniforms customShader.safeGetUniform("Time").set((float)Blaze3D.getTime() / 1000.0f); customShader.safeGetUniform("Color").set(1.0f, 1.0f, 1.0f, 1.0f);
// Bind shader customShader.apply();
// Render geometry renderGeometry(poseStack, bufferSource.getBuffer(customRenderType));
// Clear shader customShader.clear(); }}Shader Configuration Files
Section titled “Shader Configuration Files”Shaders are configured through JSON files:
{ "blend": { "func": "add", "src": "src_alpha", "dst": "one_minus_src_alpha" }, "vertex": "my_mod:shaders/custom.vert", "fragment": "my_mod:shaders/custom.frag", "attributes": [ { "name": "Position", "type": "float", "count": 3 }, { "name": "Color", "type": "float", "count": 4 }, { "name": "UV0", "type": "float", "count": 2 } ], "samplers": [ { "name": "Sampler0" } ], "uniforms": [ { "name": "Time", "type": "float", "count": 1 }, { "name": "Color", "type": "float", "count": 4 } ]}Pipeline Configuration
Section titled “Pipeline Configuration”Render Types with Custom Shaders
Section titled “Render Types with Custom Shaders”Integrate custom shaders with render types:
// Example: Render type with custom shaderpublic class CustomRenderTypes { public static final RenderType CUSTOM_SHADER_TYPE;
static { CUSTOM_SHADER_TYPE = RenderType.create( "custom_shader_type", DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, RenderType.CompositeState.builder() .setShaderState(RenderStateShaders.RENDERTYPE_ENTITY_TRANSLUCENT_SHADER) .setTextureState(RenderStateShaders.RENDERTYPE_ENTITY_TRANSLUCENT_TEXTURE) .setTransparencyState(RenderStateShards.TRANSLUCENT_TRANSPARENCY) .setCullState(RenderStateShards.NO_CULL) .setLightmapState(RenderStateShards.LIGHTMAP) .setOverlayState(RenderStateShards.OVERLAY) .createCompositeState(false) ); }}Pipeline Snippets
Section titled “Pipeline Snippets”Use pipeline snippets for reusable configurations:
// Example: Custom pipeline snippetpublic class CustomPipelineSnippets { public static final RenderStateShard.ShaderStateShard CUSTOM_SHADER = new RenderStateShard.ShaderStateShard() { @Override public ShaderStateShard createSupplier() { return () -> Minecraft.getInstance().getShaderManager() .getShader("my_mod:custom_shader"); } };
public static RenderType.CompositeState.TransparencyStateShard TRANSLUCENT_BLACK = RenderStateShards.TransparencyStateShard.of( RenderStateShards.SourceFactor.ONE, RenderStateShards.DestFactor.ONE_MINUS_SRC_COLOR );}Advanced Shader Techniques
Section titled “Advanced Shader Techniques”Uniform Animation
Section titled “Uniform Animation”Animate shader uniforms over time:
// Example: Animated uniformspublic class AnimatedShaderRenderer { private float animationTime = 0.0f;
public void render(PoseStack poseStack, MultiBufferSource bufferSource, float partialTicks) { animationTime += partialTicks;
// Set animated uniforms customShader.safeGetUniform("Time").set(animationTime); customShader.safeGetUniform("WaveIntensity").set((float)Math.sin(animationTime * 2.0f));
renderGeometry(poseStack, bufferSource); }}Multi-Pass Rendering
Section titled “Multi-Pass Rendering”Implement multi-pass shader effects:
// Example: Multi-pass renderingpublic class MultiPassRenderer { private final RenderTarget framebuffer; private final ShaderInstance firstPass; private final ShaderInstance secondPass;
public void render() { // First pass: render to framebuffer framebuffer.bindWrite(true); RenderSystem.clear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT, true);
firstPass.apply(); renderFirstPassGeometry(); firstPass.clear();
// Second pass: render to screen Minecraft.getInstance().getMainRenderTarget().bindWrite(true);
secondPass.safeGetUniform("InputTexture").set(framebuffer.getColorTextureId()); secondPass.apply(); renderFullscreenQuad(); secondPass.clear(); }}Shader Optimization
Section titled “Shader Optimization”Uniform Caching
Section titled “Uniform Caching”Cache uniform references to avoid repeated lookups:
// Example: Uniform cachingpublic class OptimizedShaderRenderer { private final Uniform timeUniform; private final Uniform colorUniform;
public OptimizedShaderRenderer(ShaderInstance shader) { this.timeUniform = shader.safeGetUniform("Time"); this.colorUniform = shader.safeGetUniform("Color"); }
public void render(float time, Vec3 color) { timeUniform.set(time); colorUniform.set(color.x, color.y, color.z, 1.0f); renderGeometry(); }}Conditional Shader Features
Section titled “Conditional Shader Features”Use preprocessor defines for feature toggles:
// Example: Feature toggles#version 330 core
#moj_import <minecraft:common>
#ifdef ENABLE_LIGHTINGuniform vec3 Light0_Direction;#endif
in vec3 Position;in vec4 Color;
out vec4 vertexColor;
void main() { gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
vertexColor = Color;
#ifdef ENABLE_LIGHTING float lightFactor = max(0.0, dot(normalize(Normal), Light0_Direction)); vertexColor *= lightFactor;#endif}Common Issues and Solutions
Section titled “Common Issues and Solutions”Shader Compilation Errors
Section titled “Shader Compilation Errors”Problem: Shader fails to compile Solution: Check shader syntax, variable names, and OpenGL version compatibility
Uniform Not Found
Section titled “Uniform Not Found”Problem: Uniform not found errors
Solution: Ensure uniform names match exactly between shader code and configuration
Texture Binding Issues
Section titled “Texture Binding Issues”Problem: Textures appear black or missing Solution: Verify texture units are bound correctly and samplers match shader expectations
Best Practices
Section titled “Best Practices”- Use the preprocessor for feature toggles and code reuse
- Cache uniform references to improve performance
- Group similar effects into unified shaders
- Profile shader performance to identify bottlenecks
- Use proper resource cleanup for framebuffers and render targets
Next Steps
Section titled “Next Steps”- Custom Render Types - Advanced render type configuration
- Performance Optimization - Shader performance techniques
- Advanced Shader Examples - Complete shader implementations