"Only a vertex shader can declare an attributes block.
"Only a vertex shader can declare an attributes block."
A shader must either defined main(){} or function(){} (but not both)
A shader must either defined main(){} or function(){} (but not both)
Vertex shader cannot have any input blocks (use attributes block instead).
Vertex shader cannot have any input blocks (use attributes block instead).
A shader must either defined main(){} or function(){} (but not both).
A shader must either defined main(){} or function(){} (but not both).
If a shader defines one or more output blocks it must define main(){}.
If a shader defines one or more output blocks it must define main(){}. Fragment shaders are allowed to have main(){} without an output block.
All uniforms must be declared in the same block.
All uniforms must be declared in the same block. Engine structs may be translated to GLSl uniform blocks depending on the implementation.
ShaderPrototype defines a DSL to assist with writing shaders and and linking them together.
Glsl version is inferred based on profile. For Glsl 1.2 non-suqare matrices are re-mapped to square matrices.
Function dependencies are declared with use() declaration.
Uniform values must be specified inside a uniform{} block using the declare() directive. Glsl qualifiers can be chained using qualify() statement. For example: declare[Vec2]("texCoords").qualify("smooth")
Unsized arrays are allowed only in uniform blocks, their size will be automatically resolved to a size of the corresponding BindingSeq.
All dependent variables should be defined inside attribute{} or in{} blocks using declare(). Only VertexShaders are allowed to have attribute{} blocks. Other shaders must use named in{} block and must prefix the variables with the block name in the source code.
Each shader can link with the next stage using an out{} block. In this case shader must also declare main(). Multiple main declarations are allowed within the same program. Alternatively, a shader with main() declaration can share a named set of values using main(){ out{} }. Only one out{} block is allowed per shader, either stage interface out{} or main{ out{} }. Fragment shaders cannot define interface out{}. Shared pre-computed values within the same stage can be requested within main(){ in{} } blocks.
Arrays in in{} and out{} blocks must be sized either to a literal value or to a size of some uniform array. If a uniform array is defined in the shader scope, its size can be accessed using injected variable of the form: se_sizeOf_${StructType}_${ArrayName} or simply se_sizeOf_${ArrayName} when array is declared at the top level.
If a shader does not provide a main(), then it must define a function(){}. Functions can be used within the same stage. Functions can have multiple in{} blocks, but cannot have any out{} blocks.
Additional shader sources can be attached using src() declarations. They will be inserted into the shader code before main() or function() in the order they appear.
A path that resolves to enumeration and a condition on the result can be specified to control shader selection using enums.
Samplers are extracted from structs by the texture manager and then injected at the top level in the shader. This is done to allow property-to-UBO mapping in the future. As a consequence, texture names have to be unique not just inside the parent Struct, but among all the Structs, and all the top-level declarations in Material and Environment.
Texture dimensions can be accessed by declaring integer verctor "se_dimsOf_textureName", for example: declare[Vec2i]("se_dimsOf_myTexture")