1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#![allow(dead_code)] // @TODO @TEMPORARY
use std::fmt::Write;
// we're only writing numbers and strings so write! should never fail.
macro_rules! write_str {
($( $arg:tt )*) => { write!($($arg)*).unwrap() }
}
enum R3ToR3 {
Identity,
Translate([f32; 3])
}
enum RToR {
Identity,
Add(f32)
}
pub struct Sdf {
pre: R3ToR3,
post: RToR
}
impl RToR {
/// treats `v<*initial value of var_idx>` as the input, and puts the output in `v<final value of *var_idx>`.
fn to_glsl(&self, code: &mut String, var_idx: &mut u32) {
use RToR::*;
let input = *var_idx;
match self {
Identity => {}, // no code
Add(x) => {
*var_idx += 1;
let output = *var_idx;
write_str!(code, "float v{output} = v{input} + {x};\n");
}
}
}
}
impl R3ToR3 {
/// treats `v<*initial value of var_idx>` as the input, and puts the output in `v<final value of *var_idx>`.
fn to_glsl(&self, code: &mut String, var_idx: &mut u32) {
use R3ToR3::*;
let input = *var_idx;
match self {
Identity => {}, // no code
Translate([x, y, z]) => {
*var_idx += 1;
let output = *var_idx;
write_str!(code, "vec3 v{output} = v{input} + vec3({x}, {y}, {z});\n");
},
}
}
}
impl Sdf {
/// test sphere
pub fn sphere() -> Self {
Self {
pre: R3ToR3::Identity,
post: RToR::Identity
}
}
/// appends some glsl code including a function `float sdf(vec3 p) { ... }`
pub fn to_glsl(&self, code: &mut String) {
code.push_str("float sdf(vec3 p) {\n");
// don't start out right next to the origin, since weird stuff might be happening there
let origin_dist: f32 = 3.0;
write_str!(code, "vec3 v0 = p - vec3(0,0,-{}.);\n", origin_dist);
let mut var_idx = 0;
self.pre.to_glsl(code, &mut var_idx);
write_str!(code, "float v{} = length(v{}) - 1.0;\n", var_idx + 1, var_idx);
var_idx += 1;
self.post.to_glsl(code, &mut var_idx);
write_str!(code, "return v{var_idx};\n");
code.push('}');
}
}
|