Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Planet texturing #4554

Draft
wants to merge 50 commits into
base: master
Choose a base branch
from
Draft

Conversation

fluffyfreak
Copy link
Contributor

@fluffyfreak fluffyfreak commented Mar 5, 2019

NB: This is hilariosuly WIP but there's reasons for making it a draft PR now.

Add texturing to planets based on a Look-Up-Table (aka LUT) and Texture Arrays (aka Atlas)

Here are two shots of Mars with the current code for example:
snap
screenshot-20190305-222720

Work still to do:

  • Replace hardcoded textures with per-planet-type LUT and unique textures
  • Replace the Gas Giant texture generation with shader ported code
  • Remove all of the GetColor system from Terrain classes (maybe re-use colourisation if viable)
  • See if Gas Giant HueShift from gen-gas-giant-colour.frag shader can be used to add variety
  • Split Star generation/rendering into it's own thing just like I did for Gas Giants
  • Get textures, cc-by-sa / created / etc, to replace the test ones I "found"
  • Document the height sampling madness a lot
  • Look into using Git LFS for storing the textures
  • Make this a longer list...

Questions, suggestions, thrashing and screaming all welcome.

The textures used for this test so anyone can have a go.
Contained in the ZIP file is a folder with textures, extract it into /data/textures/ so that you have /data/textures/terrain/
terrain.zip

<impaktor> So how many textures would one need to create an infinite universe?
<impaktor> Something there I don't understand, unless textures are randomly generated.... which I guess counteracts the idea of using a texture.
<fluffyfreak> a finite number of textures, but with a variety of combinations, plus there's the possibility of some hue shifting at runtime
<fluffyfreak> basically you've got a pool of textures... lets say 128 of them in total which is about 80MiB of textures given the sizes etc used so far
<fluffyfreak> you pick upto 16 for a single planet
<fluffyfreak> and those are chosen/blended in the terrain shader using a LUT table
<impaktor> OK.
<fluffyfreak> we may want to do some stuff like use the Git LFS stuff to manage these textures

@fluffyfreak fluffyfreak self-assigned this Mar 5, 2019
@sturnclaw
Copy link
Member

Oh hey, it actually looks like a planet and not a giant ball of vomit. Imagine that.

In other news, I could not be happier that this is finally getting done. For suggestions, I'd throw in distance-dependent detail texturing, e.g. having a high-res texture blend in when you're close to the ground. That'd reduce the tiling-pattern effect of having a higher-res texture at long distances, and mitigate the previous problem of textures being 1:1 pixels to meters.

@bszlrd
Copy link
Contributor

bszlrd commented Mar 6, 2019

Neat!
Could you shoot the textures towards me? I want to see, how complex they are, and want to take a shot on them. I'd prefer having custom made in the end.

@fluffyfreak
Copy link
Contributor Author

@nozmajner I've added a zip of the textures, they're currently horrible :)

They're all 1024x1024 and DDS DXT1 compressed, I think that there might need to be some other changes in the future such as adding specular & normal map support but that starts to get very texture heavy so for now they're just diffuse. One option might be to bake the specular data into the alpha channel, that will need some thought and possibly custom art process or code tooling.

There are 16 textures + 1 LUT, that plus the two detail texture maps that were already there bring the total number of texture channels used to 19 textures total.

It doesn't have to be that many, we could have just two or three for a planet (barren, airless... like the Moon for example) but for now it's 16 total for a planet.

The LUT is made of 16 shades, starting at black through to 255.

NB: I need to double check this next part but I think that it's correct ;)
The origin is in the TOP LEFT.
Height runs vertically (Y axis), so lowest at the top of theimage, max height at the bottom.
The horizontal (X axis) is for the slope, so flat is on the left, vertical surfaces are on the right. Very few surfaces actually get to vertical ingame it seems.

@fluffyfreak
Copy link
Contributor Author

Well that took a LOT longer than I'd hoped.
Ported over the shader gas giant stuff to CPU, removed all of the crazy templated GetColor implementations, discovered some stuff on the way through so random other changes happened.

There's still a bug when building Saturns texture that I cannot claim to even begin to understand yet but I'll figure it out eventually.

@impaktor
Copy link
Member

Nice to see you back!

Let us know when you need testing

@fluffyfreak
Copy link
Contributor Author

Having used LFS at work on 2 projects now I think I can safely say... I'd really rather use a submodule or another repository instead. LFS works but we've had issues with it.

@sturnclaw
Copy link
Member

sturnclaw commented May 18, 2019

