我正在研究如何实现类似于这项工作的东西:https://vimeo.com/9121195。但是明确地将颜色归因于给定颜色阵列中的每个元球。据我所知,这完全是从这个示例中的着色器端完成的,但我想知道这是否无法使用Threejs和marchingcubes实现。
通过创建一个新的THREE.ShaderMaterial
,我假设我可以将每个元球的位置传递到着色器,然后使用给定位置评估每个顶点的距离,最后为每个像素指定一种颜色。
为了简化问题,我从两个移动的元球开始。
来自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);
}
//...
}
这是我的着色器:
'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
做的两种颜色之间的过渡也不起作用。有什么想法吗?
答案 0 :(得分:0)
是的,但是我不认为这样做是开箱即用的。我偷看了你链接的marchingcubes代码,它有一个&#34; enableColor&#34;标志,但颜色似乎用顶点坐标填充,而不是从密度字段插入单独的颜色值。
我过去必须做一些非常相似的事情来从噪声场做多物质地形生成。我想我最终扩展了行进立方体以插入颜色,然后将每个材质分配给颜色通道r,g,b。