Connect the vertices of a geometry - three.js

I imported in Three.js a THREE.BufferGeometry created in blender.
And I would like to move the vertices along normals with a custom shader ( more or less like that : http://codepen.io/yoanngueny/pen/FnxEl )
The problem is that all the faces are animated.
https://jsfiddle.net/hz4xv49g/1/
I tried to use geometry.computeVertexNormals() but it only works with THREE.Geometry.
I need THREE.BufferGeometry because I will apply specific parameter for each vertices ( attributes ) later and it seems that we can't do that for THREE.Geometry since r72.

Related

Three.js Map Texture to irregular Geometry (UW-Coordinates)

I have a problem with mapping a texture in THREE.js which is possibly related to creating custom UV-Coordinates as extensive search indicates.
The following picture shows a geometry which was created from THREE.BoxGeometry by manipulating the lower vertices of the box. The texture on the side looks stretched (although this is correct I guess).
picture1
Is there a way of "projecting" the texture onto the side, e.g. by creating custom uv-coordinates to look like in the second (photoshopped) picture?
picture2
Thanks for you help!
You will need to remap your vertices manually to perform what is called a "box mapping" or a "triplanar mapping".
Here is an example I threw together: https://codesandbox.io/s/qxk8xvnrvj
It creates a cube with some subdivisions.. perturbs those vertices if they are on top... and then does the iterations through the faces uvs and vertices to remap each faces UVs with a box mapping, by finding the dominant axis the face normal points along... and then using the other 2 axis' as the U and V axis for unwrapping.

Add clipping to THREE.ShaderMaterial

I'm trying to create a shader that takes into account the clipping planes I'm defining in the scene. These clipping planes work fine for all of the 'vanilla' materials I'm using: THREE.MeshLambertMaterial, THREE.MeshPhongMaterial, and THREE.MeshPhysicalMaterial, but THREE.ShaderMaterial is missing this implementation. This is an example of what I mean: https://jsfiddle.net/fraguada/27LrLsv5/
In this example there are two cubes, one with a THREE.MeshStandardMaterial and one with a material defined by THREE.ShaderMaterial. The cube with a THREE.MeshStandardMaterial clips ok. The cube with THREE.ShaderMaterial does not clip.
(I'm not typically defining the vertex/fragment shader in script tags as I show in the jsfiddle, instead I'm defining them in a similar manner to this: https://github.com/mrdoob/three.js/blob/dev/examples/js/shaders/BasicShader.js.)
So, a few questions:
Should THREE.ShaderMaterial include Clipping Planes out of the box? (there is a clipping property, but not sure what it enables)
If not, how could I modify this shader to include the necessary params and shader chunks to enable clipping?
Actually, clipping is done inside the Three.js shaders.
To make it work, you have to handle it inside your shader, by adding those 4 "shader chunks" :
clipping_planes_pars_vertex.glsl at the top of your vertex shader ;
clipping_planes_vertex.glsl inside the main() of your vertex shader ;
clipping_planes_pars_fragment.glsl at the top of your fragment shader ;
clipping_planes_fragment.glsl inside the main() of your fragment shader.
You can access those chunks by simply adding #include <(chunk name)> to your shaders.
Then, set material.clipping = true; and it should work.
Check this fiddle.
Note
To make your shader work, I also added begin_vertex.glsl and project_vertex.glsl.
I checked the current phong shader implementation to understand where to put those chunks.
Note 2
This code should work with a shader implemented with an array of strings but note that you can also reference shader chunks with THREE.ShaderChunk[(chunk name)].
This should be more suitable in your case.

BufferGeometry always creates FlatShading normals. I need SmoothShading

I use ThreeJS r68.
I always used THREE.Geometry for my project and it just works fine.
Now I want to change from THREE.Geometry to THREE.BufferGeometry because I read that this is the better choice.
But I couldn't get SmoothShading to work with my THREE.BufferGeometry.
I load my Object into a BufferGeometry and call bufferGeometry.computerVertexNormals. And then my result is FlatShading.
I read in the computeVertexNormals() method that BufferGeometry calculates differently if I use an "index" attribute. I tried to create an "Indexed" BufferGeometry but that just made everything worse. I don't know if I just created that right. I just added the indices like I would add them to the faces in a normal Geometry. The BufferGeometry.fromGeometry() method does not create an indexed BufferGeometry so I don't know where to look.
Do I need an indexed BufferGeometry for SmoothShading?
UPDATE
[... some time later....]
I think I could create a indexed THREE.BufferGeometry now. It's more like Geometry. And smooth shading looks fine with an indexed BufferGeometry. So now i have SmoothShading but a invalid uv-map. But why is the uv-map different in an indexed BufferGeometry to compared to not indexed BufferGeometry? BufferGeometry is really not easily loaded.
OK.
Here is what i got:
1.) SmoothShading only works for indexed THREE.BufferGeometry. (as far as I know) And not for non indexed BufferGeometry.
2.) An indexed THREE.BufferGeometry only has 1 uv point per vertex, and not 1 uv point per face-vertex.
That means if you have a square with 4 points, then you only have 4 uv points and not 6 like in THREE.Geometry and non indexed THREE.BufferGeometry. (That is confusing and will not allow complicated uv-maps)
UPDATE
[... a few hours of sleep later ...]
I looked into THREE.BufferGeometry.computerVertexNormals() again.
And I have to correct myself.
indexed THREE.BufferGeometry:
1) only 1 uv per vertex
2) only 1 normal per vertex
result :
- only smoothShading possible.
- only simple uv maps.
- limit of 65.535 vertices.
non indexed THREE.BufferGeometry:
1) 1 uv per face vertex
2) 1 normal per face vertex
result:
- calculating normals in ThreeJS(r68): only FlatShading
- calculating normals outside of ThreeJS and import the normals: FlatShading and SmoothShading
- complicated uv maps possible
You can apply THREE.FlatShading to your material to get a flat shaded indexed THREE.BufferGeometry. In that case you don't need to define any normals at all.
This saves you a lot of headaches and overhead:
geometry = new THREE.BufferGeometry
material = new THREE.MeshPhongMaterial({
color: 0xff0000,
shading: THREE.FlatShading
});
mesh = new THREE.Mesh( geometry, material );
Your mesh will render flat shaded.
This doesn't work for THREE.MeshLambertMaterial yet. But they are working on it. Check the related issue here on GitHUB.

