For some time, I've been trying to figure out how to do an object selection outline in my game. (So the player can see the object over everything else, on mouse-over)
This is how the result should look:
The solution I would like to use goes like this:
Layer 1: Draw model in regular shading.
Layer 2: Draw a copy in red color, scaled along normals using vertex shader.
Mask: Draw a black/white flat color of the model to use it as a stencil mask for the second layer, to hide insides and show layer 1.
And here comes the problem. I can't really find any good learning materials about masks. Can I subtract the insides from the outline shape? What am I doing wrong?
I can't figure out how to stack my render passes to make the mask work. :(
Here's a jsfiddle demo
renderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, renderTargetParameters)
composer = new THREE.EffectComposer(renderer, renderTarget)
// composer = new THREE.EffectComposer(renderer)
normal = new THREE.RenderPass(scene, camera)
outline = new THREE.RenderPass(outScene, camera)
mask = new THREE.MaskPass(maskScene, camera)
// mask.inverse = true
clearMask = new THREE.ClearMaskPass
copyPass = new THREE.ShaderPass(THREE.CopyShader)
copyPass.renderToScreen = true
composer.addPass(normal)
composer.addPass(outline)
composer.addPass(mask)
composer.addPass(clearMask)
composer.addPass(copyPass)
Also I have no idea whether to use render target or renderer for the source of the composer. :( Should I have the first pass in the composer at all? Why do I need the copy pass? So many questions, I know. But there are just not enough resources to learn from, I've been googling for days.
Thanks for any advice!
Here's a js fiddle with working solution. You're welcome. :)
http://jsfiddle.net/Eskel/g593q/6/
Update with only two render passes (credit to WestLangley):
http://jsfiddle.net/Eskel/g593q/9/
The pieces missing were these:
composer.renderTarget1.stencilBuffer = true
composer.renderTarget2.stencilBuffer = true
outline.clear = false
Now I think I've found a bit simpler solution, from the THREEx library. It pre-scales the mesh so you dont need a realtime shader for it.
http://jeromeetienne.github.io/threex.geometricglow/examples/geometricglowmesh.html
Related
i need a (nameplate) sprite without sizeAttenuation in Three.js and it should looks like this example:
//load image with 256x128px 32bit png
var spriteMap = new THREE.TextureLoader().load("tex/plates/mytest.png");
var spriteMat = new THREE.SpriteMaterial({map:spriteMap, transparent:true, sizeAttenuation:false});
var sprite = new THREE.Sprite(spriteMat);
...
spriteMat.map.minFilter = THREE.NearestFilter;
The result is not blurry, but its not correctly and hav some artefacts what i dont want:
Here is my second try with (THREE.LinearFilter), also not what i want cos its too blurry:
Renderer size: 1200x800px (not full window)
So, i dont know if its a problem with the filter, position or scaling. The first example seems like a bitmap text, but i really dont know how i can solve this problem. I also dont need a 2d sprite in screenspace. I need the nameplate in 3d worldspace behind other objects. I have really no idea how i can solve this, pls anyone can help me with this problem?
I have a Box Mesh where I subtract another Box with Three.CSG to create a wall with a window.
After doing so, there are tiny holes in the Mesh alongside the cut. They are not visible alle the time, but show up when moving around.
How to close these holes?
This is part of the code how I am creating the Mesh:
var wallBsp = new ThreeBSP( myWallMesh );
var subMesh = new THREE.Mesh( mygeo );
var subBsp = new ThreeBSP( subMesh );
var subtract_bsp = wall_bsp.subtract( subBsp );
var result = subtract_bsp.toMesh();
result.material.shading = THREE.FlatShading;
result.geometry.computeVertexNormals();
Update
I have created a jsfiddle, but it is difficult to reproduce the error, I couldnt make it visible there: http://jsfiddle.net/L0rdzbej/23/
However, you can see the full application here.
Like #gaitat suggested, geometry.mergeVertices() does not look like it changes anything for me. Chandler Prall hinted at the source where precisionPoints, which is a variable inside the mergeVertices function, could solve this. Depending on the scale of the scene its value should be lower or negative, but I had no success so far.
I have a model with a skeleton, all set up.
I've added the animations and Animation Helper to see the model move.
The result is odd - the bones are moving (according to animation helper rendering), but the actual model itself does not.
It's better explained with an gif:
Animation is attached to the mesh using:
animation = new THREE.Animation( mesh, geometry.animation );
Any suggestions on what might be wrong?
The solution was pretty simple actually:
for ( var k in materials ) {
materials[k].skinning = true;
}
I'm trying to make the following in three.js:
I made the model in sketchup with some simple coloured textures and used the collader importer, the result looks like this:
Now I want to dynamically load some photographs onto each of the different planes, however what I end up with is this:
So as you can see, each image is loaded but they are very small and repeated across the rest of the surface.
This is how I load the textures: (preloadTexture() is just a simple preloader)
for(i in cubeSidesArray)
{
preloadTexture(modelThumbsArray[i]);
var newTexture = new THREE.MeshPhongMaterial( { map: THREE.ImageUtils.loadTexture(modelThumbsArray[i]) } );
cubeSidesArray[i].material = newTexture;
}
How do I get the textures to fill the surface?
Thanks!
Edit - I played with the model in sketchup and managed to get it a little better, but not much!
Edit 2 - Still no luck, I'm starting to think building it in code from scratch would be simpler
Option 1: I would advise you to do or next.
1 -.Import the model blender
2 -.Export blender to threejs
3 -.Use this method of charging.
AgregarModeloBlender function (geometry, materials) {
console.log(materials);
material = new THREE.MeshFaceMaterial( materials );
modelo3d_ = new THREE.Mesh( geometry,material );
escenario.add(modelo3d_);
modelo3d_.add(camera);
modelo3d_.scale.set(5,5,5);
modelo3d_.position.set(-900,25,850);
modelo3d_.rotation.y=Math.PI;
}
4 -. Subsequently trabajr with textures independently.
Example: http://all.develoteca.com/builder/
Option 2: I would advise you to do or this:
1 -. Create the geometric shape (vertices) to modify each of the faces of the texture.
Example: http://develoteca.com/Panel/
Greetings.
I have this object I'm loading with THREE.objLoader and then create a mesh with it like so:
mesh = new THREE.SceneUtils.createMultiMaterialObject(
geometry,
[
new THREE.MeshBasicMaterial({color: 0xFEC1EA}),
new THREE.MeshBasicMaterial({
color: 0x999999,
wireframe: true,
transparent: true,
opacity: 0.85
})
]
);
In my scene I then add a DirectionalLight, it works and I can see my object, however it's like the DirectionalLight was an ambient one. No face is getting darker or lighter as it should be.
The object is filled with the color, but no lighting is applied to it.
If someone can help me with that it would be much appreciated :)
What could I be missing ?
Jsfiddle here: http://jsfiddle.net/5hcDs/
Ok folks, thanks to Maƫl Nison and mr doob I was able to understand the few things I was missing, being the total 3d noob that I am... I believe people starting to get into the 3d may find useful a little recap:
Basic 3d concepts
A 3d Face is made of some points (Vertex), and a vector called a normal, indicating the direction of the face (which side is the front and which one is the backside).
Not having normals can be really bad, because lighting is applied on the frontside only by default. Hence the black model when trying to apply a LambertMaterial or PhongMaterial.
An OBJ file is a way to describe 3D information. Want more info on this? Read this wikipedia article (en). Also, the french page provides a cube example which can be useful for testing.
Three.js tips and tricks
When normals are not present, the lighting can't be applied, hence the black model render. Three.js can actually compute vertex and face normals with geometry.computeVertexNormals() and/or geometry.computeFaceNormals() depending on what's missing
When you do so, there's a chance Three.js' normal calculation will be wrong and your normals will be flipped, to fix this you can simply loop through your geometry's faces array like so:
/* Compute normals */
geometry.computeFaceNormals();
geometry.computeVertexNormals();
/* Next 3 lines seems not to be mandatory */
mesh.geometry.dynamic = true
mesh.geometry.__dirtyVertices = true;
mesh.geometry.__dirtyNormals = true;
mesh.flipSided = true;
mesh.doubleSided = true;
/* Flip normals*/
for(var i = 0; i<mesh.geometry.faces.length; i++) {
mesh.geometry.faces[i].normal.x = -1*mesh.geometry.faces[i].normal.x;
mesh.geometry.faces[i].normal.y = -1*mesh.geometry.faces[i].normal.y;
mesh.geometry.faces[i].normal.z = -1*mesh.geometry.faces[i].normal.z;
}
You have to use a MeshPhongMaterial. MeshBasicMaterial does not take light in account when computing fragment color.
However, when using a MeshPhongMaterial, your mesh becomes black. I've never used the OBJ loader, but are you sure your model normales are right ?
Btw : you probably want to use a PointLight instead. And its position should probably be set to the camera position (light.position = camera.position should do the trick, as it will allow the light to be moved when the camera position will be edited by the Controls).