godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Improved syntax for vector manipulation in shaders #2807

Open jabcross opened 3 years ago

jabcross commented 3 years ago

Describe the project you are working on

A 3D game with custom shaders

Describe the problem or limitation you are having in your project

The swizzling syntax in the shading language is helpful, but limited. Since shaders are relatively low-level programs that aren't very modular, being concise and readable is even more valuable. As many shaders tend to become unreadable clumps of nested parentheses, most of these proposals are intended to decrease the necessity to use parentheses in the first place.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

  1. Allow ints in vec2, vec3 and vec4
vec3 foo = vec3(2,3,4);    // equivalent to vec3(2.0, 3.0, 4.0); 
  1. Allow single digits as components when swizzling
vec3 a = vec3(2.0, 3.0, 4.0);
vec3 b = a.x1z;    // equivalent to vec3(a.x, 1.0, a.z)
vec3 c = a.xy0;    // equivalent to vec3(a.x, a.y, 0.0)
vec3 d = a.9xx;    // equivalent to vec3(9.0, a.x, a.x)
  1. Allow swizzling literals (treating literals as "vec1"s)
float foo = 3.1;
vec3 bar = foo.xxx           // equivalent to vec3(foo)
vec2 baz = (4.5).xx          // equivalent to vec2(4.5)
  1. Allow concatenation without parenthesis (would require new operator)
float a = 1.0;
vec2 b = vec2(2.0, 3.0);
vec3 c = a..b;  // equivalent to vec3(a, b).

Note that these ideas are uncoupled and can be discussed individually.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

See above

If this enhancement will not be used often, can it be worked around with a few lines of script?

It can, but as I've mentioned, the issue is the code quality and readability itself.

Is there a reason why this should be core and not an add-on in the asset library?

Can't override the shader preprocessor from an add-on, AFAIK

I can work on a PR, if this gets enough traction.

Calinou commented 3 years ago
  1. Allow ints in vec2, vec3 and vec4

Implicit int -> float conversion is not done because it's not mandated in the shader compiler for GLES2. However, it is mandated in GLES3 and any hardware that supports Vulkan, so it might be possible to allow this in 4.0.

For the record, this limitation is also present in raw GLSL when targeting OpenGL ES 2.0. In the meantime, remember that you don't have to specify non-significant zeros when writing floating-point numbers. This means .0 (0.0) and 1. (1.0) are both valid.

  1. Allow single digits as components when swizzling
  2. Allow single digits as components when swizzling
  3. Allow concatenation without parenthesis (would require new operator)

I wouldn't add more syntax that is not present in GLSL. One goal of the Godot shader language is to be easy to pick up for people who already know GLSL (or even HLSL). This is why the Godot shader language went with braces and semicolons instead of indentation like GDScript.

Every time you add a new syntax feature, you have to consider whether the typing it saves is worth the added complexity in the implementation – and the fact that the code becomes harder to read for new programmers. Code is read way more often than it is written :slightly_smiling_face:

jabcross commented 3 years ago

Implicit int -> float conversion is not done because it's not mandated in the shader compiler for GLES2. However, it is in GLES3 and later, so it might be possible to do this in 4.0.

For the record, this limitation is also present in raw GLSL when targeting OpenGL ES 2.0.

I was thinking it would be de-sugared before it went to the shader compiler.

I wouldn't add syntax that is not present in GLSL. One goal of the Godot shader language is to be easy to pick up for people who already know GLSL (or even HLSL).

It would still be backwards-compatible, of course. The old way would still work. Plus, Godot already breaks compatibility with GLSL, for instance with the built-in variables.

Code is read way more often than it is written

This is exactly the motivation for this proposal! (Even though, for shaders particularly, the iteration cycle tends to be just a couple seconds. Visual fine-tuning is a big part of shader development)