Last active
December 30, 2024 01:45
-
-
Save Ninja-Koala/74fa7652fb4de248949ce1e27b989c14 to your computer and use it in GitHub Desktop.
Convert a svg path to a shadertoy shader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import os | |
import sys | |
import numpy as np | |
def read_value(string, index): | |
#go to the beginning of the value | |
while svg_content[index] not in numerals: | |
index+=1 | |
#read in the value | |
number_string="" | |
while svg_content[index] in numerals: | |
number_string+=svg_content[index] | |
index+=1 | |
value=float(number_string) | |
return (value,index) | |
def read_coordinate(string, index): | |
(x_coordinate,index)=read_value(string,index) | |
(y_coordinate,index)=read_value(string,index) | |
point=np.array([x_coordinate,y_coordinate]) | |
return (point,index) | |
if len(sys.argv) not in (2,3): | |
print("Please give input svg file and optionally shader filename") | |
exit() | |
svg_file=open(sys.argv[1]) | |
svg_content=svg_file.read() | |
if svg_content.find("<svg") == -1: | |
print("Doesn't look like a svg file") | |
exit() | |
if len(sys.argv) == 3: | |
shaderfilename=sys.argv[2] | |
else: | |
shaderfilename=os.path.splitext(sys.argv[1])[0]+".glsl" | |
shaderfile = open(shaderfilename, 'w') | |
index=0 | |
numerals="0123456789-.eE" | |
path_index=0 | |
path_strings="" | |
path_dis_strings="" | |
point_lists=[] | |
segment_lists=[] | |
q_bezier_lists=[] | |
c_bezier_lists=[] | |
while svg_content.find("<path",index) != -1: | |
index=svg_content.find("<path",index) | |
index=svg_content.find(" d=\"",index) | |
index+=4 | |
initial_point=-1 | |
cur_point=-1 | |
point_list=[] | |
segment_list=[] | |
q_bezier_list=[] | |
c_bezier_list=[] | |
relative=False | |
while index < len(svg_content): | |
#m or M means move current point to given coordinate | |
if svg_content[index] in "mM": | |
if svg_content[index] == "m": | |
relative=True | |
else: | |
relative=False | |
first_iteration=True | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
if first_iteration: | |
initial_point=p1 | |
else: | |
segment_list+=[(cur_point,p1)] | |
cur_point=p1 | |
while svg_content[index] == " ": | |
index+=1 | |
first_iteration=False | |
cur_point=len(point_list)-1 | |
if initial_point == -1: | |
initial_point=cur_point | |
index-=1 | |
#l or L means line | |
if svg_content[index] in "lL": | |
if svg_content[index] == "l": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
segment_list+=[(p0,p1)] | |
cur_point=p1 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#h or H means horizontal line | |
if svg_content[index] in "hH": | |
if svg_content[index] == "h": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
(value,index)=read_value(svg_content,index) | |
coord=np.array([value,0]) | |
if True or cur_point!=-1: | |
if relative: | |
coord+=point_list[cur_point] | |
else: | |
coord[1]=point_list[cur_point][1] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
segment_list+=[(p0,p1)] | |
cur_point=p1 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#v or V means vertical line | |
if svg_content[index] in "vV": | |
if svg_content[index] == "v": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
(value,index)=read_value(svg_content,index) | |
coord=np.array([0,value]) | |
if cur_point!=-1: | |
if relative: | |
coord+=point_list[cur_point] | |
else: | |
coord[0]=point_list[cur_point][0] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
segment_list+=[(p0,p1)] | |
cur_point=p1 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#q or Q means quadratic bezier curve(s) | |
if svg_content[index] in "qQ": | |
if svg_content[index] == "q": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p2=len(point_list)-1 | |
q_bezier_list+=[(p0,p1,p2)] | |
cur_point=p2 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#t or T means smooth quadratic bezier curve(s) | |
if svg_content[index] in "tT": | |
if svg_content[index] == "t": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
if q_bezier_list[-1][-1] == cur_point: | |
last_control_point=point_list[q_bezier_list[-1][1]] | |
cur_coord=point_list[cur_point] | |
coord=2*cur_coord-last_control_point | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
else: | |
p1=cur_point | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p2=len(point_list)-1 | |
q_bezier_list+=[(p0,p1,p2)] | |
cur_point=p2 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#c or C means cubic bezier curve(s) | |
if svg_content[index] in "cC": | |
if svg_content[index] == "c": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p2=len(point_list)-1 | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p3=len(point_list)-1 | |
c_bezier_list+=[(p0,p1,p2,p3)] | |
cur_point=p3 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
#s or S means smooth cubic bezier curve(s) | |
if svg_content[index] in "sS": | |
if svg_content[index] == "s": | |
relative=True | |
else: | |
relative=False | |
index+=1 | |
while svg_content[index] == " ": | |
index+=1 | |
while svg_content[index] in numerals: | |
p0=cur_point | |
if c_bezier_list[-1][-1] == cur_point: | |
last_control_point=point_list[c_bezier_list[-1][2]] | |
cur_coord=point_list[cur_point] | |
coord=2*cur_coord-last_control_point | |
point_list+=[coord] | |
p1=len(point_list)-1 | |
else: | |
p1=cur_point | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p2=len(point_list)-1 | |
(coord,index)=read_coordinate(svg_content,index) | |
if relative and cur_point != -1: | |
coord+=point_list[cur_point] | |
point_list+=[coord] | |
p3=len(point_list)-1 | |
c_bezier_list+=[(p0,p1,p2,p3)] | |
cur_point=p3 | |
while svg_content[index] == " ": | |
index+=1 | |
index-=1 | |
if svg_content[index] in "zZ": | |
if np.linalg.norm(point_list[cur_point]-point_list[initial_point]) < .001: | |
if len(segment_list)>0 and segment_list[-1][-1] == cur_point: | |
tmp=list(segment_list[-1]) | |
tmp[-1]=initial_point | |
segment_list[-1]=tuple(tmp) | |
elif len(q_bezier_list)>0 and q_bezier_list[-1][-1] == cur_point: | |
tmp=list(q_bezier_list[-1]) | |
tmp[-1]=initial_point | |
q_bezier_list[-1]=tuple(tmp) | |
elif len(c_bezier_list)>0 and c_bezier_list[-1][-1] == cur_point: | |
tmp=list(c_bezier_list[-1]) | |
tmp[-1]=initial_point | |
c_bezier_list[-1]=tuple(tmp) | |
else: | |
print("Something weird happened…") | |
point_list=point_list[:-1] | |
else: | |
segment_list+=[(cur_point,initial_point)] | |
cur_point=initial_point | |
if svg_content[index] == "\"": | |
break | |
index+=1 | |
point_lists+=[point_list] | |
segment_lists+=[segment_list] | |
q_bezier_lists+=[q_bezier_list] | |
c_bezier_lists+=[c_bezier_list] | |
min_x=float("inf") | |
max_x=float("-inf") | |
min_y=float("inf") | |
max_y=float("-inf") | |
path_min_x=[] | |
path_max_x=[] | |
path_min_y=[] | |
path_max_y=[] | |
if len(point_lists)==0: | |
print("No path found in svg file") | |
exit() | |
for path_index in range(len(point_lists)): | |
#TODO: compute more accurate bounding box, see https://www.shadertoy.com/view/XdVBWd and https://www.shadertoy.com/view/lsyfWc | |
path_min_x+=[min(min_x,min(map(lambda x: x[0], point_lists[path_index])))] | |
path_max_x+=[max(max_x,max(map(lambda x: x[0], point_lists[path_index])))] | |
path_min_y+=[min(min_y,min(map(lambda x: x[1], point_lists[path_index])))] | |
path_max_y+=[max(max_y,max(map(lambda x: x[1], point_lists[path_index])))] | |
min_x=min(path_min_x) | |
max_x=max(path_max_x) | |
min_y=min(path_min_y) | |
max_y=max(path_max_y) | |
zoom=min(0.4/(max_y-min_y),0.8/(max_x-min_x)) | |
offset=np.array([(min_x+max_x)/2,(min_y+max_y)/2]) | |
max_x=(max_x-offset[0])*zoom | |
min_x=(min_x-offset[0])*zoom | |
max_y=-(max_y-offset[1])*zoom | |
min_y=-(min_y-offset[1])*zoom | |
#swap max_x and max_y because we changed sign | |
tmp=max_y | |
max_y=min_y | |
min_y=tmp | |
for path_index in range(len(point_lists)): | |
for i in range(len(point_lists[path_index])): | |
point_lists[path_index][i]=(point_lists[path_index][i]-offset)*zoom | |
point_lists[path_index][i]=np.array([point_lists[path_index][i][0],-point_lists[path_index][i][1]]) | |
path_max_x[path_index]=(path_max_x[path_index]-offset[0])*zoom | |
path_min_x[path_index]=(path_min_x[path_index]-offset[0])*zoom | |
path_max_y[path_index]=-(path_max_y[path_index]-offset[1])*zoom | |
path_min_y[path_index]=-(path_min_y[path_index]-offset[1])*zoom | |
#swap max_x and max_y because we changed sign | |
tmp=path_max_y[path_index] | |
path_max_y[path_index]=path_min_y[path_index] | |
path_min_y[path_index]=tmp | |
shader_template="""#define ZERO min(0,iFrame) | |
float border; | |
// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c | |
// Credits to Doublefresh for hinting there | |
int solve_quadric(vec2 coeffs, inout vec2 roots){{ | |
// normal form: x^2 + px + q = 0 | |
float p = coeffs[1] / 2.; | |
float q = coeffs[0]; | |
float D = p * p - q; | |
if (D < 0.){{ | |
return 0; | |
}} | |
else{{ | |
roots[0] = -sqrt(D) - p; | |
roots[1] = sqrt(D) - p; | |
return 2; | |
}} | |
}} | |
//From Trisomie21 | |
//But instead of his cancellation fix i'm using a newton iteration | |
int solve_cubic(vec3 coeffs, inout vec3 r){{ | |
float a = coeffs[2]; | |
float b = coeffs[1]; | |
float c = coeffs[0]; | |
float p = b - a*a / 3.0; | |
float q = a * (2.0*a*a - 9.0*b) / 27.0 + c; | |
float p3 = p*p*p; | |
float d = q*q + 4.0*p3 / 27.0; | |
float offset = -a / 3.0; | |
if(d >= 0.0) {{ // Single solution | |
float z = sqrt(d); | |
float u = (-q + z) / 2.0; | |
float v = (-q - z) / 2.0; | |
u = sign(u)*pow(abs(u),1.0/3.0); | |
v = sign(v)*pow(abs(v),1.0/3.0); | |
r[0] = offset + u + v; | |
//Single newton iteration to account for cancellation | |
float f = ((r[0] + a) * r[0] + b) * r[0] + c; | |
float f1 = (3. * r[0] + 2. * a) * r[0] + b; | |
r[0] -= f / f1; | |
return 1; | |
}} | |
float u = sqrt(-p / 3.0); | |
float v = acos(-sqrt( -27.0 / p3) * q / 2.0) / 3.0; | |
float m = cos(v), n = sin(v)*1.732050808; | |
//Single newton iteration to account for cancellation | |
//(once for every root) | |
r[0] = offset + u * (m + m); | |
r[1] = offset - u * (n + m); | |
r[2] = offset + u * (n - m); | |
vec3 f = ((r + a) * r + b) * r + c; | |
vec3 f1 = (3. * r + 2. * a) * r + b; | |
r -= f / f1; | |
return 3; | |
}} | |
float quadratic_bezier_normal_iteration(float t, vec2 a0, vec2 a1, vec2 a2){{ | |
//horner's method | |
vec2 a_1=a1+t*a2; | |
vec2 uv_to_p=a0+t*a_1; | |
vec2 tang=a_1+t*a2; | |
float l_tang=dot(tang,tang); | |
return t-dot(tang,uv_to_p)/l_tang; | |
}} | |
float quadratic_bezier_dis_approx_sq(vec2 uv, vec2 p0, vec2 p1, vec2 p2){{ | |
vec2 a2 = p0 - 2. * p1 + p2; | |
vec2 a1 = -2. * p0 + 2. * p1; | |
vec2 a0 = p0 - uv; | |
float d0 = 1e38; | |
float t; | |
vec3 params=vec3(0,.5,1); | |
if(all(lessThan(uv,max(max(p0,p1),p2)+border)) && all(greaterThan(uv,min(min(p0,p1),p2)-border))){{ | |
for(int i=ZERO;i<3;i++){{ | |
t=params[i]; | |
for(int j=ZERO;j<3;j++){{ | |
t=quadratic_bezier_normal_iteration(t,a0,a1,a2); | |
}} | |
t=clamp(t,0.,1.); | |
vec2 uv_to_p=(a2*t+a1)*t+a0; | |
d0=min(d0,dot(uv_to_p,uv_to_p)); | |
}} | |
}} | |
return d0; | |
}} | |
float cubic_bezier_normal_iteration(float t, vec2 a0, vec2 a1, vec2 a2, vec2 a3){{ | |
//horner's method | |
vec2 a_2=a2+t*a3; | |
vec2 a_1=a1+t*a_2; | |
vec2 b_2=a_2+t*a3; | |
vec2 uv_to_p=a0+t*a_1; | |
vec2 tang=a_1+t*b_2; | |
float l_tang=dot(tang,tang); | |
return t-dot(tang,uv_to_p)/l_tang; | |
}} | |
float cubic_bezier_dis_approx_sq(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3){{ | |
vec2 a3 = (-p0 + 3. * p1 - 3. * p2 + p3); | |
vec2 a2 = (3. * p0 - 6. * p1 + 3. * p2); | |
vec2 a1 = (-3. * p0 + 3. * p1); | |
vec2 a0 = p0 - uv; | |
float d0 = 1e38; | |
float t; | |
vec3 params=vec3(0,.5,1); | |
if(all(lessThan(uv,max(max(p0,p1),max(p2,p3))+border)) && all(greaterThan(uv,min(min(p0,p1),min(p2,p3))-border))){{ | |
for(int i=ZERO;i<3;i++){{ | |
t=params[i]; | |
for(int j=ZERO;j<3;j++){{ | |
t=cubic_bezier_normal_iteration(t,a0,a1,a2,a3); | |
}} | |
t=clamp(t,0.,1.); | |
vec2 uv_to_p=((a3*t+a2)*t+a1)*t+a0; | |
d0=min(d0,dot(uv_to_p,uv_to_p)); | |
}} | |
}} | |
return d0; | |
}} | |
//segment_dis_sq by iq | |
float length2( vec2 v ) {{ return dot(v,v); }} | |
float segment_dis_sq( vec2 p, vec2 a, vec2 b ){{ | |
vec2 pa = p-a, ba = b-a; | |
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); | |
return length2( pa - ba*h ); | |
}} | |
int segment_int_test(vec2 uv, vec2 p0, vec2 p1){{ | |
p0-=uv; | |
p1-=uv; | |
int ret; | |
if(p0.y*p1.y<0.){{ | |
vec2 nor=p0-p1; | |
nor=vec2(nor.y,-nor.x); | |
float sgn; | |
if(p0.y>p1.y){{ | |
sgn=1.; | |
}} | |
else{{ | |
sgn=-1.; | |
}} | |
if(dot(nor,p0)*sgn<0.){{ | |
ret=0; | |
}} | |
else{{ | |
ret=1; | |
}} | |
}} | |
else{{ | |
ret=0; | |
}} | |
return ret; | |
}} | |
int quadratic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2){{ | |
float qu = (p0.y - 2. * p1.y + p2.y); | |
float li = (-2. * p0.y + 2. * p1.y); | |
float co = p0.y - uv.y; | |
vec2 roots = vec2(1e38); | |
int n_roots = solve_quadric(vec2(co/qu,li/qu),roots); | |
int n_ints = 0; | |
for(int i=ZERO;i<n_roots;i++){{ | |
if(roots[i] >= 0. && roots[i] <= 1.){{ | |
float x_pos = p0.x - 2. * p1.x + p2.x; | |
x_pos = x_pos * roots[i] + -2. * p0.x + 2. * p1.x; | |
x_pos = x_pos * roots[i] + p0.x; | |
if(x_pos > uv.x){{ | |
n_ints++; | |
}} | |
}} | |
}} | |
return n_ints; | |
}} | |
int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3){{ | |
float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y); | |
float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y); | |
float li = (-3. * p0.y + 3. * p1.y); | |
float co = p0.y - uv.y; | |
vec3 roots = vec3(1e38); | |
int n_roots; | |
int n_ints=0; | |
if(uv.x<min(min(p0.x,p1.x),min(p2.x,p3.x))){{ | |
if(uv.y>=min(p0.y,p3.y) && uv.y<=max(p0.y,p3.y)){{ | |
n_ints=1; | |
}} | |
}} | |
else{{ | |
if(abs(cu) < .0001){{ | |
n_roots = solve_quadric(vec2(co/qu,li/qu),roots.xy); | |
}} | |
else{{ | |
n_roots = solve_cubic(vec3(co/cu,li/cu,qu/cu),roots); | |
}} | |
for(int i=ZERO;i<n_roots;i++){{ | |
if(roots[i] >= 0. && roots[i] <= 1.){{ | |
float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x; | |
x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x; | |
x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x; | |
x_pos = x_pos * roots[i] + p0.x; | |
if(x_pos > uv.x){{ | |
n_ints++; | |
}} | |
}} | |
}} | |
}} | |
return n_ints; | |
}} | |
{}void mainImage(out vec4 fragColor, in vec2 fragCoord){{ | |
border=1./iResolution.x; | |
vec2 uv=fragCoord.xy/iResolution.xy; | |
uv-=.5; | |
uv.y*=iResolution.y/iResolution.x; | |
vec2 mouse=vec2(0); | |
if(iMouse.x>0.0){{ | |
mouse = iMouse.xy / iResolution.y; | |
mouse.x -= .5 * iResolution.x / iResolution.y; | |
mouse.y -= .75; | |
}} | |
const float pi=3.14159265358979; | |
float t0=smoothstep(0.,5.,iTime); | |
float t1=t0*6.*pi; | |
mat2 rot=mat2(cos(t1),sin(t1),-sin(t1),cos(t1)); | |
border*=exp(4.*mouse.y)*exp(1.-1.*t0); | |
uv*=exp(4.*mouse.y)*exp(1.-1.*t0); | |
uv*=rot; | |
uv.x+=mouse.x; | |
float dis_sq=1e38; | |
if(all(lessThan(uv,vec2({:.6},{:.6})+border)) && all(greaterThan(uv,vec2({:.6},{:.6})-border))){{ | |
{} }} | |
float dis=sign(dis_sq)*sqrt(abs(dis_sq)); | |
fragColor=vec4(smoothstep(-border, border, dis)); | |
}}""" | |
path_template="""float path{}_dis_sq(vec2 uv){{ | |
float dis_sq=1e38; | |
int num_its=0; | |
{} | |
if(all(lessThan(uv,vec2({:.6},{:.6})+border)) && all(greaterThan(uv,vec2({:.6},{:.6})-border))){{ | |
{} }} | |
float sgn=1.; | |
if(num_its%2==1){{ | |
sgn=-1.; | |
}} | |
return sgn*dis_sq; | |
}} | |
""" | |
path_dis_template="\t\tdis_sq=min(dis_sq,path{}_dis_sq(uv));\n" | |
segment_dis_template="\t\t\tdis_sq=min(dis_sq,segment_dis_sq(uv,{}));\n" | |
q_bezier_dis_template="\t\t\tdis_sq=min(dis_sq,quadratic_bezier_dis_approx_sq(uv,{}));\n" | |
c_bezier_dis_template="\t\t\tdis_sq=min(dis_sq,cubic_bezier_dis_approx_sq(uv,{}));\n" | |
segment_int_template="\t\t\tnum_its+=segment_int_test(uv,{});\n" | |
q_bezier_int_template="\t\t\tnum_its+=quadratic_bezier_int_test(uv,{});\n" | |
c_bezier_int_template="\t\t\tnum_its+=cubic_bezier_int_test(uv,{});\n" | |
vector_template="vec2({:.6},{:.6})" | |
ivec2_template="ivec2({},{})" | |
ivec3_template="ivec3({},{},{})" | |
ivec4_template="ivec4({},{},{},{})" | |
points_template="\tvec2[{}] p=vec2[](" | |
segments_template="\tivec2[{}] seg=ivec2[](" | |
q_beziers_template="\tivec3[{}] q_bez=ivec3[](" | |
c_beziers_template="\tivec4[{}] c_bez=ivec4[](" | |
segment_points_template="p[seg[i][{}]]," | |
q_bezier_points_template="p[q_bez[i][{}]]," | |
c_bezier_points_template="p[c_bez[i][{}]]," | |
loop_template="""\t\tfor(int i=ZERO;i<{};i++){{\n{}\t\t}}\n""" | |
data_string="" | |
loops="" | |
points="" | |
points=points_template.format(len(point_lists[path_index])) | |
separator=",\n\t"+(len(points)-1)*" " | |
for (i,point) in enumerate(point_lists[path_index]): | |
points+=vector_template.format(point[0],point[1])+separator | |
points=points[:-len(separator)]+");\n" | |
data_string+=points | |
if len(segment_lists[path_index])>0: | |
segments=segments_template.format(len(segment_lists[path_index])) | |
separator=",\n\t"+(len(segments)-1)*" " | |
for (i,curve) in enumerate(segment_lists[path_index]): | |
segments+=ivec2_template.format(curve[0],curve[1])+separator | |
segments=segments[:-len(separator)]+");\n" | |
data_string+="\n"+segments | |
segment_points="" | |
for i in range(2): | |
segment_points+=segment_points_template.format(i) | |
segment_points=segment_points[:-1] | |
loop_body=segment_dis_template.format(segment_points) | |
loop_body+=segment_int_template.format(segment_points) | |
loops+=loop_template.format(len(segment_lists[path_index]),loop_body) | |
if len(q_bezier_lists[path_index])>0: | |
q_beziers=q_beziers_template.format(len(q_bezier_lists[path_index])) | |
separator=",\n\t"+(len(q_beziers)-1)*" " | |
for (i,curve) in enumerate(q_bezier_lists[path_index]): | |
q_beziers+=ivec3_template.format(curve[0],curve[1],curve[2])+separator | |
q_beziers=q_beziers[:-len(separator)]+");\n" | |
data_string+="\n"+q_beziers | |
q_bezier_points="" | |
for i in range(3): | |
q_bezier_points+=q_bezier_points_template.format(i) | |
q_bezier_points=q_bezier_points[:-1] | |
loop_body=q_bezier_dis_template.format(q_bezier_points) | |
loop_body+=q_bezier_int_template.format(q_bezier_points) | |
loops+=loop_template.format(len(q_bezier_lists[path_index]),loop_body) | |
if len(c_bezier_lists[path_index])>0: | |
c_beziers=c_beziers_template.format(len(c_bezier_lists[path_index])) | |
separator=",\n\t"+(len(c_beziers)-1)*" " | |
for (i,curve) in enumerate(c_bezier_lists[path_index]): | |
c_beziers+=ivec4_template.format(curve[0],curve[1],curve[2],curve[3])+separator | |
c_beziers=c_beziers[:-len(separator)]+");\n" | |
data_string+="\n"+c_beziers | |
c_bezier_points="" | |
for i in range(4): | |
c_bezier_points+=c_bezier_points_template.format(i) | |
c_bezier_points=c_bezier_points[:-1] | |
loop_body=c_bezier_dis_template.format(c_bezier_points) | |
loop_body+=c_bezier_int_template.format(c_bezier_points) | |
loops+=loop_template.format(len(c_bezier_lists[path_index]),loop_body) | |
p_max_x=path_max_x[path_index] | |
p_max_y=path_max_y[path_index] | |
p_min_x=path_min_x[path_index] | |
p_min_y=path_min_y[path_index] | |
path_strings+=path_template.format(path_index,data_string,p_max_x,p_max_y,p_min_x,p_min_y,loops) | |
path_dis_strings+=path_dis_template.format(path_index) | |
shader_string=shader_template.format(path_strings,max_x,max_y,min_x,min_y,path_dis_strings) | |
shaderfile.write(shader_string) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment