I'm currently building a web application to visualize CAD / CAE data.
data
is an array with all my triangles.
My first approach to draw the triangles is to create one geometry:
triangles = new THREE.Geometry();
And then add all triangles to it:
for (var i = 0; i < data.triangles.length; i++) {
triangles.vertices.push(new THREE.Vector3(data.triangles[i][0].x, data.triangles[i][0].y, data.triangles[i][0].z));
triangles.vertices.push(new THREE.Vector3(data.triangles[i][1].x, data.triangles[i][1].y, data.triangles[i][1].z));
triangles.vertices.push(new THREE.Vector3(data.triangles[i][2].x, data.triangles[i][2].y, data.triangles[i][2].z));
triangles.faces.push(new THREE.Face3(0,1,2));
triangles.faces[i].vertexColors[0] = new THREE.Color(0xFF0000);
triangles.faces[i].vertexColors[0].setRGB(data.triangles[i][0].r, data.triangles[i][0].g, data.triangles[i][0].b);
triangles.faces[i].vertexColors[1] = new THREE.Color(0x00FF00);
triangles.faces[i].vertexColors[1].setRGB(data.triangles[i][1].r, data.triangles[i][1].g, data.triangles[i][1].b);
triangles.faces[i].vertexColors[2] = new THREE.Color(0x0000FF);
triangles.faces[i].vertexColors[2].setRGB(data.triangles[i][2].r, data.triangles[i][2].g, data.triangles[i][2].b);
lvar += 3;
}
Add a material
material = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.DoubleSide,
transparent: true,
opacity: .99
});
and add the mesh to my scene object.
var mesh = new THREE.Mesh(triangles, material);
scene.add(mesh);
This approach works fine so far but because I only use one material I don't know how to add alpha to my vertexColors.
My second approach is to create a single geometry for every triangle.
for (var i = 0; i < data.triangles.length; i++) {
triangles = new THREE.Geometry();
triangles.vertices.push(new THREE.Vector3(data.triangles[i][0].x, data.triangles[i][0].y, data.triangles[i][0].z));
triangles.vertices.push(new THREE.Vector3(data.triangles[i][1].x, data.triangles[i][1].y, data.triangles[i][1].z));
triangles.vertices.push(new THREE.Vector3(data.triangles[i][2].x, data.triangles[i][2].y, data.triangles[i][2].z));
triangles.faces.push(new THREE.Face3(0,1,2));
triangles.faces[i].vertexColors[0] = new THREE.Color(0xFF0000);
triangles.faces[i].vertexColors[0].setRGB(data.triangles[i][0].r, data.triangles[i][0].g, data.triangles[i][0].b);
triangles.faces[i].vertexColors[1] = new THREE.Color(0x00FF00);
triangles.faces[i].vertexColors[1].setRGB(data.triangles[i][1].r, data.triangles[i][1].g, data.triangles[i][1].b);
triangles.faces[i].vertexColors[2] = new THREE.Color(0x0000FF);
triangles.faces[i].vertexColors[2].setRGB(data.triangles[i][2].r, data.triangles[i][2].g, data.triangles[i][2].b);
lvar += 3;
material.triangles = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.DoubleSide,
transparent: true,
opacity: .99
});
var mesh = new THREE.Mesh(triangles, material);
scene.add(mesh);
}
With this approach I could add my alpha / opacity to the material for every facet.
Unfortunately I get low fps with the second aproach.
Approach 1: 6000 triangles => 60 fps
Approach 2: 6000 triangles => 15 fps
Is there a way to draw lots of triangles (> 50.000) with alpha for every face / point and still beeing around 60 fps (yeah I know it depends on the hardware, too).
Edit:
Using Raycaster
is essential for my project.
Edit 2:
After some testing I decided to go with the following approach:
Create one geometry like I did in my first approach
Replace the MeshBasicMaterial
with ShaderMaterial
First I created my two 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>
Then I replaced my MeshBasicMaterial
with ShaderMaterial
.
Define my attributes
.
attributes = {
customColor: { type: 'c', value: [] },
customOpacity: { type: 'f', value: []}
};
Create/Filled my geometry, colors and opacity:
geometry = new THREE.Geometry();
for (var i = 0, k, lvar = 0; i < data.triangles.length; i++) {
for (k = 0; k < 3; k++) {
geometry.vertices.push(new THREE.Vector3(data.triangles[i][k].x, data.triangles[i][k].y, data.triangles[i][k].z));
attributes.customColor.value[lvar + k] = new THREE.Color(THREE.ColorKeywords.black);
attributes.customColor.value[lvar + k].setRGB(data.triangles[i][k].r, data.triangles[i][k].g, data.triangles[i][k].b);
attributes.customOpacity.value[lvar + k] = 1.0;
}
geometry.faces.push(new THREE.Face3(lvar, lvar + 1, lvar + 2));
lvar += 3;
}
Created my ShaderMaterial
:
var shaderMaterial = new THREE.ShaderMaterial({
attributes: attributes,
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent,
blending: THREE.NormalBlending,
depthTest: true,
transparent: true,
side: THREE.DoubleSide,
linewidth: 2
});
And finaly my mesh:
var mesh = new THREE.Mesh(sc.geometry.triangles, shaderMaterial);
scene.add(mesh);