I need some guidance and help. I am new to three.js and want to make a terrain with given terrestrial map image for texture and given heightmap data.
For this, i have to deal with large scale terrestial map image like 4104x1856
If i create a plane mesh with such a large number of vertices and use height map in those vertices and map terrestian texture in that elevated surface, it becomes so slow.
For this, i created mesh of segments 4104x1856, but i am sure it is very oldschool and not optimum way of doing this.
I have two concern
can i do such a big scale in three.js ?
if yes, what are things that i should do in order to make it not only renderable but also efficiently interactivable.
Thank you in advance !!!
Related
My scene contains a number of planes with PNG textures. First, my problem was the transparent parts of the texture hiding other objects behind it. Then I found the workaround by disabling depth testing and depth buffer writing, which however introduced another problem: at certain distances and angles, objects that are behind, render over those that are in front of them:
Now, I'm a relative newcomer to 3D programming, but through reading other SO answers, such as:
Three.js / WebGL - transparent planes hiding other planes behind them
Transparent textures behaviour in WebGL
Three.js - depthWrite vs depthTest for transparent canvas texture map on THREE.Points
I think I understand that depth and transparency are a difficult issue in general. However, I am not sure what the right direction from here is. Should I manually calculate the distance of the objects from camera, then tell three.js to render them from farthest to closest? Would that fix the issue? Or is there another general solution?
I'm looking to find out if its possible to create a sphere that handles clipping in threejs. At the moment I'm building a series of clipping planes to handle all directions as shown in the image, but this seems rather wasteful. If its just affecting a material property would it not be possible for a sphere or rect geo to do the same thing.
thanks in advance!
So I found out that texturing planets can be really hard. I created a 4096k image and wrapped it around a high poly sphere. Apart from the possible memory management performance issue that comes with a 3-4 mb image, the texture looks bad / pixelated on a close up (orbital) view.
I was thinking that I could maybe increase the resolution significantly by splitting up the picture. Then create a low, medium and high version of each section. If the camera viewport is very close to that particular section then render the high resolution image. If far away remove image from memory and apply low or medium version.
To be honest I am not sure what strategy to use to render high quality planets. Should I maybe avoid textures and just use height maps and color the planet with Javascript? Same thing for the clouds. Should I create a sphere with an alpha map or should I use shaders?
As you can see this is the issue im having and hopefully you could enlighten me. Performance with Webgl / three.js has significantly improved over time but since this is all done within the browser I assume thinking about the right solution is vital in the long term.
You're going to need to implement a lod system. lod = "level of detail" and in 3d it means generally means switching from high-polygon to low-polygon models but in general it means doing anything to switch high detail to low-detail
Because you can't make textures 1000000x100000 which is pretty much what you'd need to do to get the results you want you'll need build a sphere out of multiple sections and texture each one separately. How many sections depends on how close you want to be able to zoom in. Google Maps has millions of sections. At the same time, if you can zoom out to see the whole planet (like you can in Google Maps) you can't draw millions of sections. Instead you'd switch to a single sphere. That process is called "LODing"
There is no "generic" solution. You generally need to write your own for your specific case.
In the case of something like Google Maps what they most likely do is have several levels of detail. A single sphere when you can see the whole planet. A sphere made of say 100 pieces when slightly closer. A sphere made of 1000 pieces when closer, A sphere made of 10000 pieces when closer, etc etc. They also only show the pieces you can see. Deciding and managing which pieces to show with a generic solution would be way to slow (look at millions of pieces every frame) but you, as the application writer know what pieces are visible so you can make sure only those pieces are in your scene.
Another thing that people often do is fade between LODs. So when Google Maps is showing the single mesh sphere when all the say zoomed out and they transition to the 100 piece or 1000 piece sphere they crossfade between the two.
Some examples of lodding
http://acko.net/blog/making-worlds-1-of-spheres-and-cubes/
http://vterrain.org/LOD/spherical.html
You could create a sphere with different topology.
Say you create 6 square planes, arranged in such a way that they form a box. You can tesselate these planes to give the sphere enough resolution. These planes would have UV mapping that would work similar to cube-mapping, each will hold a cubemap face.
Then you loop through all the vertices, take the position vector and normalize it. This will yield a sphere.
You can convert an equirectangular panorama image into a cubemap. I think it will allow you to to get more resolution and less stretching for cheap.
For starters, the 4096 x 4096 should be 4096x2048 on the default sphere with equirectangular, but the newly mapped sphere can hold 6 x 4096 x 4096 with no stretching, and can be drawn in 6 draw calls.
Further splitting these could yield a good basis for what gman suggests.
So I am trying to build a 3D based world consisting of tiles.
I have successfully managed to do this using the plane geometry and height values etc. But now I have come to a point where I possibly have to change everything.
The problem is that I want a tile to have multiple textures (using a shader because I want to blend them). I was able to do this globally (so each tile would have same textures + using some uv mapping).
However I fail to understand how I would be able to specify which tile has which textures (and I have about a 100 textures), since the plane geometry has only 1 shader material. And I am also not sure if it is a good idea to send 100 textures through a shader?
So my questions basically boil down to this:
Is there a decent/performant way to link the tile/vertices to the textures, so I can keep the plane geometry.
- If yes: how?
- if no: Should I create each tile separately (so a plane of 1x1) and merge them somehow together (performance/vertex blending?) so it acts as a single plane (in this case the merged plane consists of many 1x1 planes) and use the shader per tile (a 1x1 plane)?
How are these things generally done?
Edit:
Some extra information because it seems that my question is not really clear:
What I want is that a tile (2 faces) has multiple "materialIndexes" to say so. Currently I need to have 1 tile to have 3 textures, so I can blend them in a shader with a specific algorithm.
For example I want to have a heart shape (red heart/black background) as texture and than based on the colors I want to blend/change the other 2 textures so I can get for example wooden heart and a blue background. Or for example I should be able to blend 4 textures evenly on the square, each take 1/4 of the square. But the point here is not what has to be done with the textures, but how that i can specify such 3, 4, or more textures for my faces/tiles.
I think you have to take a look at what is called a multi material object.
THREE.SceneUtils.createMultiMaterialObject( geometry, materials );
If you google for those you find several examples. Like this answer on a similar question.
Or take a look at THREE.MeshFaceMaterial. You can use it to assign multiple materials for the same geometry.
var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
Where materials is an array of materials and the faces use a materialIndex paramater to get appointed the right material
Similar questions here and here
EDIT:
Here is a fiddle to demonstrate that it is possible. I used the code from one of the links.
If your textures have all the same size, you can do the following:
Create a texture 10x the size of an individual texture (you can do that automatically, create a canvas, draw the texture file on the canvas at the correct coordinates, get the texture from the canvas). This allows for 100 (10x10) textures.
Assign to the tiles a base uv coordinates in the range 0 - 0.1 (since a single texture occupies 1/10th of the global texture),
Add to the previous uv values the offset of the individual texture (for the second texture, offset of 0.1 in u and 0 in v, for the 3rd texture 0.2 and 0; for the 10th 0 and 0.1.
Can anybody help me with three.js?
I need to draw background, something, like a THREE.Sprite, but it neet to be UNDER any 3d object, that will draw later. I have a camera, that can be move only on Z axis.
I tryed to use:
cube mapping shader - PROBLEM: artefacts with shadow planes, it's unstable draw
THREE.Sprite that dublicate camera moving - PROBLEM: artefacts with shadow plane - it have a edge highlighting OR drawing only other spirtes without objects.
HTML DOM Background - PROBLEM: big and ugly aliasing in models.
What can I try more? Thanks!
You could maybe try drawing in several passes, i.e. making a first render of the background scene to a buffer, and then a second one over the first "buffer". Maybe using the buffer as background (painting it in 2D with an orthographic projection, and disabling depth buffer writes in that pass).
I haven't tried it myself with three.js, but that's how I'd do that with "traditional" OpenGL.
If you want a "3d" background i.e. something that will follow the rotation of your camera, but not react to the movement (be infinitely far), then the only way to do it is with a cubemap.
The other solution is a environment dome - a fully 3d object.
If you want a static background, then you should be able todo just a html background, i'm not sure why this would fail and what 'aliasing in models' you are talking about.