Skip to content

Render Types

Render types are the cornerstone of Minecraft 26.1’s rendering system, defining complete rendering configurations including shaders, textures, blend modes, and other OpenGL state. This guide covers how to understand and create custom render types.

A Render Type encapsulates:

  • Shader configuration and uniforms
  • Texture bindings and samplers
  • Blend modes and transparency settings
  • Depth testing and culling behavior
  • Output targets and framebuffer operations

The RenderType class represents a complete rendering configuration:

net.minecraft.client.renderer.RenderType
public class RenderType {
private final String name;
private final VertexFormat format;
private final VertexFormat.Mode mode;
private final int expectedBufferSize;
private final boolean affectsCrumbling;
private final boolean sortOnUpload;
private final CompositeState state;
public static RenderType create(String name, VertexFormat format, VertexFormat.Mode mode,
int expectedBufferSize, CompositeState state) {
return new RenderType(name, format, mode, expectedBufferSize, false, false, state);
}
}

The CompositeState combines individual rendering state components:

// Excerpt: net.minecraft.client.renderer.RenderType$CompositeState
public static class CompositeState {
private final Optional<ShaderStateShard> shaderState;
private final Optional<TextureStateShard> textureState;
private final Optional<TransparencyStateShard> transparencyState;
private final Optional<DepthTestStateShard> depthTestState;
private final Optional<CullStateShard> cullState;
private final Optional<WriteMaskStateShard> writeMaskState;
private final Optional<LayeringStateShard> layeringState;
private final Optional<OutputStateShard> outputState;
private final Optional<Boolean> sortOnUpload;
private final Optional<Shader> shader;
public static Builder builder() {
return new Builder();
}
}

Minecraft provides many built-in render types for common use cases:

// Example: Common built-in render types
public class RenderTypes {
// Solid opaque rendering
public static final RenderType SOLID = RenderType.create(
"solid",
DefaultVertexFormat.BLOCK,
VertexFormat.Mode.QUADS,
2097152,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.NEW_ENTITY_SHADER)
.setTextureState(RenderStateShards.BLOCK_SHEET_MIPPED_TEXTURE)
.setTransparencyState(RenderStateShards.NO_TRANSPARENCY)
.setOutputState(RenderStateShards.ITEM_ENTITY_TARGET)
.createCompositeState(false)
);
// Transparent rendering
public static final RenderType TRANSLUCENT = RenderType.create(
"translucent",
DefaultVertexFormat.BLOCK,
VertexFormat.Mode.QUADS,
2097152,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.NEW_ENTITY_SHADER)
.setTextureState(RenderStateShards.BLOCK_SHEET_MIPPED_TEXTURE)
.setTransparencyState(RenderStateShards.TRANSLUCENT_TRANSPARENCY)
.setOutputState(RenderStateShards.TRANSLUCENT_TARGET)
.createCompositeState(true) // sortOnUpload
);
// Cutout rendering (alpha test)
public static final RenderType CUTOUT = RenderType.create(
"cutout",
DefaultVertexFormat.BLOCK,
VertexFormat.Mode.QUADS,
2097152,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.NEW_ENTITY_SHADER)
.setTextureState(RenderStateShards.BLOCK_SHEET_MIPPED_TEXTURE)
.setTransparencyState(RenderStateShards.CUTOUT_TRANSPARENCY)
.setOutputState(RenderStateShards.ITEM_ENTITY_TARGET)
.createCompositeState(false)
);
}
// Example: Entity render types
public static final RenderType ENTITY_SOLID = RenderType.create(
"entity_solid",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.QUADS,
256,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.RENDERTYPE_ENTITY_SOLID_SHADER)
.setTextureState(RenderStateShards.ENTITY_SHEET_TEXTURE)
.setTransparencyState(RenderStateShards.NO_TRANSPARENCY)
.setLightmapState(RenderStateShards.LIGHTMAP)
.setOverlayState(RenderStateShards.OVERLAY)
.createCompositeState(false)
);
public static final RenderType ENTITY_TRANSLUCENT = RenderType.create(
"entity_translucent",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.QUADS,
256,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.RENDERTYPE_ENTITY_TRANSLUCENT_SHADER)
.setTextureState(RenderStateShards.ENTITY_SHEET_TEXTURE)
.setTransparencyState(RenderStateShards.TRANSLUCENT_TRANSPARENCY)
.setLightmapState(RenderStateShards.LIGHTMAP)
.setOverlayState(RenderStateShards.OVERLAY)
.createCompositeState(true) // sortOnUpload
);
// Example: Creating a custom render type
public class CustomRenderTypes {
public static final RenderType CUSTOM_GLOW;
static {
CUSTOM_GLOW = RenderType.create(
"custom_glow",
DefaultVertexFormat.POSITION_COLOR_TEX,
VertexFormat.Mode.QUADS,
256,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.NEW_ENTITY_SHADER)
.setTextureState(RenderStateShards.BLOCK_SHEET_MIPPED_TEXTURE)
.setTransparencyState(RenderStateShards.ADDITIVE_TRANSPARENCY)
.setCullState(RenderStateShards.NO_CULL)
.setLightmapState(RenderStateShards.LIGHTMAP)
.setWriteMaskState(RenderStateShards.COLOR_WRITE)
.createCompositeState(true)
);
}
}

Create custom shader states for specialized rendering:

// Example: Custom shader state
public class CustomShaderStates {
public static final RenderStateShard.ShaderStateShard CUSTOM_WAVE_SHADER =
new RenderStateShard.ShaderStateShard() {
@Override
public ShaderStateShard.Supplier createSupplier() {
return () -> Minecraft.getInstance().getShaderManager()
.getShader("my_mod:wave_shader");
}
};
public static final RenderStateShard.ShaderStateShard CUSTOM_RAINBOW_SHADER =
new RenderStateShard.ShaderStateShard() {
@Override
public ShaderStateShard.Supplier createSupplier() {
return () -> Minecraft.getInstance().getShaderManager()
.getShader("my_mod:rainbow_shader");
}
};
}
// Example: Custom transparency states
public class CustomTransparencyStates {
public static final RenderStateShard.TransparencyStateShard SCREEN_TRANSPARENCY =
RenderStateShard.TransparencyStateShard.of(
RenderStateShard.SourceFactor.ONE,
RenderStateShard.DestFactor.ONE_MINUS_SRC_COLOR
);
public static final RenderStateShard.TransparencyStateShard MULTIPLY_TRANSPARENCY =
RenderStateShard.TransparencyStateShard.of(
RenderStateShard.SourceFactor.DST_COLOR,
RenderStateShard.DestFactor.ZERO
);
}
// Example: Advanced custom render type with multiple configurations
public class AdvancedRenderTypes {
public static final RenderType ENERGY_FIELD;
public static final RenderType HOLOGRAM;
public static final RenderType FORCE_FIELD;
static {
// Energy field with additive blending
ENERGY_FIELD = RenderType.create(
"energy_field",
DefaultVertexFormat.POSITION_COLOR_TEX_LIGHTMAP,
VertexFormat.Mode.QUADS,
512,
RenderType.CompositeState.builder()
.setShaderState(CustomShaderStates.CUSTOM_WAVE_SHADER)
.setTextureState(RenderStateShards.BLOCK_SHEET_MIPPED_TEXTURE)
.setTransparencyState(CustomTransparencyStates.SCREEN_TRANSPARENCY)
.setCullState(RenderStateShards.NO_CULL)
.setDepthTestState(RenderStateShard.DepthTestStateShard.LEQUAL)
.setLightmapState(RenderStateShards.LIGHTMAP)
.setWriteMaskState(RenderStateShard.COLOR_WRITE)
.setLayeringState(RenderStateShard.VIEW_OFFSET_Z_LAYERING)
.createCompositeState(true)
);
// Hologram with special output target
HOLOGRAM = RenderType.create(
"hologram",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.QUADS,
256,
RenderType.CompositeState.builder()
.setShaderState(CustomShaderStates.CUSTOM_RAINBOW_SHADER)
.setTextureState(RenderStateShards.ENTITY_SHEET_TEXTURE)
.setTransparencyState(RenderStateShards.TRANSLUCENT_TRANSPARENCY)
.setCullState(RenderStateShards.NO_CULL)
.setOutputState(RenderStateShards.OUTLINE_TARGET)
.setLightmapState(RenderStateShards.LIGHTMAP)
.setOverlayState(RenderStateShards.OVERLAY)
.createCompositeState(true)
);
// Force field with special layering
FORCE_FIELD = RenderType.create(
"force_field",
DefaultVertexFormat.POSITION_COLOR_TEX,
VertexFormat.Mode.QUADS,
1024,
RenderType.CompositeState.builder()
.setShaderState(RenderStateShards.RENDERTYPE_BEACON_BEAM_SHADER)
.setTextureState(RenderStateShards.BEACON_TRANSPARENCY_TEXTURE)
.setTransparencyState(RenderStateShards.ADDITIVE_TRANSPARENCY)
.setCullState(RenderStateShards.NO_CULL)
.setDepthTestState(RenderStateShard.DepthTestStateShard.EQUAL)
.setWriteMaskState(RenderStateShards.COLOR_DEPTH_WRITE)
.setLayeringState(RenderStateShard.POLYGON_OFFSET_LAYERING)
.createCompositeState(true)
);
}
}

Control how colors blend with existing pixels:

// Example: Different transparency modes
public class TransparencyExamples {
// Standard alpha blending
public static final RenderType ALPHA_BLEND = RenderType.create(
"alpha_blend",
format, mode, size,
RenderType.CompositeState.builder()
.setTransparencyState(RenderStateShards.TRANSLUCENT_TRANSPARENCY)
.createCompositeState(false)
);
// Additive blending (good for glows)
public static final RenderType ADDITIVE = RenderType.create(
"additive",
format, mode, size,
RenderType.CompositeState.builder()
.setTransparencyState(RenderStateShards.ADDITIVE_TRANSPARENCY)
.createCompositeState(false)
);
// Alpha test (hard edges)
public static final RenderType CUTOUT = RenderType.create(
"cutout",
format, mode, size,
RenderType.CompositeState.builder()
.setTransparencyState(RenderStateShards.CUTOUT_TRANSPARENCY)
.createCompositeState(false)
);
}

Control how depth testing is performed:

// Example: Depth test configurations
public class DepthTestExamples {
// Standard depth testing
public static final RenderType STANDARD_DEPTH = RenderType.create(
"standard_depth",
format, mode, size,
RenderType.CompositeState.builder()
.setDepthTestState(RenderStateShard.DepthTestStateShard.LEQUAL)
.createCompositeState(false)
);
// No depth testing (always draws)
public static final RenderType NO_DEPTH_TEST = RenderType.create(
"no_depth_test",
format, mode, size,
RenderType.CompositeState.builder()
.setDepthTestState(RenderStateShard.DepthTestStateShard.ALWAYS)
.createCompositeState(false)
);
// Equal depth test (only at exact depth)
public static final RenderType EQUAL_DEPTH = RenderType.create(
"equal_depth",
format, mode, size,
RenderType.CompositeState.builder()
.setDepthTestState(RenderStateShard.DepthTestStateShard.EQUAL)
.createCompositeState(false)
);
}

Control which faces are rendered:

// Example: Culling configurations
public class CullingExamples {
// Standard backface culling
public static final RenderType BACKFACE_CULLING = RenderType.create(
"backface_culling",
format, mode, size,
RenderType.CompositeState.builder()
.setCullState(RenderStateShards.CULL)
.createCompositeState(false)
);
// No culling (all faces rendered)
public static final RenderType NO_CULLING = RenderType.create(
"no_culling",
format, mode, size,
RenderType.CompositeState.builder()
.setCullState(RenderStateShards.NO_CULL)
.createCompositeState(false)
);
}
// Example: Using custom render type in entity renderer
public class EnergyEntityRenderer extends EntityRenderer<EnergyEntity> {
private static final RenderType ENERGY_RENDER_TYPE = CustomRenderTypes.ENERGY_FIELD;
@Override
public void render(EnergyEntity entity, float partialTicks, PoseStack poseStack,
MultiBufferSource bufferSource, int packedLight) {
VertexConsumer vertexConsumer = bufferSource.getBuffer(ENERGY_RENDER_TYPE);
poseStack.push();
poseStack.translate(entity.getX(), entity.getY(), entity.getZ());
renderEnergyField(poseStack, vertexConsumer, packedLight);
poseStack.pop();
}
private void renderEnergyField(PoseStack poseStack, VertexConsumer vertexConsumer,
int packedLight) {
Matrix4f poseMatrix = poseStack.last().pose();
// Add vertices for energy field effect
for (int i = 0; i < 8; i++) {
float angle = (float) (i * Math.PI / 4.0);
float x = (float) Math.cos(angle);
float z = (float) Math.sin(angle);
vertexConsumer.vertex(poseMatrix, x, -0.5f, z)
.color(1.0f, 0.5f, 1.0f, 0.7f)
.uv(0.0f, 0.0f)
.overlayCoords(OverlayTexture.NO_OVERLAY)
.uv2(packedLight)
.endVertex();
}
}
}
// Example: Using custom render type in world rendering
public class CustomWorldRenderer {
public void renderCustomBlocks(LevelRenderEvent event) {
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS) {
return;
}
PoseStack poseStack = event.getPoseStack();
MultiBufferSource bufferSource = event.getVertexConsumers();
// Get all custom blocks in view
List<CustomBlock> blocks = getCustomBlocksInView(event.getCamera());
// Group by render type for batching
Map<RenderType, List<CustomBlock>> grouped = blocks.stream()
.collect(Collectors.groupingBy(CustomBlock::getRenderType));
// Render each group
for (Map.Entry<RenderType, List<CustomBlock>> entry : grouped.entrySet()) {
RenderType renderType = entry.getKey();
List<CustomBlock> blockGroup = entry.getValue();
VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType);
for (CustomBlock block : blockGroup) {
renderCustomBlock(block, poseStack, vertexConsumer);
}
}
}
}

Sort objects by render type to minimize state changes:

// Example: Efficient render type sorting
public class OptimizedRenderer {
public void renderObjectsEfficiently(List<RenderableObject> objects,
PoseStack poseStack,
MultiBufferSource bufferSource) {
// Group objects by render type
Map<RenderType, List<RenderableObject>> grouped = objects.stream()
.collect(Collectors.groupingBy(RenderableObject::getRenderType));
// Render each group
for (Map.Entry<RenderType, List<RenderableObject>> entry : grouped.entrySet()) {
RenderType renderType = entry.getKey();
List<RenderableObject> group = entry.getValue();
VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType);
// Render all objects with this render type
for (RenderableObject obj : group) {
obj.render(poseStack, vertexConsumer);
}
}
}
}

Choose appropriate buffer sizes for your render types:

// Example: Buffer size optimization
public class BufferSizeExamples {
// Small buffers for simple objects
public static final RenderType SMALL_PARTICLE = RenderType.create(
"small_particle",
DefaultVertexFormat.POSITION_COLOR,
VertexFormat.Mode.QUADS,
64, // Small buffer for particle effects
smallParticleState
);
// Large buffers for complex geometry
public static final RenderType COMPLEX_MODEL = RenderType.create(
"complex_model",
DefaultVertexFormat.NEW_ENTITY,
VertexFormat.Mode.TRIANGLES,
8192, // Large buffer for detailed models
complexModelState
);
// Dynamic sizing based on expected content
public static RenderType createDynamicRenderType(String name, VertexFormat format,
int expectedVertices) {
return RenderType.create(
name,
format,
VertexFormat.Mode.QUADS,
expectedVertices * format.getVertexSize(),
defaultState
);
}
}

Problem: Custom render type not registered Solution: Ensure render types are created in static initialization before use

Problem: Unexpected blending behavior Solution: Check transparency state configuration and blend function parameters

Problem: Objects rendering in wrong order Solution: Verify depth test state and sortOnUpload settings

  1. Reuse render types instead of creating new ones
  2. Group by render type to minimize state changes
  3. Choose appropriate buffer sizes for expected content
  4. Use sorting for transparent objects
  5. Profile performance to identify bottlenecks