尝试 gl backend
This commit is contained in:
@ -18,8 +18,8 @@ from dataclasses import dataclass
|
||||
import re
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
from konabot.plugins.marchtoy.obj import Object, Camera, OBJECT_ENTRIES
|
||||
from konabot.plugins.marchtoy.op import OPERATION_ENTRIES
|
||||
from obj import Object, Camera, OBJECT_ENTRIES
|
||||
from op import OPERATION_ENTRIES
|
||||
from typing import Optional
|
||||
|
||||
@dataclass
|
||||
@ -113,8 +113,8 @@ class Scene:
|
||||
def __str__(self) -> str:
|
||||
return ", ".join([str(type(obj)) for obj in self.canvas_objs])
|
||||
|
||||
def compile(self) -> str:
|
||||
PATH = pathlib.Path(__file__).parent / "shaders" / "raymarch.sksl"
|
||||
def compile(self, fs_src: str = "frag.glsl") -> str:
|
||||
PATH = pathlib.Path(__file__).parent / "shaders" / fs_src
|
||||
with PATH.open(encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
sdf_block: str = ""
|
||||
|
||||
37
konabot/plugins/marchtoy/gl_render.py
Normal file
37
konabot/plugins/marchtoy/gl_render.py
Normal file
@ -0,0 +1,37 @@
|
||||
"""
|
||||
headless moderngl
|
||||
"""
|
||||
import pathlib
|
||||
import moderngl
|
||||
from command import Scene
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
def render(vs: str, fs: str, res: tuple[int, int]):
|
||||
ctx = moderngl.create_context(standalone=True)
|
||||
try:
|
||||
program = ctx.program(
|
||||
vertex_shader=vs,
|
||||
fragment_shader=fs
|
||||
)
|
||||
except Exception as _:
|
||||
raise Exception("cannot compile glsl")
|
||||
uniform = program['u_resolution']
|
||||
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)
|
||||
ibo = ctx.buffer(indices)
|
||||
vbo = ctx.buffer(vertices)
|
||||
vao = ctx.vertex_array(program, vbo, 'in_position', index_buffer = ibo)
|
||||
fbo = ctx.simple_framebuffer(res)
|
||||
fbo.use()
|
||||
fbo.clear(0.0, 0.0, 0.0, 0.0)
|
||||
vao.render(moderngl.TRIANGLES)
|
||||
Image.frombytes('RGB', fbo.size, fbo.read(), 'raw', 'RGB', 0, -1).show()
|
||||
|
||||
fs = Scene("cube camera.pos(1).lookat(0)").compile()
|
||||
PATH = pathlib.Path(__file__).parent / "shaders"
|
||||
with (PATH / "vert.glsl").open(encoding='utf-8') as f:
|
||||
vs = f.read()
|
||||
|
||||
render(vs, fs, (320, 320))
|
||||
@ -1,6 +1,6 @@
|
||||
import numpy as np
|
||||
from konabot.plugins.marchtoy.texture import Texture
|
||||
from konabot.plugins.marchtoy.utilities import ArgParser, SkslFormatter
|
||||
from texture import Texture
|
||||
from utilities import ArgParser, Formatter
|
||||
|
||||
OBJECT_ENTRIES = {}
|
||||
|
||||
@ -65,7 +65,6 @@ class Transform:
|
||||
zaxis = Transform.normalize(q - p)
|
||||
xaxis = Transform.normalize(np.cross(zaxis, up))
|
||||
yaxis = Transform.normalize(np.cross(xaxis, zaxis))
|
||||
# 约定本地 -Z 为“朝前”,这样和 shader 中使用的相机射线方向保持一致。
|
||||
self.t[:3, 0] = xaxis
|
||||
self.t[:3, 1] = yaxis
|
||||
self.t[:3, 2] = -zaxis
|
||||
@ -73,7 +72,7 @@ class Transform:
|
||||
|
||||
def p_expr(self) -> str:
|
||||
inv = np.linalg.inv(self.t) # + 1e-5 * np.identity(4, dtype=np.float32))
|
||||
return f"({SkslFormatter.mat4(inv)} * float4(p, 1.0)).xyz"
|
||||
return f"({Formatter.float4(inv)} * float4(p, 1.0)).xyz"
|
||||
|
||||
|
||||
class Object:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from konabot.plugins.marchtoy.obj import Object
|
||||
from obj import Object
|
||||
import numpy as np
|
||||
from konabot.plugins.marchtoy.utilities import ArgParser
|
||||
from utilities import ArgParser
|
||||
|
||||
OPERATION_ENTRIES = {}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from konabot.plugins.marchtoy.command import Scene
|
||||
from command import Scene
|
||||
import skia
|
||||
import struct
|
||||
from PIL import Image
|
||||
|
||||
83
konabot/plugins/marchtoy/shaders/frag.glsl
Normal file
83
konabot/plugins/marchtoy/shaders/frag.glsl
Normal file
@ -0,0 +1,83 @@
|
||||
#version 330
|
||||
uniform vec2 u_resolution;
|
||||
// compatibility
|
||||
#define float4x4 mat4x4
|
||||
#define float4 vec4
|
||||
#define float3 vec3
|
||||
#define float2 vec2
|
||||
|
||||
const float EPS = 0.001;
|
||||
const int MAX_ITER = 64;
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
struct sdQuery {
|
||||
float value;
|
||||
int obj_id;
|
||||
};
|
||||
|
||||
float sdCube(vec3 p, vec3 b) {
|
||||
p = abs(p) - b;
|
||||
return length(max(p, 0.0)) + min(max(p.x, max(p.y, p.z)), 0.0);
|
||||
}
|
||||
|
||||
float sdSphere(vec3 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
sdQuery sd(vec3 p) {
|
||||
sdQuery qry;
|
||||
qry.value = 100000000.0;
|
||||
qry.obj_id = -1;
|
||||
<SDF_BLOCK>
|
||||
return qry;
|
||||
}
|
||||
|
||||
vec3 nrm(vec3 p) {
|
||||
vec2 d = vec2(EPS, 0.0);
|
||||
return normalize(vec3(
|
||||
sd(p + d.xyy).value - sd(p - d.xyy).value,
|
||||
sd(p + d.yxy).value - sd(p - d.yxy).value,
|
||||
sd(p + d.yyx).value - sd(p - d.yyx).value
|
||||
));
|
||||
}
|
||||
|
||||
vec4 materialColor(int obj_id) {
|
||||
<COLOR_BLOCK>
|
||||
return vec4(1.0);
|
||||
}
|
||||
|
||||
vec4 color(vec3 p, int obj_id) {
|
||||
vec3 normal = nrm(p);
|
||||
vec3 light_dir = normalize(vec3(0.5, 0.8, -0.6));
|
||||
float light = 0.2 + 0.8 * max(dot(normal, light_dir), 0.0);
|
||||
vec4 base = materialColor(obj_id);
|
||||
return vec4(base.rgb * light, base.a);
|
||||
}
|
||||
|
||||
vec4 march(vec3 p, vec3 r) {
|
||||
sdQuery qry;
|
||||
vec4 col = vec4(0.0);
|
||||
for(int i = 0; i < MAX_ITER; ++i) {
|
||||
qry = sd(p);
|
||||
if(qry.value < EPS){
|
||||
col = color(p, qry.obj_id);
|
||||
break;
|
||||
}
|
||||
p += qry.value * r;
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = -2. * (fragCoord / u_resolution - .5) * vec2(u_resolution.x / u_resolution.y, 1.);
|
||||
vec3 c_p = vec3(<CAM_POS>);
|
||||
vec3 c_z = normalize(vec3(<CAM_DIR>));
|
||||
vec3 world_up = abs(c_z.y) > 0.999 ? vec3(0., 0., 1.) : vec3(0., 1., 0.);
|
||||
vec3 c_x = normalize(cross(c_z, world_up));
|
||||
vec3 c_y = normalize(cross(c_x, c_z));
|
||||
mat3 view = mat3(c_x, c_y, c_z);
|
||||
vec3 r = normalize(vec3(uv, <CAM_FOCUS>));
|
||||
fragColor = march(c_p, view * r);
|
||||
}
|
||||
7
konabot/plugins/marchtoy/shaders/vert.glsl
Normal file
7
konabot/plugins/marchtoy/shaders/vert.glsl
Normal file
@ -0,0 +1,7 @@
|
||||
#version 330
|
||||
in vec2 in_position;
|
||||
out vec2 fragCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(in_position, 0.0, 1.0);
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
import numpy as np
|
||||
from konabot.plugins.marchtoy.texture import COLORS
|
||||
from texture import COLORS
|
||||
|
||||
|
||||
class SkslFormatter:
|
||||
class Formatter:
|
||||
@staticmethod
|
||||
def mat4(m: np.ndarray) -> str:
|
||||
def float4(m: np.ndarray) -> str:
|
||||
if m.shape != (4, 4):
|
||||
m = np.identity(4)
|
||||
v_0 = ", ".join([str(x) for x in m[0]])
|
||||
|
||||
Reference in New Issue
Block a user