three.js transparent png texture strange border webgl - javascript

I am having a strange problem when using pngs as a texture in three.js. The pngs get strange borders at the area between visible and transparent. I allready tried to play around with alphatest value but then sometimes the image disapears completly in areas where are really thin 1px lines. Is there a solution how to solve this?
var explosionTexture = new THREE.ImageUtils.loadTexture( 'explosion.png' );
boomer = new TextureAnimator( explosionTexture, 4, 4, 16, 55 ); // texture, #horiz, #vert, #total, duration.
var explosionMaterial = new THREE.MeshBasicMaterial( { map: explosionTexture } );
explosionMaterial.transparent = true;
var cube2Geometry = new THREE.PlaneGeometry( 64, 64, 1, 1 );
cube2 = new THREE.Mesh( cube2Geometry, explosionMaterial );
cube2.position.set(100,26,0);
scene.add(cube2);
// renderer
//renderer = new THREE.WebGLRenderer( { antialias: false, premultipliedAlpha: true } );
renderer = new THREE.WebGLRenderer( { antialias: false } );

Just try this:
explosionTexture.anisotropy = 0;
explosionTexture.magFilter = THREE.NearestFilter;
explosionTexture.minFilter = THREE.NearestFilter;
Also you should not use antialaising when constructing the renderer:
renderer = new THREE.WebGLRenderer({antialias: false});
Did this to preview minecraft texture packs, works great :-)

Use material blending, the following configuration worked for me:
material.blending = THREE.CustomBlending
material.blendSrc = THREE.OneFactor
material.blendDst = THREE.OneMinusSrcAlphaFactor
See this example:
http://threejs.org/examples/#webgl_materials_blending_custom

Congratulations, you've run directly into the Texel-to-Pixel-mapping-trap. :)
This should help you out of there, although it's not WebGL the basics still apply.

Ok, so I tried all the solutions on this page. They all failed.
What worked for me was to use the correct Texture.wrapS (horizontal wrapping) and Texture.wrapT (vertical wrapping) for the sprite texture.
I personally was finding this ugly edge on the top of my sprite. I just had to make sure my Texture.wrapT setting was THREE.ClampToEdgeWrapping instead of THREE.RepeatWrapping.
Solved the issue perfectly without messing with alpha test values, texture filters, vertices or antialiasing.

i solved it like this:
var c2GVertices = cube2Geometry.vertices;
for (var i = 0; i < c2GVertices.length; i++) {
c2GVertices[i].x = c2GVertices[i].x - 0.5;
c2GVertices[i].y = c2GVertices[i].y - 0.5;
}
is there an easier way to move all vertices a half pixel?

Related

Box3 attached to the camera is not responding to collision with another Box3

I am having problem with detecting intersection between a box3 (which is a wall) and the camera (which is player moving).
Here is the code:
const wallgeometry = new THREE.PlaneGeometry( 200, 50 );
const wallmaterial = new THREE.MeshStandardMaterial( {color: 0x366078, side: THREE.DoubleSide} );
const wall1a = new THREE.Mesh( wallgeometry, wallmaterial );
wall1a.position.set(40,0,50); wall1a.rotation.y=0.5*Math.PI; scene.add( wall1a );
const humangeometry = new THREE.BoxGeometry( 3,3, 3 );
const humanmaterial = new THREE.MeshBasicMaterial( {color: 0x00ff00, transparent: false, opacity: 1.0} );
const human = new THREE.Mesh( humangeometry, humanmaterial );
**scene.add( human );
var humanhelper = new THREE.BoxHelper(human, 0x00ff00);
scene.add(humanhelper);
var humanbox3 = new THREE.Box3();
humanbox3.setFromObject(humanhelper);
camera.add(human);**
var wallhelper = new THREE.BoxHelper(wall1a, 0x00ff00);
scene.add(wallhelper);
var box3b = new THREE.Box3();
box3b.setFromObject(wallhelper);
and in animate() function:
humanhelper.update();
humanbox3.setFromObject(humanhelper);
if(humanbox3.intersectsBox(box3b))
{
console.warn("Collision TRUE");
};
and so I'm going with the camera through the wall but no collision is being detected.
I'm sure that camera wireframe and position is getting updated correctly because it moves along with player (human).
//EDIT
no, actually it looks like the box3 is not being updated at all. I placed 2 walls in the same place, collision was detected, so I started moving one of walls away in animation loop but it was still saying that they are colliding.
humanhelper.update();
...will update the geometry of human helper to match human, but not its position.
Since humanhelper is a child of the scene, it will stay in a fixed position and will never trigger the collider.
I think you need to make humanhelper a child of camera or human. Then it will move along with the camera/human and should trigger the collision you want.
human.add(humanhelper);
or
camera.add(humanhelper);
instead of
scene.add(humanhelper);
should make the difference.

