gradient multicolor metaballs with threejs and marchingcubes

一个人想着一个人 提交于 2019-12-13 04:04:44

问题


I am looking on how to implement something similar than this work: https://vimeo.com/9121195 . But with explicitly attributing colors to each metaball from an array of given colors. As far as I can see, this is done entirely from the shader side in this example but I was wondering if this could not be implemented with Threejs and marchingcubes.

By creating a new THREE.ShaderMaterial I assume I can pass positions of each metaball to the shader and then evaluate the distance of each vertex with the given positions to finally assign a color to each pixel.

Just to simplify the problem I start with two moving metaballs.

from threejs:

function init() {
    //...
var strength = 0.61;
var resolution = 70;
var substract = 25;
var scaleFactor = 1200;
var posData = []; // array storing metaballs positions

var myShaderMaterial = new THREE.ShaderMaterial({ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
                                                   vertexShader: shader.vertexShader, 
                                                   fragmentShader: shader.fragmentShader,
                                                   name:"myShaderMaterial" }); // shader is described below

effect = new THREE.MarchingCubes( resolution, myShaderMaterial,false,true);

effect.position.set( 0, 0, 0 );
effect.scale.set( scaleFactor, scaleFactor, scaleFactor );
effect.enableUvs = true;
effect.enableColors = true;
effect.hasColors = true;
effect.castShadow = true;
//...

scene.add( effect );
}

function render() {
effect.reset();
effect.init(resolution);
for (var i = 0; i <= posData.length - 1; i++) {
    item = posData[i];
    effect.addBall(item[0], item[1], item[2], strength, substract);
    effect.material.uniforms.allPos.value[i] = new THREE.Vector3(item[0],item[1],item[2]).multiplyScalar(1./scaleFactor);

}
//...

}

here is my shader:

'myShaderMaterial' : {

uniforms: {

    "colChoice":{type: "v3v", value:[new THREE.Color( 0xef5350 ),
                                    new THREE.Color( 0xffffff )]},
    "allPos":{type: "v3v",value:[new THREE.Vector3(0., 0., 0.),
                                 new THREE.Vector3(0., 0., 0.)]},
},

vertexShader: [

    "uniform vec3 colChoice[2];",
    "varying vec3 vNormal;",
    "varying vec3 vRefract;",
    "varying vec3 blobColor;",
    "varying vec3 otherColor;",
    "uniform vec3 allPos[2];",
    "varying float mixScale;",

    "void main() {",

        "vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
        "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
        "vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
        "vNormal = normalize( normalMatrix * normal );",

        "gl_Position = projectionMatrix * mvPosition;",

        "float distMin = 100000000000000000000000000000000000000.;",
        "float distMax = 0.;",      
        "for (int i=0;i<2;i++){",               
                "float distV = distance(allPos[i], position );",
                "if (distV<distMin){",
                    "distMin = distV;",
                "}",
                "if (distV>distMax){",
                    "distMax = distV;",
                "}",

                "mixScale = smoothstep(distMin,distMax,distV);",
                "if (mod(float(i),2.0)==0.){",
                    "blobColor = colChoice[0];",
                    "otherColor = colChoice[1];",
                "}",
                "else{",
                    "blobColor = colChoice[1];",
                    "otherColor = colChoice[0];",
                "}",
        "}",
    "}",
].join( "\n" ),

fragmentShader: [

    "varying vec3 blobColor;",
    "varying vec3 otherColor;",
    "varying vec3 vNormal;",
    "varying float mixScale;",


    "void main() {",

        "vec3 finalColor = (0.3*vNormal) +  mix(otherColor,blobColor,mixScale);",
        "gl_FragColor = vec4(finalColor,1.0);",

    "}",

].join( "\n" )

here is a sample result:

The issue here is that obviously the distance is not calculated properly and the transition between two colors that I tried to do with mixScale also does not work. Any idea?


回答1:


Yeah it's possible but I don't think it does it out of the box. I peeked at the marchingcubes code you linked, and it has an "enableColor" flag but color seems to be filled with the vertex coordinate instead of interpolating a separate color value from the density field.

I've had to do something very similar in the past to do multi material terrain generation from noise fields. I think I ended up extending the marching cubes to interpolate colors, then assigned each material to a color channel, r, g, b.



来源:https://stackoverflow.com/questions/49544638/gradient-multicolor-metaballs-with-threejs-and-marchingcubes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!