Is there a technique I can use in WebGL (using Three.js by MrDoob) that will cover a large area E.g. a stone wall or a cobbled floor with a random texture that doesn't look like it's repeating? I have an example at http://www.timeref.com/webgl_house_test2.html. Could I use a shader to do this?
1 Answers
First off, nice demo!
In regards to your question: This is something that has kept engine programmers up at night since the dawn of time. :)
There are a few things you can do to mitigate the visibility of repeated textures. The first and most obvious is simply not to use a repeated texture! Called virtual texturing, this is a bit tricky to do in the general case (RAGE's Megatexture is one of the only commercial implementations I know of) but if you have a more restricted use like texturing a landscape it can be made a bit easier. I would imagine that such an approach is overkill for most needs, though.
There are some simpler methods to help the situation, though. If you wanted to go the route of generating the surface detail entirely in the shader (which can be expensive) then you can get a lot of mileage out of applying various fractals to your output. (Think of something like a Mandelbrot set) but that is typically harder for an artist to control. There's some interesting resources out there about ways to blend repeating textures in such a way as to make them look less repetitive, but they have a tendency to mangle textures with very orderly patterns (like bricks or tiles).
Probably the most artist-friendly route that I know of, though, is using detail textures. These can work two ways: They can add fine grained detail to a larger repeated pattern or they can add a larger layer of variance over the top of a repeated pattern to break up the monotony. (That's the one that you would want.) In both cases the blend is very simple and doesn't cause much runtime hit.
If all else fails, you can continue to use repeated textures but just make the base texture larger and more varied. In may still look funny from far away, but that really depends on the type of app you're making. If the intent is for users to walk around in a first person perspective then this will probably be sufficient. If you're doing a fly over, it could be more easily noticeable. (But in that case you probably don't need small textures with many repetitions like your example shows.) Of course the tradeoff here is using more texture memory and the performance hits that come with that.
You've probably realized by now that there's not really any silver-bullet solution to this problem. It's mostly about balancing the visual needs of your app with the performance requirements, and it's something that's going to be different for just about every project.