-
-
Notifications
You must be signed in to change notification settings - Fork 35.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
Bug in r119 attributes? #20057
Comments
Thanks for the report. Let me investigate. |
Conclusion I think I have to say that adding/removing attributes to/from geometry in Workaround A workaround I came up with so far is picking up morph color attributes before calling function onBeforeRender(mesh) {
const geometry = mesh.geometry;
// remove all the color attributes
for (const {name} of colorAttributes) {
geometry.deleteAttribute(name);
}
// Find the up to eight biggest influences other than 0 influence
const influences = [];
for (let i = 0; i < mesh.morphTargetInfluences.length; i++) {
influences.push([i, mesh.morphTargetInfluences[i]]);
}
const effectiveInfluences = influences
.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]))
.slice(0, 8)
.sort((a, b) => a[0] - b[0]) // comment out this line for r115
.filter(a => !!a[1]);
// Add corresponding color attributes
for (let i = 0; i < effectiveInfluences.length; ++i) {
const ndx = effectiveInfluences[i][0];
const name = `morphColor${i}`;
geometry.setAttribute(name, colorAttributes[ndx].attribute);
}
}
function render() {
onBeforeRender(scene.children[0]);
renderer.render(scene, camera);
} Example with r119 https://jsfiddle.net/7or8t4d1/ It looks working. The limitation is this idea can not be used if multiple meshes share a geometry. I haven't come up with an idea for such a case yet. Why we shouldn't add attributes in The reason why we shouldn't add/remove attributes to/from geometry in WebGL buffer handling and
From this, I can explain how the problems you reported happen.
And morph attributes in geometry you see in
WebGL buffer corresponding to morph color attribute is bound in the third render then you see it looks working. But note that morph attributes in geometry you see in
In this example, geometry isn't changed since the previous render call. (In Is this a bug?
WebGL resource management in render is complex. Perhaps hard to resolve this issue "adding/removing attributes in |
Thank you for taking a look at the code. I kind of expected you might come to that conclusion. It doesn't seem like a good API where I have to guess what the API will do and reproduce that result outside. Instead, I should be able to ask the API what it did or what it will do, and then do the correct corresponding thing outside. That means if what it does changes my code still works. As an example, Off the top of my head maybe function like |
Should VAO be reverted? |
(Sorry, I'm overwhelmed and frustrated with this) |
I don't think (and I don't hope) we should revert because the root issue of this problem is not from VAO as I wrote above. Adding/Removing attributes in But yeah sorry for the bugs reported in other threads and already fixed. VAO actually improves the performance. So I prefer trying to further clean up and optimize VAO related code rather than reverting. |
(Even if unfortunately you end up deciding to revert, I'd be pleased if you open an issue or PR before you do that and give us a chance to discuss. Because I really want VAO in Three.js) |
I also think that VAO usage is a must for a WebGL engine. We should clearly state to not support specific use cases (like adding/removing attributes in |
I'll suggest we mark the issue as a |
@greggman for motivation sake... can you show something a bit more compelling than a yellow square? |
Meaning... You're hacking around an a part of the API that is hard to guarantee is not going to break. |
Sounds interesting. But it would not resolve the case where a geometry is shared among multiple meshes. And I think "Renderer automatically adds/removes some of morph position and normal attributes to/from geometry depending on An idea in my mind so far is, renderer adds not only If we don't need flexibility but we want to add color morph, just supporting |
Here's the use case. https://r105.threejsfundamentals.org/threejs/threejs-lots-of-objects-morphtargets-w-colors.html Basically making the WebGL Globe but fixing the part where colors only match the first dataset. The solution I'd prefer is to be able to ask three what it is going to do.
It doesn't have to usable in onBeforeRender. To be clear, I'd prefer not adding color support to three.js specifically but a solution that allows the user to add their own code and still utilize what three is already doing. That's the point of the example. It is not "how do I morph colors", it is "how do I add my own data to morph targets" I can use solution takahirox posted above and just comment that this isn't really something three wants to support and that you should really write your own custom shaders and write your own morph target system if that's the recommended solution. I was just hoping that given the code to support morph targets is already in three.js that it was possibly to piggyback off that rather than having to go 100% custom. |
@greggman Wouldn't it be better for that use case to use |
I could have sworn i had a PR about this, but it seems i was wrong. What i hear:
What i think is the solution:
While this may be an esoteric use case, i think Before we ever call Consider an additional hook called
Question, would something like this be able to replicate the functionality from the examples?
|
Not sure that's a win. For a 1000 cubes the morph target solution requires updating max 8 attributes, 8 influence values, and 1 draw call per frame. The InstanceMesh solution requires computing 1000 lerped matrices, updating 1000 matrices, computing 1000 lerped colors, 1000 colors, and 1 draw call per frame. In any case, for the sample to work ATM I updated it to use @takahirox's example, shortened to
and it's no longer in If the top few lines of |
With the new texture array based morph target system (#22293), the assumptions of this issue are no longer valid. At least not for WebGL 2. TBH, I was not a fan of this issue right from the beginning since it was filed based on the premise that a feature (morphing vertex colors) was hacked in. In general, users should work with the API. If a feature is missing, a feature request should be created so the maintainers can think about a possible enhancement. Many parts of the library are considered to be private and should not touched by the user (e.g. how |
Which is exactly what I asked for. A way to work with the API to achieve the goal. |
Do you want to create a new issue / feature request for adding vertex color support to morph targets? |
Description of the problem
I'm not 100% sure this is a bug vs my bad code but r115 shows a yellow square (which is what I expect) and r119 shows a black square, same code
https://jsfiddle.net/greggman/42gm165d/ (r119)
https://jsfiddle.net/greggman/74w5tzub/ (r115)
First let me explain my code. I'm trying to use morph targets with both positions and vertex colors. three.js doesn't support vertex color morphing so I'm hacking those in.
Three.js, can be given a bunch of morph targets (say 100 targets), and then based on the influences of those 100 targets it will choose up to 4 of them to actually pass to the shader (I think that's how it works).
In order for me to know which color data to pass to the shader I need to know which position data three.js decided to pass to the shader so I iterate over the morphTarget0-3 attributes and check which BufferAttribute (which data) is being used
I execute the above code in
onBeforeRender
and it turns out which morph targets will be used is not up to date until render 3 times in r115 but it does actually get there by the 3rd render.On r119 it never gets there.
In the example there are cube morph targets (red, yellow, green, cyan). I set the influences to 0, 1, 0, 0 so I should see a yellow cube). I added some WebGL logging. On r115 I see this
first render
First we see all these
bindBuffer
calls. Those are the ones used when uploading the vertex data. Then you can see atonBeforeRender
there was no info about which morph targets are used so no color is set. Three then sets up 2 attributes, 'position' to the cube 0 (red) andmorphTarget0
to cube 1 (yellow). With no color set it will be black2nd render
This time we see on
onBeforeRender
that my code saw1morph-target-position
(the yellow cube's positions) was assigned tomorphTarget0
so it assigns the corresponding colormorph-color-data1
tomorphColor0
But then we see three.js ignores that when actually setting up th attributes even though it sets up the attributes after
onBeforeRender
3rd render
This time we see the same
onBeforeRender
behavior (the color data for cube1(yellow) is assigned to morphColor0) and then three.js actually uses it and we get a yellow cube.Switching to r119
the first and second render are exactly the same as above so no need to repeat them but the 3rd render does not set up the color attribute
In fact no attributes are setup. My guess is the caching that was added thinks nothing needs to happen so it just binds the existing VAO and so nothing changes, the cube stays black.
Maybe I'm using three wrong so sorry if this really belongs on S.O but I have 2 question
Three.js version
Browser
OS
Hardware Requirements (graphics card, VR Device, ...)
The text was updated successfully, but these errors were encountered: