Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Chat / [BUG?] Terrain's Meshes UV Bug with CreateObjectFromHeightMap() command.

Author
Message
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 31st Dec 2017 02:36 Edited at: 31st Dec 2017 02:39
Hello all

I'm actually working on a 3D Map Editor in Tier1. The idea is to be able to paint over the terrain with textures in a good resolution.

So i wanted to create a Splitted Terrain ( with the CreateObjectFromHeightMap() command) and reassign a HighRes texture on each mesh.

When i use only 1 split, there is no problem ... there is only one mesh and everything is working well.

But when i use multiple meshes (Split parameter) and assign a splitted texture to them, this doesn't look correct (it seems to be an UV Problem) :

I have attached a simple example project of the bug which splits the main texture map in 4 parts and assign them to 4 sub-meshes of a splitted terrain.

With WrapMode enabled on sub textures :



With WrapMode disabled on sub textures :



I think my UV calculations are correct so .. if anyone has an idea to make it work perfectly (with 4 sub-meshes and more ...)

Thanks in advance for you suggestions

Attachments

Login to view attachments
Jack
13
Years of Service
User Offline
Joined: 4th Oct 2004
Location: [Germany]
Posted: 31st Dec 2017 03:24 Edited at: 31st Dec 2017 03:37
This is a common "feature", caused by OpenGL. It happens, if a texture gets scaled down, so there will be an interpolation between the pixels of each side, resulting in a strip at the borders.

I use a custom shader in order to get rid of it.
The method I use is to scale the UV map *0.998, this works in some chases, but there should be better methods out there,
I just had not enough time to spare on this problem.
As far I know, I had something similar solved by changing the interpolation method of the shader.

Why do you need texture WrapMode on this segments anyway?
Do you plan to add detail textures?


I had a thread with old terrain shading code, maybe you find something useful here:
https://forum.thegamecreators.com/thread/218835

BTW, nice Work! Keep us updated.
Do you plan to support procedual generated infinite worlds?

[/url]
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 1st Jan 2018 03:20
Textures are not scaled down in this example. Only splitted. I've checked the generated splitted images and re-joined them, they are perfect at pixel precision.

I used the wrapmode only to demonstrate the problem more visibly.

And yes there is a Detail map support and custom object creation (OBJ files only for the moment with MTL support ... you click on the obj file in my custom directory browser, and it takes all the textures needed automatically and apply them following the terrain if needed)

Actually i've done the realtime terrain modeler, terrain painter, object creation and edition (move/rotate/scale). for procedural world it's not the aim for the moment .

But this problem of UV in the terrain split meshes is VERY annoying i can't find a workaround which works.
MadBit
AGK Tool Maker
8
Years of Service
User Offline
Joined: 25th Jun 2009
Location: Germany
Posted: 1st Jan 2018 13:07
if I remember correctly. you must to calculate half pixels in the texture caculation. For a texture size of 100x100 pixels, pixel 0,0 would not be 0.0,0.0 but 0.005,0.005.
Share your knowledge. It\'s a way to achieve immortality. (Tenzin Gyatso)
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 1st Jan 2018 18:20
Thanks MadBit but it doesn't seem to fix the problem ... i can almost have a good result with an offset of 0.0035 (but not perfect) but when i try with more Splitted than 2 parts it's strange again ....



Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 1st Jan 2018 19:48 Edited at: 1st Jan 2018 20:25
Ive tried this and not really had the problem you having



As Madbit said above....You can use SetObjectMeshUVOffset() to try to solve it. This is key if a low resolution texture is going on a high res heightmap

The key is to move the UV's by 0.5pixels = 1/TextureWidth - so if your texture is 256x256 you need to offset by -0.00390625 so that each edge vertex point sits in the middle of a pixel

Are your textures a power of 2 size and is your heightmap also a power of 2??

EDIT: Changed the attached image so it wasnt so large and didnt take everyone long to download
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 1st Jan 2018 20:18
i'm using the CreateObjectFromHeightMap() command which allows to "split' the terrain into meshes. In this case, UV are calculated for one big TextureMap. So each mesh must be offset and scaled to be clamp between 0 and 1

The project zip is attached on first post ...
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 1st Jan 2018 20:23
Im doing the same above with a 2x2 split and 4 textures

I think you just need to scale and offset your UV values as I did above. The offset needs to include the half pixel offset so that the edges dont bleed from the opposite side of the texture. One of the AppGameKit tutorials/guides explains it.
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 1st Jan 2018 20:59
yes, it works for 2x2 with 4 textures ... but not with more split.

I'm still searching the good correction formulas ...
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 3rd Jan 2018 12:33 Edited at: 3rd Jan 2018 12:48
Wow ... it's a real big problem for me ... i'm not able to find the correct formula to Scale and Offset UVs to make it work perfectly with multiple Terrain Meshes ...

It would have been cool to be able to rewrite UVs over each Mesh from 0 to 1 ... lol

is anyone can help ? (project attached in first post)
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 5th Jan 2018 00:51 Edited at: 5th Jan 2018 00:56
i'm just going crazy ... grrrr it's a real challenge to combine UV's offsets and UV's scales..

can't make it work ...
Preben
13
Years of Service
User Offline
Joined: 30th Jun 2004
Location:
Posted: 5th Jan 2018 02:13 Edited at: 5th Jan 2018 02:20
Took a look , and your never going to fit this 100% (without a custom shader) you have some large polygons on the terrain that are interpolated so its kind of impossible to make it 100% perfect.

A simple fix would be to scale your heightmap terrain2.png to 1024x1024 and give it a blur. then also blur more when creating:


Then your "nearly" not able to see it

A better way would be to use a splashmap for painting the terrain, it will give you a way better looking terrain , and you only need to use the splashmap uv for the hole terrain.

Edit: attached image use 1024x1024 heightmap and SplitNumber=8
Subscribe and checkout great AppGameKit video's here: Videos click here
Latest GameGuru Loader news: News click here
best regards Preben Eriksen,

Attachments

Login to view attachments
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 09:40 Edited at: 5th Jan 2018 09:59
Rendering the terrain works fine as long as you dont split the texture up. If you use one big terrain texture it looks fine. You can split the terrain mesh into any number and it still works as long as one texture is used for the whole surface.

The reason why using multiple textures creates problems at the seams is that with one single texture, the colour used on the terrain is linearly interpolated (by the std pixel shader) perfectly accross the seam between any two meshes but if you have two textures then only one or the other is used either side of the seams and so the value between the right hand side of texture1 and the left hand side or texture2 cant be interpolated between easily. One texture doesnt know whats on the other texture and the stock standard pixel shader is only using one texture at a time. Pixel shaders in GPU's can interpolate colour accross a single texture but they cant interpolate a colour between 2 textures without using complex blending or a pixel shader! One texture ends and the other texture starts..no interpolation between the pixels on the edges of the two seperate textures. This is further complicated by mipmapping which actually makes the seam appear larger. This is how interpolation and mipmaps work and is not a problem only in AppGameKit but in all 3d rendering. Its been discussed elsewhere on the net.

There are a few solutions

1) One big texture for the whole terrain (This isnt a problem and uses no more memory then separate textures and is quicker to draw too!! As it is effectively an atlas texture which is recommended in 3D and in AGK's documentation)
2) Use smaller individual textures for each mesh but each of these would have to have a border area added to it. The border area would have to contain the pixel image from the neighbour texture and you would have to offset and scale the UV's to correctly use this solution to compensate for the border. This is a horrible solution.
3) Use multiple textures and a custom pixel shader that interpolates between multiple different textures at the seams. A technically challenging and difficult way to solve the problem
4) As Preben suggested above you can blur the edges of the textures so that the colours at the edges of one match those on the colour on the next texture so interpolation isnt needed..This is similar to solution 2. I wouldnt want to try this as its not a perfect solution and leaves you needing textures blured intentionally at the edges

my advice.....do Number one. Your actually splitting a texture up in your code above...but if you leave it whole...it renders fine...no issues at the seams

If you want, have multiple texture files for each mesh but copy them together into one single image (the atlas texture) before 3D rendering and render using the 1 atlas texture.
Markus
Valued Member
14
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 5th Jan 2018 10:48 Edited at: 5th Jan 2018 10:55
you need to put trees on the seams

maybe also check the part meshes uvs min max values if they are really between 0.0 and 1.0 (just because we know agk)
GetMeshMemblockVertexU ( memID, vertexIndex )
GetMeshMemblockVertexV ( memID, vertexIndex )
AGK (Steam) V2017.12.12 : Windows 10 Pro 64 Bit : AMD (17.12.1) Radeon R7 265 : Mac mini OS High Sierra (10.13)
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 11:01
They are 0.0 and 1.0, there's nothing wrong with the U V values. As I said above the problem is with splitting textures so interpolation cant occur at the seams correctly.
Markus
Valued Member
14
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 5th Jan 2018 15:30
i can't agree that the uvs are correct , i made a test function and i am also confused about this results.
why did it get a max value of 0.503937 ??? of the top left mesh

AGK (Steam) V2017.12.12 : Windows 10 Pro 64 Bit : AMD (17.12.1) Radeon R7 265 : Mac mini OS High Sierra (10.13)
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 16:47 Edited at: 5th Jan 2018 16:50
How weird?? Mine came back with 0.0000 and 0.50000 for a split of 2.

I will check this again with some different sized heightmap images when I get home later.

Did you get similar values for your other 3 meshes?
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 5th Jan 2018 18:38 Edited at: 5th Jan 2018 18:39
Thanks for your help

Bengismo wrote: "1) One big texture for the whole terrain (This isnt a problem and uses no more memory then separate textures and is quicker to draw too!! As it is effectively an atlas texture which is recommended in 3D and in AGK's documentation)"


But ... Try to resize the texture map to 16384x16384 with no split (SplitNumber=1) ... => the texture map doesn't apply to terrain. (at least on my computer ... and on mobile phone... i won't try it lol)

Try a SplitNumber of 2 with the same 16384 image (so 2x2 terrain with splitted 8192pix image (x4)) => it works.

I want an high detailed map ... and split them prevent to touch ands apply paint modifications over a huge image (in the memblock it's not a problem but it will decrease performance on applying it on the terrain meshes ...)

Using BlendMap should do the trick with a shader but ... i will be limit to 8 textures stages (0-7) no ?
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 19:31 Edited at: 5th Jan 2018 19:36
A 16384x16384 image will be HUGE! A single image will be 1.1GB (or 1.4GB including mipmaps) in graphics memory so it wont work and even if it did it would be VERY slow! Your attempting to store way too much detail. Most graphics cards are limited to 8192 pixel textures in any one dimension. Most mobiles will be much lower than that!

Even if you split the textures up, the memory use will still be a very similar amount. That level of detail is way too high for even a very high spec modern PC and mobiles wont stand a chance.

Repeating textures and a detail texture or texture blending would be a much better option. Have you considered detail textures or texture splatting.
http://www.rastertek.com/tertut13.html
https://blogs.msdn.microsoft.com/shawnhar/2008/11/03/detail-textures/
http://www.bundysoft.com/wiki/doku.php?id=tutorials:l3dt:tx_res

Quote: "
I want an high detailed map ... and split them prevent to touch ands apply paint modifications over a huge image (in the memblock it's not a problem but it will decrease performance on applying it on the terrain meshes ...)"


Sorry, Im not sure I understand what you mean?? - perhaps there was a miss type?

And yes, most pixel shaders only access up to 8 textures at a time.
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 20:31 Edited at: 7th Jan 2018 22:27
Hah.... I got it!! ....(err I think)

Replace your terrain2.png with this attached one Mike!! Run it with you code you listed in the first post... It renders without any seam problems on my PC but please check it



And Marcus & Mike..I will explain why your getting texture uvs that arent 0.5!! in a minute! This is all to do with how the height meshes are generated then split up!!
I need to go out and drink alcohol (its friday) so will have to explain this later.

The main point is your height maps resolution should be a (power of 2) + 1 ....in other words - an odd number

Attachments

Login to view attachments
Markus
Valued Member
14
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 5th Jan 2018 21:57
Quote: "should be a (power of 2) -1"

if that work then its a workaround & a compromise
AGK (Steam) V2017.12.12 : Windows 10 Pro 64 Bit : AMD (17.12.1) Radeon R7 265 : Mac mini OS High Sierra (10.13)
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 5th Jan 2018 22:09 Edited at: 7th Jan 2018 23:03
Its not compromise at all.

The CreateObjectFromHeightMap() function creates a mesh that is (xresolution) by (yresolution) vertices. Both the X and Y values have to be an ODD number so that the meshes in the heightmap easily divide in half/quarters etc...

The resolution of the image has to be one more ....or the mesh wont divide into equal portions as its an odd number wide and tall!



Consider the image above ...it looks like 2x2 squares....but 3 vertices are needed on the x and y axis!!

To make a 256x256 set of squares you need 257 vertices in each direction. Your heightmap has to be 257x257 pixels wide etc... This then allows the mesh to be split up into equal smaller meshes with no problem and allows texture to sit over it perfectly. I was incorrect in saying it had to be a (power of 2)-1. It doesnt...it basically has to be a multiple of your split size + 1.

In Mikes example above he ended up with 4 meshes that were all actually different widths and heights! Thats what caused the UV values that werent 0.5. If you do as I have said above then you get the right result.

The image texture can still be a perfect power of 2...its just the heightmaps that need to be one pixel more.
Markus
Valued Member
14
Years of Service
User Offline
Joined: 10th Apr 2004
Location: Germany
Posted: 5th Jan 2018 22:44
aha interesting
Mike can test it with ResizeImage so you still have the original
AGK (Steam) V2017.12.12 : Windows 10 Pro 64 Bit : AMD (17.12.1) Radeon R7 265 : Mac mini OS High Sierra (10.13)
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 6th Jan 2018 00:48 Edited at: 6th Jan 2018 00:50
Thanks Bengismo !!! it makes sense and i've already seen heightmaps of 127x127 and 255x255 a lot of times ... now i (we) understand why lol thanks a lot it is working well now

Markus, For the moment the CreateObjectFromHeightMap() command doesn't accept ImageID ... only a path to the image file so i can't use resizeimage command without re-saving the file (i'm now doing this) But i already asked to Paul to add this feature and it's now on his todo list. So it will be possible to manipulate terrains with an image's memblock without re-saving to a file and reloading from this file (also doing it in this way for the moment ... thanks to the SSD hard-disk lol)

Thanks again for your help
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 6th Jan 2018 11:22 Edited at: 8th Jan 2018 11:50
Great! Good to hear its working

Having the CreateHeightMapFromImage() would be useful.

Allthough....Its possible to actually write an AppGameKit function to do this. It doesnt have to be part of the engine but it would help. It would involve calculating normals, generating indices and would be slower than having it built into the AppGameKit engine. We have the memblocks to access both the image data and the meshdata....so its possible. (I think)

EDIT: Yes...its is possible to write CreateHeightMapFromImage() ...as Ive done it and it works
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 6th Jan 2018 14:25
yes i have already created a terrain loader function few years ago (creating an obj file ... because memblocks did not exist at the time in AGK).

That would have been my workaround if the textures hadn't worked
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 9th Jan 2018 00:08 Edited at: 9th Jan 2018 00:33
MikeMax wrote: "
Markus, For the moment the CreateObjectFromHeightMap() command doesn't accept ImageID ... only a path to the image file so i can't use resizeimage command without re-saving the file (i'm now doing this) But i already asked to Paul to add this feature and it's now on his todo list. So it will be possible to manipulate terrains with an image's memblock without re-saving to a file and reloading from this file (also doing it in this way for the moment ... thanks to the SSD hard-disk lol)
"


We can edit 3D Mesh heightmaps themselves via a mesh memblock and not have to use an image at all. That is a much quicker way of editing 3D object heightmaps then via images. I suppose its easier to draw things onto images like craters or features etc... but changing y values in the memblocks is very easy. You can save images but its also easy enough to save the mesh memblock too.

I have created my own function CreateObjectFromHeightMapImage function that works (with no saving to disk) - It uses an Image memblock to create MeshMemblock. My smoothing isnt quite the same as the AppGameKit functions one but I dont know what algortihm they are using for that - mine does some averaging. Ive not implemented splitting yet. I can share the functions if wanted. This is it in action ....im still testing it a bit



Editing the vertex y values in the memblock seems easier to me. Simply edit the array of heights then one function to update 3D object after normal generation.
Carharttguy
1
Years of Service
User Offline
Joined: 8th Jul 2016
Location: Belgium
Posted: 9th Jan 2018 09:24
Just hopping in.

Bengismo, I'm HIGHLY interested in your CreateObjectFromHeightMapImage function.
I guess an GetObjectHeightMapHeight() function shouldn't be too hard if your using memblocks?
MikeMax
AGK Academic Backer
6
Years of Service
User Offline
Joined: 13th Dec 2011
Location: Paris
Posted: 9th Jan 2018 10:43
This kind of command is about to be released by Paul for a future AppGameKit version (next version ?).
The ability to split it to sub-meshes by design is a good thing
Carharttguy
1
Years of Service
User Offline
Joined: 8th Jul 2016
Location: Belgium
Posted: 9th Jan 2018 10:57
MikeMax wrote: "This kind of command is about to be released by Paul for a future AppGameKit version (next version ?).
The ability to split it to sub-meshes by design is a good thing "


This is indeed a good thing, but the next major downside for me is the fact that CreateObjectFromHeightmap only supports 8bit greyscale.
Which is just not enough for my purpose.
Bengismo
Recently Online
Joined: 20th Nov 2017
Location: Yorkshire, England
Posted: 9th Jan 2018 11:21 Edited at: 9th Jan 2018 11:25
MikeMax wrote: "This kind of command is about to be released by Paul for a future AppGameKit version (next version ?).
The ability to split it to sub-meshes by design is a good thing "


Ok... well... wait for Paul to add it then.

The splitting to sub meshes is easy enough. (Just a case of copying portions of it into individual smaller meshes). Ill add that later so it allows for culling off screen sections as well as individual textures per split.

CarHartGuy wrote: "This is indeed a good thing, but the next major downside for me is the fact that CreateObjectFromHeightmap only supports 8bit greyscale."


Yes... In my code I have an option to use just the greyscale (8bits), R channel (8 bits) or the full 24bits of the RGB values in the image. The original image needs to be encoded properly for the last one to work.

Im not sure AGK's image loader supports loading a 16bit grayscale png file though?? Anyone tried loading one?
Carharttguy
1
Years of Service
User Offline
Joined: 8th Jul 2016
Location: Belgium
Posted: 9th Jan 2018 12:29
AGK documentation wrote: "The image should be PNG 8-bit greyscale or RGB, if it is RGB then only the red channel is read. 16-bit greyscale support may be added in future."


I'm going to mail Paul, maybe, now he's working on the imageID usage of that function, implementing those extra bits is doable.
Carharttguy
1
Years of Service
User Offline
Joined: 8th Jul 2016
Location: Belgium
Posted: 10th Jan 2018 10:21
I got answer from the AppGameKit team.

Paul is not working on 16bit greyscale support for heightmaps right now. It's on a todo list somewhere, so I guess, if you want it, let them know. The more people that need it, the more the devs will feel the need to implement this.

Login to post a reply

Server time is: 2018-04-24 13:40:33
Your offset time is: 2018-04-24 13:40:33