Can a shader modulate the color of a texture in a TextureProgress control? For example, say I have a vertical TextureProgress:[img width=183 height=241]http://i.imgur.com/z0ckCYN.gif[/img]And I would like to modulate the color of the 'progress' texture via shader, based on the numeric value of the progress bar. Since it is not a sprite, can the texture somehow expose itself via script and allow a shader to manipulate its color? I am just curious to know if this is even possible before I consider selling my soul to dabble in the black art of shader programming.

uniforms are public/accessible from GDScript.I couldn't get a material override to work/show up on textureProgress however building a custom progress bar from a panel node is totally doable. I used shaderGraph for the example, see attachment.

Putting a material on a TextureProgress seemed to work fine for me. However, there's a big catch: the shader works on the whole CanvasItem, so it'll affect the over, under, and progress textures. So you'll probably want to use a separate node for the actual progress bar. Ignoring that, here's how to do a simple shader that fades the modulate color between two colors. [img width=550 height=182]http://i.imgur.com/F2gEQE2.gif[/img] [size=8pt][i](sorry for the weird bit at the end, some glitch with my gif recorder)[/i][/size]You would have to set the parameter on the shader to match the progress value of your progress bar via GDScript. [img width=760 height=336]http://godotdevelopers.org/index.php?action=dlattach;topic=15504.0;attach=2229;image[/img]It sounds like you're not familiar with shaders, so here's a line-by-line breakdown. Sorry if it's totally overkill.[tt]uniform float percentfull;[/tt] - [tt]uniform[/tt] is godot's shader language equivalent of the [tt]export[/tt] keyword for variables in GDScript, it means the variable comes from outside the shader and is exposed in the editor. [tt]float[/tt], it's a float, obviously. This variable will be the 0-1 measure of how full the progress bar is. We'll use it to blend between the empty color and the full color. [tt] ;[/tt] The shading language requires a semicolon at the end of every line. [tt]uniform color emptyColor; uniform color fullColor;[/tt] - Pretty self-explanatory, the modulate colors for when the bar is full and empty, that you can set in the editor. [tt]color currentcolor = mix(emptyColor, fullColor, percentfull);[/tt] - I just put this in a temporary variable for a little extra clarity. Mix() is just a linear interpolate; it blends the first and second arguments based on the third, float argument. So if percentfull is 0, currentcolor will equal emptyColor; if percentfull is 1, currentcolor = fullColor, etc. [tt]COLOR = tex(TEXTURE, UV) * currentcolor;[/tt] - COLOR is a built-in variable, it's the final pixel color that will be drawn on screen. Tex() reads the color of a texture at a UV coordinate. TEXTURE, and UV, are also built-in variables. They're inputs into the shader that come from the inspector settings of the node.

