how to handle hairs better in three.js? - three.js

The result I have right now is on the left. I want to make the result close as possbile to the one from the right. Hairs only. Here's my model.
How can I achieve that?
here's the code I use right now:
m.color.set( 0xffffff );
m.map.magFilter = THREE.NearestFilter;
m.map.minFilter = THREE.NearestFilter;
m.transparent = true;
m.alphaTest = 0.001;
m.alphaMap = null;
m.side = THREE.DoubleSide;
m.shininess = 6;
m.depthTest = true;
m.depthWrite = true;
m.skinning = true;
m.map.needsUpdate = true;
I've tried different variations of code but I don't know the three.js well. I see the problem with sorting, overlapping, etc. How can I can solve this?
I see some succesfull results with webgl here:
https://sketchfab.com/3d-models/knight-princess-6495fc2ab3ac4fce84315453ab0a6809
https://sketchfab.com/3d-models/jolly-roser-31008c461a2644ea95f57f938f3e42a8
https://sketchfab.com/3d-models/subsurface-scattering-sss-demo-lara-a231143a88e44951820bdf11ab4cbf53

Related

Three.js - repositioning vertices in a 'particle' mesh

I have a basic three.js game working and I'd like to add particles. I've been searching online, including multiple questions here, and the closest I've come to getting a 'particle system' working is using a THREE.BufferGeometry, a THREE.BufferAttribute and a THREE.Points mesh. I set it up like this:
const particleMaterial = new THREE.PointsMaterial( { size: 10, map: particleTexture, blending: THREE.AdditiveBlending, transparent: true } );
const particlesGeometry = new THREE.BufferGeometry;
const particlesCount = 300;
const posArray = new Float32Array(particlesCount * 3);
for (let i = 0; i < particlesCount; i++) {
posArray[i] = Math.random() * 10;
}
const particleBufferAttribute = new THREE.BufferAttribute(posArray, 3);
particlesGeometry.setAttribute( 'position', particleBufferAttribute );
const particlesMesh = new THREE.Points(particlesGeometry, particleMaterial);
particlesMesh.counter = 0;
scene.add(particlesMesh);
This part works and displays the particles fine, at their initial positions, but of course I'd like to move them.
I have tried all manner of things, in my 'animate' function, but I am not happening upon the right combination. I'd like to move particles, ideally one vertex per frame.
The current thing I'm doing in the animate function - which does not work! - is this:
particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
particlesGeometry.setAttribute( 'position', particleBufferAttribute );
//posArray[particlesMesh.counter] = objects[0].position;
particlesMesh.counter ++;
if (particlesMesh.counter > particlesCount) {
particlesMesh.counter = 0;
}
If anyone has any pointers about how to move Points mesh vertices, that would be great.
Alternatively, if this is not at all the right approach, please let me know.
I did find Stemkoski's ShaderParticleEngine, but I could not find any information about how to make it work (the docs are very minimal and do not seem to include examples).
You don't need to re-set the attribute, but you do need to tell the renderer that the attribute has changed.
particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
particleBufferAttribute.needsUpdate = true; // This is the kicker!
By setting needsUpdate to true, the renderer knows to re-upload that attribute to the GPU.
This might not be concern for you, but just know that moving particles in this way is expensive, because you re-upload the position attribute every single frame, which includes all the position data for every particle you aren't moving.

Blending artifacts when rendering polygon hair with Three.js

Trying to render polygon hair with transparency I get this artifact:
What I've checked so far:
renderer.sortObjects is true.
The hair's material.side is THREE.DoubleSide.
Set material.alphaTest=0.5 - reduced the problem but some artifacts are still visible.
How do I debug this?
What solved the problem was rendering the hair twice, first the back side and then the front side:
var hairMesh1 = obj;
var hairMaterial1 = hairMesh1.material;
hairMaterial1.opacity = 1.0;
hairMaterial1.transparent = true;
hairMaterial1.side = THREE.BackSide;
hairMaterial1.depthWrite = false;
var hairMesh2 = hairMesh1.clone();
var hairMaterial2 = hairMesh2.material = hairMesh2.material.clone();
hairMaterial2.side = THREE.FrontSide;
var hairObj2 = new THREE.Object3D();
hairObj2.add(hairMesh2)
hairObj2.renderOrder = 1;
model.add(hairObj1);
model.add(hairObj2);
This is explained in this answer.
Another thing I tried was like here - I set
material.alphaTest = 0.5; // between 0 and 1
which reduced problem (still noticeable artifacts seen). An explanation can be found here.

THREEJS: add hole to rendered Shape

I'm trying to inject hole to the shape that is already added to the scene, but some thing going wrong...
so in details: the shape
var well,
vertices = [],
wellShape,
wellMaterial = new THREE.MeshLambertMaterial({color: this.params.wellsColor});
vertices.push(new THREE.Vector2(0,3000));
vertices.push(new THREE.Vector2(4000,3000));
vertices.push(new THREE.Vector2(4000,0));
vertices.push(new THREE.Vector2(0,0));
wellShape = new THREE.Shape(vertices);
well = new THREE.Mesh( new THREE.ShapeGeometry(wellShape), wellMaterial);
scene.add(well);
well.geometry.dynamic = true;
var hole = [
new THREE.Vector3(300,300,0),
new THREE.Vector3(1000,300,0),
new THREE.Vector3(1000,1000,0),
new THREE.Vector3(300,1000,0)
];
well.geometry.vertices = well.geometry.vertices.concat(hole);
well.geometry.faces = [];
var triangles = THREE.Shape.Utils.triangulateShape ( well.geometry.vertices, hole );
for( var i = 0; i < triangles.length; i++ ){
well.geometry.faces.push( new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2] ));
well.geometry.faceVertexUvs[ 0 ][i] = THREE.ExtrudeGeometry.WorldUVGenerator.generateTopUV(well.geometry, triangles[i][0], triangles[i][1], triangles[i][2]);
}
but as result i got something strange: in console output "Infinite Loop! Holes left:4, Probably Hole outside Shape!" and on desktop i got https://yadi.sk/i/WHRzH7c2jnaRm
could someone tell me what is wrong in my code?
after few days play around I found what is wrong:
1. THREE.Shape.Utils.triangulateShape expect vertices and holes to be parts of same shape.
2. hole should be not the array of points but array of path.
3. vertices should be concated after triangulation.
so correct result is:
....
var holePoints = [
new THREE.Vector3(300,300,0),
new THREE.Vector3(1000,300,0),
new THREE.Vector3(1000,1000,0),
new THREE.Vector3(300,1000,0)
],
hole = new THREE.Path();
hole.fromPoints(holePoints);
var shape = new THREE.Shape(well.geometry.vertices);
shape.holes = [hole];
var points = shape.extractPoints();
well.geometry.faces = [];
var triangles = THREE.Shape.Utils.triangulateShape ( points.vertices, points.holes );
....
Hope someone will find this info helpful.

three.js loaded model is disappearing while switch to FirstPerson control from Orbitcontrol

am having an option to switch Orbit control to FirstPerson control, but while switch my model is disappearing from the scene
my code is below
controls = new THREE.FirstPersonControls( camera );
controls.movementSpeed = 70;
controls.lookSpeed = 0.04;
controls.noFly = true;
controls.lookVertical = false;
i need that switch from one control to another the object should be fixed on the position at present
Unlike OrbitControl, in the FirstPersonControl the camera points to an artbitrary directions. So use camControl.lon and camControl.lat to control the initial direction of camera.
camControl = new THREE.FirstPersonControls(camera);
camControl.lookSpeed = 0.1;
camControl.movementSpeed = 4;
camControl.noFly = true;
camControl.lookVertical = true;
camControl.lon = -90;
camControl.lat = 0;
Also make sure your mouse is not over the window as the scene is moving because as another poster pointed out, as soon as the mouse is on the cavas FirstPersonControl will start rotating the camera.
As of three.js R101, it's possible to use FirstPersonControls.lookAt(). FirstPersonControls.lat and FirstPersonControls.lon have been removed.
Besides, when creating FirstPersonControls the initial orientation of the camera is now respected.

Stencil testing in XNA 4

I was able to do this in XNA 3.1, however I see that we now use state objects in XNA 4, which is certainly an improvement, although I can't accomplish what I want so far :)
I am trying to:
Clear the stencil buffer to 0.
Draw a texture to the stencil buffer, setting the stencil buffer to 1 where the texture is drawn.
Draw another texture that will only appear where the stencil buffer is not 1.
Here is what I have so far, which appears to have no effect on the drawing of texture 2:
BlendState blend = new BlendState();
blend.ColorWriteChannels = ColorWriteChannels.None;
_preSparkStencil = new DepthStencilState();
_preSparkStencil.StencilEnable = true;
_preSparkStencil.StencilFunction = CompareFunction.Always;
_preSparkStencil.ReferenceStencil = 1;
_preSparkStencil.DepthBufferEnable = true;
_sparkStencil = new DepthStencilState();
_sparkStencil.StencilEnable = true;
_sparkStencil.StencilFunction = CompareFunction.NotEqual;
_sparkStencil.ReferenceStencil = 1;
_sparkStencil.DepthBufferEnable = true;
gd.DepthStencilState = _preSparkStencil;
gd.Clear(ClearOptions.Stencil, Color.Black, 0, 0);
sb.Begin(SpriteSortMode.Deferred, blend);
DrawTexture1();
sb.End();
gd.DepthStencilState = _sparkStencil;
sb.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
DrawTexture2();
sb.End();
gd.DepthStencilState = old;
The problem was that the RenderState needs to be passed into SpriteBatch, or else the SpriteBatch will use it's own RenderState.
sb.Begin(SpriteSortMode.Deferred, BlendState.Opaque,
SamplerState.LinearWrap, _preSparkStencil,
RasterizerState.CullCounterClockwise, CLM.AlphaClip);

Resources