Open microaaron opened 1 year ago
That would be great if somebody would want to tackle it.
Suggest adding, not breaking. X3D 4.0 includes full support for glTF 2.0, either as an Inline file or through use of corresponding X3D 4.0 nodes provide equivalent rendering capabilities.
Just to clarify, glTF 2.0 does not depend on WebGPU.
Base glTF 2.0 is already well supported by x3dom. The main piece missing is skinning.
However, glTF extensions became more important, in particular the Khronos ratified ones:
https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos
The added materials in particular would be a priority.
@andreasplesch @brutzman I'm very excited to say that this is achievable. I disabled most of the functionality to make this minimal scene runnable. Yes, it is WebGPU based. https://jsitor.com/yxjz-UVVAf7
Very cool, you did it ! It works for me in on Linux in Firefox nightly. I could not get WebGPU in Chrome to work on Linux.
A looked around a bit in the code. A serious deep dive into the gfx rendering and figured how to use WebGPU. For the x3dom.WebGPU classes did you use an existing library or framework as a template ? I found for example
https://pursuit.purescript.org/packages/purescript-webgpu/0.0.0
There are probably many others. https://jmberesford.github.io/webgpu-kit/docs/
I see you adapted the dynamic shader to make it work, more or less directly translating glsl I think.
To be honest, I think the shader generation is not really sustainable the way it is. It may move to #defines et al. and chunks and webgpu may the opportunity to do that. Easier said than done. Ideally, we would want a way to reuse three.js shader chunks, I think. That may mean to also use similar webgpu layout, pipelines and such which may not be feasible.
webgpu is so flexible since lower level than webgl that it may make sense to think more fundamentally about how to map best x3d to webgpu. Is there something which can be moved from the CPU to the GPU ? Porting and trying things may reveal more.
Great progress !
I studied the examples in /webgpu.github.io. Sort out their program flow. Take shadowMapping as an example: I found that matching data in uniform/storage buffers and shader moudles was a tedious and error-prone job. So I wrote a lightweight class myself. (No reference to other frameworks.) The core file is here: https://github.com/microaaron/x3dom/blob/webgpu/src/util/WebGPU/WebGPU.js (it's incompleted yet)
Yeah, quite intimidating. Thanks for sharing !
To facilitate portability I wrote this "RenderPassResource" class. https://github.com/microaaron/x3dom/blob/e75c52240d6bfac99f81c17c2d8a904e935b7755/src/util/WebGPU/WebGPU.js#L582 It has similar functions to the previous "shader". It can write data to the corresponding buffer by the variable name.
Added texture and sampling functionality https://jsitor.com/s4asRDroIR6 Compute shaders are not implemented yet. Webgpu is not difficult for me, but I don't know all the functions of x3dom, and I don't know how the current code works. The porting work is difficult for me to do.
I see you adapted the dynamic shader to make it work, more or less directly translating glsl I think.
To be honest, I think the shader generation is not really sustainable the way it is. It may move to #defines et al. and chunks and webgpu may the opportunity to do that.
Yes, I translated glsl directly. Refactoring some modules is worth considering, but before that I hope to have an architecture diagram for reference.
There's something wrong with the near plane.This may be related to NDC.
You probably have seen how znear is automatically calculated if not explicitly provided:
Adding
<viewpoint znear='0.1'></viewpoint>
to the example avoids the clipping. So perhaps something is off how znear is automatically calculated or then used.
Maybe it is time again to consider an option for the infinite projection matrix, #1207.
It would be a good default, or a default if only znear is provided and no zfar.
You probably have seen how znear is automatically calculated if not explicitly provided:
I got it, these two codes need to be modified together.The same code exists in two files. https://github.com/x3dom/x3dom/blob/c5489754e8571fce582978546443c1250b739942/src/nodes/Navigation/Viewpoint.js#L297-L298 https://github.com/x3dom/x3dom/blob/c5489754e8571fce582978546443c1250b739942/src/fields.js#L315-L325
You probably have seen how znear is automatically calculated if not explicitly provided:
I got it, these two codes need to be modified together.The same code exists in two files.
This looks like a perhaps unnecessary optimization to avoid having to generate a completely new SFMatrix4f object.
Depending on how often this gets called (probably not every frame), it should be possible to replace it with something like
this._projMatrix = x3dom.fields.SFMatrix4f.perspective ( fovy, aspect, znear, zfar ) ;
https://github.com/x3dom/x3dom/blob/c5489754e8571fce582978546443c1250b739942/src/fields.js#L315-L325
For infinite projection, perhaps it works best to special case in this function far == null (or -2 ?) and then return the infinite projection matrix ?
shows when that the recalculation of perspective in Viewpoint was optimized.
shows when that the recalculation of perspective in Viewpoint was optimized.
This might be better:
//fields.js
x3dom.fields.SFMatrix4f.Perspective = class Perspective extends x3dom.fields.SFMatrix4f
{
//Normalized device coordinates X:[-1~1] Y:[-1~1] Z:[0~1]
constructor ( fov, aspect, near, far )
{
var f = 1 / Math.tan( fov / 2 );
if ( far )
{
var m_22 = far / ( near - far );
var m_23 = near * far / ( near - far );
}
else //lim far->+∞
{
var m_22 = -1;
var m_23 = -near;
}
super(
f / aspect, 0, 0, 0,
0, f, 0, 0,
0, 0, m_22, m_23,
0, 0, -1, 0
);
this.aspect = aspect;
this.nearDistance = near;
this.farDistance = far;
}
setDistances ( near, far )
{
this.nearDistance = near;
this.farDistance = far;
if ( far )
{
this._22 = far / ( near - far ); this._23 = near * far / ( near - far );
}
else //lim far->+∞
{
this._22 = -1; this._23 = -near;
}
}
setNearDistance ( near )
{
setDistances( near, this.farDistance );
}
setFarDistance ( far )
{
setDistances( this.nearDistance, far );
}
setFieldOfView ( fov )
{
var f = 1 / Math.tan( fov / 2 );
this._00 = f / this.aspect;
this._11 = f;
}
setAspect ( aspect )
{
this.aspect = aspect;
this._00 = this._11 / aspect;
}
};
//Viewpoint.js
if ( this._projMatrix == null )
{
this._projMatrix = new x3dom.fields.SFMatrix4f.Perspective( fovy, aspect, znear, zfar );
}
else if ( this._zNear != znear || this._zFar != zfar )
{
this._projMatrix.setDistances( znear, zfar );
}
else if ( this._lastAspect != aspect )
{
this._projMatrix.setAspect( aspect );
this._lastAspect = aspect;
}
Textured shapes does not seem to be affected by head light, is this expected?
With the release of chrome 113, webgpu has been officially supported. Is it time to start transitioning x3dom from webgl2.0 to webgpu?