Three.js - Place a dynamic 2D Canvas on a PlaneGeometry

so I have a school project where I have to remake a GameBoy. For this I wanted to create a GameBoy model with ThreeJS (i'm a beginner) and use a public repo of a GameBoy emulator in JavaScript. So I somewhat finished the GameBoy model (still need some some stuff to be added but i'll make it better later) and I decided to use this repo for the GameBoy emulator https://github.com/alexaladren/jsgameboy. This repo worked perfectly fine when it was given a canvas with an ID "display". But when I tried to change the canvas to the canvas I made in ThreeJS it doesn't display anything, here is the code of when I make the Canvas:
geometry = new THREE.PlaneGeometry( 0.55, 0.45, 0.1 );
for (let index = 0; index < 6; index++) {
let x2 = document.createElement("canvas");
let xc2 = x2.getContext("2d");
x2.width = 320;
x2.height = 288;
xc2.fillStyle = "rgba(0, 0, 200, 0.5)";
x2.style.id = 'display';
screenCanvas = x2;
xc2.fillRect(0, 0, x2.width, x2.height);
let tex2 = new THREE.CanvasTexture(x2);
screen.push(new THREE.MeshBasicMaterial({
map: tex2,
transparent:true,
opacity:0.3
}))
number++;
}
material = new THREE.MeshBasicMaterial({color: 0xA1A935});
mesh = new THREE.Mesh( geometry, screen );
mesh.position.y = 0.25;
mesh.position.z = 0.3;
group.add(mesh);
Here is the code I edited in the emulator where the default "display" canvas was mentioned:
if(window.gb != undefined){
clearInterval(gb.interval);
screenCanvas.getContext("2d").setTransform(1,0,0,1,0,0);
}
gb = new GameBoy(arraybuffer);
gb.displaycanvas = screenCanvas.getContext("2d");
screenCanvas.getContext("2d").scale(2,2);
The PlaneGeometry is correctly displayed (I also tried BoxGeometry but same results) but the game won't display on the Canvas I created.
My thoughts on why it doesn't work:
- Because the Canvas is created in ThreeJS it doesn't seem to be added to the DOM elements and probably to the already existing ThreeJS canvas?
- Maybe the canvas I created isn't updating? But I set it to a CanvasTexture so it should update?
Thank you for your help.
Update: Still looking into it but haven’t found a solution, been trying to find help in 3 different Discord servers that provide threejs Discord but no luck. I might have to make the gameboy static while the game is playing and put the game display ontop of the screen if I don’t find another solution.

Using an alphaMap is not providing transparency in my material

