[Feature Proposal] Vertex Colors on TriangleMesh
Knee Snap
kneester77 at gmail.com
Wed Aug 21 03:41:03 UTC 2024
Thanks for the reply!
*> If you can give links to the API and docs of vertex coloring in D3D9,
OpenGL, Metal and possibly Vulkan and D3D11 for future-proofing, we could
see what APIs they support exactly and come up with a common one for
JavaFX. Sometimes different pipelines support the same features in
different ways, which makes it harder to provide a single API abstraction.
D3D9, OpenGL, Metal and possibly Vulkan and D3D11*
I've laid out a very basic explanation of the API changes I imagine in the
first email, but I'll follow up in a bit with a more in-depth proposal once
the aforementioned Kevin or Johan give the OK on the proposal to continue
to the API discussion stage detailed in the contribution guide.
Fixed Rendering Pipeline Documentation Examples (PLEASE READ BELOW FOR MORE
CONTEXT FIRST):
- Enable/Disable Per-Vertex Coloring
<https://learn.microsoft.com/en-us/windows/win32/direct3d9/per-vertex-color-state>
(
https://learn.microsoft.com/en-us/windows/win32/direct3d9/per-vertex-color-state
)
- Shows D3DFVF_DIFFUSE as the flag to use to enable vertex colors in the
vertex format.
<https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dfvf> (
https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dfvf)
Providing documentation is a little hard to do, and I think I need to
explain/give a little more context , since JavaFX doesn't appear to use any
fixed rendering pipelines.
When I said "DirectX / OpenGL supports vertex colors", what I'm referring
to is two things: the fixed rendering pipeline which explicitly supports
vertex colors, and the shader-based pipeline capable of supporting
vertex colors.
The fixed rendering pipeline is the one where there would be a specific
library function call relating to vertex colors. I've included some links
above as examples.
However, fixed rendering pipelines aren't often used these days because
they're less flexible because shaders are actually akin to small embedded
programs that run in parallel, which the developer can write themselves.
Since JavaFX doesn't use fixed rendering pipelines and it wants to
anticipate the future, I don't see any reason to focus on the fixed
rendering pipeline, which makes it more difficult to give documentation on
how to do this.
I think I can still answer the spirit of the question though.
The reason there's no explicit API call when using shaders is because these
APIs aren't actually managing the color for us directly anymore.
Instead, JavaFX is responsible for creating/ordering/organizing
arrays/buffers itself, and giving the GPU a shader program configuring how
to render the contents of the buffer.
So in order to make vertex colors work under this paradigm, it's one of the
most simple operations out there, a simple multiplication. We'll put the
color in the buffer, then when drawing a vertex, the GPU shader will take
the color out of the buffer and perform a multiplication operation.
That's all it takes to make vertex colors work with the shader paradigm, so
it's very hard to imagine a future potential shader-based system which
cannot do this, as it's hard to imagine a shader which doesn't both have
even a single one of these three things:
1) Access to arbitrary buffer data per-vertex supplied by the CPU
(otherwise how could it render anything?)
2) Multiplication support (How could it do anything useful without this?)
3) Ability to control the output color on a per-pixel basis,
using interpolated data from the vertiex buffer(s) used for the given
polygon. (This is the entire purpose of the pixel/fragment shader so it's
unfathomable for this to not exist, there would be almost no point to
shaders if this didn't exist.)
These are all super critical to shaders in general being useful, so it's
very difficult to imagine a scenario where JavaFX would be looking to
support a shader-based backend that didn't have even a single one of those
things.
I think this should hopefully answer that question, even if I didn't do
exactly the way you wanted.
But wait, if I'm not actually making major changes that involve any
Direct3D / OpenGL function calls, what would even get changed for this
feature?
Firstly, the shader(s) themselves. We've got to make it so the shaders
properly describe that they should receive vertex color data in a buffer,
and multiply that vertex color data as described previously.
(modules\src\main\resources\prism.es2.glsl\ and
modules\src\main\resources\native-prism-d3d\hlsl)
Secondly, JavaFX's buffer management code needs to be changed to include
vertex color data in the buffers, when applicable. (BaseMesh.java?)
Lastly, all of the code sitting between the previous steps and the public
user-facing API additions will need to be filled in. I think this is mostly
just the bridge between TriangleMesh.java and NGTriangleMesh.java.
*> 1. Are there other closely related APIs that can come with this feature?
This is required to be able to plan ahead. For example, if an API provides
setting one of the modes A, B or C, and a user proposes an API that only
deals with A, you'd end up with a single method that sets or unsets A.
However, if you then want to evolve the API to support B and C, you would
have liked to model it in a different way that allows you set any of the
modes, and not end up with a single method for each. So, if vertex color is
part of a larger API context, we will need to plan accordingly.*
I've thought of a few features which could be related, but I don't think
vertex colors impact these features in a way which adds difficulties which
aren't already present:
- The ability to use custom shaders supplied by the user alongside
arbitrary buffers, textures, and globals. (This is probably never coming,
but if it does, good to plan ahead of time)
- Deferred rendering to allow efficient implementation of more than 3
lights at a time. (Could even be thousands of lights)
- Allowing the user to choose 3D scene axis orientations instead of always
defaulting to Y- being "up". (Perhaps this can be done just by messing with
the camera without a JavaFX feature, not sure.)
- Allowing the user to choose between clockwise/counter-clockwise winding
order.
- Allowing the user to choose whether mip-maps are enabled.
- Allowing the user to choose the texture wrapping mode for a
PhongMaterial.
If anyone can think of any other features which it could conflict with, or
ways it could complicate the features I've mentioned, do share the concerns.
*> 2. The performance of 3D is already problematic in some aspects. Small
additions can drop the FPS considerably. More research should be done to
find out why. We will need to make sure performance isn't going to drop for
cases where this feature isn't used. Seeing as this is only vertex shader
data, which tends to be cheap and the number of registers available for it
large, I don't foresee problems off the top of my head.*
The biggest thing for performance is going to be how the underlying
implementations work for each backend. If done using best practices, this
should have no meaningful performance impact. After all, this technique has
been used since before 3D hardware acceleration, so it should be very
performance friendly.
As for when the feature is disabled, this feature should be possible to
completely disable when not in use, ensuring it would have zero performance
impact. There's already code I see to allow compiling different versions of
shaders, we could compile a version without the vertex colors enabled. I'm
not sure if this would even be necessary, but the option is there.
*> Implementing this will require simultaneous implementations for D3D9 and
OpenGL. Metal is still in the works, so I'm not sure about that one.*
I see, is there someone/a group working on the Metal backend? If so, it'd
be nice to hear if they have any thoughts on this.
On Tue, Aug 20, 2024 at 1:08 PM Nir Lisker <nlisker at gmail.com> wrote:
> When modern APIs agree on a feature, it makes sense to consider it for
> JavaFX (that lacks a lot of standard features). If you can give links to
> the API and docs of vertex coloring in D3D9, OpenGL, Metal and possibly
> Vulkan and D3D11 for future-proofing, we could see what APIs they support
> exactly and come up with a common one for JavaFX. Sometimes different
> pipelines support the same features in different ways, which makes it
> harder to provide a single API abstraction.
>
> There are a couple of points I would look at when designing this feature:
> 1. Are there other closely related APIs that can come with this feature?
> This is required to be able to plan ahead. For example, if an API provides
> setting one of the modes A, B or C, and a user proposes an API that only
> deals with A, you'd end up with a single method that sets or unsets A.
> However, if you then want to evolve the API to support B and C, you would
> have liked to model it in a different way that allows you set any of the
> modes, and not end up with a single method for each. So, if vertex color is
> part of a larger API context, we will need to plan accordingly.
> 2. The performance of 3D is already problematic in some aspects. Small
> additions can drop the FPS considerably. More research should be done to
> find out why. We will need to make sure performance isn't going to drop for
> cases where this feature isn't used. Seeing as this is only vertex shader
> data, which tends to be cheap and the number of registers available for it
> large, I don't foresee problems off the top of my head.
>
> Implementing this will require simultaneous implementations for D3D9 and
> OpenGL. Metal is still in the works, so I'm not sure about that one.
>
> It will need the approval of Kevin or Johan.
>
> - Nir
>
> On Tue, Aug 20, 2024 at 9:08 AM Knee Snap <kneester77 at gmail.com> wrote:
>
>> This is my first time attempting to submit a feature request so bear with
>> me if I mess up the instructions, I'll do my best to rectify any issues if
>> they occur and are pointed out.
>>
>> *Feature Proposal:* Vertex Colors on TriangleMesh
>> Add a new ObservableIntegerArray to TriangleMesh which contains vertex
>> colors in ARGB8888 integer format. (I'm open to the pixel format being
>> flexible too, but this may be unnecessary).
>> Operation of this array should be the same as the other mesh arrays, in
>> the sense that the VertexFormat object configures how they should operate.
>> Similarly to how normals currently work, the array is optional, and may
>> not necessarily need to be included.
>> Additionally, the face array will also work the same as usual, where the
>> new color indices will be specified on a per-face-vertex basis. (Each
>> vertex of each face will have an index specified)
>> If the array is present/valid, the colors should be multiplied by 2x the
>> diffuse/selfIllumination/specular textures when calculating the FragColor.
>> (Clamp the color to the maximum color value of 1.0 when done)
>> The reason we multiply by two is to allow the vertex colors to create
>> color components larger than what was seen in the texture. So for example,
>> a blue component of .75 will result in 1.5x the blue value from the
>> material texture.
>> This is the standard way of calculating vertex colors when there is a
>> texture as I understand. If there were no texture, it would not be
>> multiplied by 2.0
>> The rasterization process should be responsible for interpolation colors,
>> as seen in my examples below.
>>
>> Example without feature:
>> https://i.imgur.com/Hg81LtU.png
>>
>>
>> Example with feature:
>> Notice how the lava stream & pipes are the same texture repeated many
>> times, but once the vertex coloring feature is used it becomes
>> significantly less apparent.
>> It can also be used to add details like the rust on various
>> metal surfaces, or how the lava fades to black towards the edges. JavaFX
>> doesn't contain the appropriate tools to render this scene, but pretty much
>> any other 3D library does.
>>
>>
>>
>>
>> *Why adding this API to the core of JavaFX is a positive/useful addition
>> for different applications.*Vertex coloring is a core 3D rendering
>> feature supported by virtually every other 3D rendering system on the
>> planet. It works on low-end systems, and has been part of 3D rendering
>> since the beginning.
>> This is true whether the 3D rendering library is high-level (SGI
>> OpenInventor, Java3D, jmonkeyengine, etc), low-level (DirectX, Metal,
>> Vulkan, OpenGL), or somewhere in-between (Unreal Engine, Unity, Blender,
>> etc).
>> The only library I could even find which did not support this was JavaFX.
>>
>> But, just because everyone else does it doesn't mean JavaFX should, right?
>> Well, I'd actually like to argue that it should. If JavaFX wants to be
>> reasonably compatible/interoperable with virtually any other 3D format,
>> application, or tool, it needs to support this.
>> Any tool with the capability of importing/exporting 3D models has only
>> one for displaying vertex coloring right now: to generate their own texture
>> sheet with vertex color shading baked in on a per-face basis.
>> This can be a pretty slow process when there are a lot of different
>> faces, since every single face with even a single polygon with a slightly
>> different texture coordinate will need a new texture on the texture sheet.
>> The above screenshot I've shown requires a 4096x4096 texture sheet in
>> order to render in JavaFX, and it's a pretty small scene! I've got
>> significantly larger scenes which I'm completely unable to render with
>> shading because I need to generate a texture sheet more than a gigabyte
>> large in order to shade it properly.
>> And forget about any kind of common texCoord/UV animations. The CPU needs
>> to be constantly redrawing shading textures onto the texture sheet in order
>> to ensure animations have the correct shading.
>> For the above example, trying to animate the lava to flow down the screen
>> as it's supposed to brings my FPS below 30.
>> This is despite the texture drawing process having run in parallel and
>> extensive performance profiling on my part. I've concluded there's no way
>> to get around having proper vertex color support as the main bottleneck is
>> just sending such a massively large image to the GPU so frequently as well
>> as having to actually shade the images still taking a pretty decent amount
>> of time even when done in parallel. And remember, these performance issues
>> are happening on one of my small scenes.
>>
>> Normally drawing vertex colors like this is extremely fast (even on 30
>> year old hardware!) when done by the GPU/dedicated hardware, but JavaFX
>> just doesn't provide a way to do it with the GPU.
>> JavaFX is also the only mainstream 3D library I could find which lacks
>> this feature.
>> There are 3D environments I cannot even display with shading right now at
>> all due to the sheer amount of large textures that need to have shading
>> manually drawn onto them.
>> This cannot be solved by using a project like Fxyz
>> <https://github.com/FXyz/FXyz>, since it just comes down to the texture
>> sheets being too large.
>> These scenes aren't even particularly large either, having been made for
>> game consoles in the range of 20-30 years ago.
>>
>> This will happen to anyone who needs to use vertex coloring with a
>> significant number of textures, and requires writing a lot of code to
>> manage texture sheets to ultimately just for it to only partially suffice.
>>
>> There are other reasons to want vertex coloring outside of compatibility
>> with other software too.
>> Vertex coloring can often be used to add significant mesh details.
>> In the above example, I've already demonstrated how this can be used to
>> add details such as rust, fade-outs, etc. But there are many more ways to
>> include it too, such as using art styles with flat textures, such as for
>> clouds, cartoon art-styles, etc. It's even possible to create shadows by
>> using darker colors in areas obscured by others. There are so many clever
>> ways this can be used, and I'd spend too much time on individual examples.
>> The reason vertex colors have been so prevalent is specifically because of
>> the payoff between how easy they are to add and how much can be achieved
>> with them.
>> I'm not enough of an artist to explain everything with words, but I can
>> certainly give a lot of examples via screenshot, if desired.
>>
>> Since the guideline was to tailor this pitch to the JavaFX community, I
>> thought I'd include mention of a few JavaFX projects that I thought would
>> benefit significantly. There were others that would benefit in less
>> significant ways, so I tried to keep it brief:
>> - Fxyz <https://github.com/FXyz/FXyz>: Probably the most popular JavaFX
>> 3D project.
>> - GameExtractor <https://github.com/wattostudios/GameExtractor/>:
>> Capable of showing 3D objects in many common formats (.obj, .3ds, Unity
>> Format, Unreal Engine 2/3 Format, etc), but is unable to show vertex colors
>> due to JavaFX's lack of support.
>> - FrogLord <https://github.com/Kneesnap/FrogLord>: This is my project,
>> but every single game I support desperately needs this feature in order to
>> accurately preview the custom levels as they are edited, so the user can
>> see how they will appear in their game.
>>
>> Pretty much any project which creates texture sheets containing
>> interpolated colors will benefit from this change as in many cases they
>> won't need to do that anymore.
>> Due to the reduced time and memory usage it will also become
>> significantly more feasible/performant to use meshes which change over time
>> as well, since fewer changes to the texture sheet will be required, if any
>> at all.
>>
>> I also imagine this fitting in very easily with the existing API, as
>> pretty much all of the public facing APIs could just have a few new methods
>> in them, without needing to change any pre-existing APIs at all.
>>
>> In summary,
>> Vertex colors are a feature as ubiquitous in the 3D world as texture
>> coordinates, lighting, and materials, yet JavaFX doesn't have them.
>> Adding them will allow for a significant amount of detail for virtually
>> no performance or maintenance cost, and for some projects it will even
>> improve performance & simplify texture sheets.
>>
>> Additional Note:
>> https://bugs.openjdk.org/browse/JDK-6586559
>> It looks like this feature may have already been planned at one point,
>> but was forgotten due to being low-priority? I don't know.
>>
>> What does everyone think about this proposal? I eagerly await responses!
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/openjfx-dev/attachments/20240820/03472115/attachment-0001.htm>
More information about the openjfx-dev
mailing list