带点着色器的threejs metaballs

时间:2018-06-29 11:45:53

标签: three.js marching-cubes shadermaterial

我正在尝试在2pha制作的ThreeJS中测试一个简单的点着色器:https://2pha.com/demos/threejs/shaders/simple_dots.html

对于使用Marching Cubes的metaball来说,它似乎无法正常工作:https://threejs.org/examples/webgl_marchingcubes.html。 这是UV坐标问题吗? ThreeJS版本具有enableUvs标志,但似乎还不够。

此处将着色器传递给ShaderMaterial

'polkadots' : {
    uniforms: {

        "amount":{type: "f",value: 5.},
        "radius1":{type: "f",value: 0.3},
        "radius2":{type: "f",value: 0.32},
        "color1":{type:"c",value: new THREE.Color(0xffffff)},
        "color2":{type:"c",value: new THREE.Color(0x000000)},

    },

    vertexShader: [
        "varying vec2 vUv;",


        "void main() {",
            "vUv = uv;",
            "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
            "gl_Position = projectionMatrix * mvPosition;",

        "}",
    ].join( "\n" ),

    fragmentShader: [

        "uniform vec3 color1;",
        "uniform vec3 color2;",
        "uniform float radius1;",
        "uniform float radius2;",
        "uniform float amount;",
        "varying vec2 vUv;",

        "void main(void){",

            "float p = smoothstep(radius1, radius2, length(fract(amount*vUv)-0.5));",
            "vec3 col = mix(color1,color2,vec3(p));",
            "gl_FragColor = vec4(col,1.0);",

        "}",
    ].join( "\n" )
}

1 个答案:

答案 0 :(得分:0)

是的。您的点着色器正在使用UV确定绘制点的位置...如果行进立方体算法未设置UV,则您必须自己合成一些... 您可以打开包装盒。 它并不太复杂,但是很有趣。 您可以遍历几何图形的各个面...找出三角形所在的平面,并将顶点投影到该uv平面上。我随便为Ya编写了它:

    function boxUnwrapUVs(geometry) {
        for (var i = 0; i < geometry.faces.length; i++) {
            var face = geometry.faces[i];
            var faceUVs = geometry.faceVertexUvs[0][i]
            var va = geometry.vertices[geometry.faces[i].a]
            var vb = geometry.vertices[geometry.faces[i].b]
            var vc = geometry.vertices[geometry.faces[i].c]
            var vab = new THREE.Vector3().copy(vb).sub(va)
            var vac = new THREE.Vector3().copy(vc).sub(va)

            //now we have 2 vectors to get the cross product of...
            var vcross = new THREE.Vector3().copy(vab).cross(vac);
            //Find the largest axis of the plane normal...
            vcross.set(Math.abs(vcross.x), Math.abs(vcross.y), Math.abs(vcross.z))
            var majorAxis = vcross.x > vcross.y ? (vcross.x > vcross.z ? 'x' : vcross.y > vcross.z ? 'y' : vcross.y > vcross.z) : vcross.y > vcross.z ? 'y' : 'z'
            //Take the other two axis from the largest axis
            var uAxis = majorAxis == 'x' ? 'y' : majorAxis == 'y' ? 'x' : 'x';
            var vAxis = majorAxis == 'x' ? 'z' : majorAxis == 'y' ? 'z' : 'y';
            faceUVs[0].set(va[uAxis], va[vAxis])
            faceUVs[1].set(vb[uAxis], vb[vAxis])
            faceUVs[2].set(vc[uAxis], vc[vAxis])
        }
        //Tell THREE that our modifications need to be uploaded to the GPU
        geometry.elementsNeedUpdate = geometry.verticesNeedUpdate = true;
    }