Transparent canvas and transparent ShaderMaterial - three.js

I have a renderer:
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: false,
alpha: true
})
And a ShaderMaterial:
const material = new THREE.ShaderMaterial({
uniforms: { ... },
transparent: true,
blending: THREE.NormalBlending,
vertexShader: renderVert,
fragmentShader: renderFrag
})
And i have a fragment shader (simplified here):
void main() {
gl_FragColor = vec4(vec3(0.0), 0.2);
}
But the alpha is not taken into account and the shader renders all colours fully opaque. Also with another blending mode still doesn't work as expected. Why?

Related

Why threejs pointshadermaterial is rectangular rather than circular when I use a png texture?

I have written a points example according to official example, but the result is not happy:
The point is Rectangular, rather than circular!
Here is my material code:
let material = new THREE.ShaderMaterial({
uniforms: {
uColor: { value: new THREE.Color(0xffffff) },
uPointTexture: { value: new THREE.TextureLoader().load(require('./res/spark1')) }
},
vertexShader: _me.vertex_shader,
fragmentShader: _me.fragment_shader,
transparent: true
})
After some try, like: blending: THREE.AdditiveBlending, fog: false...I found is related to depthTest property, after I set false, result is below:
see, black square disappeared!Here is final code:
let material = new THREE.ShaderMaterial({
uniforms: {
uColor: { value: new THREE.Color(0xffffff) },
uPointTexture: { value: new THREE.TextureLoader().load(require('./res/spark1')) }
},
vertexShader: _me.vertex_shader,
fragmentShader: _me.fragment_shader,
depthTest: false,
transparent: true
})

Artifacts on the top and bottom of png textures in THREE.js v76

I'm getting some artifacts on the top and bottom sides on some of my sprites. These are the shaders I am using, if that matters. I'm using v76.
And I'm building these sprites like this:
var object = new THREE.Object3D();
var textureLoader = new THREE.TextureLoader();
textureLoader.load('path/to/image.png', function(texture) {
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
var geometry = new THREE.PlaneBufferGeometry(15, 15);
var material = new THREE.MeshPhongMaterial({
map: texture,
color: 0xffffff,
transparent: true,
alphaTest: 0.2,
side: DoubleSide,
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.customDepthMaterial = new ShaderMaterial({
uniforms: { texture: { type: 't', value: this.material.map } },
vertexShader: vertexShader,
fragmentShader: fragmentShader,
});
object.add(mesh);
})
Don't set your textures to wrap with THREE.RepeatWrapping. This can leave artifacts on texture edges meant to be used as sprites.

ThreeJS: Some material texture faces / triangles not rendering

I have a .obj and .mtl which load textures from .tga files. This all seems to work / look fine in 3D modeling software, but when loaded with three.js (THREE.WebGLRenderer({ antialias: true })) some of the object's children, (specifically between the knees and the calves, but not, for example, the pockets and legs), seem to have a transparent jagged gap / empty triangles.
(Tried turning on antialiasing, changing the overdraw value, turning off transparency, etc.)
Loader function:
threejsHelper.helpers.loadObject('objects/pants/MaleBaggyPants.obj', 'objects/pants/MaleBaggyPants.mtl', {
blinn1SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/button.tga') })),
blinn2SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })),
blinn4SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') })),
blinn5SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/pocket.tga') })),
blinn6SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })),
blinn7SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') }))
}, function (object) {
object.rotation.x = (-90*Math.PI/180);
object.rotation.z = (-90*Math.PI/180);
app.scene.add(object);
app.ready = true;
});
Helper functions:
...
loadTexture: function (manager, path) {
var texture;
if (path.split('.').pop() == 'tga') {
var loader = new THREE.TGALoader();
texture = loader.load(path);
} else {
texture = new THREE.Texture();
var loader = new THREE.ImageLoader(manager);
loader.load(path, function (image) {
texture.image = image;
texture.needsUpdate = true;
});
}
return texture;
},
loadMaterial: function (mtlPath, textures, complete) {
var loader = new THREE.MTLLoader();
loader.load(mtlPath, function (materials) {
materials.preload();
if (!!materials.materials) {
for (var key in materials.materials) {
if (key in textures) {
materials.materials[key] = textures[key];
}
}
}
complete(materials);
});
},
loadObject: function (objPath, mtlPath, textures, complete) {
app.helpers.loadMaterial(mtlPath, textures, function (materials) {
var loader = new THREE.OBJLoader();
loader.setMaterials(materials);
loader.load(objPath, function (object) {
complete(object);
});
});
},
...
You seem to have extra vertices along the seem on both the objects which I think will screw with the triangulation.
Remove these vertices that are not needed and I'm 99% sure it will fix your problem.
I also noticed the model is at a very small scale.
I had the same problem. Some triangle didn't properly render on Threejs while it properly rendered on my OpenGL app.
I solved this trouble by using Uint32Array instead of Uint16Array to define the index of the geometry. I just put this line of code and everything worked like a charm.
const indices = new Uint32Array(faceDict.index);

three.js transparent material issue

I have set a transparent map, though, not all parts are transparent.
I'm using a transparent PNG image as the material map, though it shows background as seen here:
material:
new THREE.MeshLambertMaterial({ map: texture, transparent: true, alphaTest: 0})
renderer:
renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
renderer.preserveDrawingBuffer = true;
renderer.premultipliedAlpha = false;

Three.js: Wireframe renderd behind ShaderMaterial

Because I needed transparency for every face on its own I switched from MeshBasicMaterial to ShaderMaterial.
I draw my geometry twice:
First my filled trianges
and then a wireframe to get a border for every triangle.
Is there a better way to archive this?
With MeshBasicMaterial it looks fine:
But if I switch to ShaderMaterial: (Opacity is reduced to .3 so that you can see the wireframe)
Is there a way to tell webgl which shader "comes first"?
My MeshBasicMaterial:
var material = new THREE.MeshBasicMaterial({
color: new THREE.Color(0xa5a5a5),
side: THREE.DoubleSide,
transparent: true,
opacity: .99
});
and
var materialLines = new THREE.MeshBasicMaterial({
color: new THREE.Color(0x0),
side: THREE.DoubleSide,
wireframe: true
});
My ShaderMaterial:
var attributes = {
customColor: { type: 'c', value: [] },
customOpacity: { type: 'f', value: []}
};
var shaderMaterial = new THREE.ShaderMaterial({
attributes: attributes,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.NormalBlending,
depthTest: false,
transparent: true,
side: THREE.DoubleSide
});
shaderMaterial.linewidth = 5;
and
var uniforms = {
color: { type: "c", value: new THREE.Color(0x0) }
};
var ShaderMaterialLines = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexshaderline').textContent,
fragmentShader: document.getElementById('fragmentshaderline').textContent,
depthTest: false,
side: THREE.DoubleSide,
wireframe: true
});
with my shaders:
<script type="x-shader/x-vertex" id="vertexshader">
attribute vec3 customColor;
attribute float customOpacity;
varying vec3 vColor;
varying float vOpacity;
void main() {
vColor = customColor;
vOpacity = customOpacity;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
varying vec3 vColor;
varying float vOpacity;
void main() {
gl_FragColor = vec4( vColor, vOpacity);
}
</script>
<script type="x-shader/x-vertex" id="vertexshaderline">
uniform vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentshaderline">
varying vec3 vColor;
void main() {
gl_FragColor = vec4( vColor, 1.0);
}
</script>
Edit 1:
What exactly are you trying to achieve?
I want to draw a 3D object that consist of triangles.
I want to have the possibility to control transparency and color for every triangle.
What are the requirements?
The user should see every triangle edge / a border around every triangle.
Each triangle surfaces can have a different color (based on the color of the three corners) and alpha / transpareny value.
The user can set every triangle to invisible (opacity = 0.0), visible (opacity = 1.0) or something between.(Only the triangle surface not the border)
What is your question?
What is the best way to draw triangles with a border in black or whatever color.
What is the best way to get transparency for every triangle( but keep the border).
EDIT - answer updated. WireframeHelper has been deprecated.
You want your mesh to have both a transparent material and a wireframe.
To render a border around each triangle, use WireframeGeometry, and make sure your mesh material has transparent = true.
Transparent objects are rendered last, so the entire wireframe will show.
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// wireframe
var geometry2 = new THREE.WireframeGeometry( geometry ); // or EdgesGeometry
var material2 = new THREE.LineBasicMaterial( { color: 0x000000, transparent: true } );
var wireframe = new THREE.LineSegments( geometry2, material2 );
mesh.add( wireframe );
three.js r.84

Resources