Estoy participando en el evento de experiencia Nuggets sobre el código, detalles: muestra tus bloques de código creativo
prefacio
Hola a todos, este es el mago de CSS y WebGL - alphardex. En este artículo, usemos el componente raymarching de kokomi.js para dibujar una pokebola~
¡Salpica a Mo y lucha contra un ladrón en Tuo!
comienza la pintura
Primero bifurcar esta plantilla
Vea el bloque "Comencemos aquí ~", comenzaremos allí
material
Las pokebolas vienen en 3 colores: negro, blanco y rojo.
Primero define el material de 3 colores.
// 材质
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);
复制代码
en la esfera
El interior de la Poké Ball es una pequeña bola negra.
const sphere = new marcher.SphereSDF({
sdfVarName: "d1",
materialId: BLACK_MAT,
});
layer.addPrimitive(sphere);
复制代码
botón
Hay un botón blanco en el medio, que en realidad es un cilindro.
const button = new marcher.CylinderSDF({
sdfVarName: "d2",
materialId: WHITE_MAT,
radius: 0.1,
height: 0.54,
});
button.rotate(90, "x");
layer.addPrimitive(button);
复制代码
Capa esférica superior e inferior
En raymarching, solo se puede crear la esfera completa, ¿y qué si solo quieres la mitad de la esfera?
Cree un bloque temporal, muévalo a la mitad de la esfera y luego haga una intersección con la esfera para obtener la mitad de la 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);
复制代码
El botón en el medio de lo normal todavía está bloqueado por la capa esférica, por lo que debemos ahuecar la parte bloqueada.
hueco medio
Cree 2 cilindros (similar al botón anterior), aumente ligeramente el radio y la altura, y utilícelos para deducir las capas esféricas superior e inferior respectivamente para tener el efecto de ahuecar el medio
// 球壳(上):挖除中间镂空部分后
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();
复制代码
embellecer
Aquí puede jugar libremente, ya sea la iluminación, el ángulo de la cámara o el material, y se pueden optimizar otros factores.
Los resultados optimizados del autor son los siguientes