Тройные метаболлы с точечным шейдером
Я пытаюсь протестировать простой точечный шейдер в ThreeJS, созданный 2pha: https://2pha.com/demos/threejs/shaders/simple_dots.html
Кажется, он не работает должным образом для метаболов, использующих шествующие кубы: https://threejs.org/examples/webgl_marchingcubes.html. Это проблема УФ-координат? Версия 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 ответ
Да. Ваш точечный шейдер использует ультрафиолетовые лучи, чтобы определить, где нужно рисовать точки... Если ваш алгоритм походного куба не настраивает ультрафиолетовые лучи, вам придется самостоятельно синтезировать некоторые из них... Вы можете сделать развертывание коробки... Это не слишком сложный, но было забавно выяснить... вы проходите грани геометрии... выясняете, на какой плоскости лежит треугольник, и проецируете вершины на эту ультрафиолетовую плоскость. Я позволил себе написать это для тебя:
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;
}