Hello. I'm new to these forums (I crawled out of a bukkit), so I thought I would join the likes of brilliant and talented reverse-engineers with my first post. If there is anything I missed, any existing resources on the topic, etc, please let me know. Onward.
As many of you know, the recent 1.7 update introduced one of the biggest changed to Miencraft's rendering code, the additions of shaders to it's rendering pipeline.
The shaders are conveniently located in the assets folder, and are therefore customizable by resource packs. These shaders do, however, have a few limitations:
Shaders cannot access most of the data from the rendering pipeline without client mods. They can only (at least for now) access a texture containing the rendered image, as well as a few other pieces of data that we will cover later. This means that they can only do post-processing effects such as edge detection or sepia, as opposed to more involved effects like bloom (still possible, but not as convincing), or depth of field. It seems promising that this will not be true in the future, but in it's current form it allows servers and resource pack creators to offer unique gameplay elements and visual style, beyond that of a custom texture.
Shaders, once loaded from a resource pack, must be activated using the super secret settings button. You must overwrite one of the existing effects, however you are free to create and combine as many shaders as you want.
Here, I present the knowledge I gained about minecraft's effects system from reverse engineering it, in the hopes that others can build on the knowledge freely. If there is enough interest, I want to make a series about it, and hopefully we will be able to take a look at how to make our own effects, and we will look at how the stock shaders accomplish their respective effects.
Prerequisites:
You must know at least one programming language, preferably c-like. (i.e java, glsl, c, c++, c#)
Familiarly with json.
Familiarity with the programmable pipeline in opengl is not required (I am hardly an expert myself), although it will help you a lot. It also helps if you know glsl (the shading language), but I'll try to make the examples as accessible as possible.
Getting your feet wet, building a black and white shader:
Ok. Create a folder, and add a stock mcmeta and pack.png (or find a resource pack template). Create the folder assets/minecraft/shaders. In that folder, create the following folders:
post - This is where the json files for the post-processing effects go. It specifies the passes that the effect takes, as well as the inputs/output for each pass
program - The json files for, as well as the glsl fragment/vertex shaders that actually apply the effects
In post, create a new file called fxaa.json. Unfortunately, the effect names are hardcoded, and you have to overwrite one of them in order for the super secret settings button to activate it. Fxaa is just the first shader to be activated. In it, write the following:
#version 120
// The current rendered image
// (name is hardcoded into the minecraft code,
// so if you want it to be updated properly,
// you must name it DiffuseSampler)
uniform sampler2D DiffuseSampler;
// texCoord is the current xy position of this fragment(pixel) on the screen.
// It ranges from 0 to 1.
// It is interpolated from between the positions of the positions sent to the vertex shader (that's what varying's do)
varying vec2 texCoord;
void main() {
// This is the current colour of the rendering
vec4 CurrTexel = texture2D(DiffuseSampler, texCoord);
// Average the colours, and use that as the brightness value
float brightness = (CurrTexel.x + CurrTexel.y + CurrTexel.z)/3.0;
CurrTexel.r = brightness;
CurrTexel.y = brightness;
CurrTexel.z = brightness;
gl_FragColor = CurrTexel;
}
Load the resource pack, then click once on the super secret settings button. You should see this:
So, I guess I have a lot of explaining to do now. A vertex shader is run on each vertex of a shape, and controls the final position on the screen of it, as well as any values to the fragment shader. In this case, in order to do the post-processing effects, Minecraft renders the game to a texture first, then renders a square to the screen, textured using the rendered texture. The vertex shader (sobel in our example) just outputs the same position as is given to it, multiplied by a projection matrix, as well as a position in the texture for the fragment shader. To illustrate this, if I change the vertex shader to cut the output vertex in half, you get this:
The fragment shader (which is run for every pixel in a shape) is then run over the square, and does any necessary effects. It can pull data from the texture, and do whatever effects to this data that it wants (in our case, the fragment shader we wrote makes the screen b&w). It runs through every pixel (fragment) in the square, which is why it is black in the above image.
Hopefully now you have your feet wet. Enable the minecraft developer console and play around with the values in the fragment shader. See what works and what doesn't. Restart the game for your changes to take effect (and make sure to click the super secret settings button again). Try creating a mild desaturation effect, or perhaps even a sepia effect like this (code in the spoiler):
PS: Sorry for linking to attachments at bukkit for the pics. I couldn't figure out how to upload the images, and I'm not allowed to embed external images.Reserved.
Wow that looks really cool Unfortunately for me, I know nothing about coding/programing, although I have tried to mess around a little with some shaderpacks and the vanilla shaders to try and get some cool shaders for mc 1.7....didnt really work lol...Probably due to the limitation to post-processing and the hard coded names you mentioned. All the best for your project
I have a hunch that this could be worked around by using a vertex shader instead, by modifying the world coordinates of vertices before projecting them. However, I've not yet had any luck with this. If you have any more information on how the vertex shaders work in Minecraft, please share.
The vertex shader program that minecraft lets you run is, AFAIK, only for the position of the render target. Hopefully, in the next version, proper vertex shaders will be implemented (The first thing I want to try when that happens is Depth of Field). Your shader does look really nice, and I would love to see how you did it.
I was hoping that this would generate more interest, and we could make a community post-effect pack. If you, or anyone else, is interested, feel free to PM me
I'm also glad to have found your post, after looking at some of the code behind shaders used with the shaders mod I've become interested in making shaders. Did you ever write anything else in this series? Or would you have any suggestions where to go next?
As many of you know, the recent 1.7 update introduced one of the biggest changed to Miencraft's rendering code, the additions of shaders to it's rendering pipeline.
The shaders are conveniently located in the assets folder, and are therefore customizable by resource packs. These shaders do, however, have a few limitations:
Prerequisites:
Ok. Create a folder, and add a stock mcmeta and pack.png (or find a resource pack template). Create the folder assets/minecraft/shaders. In that folder, create the following folders:
post - This is where the json files for the post-processing effects go. It specifies the passes that the effect takes, as well as the inputs/output for each pass
program - The json files for, as well as the glsl fragment/vertex shaders that actually apply the effects
In post, create a new file called fxaa.json. Unfortunately, the effect names are hardcoded, and you have to overwrite one of them in order for the super secret settings button to activate it. Fxaa is just the first shader to be activated. In it, write the following:
In program, add bw.json:
and bw.fsh (where the actual work is done):
Load the resource pack, then click once on the super secret settings button. You should see this:
http://forums.bukkit...1-36-png.15666/
http://forums.bukkit...1-52-png.15668/
So, I guess I have a lot of explaining to do now. A vertex shader is run on each vertex of a shape, and controls the final position on the screen of it, as well as any values to the fragment shader. In this case, in order to do the post-processing effects, Minecraft renders the game to a texture first, then renders a square to the screen, textured using the rendered texture. The vertex shader (sobel in our example) just outputs the same position as is given to it, multiplied by a projection matrix, as well as a position in the texture for the fragment shader. To illustrate this, if I change the vertex shader to cut the output vertex in half, you get this:
http://forums.bukkit...3-24-png.15669/
The fragment shader (which is run for every pixel in a shape) is then run over the square, and does any necessary effects. It can pull data from the texture, and do whatever effects to this data that it wants (in our case, the fragment shader we wrote makes the screen b&w). It runs through every pixel (fragment) in the square, which is why it is black in the above image.
Hopefully now you have your feet wet. Enable the minecraft developer console and play around with the values in the fragment shader. See what works and what doesn't. Restart the game for your changes to take effect (and make sure to click the super secret settings button again). Try creating a mild desaturation effect, or perhaps even a sepia effect like this (code in the spoiler):
http://forums.bukkit...4-06-png.15671/
http://forums.bukkit...4-08-png.15672/
uniform sampler2D DiffuseSampler;
varying vec2 texCoord;
void main() {
vec4 CurrTexel = texture2D(DiffuseSampler, texCoord);
CurrTexel.x = (CurrTexel.x * 0.3588) + (CurrTexel.y * 0.7044) + (CurrTexel.z * 0.1368);
CurrTexel.y = (CurrTexel.x * 0.2990) + (CurrTexel.y * 0.5870) + (CurrTexel.z * 0.1140);
CurrTexel.z = (CurrTexel.x * 0.2392) + (CurrTexel.y * 0.4696) + (CurrTexel.z * 0.0912);
CurrTexel*=vec4(1.2,1.1,1,1);
gl_FragColor = CurrTexel;
}
http://forums.bukkit...3-32-png.15679/
http://forums.bukkit...4-01-png.15680/
and after that, we will talk about render targets in more depth (motion blur):
http://forums.bukkit...7-45-png.15674/
http://forums.bukkit...1-40-png.15675/
http://forums.bukkit...1-43-png.15676/
So, if this interests you, please leave a message. If there is enough positive response, I'll write some more. Thanks for reading, and I hope I can become part of your community!
PS: Sorry for linking to attachments at bukkit for the pics. I couldn't figure out how to upload the images, and I'm not allowed to embed external images.Reserved.
The vertex shader program that minecraft lets you run is, AFAIK, only for the position of the render target. Hopefully, in the next version, proper vertex shaders will be implemented (The first thing I want to try when that happens is Depth of Field). Your shader does look really nice, and I would love to see how you did it.
I was hoping that this would generate more interest, and we could make a community post-effect pack. If you, or anyone else, is interested, feel free to PM me
You have no idea how useful this shader will be for my project here. Kudos!