Skip to content

Quick Start Tutorial

grondag edited this page Jun 22, 2020 · 14 revisions

Overview

This tutorial will walk you through writing a shader that makes stone (or some other block you choose) have an animated disco glow! It won't teach you GLSL or much about the details, but you'll get a rough idea of what is involved and where to start. Here's what it will look like when we are done:

End Result

Setting up

For this tutorial, you'll be using a resource pack. There are other ways to associate shaders with blocks, but this way requires no Java development.

You'll need Minecraft instance that includes Fabric Loader, Fabric API and Canvas 1.0 or later. In the folder where Minecraft runs, open the resourcepacks folder and create a new sub folder named shaderpack. (It can be any name, we're just using that name for the tutorial.)

In the shaderpack folder, use a text editor to create a filed named pack.mcmeta with these contents:

{
  "pack": {
    "pack_format": 5,
    "description": "Canvas shader tutorial pack"
  }
}

Within the shaderpack folder create the following subfolders:

assets/minecraft/materials
assets/minecraft/shaders/material
assets/minecraft/materialmaps/block

Start Minecraft and confirm shaderpack is now in the list of available resource packs and then load it. Because it is empty, loading it will not have any effect.

Creating Shaders

For this effect, we need a vertex shader and a fragment shader.

Vertex Shader

The vertex shader collects information from incoming quad vertices and makes it available to the fragment shader, usually via "varying" variables. (Yes, I know, all variables are varying, aren't they? It's just how OpenGL names things. You get used to it.)

Create tutorial.vert with the code below and place it in assets/minecraft/shaders/material:

#include canvas:shaders/api/vertex.glsl
#include canvas:shaders/lib/face.glsl

// sends noise coordinates from the vertex shader
varying vec2 v_noise_uv;

// The name of this method is special - Canvas will call it for each vertex associated with your shader 
void cv_startVertex(inout cv_VertexData data) {
	// 2D noise coordinates are derived from world geometry using a Canvas library function
	v_noise_uv = cv_faceUv(data.vertex.xyz, data.normal);
}

Fragment Shader

The fragment shader modifies individual pixels or sub pixels (the "fragments") before they are drawn to the screen. This is where we will do most of the work for this effect.

Create tutorial.frag with the code below and place it in assets/minecraft/shaders/material:

#include canvas:shaders/api/fragment.glsl
#include canvas:shaders/lib/math.glsl
#include canvas:shaders/api/world.glsl

// holds our noise coordinates from the vertex shader
varying vec2 v_noise_uv;

// The name of this method is special - Canvas will call it for each fragment associated with your shader 
void cv_startFragment(inout cv_FragmentData fragData) {
	// modify appearance where stone texture is lighter in color
	if (cv_luminance(fragData.spriteColor.rgb) > 0.5) {
		// get a time value we can use for animation
		float time = cv_renderSeconds();

		// use an animated noise function to mix a pastel blue/red color
		float color_weight = cv_noise2dt(v_noise_uv * 2.0, time);

		// mix 'em up!
		vec4 highlight = mix(vec4(1.0, 0.7, 1.0, 1.0), vec4(0.7, 1.0, 1.0, 1.0), color_weight);

		// call animated noise function with noise coordinates scaled and shifted
		float blend_weight = cv_noise2dt(v_noise_uv * 4.0 - 16.0, time * 2.0);

		// mix with the stone texture colors
		fragData.spriteColor = mix(fragData.spriteColor, highlight, blend_weight);

		// make these fragments fully lit
		fragData.emissivity = 1.0;
		fragData.ao = false;
		fragData.diffuse = false;
	}
}

Material

Now that we have shaders, we need to let Canvas know about them so they can be applied to models. This is done by creating a RenderMaterial (usually just called "materials") to describe how a quad should be rendered. The Fabric Rendering API includes materials already, but Canvas lets you add shaders to them.

We're going to name our material minecraft:tutorial for simplicity. For your own materials you should use a different name (typically the name of your mod) instead of minecraft so that your materials don't have name conflicts with others.

Create tutorial.json with the text below and place it in assets/minecraft/materials:

{
	"layers": [
		{
			"vertexSource": "minecraft:shaders/material/tutorial.vert",
			"fragmentSource": "minecraft:shaders/material/tutorial.frag"
		}
	]
}

NOTE: The extensions for adding shaders to render materials and the JSON loader for render are actually part of FREX. But, Canvas always includes FREX, so you don't need to worry about that.

MaterialMap

Now that Canvas has a material containing our shaders, we have to let it know what blocks to use it with. There are several ways to do this, but for this tutorial we're going to create a Material Map.

A material map does what it sounds like: maps specific materials to blocks or items or even to specific textures on them. Stone only has one texture so the material map for this tutorial is very simple.

The name and location of the material map file must match the target block or itemsimilar to the way blockstate model files are named and located.

Create stone.json with the text below and place it in assets/minecraft/materialmaps/block:

{
	"defaultMaterial": "minecraft:tutorial"
}

Conclusion

That's it! Start up Minecraft and if everything was done correctly your stone blocks should look like those int the video at the top of the page.

If things aren't working, compare your files with those located here.

For more information on creating shaders with Canvas, return to the home page.

Clone this wiki locally