Haven't tested the gas giants yet (and I just realized I haven't tested the new textures), but planet texturing appears to be improved. I'm noticing a few issues:

Screenshot from 2019-05-18 10-19-29

You can see in the upper right of this screenshot that there's noticable pop-in where two patches have different UV scale instead of smoothly blending - this might only be a problem with the existing terrain rendering, but ideally we want a consistent UV scaling that blends in the 'detail' UV scale smoothly over distance instead of a binary switch per-patch.

EDIT: haven't tried the new textures on Earth, apparently vertex-based coloration is a fallback or something.

@fluffyfreak
Copy link
Contributor Author

@Web-eWorks that's the existing terrain, it's vertex based colouring, there's already a couple of detail textures.

What does this have to do with this PR?

@sturnclaw
Copy link
Member

What does this have to do with this PR?

I pulled the PR and tested it (albeit accidentally without the new texture files) and wanted to point out the issues I saw under what I thought was the new texturing method... On taking a second look, I apparently forgot to change branches before compiling. Please disregard.

@sturnclaw
Copy link
Member

Something you might want to look into (assuming you haven't already) is this post on derivative-based surface normals - from the looks of it, it could help improve the quality of terrain texturing even further than this PR already does.

@fluffyfreak
Copy link
Contributor Author

@Web-eWorks

fluffyfreak: ...you do realize glsl's mix() function blends two textures together without affecting the resulting luminance, right? trying to finish the terrain texturing PR and the color = (s1 * s2) * 2.0; bit threw me for a loop there just use mix(s1, s2, 0.5) and it doesn't darken the resulting texture at all"

yes, I wasn't expecting anyone to try and contribute to the branch so things aren't as well documented as they should be!
mix is an option but I was porting the code from elsewhere
originally it was from https://forum.unity.com/threads/improved-terrain-texture-tiling.116509/
but it might also be the cause of the visible texture seams when close to the surface

doesn't help that the default LUT doesn't use texture slot 0 for some things

it's all work in progress, the LUT is supposed to be one of a selection of LUTs, and this one isn't very good yet, just for testing

There are a couple of low-effort things I want to improve about planet texturing
First of all, it should be absolutely possible to define e.g. only 4 textures for a planet instead of needing to fill out the giant 16-texture JSON file
pass the number of textures in the array as a uniform or use GLSL's textureSize(texArray).z to figure out the multiplier

yes, it's supposed to be variable eventually

Secondly, if I'm right in thinking that our LUT starts at top-left for flat sea-level, I'd recommend changing that around

probably should, just used it as-is to get it working

we should also do some form of multi-tap sampling and blend different textures together
not sure the best way to do that, but transitions between textures should absolutely be much softer than they are new
because LUTs have discontiguous values (e.g. you could tap twice and get 1 and 15) it's probably better to blend the resulting texture values, but you're looking at triple the texture bandwidth in some cases (especially with displacement maps et. al.)

splatting would be ideal I think, use N textures with weighting and blend between them, not figured out how yet

for the record, our current shader code is an absolute mess and I really really really really really want to facedesk every time I read it
don't statically #if on whether or not textures are bound to the material, please!
If it's a material that needs textures, bind our unknown.png to samplers which don't have assigned textures
if it doesn't need textures, don't provide slots for them in the first place
but above all, don't complicate the shader any further!

this is just dealing with how it works currently so as not to break things, hopefully it gets simpler because there's only one code path after this is done and it will always use a texture, but development is messy

We need some way of realistically varying the coloration of planets. At the moment, I understand that's what the different color fractal jsons are for, and the idea behind setting up alternate textures based on metallicity, etc.

No Man's Sky did something interesting with this, they defined a palette for each world, the textures were palettised and the palette was simply replaced with this worlds new palette!

I stalled out on loading array sub-textures from PNG last time, though it was more because TextureBuilder is kind of internally an abomination

There's other formats which support texture arrays but fuck trying to use anything standard from DDS, and it has to be pre-generated DDS due to Intel DDS generation issues on some linux versions with some GPUs

When close to the surface of the planet there are visible texture seams; it appears there's an issue with uv scale of our "close" texture sampling

yeah, it's got bugs, lots of bugs

regarding where to source textures, cc0textures.com looks like a wonderful resource; they're the GameTextures of the open-source world

Any source that suits our needs is good by me, I'm just using some textures from... actually I don't even remember but they might not be open source!

re: git LFS, I'm glad to see you've seen the light with it; I don't think it's a good fit for pioneer either

ugh, the project I'm on that uses it drives me insane!

fluffyfreak: planet texturing height sampling is based on sea-level reference height, right?
How are you encoding that into 0..1 uv space? What's the scale / metric?

horribly, if you look in GeoSphere::SetUpMaterials you'll see at the bottom a height sampling loop.
It goes through and finds approximate min/max heights for the world, then in GeoPatch::UpdateVBOs this is used to normalise(ish) the height and puts it into the second uv slot of the vertex

@sturnclaw
Copy link
Member

@fluffyfreak: I've left quite a few links to implementation papers in IRC, most of which are from Frostbite. I've taken another stab at UV scale, and I'm currently doing debug visualizations to track down a few bugs.


Here are the mentioned debug visualizations, with a bit of commentary for scale.

@The-EG
Copy link
Contributor

The-EG commented Jun 19, 2020

I'm happy to see this, the stations always seemed good to me but landing on a planet always felt wrong.
Pioneer feels very lonely. I think this is right for spaceflight, it should be lonely...landing at a space station feels like you are coming back to an island of civilization, which I also think is right. But landing at a city really feels like I'm just landing at a remote fuel depot with a computer terminal.

This makes me think back to MS Flight Sim 5 / 95; even with the textures turned off (a 386 with 4MB couldn't really handle them!), you still felt like you were flying over different terrain. A city (light grayish) stretched out around you with roads (dark gray). And you could tell when the terrain changed due to changes (albeit abrupt) in color: dark green (wooded), light green (grassy plains), brown (barren, sandy), white (snow), etc. Textures added to that effect: cities had rooftops and roads, wooded areas (sort of) looked like tree canopies, etc.

I get the impression that Cydonia is supposed to be a large (maybe even huge?) settlement. But, looking at it in game I feel like I'm only seeing the downtown/industrial area where the spaceport is, and that there must be another 80% of the city somewhere:
image
I think simple texturing could go a long, long way there. I think I'd rather see more texturing than modeled buildings!

Another thought that just occurred to me: if you do end up with textures that are to be areas around cities/populated areas, can they have areas pixels that are lit (maybe not specifically give off light, but are visible as the same color and shade regardless of lighting)? I would imagine that would be a layer/map on top of the texture.
Another thing that's always bothered me is flying near a populated planet (ie Earth) and it's completely dark...and landing in a large city and there's only a few lights coming from the spaceport and modeled buildings.

@The-EG
Copy link
Contributor

The-EG commented Jun 26, 2020

I played with this some this evening....it's cool!

It looks like the LUT isn't actually getting loaded and it's using unknown.png instead (which makes for an interesting LUT). I had to change the LUT entry in the terrain JSON to the path of the png file including the extension to get it to work (ie. textures/terrain/terrainLUT.png).

Some simple textures I came up with playing around:
image

I haven't figured out the LUT enough to get mountains/snow showing properly yet, but it's exciting as is.

Some things I wasn't expecting:
I had to create a water texture and make sure that 0,0 in the LUT was pointing to it.
The Y axis on the LUT isn't really intuative. The x axis seems to work like I'd think, but the scale for y seems weird or insanely huge. What is the max height?

I also had to increase the LUT size from 256x256 to 512x512 to get something workable at the coast. Otherwise a single pixel for 'beach' would run from the water almost up to L.A. This is at 512 with a single pixel which is much more reasonable, I think (near L.A. on Earth):
image

I'm not real sure why that lighter texture is showing black edges. It doesn't actually have that in the texture...and the other textures aren't doing that...

Very cool stuff though.

edit: messed around with the LUT some more...Mars:
image

And some rocky textures:
image

@The-EG
Copy link
Contributor

The-EG commented Jun 28, 2020

In case anyone else wants to mess with this, unzip this into pioneer/data which will overwrite some of the files from this PR and the zip that fluffyfreak attached above:
terrain textures.zip

I think it's a decent start for EarthLikeHeightMapped:
image
image

The textures aren't great, but I created them from scratch so there are no issues with licenses. And, more importantly, they can serve as placeholders until something better is created.

I approached this by defining terrain types and creating textures for those types: water, light-grass, green-brush, forest, snow and stone (mountains). So in this setup, Earth and Mars are currently using 7 layers of the 16 available.
With this approach, we can create a library of terrain types, and profiles can be built by choosing the applicable types for the type of planet/body.

With that, the 'atlas' for a profile contains a layer for each type of terrain. The order doesn't strictly matter, but the LUT will reference the layers by index:

...
   "atlas" : [
      {
         "description" : "sand / beach",
         "textures" : [
            {
               "texture" : "lightsand.dds",
               ...
            }
         ]
      },
      {
         "description" : "grassy plains",
         "textures" : [
            {
               "texture" : "lightgrass.dds",
               ...
            }
         ]
      },

As described above, the LUT texture maps the terrain's height (y) and slope (x) to the layer. It looks like only the red channel is used, so I created a reference table like this to help when modifying the LUT:

Layer Red (0 / 255) Earthlike
0 0.000 sand
1 17.000 grassy
2 34.000 brush
3 51.000 forest
4 68.000 stone
5 85.000 snow
6 102.000 water
7 119.000  
8 136.000  
9 153.000  
10 170.000  
11 187.000  
12 204.000  
13 221.000  
14 238.000  
15 255.000  

It's important to note that even though the profile only has 7 layers, you still index the LUT as if there were 16 (obviously don't use the ones that don't exist).
My earthlikeLUT.png looks like this (can definitely be improved):
image

The bright red dot in the top left is water (last layer, it's the brightest). The basic idea is that as slope increases (farther right), less vegetation can grow, so it goes from forest, to brush, to grass and then finally to stone. Similar for height (top to bottom): there's water at sea level, followed by a little bit of sand, grass, brush, forest, then stone and finally snow.

@fluffyfreak
Copy link
Contributor Author

fluffyfreak commented Jun 30, 2020

@The-EG this is exactly what I HOPED would happen with this PR, I've really struggled to pull togethher the textures and visuals but you've done a great job!

@The-EG
Copy link
Contributor

The-EG commented Jul 1, 2020

@fluffyfreak Thanks! My intent is that this might help get others started with this.

I also created 2 test profiles, one for height and one for slope, that show how the terrain is actually mapped out and allows one to see what's interesting about the terrain. Here's the height (left) and slope (right) test for the moon (red is min , green is max):
image

So, most of the interesting variation is within the height. The changes in slope mostly occur within the first layer (so using slope won't in the LUT won't do much). To get something interesting looking (for the moon at least), we'll probably need at least 7-8 textures of varying shades, most likely darker shades to lower heights, with most of the variation centered towards the max height.

A similar approach might work for something like Pluto (Rock) (this is the height test, red=min, green=max):
image
I think something with different colors (tan, pinkish, blue-gray) could actually look interesting! (not like pluto probably, but interesting)

@bszlrd
Copy link
Contributor

bszlrd commented Jul 2, 2020

@The-EG The ctrl+F10 shortcut might be handy for this, it views the selected nav target, so you don't need to fly to it. Works for planets and ships as well.
image
You can even play with the planet settings if they aren't using height maps. Handy for custom system making.

@impaktor
Copy link
Member

impaktor commented Jul 2, 2020

Ctrl+f10

I've added it to my very ugly first draft of development tricks/tools that have, so far, been un-documented:
https://pioneerwiki.com/wiki/Development_Tools#Debug

(please add/say if there's any more cool stuff missing from there that is only "documented" in the source code itself)

@The-EG
Copy link
Contributor

The-EG commented Jul 3, 2020

Here are the test profiles I created. Just replace the profile you want to test out (ie. EarthLikeHeightMapped.json) with one of the profiles (testHeight.json or testSlope.json):
test_profiles.zip

@The-EG
Copy link
Contributor

The-EG commented Jul 4, 2020

Also, I put together a page on the Wiki showing how to create some basic textures from scratch: https://pioneerwiki.com/wiki/Creating_Simple_Pattern_Textures_in_GIMP

@The-EG
Copy link
Contributor

The-EG commented Sep 21, 2020

In case it's helpful to anyone: here's a branch where I was able to get the conflicts resolved and merged with master a month or two ago. I have no idea if my choices on the conflicts were right, but it did compile, run and display the planet texturing stuff properly.

https://github.com/The-EG/pioneer/tree/planet-textures

@sturnclaw
Copy link
Member

@The-EG thank you for the rebased branch; I wound up rebasing this one instead (and did a fair amount of cleanup along the way). I've been doing some exploratory work into texture blending, so far I have this:

slope_blending

In this image, a transition between horizontal LUT texels driven by slope is shown as a transition from bright red to black; you can think of it as a contour map as used in orienteering, except it shows the change in slope, not in height. The green indicates (artificially scaled by 8x) actual slope value.

Once I get blending between two different textures working correctly, I'm going to merge this branch into a work branch here on the main repository for you, myself, and @zesterer to work on terrain generation and rendering; I'd like to be able to replace all existing generation and texturing code before we merge it into master, but also be able to collaborate.

@sturnclaw
Copy link
Member

HEADS UP: this branch is going to be force-pushed with the newly rebased branch. To make up for the work you'll have to do locally, have some nice terrain texture blending:
blending
blending2

I think we're almost to the stage where we can merge this to a work branch and start building out the "procedural" aspect of the texturing; I'll take a look at the TODO before evaluating that, so please let me know if there's anything left to implement or fix @fluffyfreak!

mwerle and others added 22 commits November 29, 2024 22:09
Make all string representations of the views follow the same pattern, and
give views which did not have a name a name.

Following this, use that string representation in the Lua side as well
instead of using a separate string. This allows for unique and easy
referencing of views across the entire codebsae using 'grep' or
Visual Studio Code's search function.

This also allowed for some simplification of getting/setting views.
Use the new 'onViewChanged' event parameters to only add/remove the radar
input frame if the view changes to/from "WorldView".
 - Replace GetSamples() with GetMusicFiles().
MusicEvent differs from Event by only one line and is replaced by an
Event::PlayMusic method.
This cleans up lots of VolumeAnimate/SetOp calls and allows for future
optimizations (such as eliminating one mutex lock operation).
Consolidating all the stop/play/fade operations will allow the number of
mutex locks to be reduced in the future.
Fixing the icons.svg I provided for the radar PR, I put the new icons for that onto an older version of the file.
The nice thing is that the free space is similar in both, so there's no need to do anything in the theme, if I'm reading it correct.
By placing all of the radar drawing routines into a window, the mouse
wheel is captured and is not passed back to the world view.

The original implementation failed to get this to work properly as the
wrong API was used for setting the center of the 3D radar. Using
'setCursorScreenPops()' instead of 'setCursorPos()' has the 3D radar
background showing up in the correct location even when placed inside a
window.
Radar buttons are now aligned properly with the other buttons on the
screen.

Also fix the 2D radar being slightly clipped by taking into account its
line thickness.
Use the zoom mode indicator to also toggle between automatic and manual
zoom modes for the 3D radar.
- Remove color from GeoSphere/Patch/Jobs/etc
- Add support for UV1 attribute
- Initial JSON support for terrains
Get the LUT and texture names from the terrain colours config
- wide impacts
- remove EnableGPUJobs config option, everything supports shaders!
- remove GetColor from all terrain colour templates
- fix GasGiant and GeoPatch jobs
- add extra textures
- add a_uv1
- add texture sampling code
TextureBuilder Array mangles the filenames that are passed in if vector isn't included. Bizarre bug because it compiles just fine.
@fluffyfreak
Copy link
Contributor Author

Urgh, I'd ask what I fucked up with that commit history but it's after midnight and I'm going to bed.
I built this atop #5979 because I realised that I needed those changes as that's quite a refactor of the GeoPatch/SPhere code etc. However I appear to have messed that up 🤷

Anyway, hopefully some Git wizard can help me fix that later with rebasing or something magical involving history rewriting.

It's compiles, builds, runs, it's generally glorious!
Or at least it's as good as it was several years ago and ready for fresh eyes to look at it again.

I've attached a zip with the original textures and LUT, plus the lovely work that @The-EG did.
terrain.zip

@fluffyfreak
Copy link
Contributor Author

It's probably because of commit [1924465] which I did and then brought in the #5979 changes 🤦 anyway, problem for another day

- delete all TerrainColorFractal classes
- move names to enum, string and surface effect lookups
- rework InstanceTerrain method
@fluffyfreak
Copy link
Contributor Author

The removal of TerrainColorFractal, and the deletion of the vector3d color arrays reduces the size of the Terrain class from 2800 bytes to 512.

@fluffyfreak
Copy link
Contributor Author

fluffyfreak commented Nov 30, 2024

I need to work out how to actually // do the choosing... as described on line 633 of GeoSphere.cpp so that I can support texture selection from variants based on temperature, life, atmosphere etc.

Suggestions welcome.

Also I'm not sure if the choice of slope & height is really useful for the UV coordinates of the LUT texture. They can be based on anything and I went with them as it seemed logical at the time. However as people have pointed out above slope isn't great and perhaps we could derive some other value to range from 0..1 to replace it?

Maybe the pairing could be height and normalised(slope * avg-temperature)??? it's really about making the 2 axes we have to feed into the UV LUT lookup more useful.

Again suggestions welcome as I'm making this up as I go along.

@bszlrd more textures will be very welcome, but I don't have a single coherent answer for what's needed yet thanks 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants