Skip to content

Custom Textures

Iris/Optifine allows binding a texture to an existing sampler (such as a colortex sampler). This allows the shader to access images/data included with the shader pack, textures from the resource pack / game files, atlas textures, and more. The following directive can be put in the shaders.properties file to set up a custom texture:

shaders.properties
texture.<stage>.<bufferName> = <path>

Texture Types

Optifine/Iris support four different texture types, which are specified in the <path> parameter.

Images from Shader Files

Image files can be loaded from the shader pack files by replacing <path> with the file path to the image relative to the shaders folder. For example texture.composite.colortex5 = textures/perlin.png would load perlin.png from the shaders/textures folder. Iris supports only .png image format, whereas Optifine supports .png and .jpg formats.

Textures from Game Files / Resource Packs

Textures can also be loaded from the resource pack by replacing <path> with minecraft: followed by the path in the resource pack (or vanilla files) of the texture. For example, texture.deferred.colortex7 = minecraft:textures/block/dirt.png will load the dirt texture from the resource pack or vanilla assets.

Atlas and Dynamic Textures

Atlas textures (such as the block atlas) can be loaded by passing their file path, starting with minecraft:textures/atlas/. For example, texture.composite.colortex9 = minecraft:textures/atlas/blocks.png loads the block atlas into colortex9. A list of available texture atlases can be found in the Minecraft Wiki under “Procedurally-generated” in the Navigation table.

Additionally, the lightmap dynamic texture can be loaded using either minecraft:dynamic/lightmap_1 or minecraft:dynamic/light_map_1. This texture is equivalent to the lightmap sampler used in gbuffers. For example texture.prepare.colortex2 = minecraft:dynamic/lightmap_1 loads the lightmap into colortex2.

Raw Textures

Raw textures can be loaded from the shader files, similarly to image files. However raw textures are uncompressed binary files, where the bytes represent the values in the texture directly. Raw files can also encode 3D textures, and the texture format can be directly controlled (images are always loaded as RGBA8). To use a raw texture, add the following parameters to the custom texture directive:

shaders.properties
texture.<stage>.<bufferName> = <path> <type> <internalFormat> <dimensions> <pixelFormat> <pixelType>
  • Replaec <type> with one of the following: TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, or TEXTURE_RECTANGLE.
  • Replace <internalFormat> with the texture format.
  • Replace <dimensions> with the fixed size dimensions of the texture (the number of components depends on the type).
  • Replace <pixelFormat> with the pixel format described in the “Pixel Formats” section of the texture format section.
  • Replace <pixelType> with the pixel type described in the “Pixel Types” section of the texture format section.

PBR textures

For any resource pack or atlas texture, the normal or specular versions of the textures (if they exist) can be loaded by appending the _n or _s suffix respectively. For example, texture.deferred.colortex2 = minecraft:textures/atlas/blocks_s.png loads the specular block atlas.

Stage binding

The Optifine spec for custom textures overwrites the binding of an existing sampler with the new texture. This means the texture originally in the sampler is no longer accessible. Iris adds Iris Enhanced Custom Textures which creates a new sampler, thus avoiding this issue.

When using the Optifine spec, replace <stage> with the stage of programs which the texture will be bound in. During that stage, the sampler specified with <bufferName> will sample the custom texture rather than it original texture. The following options are available for <stage>:

namedescription
setupsetup programs, exclusive to Iris
beginbegin programs, exclusive to Iris
shadowcompshadowcomp programs
prepareprepare programs
gbuffersgbuffers and shadow programs
deferreddeferred programs
compositecomposite and final programs

Iris Enhanced Custom Textures

Iris adds support for the customTexture directive, which allows the shader dev to use a different sampler instead of overriding an existing sampler. This allows creation of a sampler of (mostly) any name, which replaces <name> in the directive and is used in the shader code. Otherwise the syntax of the enhanced custom textures are identical to standard custom textures.

shaders.properties
customTexture.<name> = <path>
customTexture.<name> = <path> <type> <internalFormat> <dimensions> <pixelFormat> <pixelType>
shader code
uniform sampler2D <name>;
uniform sampler<dimensions> <name>; // Raw textures may create sampler1D, sampler2D, sampler3D, or sampler2DRect

.mcmeta File

Hardware bilinear filtering and wrapping/clamping behavior can be controlled with a .mcmeta file with the same filename as the texture with .mcmeta appended (for example perlinNoise.png.mcmeta). The mcmeta file should be located in the same folder as the texture itself. The syntax is as follows:

.mcmeta file
{
"texture":
{
"blur": <true|false>,
"clamp": <true|false>
}
}
  • blur controls texture filtering, true is bilinear, false is nearest neighbor
  • clamp controls edge behavior, true clamps at the edges, false wraps at the edges

By default, image files will use nearest neighbor and wrapping, and raw textures will use bilinear filtering and clamping. Shader provided mcmeta files cannot be used for resource pack / atlas textures.