Posts
Search
Contact
Cookies
About
RSS

Shaders with raylib

Added 17 Sep 2019, 2:32 p.m. edited 18 Jun 2023, 5:53 p.m.

While I've touched on "simple" lighting and the related fog shader, both of these are fairly complex to pick apart, so I've been meaning to do something to show how you can implement your own simple shader to do specific effects.

https://youtu.be/gFjJ8HbY0F0

Keeping things simple all the vert shader does is sends the frag shader the texture coordinates, the fragment shader is a simple mix and discard affair. More about discarding later, the main thing is the shaders are little more than texture mapping, and it gives me a chance to explain how to add additional textures to your own shaders.

// load the shader
Shader shader = LoadShader("data/mask.vs", "data/mask.fs");

// static "water" looking-ish texture
Texture tex = LoadTexture("data/water.png");

I did have a water-ish horrible texture, but I ended up replacing it with a simple multicoloured plasma... the "water" is our diffuse (or "main" colour map) which is passed to the shader automatically (the texture0 sampler).

// using MAP_EMISSION as a spare slot to use for 2nd texture
// dont use MAP_IRRADIANCE, MAP_PREFILTER, or  MAP_CUBEMAP
// as they are bound as cube maps (which don't seem to work at all on my machine!)

Texture maskTx = LoadTexture("data/mask.png");
model.materials[0].maps[MAP_EMISSION].texture = maskTx;
model2.materials[0].maps[MAP_EMISSION].texture = maskTx;
shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(shader, "mask");

There are a number of additional named maps, just use any map other than the diffuse map and you're good to go, but do avoid the three maps that are automatically bound as cube maps! (honest I wasn't scratching my head for 10 minutes there at all!). Use the corresponding shader location for your chosen map, and set it to whatever you have called the additional sampler in the shader.

Alpha on the cheap

Actually this would be more accurately described as chroma keying I suppose, and its an all or nothing affair, either you can see straight through or you can't. Doing alpha blending correctly is frankly a pain, not only do you need to sort by camera distance all your models, also all the triangles in the model need to be sorted each frame by camera distance (oh and you probably need double sided triangles or switch out backface culling too!). This is because you need everything rendered behind the alpha before you can actually blend it. However with discarding you never draw anything and you're not blending so the issues just goes away, while you don't get smooth transitions its great where you want a ragged fringe on something but you don't want loads of extra triangles to represent this detail.

In the included shader all I have done is checked the red level of the "mask" texture and immediately discarded if its below a threshold, you might want to make this threshold an exact value, so you can still have (very nearly) that colour in your texture without it being discarded. Notice that the discard check is to right up front, before even looking up the colour texture, which is good practice as why do anything you don't need to.

Hopefully with paring this shader right down, I have shown you how you can easily integrate your own simple (or even complex!) shaders with raylib, something that not too obvious from first glance.

You can get the source code here

Enjoy!