Working on some shaders in Unity these days. Here's one.
Same shader, just different bitmaps & vertex colors.
Result, and the things that go into it.
Red vertex color is for the foam, green for the water surface, blue for the muddy edges (black vc shows the rocks). Vertex alpha for alpha blending.
Distortion texture is just the Clouds filter in Photoshop, repeated again in each channel. The distortion texture is applied to the UVs. It's done separately for foam/surface vs. mud/rocks, so the mud/rocks are distorted but don't scroll, while the foam/surface both scrolls and distorts.
The mesh is flat, no depth, a requirement for a game I'm working on.
The color textures for the water are all packed into one bitmap. Red channel = foam, green channel = water surface, blue channel = mud, alpha channel = rocks.
The lava version uses a different bitmap, same rgba layout though.
(bigger image
here, slightly modified but essentially the same)
I can explain more if anyone has questions.
I like how it came out, but it's too expensive for our mobile game so I'll have to revisit it.
Replies
iOS can render it fine, it's only an issue because there's a lot else happening in the level (foliage, characters, fx, etc.). It's just a fairly expensive shader, comparatively.
Channel packing keeps the texture fetch quick, but it still blends together four layers.
I could put this off to the side somewhere and it would be OK as-is. But I want to use flowing water/lava in dense areas too.
Going to try replacing the Power nodes with cheaper ones, see how it goes.
Here's a new gif to share. Pretty simple effect, but the fx artist was too busy so I jumped in. We avoid particles if possible, since emitters are pretty expensive.
The texture's red channel is the flame pattern, green is the sparks, and blue is the distortion. Though I might also use the blue for smoke later.
Vertex colors separate out the texture channels onto various polygons, and there's vertex alpha for transparency. I also added the red vertex color on top to make the center hotter, that's what the multiplier does in the material.
Red and green channels scroll, but the blue channel stays still, so red and green are distorted as they move through blue.
Is the game announced yet ?
Not much announced yet. Have to be a bit careful what I show. We have some old stuff on Twitter.
https://twitter.com/OutactInc
Figured out how to make a very cheap fresnel for our mobile shaders. So I'm using Subtract instead of Power.
Here's some lava, with different material values plugged in. As the player gets further in the game, we make things hotter. The rocks have a little bit of rim on them. Everything is emissive, no lighting here, just tweaking the same material values.
Another shader today. Swirly cloud animation for our stylized game. Using a scrolling flow map.
Did some sketching today in the MFA in Boston. Little thing, about 3 inches across. Not happy with the proportions, not looking all that neo-classical. More practice needed!
http://ericchadwick.com/img/wartide.html
The Shader Forge wiki was a good place for me to start. I keep going back for more tips as I make more shaders.
http://acegikmo.com/shaderforge/wiki/index.php?title=Advanced_Texture_Splatting
I also added a bunch of references on our wiki about texture blending.
http://wiki.polycount.com/wiki/MultiTexture#Modulation_Blending
Here's one of the terrains in our mobile game.
I use the Unity terrain system to sculpt because it's really easy to use, and I can play-test while I work. Then I export the terrain as a mesh, optimize it in 3ds Max to lower the vertex count, and re-import it. The less vertices, the less memory it uses, and the faster it loads in-game.
I paint a splatmap using Unity's terrain system, and use that in a custom shader to blend the textures. On non-terrain meshes I use vertex colors to blend instead, because it means less textures to load.
The terrain textures are packed into a single bitmap, and extracted in the shader.
This way I only load 1 texture instead of four. Because they're grayscale, I can colorize them in the material for different time-of-day effects. I can also reuse them in the shader for heightmap-based blending to add detail where they blend.
To compare... here's a straight linear blend, next to a heightmap-modulated blend, and an example in-game.
Here's one of the terrain shaders.
Most modulation-blend shaders use a Power function to add contrast to the blend. But for our mobile target, the power nodes were too expensive. So I used Subtract and Multiply to get a similar effect for better performance.
Here are a few color variations, just reusing the same texture assets with different colors in the materials.
haha Eric I was the one who wrote you the email, and thanks a lot for complement the information with this. Actually this images are very very good examples. I took a look at your links but I still have a little doubt.
I see you imported the unity terrain to 3ds max, optimized it and then re import it to unity, and then apply the terrain shader to use the 4 textures as one shader. But first, does shader forge has a unity terrain shader template? (I haven't use it yet).. and, if you use vertex paint to spread and blend the textures on the terrain, how do you keep that information on the optimized low poly mesh, since vertex paint is better with higher vertex count/resolution?
anyhow, thanks a lot for your support and help
I'm not using vertex color on the terrain. Instead I'm using a splatmap. More info here http://polycount.com/discussion/comment/2399645/#Comment_2399645
Nope not gradient mapping, a bit more manual than that. And I guess a bit cheaper to render/store. I just change the tint colors in each scene material (usually about 8 or ten materials), and store those in a palette array. The designer then specifies which palette they want to load when they instantiate the level.
Here's the palette tool, from our lead programmer. And three different material settings, just for the terrain. The sky, props, vegetation each have their own material settings to adjust.
Way above, you built your own Fresnel. Is it really significantly cheaper than using SF's Fresnel node?
Cheers for your interesting posts, as always!
Fresnel typically uses a Power function, but some math functions are a bit expensive on mobile. So I'm avoiding Power altogether.
Unity talks about it a little bit here
https://docs.unity3d.com/Manual/OptimizingGraphicsPerformance.html
Thank you for sharing your insight here. It drove me to create an account to tell you this. I've had Shader Forge for a little while now, but truly being an independent dev, my time to learn the system has been limited. I wasn't able to execute your water shader with much success, but I understand SF much better now. Also, your pointers on the optimizations is excellent.. and so is your artwork!
You said that the first version of your water shader was too heavy for your mobile game, but then you showed the shader you chose for it. Is this the modified version you shared later? I don't want to see your build, just more of the approach you took to get to it. Also, how much of a performance gain would you say you gained between using the alpha channel and not. I understand there are a lot of factors that would affect this, but was wondering if you had an idea of a general percentage.
I added a control in the shader for the vertex positions to be distorted by the same scrolling motion. This has some ragged jumpy motion, I guess it's the big pixels. It's not that big a deal though. And our graphics programmer does some magic of his own to optimize the shader, since Shader Forge does not create optimized shaders. It's more of a prototyping tool, as the author Joachim admits.
I ended up with a river shader using only 3 layers... foam, waves, rocks. Didn't need dirt as well, that was overkill.
I disabled alpha blending, since in my situation it wasn't really needed. I was only using it for the edges, and those aren't that visible in our game. You can see the setup in the latest GIF.
Also I disabled lighting altogether, which also helps improve rendering speed. That removed the need to use a lightmap, which costs download time, loading time, and memory. I baked the shading into vertex alpha.
Alpha blending is fill-rate expensive... it gets more expensive the more it fills the screen. And if you have multiple overlapping alpha-blended surfaces, that gets more and more expensive. It's not a straight % decrease, because it changes relative to your usage. Only way to judge the difference is to profile it.
I'll post another node layout shot when I get a chance.
https://www.youtube.com/watch?v=H2vLwOAu0UI
Another shader, testing GIFV support. This one uses red vertex color to blend between hot & cold lava, and green vert color to paint extra-hot areas.
I start with a flat Unity Terrain, and just start sculpting with the built-in tools.
https://docs.unity3d.com/Manual/terrain-UsingTerrains.html
I use Terrain Painter, which has a lot of great painting and sculpting tools. I use it mostly for painting the splatmaps, since it has nicer brush control, lets me add noise to the transitions, lets me blur/sharpen, etc.
https://www.assetstore.unity3d.com/en/#!/content/27340
I also use Terrain Pressure Paint, so I get pressure sensitivity on the Cintiq.
https://www.assetstore.unity3d.com/en/#!/content/30384
I use Shader Forge to make custom terrain shaders.
http://acegikmo.com/shaderforge/
I pack 3 grayscale terrain textures into one RGB texture, then use each channel for both the texture and the detail in the blends. I think I detailed how that works earlier.
I used to use RGBA to pack four textures, but I found I could get away with just 3 and reusing one of them as 2 layers. This saves a decent amount of texture memory and download size for a mobile game.
I make two shaders... one for Unity's terrain since it requires a special setup, and another one for after I convert it to a mesh. So I can optimize out all the unneeded vertices and memory bloat.
http://acegikmo.com/shaderforge/wiki/index.php?title=Basic_Terrain_Setup
https://alastaira.wordpress.com/2013/12/07/custom-unity-terrain-material-shaders/
To export/import a height map, for example from World Machine or Photoshop or whatever, I use Raw file format. 16 bits per channel, single channel (grayscale), byte order: IBM PC, 65x65 pixels (see Unity docs for why it's not powers-of-two). Terrain has height map import/export built in.
To export a splatmap, I use VacuumShaders Terrain To Mesh. I also use this to convert the Terrain into a mesh once I'm done painting and sculpting.
https://www.assetstore.unity3d.com/en/#!/content/47276
To import a splatmap, I use Terrain Importer.
https://www.assetstore.unity3d.com/en/#!/content/21223
New job, no more game shaders. I'm using my commute to catch up on some sketching, with charcoal pencils.