-
Notifications
You must be signed in to change notification settings - Fork 0
The Cool Stuff
Now that you (hopefully) understand what is happening, we can finally get on to the most exciting part. Unfortunately, this requires a bit of math, but don't worry! It's not too hard.
After undoing your changes, your file should look a bit like this,
#version 150
in vec3 Position;
in vec4 Color;
in vec2 UV0;
in ivec2 UV2;
uniform sampler2D Sampler2;
uniform mat4 ModelViewMat;
uniform mat4 ProjMat;
uniform float GameTime;
out float vertexDistance;
out vec4 vertexColor;
out vec2 texCoord0;
void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0);
texCoord0 = UV0;
}
I also removed some unused variables as they were, well, not going to be used.
You might notice a new variable, GameTime
, this is explained wonderfully here, but this is exactly what it sounds like - the time of the game.
In order to add this to to the shader file, the json file needs editing.
Under uniforms
, the GameTime line needs to be added, this allows the variable to be seen by our shader.
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] },
{ "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] },
{ "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] },
{ "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] },
{ "name": "GameTime", "type": "float", "count": 1, "values": [0]}
]
Done!
You may have realised that every change you did also applied to all of the other text rendered on screen. We definitely don't want this. The most effective way that I've found to prevent this is by checking the colour of the text.
if (Color.xyz == vec3(255.0, 255.0, 254.0) / 255.0) {
}
RGB 255, 255, 254 is equal to hex colour #FFFFFE. This is incredibly useful as when sending a message to a player, you can colour it in #FFFFFE. This shouldn't cause any issues as white text is #FFFFFF, and I doubt that you'll ever be using #FFFFFE anywhere else.
This example will turn all #FFFFFE text to red. We need the else statement to make all other text stay the same colour.
void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
if (Color.xyz == vec3(255.0, 255.0, 254.0) / 255.0) {
vertexColor = vec4(255, 0, 0, 1) * texelFetch(Sampler2, UV2 / 16, 0);
} else {
vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0);
}
texCoord0 = UV0;
}
As the GameTime variable is now available to us, we can do things like this!
This is done by using sine to constrain the GameTime to between -1 and 1, multiplying it by 5000 for the speed. This is in the first parameter of the vector (you can use normalised colours here), so it transitions between black (0) and red (1). It stays on black for longer, as it decreases to -1 before going back to positive numbers.
void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
if (Color.xyz == vec3(255.0, 255.0, 254.0) / 255.0) {
vertexColor = vec4(sin(GameTime * 5000), 0, 0, 1) * texelFetch(Sampler2, UV2 / 16, 0);
} else {
vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0);
}
texCoord0 = UV0;
}
Next, we can manipulate the vertices too. You can create some cool effects while manipulating their positions.
void main() {
gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0);
if (Color.xyz == vec3(255.0, 255.0, 254.0) / 255.0) {
vertexColor = vec4(sin(GameTime * 5000), 0, 0, 1) * texelFetch(Sampler2, UV2 / 16, 0);
gl_Position.y += sin(GameTime * 12000.0) / 150.0;
} else {
vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0);
}
texCoord0 = UV0;
}
This shader creates this effect.
Using sine again, we add to the y position. This will add a number between -1 and 1, and gradually go between them, creating a smooth animation. It's also divided by 150 to keep the number small enough for the text to stay on the line.
Sometimes, you may want to edit the vertices independently, this is pretty simple. This tiny line will allow you to get the id of the vertex.
float vertexId = mod(gl_VertexID, 4.0);
These are the ids:
void main() {
vec4 vertex = vec4(Position, 1.0);
gl_Position = ProjMat * ModelViewMat * vertex;
vertexColor = Color * texelFetch(Sampler2, UV2 / 16, 0);
if (Color.xyz == vec3(255.0, 255.0, 254.0) / 255.0) {
float vertexId = mod(gl_VertexID, 4.0);
if (vertexId == 3.0 || vertexId == 0.0) vertex.x -= cos(GameTime * 12000.0 / 4) * 3;
vertex.x -= max(cos(GameTime * 12000.0 / 4) * 4, 0.0);
gl_Position = ProjMat * ModelViewMat * vertex;
}
texCoord0 = UV0;
}
Firstly, I like to create a variable to hold the vertex, as we need to edit this. I set the gl_Position here as it's easier than adding an else statement. Again, checking if the colour is #FFFFFE, and getting the vertexId just like earlier.
At this point, I check if the vertexId is either 3 or 0 as these are the top 2 vertices.
If so, animate these to move back and forth. After this, it animates all vertices at a different rate. This creates the effect of the top two moving more than the bottom two.
This works by setting the x location of the vertex. The vertex is then passed back into gl_Position, multiplied by the ProjMat and ModelViewMat, as always.
Now you have slanted text!
You can easily create more effects in the same shader by checking for another color.
if (Color.xyz == vec3(255, 255, 254) / 255) {
// Cool Effect 1!
} else if (Color.xyz == vec3(255, 255, 253) {
// Cool Effect 2!
}
Be careful of what colours you overwrite, though, as you may need to use them elsewhere. Personally, I'd recommend colours that are pretty close to other colours, ones that wouldn't be noticable. One major limitation of this is, however, that you won't be able to use some colours. You can probably avoid this, but restricting the use of some specific colours on a multiplayer server isn't easy - I'm not even sure of any plugins that allow this.
A plugin like RoseChat (made by me) is incredibly useful for this, as, when a player sends a message containing #FFFFFE, it can automatically be changed to #FFFFFF. You can also allow players to create these effects in different ways, such as typing <bounce>Text</bounce>, and Text
will bounce in chat.
Well, that's it! The end!
Hopefully I've taught you a bit about shaders as well as how to create some cool shit!
I hope you have fun messing around and creating your own shaders, if you do, I'd love to see what you create!
If you have any problems, or want to correct any information here (I definitely don't know everything about shaders), feel free to create an issue or DM me on Discord at vekhove
.