【问题标题】:gradient multicolor metaballs with threejs and marchingcubes带有threejs和marchingcubes的渐变多色元球
【发布时间】:2018-09-07 17:41:02
【问题描述】:

我正在研究如何实现与这项工作类似的东西:https://vimeo.com/9121195。但是通过给定颜色数组中的每个元球显式地分配颜色。据我所知,在这个例子中这完全是从着色器方面完成的,但我想知道这是否不能用 Threejs 和 marchingcubes 来实现。

通过创建一个新的THREE.ShaderMaterial,我假设我可以将每个元球的位置传递给着色器,然后评估每个顶点与给定位置的距离,最终为每个像素分配颜色。

为了简化问题,我从两个移动的元球开始。

来自三个js

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);

}
//...

}

这是我的着色器

'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" )

这是一个示例结果:

这里的问题是显然没有正确计算距离,并且我尝试使用mixScale 进行的两种颜色之间的过渡也不起作用。有什么想法吗?

【问题讨论】:

    标签: three.js webgl fragment-shader vertex-shader marching-cubes


    【解决方案1】:

    是的,这是可能的,但我不认为它是开箱即用的。我查看了您链接的 Marchingcubes 代码,它有一个“enableColor”标志,但颜色似乎是用顶点坐标填充的,而不是从密度字段中插入一个单独的颜色值。

    过去我不得不做一些非常相似的事情来从噪声场生成多材质地形。我想我最终扩展了行进立方体以插入颜色,然后将每种材料分配给一个颜色通道,r、g、b。

    【讨论】:

    • 任何现有的样本了解如何进行?我发现 mnmxmx 在 2d 上完成了类似的工作:codepen.io/mnmxmx/pen/VjjvEq
    • 很棒的演示!但这不是行进立方体..我认为这是画布上的高斯模糊/斑点。不,我没有代码链接。我是在 Unity 中完成的。再次看那个视频,它看起来就像表面正常。要找到表面法线,您可以在行进立方体中评估密度场两次..第二次稍微增加密度偏差..然后取这两个点之间的差异,对其进行归一化..并将其分配给颜色通道 rgb=(xyz*0.5)+1
    • 我将问题编辑为一个更简单的解决方案:颜色将在传递给 threeJS 的材料着色器中计算,并且相对于字段位置。不过还不好用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2015-03-23
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多