-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIX sdf/msdf shaders, add Shader.glslVersion #5328
Conversation
src/core/shader.js
Outdated
@@ -45,6 +45,8 @@ Shader.prototype = { | |||
'gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);' + | |||
'}', | |||
|
|||
glslVersion: null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this to be configurable? Probably passing the correct value here should be enough:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on if we want to support WebGL1 or not. (Though I'm not sure if A-Frame works with a WebGL1 context at the moment as I've never tried it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be part of the public API. Should check if the WebGLRenderer is webgl1 or not. Still I think is moot because as you said A-Frame doesn't offer a WebGL1 option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definitely depends of decision to support WebGL1. If we drop WebGL1 support than sdf/msdf code should also be stripped/cleaned to remove GL1 shaders (which are differs from GL2 ones) and some startup checks for WebGL version has to be added to warn user of unsupported WebGL version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This THREE functionality looks a bit not clean as it is THREE who injects extra code in to shader so it is THREE job to inject code right way instead of forcing users to fill in the additional version parameter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be part of the public API. Should check if the WebGLRenderer is webgl1 or not.
It's a bit more subtle than that. The WebGLRenderer
supports both WebGL 1 and WebGL 2 and will automatically pick one. The WebGL1Renderer
class only exists to force WebGL 1. In other words, just checking .isWebGL1Renderer
isn't sufficient, as you can have a normal WebGLRenderer
with a WebGL 1 context (in case your browser/device doesn't support WebGL 2).
What we're discussing however is the glslVersion. This is tied to the WebGL version in the sense that you can only use ES 3.0 shaders with WebGL 2, but you can use ES 1.0 shaders on both WebGL 1 and 2. There are differences in syntax so you can't simply tag on a #version 300 es
on an ES 1.0 shader.
So if we hide this and default to THREE.GLSL3
we're basically deciding two things at the same time:
- A-Frame will only supports WebGL2 (which it might already depend in other areas of the code?)
- A-Frame will only supports ES 3.0 shaders
Which I don't view as a problem, but is worth having clear in case someone wants to incorporate a (raw) ES 1.0 shader. And as @nightgryphon points out, if we do opt for this approach we should cleanup the sdf/msdf code and add an explicit WebGL2 check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This THREE functionality looks a bit not clean as it is THREE who injects extra code in to shader so it is THREE job to inject code right way instead of forcing users to fill in the additional version parameter
Totally agree with you on this. I don't mind THREE.js injecting things into shaders, but it's surprising that they now also do this for RawShaderMaterial
...
src/core/shader.js
Outdated
@@ -56,7 +58,8 @@ Shader.prototype = { | |||
// attributes: this.attributes, | |||
uniforms: this.uniforms, | |||
vertexShader: this.vertexShader, | |||
fragmentShader: this.fragmentShader | |||
fragmentShader: this.fragmentShader, | |||
glslVersion: this.glslVersion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably passing here THREE.GLSL3
is all the changes we need if I'm not missing anything. thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoding version instead of making default value for parameter can be not the best solution. What if somewhere in future we will get GLSL4,5,6 or sort of custom extensions which require to pass different version string? For me the right way was to respect original user shader code but THREE did this...
Also hardcoding version require cleanup for sdf/msdf shader modules to remove GL1 shaders and add GL version checks to their init
constructors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoding in this instance is not too bad. There's almost certainly never going to be a newer version for WebGL with WebGPU on the horizon.
It all boils down to two separate decisions (see other comment thread): do we want to support ES 1.0 GLSL shaders with A-Frame and do we want to support WebGL1 (if that even works right now?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can hardcode for now or can also determine from the renderer (WebGL1, WebGL2, WebGPU) instead of a public API. sounds good? thanks for the patience
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some testing and it seems A-Frame can (still) work fine with WebGL1, so I'd rather not break core components and try to postpone that till Three.js drops support (r163). Also found out that hardcoding it, actually breaks non-raw custom shaders as the GLSL 3.0 shader conversion that Three.js does ends up behaving slightly different :-/
Automatically determining it from the renderer won't be an option as the shader is written in a specific shading language. So either we expose a way for users to tell which language/version they used, or we restrict what A-Frame supports.
Basically the following support matrix exists:
WebGL 1.0 | WebGL 2.0 | WebGPU | |
---|---|---|---|
ShaderMaterial (GLSL 1.0 /w 3.0 conversion) | ✅/❌ (2) | ✅ | ❌ |
GLSL 1.0 | ✅ | ✅ | ❌ |
GLSL 3.0 | ❌ | ❌ | |
NodeMaterial | ? | ✅ | ✅ |
- Before the Three.js update the shader code itself could indicate the GLSL version in its source. Now that three.js injects other things at the start, it must also handle injecting the version directive. By extension this means that we must tell three.js which version it is.
- Depends on which GLSL features and keywords are used. The GLSL 3.0 conversion in Three.js only handles a small subset.
tl;dr I'd suggest the following:
- For now set
glslVersion: raw ? THREE.GLSL3 : undefined
, fixing the problem for the majority of the users. - As a separate/follow-up: change the sdf and msdf shaders to non-raw shaders. This would remove the need to keep two almost identical copies around (GLSL1 and GLSL3 versions), restores WebGL1 compatibility, makes it easier to fix fog interaction (Scene fog not working on a-text #4261), logarithmic depth (Text not rendering when logarithmicDepthBuffer is enabled #4279) and color management.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's go for the simple solution. thanks
For now set glslVersion: raw ? THREE.GLSL3 : undefined, fixing the problem for the majority of the users.
As a separate/follow-up: change the sdf and msdf shaders to non-raw shaders. This would remove the need to keep two almost identical copies around (GLSL1 and GLSL3 versions), restores WebGL1 compatibility, makes it easier to fix fog interaction (#4261), logarithmic depth (#4279) and color management.
@nightgryphon can we incorporate these changes:
notice that undefined a better choice than |
@dmarcos this will make all raw shaders treated as GLSL3. Didn't this cause compatibility issues for anyone who uses raw shaders? Regarding sdf/msdf shaders this will not fix them and text component. The minimum is to remove version string from GLSL3 shader code. But it is better also to drop GLSL1 shaders just to be sure using right shader code in any case to prevent hard to detect bugs. As an alternative we can just extract version from shader fixing shader code at the same time. Should work for most cases. Updating sdf/msdf is not required and can be postponed.
here is the commit i can make PR from a6d735c |
@nightgryphon The idea is indeed both This does indeed mean that third party raw shaders will require changes, though I think you'll find that not many people use raw shaders in the first place. For GLSL3 shaders they will simply have to remove the I'd rather not introduce workarounds or special behaviour into A-Frame for the purpose of retaining old Three.js behaviour. While it's annoying that many of the breaking changes in A-Frame come from (breaking) changes in Three.js, going against it would result in workarounds and fixes piling up over time. And given that A-Frame offers virtually no abstraction over the Three.js shaders I don't think it makes sense to maintain this old behaviour indefinitely. |
Hm. Okay. At least that fixes the current problem with text. PS Just notice regarding not to create THREE abstraction layer. On the one hand we pass through the untouched shaders code but on the other hand we abstract users from the |
@nightgryphon can you modify this PR? |
A bit messy but done. Huh... |
src/core/shader.js
Outdated
@@ -50,11 +50,16 @@ Shader.prototype = { | |||
* Called during shader initialization and is only run once. | |||
*/ | |||
init: function (data) { | |||
if (this.raw) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this message is very valuable. Perhaps better making a note in the docs. I'm also happy to rip the band-aid and perhaps starting to say that WebGL1 is deprecated and WebGL2 is the way to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definitely has to be added to docs. But i think keeping such warning just for a few versions can save some headache to those who still using old shaders and has to migrate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure warning is super descriptive for the avg. dev. It is extra code to maintain and eventually have to remember to remove when obsolete.
What we usually do is to add deprecations
in the release notes for those migrating https://github.com/aframevr/aframe/releases That's evergreen info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning isn't particular useful as it will always be printed. It might even confuse people seeing the warning when everything is correct. The fact that a big error is printed by Three.js down the line is probably enough. Anyone writing their own raw shaders will either understand the error or look it up and find the relevant Three.js and A-Frame issues. Those using older shaders from others will most likely open an issue about that error message anyway.
Documenting this change and mentioning it in the release notes is key, as that will help anyone updating and can easily be linked/pointed to when people encounter this.
Ok. I've removed the warning @mrxz the idea of that warning was regarding migrating from GLSL1 shaders where THREE most likely will not print any error but shader will be compiled with GLSL3 header line instead. |
GLSL1 shaders can't be compiled as GLSL3 shaders even with the (Note that with non-raw |
@mrxz Oh. That's makes things clear. Thanks! |
Thanks so much for the patience and being so accomodating! |
Description:
Fix shaders according to THREE changes. Fixes Text component.
Changes proposed:
Shader.glslVersion
. Shaders should use this to specify version instead of shader#version
string