Looks nice, but I know what you mean there seems to be too much contrast going on here and there, probably due to the light, I dont know? Nice. IMHO you might want to try to combine different kinds of noise, and maybe add some kind of worley noise to especially form your hill tops and add some linear cut lines beside the regular perlin/simplex noise surface. BTW most important, the atmosphere looks beautiful in this and your previous screenshot!! Very well done.
Maybe I got that question wrong, but you should take care of your amplitute value when setting up e.g. FBM noise to make sure your noise doesnt got above your prefered maximum value or remains within the required range (of course once you start to sum different noise results you need additional code to make sure everything stays within your prefered range).
PS: Make sure you are aware of your prefered noise algorithm’s results value range, one implementation may stay between [0,+1] while the next implemenation uses [-1,+1], but your certainly already are aware of that as you already progressed very far when looking at your screens.
Congratulations!! What a frustrating little ‘bug’… very glad you’re able to move forward now! And none of us will have to suffer the same fate…
The reason I won’t do it that way is beacuse you’ll be having to calculate your vertex normals every single frame. By using a compute shader, I calculate the normals once, and store them with the patch. But I’m not doing per-pixel lighting, or bump-mapping either. Granted, with bump/normal mapping, I’ll still use the per-vertex normals, and then simply perturb them with a texture-lookup.
Regarding SV_DispatchThreadID… not sure, I only use SV_VertexID. Perhaps you need to use #ifdef SHADER_API_D3D11 ? Here’s the equivalent code from my surface shader:
Because while doing lets say a 64x64 texture, I could reuse all the noise results from the 32x32 mesh result and only calculate the missing coordinates inbetween. So in the end I could skip half of the noise computations for the texture, which was a good win when it came to cellular noise. Although you can do this kind of separation in two different shaders too. It was in one of the first tutorials I’ve looked upon on procedural planets (need to check which one it was) that you dont want to throw away your noise results never ever. Having the same noise computation twice gives me a bad feeling.
well what you can do is create a single compute shader in which you calculate all your patch related values into a 32 bit rgba texture map. The ‘rgb’ components of the texture contain the position of the vertices after getting spherized alongwith the height value to generate the terrain, and you can save the height value in ‘a’ the alpha component to be used later. Then in the vertex shader assign the position values from the texture’s rgb component and then in fragment shader compute the normal map from this same texture using the respective component values. In the vertex shader you will though need to use tex2Dlod instead of tex2D function. This is how I plan to do though i am still waiting for the weekend to actually implement it. But in the above method you will need only a single dispatch call per patch which will save multiple noise calls. let me know what do you think.
The reason I won’t do it that way is beacuse you’ll be having to calculate your vertex normals every single frame. By using a compute shader, I calculate the normals once, and store them with the patch. But I’m not doing per-pixel lighting, or bump-mapping either. Granted, with bump/normal mapping, I’ll still use the per-vertex normals, and then simply perturb them with a texture-lookup.
I agree, there were several problems with my approach that i just kept ignoring over my several attempts at creating a planet terrain. This thread helped me rectify those for which i am very thankful . And regarding normal calculation well there is a tradeoff, if you calculate normals once in the compute shader you will need multiple noise calls and also to store the normals where as if you calculate normals in pixel shader from the texture map which as i mentioned in my reply above, the texture contains position values in ‘rgb’ component and height value in ‘a’ component, first you wont need to store normals anywhere and the calculations will though be done every frame but it will not be noise calls rather texture lookups and a cross product. Now i will need to experiment with both the approaches and see what works better, doing things once is attractive but if we reduce runtime calculations enough we can be ok with a minute overhead.
It is very common for Shaders to include Normal or Bump-map input textures, the calculations are so trivial that the performance hit doesn’t even need to be considered.
What I am doing currently is to store the noise results (besides the vertex positions, normals etc) in the compute shaders output buffer, it is part of my Output struct. Simple because I prefer to have the original values and types, and not encode them into a texture. Not sure if this is common, its just what I prefer.
// The structure of the output computebuffer
struct OutputStruct
{
float4 position;
float3 normal;
float noise;
float3 patchCenter;
};
I write the noise value in my first kernel, then from there on this gives me all the freedom to pass the original noise values around, to another compute shader or kernel, or to a vertex shader or surface shader. This works like a charm, right now I pass this output buffer into another kernel, and afterwards I read this value in the vertex shader (and do nothing with it, only for testing) and in the surface shader (for coloring, although this will be changed later on when I move from noise to terrain type (which will also be part of the output struct, stored maybe as something like an int) for coloring).
void surf(Input IN, inout SurfaceOutputStandard o)
{
fixed4 terrainColor;
if (IN.noise <= 0.0) {
terrainColor = fixed4(0.0, 0.2 +IN.noise/10 , 1.0 + IN.noise/5, 1.0); // Blue
}
else ....
}
My plan is to keep especially the noise results in the buffer as long as I can, so that I can reuse the values when I split a plane (half the noise computations as I reuse the parent nodes noise values from the buffer) and no noise computations at all at a merge as I can reuse all the children’s noise. Havent tryied this strategy on the GPU with buffers, so not sure if this will work. @NavyFish: This is the second reason why I stored my noise values in the CPU implementation.
But I admit, as I havent dealt with texturing at all until now in shaders, there might be the point where it is advisable to store or create a texture earlier in the process, I dont know, I’ll revisit these latest posts when I get to that point. To find out is part of the voyage
Normal calculation in second kernel is now included, by checking the vertex buffer from the first kernel. Really straightforward. Whats left is special handling of the plane’s side borders, where information of the surrounding vertices is missing (or better: in another plane’s buffer). I need to check the options, currently I am thinking to do extra noise calls for these edgecases, which would be 224*2 calls (as for each vertex I check the next top and right vertex), which i find acceptable at a current amount of 224x224. Or maybe an approximation, we’ll se.
My solution was to create 226x226 vertices with the first kernel. The 2nd kernel then had all the information it needed to calculate 224x224 normals. It was also responsible for copying the appropriate 224x224 vertex positions from the first ‘oversized’ buffer into a new, 224x224 buffer. It was a straightforward approach, but I didn’t profile it to compare against what you’re suggesting. The nice thing with creating these extra verts is that you don’t have to replicate your noise function code into the 2nd kernel, which would require you to always keep it up to date whenever the original function changes (though that might not be an issue if both kernels are in the same code file). Just a thought.
Sure the performance hit of a texture lookup is minimal. But @yuneeb90 is suggesting recalculating the normals every frame. That will be much more expensive than a texture lookup
Yes it can totally be done, but the performance impact is something you’ll have to test and evaluate for your own application.
Also, I think there’s a misunderstanding here - if you store vertex data (be it in a texture or Buffer, it doesn’t really matter, although for this application I find Buffers much more flexible. Textures are good if you’re going to be doing a lot of spatial filtering of data, however) - then you don’t need to do any noise calls when calculating the normals (assuming you have data for the 4 neighboring vertices). The equation for doing so is posted earlier in this thread.
The problem with it is that there’s no way to specify a seed, and so I have to resort to using input offsets. this is fine for now but once I expand to multiple planets, will quickly give me precision errors. So I’m looking to either modify this implementation with a specifiable seed, or move on to something else.
@cybercritic:
Very nice. I like that you have big continents formations and not small ones randomly spreaded across the ocean. Looks very natural!
On the CPU I’ve been using two types of additional noise functions on top (or better: below) my Simplex Noise. Worley Noise or Voronoi Noise, so cellular noise representatives. And Ridged Multifractal Noise. So the process was to first pass the original spherical vertex positions into the RMf or Worley Noise algorithm (on low octaves) and then secondly pass the displaced vertex positions into the Simplex Noise (on the required octaves based on LOD).
I’ve been experimenting in using both RMf and Worley Noise algorithm to let it define the raw formation of planetary continents, while the Simplex Noise algorithm uses this raw first displacement as a seed and refines these. So a low octave the first algorithsm was absolutely sufficient. I didnt need to care about Simplex Noise seeds anymore then as this was already going on before the Simplex Noise call. So maybe my strategy is similar to yours, NavyFish, as my seed is the displacement of the Simplex Noise’s input.
Unfurtonately I’ve only been using a CPU implementation yet. If you google for Worley/Voronoi/Cellular Noise you have a few hits, but I’ve found scrawks the most promising. So my plan is to review the Worley/Voronoi implementation by scrawk in his article “Improved voronoi noise in Unity”. There is an example Unity project where you have the required libs (ImprovedVoronoiNoise3D.cginc). http://scrawkblog.com/category/procedural-noise/
Ok so i have been quite busy with trying to implement per pixel lighting in my planet renderer, Initially I had a very hard time trying to calculate normal map wrapped around a planet without using tangent, binormal and normal vectors. But in the end i ended up calculating these TBN vectors and then calculating normal values from a height map, which worked perfect, though my algo is not perfect, its still work in progress related to correct normal maps per patch as right now there are seams around patch edges and my procedural normal map is per vertex resolution,so i added an additional bump map texture to see if it looks right and it does as you can see in the pics below,
further more my planet is 13 levels deep but i tried to go till 18 levels deep and just after i guess 14th or 15th level i started to get into floating point precision issues. Now I just want to know regarding over coming floating precision problem, are doubles the best alternative to it? because there are some performance related issues (i havent tested them) but i am thinking that since its easier I should go with it for making my planet renderer future proof as gpus will advance from here onwards and doubles may soon become mainstream?
@montify your terrain looks awesome, nice work there. but regarding ocean rendering, is there any advantage to using projection grids in place of simple quadtree based lod algorithm in terms of performance, if i understood the projective grid concept correctly, i mean you can just create a lod sphere slicing through the planet just like the terrain? Plus as can be noticed in Inovae’s planet with ocean videos, if you move far away from the surface of the planet you will notice the terrain topology changing a little bit especially if you look at the rings video below the changes in topology on moving towards or away from the planets, can projection grid solve this problem?
Very first implementation of quadtree terrain splits. I am currently trying to figure out how to set the spacing and scale values after each split for the child nodes. The level 0 node plane starts with
so it fills one complete side from -1 to +1 in cubespace
I would have guessed that for each quadtree division I would simply have to split spacing by 2 for the children, but obviously things are not that easy (children planes are way too small). For a split until level 2 the right division value is roughly ~1.32. Anyway need to rethink about that what logically would be the right change to the spacing at each quadtree division. But anyway, got my first more detailed shader only surface running with 224x224 planes and level 2.
Geforce GTX 570. Currently its running well when simply flying around in that scene, but since I havent added any update of planes during runtime and also no LOD (especially NavyFish’s LODSphere approach) from my old implementation I guess its too early to tell.
But I think I might fall back to maybe 128x128 planes later (and split earlier in the visible area) to avoid too much detail in sections that are not directly in front of the observer.
EDIT:
Got the spacing value working while splitting, now I can continue to add details… well… two levels more (level 4) and with 128x128 planes I am at ~50M triangles, as expected my graphic card is not amused . Guess its time to implement the LODSphere algorithm next
PS: Strange circular artefacts to deal with now that details occour.