I am participating in the Code nuggets experience, details: Show your creative code blocks
preface
Hi, here is CSS and WebGL magic – Alphardex. This article uses the Raymarching component of Kokomi. Js to draw a Sprite ball
Pour it on mo! Give it to the thief!
Start painting
First fork the template
Codesandbox. IO/s/kokomi – js…
See the “Start here ~” code block and we’ll start there
The material
The balls come in three colors: black, white and red
First, define the materials for the three colors
/ / material
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);
Copy the code
The ball inside
Inside the ball is a small black ball
const sphere = new marcher.SphereSDF({
sdfVarName: "d1".materialId: BLACK_MAT,
});
layer.addPrimitive(sphere);
Copy the code
button
There’s a white button in the middle, which is actually a cylinder
const button = new marcher.CylinderSDF({
sdfVarName: "d2".materialId: WHITE_MAT,
radius: 0.1.height: 0.54}); button.rotate(90."x");
layer.addPrimitive(button);
Copy the code
Up and down the spherical shell
Raymarching can only create whole spheres, so what if you only want half of a sphere?
Create a temporary square, move it to half of the ball, and then intersect with the sphere to get half of the sphere
// the ball shell (top)
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);
Copy the code
Again, the button in the middle of the normal line is blocked by the shell, and we’re going to have to hollow it out
The middle hollow out
Create two cylinders (similar to the previous button), slightly increase the radius and height, and use them to deduct the upper and lower shells respectively to create the effect of digging between the air
// Ball shell (top) : after cutting the hollow part in the middle
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();
// Under the ball shell: after cutting the hollow part in the middle
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();
Copy the code
beautify
There’s a lot of freedom here, and everything from lighting to camera angles to textures can be optimized
The author’s optimized results are as follows