Three.js animated cartesian wireframe

时间:2018-03-09 19:11:02

标签: javascript three.js glsl

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?

0 个答案:

没有答案