I am trying to create chainlink surface. I have 2 textures; a standard map which has the metallic look of the metal links with a white background (diffuse):
I also have an alpha map:
I am trying to apply both of these to a MeshBasicMaterial without luck:
var chainlinkMask = THREE.ImageUtils.loadTexture('textures/chainlink_Large-Panels_mask.png');
chainlinkMask.wrapS = THREE.RepeatWrapping;
chainlinkMask.wrapT = THREE.RepeatWrapping;
chainlinkMask.repeat.set( 2, 2 );
var chainlinkDiffuse = THREE.ImageUtils.loadTexture('textures/chainlink_Large-Panels_Diffuse.png');
chainlinkDiffuse.wrapS = THREE.RepeatWrapping;
chainlinkDiffuse.wrapT = THREE.RepeatWrapping;
chainlinkDiffuse.repeat.set( 2, 2 );
material.map = chainlinkMask;
material.alphaMap = chainlinkDiffuse;
material.transparency = true;
material.side = THREE.DoubleSide;
This gives me the following:
As you can see, the alpha map isn't being applied.
Why not?
Any help appreciated.
Try setting the transparent parameter to true instead of transparency
material.transparent = true;
If you are using an alpha map, use one of these two patterns when defining your material:
alphaMap: texture,
transparent: true,
or
alphaMap: texture,
alphaTest: 0.5, // if transparent is false
transparent: false,
Use the latter if possible, and avoid artifacts that can occur when transparent is true.
three.js r.85
directly use material.transparent will cause rendering problem, for example. you have 2 corssing plane with each one applied material.transparent = true, and material.side = DoubleSide. rotate it you will see rendering problem.
just use the solution #WestLangley mentioned above.

Threejs - Reflectivitybitmap does not work on MeshLambertMaterial

what works:
I am using threejs revision 73.
I want to render a tool with the WebGLRenderer.
The tool consists of 3 Meshes. Each mesh consists of a BufferGeometry and a MeshLambertMaterial:
var geometry = new THREE.BufferGeometry();
var material = new THREE.MeshLambertMaterial();
var mesh = new THREE.Mesh(geometry, material);
The result looks like the following:
what I want to archive:
Now I want to make the tool look more realistic by applying a Texture ("img/tablereflection.bmp", grayscale 256x256px, bmp). I am unsure what is the best approach if I want this texture to affect my reflectivity behavior.
What I do, is:
var geometry = new THREE.BufferGeometry();
var material = new THREE.MeshLambertMaterial({
map: new THREE.TextureLoader().load("img/tablereflection.bmp")
});
var mesh = new THREE.Mesh(geometry, material);
But the result looks like that:
That is not what I want to have. It should look like:
Can someone tell me please, what I might be missing?
Edits
My light function is
function initLight(scene, camera) {
var ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);
var leftLight = new THREE.PointLight(0x888888, 0.7, 0);
leftLight.position.set(-2, 5, 2);
camera.add(leftLight);
var rightLight = new THREE.PointLight(0x888888, 0.7, 0);
rightLight.position.set(2, 5, 2);
camera.add(rightLight);
}
I've already tried to use The material browser for MeshLambertMaterial and possibly was able to archieve what I wanted as you can see here using these settings , but as you can see the Type is now empty and so I am not sure what happens behind the scene. Where is the error? Im glad for any hints.

Three.js - Shape disappears on flip side

I've made a circle as follows:
material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
arcShape = new THREE.Shape();
arcShape.absarc( 0, 0, 20, 0, -Math.PI*2, true );
geometry = arcShape.makeGeometry();
circle = new THREE.Mesh(geometry, material);
scene.add(circle);
Like that, it is visible. But rotate it, and it disappears.
shadow.rotation.x = Math.PI / 2;
I've seen several other posts where this problem has not been solved. (So unless someone has a solution, I'll resort to making a flat cylinder instead. It's just a niggling problem).
I've set mesh.doubleSided = true and mesh.flipSided = false. I've also tried all 4 combinations of toggling the renderer's depthTest and the material's depthWrite properties.
Is there anything else I could try? If not, I'm guessing the code is sensitive to the order of some of my calls, in which case, I've had a long day so I'll stick with the cylinder!!
material.side = THREE.DoubleSide;

Categories

Resources