bool and smooth

This commit is contained in:
bk_office
2026-04-27 21:41:16 +08:00
parent 733114b941
commit 250eaaf59c
6 changed files with 69 additions and 13 deletions

View File

@ -11,11 +11,11 @@ cmd_marchtoy = on_command("march")
async def _(args: Message = CommandArg()):
if cmd := args.extract_plain_text():
try:
img = await render.render(cmd, (256, 256))
img = await render.render(cmd, (512, 512))
buffer = io.BytesIO()
# img.show()
# img.save("/mnt/d/output.png", format="GIF")
img.save(buffer, format="GIF")
img.save(buffer, format="PNG")
buffer.seek(0)
await cmd_marchtoy.send(await UniMessage().image(raw=buffer).export())
except Exception as e:

View File

@ -24,7 +24,10 @@ async def render(command: str, res: tuple[int, int]):
)
except Exception as e:
raise Exception(f"cannot compile glsl: {e}") from e
uniform = program["u_resolution"]
try:
uniform = program["u_resolution"]
except Exception as e:
raise Exception("无法获取 uniform可能相机位于物体内部")
uniform.write(np.array(res, dtype=np.float32))
vertices = np.array([-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0], dtype=np.float32)
indices = np.array([0, 1, 2, 1, 2, 3], dtype=np.int32)

View File

@ -81,6 +81,7 @@ class Object:
def __init__(self) -> None:
self.transform: Transform = Transform()
self.texture: Texture = Texture()
self.round_corner: float = 0.0
def parse_args(self, args: list[str]):
raise NotImplementedError
@ -172,7 +173,7 @@ class Capsule(Object):
@make_obj("smoothed", "mix")
class Smoothed(Object):
def __init__(self, _k: float = 0.25):
def __init__(self, _k: float = 12.00):
super().__init__()
self.block_a: str = "INF"
self.block_b: str = "INF"
@ -196,12 +197,56 @@ class Smoothed(Object):
def sdf_block_glsl(self):
return f"smin({self.block_a}, {self.block_b}, {self.k})"
@make_obj("intersect", "bool")
class BoolIntersect(Object):
def __init__(self):
super().__init__()
def parse_args(self, args: list[str]):
from konabot.plugins.marchtoy.scene import Scene
try:
if not len(args) >= 2:
raise Exception("expecting at least 2 args")
scene_a = Scene(args[0])
scene_b = Scene(args[1])
self.block_a = scene_a.canvas_objs[0][1]
self.block_b = scene_b.canvas_objs[0][1]
if len(args) > 2:
self.k = ArgParser.as_float(args[2], 0.25)
except Exception as e:
raise Exception(f"cannot build bool object over {args}: {e}")
def sdf_block_glsl(self):
return f"max({self.block_a}, {self.block_b})"
@make_obj("substract", "minus")
class BoolSubstract(Object):
def __init__(self):
super().__init__()
def parse_args(self, args: list[str]):
from konabot.plugins.marchtoy.scene import Scene
try:
if not len(args) >= 2:
raise Exception("expecting at least 2 args")
scene_a = Scene(args[0])
scene_b = Scene(args[1])
self.block_a = scene_a.canvas_objs[0][1]
self.block_b = scene_b.canvas_objs[0][1]
if len(args) > 2:
self.k = ArgParser.as_float(args[2], 0.25)
except Exception as e:
raise Exception(f"cannot build bool object over {args}: {e}")
def sdf_block_glsl(self):
return f"max({self.block_a}, -{self.block_b})"
@make_obj("camera", "cam")
class Camera(Object):
def __init__(self, _focus: float = 1.0) -> None:
def __init__(self, _focus: float = 2.0) -> None:
super().__init__()
self.focus = _focus
self.transform.translate(5.0, 5.0, 5.0).lookat(0.0, 0.0, 0.0)
self.transform.translate(8.0, 8.0, 8.0).lookat(0.0, 0.0, 0.0)
def parse_args(self, args: list[str]):
self.focus = ArgParser.as_float(args)

View File

@ -3,7 +3,7 @@ from konabot.plugins.marchtoy.utilities import ArgParser
OPERATION_ENTRIES = {}
def make_operation(*name: str):
def make_op(*name: str):
def decorator(op):
# OPERATION_ENTRIES[name] = op
for alias in [*name]:
@ -13,25 +13,25 @@ def make_operation(*name: str):
return decorator
@make_operation("pos", "translate", "position", "p")
@make_op("pos", "translate", "position", "p")
def translate(obj: Object, args: list[str]):
pos = ArgParser.as_vec3(args)
obj.transform.translate(pos[0], pos[1], pos[2])
@make_operation("rot", "rotate", "r")
@make_op("rot", "rotate", "r")
def rotate(obj: Object, args: list[str]):
pos = ArgParser.as_vec3(args)
obj.transform.rotate(pos[0], pos[1], pos[2])
@make_operation("lookat", "look", "l")
@make_op("lookat", "look", "l")
def lookat(obj: Object, args: list[str]):
pos = ArgParser.as_vec3(args)
obj.transform.lookat(pos[0], pos[1], pos[2])
@make_operation("color", "col", "texture")
@make_op("color", "col", "texture")
def color(obj: Object, args: list[str]):
try:
if len(args) == 1:
@ -48,3 +48,9 @@ def color(obj: Object, args: list[str]):
except:
raise Exception("unknown color")
@make_op("rounded", "round_corner", "corner")
def rounded(obj: Object, args: list[str]):
if len(args) >= 1:
obj.round_corner = ArgParser.as_float(args[0])

View File

@ -71,7 +71,9 @@ class Scene:
obj, sdf_expr = canvas_item
sdf_block += f"float sd{index} = {sdf_expr};"
sdf_block += f"if(sd{index} < qry.value)"
sdf_block += "{" + f"qry.value = sd{index}; qry.obj_id = {index}; " + "}\n"
# 1e-8 最好换成某个 epsilon
round_corner = f"- {obj.round_corner}" if obj.round_corner > 1e-8 else ""
sdf_block += "{" + f"qry.value = sd{index} {round_corner}; qry.obj_id = {index}; " + "}\n"
color = obj.texture.color
color_block += (
f"if(obj_id == {index}) return vec4("

View File

@ -1,6 +1,6 @@
#version 330
const float EPS = 0.001;
const int MAX_ITER = 64;
const int MAX_ITER = 128;
uniform vec2 u_resolution;
out vec4 fragColor;