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 bluish 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.

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;
	}
}
Clone this wiki locally