iOS terrain shader with three texture blending and grayscale vertex color: is it possible?

I am developing a game for iOS, and for my terrain purposals, I need a simple shader wich can both enable grayscale vertex colors (I need only black color tone, so I can make darker variations of the surface), and also blend between three textures, always using vertex colors (so I can have something like dirt, rock and grass).

Since vertex colors have always three different informations (hue, saturation and brightness), I would use them this way:

  • Hue: intensity of the second texture
  • Saturation: intensity of the third texture
  • Brightness: intensity of the black color
  • First texture is the basic texture and is always present.

Combined to Lightmapping, this shader should work very well.
I already tought to use a simple and big diffuse map with all the things directly painted on it, but since I’m going to have many different terrains, this would skyrocket the final App’s size. I prefer using this kind of shader instead.

I’m not much into shader scripting so I’m not experienced in this field, but I would ask if it’s possible to script a shader like this. Any help will be very appreciated. Thanks!

What you are talking about is more complex and less performant than it needs to be. I recommend trying to work the way Unity’s terrain does, first. That is, the color channels of your blend mask are multiplied by the textures, and the results are added together. The result needs to add up to one, though, and I can’t recommend any tools that do that. Please let me know if you can.

If you can get that result, then you can paint greyscale “light” in the alpha channel of the vertex colors. Ideally, you could have the alpha channel multiplied into the RGB colors, which would save a multiply instruction in the vertex shader. But even better, if you have a better painting tool, you could get four textures blending, not just three, by blending with all four channels. (This would require that the painting tool use more than four channels internally, in order to perform live blending and light calculations.)

There’s a lot of potential for vertex colors, but personally, I can hardly harness their power. I use Blender, which is god-awful for vertex coloring. It doesn’t even handle the alpha channel; I have to do stupid hacks to get that exporting. I know how to deal with them in shaders though, so if you learn of a tool that can help with the stuff I’m describing, again, please let us know, here.

Also, you can’t run this on hardware that won’t run iOS 5 (pre-3GS). There’s not really a way to do a fallback, either, without other assets, so I recommend forgetting about them. If that’s not an option, you’ll have to drop down to only two textures instead of three or four.

Shader "Vert Color Mix (RGB)" {
	
Properties {
	_RedTex ("Red", 2D) = "" {}
	_GreenTex ("Green", 2D) = "" {}
	_BlueTex ("Blue", 2D) = "" {}
}

SubShader {Pass {
	GLSLPROGRAM
	varying vec2 uv;
	varying lowp vec3 color;
	
	#ifdef VERTEX
	void main() {
		gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
		uv = gl_MultiTexCoord0.xy;
		color = gl_Color.rgb * gl_Color.a;
	}
	#endif
	
	#ifdef FRAGMENT
	uniform lowp sampler2D _RedTex, _GreenTex, _BlueTex;
	void main() {
		gl_FragColor = vec4(
			mat3(texture2D(_RedTex, uv).rgb, texture2D(_GreenTex, uv).rgb, texture2D(_BlueTex, uv).rgb) 
				* color, 1
		);
	}
	#endif
	ENDGLSL
}}

}