[quote author=Megalomaniak link=topic=15504.msg16266#msg16266 date=1463188011]uniforms are public/accessible from GDScript.I couldn't get a material override to work/show up on textureProgress however building a custom progress bar from a panel node is totally doable. I used shaderGraph for the example, see attachment.[/quote]Thank you for putting that scene and shadergraph together! As a total beginner who is just starting to learn this stuff, it took a moment to figure out what was going on. Eventually I was able to [tt]linear_interpolate[/tt] between colors in a script on the parent panel, and assign the color to the custom panel via the material's [tt]set_shader_param[/tt] method.[img width=34 height=150]http://i.imgur.com/5dsoPPg.gif[/img]As for the shadergraph... is Godot able to convert a shadergraph into readable, editable code? The shader file created by the engine looks like a nearly-unreadable jumble. The node-based editor looks interesting but daunting, and i'm guessing you'd need a pretty good understanding of shaders before using it.

[quote author=Ross link=topic=15504.msg16267#msg16267 date=1463189690]Putting a material on a TextureProgress seemed to work fine for me. However, there's a big catch: the shader works on the whole CanvasItem, so it'll affect the over, under, and progress textures. So you'll probably want to use a separate node for the actual progress bar. Ignoring that, here's how to do a simple shader that fades the modulate color between two colors. You would have to set the parameter on the shader to match the progress value of your progress bar via GDScript. It sounds like you're not familiar with shaders, so here's a line-by-line breakdown. Sorry if it's totally overkill.[tt]uniform float percentfull;[/tt] - [tt]uniform[/tt] is godot's shader language equivalent of the [tt]export[/tt] keyword for variables in GDScript, it means the variable comes from outside the shader and is exposed in the editor. [tt]float[/tt], it's a float, obviously. This variable will be the 0-1 measure of how full the progress bar is. We'll use it to blend between the empty color and the full color. [tt] ;[/tt] The shading language requires a semicolon at the end of every line. [tt]uniform color emptyColor; uniform color fullColor;[/tt] - Pretty self-explanatory, the modulate colors for when the bar is full and empty, that you can set in the editor. [tt]color currentcolor = mix(emptyColor, fullColor, percentfull);[/tt] - I just put this in a temporary variable for a little extra clarity. Mix() is just a linear interpolate; it blends the first and second arguments based on the third, float argument. So if percentfull is 0, currentcolor will equal emptyColor; if percentfull is 1, currentcolor = fullColor, etc. [tt]COLOR = tex(TEXTURE, UV) currentcolor;[/tt] - COLOR is a built-in variable, it's the final pixel color that will be drawn on screen. Tex() reads the color of a texture at a UV coordinate. TEXTURE, and UV, are also built-in variables. They're inputs into the shader that come from the inspector settings of the node.[/quote]It works! I tried messing with the code in an attempt to prevent the shader from affecting the 'over' texture, with absolutely no success.[img width=203 height=111]http://i.imgur.com/N9irnn6.gif[/img]However while researching your code in an attempt to understand it better, I stumbled upon [url=http://godotengine.org/qa/2935/best-colour-palettes-asking-again-cause-last-time-didnt-help?]this shader[/url] posted in the Godot QA forum that basically swaps one color for another based on a threshold value:[code]uniform texture in_tex; //input textureuniform color test_col; //the color to test againstuniform color new_col; //the target coloruniform float threshold; //get the texture colorvec4 out_col = tex(in_tex, UV);//calculate the difference between our color and test colorvec3 diff = out_col.rgb - test_col.rgb;//if the difference is less than our thresholdif(abs(length(diff)) < threshold){    //the new texture color is now  new_color diff    out_col.rgb = new_col.rgb * (vec3(1.0,1.0,1.0) - diff);}COLOR = out_col;[/code][img width=203 height=111]http://i.imgur.com/cewQQh1.gif[/img]The modulated pixels are jagged and rough, but modulating the 'over' texture can be avoided if colors are chosen with care. I'm going to play around with this further and see if the jagged pixels can be drawn more smoothly.By the way, I appreciate that you took the time to explain your code... it's definitely not overkill, it's perfect for someone wanting to learn. Thank you!

[quote author=ericdl link=topic=15504.msg16272#msg16272 date=1463275415]As for the shadergraph... is Godot able to convert a shadergraph into readable, editable code? The shader file created by the engine looks like a nearly-unreadable jumble. The node-based editor looks interesting but daunting, and i'm guessing you'd need a pretty good understanding of shaders before using it.[/quote]Have you ever dealt with electronics/breadboard? I'm asking because if you have you can basically think of shader graph the same way. Each node is a like a chip placed on the board and the node connections are like the wires connecting one chips output pin to another chips input. Mind you in case you are not familiar with this sort of electronics 101 this analogy probably doesn't help.In other words every node is essentially a black box with internal shader logic and has inputs and outputs. Or like a class/function with public variables for inputs that outputs something into other variables. It's a flow chart, but instead of pseudo-code flowchart for reference of how to implement a function/architecture it an actual flowchart of a shader pipeline.Not sure I can explain it much simpler than that.

17 days later

[quote author=Megalomaniak link=topic=15504.msg16307#msg16307 date=1463505402]Have you ever dealt with electronics/breadboard? I'm asking because if you have you can basically think of shader graph the same way. Each node is a like a chip placed on the board and the node connections are like the wires connecting one chips output pin to another chips input. Mind you in case you are not familiar with this sort of electronics 101 this analogy probably doesn't help.In other words every node is essentially a black box with internal shader logic and has inputs and outputs. Or like a class/function with public variables for inputs that outputs something into other variables. It's a flow chart, but instead of pseudo-code flowchart for reference of how to implement a function/architecture it an actual flowchart of a shader pipeline.Not sure I can explain it much simpler than that.[/quote]Thanks for that explanation, it makes sense.

If you are confused by what a specific node does though, just ask here, once you get the basic gist of it you can just check out a few GLSL tutorials on the web and implement those shaders through the graph, to be fair though everything you can do through the graph you can also do in the shader language if you're more comfortable with that, and the shader language lets you define a somewhat better material interface for the shaders since you are in direct control of the order of parameters and you have Boolean uniforms, which sadly haven't been implemented for the graph. :(

Thanks, will do, and I'm keeping an eye on your 'Lets study shadergraph together" thread. It looks promising and is definitely appreciated.

After experimenting with Godot's shader language for a while, I took a break and attempted to build a TextureProgress control from scratch by simply placing sprites atop one another to mimic the over, under and progress textures of Godot's built-in TextureProgress control. Since the texture of this particular progress sprite was animated, adjusting its width via scale wasn't an option since it would distort the texture. The solution was to override the sprite's [tt]draw[/tt] function and manually draw the texture via [tt]draw_texture_rect_region[/tt], which conveniently takes an optional [tt]modulate[/tt] parameter:[code]func draw(): var size = temp_texture.get_size() var region = Rect2(Vector2(), Vector2(size.x * (progress_value / 100), size.y)) self.draw_texture_rect_region(temp_texture, region, region, modulate_color)[/code][img width=204 height=48]http://i.imgur.com/W3gMKe0.gif[/img]It works, but it's kind of hacky and certainly not as elegant as doing it entirely via shader.

Well, if you are willing to give it another go with shaders, just map everything but the alpha according to screenspace(screen uv). This way you have coordinates that don't change for the animated texture and you make the percentage control the alpha of the bar.

7 years later