Well the (geometry’s) terrain positions are fine because they are calculated in double precision on the CPU so the actual geometry doesn’t suffer from these artifacts (on the GPU I’ve been experimenting with using emulated double precision for my normals calculation but it hasn’t led to any major improvements) - it’s the GPU-generated normal map that is suffering from the issues (I didn’t really make that clear in my first post) because the positions used in the calculation suffer from the precision limits. I can’t really generate the noise in patch coordinates because the result wouldn’t be continuous across the entire planet AFAIK (actually I would just have the same terrain patch everywhere [right?] - I’m really confused as to how that is working for you). Pretty much everything involving the normals has to be done in world space because the normal map itself is in “world” [object] space. From what I’ve read the most you can do to reduce the latency with GPU -> CPU is explained here: http://answers.unity3d.com/questions/465409/reading-from-a-rendertexture-is-slow-how-to-improv.html
[quote=“NavyFish, post:82, topic:765”]
GPU -> CPU is definitely slow - well, to be more precise, the transfer itself isn’t slow, but there’s a latency involved since the GPU must flush its pipeline before downloading the data. I’m looking into ways to mitigate/hide this latency myself,[/quote]
You can use a fence and async gpu texture reads to read back data from the gpu without slowing down the cpu. You’ll have a delay of up to many frames before the data is ready though, so your procedural generation pipeline has to be written in an async way.
You’re generating normals from absolute vertex positions ? Try deriving the heightmap in tangent space instead, that will give you more precision.
I’m a little confused by this - so I’m supposed to create tangent space normals and convert them to object space before writing the normals into the normalmap?
Thanks. As alluded to by SkavenPlanet’s link, this is somewhat more difficult in unity. I am considering forcing OpenGL mode so that I can access PBOs directly to perform the async transfer, but need to research further into what secondary effects this may have.
Like IA said, you want your vertex positions and normals calculated in ‘tangent space’ (I was calling this patch space, but his term is more precise). Typically a normal map is not defined in world space, it is defined in tangent (also called texture) space, so that it aligns with a mesh’s UV mapping. As such, when rendering, you simply transform the camera and relevant lights into tangent space to perform lighting calculations. If you were actually working with world-coordinate normal maps, you’d have to transform each and every normal into the camera’s coordinate system, which is a heck of a lot more work.
I haven’t had an issue with 32-bit floating point precision for generating vertex positions. My lowest lod patches - the 6 patches that comprise the root of each quadtree / face - span nearly 8000 miles, and the vertices are each some 35+ miles apart. 32bit FP gives you about 7 significant digits of precision, so from 0 to 8000 miles, your minimum representable change is about .0008 miles, or about 50 feet. This isn’t perceptible at the distances from which a LOD-0 patch would be viewed. As higher and higher LOD patches are generated, the corresponding area they cover is reduced, and since I work in patch coordinates, precision does not become an issue.
For bump map generation, I recommend you “wrap” your domain (the function’s input coordinates). Bump mapping is very high frequency noise, so the wrapping range must be large enough so that tiling isn’t visible. But since it won’t be visible from very far away, this isn’t a problem. “Wrap” is probably the wrong word, because simply doing a modulus on your domain will cause discontinuities at the wrap - instead, you want the input domain to ‘loop’. sin and cosine can achieve this.
EDIT: The input coordinates can be specified either in world space, or a ‘global texture space’ (a topic I haven’t discussed yet but likely will soon - one which maps 3d coordinates to a 2d parameterization). Assuming you’ve defined your patch its own space (although I don’t think you have, so disregard this), you’ll need to transform the vertex/texel position from patch space to world space prior to wrapping them and inputting them into the noise function.
For all intents and purposes, tangent space == object space for each patch. At least this is the case for me.
Each patch should have its own coordinate system with an origin near/at the center of the patch, and the ‘up’ direction being aligned with an axis. Calculate your vertex normals from the position of the terrain vertices in this space. Then create a normal map which is ‘additive’ to those vertex normals: in other words, the normal map perturbs the vertex-interpolated normals you calculated in patch/tangent space.
When drawing the patch, use the patch coordinate space (tangent space) - in other words, transform all of your lights and cameras into that patch’s space. Now your lighting calculations can do a direct lookup from the normal/bump map, as those (thousands) of values are already in the ‘correct’ coordinate system.
If they’d been calculated in world coordinates, when you’re drawing (in camera coordinates, by definition), you’d need to transform all (thousands) of normal vector look-ups into camera space EVERY FRAME.
In general, since you’ll have to transform everything into a common / consistent space anyway, choose that common space to be the one with the most data. That way you won’t have to transform said data at all.
I thought that you can’t directly use tangent space normal maps for procedural planets because there will be discontinuities at the edges of the 6 quad-cube sphere faces so they have to be generated in object space (not world space - the world space origin is somewhere near the camera at all times [which can be millions of kilometers away]) - a space that is relative to the planet’s center and rotation. This is why I though that after finding the normals in tangent space I had to get them into object space at some point (because the uv’s [and subsequently tangents] for the tangent space normal maps won’t wrap seamlessly no matter how you orient the quad-cube faces).
Well, the vertex normals are already in-use for something else… part of the benefit of the normal map is that I won’t need vertex normals as the procedural noise functions that are used to generate the vertices and (ultimately) the normal map are identical so essentially the normal map just represents a higher resolution version of what the vertex normals would be. This image should explain it: https://dl.dropboxusercontent.com/u/88635652/terrainnormals.png
At higher altitudes (especially from orbit) the normal mapping just makes the terrain look higher resolution as opposed to just giving it generic detail (like a detail texture) and thus has to be generated in the same way as the terrain vertices (more or less).
Although I don’t fully understand them, your and Flavien’s recommendations gave me some ideas to try out…
EDIT: Quickly testing what Flavien recommended I am still getting stripy artifacts, but the noisy-ness seems to have been reduced…
(By the way, it’s now apparent that we’ve been using different terms for the coordinate systems, so I’ll conform to yours for the sake of clarity)
If you use 3D inputs to your noise function, it will be continuous over all six faces. This applies for both vertices and normals. I sotre the vertex positions in tangent space, but calculate them using object-space (planet-centric) input coordinates to the noise functions. For vertices, there is enough precision to do so using 32-bit floats. I am not generating a normal map in the same way as you, however - and I suspect you are right that there wouldn’t be enough object-space precision for the inputs to the noise function if you’re generating a high-resolution normal map.
I’d be very interested in your solution to this, so please continue to share!
In my previous engine, I used per-vertex normals, with those normals being calculated through numerical derivation of the vertex positions. So the normals were continuous over the entire planet becuase the vertex positions were calculated using 3d inputs to the noise function. For details/bump-mapping, I applied a high-frequency ‘perturbation’ normal-map to these (interpolated) normals in the fragment shader, using a generic and tileable normal map (generic: since the map only described perturbations of the existing (vertex-interpolated) normals, it could be used on any terrain patch). This normal map was generated procedurally once per “biome”, so that different regions have deifferent-looking details, and also once for each LOD. The normal maps were the size of each patch (at each LOD), and thus mapped directly to the patch’s tangent-space UV coordinates. The quad-sphere’s corner and edge faces used unique special-cases of these ‘normal perturbation’ textures which blended seamlessly between adjacent faces - this solved the wrapping/tiling problem.
Admittedly this approach was not ideal - there were several issues I never properly addressed: 1) there were slight discontinuities in the normal map at borders between patches of different LOD. 2) In very flat areas, tiling of the normal map could be seen. 3) Transition between the different detail maps for separate biomes was handled by weighted blending, which had the effect of muting the details (The biomes were quite large, however, so it didn’t present much of an issue, but this itself probably would have been real show-stopper for more diverse or realistic terrains… But honestly it was ‘good enough’ at the time, and I didn’t want to spend much more time working this issue.
That was several years ago, and I’m reinterested in finding a good solution for this. I think that object-space inputs to normal map generation would produce very nice results: I think this would require using an analytically differentiable noise function (such as simplex noise), since numerically calculating the terrain’s derivative at the texel-scale would be very costly.
I will keep thinking about this and will report back if I come up with anything. Please continue to share your efforts with us as well! I’m consistently and pleasantly surprised by how many developers/code-monkeys participate in the Inovae forums. (Ysaneya’s game dev articles from 2006 introduced me to Infinity: TQFE, so perhaps that is true for others).
Yeah, absolutely, same here! His development blogs were amazing, and even more was what he came up with. He was what lead me to my interest in procedural content generation and the development in space/planet segments. thumbs-up
I received a nice post on google with regards to my TransitionManager (doing the transformation between the scaled spaces). Right now I apply a script (“TransitionManager”) to every gameobject, which checks the distance of the object to the player cam, and rescales and repositions the object at certain distances.
The hint was, and I guess thats probably common practice, to use colliders around the cameras to detect if an object leaves a certain area. And to rescale / reposition an object on a collision trigger event.
Nice approach I think. I am going to use that for the Transition between spaces, and also in order to detect objects for removal (if the largest collision box of the stellar space camera detects an “Exit”-Event).
This could be more efficient than my continues distance checks for removal of too far away objects, besides that it is a more beautiful approach. And it is more accurate when it comes to the point when a planet enters the local space area, as I am right now checking the center of the planet for this event, but by using the collision approach I can check the volume for the planet.
Should be done this week / this weekend.
That’s great! I bet unity uses an Octtree or some other spatially hierarchical scene graph to optimize collision detection. Might as well use what’s already built!
Am I doing this right?
![]()
Heh, looks good! I’ve been watching your progress in the personal projects thread.
Just a quick update - no code yet, but I’ve been considering using tri-planar texture mapping to apply a pre-rendered high detail normal map to the terrain. Not sure how visible the blending would be, particularly in areas with a higher speculation content, but the only way to know for sure is to try it out.
Again, the majority of the normal information would come from an analytical measuremrnt of terrain slopes (code is posted earlier in this thread), with a high detail pre rendered normal map blended with this information to add higher resolution details.
Only problem is that tri-planar mapping is expensive -three lookups per texel. I’m still exploring 3-d input to 2-D output parameterizations, although I know this is a much studied topic (cartography namely).
Hi,
I think I need your advice for my switch from TransformationManager-Scripts applied to each object to collider-cubes which are responsible to scale objects up or down for certain areas (see my last post).
I started to implement this, but I faced one topic where I am unsure how to use the cubes best. Maybe someone has an elegant idea, I got stuck a bit while thinking about it.
Goal:
- If an object enters (or is initiated) within the LocalSpace cube, the LocalSpace cube-collider has to make sure it is at the right localspace scale (1:1) and has applied the localspace layer (if not, scale up and change layer).
- If an object enters (or is initiated) with the ScaledSpace cube, ScaledSpace cube-collider has to make sure it is at the right scaledspace scale (1:10.000) and has applied the scaledspace layer (if not, scale up or down and change layer). BUT: it may not do so if the object is with localspace cube.
- If an object enters (or is initiated) with the StellarSpace cube, StellarSpace cube-collider has to make sure it is at the right stellarspace scale (1:1.000.000) and has applied the stellarspace layer (if not, scale down and change layer). BUT: it may not do so if the object is with the scaledspace cube.
The problem is: each cube has its own collider. As the stellarspace collider’s area matches with the areas of the scaledspace- and localspace collider areas (as they are within the stellarspace area), collider of the largest cube (stellarspace cube in this case) will notice an “Entered” and “Stays” trigger. But, it does not “know” if the object is e.g. within LocalSpace and might have the right layer (“localspace”) applied already, and needs not to be scaled down.
I attached an image to to show the problem. My idea to solve this was in implementing a check, if, when a larger collider is triggered, there is an intersection with the next inner collider before doing anything.
This first seemed like a working approach, however things are more complicated. Because, as I need scale up (enlarge) an object when it enters a space (e.g. from stellarspace to scalespace) and reposition it farer away (so that the player does not notice the change of scaling), It looks it can happen that the object leaves the bounds of the scaledspace-collidercube, will now be scaled down again due to the stellarspace-collidercube doesnt detect a collision of the object to the scaledspace-collidercube. And so the object starts to switch between colliders, being scaled up and down again. Damn.
Maybe all colliders should be of the same size at ~80.000 units? And just create one additional larger box that only does the deletion of objects very far away?
Hope that makes sense. Anyone has an idea how to solve this best?
Joerg,
For the 2nd part of your problem:
What if you used a set of ‘empty’ colliders for space-determination, which are unlinked from the actual planets?
So: for each planet/star, create a game object that only has a transform and collider. Put this in a layer so that it will be tested against your various space box colliders. When a space transition occurs on this ‘empty’ collider, it should notify its corresponding actual planet/star and adjust that object’s scale & transform accordingly (see code below : setCurrentSpace()). This way, the ‘empty’ collider is not re-scaled/re-positioned, so it won’t bounce between various spaces. The actual planet/star do not interact with the space box colliders.
edit: you’ll have precision issues unless you use doubles for the positions: not sure if Unity supports this though. But then again the precision issues probably wouldn’t matter unless a collider is right on the border between two spaces, in which case rounding errors might cause it to bounce back and forth. Preventing a collider from transitioning more than once every few seconds could help that, but admittedly that’s not an elegant solution.
To address the space-within-a-space:
For your ‘empty collider’ script, create 3 booleans, or use a bitmask (booleans are more clear):
boolean withinStellarSpace, withinScaledSpace, withinLocalSpace
and another boolean: boolean spaceChanged;
Next, when any of the spaces’ “OnTriggerEnter” or “OnTriggerExit” functions fire, change the appropriate "empty collider"s spaceChanged to true, and update its three booleans accordingly:
LocalSpace.OnEnter() -> withinLocalSpace = true
LocalSpace.OnExit() -> withinLocalSpace = false
ScaledSpace.OnEnter() -> withinScaledSpace = true
ScaledSpace.OnExit() -> withinScaledSpace = false
StellarSpace.OnEnter() -> withinStellarSpace = true
StellarSpace.OnExit() -> withinStellarSpace = false
Finally, in this object’s update() function, check if spaceChanged == true. If so:
if (withinLocalSpace) {
setCurrentSpace(local);
} else if (withinScaledSpace){
setCurrentSpace(scaled);
} else if (withinStellarSpace){
setCurrentSpace(stellar);
}
Not necessarily the most elegant solution, but it should work assuming I understand the problem correctly. Hope that helps!
At the end of it all, I’m not sure if Unity’s box collider approach would be faster than just checking the distance to each object each frame. Actually you don’t need to do it each frame - maybe once every 100 frames. It’s not like the timing of the transition is that critical. Also, if you ‘spread-out’ the checks, so that they weren’t all clustered at the 100th frame but spread out over this 100-frame ‘cycle’ of distance checks, you would reduce ‘spikes’ in performance.
Sometimes it maybe is good not to keep implementing one approach and keep thinking about it. Maybe. The approach that each space has its own collider area, I am almost certain, leads to problems in my approach that rescales and replaces objects. As I need to move an object “out of the right collider” (e.g. at upscaling from ScaledSpace to LocalSpace"), I think its hardly solvable that the next outer collider knows if the object has to be scaled down (as the object seriously has left e.g. LocalSpace), or if its already in the right scale even if its in the outer bounds of the corresponding collider. Using bools could work in the end, but right now I am not sure is this problem can be really handled this way.
Maybe another approach is better: Use only two colliders, one inner close to the camera that scales up (for all spaces/scales) if an objects enters this specific inner collider and one outer that scales down (for all spaces/scales) if an object exists this specific outer collider / removes an object if it is at smallest scale.
The benefit of it is, I only need to handle a one time / one frame fired enter or exit event. Should be much more resource friendly compared to three colliders per space, especially as I need the “Stays” event there called likely each frame by most of the objects, and synchronize between spaces.
Only challenge might be to set the size of the inner upscale and outer downscale bounds right, and define the scaling-/replacement factor of each space right.
But this could be a working alternative approach.
I am currently doing some refactoring and reimplementations of my Unity3D implementation, one topic is still the creation and management of space objects in a scene (see the above discussion of colliders, however I might get away from the collider strategy again and have every object being created completely manage itself for transition between spaces and deletion).
The other topic is the procedural planet generation, as I need to speed things up. I did some measurements on the performance of each function called while creating a plane before rendering with Unity3D.
CalculateVerticeData
Create initial vertice_pos array, vertices_uv array, triangles index of the plane (between [-1,1]).
PrepareNoiseData
Precalculate a noise array by use of the bounds of the plane. I calculate the 3D-coordinates for the noise calls by using the plane’s outer vector3 coordinates and using the texture resolution as step value to get the next 3D-coordinate.
PushToSphere
Parse the vertice_pos array and normalize each value so that we get from cube to sphere.
ApplyNoiseToMesh
Parse the vertice_pos array and apply the noise values from the noise array to the vertices. Also update the normals afterwards by doing “vertices_normals[index] = vertices_pos[index].normalized;”
PushToWorldSpace
Parse the vertice_pos array and psh the vertices to world space, away from [-1,1] range to the final range.
Also do the calculations to get from Patch-Aligned BB to AABB to be able to do the SpherevsAABB checks.
Results:
Elapsed CalculateVerticeData = 00:00:00.0025273
Elapsed PrepareNoiseData = 00:00:00.0116697
Elapsed PushToSphere = 00:00:00.0017177
Elapsed ApplyNoiseToMesh = 00:00:00.0023375
Elapsed PushToWorldSpace = 00:00:00.0038277
Elapsed CalculateVerticeData = 00:00:00.0009864
Elapsed PrepareNoiseData = 00:00:00.0043878
Elapsed PushToSphere = 00:00:00.0006643
Elapsed ApplyNoiseToMesh = 00:00:00.0008846
Elapsed PushToWorldSpace = 00:00:00.0014682
Elapsed CalculateVerticeData = 00:00:00.0009933
Elapsed PrepareNoiseData = 00:00:00.0043831
Elapsed PushToSphere = 00:00:00.0006910
Elapsed ApplyNoiseToMesh = 00:00:00.0008940
Elapsed PushToWorldSpace = 00:00:00.0014490
So two functions are catching the eye. The first one, not suprisingly, is PrepareNoiseData, where I do a combination of Simplex Noise (up to 4 octaves) and FastRidgedMultifractal while doing the measurement. By getting rid of FastRidgedMultifractal I things get a little better (~half the time required), however 4 octaves are not too much and things get more worse each time I get closer to the planet where more octaves are required.
Second function is PushToWorldSpace. Issue seems to be with the calculations to get from BB to AABB. Problem seems to be with lots of heavier function calls such as Mathf.Atan2, Mathf.Sign, Vector3.Dot, Vector3.Angle, Quaternion.AngleAxis to get from BB to AABB. As I basically want to stick with the SpherevsAABB approach, I might try to create and keep the AABB initially while creating the plane, and try to avoid the rotations of the BB in the end. However I want to skip this topic and first look at the real problem, the noise.
I understood that is generally faster to do the noise calulcations on the GPU. However I have some problems to understand the best approach to do that in Unity3D. My basic idea, and please correct me or lead me into the right direction, is that I
- Would have to stick with the initial creation of a plane on the CPU (my , so create the vertice_pos, vertice_normal, triangles indices within [-1,1] range. My CalculateVerticeData function.
- I would then skip the noise precalulcation and do the normalization (my PushToSphere function) as well as the PushToWorldSpace call to move everything out from [-1,1] range to the final size.
I’d then have an untextured sphere in its final size. The rest now must happen on the GPU (So I’d skip creating the texture on the CPU which also takes some time not mentioned in my measurement)? Is the idea not doing
Texture2D texture = new Texture2D(this.TEXTURE_WIDTH,this.TEXTURE_WIDTH);
Material newMat = new Material (Shader.Find("Standard"));
texture.SetPixels (this.textureArray);
texture.Apply ();
but doing everything in the shader?
Also I wonder if there is a way to precalculate a (heighmap) texture beforehand ob the GPU and pass it over to the CPU and the C# code to read the values from that texture to apply it to the vertices in the vertice_pos array? So in my case that I skip filling the noise array on the CPU but read within my ApplyNoiseToMesh the information from that heighmap texture from the GPU? From my point of understanding this would be necessary to still to for example collision detections.
Any hint or starting point very much appreciated, as this hopefully would signifcantly improve my implementation.
Gladly, I’llneed some time to answer your questions and form a complete example though, so check back this weekend.
Hi NavyFish, thank you very much beforehand, really!! Shader and how to use them is my biggest gap, so any hint is very much appreciated!! Thanks for your effort.
While putting the planet generation asided I started on asteroid generation, which works fine. I didnt use Unity’s LOD system but created an own one. Each asteroid checks its distance to its camera (the size of the asteroid is to be considered also, thats still to be done) and recalculates its mesh on demand. Each has 7 LOD levels. In the lower 4 ones I use an Icosphere for the creation. As the lowest icosphere has only 12 vertices which I think is a fairly low amount for a round object far away, and works quite well. I was first testing a plane (4 vertices) for the farest LOD, but the fact that I continuesly need to check and rotate the plane to always face the camera every several frames made it less usable in my tests.
So after the Icospheres with 0 up to 3 subdivisions depending on the LOD, I switch to a Cubesphere with non-shared vertices for better lightning. So the highest LOD then is made out of cubesphere with ~60.000 vertices.
For the deformation I first reposition the vertices by a Worley Noise (a cellular noise, for an organic structure) algorithm and additionally a Simplex Noise for some roughness on top.
The vertices are calculated by a background-thread (one per asteroid, iniated when a LOD changes)). Performance is pretty good, and an asteroid field of ~1000 visible asteroids is created pretty quick.
I now want, besides planet creation, rethink the positioning of objects. Right now I position suns and planets independent. Each type is positioned by simplex noise and a certain threshold on the noises result. I am going to change that so that only suns are positioned by simplex noise, and planets are afterwards created nearby suns in a certain orbit / distance. So then lightning should become easier then. As I do want to create not only asteroids fields in empty space, but also in ringformations around a planet, I need to check out how to calculate the placement of asteroids in a ring-formation around a planet/center coordinate.
Thats it for the moment. Really looking forward for your shader hint, NavyFish!
![]()
Quick question on this one -
Does that actually work? I think the normals must depend on surrounding vertices, not just the one vertex’s position.
Your asteroids look great! I’m impressed with how much you’ve accomplished. Very inspiring…
So, regarding Unity and generating terrain data in the shader: I must warn you, it’s hacky. There are many things that must be done to overcome certain limitations put in place by Unity. For the sake of demonstration, it’s good enough. but in terms of building a full-scale terrain generator that does GPGPU (General Purpose GPU) computing with Unity, I’m not yet sure I would recommend doing so. Specifically, there are several major constraints:
-Each terrain patch is limited to exactly 65,000 vertices. This equates to no more than 254254 vertices - but for efficiency (shader thread group alignment), each dimension is best a multiple of 32 (this may be different on the most modern of GPUs, but for DX11, a multiple of 32 is typically the best), so your patches end up being a max size of 224224. this is OK, but many cards could run more efficiently using larger ‘batches’, and it’s presently a hard-limit in Unity.
-(somewhat important) Unity must be run in Direct3D 11 mode to support ComputeShaders (which do the GPGPU). This is the problem with an API-agnostic engine like unity (i.e. it can run on OpenGL or D3D): they must cater to the ‘common ground’ between each API, and thus miss out on many of the latest features. OpenGL and D3D both support GPGPU via ComputeShader, but there are enough differences in the implementation that Unity has yet to write code for the OpenGL back-end. So this means your code will only run on Windows… 
-(more importantly) Unity’s renderer performs “batching”, where objects which use the same Shader and same material are executed within the same batch, thus reducing the amount of state changes on the graphics card. When making small changes in the material between several objects (i.e. changing just the ‘base’ color, but otherwise leaving the material alone), Unity supports client-side state caching via “MaterialPropertyBlocks” to gain much of the benefit of this caching. Unfortunately, Unity does not support Buffer handles as part of their MaterialPropertyBlock system (i.e. Block.SetBuffer()), even though there is really no difference between changing the buffer reference and changing the color. As a result, each individual terrain patch is rendered into its own Batch, even though each uses the exact same ‘base’ mesh, and exact same material.
-(most importantly) Unity currently provides no mechanism for asynchronously reading GPU data. I’m presently exploring writing a native plugin that will provide this kind of functionality (no one has yet done so), but until that time, trying to grab data from the GPU causes a pipeline stall. What this means is: you can generate your terrain on the GPU and render it just fine… but if you want to copy that data from the GPU’s memory back to the host (CPU) memory in order to perform physics calculations etc, you get a massive (up to 500 milliseconds) stall, where nothing is rendered. Thus, for the time being, anything generated on the GPU stays on the GPU - no querying terrain heights, performing collision checks, determining min/max terrain height for a patch, etc. Reading back any data causes the stall. This is very fixable - asynchronous reads. Basically you tell the GPU “Start preparing to copy this data to the host”, and then wait two frames, at which point it is available, and the read-back is thousands of times faster. So your data is a few frames late, but since you’ll probably be using a generated patch of terrain for at least ~300 frames, that’s not a big deal. Again, though, Unity doesn’t support this, so unless they implement it, or I or someone else creates a third-party plugin to do so, then doing terrain generation on the GPU with Unity is relegated to demonstrations only, because you really do need to have access to that terrain data.
I’m going to post this for now and start writing a basic summary of GPGPU, generating terrain on the Shader. If you’re still interested, I can go into details about how to do it in Unity, but keep all of the above limitations in mind. Also, this buys me time to fix my code, because I just realized I broke it horribly during a refactor and am having trouble putting the pieces back together (Why did I not make a back-up!! Argh!).