[1.7] Give your server a distinct visual style with custom shaders, no client mod needed!

Discussion in 'Resources' started by jtjj222, Nov 10, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    jtjj222

    As many of you know, the recent 1.7 update added two huge new features (well, one new one, and the re-addition of an old one):

    • The addition of shaders to Minecraft's rendering pipeline (the biggest change since it's inception)
    • The ability for servers to recommend resource packs

    The shaders are conveniently located in the assets folder, and are therefore customizable by resource packs. Yes, servers can run code on the client's gpu, albeit with a few minor stipulations:

    • 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 to offer unique gameplay elements and visual style, beyond that of a custom resource pack.
    • 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. All my original code here is public domain, and the minecraft code presented here is property of mojang. Together in this series, we will 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/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:
    Code:json
    1.  
    2. {
    3. "targets": [
    4. "swap"
    5. ],
    6. "passes": [
    7. {
    8. "name": "bw",
    9. "intarget": "minecraft:main",
    10. "outtarget": "swap"
    11. },
    12. {
    13. "name": "blit",
    14. "intarget": "swap",
    15. "outtarget": "minecraft:main"
    16. }
    17. ]
    18. }
    19.  


    In program, add bw.json:
    Code:json
    1.  
    2. {
    3. "blend": {
    4. "func": "add",
    5. "srcrgb": "one",
    6. "dstrgb": "zero"
    7. },
    8. "vertex": "sobel",
    9. "fragment": "bw",
    10. "attributes": [ "Position" ],
    11. "samplers": [
    12. { "name": "DiffuseSampler" }
    13. ],
    14. "uniforms": [
    15. { "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 ] },
    16. { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
    17. { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }
    18. ]
    19. }


    and bw.fsh (where the actual work is done):
    Code:glsl
    1.  
    2. #version 120
    3.  
    4. // The current rendered image
    5. // (name is hardcoded into the minecraft code,
    6. // so if you want it to be updated properly,
    7. // you must name it DiffuseSampler)
    8. uniform sampler2D DiffuseSampler;
    9.  
    10. // texCoord is the current xy position of this fragment(pixel) on the screen.
    11. // It ranges from 0 to 1.
    12. // It is interpolated from between the positions of the positions sent to the vertex shader (that's what varying's do)
    13. varying vec2 texCoord;
    14.  
    15. void main() {
    16. // This is the current colour of the rendering
    17. vec4 CurrTexel = texture2D(DiffuseSampler, texCoord);
    18.  
    19. // Average the colours, and use that as the brightness value
    20. float brightness = (CurrTexel.x + CurrTexel.y + CurrTexel.z)/3.0;
    21. CurrTexel.r = brightness;
    22. CurrTexel.y = brightness;
    23. CurrTexel.z = brightness;
    24.  
    25. gl_FragColor = CurrTexel;
    26. }
    27.  


    Load the resource pack, then click once on the super secret settings button. You should see this:

    2013-11-10_20.41.36.png 2013-11-10_20.41.52.png

    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:

    2013-11-10_21.03.24.png

    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):

    2013-11-10_21.14.06.png 2013-11-10_21.14.08.png

    code (open)
    Code:glsl
    1. #version 120
    2.  
    3. uniform sampler2D DiffuseSampler;
    4.  
    5. varying vec2 texCoord;
    6.  
    7. void main() {
    8. vec4 CurrTexel = texture2D(DiffuseSampler, texCoord);
    9.  
    10. CurrTexel.x = (CurrTexel.x * 0.3588) + (CurrTexel.y * 0.7044) + (CurrTexel.z * 0.1368);
    11. CurrTexel.y = (CurrTexel.x * 0.2990) + (CurrTexel.y * 0.5870) + (CurrTexel.z * 0.1140);
    12. CurrTexel.z = (CurrTexel.x * 0.2392) + (CurrTexel.y * 0.4696) + (CurrTexel.z * 0.0912);
    13.  
    14. CurrTexel*=vec4(1.2,1.1,1,1);
    15.  
    16. gl_FragColor = CurrTexel;
    17. }

    In the next tutorial, we will talk about doing multi-pass rendering(combination of the sobel and art effects):
    Screenshot from 2013-11-03 19:53:32.png Screenshot from 2013-11-03 19:54:01.png
    and after that, we will talk about render targets in more depth (motion blur):
    2013-11-07_20.17.45.png 2013-11-08_08.51.40.png 2013-11-08_08.51.43.png
    So, if this interests you, please leave a message. If there is enough positive response, I'll write some more. Thanks for reading!

    Reserved for the links to the next section

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  2. Offline

    chasechocolate

  3. Offline

    MegaScience

    So essentially the current vanilla shaders have no true access to vertexes? When the snapshots introduced shaders, I tried to make a vanilla version of the Acid Trip shaders of the shader mod two and a half years ago, but any changes I made only modified the display window and not any objects within it. Perhaps there is a way, but everything is extremely limited at the moment.
     
  4. Offline

    DSH105 Retired Staff

    Much wow. :D
     
    DogeDev and nichiatu like this.
  5. Offline

    MegaScience

    I tried testing this one more time in sobel.vsh with gl_Position, and yep - all it's doing is the screen region:

    Code:glsl
    1. #version 120
    2.  
    3. attribute vec4 Position;
    4.  
    5. uniform mat4 ProjMat;
    6. uniform vec2 InSize;
    7. uniform vec2 OutSize;
    8.  
    9. uniform float Time;
    10.  
    11. varying vec2 texCoord;
    12. varying vec2 oneTexel;
    13.  
    14. void main(){
    15. vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0);
    16.  
    17. outPos = outPos * vec4(sin(Time), cos(Time), sin(Time), cos(Time));
    18.  
    19. gl_Position = vec4(outPos.xy, 0.2, 1.0);
    20.  
    21. oneTexel = 1.0 / InSize;
    22.  
    23. texCoord = Position.xy / OutSize;
    24. texCoord.y = 1.0 - texCoord.y;
    25. }


    Testing by just adding Time used in Wobble and sine/cosining it, then multiplying it into outPos. I was disappointed they decided to push out 1.7 so abruptly without expanding shaders at least a little more, although I suppose they didn't want to risk breaking what they already had. I look forward to when I can make the game world flex in all directions, instead of just the screen region.
     
    Milkywayz and jtjj222 like this.
  6. Offline

    xTrollxDudex

    Dang dude. That's amazing!
     
  7. Offline

    Jamesthatguy

    Very cool.
     
  8. Offline

    jorisk322

    This is amazing! I love this, please do continue this as a series.
     
  9. Offline

    DarkBladee12

    jtjj222 Good job. This sounds very interesting! ;)
     
  10. Offline

    jtjj222

    It seems that I will only be continuing the series here. Server owners seem to see the true opportunities this provides. Not a single like or reply on the minecraft forums.
     
    tyzoid and Milkywayz like this.
  11. Offline

    BungeeTheCookie

    This was so beautiful I cried
     
    tyzoid and jtjj222 like this.
  12. Offline

    Gamecube762

    Looks interesting, would be cool to see how servers make use of this.
     
  13. Offline

    rguz10

    Amazing.
     
  14. Offline

    Goblom

    jtjj222 (Off topic) I noticed that you might be using Ubuntu to play Minecraft. How well does it perform?
     
  15. Offline

    totokaka

    jtjj222 Amazing! Thanks for sharing! I'll admit I don't understand much of this, a better description of the CurrTexel.x .y .z and .r variables would be nice!

    Goblom I'm running Minecraft in ArchLinux, the performance is worse than Windows with vanilla Minecraft, but with optifine and some other mods optimizing the math It's quite good. I get up to 120 FPS with my Radeon HD 6790
     
    jtjj222 likes this.
  16. Offline

    Goblom

    totokaka How much ram does the comp have ?
     
  17. Offline

    jtjj222

    totokaka I did gloss over glsl a bit. In the next tutorial, I'll try to talk more about it. Thanks for the feedback!
     
  18. Offline

    MegaScience

    Do you think we'd ever be able to reproduce acid trip shaders from the original GLSL mod? It seems the current iteration of shaders don't allow that kind of versatility, but just curious if you think they'd ever go near it.

    If you don't know the acid trip shader:
    Code:
    http://www.youtube.com/watch?v=JpksyojwqzE
     
  19. Offline

    jtjj222

    MegaScience do you have code for that mod? It seems that it modifies the position of the world vertices, so until the shaders are given a better place in the pipeline, no. We can, however, make creative effects and overlays, to convince the team at mojang to enhance the shader capabilities sooner :p
     
  20. Offline

    MegaScience

  21. Offline

    totokaka

    jtjj222 I'm looking forward to your next part!

    Off topic:
    Goblom 12GB, So the RAM wasn't no problem. However, the AMD linux drivers are painfull, and fullscreen doesn't work on my fullscreen setup.

    jtjj222 I found this: http://www.minecraftforum.net/topic/847696-100-glsl-acid-shader-mod/ after a quick search. I've never used it myself, but it would be interesting if servers could do that on the clients

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 5, 2016
  22. Offline

    MegaScience

    I doubt Mojang would make Serverside Resource Packs automatically activate shaders on a client, at least not without some option to turn on. People complain enough about rendering lag and such without the game forcing possibly intensive shaders.

    Not saying I don't like the idea, just saying I don't think we'd be able to force them upfront.
     
  23. Offline

    jtjj222

    MegaScience Personally, I'd like a recommended shader option. The server would send a shader in a resource pack, and after accepting the resource pack, the user would be asked if they would automagically like to run the shader.
     
  24. Offline

    MegaScience

    I suppose that could work, so long as they make it so you can't accidentally accept. I'd rather not have the feature get instantly removed because people who can't handle it somehow get forced into it.

    And also, while unlikely due to this requiring you join a bad server, bad shaders which do some crazy stuff which might crash you. Although it could also be likely as shader quality goes down with people making them you might get overly-intensive shaders with some bugs that end up crashing you...

    I'm just trying to consider every angle Mojang might narrow our ability to utilize shaders for the sake of the community. I'd rather not get my hopes too high only to hit one of these walls and... you know.
     
  25. Offline

    jtjj222

    MegaScience I think that shaders crashing the game are a nonissue. If I can send an invalid block change packet and crash the client, why is a shader an issue? Besides, the user can always deny it...
     
    TheButlah likes this.
  26. Offline

    MegaScience

    Well I understand that. Just that as the vanilla game, they are more careful about how many ways someone can cause you trouble, and they would still try to limit that, so I'm just trying to think of every reason this might get limited. You could also consider as shaders become more popular, low-grade ones are made which are just overly intensive or annoying in some way. Just being pessimistic for myself, don't mind me.

    However, that doesn't change my original point: Wanting to bend the entire world. I hope the current shaders wouldn't need adjustments for such a change, because I don't think they want to mess with them much at this point.
     
  27. Offline

    Hoolean Retired Staff

    jtjj222

    Looks like json doesn't work as a syntax tag, use JavaScript for now, it works OK :)
     
    jtjj222 likes this.
  28. Offline

    chrisman0091

    Very nice tutorial! The second tutorial will for sure make some really nice drug plugins:)
     
  29. Offline

    rbrick

    Off topic but is that ubuntu i see there :p
    also great job!
     
  30. Offline

    Tomshalev01

    You should really write another tutorial, it helps alot!
     
Thread Status:
Not open for further replies.

Share This Page