desenhar uma pokebola com raymarching

Estou participando do evento Nuggets Experience sobre o código, detalhes: mostre seus blocos de código criativos

prefácio

Olá a todos, este é o mágico de CSS e WebGL - alphardex. Neste artigo, vamos usar o componente raymarching do kokomi.js para desenhar uma pokeball~

Jogue em Mo e lute contra um ladrão em Tuo!

pintura começa

Primeiro bifurque este modelo

codesandbox.io/s/kokomi-js…

Veja o bloco "Vamos começar aqui~", vamos começar por aí

material

Pokébolas vêm em 3 cores: preto, branco e vermelho

Primeiro defina o material de 3 cores

// 材质
const BLACK_MAT = "1.0";
const WHITE_MAT = "2.0";
const RED_MAT = "3.0";

const mat = new marcher.SDFMaterial();
mat.addColorMaterial(BLACK_MAT, 0, 0, 0);
mat.addColorMaterial(WHITE_MAT, 255, 255, 255);
mat.addColorMaterial(RED_MAT, 255, 0, 0);
mar.setMaterial(mat);
复制代码

Na esfera

O interior da Pokébola é uma pequena bola preta

const sphere = new marcher.SphereSDF({
  sdfVarName: "d1",
  materialId: BLACK_MAT,
});
layer.addPrimitive(sphere);
复制代码

LK4vIP.png

botão

Há um botão branco no meio, que na verdade é um cilindro

const button = new marcher.CylinderSDF({
  sdfVarName: "d2",
  materialId: WHITE_MAT,
  radius: 0.1,
  height: 0.54,
});
button.rotate(90, "x");
layer.addPrimitive(button);
复制代码

LK5GIx.png

Casca esférica superior e inferior

Em raymarching, apenas a esfera inteira pode ser criada, e daí se você quiser apenas metade da esfera?

Crie um bloco temporário, mova-o para metade da esfera e, em seguida, cruze a esfera para obter metade da esfera

// 球壳(上)
const shellUpper = new marcher.SphereSDF({
  sdfVarName: "d3",
  materialId: "3",
  radius: 0.55,
});

const clipBoxUpper = new marcher.BoxSDF({
  sdfVarName: "d4",
  width: 0.55,
  height: 0.55,
  depth: 0.55,
});
clipBoxUpper.hide();
clipBoxUpper.translate(0, -0.6, 0);

layer.addPrimitive(clipBoxUpper);
layer.addPrimitive(shellUpper);

shellUpper.intersect(clipBoxUpper);

// 球壳(下)
const shellLower = new marcher.SphereSDF({
  sdfVarName: "d6",
  materialId: WHITE_MAT,
  radius: 0.55,
});

const clipBoxLower = new marcher.BoxSDF({
  sdfVarName: "d5",
  width: 0.55,
  height: 0.55,
  depth: 0.55,
});
clipBoxLower.hide();
clipBoxLower.translate(0, 0.6, 0);

layer.addPrimitive(clipBoxLower);
layer.addPrimitive(shellLower);

shellLower.intersect(clipBoxLower);
复制代码

LKI0pT.png

O botão no meio do normal ainda está bloqueado pela casca esférica, então precisamos esvaziar a parte bloqueada

oco médio

Crie 2 cilindros (semelhante ao botão anterior), aumente ligeiramente o raio e a altura e use-os para deduzir as conchas esféricas superior e inferior, respectivamente, para ter o efeito de esvaziar o meio

// 球壳(上):挖除中间镂空部分后
const clipCylinderCenter1 = new marcher.CylinderSDF({
  sdfVarName: "d7",
  radius: 0.15,
  height: 0.6,
  materialId: RED_MAT,
});
clipCylinderCenter1.rotate(90, "x");

layer.addPrimitive(clipCylinderCenter1);

clipCylinderCenter1.subtract(shellUpper);

shellUpper.hide();

// 球壳下:挖除中间镂空部分后
const clipCylinderCenter2 = new marcher.CylinderSDF({
  sdfVarName: "d8",
  radius: 0.15,
  height: 0.6,
  materialId: WHITE_MAT,
});
clipCylinderCenter2.rotate(90, "x");

layer.addPrimitive(clipCylinderCenter2);

clipCylinderCenter2.subtract(shellLower);

shellLower.hide();
复制代码

LKoECV.png

embelezar

Aqui você pode jogar livremente, seja iluminação, ângulo da câmera ou material e outros fatores podem ser otimizados

Os resultados otimizados do autor são os seguintes

LKobMF.gif

endereço do projeto

Acho que você gosta

Origin juejin.im/post/7085999564725059620
Recomendado
Clasificación