# Qt Quick Effect Maker

Qt Quick Effect Maker is a tool for creating custom shader effects for Qt Quick. It contains both a visual nodes view and a powerful code view to customize the effects. Start by adding nodes in the design mode and modifying their properties in the property view. Then optionally switch to the coding mode to see and modify the generated GLSL shader code. When ready, export the effect QML component as well as the shaders and utilize the component in your application.

## Shader inputs & outputs

vec4 | fragColor | Fragment shader's output for the color. The format is RGBA and it will be multiplied by default with the item opacity (qt_opacity).
vec2 | texCoord | Normalized position of the fragment (0.0 - 1.0).
vec2 | fragCoord | Position of the fragment in pixels (0.0 - iResolution.xy).
vec2 | vertCoord | Position of the vertex in pixels (0.0 - iResolution.xy). Modify this in the vertex shader to move the vertices.
vec3 | iResolution | Size of the source item / image in pixels. The z parameter is always 1.0
float | iTime | Animated time in seconds.
int | iFrame | Animated frame number.
sampler2D | iSource | Texture sampler of the source item / image.
vec4 | iMouse | Mouse input helper where: "iMouse.xy" is the current mouse position. "abs(iMouse.zw)" is the starting position when the mouse button was pressed. "iMouse.z > 0.0" is true if button is currently down. "iMouse.w > 0.0" is briefly true when mouse button is pressed.

## Tags

Tags are special commands which are looked for from the shader sources. Format of these tags must be exactly as explained here, so don't modify them unless needed.

@main | This tag can be used in both vertex and fragment shaders to separate code which belongs into root and inside main() method. If the tag is missing, all code goes into main.
@requires [name] | This tag is used to inform that the node depends on other node called [name]. This dependency is not enforced, it is used just to inform the users.
@nodes | This tag is used in the main node vertex and fragment shaders. It will get replaced with the main shader code of the following nodes.
@mesh w, h | This optional tag is used in the vertex shaders to define GridMesh size. The default mesh size is (1, 1). If mesh tag is used multiple times (by different nodes), biggest values will be used. Example: "@mesh 20, 10" creates horizontally 20 and vertically 10 vertices grid mesh.
@blursources | This optional tag is used by BlurHelper to generate pre-blurred sources (iSourceBlur1-6) which other nodes can then utilize.

## Porting shadertoy shaders

Shadertoy (https://shadertoy.com) is very popular website for creating and sharing shader effects. Here are few tips for porting those shaders into Qt Quick Effect Maker:

- Create a new Custom (empty) node for the Shadertoy effect.
- Shadertoy shaders contain main entry as something like "void mainImage( ... ) { ... }". Replace that with the main tag "@main" and either remove the '{' and '}' or keep them in separate lines to have the shader code in its own scope.
- Not all features of Shadertoy are supported. Effects with multipass ("Buffer" tabs) can't be done with effect maker, you must build them separately and bind the output of the buffer ShaderEffect to the source of the next ShaderEffect. Also audio, cubemaps and 3D textures are not supported.
- Shadertoy only supports fragment shaders and built-in textures. To improve the performance of the effect with QQEM you can move some calculations into vertex shader and use custom images to simplify fragment shader.
- Coordinate system between Qt and Shadereffect differs so that Qt has origin (0,0) in top-left corner while Shadertoy and OpenGL use bottom-left corner. If this is important for the effect, consider flipping the y-coordinate in a suitable way. For example to flip fragCoord in Main node switch to: "fragCoord = vec2(qt_Vertex.x, iResolution.y - qt_Vertex.y)". Similarly you may need to adjust texCoord and iMouse.

## Questions and answers

Q: How to get started?
A: First, add an effect node. Either 'Custom' for empty node or any other provided nodes. Node view should always be completely connected, so start from 'Main' node, then custom nodes in desired order, and end to 'Output' node. Double click a node to see its source code and enabled modifying its properties. Press DESIGN / CODE button to switch between these modes. When you have something usable, export the effect to generate QML component and shaders that can be taken into use in your Qt Quick application.
Q: Can all nodes be freely mixed?
A: Yes and no. You can freely add any nodes after each other, but the output may not be what you would expect. This affects especially nodes which need to do texture lookups (blur, displace etc.) from the source. You should use only one of these in the effect and that node should be the first one. For example having colorize node first and then blur node results ignoring the colorize. If you need multiple of these nodes, that needs to be done by chaining separate effects as QQEM doesn't currently support building multipass effects.
Q: What is the shader source code syntax?
A: Qt 6 uses Vulkan-compatible GLSL (#version 440) as the input and bakes that to native Vulkan, OpenGL (ES), Metal, and Direct 3D shaders. If your target requires e.g. OpenGL ES 2.0, enable the legacy GLSL option from the preferences. But note that some built-in effect nodes use features not available in legacy GLSL (booleans, unsigned integers etc.) so porting might then be required.
Q: Why am I seeing "iSourceBlur1: undeclared identifier" error?
A: Most likely you have a node which required blurred sources (like FastBlur or DropShadow) and you haven't added "BlurHelper" node which those nodes depend on.
Q: Why am I seeing error about "pseudo3dNoise", "hash21" or "HASH_BOX_SIZE"?
A: Same as above, but this time you haven't added "NoiseHelper" node which contains common noise / hash functions which some nodes depend on.
Q: Why am I seeing "[variable] redefinition" error?
A: You are using same variable name in multiple places (nodes). There are different ways to fix this. You can for example rename either of the variables or place you nodes code inside '{ ... }' blocks to not leak the variables.
Q: I try to add a node but "Add" button is disabled?
A: You are probably trying to add a node which is already used in the node view, or the node contains some properties which would override existing nodes. This can't be allowed, if you need the new node you must first remove the overlapping node or modify its property names.
Q: I try to add a property but "Add" button is disabled?
A: Add property button is only visible in code mode and only enabled when some node other than Main or Output is selected. Reason for this is that properties belong to a node and Main & Output can't contain properties.
Q: My effect uses FastBlur, DropShadow etc. but content gets clipped away?
A: Some effects need bigger item area than the source image/item has. To see the effect borders, toggle on the "Show item borders" icon in the Preview view. To adjust these, please open the Edit -> Project Settings, and add suitable padding for the item. For exported items, this needs to be done manually by creating source with the required padding.
Q: How can a pass variables from the vertex shader into fragment shader?
A: To create varying/out variables in the vertex shader, prepand them with "out" in the root of the vertex shader e.g. "out vec4 thingColor;" or "out float movement;". There is no need to have matching "in" variables in the fragment shader or care about correct layout location, those are handled automatically.
Q: Why changing some shader properties update the preview instantly and others with a short delay?
A: If the property type is "define" or property "API" export button is toggled off, changing the value requires modifying and rebaking the shader which is fast but not instant. When the property is not exported, it doesn't appear as QML API into the effect, doesn't generate uniform and so can't be changed when using the effect. This can be useful to increase the performance and have cleaner API for the effect.