Default parameter saving in Shader Toy
After quite a lengthy Twitter discussion between myself and a bunch of other folks, I feel like I should use more than 140 characters to try and explain what I’m doing.
First of all, what am I going for with Shader Toy. The goal of Shader Toy is not to replace Render Monkey or FX Composer. Not by a long shot. My goal is primarily learning but as a secondary goal to create a small tool I can use to create simple shaders for simple games. This means I’m not creating uber effects or shaders that will be reused by lots of objects that need drastically tweaked values.
So my goal with the parameter editing UI has always been “you are editing the default values”. I know I could use annotations and/or separate files to generate configurations (such as Steel has parameter A = 5, B = 3, and C = 1) and that is useful, but that isn’t what I want to do (at least not right now). I simply want to change the effect’s default value for a given parameter.
As an example, let’s say I have a simple directional light effect with this parameter:
float3 lightDir;
I could manually create a default value for the direction simply by typing it in:
float3 lightDir = float3(-1, -1, -1);
What I want to be able to do is allow myself to use a UI to generate that default value rather than typing it in. This is a problem I don’t feel requires DXSAS or a custom runtime to do. I’m simply taking the action of typing in a default value and moving it to be attached to a UI.
The main issue for me is parsing through the text of the effect to be able to accurately set this value. This is something I’m currently thinking about ways to solve, but at this time have nothing.
I will say that I think the idea of saving configurations (like my Steel example above) has some cool uses and I may look into it at some point, but for now I just want to save a single default value to the effect and have that persist. Nothing more.
I think it was Catalin who said to use DXSAS + a custom pipeline compiler to emit non-DXSAS effect files, which is probably the way I would do it, too. But then I started to ignore my own NIH feelings recently
It seems like that’s just overkill. To require a whole content pipeline just for a single default value seems like someone’s doing something wrong. I can understand the use for having varying parameter sets, but for something this simple, why is changing it in the effect text such a bad idea? Other than trying to figure out the best way to parse the text and fix it.
So, doing it properly (yep, that might be a tiny tad exaggerating
) is overkill but reinventing the wheel in a limited way is not? Also, sooner or later you might want to have something like the range limits for your UI, and later some other stuff of the DXSAS thingy
Find something else to write a parser for
I don’t see how it’s reinventing the wheel. My goal is to not require custom content pipelines or runtimes for something as logically trivial as a default parameter value. Something that could easily be hand coded in the file shouldn’t need a whole suite of attributes and runtimes just to be able to set that default with UI.
And I already do support range limits for my UI (at least my float one); I just use ‘min’ and ‘max’ instead of the DXSAS names. I could switch or support both if I got the desire.
I guess the parsing seems fairly straightforward to me…
for each line in the input file
for each defined variable
if the line contains the variable
if a semicolon trails directly after the variable
replace the semicolon with the default value + “;”
else if an “=” trails directly after the variable
find the trailing semicolon
replace everything between “=” and “;” with the default value
write the line to the output file – this will either be the unedited or modified line
if everything succeeds
delete inputfile.old
rename the input file to inputfile.old
rename the output file to inputfile.fx
Hmmm – that was all nicely indented when I typed it
I currently have a working regex that handles the situation (taking into account line breaks, arbitrary spacing, and attributes) to replace the default value. It works, but I have some other issue to work out; my float slider always sticks to the max value when I tweak it. I’m guessing some circular “my slider changes the shader which forces a recompile which sets the parameter which changes the slider” type of issue. Just more fun stuff to fix.