Package: shadermake
shader-makeDrom project to make shader translator. shader-make currently only works with GLSL. It uses a decorator to transform itself into a GPU based function, here for OpenGL. You cannot currently reuse a shader function as a default function but we prepared the setup to do that. We haven't implemented every python feature that we don't think are usefull for the purpose of what we will be using it for, such as while loops that could be interesting.Compiling a simple function to shader codeFirst you will need to import the decorator and the shader engine you want to use. We currently only support OpenGL with GLSL support. shader-make will then do type analysis on the variables to generate C code that you can compile to GLSL (you have to specify the type of your input for it to work). Here is a simple GLSL function that takes two coordinates a and b and creates a vec3 with (x, y, x + y) :fromshadermake.decoratorimportmake_shaderfromshadermake.engines.openglimportOpenGLEngine,vec3@make_shader(OpenGLEngine,argument_types=[float,float])deftransform(x,y):returnvec3(x,y,x+y)And the resulting C code is the following when you do transform.c_code():vec3transform(floatx,floaty){returnvec3(x,y,x+y);}Linking multiple functionsWe will admit you have a cool python function called magic that you would like to use in multiple shader functions. You can do that using the parameter bound_shaders. For this example we will use the cool function f(x) = x + 1 and add it to our transform function :fromshadermake.decoratorimportmake_shaderfromshadermake.engines.openglimportOpenGLEngine,vec3@make_shader(OpenGLEngine,argument_types=[float])deff(x):returnx+1@make_shader(OpenGLEngine,argument_types=[float,float],bound_shaders=[f])deftransform(x,y):y=f(y)returnvec3(x,y,x+y)floatf(floatx){returnx+1;}vec3transform(floatx,floaty){y=f(y);returnvec3(x,y,x+y);}Inputs, outputs and uniformsWhen you want to compile a shader, it can be needed to import existing inputs, setup outputs or use uniform variables shared between every vertex. For this you can use a ShaderOptions element and use addInput, addOutput and addUniform to append metadata. You can also generate the default vertex shader data or fragment shader data using the useVertex or useFragment functions. The following example generates a function with an uniform displacement :fromshadermake.decoratorimportmake_shaderfromshadermake.engines.openglimportOpenGLEngine,ShaderOptions,vec2,vec3,vec4options=ShaderOptions()\.useVertex()\.addInput(vec4,"pos",0)\.addUniform(vec4,"delta")@make_shader(OpenGLEngine,shader_options=options)defshader():gl_Position=pos+deltalayout(location=0)invec4pos;uniformvec4delta;intshader(){gl_Position=pos+delta;return0;}If statementsThe usage of if statement is implemented by default but the usage of elif strongly increments the C final code size. Here is the example of the shader used in the testing and one of the following results (the one on the github actions architecture) :@make_shader(OpenGLEngine)defmain():x=0y=1z=x+yifz>0.5:y=2elifz>=1:y=4else:y=3u=0ifu+z>0.2:a=u-zelse:a=u+yintmain(){intx=0;inty=1;intz=x+y;if(z>0.5){y=2;}else{if(z>=1){y=4;}else{y=3;}}intu=0;if(u+z>0.2){inta=u-z;}else{inta=u+y;}return0;}As you can see here, the a variable is only created in the if scope. This isn't the default behavior of python so you might have to create your variable and initialize it before the if statement with a placeholder value like 0 to avoid your data being destroyed.