Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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: Render with MeshBasicMaterial

But if I switch to ShaderMaterial: (Opacity is reduced to .3 so that you can see the wireframe) Render with ShaderMaterial

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).

like image 612
endofsource Avatar asked Sep 13 '25 16:09

endofsource


1 Answers

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

like image 75
WestLangley Avatar answered Sep 16 '25 08:09

WestLangley