The easiest way to do this is to use 4 separate single channel textures in your editor, and combine/compress them as a final step. Texture arrays are ideal for things like this.
The brushes can be easily created mathematically on the GPU, or using GDI+ (which has shape commands). You'll need a fifth single channel texture the to use as a destination channel - copy one channel to it entirely and then add/subtract/multiply blend with your brush texture.
Finally, seeing as you're only using 4 textures, you might want to consider have a fifth default texture that's applied to the entire world, and then blend the other 4 depending on your splat texture. You can do something nifty here - use a rock/cliff face texture with tri-planar texturing, and don't overpaint it with the other 4 textures on the steeper areas.
1) well if everything is done in a shader, than writing the individual channels won't be an issue, likely.
2) I think these extra channels and binding will not be needed? if I create a single render target texture, and use that to load the splat map on file->open, than i can pass a channel mask as a shader constant, allowing direct editing of each channel.
3) I'm not sure how many splats is common for a modern terrain system, but I think it would depend a lot on the size of chunks. I started with 4, because i was just going from my own thoughts(4 channels, 4 maps) but have added a 5th base texture already. Since it is default everywhere, it had no real bearing on this thead, so i neglected to mention it. But since you did, I was/am having issues when i try and visuallize just the default texture. rather than a plain dirt terrain, the ps seems to map the splat map onto the terrain. rather than the default one.
float4 splatmap = tex2D(splatmaptexsampler,float2(input.Texcoords.x , input.Texcoords.z ));
float4 base = tex2D(basetexsampler, float2(input.Texcoords.x * 10, input.Texcoords.z * 10));
float4 splat1 = tex2D(splat1texsampler, float2(input.Texcoords.x * 10, input.Texcoords.z * 10));
float4 splat2 = tex2D(splat2texsampler, float2(input.Texcoords.x * 20, input.Texcoords.z * 20));
float4 splat3 = tex2D(splat3texsampler, float2(input.Texcoords.x * 10, input.Texcoords.z * 110));
float4 splat4 = tex2D(splat4texsampler, float2(input.Texcoords.x * 5, input.Texcoords.z * 5));
result = base;
how ever, if result is a combination of base and one or more of the splats, then every thing appears ok. I assume this is because if i don't use the splatmap in the final calculations, the shader ignores it, and it's sampler. meaning that the next sampler created (basetexsampler) gets set to the stage 0 rather than stage 1.
result = float4(base.xyz,0) * (1 - splatmap.r) + (splat1 * splatmap.r);
edit: ignore the magic numbers in the PS, those scales will be passed in as constants as well, but I'm not going to fix that until i have this painting sorted.
Edited by Burnt_Fyr, 09 July 2014 - 11:47 AM.