How to apply texture to mesh without specifying UV's in geometry using three.js?

Is it possible to apply texture to mesh without specifying UV's in geometry in three.js ?
There are classes such as THREE.CubeGeometry, THREE.SphereGeometry, etc. that automatically generate the UV coordinates for you. However, if you are creating your own geometry from scratch (i.e., specifying vertex locations, creating faces, etc.) then the answer is no. Either you need to set the UV coordinates manually when creating the geometry, or you need to write a custom shader which determines the UV coordinates for any given point. Think about it this way: if you don't specify UV coordinates, the points on your geometry have no idea which point on your texture they should display.

Compute normals from displacement map in three.js r.58?

I'm using the normal shader in three.js r.58, which I understand requires a normal map. However, I'm using a dynamic displacement map, so a pre-computed normal map won't work in this situation.
All the examples I've found of lit displacement maps either use flat shading or pre-computed normal maps. Is it possible to calculate the normals dynamically based on the displaced vertices instead?
Edit: I've posted a demo of a sphere with a displacement map showing flat normals:
Here's a link to the github repo with all of my examples illustrating this problem, and the solutions I eventually found:
https://github.com/meetar/three.js-normal-map-0
This answer is based on your comments above.
You can do what you want, but it is quite sophisticated, and you will of course have to modify the three.js 'normal' shader.
Have a look at http://alteredqualia.com/three/examples/webgl_cubes_indexed.html. Look at the fragment shader, and you will see
vec3 normal = normalize( cross( dFdx( vViewPosition ), dFdy( vViewPosition ) ) );
Alteredqualia is using a derivative normal in the fragment shader ( instead of an attribute normal ) because the vertex positions are changing in the vertex shader, and the normal is not known.
What he is doing is calculating the normal using the cross product of the x and y screen-space derivatives of the fragment position.
This will set the normal as the face normal. It will be discontinuous at hard edges.
three.js r.58
What I was describing above is called a "bump map" and it comes as a default with the three.js phong shader. I combined the normalmap shader with chunks of the phong shader responsible for bump mapping:
http://meetar.github.io/three.js-normal-map-0/bump.html
Though the normals are a bit noisy they are basically correct.
You can also calculate a normal map from the displacement map with JavaScript. This results in smooth normals, and is a good option if your displacement map isn't changing too often.
This method uses the code found in this demo: http://mrdoob.com/lab/javascript/height2normal/
Demo here:
http://meetar.github.io/three.js-normal-map-0/index14.html

Resources