0

THREE.js r83

I'm trying to display a cartesian-style grid wireframe over my model, which needs to be animated (via AnimationMixer). I tried using the EdgesGeometry/LineBasicMaterial/LineSegments approach, as below (from this answer):

var geo = new THREE.EdgesGeometry( mesh.geometry ); 
var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
var wireframe = new THREE.LineSegments( geo, mat );
mesh.add( wireframe );

but unless I'm missing something, it doesn't seem like it can be animated (no morphTargets attribute, etc).

I've switched gears to trying a custom shader using ShaderMaterial or RawShaderMaterial with the following shaders (based on https://github.com/rreusser/glsl-solid-wireframe/tree/master/cartesian):

// vertex shader
precision mediump float;
uniform mat4 projection, view;
attribute vec3 position;
attribute vec3 barycentric;
varying vec3 b;
varying vec3 p;

void main () {
    b = barycentric;
    p = position;
    gl_Position = projection * view * vec4(position, 1);
}

// fragment shader
precision mediump float;
    varying vec3 b;
    varying vec3 p;
    uniform float cartesianX, cartesianY, cartesianZ;
    uniform float width, feather;

    float gridFactor (float parameter, float width_0, float feather_0) {
      float w1 = width_0 - feather_0 * 0.5;
      float d = fwidth(parameter);
      float looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
      return smoothstep(d * w1, d * (w1 + feather_0), looped);
    }
    float gridFactor (vec2 parameter, float width_0, float feather_0) {
        float w1 = width_0 - feather_0 * 0.5;  vec2 d = fwidth(parameter);
        vec2 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec2 a2 = smoothstep(d * w1, d * (w1 + feather_0), looped);
        return min(a2.x, a2.y);
    }
    float gridFactor (vec3 parameter, float width_0, float feather_0) {
        float w1 = width_0 - feather_0 * 0.5;
        vec3 d = fwidth(parameter);
        vec3 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec3 a3 = smoothstep(d * w1, d * (w1 + feather_0), looped);
        return min(min(a3.x, a3.y), a3.z);
    }
    float gridFactor (vec4 parameter, float width_0, float feather_0) {
        float w1 = width_0 - feather_0 * 0.5;
        vec4 d = fwidth(parameter);
        vec4 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec4 a4 = smoothstep(d * w1, d * (w1 + feather_0), looped);
        return min(min(min(a4.x, a4.y), a4.z), a4.w);
    }
    float gridFactor (float parameter, float width_0) {
        float d = fwidth(parameter);
        float looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        return smoothstep(d * (width_0 - 0.5), d * (width_0 + 0.5), looped);
    }
    float gridFactor (vec2 parameter, float width_0) {
        vec2 d = fwidth(parameter);
        vec2 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec2 a2 = smoothstep(d * (width_0 - 0.5), d * (width_0 + 0.5), looped);
        return min(a2.x, a2.y);
    }
    float gridFactor (vec3 parameter, float width_0) {
        vec3 d = fwidth(parameter);
        vec3 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec3 a3 = smoothstep(d * (width_0 - 0.5), d * (width_0 + 0.5), looped);
        return min(min(a3.x, a3.y), a3.z);
    }
    float gridFactor (vec4 parameter, float width_0) {
        vec4 d = fwidth(parameter);
        vec4 looped = 0.5 - abs(mod(parameter, 1.0) - 0.5);
        vec4 a4 = smoothstep(d * (width_0 - 0.5), d * (width_0 + 0.5), looped);
        return min(min(min(a4.x, a4.y), a4.z), a4.z);
    }

        void main () {
            float g = gridFactor( vec3( cartesianX > 0.0 ? p.x * cartesianX : 0.5, cartesianY > 0.0 ? p.y * cartesianY : 0.5, cartesianZ > 0.0 ? p.z * cartesianZ : 0.5 ), width, feather);
            gl_FragColor = vec4(mix(vec3(0), vec3(0.8), g), 1);
        }

And here's how the RawShaderMaterial is defined:

new THREE.RawShaderMaterial({
                // uniforms: uniforms,
                derivatives: true,
                vertexShader: document.getElementById('vertexshader').textContent,
                fragmentShader: document.getElementById('fragmentshader').textContent,
                depthTest: false,
                side: THREE.DoubleSide,
                wireframe: true,
                lights: false,
                visible: true,
                color: 0x000000
            }))

But with this approach, nothing is displayed, although I do get the following warning:

three.js:17014 THREE.WebGLProgram: gl.getProgramInfoLog() WARNING: Output of vertex shader 'b' not read by fragment shader

I'm not well versed in raw webgl code, so I'm not sure how critical that is.

To summarize:

  1. It's my impression that EdgesGeometry/LineBasicMaterial/LineSegments approach cannot be animated as is, am I mistaken?

  2. If one is true, I'm left with the shader approach. Can anyone with more webgl experience tell me what's going wrong here?

EDIT: It looks like the shader approach WON'T work for me, as it appears my shader will need to be able the handle drawing the animations, and I think that's just going to be too complex for me at this time. So back to part one, is there some way that I can get the LineSegments to animate with AnimationMixer, or maybe just replicate that look with another setup?

P.S.
  • 75
  • 1
  • 2
  • 8
  • Have a look at this forum [thread](https://discourse.threejs.org/t/how-to-achieve-this-material-effect-gif-image/1270). – prisoner849 Mar 09 '18 at 22:20
  • 1
    There's a lot going on in your shader. One way to debug shaders is to output color on whatever mesh you're transforming. With the raw shader you have more moving parts that can break, for example, are your `view` and `projection` even set up correctly? With `ShaderMaterial` at least you can count on these two (`projectionMatrix` and `viewMatrix` to be 100% accurate). From there i'd debug these fragment functions one by one. Without any, can you output a flat color and get the shape of the geometry you expect. Check. Next, one of these functions, desired results? Check. Next one... – pailhead Mar 09 '18 at 22:27

0 Answers0