Skip to content

Creating your own Lumi PBR Material Pack

spiralhalo edited this page Jul 30, 2021 · 10 revisions

Note: very outdated. Most namespace have changed (lumi -> lumiext) and a few materials are missing. The best use for this guide is to help interpret Lumi PBR Ext code. Don't use any code sample verbatim. (2021/7/30)

Making your own Material Map

Unless you need to include Lumi PBR Ext materials directly in your resource pack (see the bottom of this section for details), creating material maps is much easier than creating materials. Look at the examples to get started.

Generally there are three types of material map:

  • Simple material map with only defaultMaterial. Example.
  • Complex material map with variants defined. Example.
  • Super complicated advanced godawful entity material maps. I don't recommend doing this to yourself. Example for science.

Material map only need to link to existing materials.

There are several builtin materials within Lumi PBR Ext since v0.3:

Built-in block materials

  • lumi:bumpy_side: give bumps only to side of blocks, used for grassblock-like including path, mycelium, nylium, etc.
  • lumi:iron_wood: give bump and metallic property to low saturation part of things. Used by spruce and oak doors among other things.
  • lumi:stone_bumpy: general bumpy non-metal material, the [variant]s are:
    • lumi:stone_bumpy highest roughness, used for stone, etc.
    • lumi:stone_bumpy_smooth medium roughness, used for blackstone, etc.
    • lumi:stone_bumpy_polished lowest roughness, used for polished diorite, etc.
  • lumi:metal_bumpy: general bumpy metal material, used for iron block, iron bar, etc.
  • lumi:metal_frame: metal material that is only bumpy on the edges, used for gold block.
  • lumi:gem_bumpy, lumi:gem_frame: similar to metal materials but for gems, such as diamond and emerald block. The gem_frame variant also give coarseness feel on the middle.
  • lumi:ice, lumi:ice_solid: for translucent and solid ice respectively.
  • lumi:ore_metal, lumi:ore_gem: for ores, has the same roughness as lumi:stone_bumpy. This material detects ore part of an ore block by using saturation and might not work for every resource pack. If you're making your own resource pack you should create your own material, see below.
  • lumi:nether_ore_metal, lumi:nether_ore_gem: similar to above but for nether ores that are surrounded by the netherrack texture. *Lumi PBR Compat has ore material for the End as well if you need that.
  • lumi:wrought_iron: Material for dark-colored iron stuff such as cauldron and hopper. This material tints the texture to make them lighter and more visible, so you will need to create an empty materialmap for the respective blockItems otherwise they will look bright in the inventory (see examples).

Built-in entity materials

  • lumi:iron_wood_transform: same as iron_wood but for entities. Used for chest.
  • lumi:metal_bumpy_transform: same as metal_bumpy but for entities. Should be used for minecart but for some reason isn't.
  • lumi:iron_golem_transform: similar to above, but with higher resolution bump. For iron golem.

Making your own ore material

The file structure for one material is as follows:

  • [packname]/materials/[materialname].json for material definition. The material id would be [packname]:[materialname]
  • [packname]/shaders/material/[vert_shader_name].vert for vertex shader. The shader id would be [packname]:shader/material/[vert_shader_name].vert
  • [packname]/shaders/material/[frag_shader_name].frag for fragment shader. The shader id would be [packname]:shader/material/[frag_shader_name].frag

This applies to any material, but for ores specifically:

  • The material definitions are under lumi/materials/ore_metal.json and lumi/materials/ore_gem.json for metal and gem ores respectively.
  • The vertex shader is under lumi/shader/material/default.vert. This vertex shader is used for every block material. When making your own material you may link to this (i.e. "vertexSource": "lumi:shader/material/default.vert" in your material definition) or copy it into your own resource pack. See below for details.
  • The fragment shader is under lumi/shader/material/ore_metal.frag and lumi/shader/material/ore_gem.frag for metal and gem ores respectively.

Copy these files into your own resource pack (refrain for making lumi folder inside your own resourcepack and use your own pack name structure) then adjust the following line:

if (s > 0.2 || min_ > 0.6) {

to match your own textures. The s variable stands for saturation (i.e. how "grayish" a texture pixel--texel--is. This works for overworld ores because the surrounding stone is more grayish than the ore). The min_ variable is useful for estimating luminance, meaning very bright texels are treated as ore texels regardless of saturation. The || symbol simply means or meaning fulfill this or the other condition and can be used to string multiple checks together.

Pro-tip: press F3+A in minecraft to reload your material shader while testing it. Your sanity will thank the mojang devs for this feature.

Including Lumi PBR Ext materials in your resource pack

If you depend on Lumi PBR Ext materials you will need to ask your resourcepack users to install Lumi PBR Ext alongside your resourcepack. No credit required.

You may also include Lumi PBR Ext materials directly. Lumi PBR Ext materials are available under CC-BY-4.0 and requires some lib files which are available under LGPL-3.0. These are unrestrictive license and I personally only ask you to credit and link back to Lumi PBR Ext in your README file and distribution platform, such as Curseforge listing.

Making your very own Material

Before we begin

Disambiguation

"Include" refers to physically including files inside a resource pack.

#include is a glsl directive for logically including a glsl file content inside another glsl file, an action also known as "linking".

Confusing, I know..

Pack Id

Please put your material files inside your own pack id. The "lumi" pack id is reserved for Lumi Lights shader and material usage. Even if you decided to include Lumi libraries (lumi:shaders/lib/*) inside your own resource pack, you should put them in a separate path and link accordingly to prevent overlap with future version of Lumi libraries.

An exception goes to lumi:shaders/lib/bump_context.glsl which needs to be in that specific position in order to be recognized by Lumi Lights. See Lumi Bump Context API section below for more information.

Creating Lumi PBR Material is the same as creating material for Canvas, with a few additions:

Directives

#ifdef LUMI_PBRX (Lumi Lights v0.7+) surround pbr variables with this. #ifdef LUMI_PBR (Lumi Lights v0.1-v0.6) surround pbr variables with this. (deprecated) #ifdef LUMI_BUMP surround bump library functions and bump generation codes with this.

Vertex Shader

Required only if you want bump generation

Example code:

#include frex:shaders/api/vertex.glsl

void frx_startVertex(inout frx_VertexData data) {
#ifdef LUMI_BUMP
    bump_resolution = 1.0;
#endif
}

void frx_endVertex(inout frx_VertexData data) {
#ifdef LUMI_BUMP
    frx_var0.xy = uvN;
    frx_var0.zw = uvT;
    frx_var1.xy = uvB;
#endif
}

Explanation

  • #ifdef LUMI_BUMP required so your material don't crash the renderer when Lumi Lights is not present.
  • bump_resolution resolution of the bump. Lower means higher resolution. 1.0 for 16x, 0.5 for 32x, etc. Advanced: This number is relative to the actual texture resolution. Some textures such as entity texture might require lower number by default regardless of how they appear in game due to larger texture atlas.
  • frx_var?.?? = uv? these lines are mandatory and used by the bump generation in the fragment shader. Advanced: You can also create your own varyings. Grondag recommends shader authors to exhaust all built-in varyings before creating their own.

Fragment Shader

Required for both bump generation and PBR material params

Example code

#include frex:shaders/api/fragment.glsl
#include frex:shaders/api/world.glsl
#include lumi:shaders/lib/bump.glsl

void frx_startFragment(inout frx_FragmentData data) 
{
#ifdef LUMI_PBRX
  pbr_metallic = 1.0;
  pbr_roughness = 0.5;
#endif
#ifdef LUMI_BUMP
  vec2 uvN = frx_var0.xy;
  vec2 uvT = frx_var0.zw;
  vec2 uvB = frx_var1.xy;
  data.vertexNormal = frx_normalModelMatrix() * bump_normal(
    frxs_spriteAltas, data.vertexNormal * frx_normalModelMatrix(),
    uvN, uvT, uvB);
#endif
}

Explanation

  • #ifdef LUMI_PBRX required so your material don't crash the renderer when Lumi Lights is not present.
  • #ifdef LUMI_BUMP required so your material don't crash the renderer when Lumi Lights is not present.
  • pbr_metallic set 0.0 for non-metal and 1.0 for metals.
  • pbr_roughness material roughness. Should set 0.05 for smoothest material as 0.0 causes weird behavior.
  • bump_normal(...) built-in bump map generation, see "bump libraries" below for details.

Lumi Bump Libraries

Lumi Lights Bump Context API

A shader file located in lumi:shaders/lib/bump_context.glsl. DO NOT LINK THIS FILE INSIDE YOUR FRAGMENT SHADER.

Lumi PBR Ext already contained this file, but you need to include it if you are making an independent resource pack. The content of this file is as follows:

#define LUMI_BUMP

That's it. By defining LUMI_BUMP Lumi Lights will know that a resource pack is requesting bump generation. When Lumi Lights isn't present in the resources stack this file will not be loaded and your pack will be able to work without crashing the renderer provided that you wrap any

Lumi Lights Bump Generation

One bump generation function is available via #include lumi:shaders/lib/bump.glsl (included within Lumi Lights shader itself):

vec3 bump_normal(sampler2D tex, vec3 normal, vec2 uvn, vec2 uvt, vec2 uvb)

This function is only available in the fragment shader as of Lumi Lights v0.6 and PBR Ext v0.4

This function generates bump map based on luminance of texel (higher luminance means higher "height" of that texel). Inputs:

  • tex: the texture atlas which can be grabbed as the variable frx_spriteAltas via #include frex:shaders/api/sampler.glsl
  • normal: the microfacet normal, practically just fragData.vertexNormal
  • uvn, uvt, uvb: the texcoords within the texture atlas, supplied by Lumi Lights as uvN, uvT, and uvB in the vertex shader. To transport them into the fragment shader you need to put them inside varyings in the endVertex() function of your material vertex shader (see example in "Vertex Shader" section).

Example usage of this function can be seen in "Fragment Shader" section above.

Lumi PBR Ext Bump Generation

Lumi PBR Ext has several custom bump map generations available at the lib folder. You can link (#include) to these files if your resource pack depends on Lumi PBR Ext, or copy them into your resource pack (available under LGPL-3.0 license).

Lumi PBR Ext libraries make use of Lumi Lights internal functions which may depend on specific version(s) of Lumi Lights. This will be announced in each release of Lumi PBR Ext.