1 // Copyright 2016-2021 Doug Moen
2 // Licensed under the Apache License, version 2.0
3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0
4
5 #include <libcurv/render.h>
6
7 #include <libcurv/context.h>
8 #include <libcurv/exception.h>
9 #include <libcurv/function.h>
10 #include <libcurv/record.h>
11 #include <libcurv/shape.h>
12
13 #include <climits>
14
15 namespace curv {
16
17 const std::vector<const char*>
18 Render_Opts::shader_enum { "standard", "pew", "sf1" };
19
20 void
set_shader(Value val,const Context & cx)21 Render_Opts::set_shader(Value val, const Context& cx)
22 {
23 auto v = value_to_variant(val, cx);
24 if (v.first == "standard") {
25 if (v.second.is_missing()) {
26 shader_ = Shader::standard;
27 return;
28 }
29 goto error;
30 }
31 if (v.first == "pew") {
32 if (v.second.is_missing()) {
33 shader_ = Shader::pew;
34 return;
35 }
36 goto error;
37 }
38 if (v.first == "sf1") {
39 shader_ = Shader::sf1;
40 if (!v.second.is_missing()) {
41 sf1_ = maybe_function(v.second, cx);
42 if (sf1_ == nullptr)
43 goto error;
44 }
45 return;
46 }
47 error:
48 throw Exception(cx,
49 stringify(val," is not #standard|#pew|{sf1:<function>}"));
50 }
51
52 void
update_from_record(Record & r,const Context & cx)53 Render_Opts::update_from_record(
54 Record& r,
55 const Context& cx)
56 {
57 auto aa_val = r.find_field(make_symbol("aa"), cx);
58 if (!aa_val.is_missing()) {
59 aa_ = aa_val.to_int(1, INT_MAX, At_Field("aa", cx));
60 }
61 auto taa_val = r.find_field(make_symbol("taa"), cx);
62 if (!taa_val.is_missing()) {
63 taa_ = taa_val.to_int(1, INT_MAX, At_Field("taa", cx));
64 }
65 auto fdur_val = r.find_field(make_symbol("fdur"), cx);
66 if (!fdur_val.is_missing()) {
67 fdur_ = fdur_val.to_num(At_Field("fdur", cx));
68 }
69 auto bg_val = r.find_field(make_symbol("bg"), cx);
70 if (!bg_val.is_missing()) {
71 bg_ = value_to_vec3(bg_val, At_Field("bg", cx));
72 }
73 auto ray_max_iter_val = r.find_field(make_symbol("ray_max_iter"), cx);
74 if (!ray_max_iter_val.is_missing()) {
75 ray_max_iter_ = ray_max_iter_val.to_int(1, INT_MAX,
76 At_Field("ray_max_iter", cx));
77 }
78 auto ray_max_depth_val = r.find_field(make_symbol("ray_max_depth"), cx);
79 if (!ray_max_depth_val.is_missing()) {
80 ray_max_depth_ = ray_max_depth_val.to_num(
81 At_Field("ray_max_depth", cx));
82 }
83 auto shader_val = r.find_field(make_symbol("shader"), cx);
84 if (!shader_val.is_missing()) {
85 set_shader(shader_val, At_Field("shader", cx));
86 }
87 }
88
89 void
describe_opts(std::ostream & out,const char * prefix)90 Render_Opts::describe_opts(std::ostream& out, const char* prefix)
91 {
92 Render_Opts opts;
93 out
94 << prefix <<
95 "-O aa=<supersampling factor for antialiasing> (1 means disabled)\n"
96 << prefix <<
97 "-O taa=<supersampling factor for temporal antialiasing> (1 means disabled)\n"
98 << prefix <<
99 "-O fdur=<frame duration, in seconds> : Used with -Otaa and -Oanimate\n"
100 << prefix <<
101 "-O bg=<background colour>\n"
102 << prefix <<
103 "-O ray_max_iter=<maximum # of ray-march iterations> (default "
104 << opts.ray_max_iter_ << ")\n"
105 << prefix <<
106 "-O ray_max_depth=<maximum ray-marching depth> (default "
107 << opts.ray_max_depth_ << ")\n"
108 << prefix <<
109 "-O shader=#standard|#pew|{sf1:<function>}\n"
110 ;
111 }
112
113 bool
set_field(const std::string & name,Value val,const Context & cx)114 Render_Opts::set_field(const std::string& name, Value val, const Context& cx)
115 {
116 if (name == "aa") {
117 aa_ = val.to_int(1, INT_MAX, cx);
118 return true;
119 }
120 if (name == "taa") {
121 taa_ = val.to_int(1, INT_MAX, cx);
122 return true;
123 }
124 if (name == "fdur") {
125 fdur_ = val.to_num(cx);
126 return true;
127 }
128 if (name == "bg") {
129 bg_ = value_to_vec3(val, cx);
130 return true;
131 }
132 if (name == "ray_max_iter") {
133 ray_max_iter_ = val.to_int(1, INT_MAX, cx);
134 return true;
135 }
136 if (name == "ray_max_depth") {
137 ray_max_depth_ = val.to_num(cx);
138 return true;
139 }
140 if (name == "shader") {
141 set_shader(val, cx);
142 return true;
143 }
144 return false;
145 }
146
147 } // namespace curv
148