Extensions introduced in Castle Game Engine related to shapes.
See also documentation of supported nodes of the Shape component and X3D specification of the Shape component.
Contents:
Shape.render
)This field is deprecated now. Use instead the standard (since X3D 4.0) field visible
— it's a better name, and standardized. It is exactly equivalent to how render
worked.
X3DShapeNode { ... SFBool [in,out] render TRUE }
The field render
allows to easily hide and show
the given Shape
. A hidden shape is not rendered, but otherwise
it's still processed (for example, it is used for collision detection).
If you want to hide a particular shape, sometimes this may be a simpler method
than using standard X3D Switch
node. It doesn't require to wrap
the Shape
in a Switch
node.
This is compatible with InstantReality Shape extension.
Shape.shading
)We add a shading
field to the Shape
node
(more precisely, to the abstract X3DShapeNode
):
X3DShapeNode { ... all normal X3DShapeNode fields ... SFString [in,out] shading "DEFAULT" # ["DEFAULT"|"GOURAUD"|"PHONG"|"WIREFRAME"] }
The allowed values for the shading
field are listed below.
They are consistent with "Browser options" in X3D spec
(with DEFAULT
added by us).
DEFAULT
: use the default shading.
The default is to use Phong shading in the latest version of CGE.
In Castle Model Viewer
you control this using the "View -> Phong Shading on Everything" checkbox.
In your own games you control this using the
MyScene.RenderOptions.PhongShading
property in Pascal code.
GOURAUD
: fast per-vertex lighting calculation.
Specifying the "GOURAUD"
indicates that this shape wants to use Gouraud shading, regardless if the default scene shading is Phong or Gouraud.
Note that some features (like two-sided lighting, bump mapping, shadow maps, PBR) will override this and require Phong shading anyway, since it's impossible to realize them with Gouraud shading.
Note that the "GOURAUD"
shading can performs only one-sided lighting in the shader pipeline. So it is only allowed if the backface-culling is also used, by solid="TRUE"
. Otherwise two-sided lighting forces usage of Phong shading.
PHONG
: pretty per-pixel lighting calculation.
This also means always using shader pipeline to render this shape.
This also works nicely with two-sided lighting, if both sides
of the mesh are visible, by using solid="FALSE"
.
WIREFFRAME
: render as a wireframe.
The rendering technique matches the
LineSet specification.
This means that we display the wireframe as unlit,
using the EmissiveColor
of the material for the unlit color
(or white, if there's no material).
For now this is only honored by some nodes: Box
, Sphere
,
IndexedFaceSet
.
The intention is to extend this to all geometry nodes
(submit a GitHub issue if you need this).
Testcase of Shape.shading="WIREFRAME".
NOTE: Having "wireframe" as an option for "shading" may sound weird. Traditionally, shading is Gouraud or Phong, and it determines how lighting is calculated (not whether we render polygons or lines). But in this case, "wireframe" implies also "unlit" so it makes sense, it means you are no longer concerned with lighting calculations. It is possible we will introduce in the future an independent boolean flag to toggle "wireframe" rendering, but still enable lit shading. For now, the current approach is satisfactory for many use-cases, and it's consistent with "Browser options" in X3D spec.
alphaMode
for Appearance
)We add a new field to the Appearance
node to request a specific
alpha treatment when rendering.
Appearance { ... all normal Appearance fields ... SFString [in,out] alphaMode "AUTO" # "AUTO"|"OPAQUE"|"MASK"|"BLEND"
# deprecated way of doing the same:
SFString [in,out] alphaChannel "AUTO" # "AUTO"|"NONE"|"TEST"|"BLENDING" }
This is no longer CGE extension. X3D 4.0 defines the
alphaMode
and we advise to use it.
Our extension alphaChannel
is deprecated, and it's equivalent to alphaMode
with just different names.
Test file of alphaMode
feature.
The following values are allowed for the alphaMode
:
Value AUTO
(the default) means that we auto-detect the correct alpha treatment, looking at various things.
For backward compatibility, Castle Game Engine first checks whether the deprecated alphaChannel
field is set to something else than AUTO
. If yes, then we use alphaChannel
value.
Material
properties (whether the material uses Material.transparency
> 0),
texture properties (whether some texture defines some alpha channel, and whether it's a yes-or-no alpha channel or smooth).
The interpretation of each texture may also be affected by it's ImageTexture.alphaChannel field.
OPAQUE
: Ignore any alpha channel, render as opaque.
MASK
: Use alpha-testing, which is good for textures having
a sharp (yes-or-no) alpha channel contents.
BLEND
: Use blending, which allows to show partial
transparency of textures and/or materials.
Shape.bboxCenter
, Shape.bboxSize
)X3DShapeNode { ... SFVec3f [in,out] bboxCenter 0 0 0 # (-Inf,Inf) SFVec3f [in,out] bboxSize -1 -1 -1 # [0,Inf) or -1 -1 -1 }
X3D specification of the X3DShapeNode
(ancestor of Shape
)
already includes the fields bboxCenter
, bboxSize
.
In CGE we make them [in,out]
which means you can attach X3D routes to them,
which means you can animate them.
This bounding box is useful e.g. by glTF skinned animation. When this box is not empty, it determines the shape bounding box, which means that the engine doesn't have to recalculate it every frame when the shape changes.
Note: In Pascal, you should access this by a single property
TAbstractShapeNode.BBox
,
using the TBox3D
type (this is used throughout CGE to express axis-aligned bounding boxes).
Shape.collision
)X3DShapeNode { ... SFString [] collision "DEFAULT" # ["DEFAULT"|"BOX"|"NONE"] }
The new field collision
specifies how the shape collides:
"DEFAULT"
means that we construct a triangle octree for this shape, to resolve collisions with it precisely, as a "set of triangles".
"BOX"
means to use the shape bounding box. Which may be auto-calculated, or provided in shape's bboxCenter/Size
fields.
Colliding as a box is much faster, especially in case the shape is dynamic (e.g. changes each frame by skinned animation or morphing). This is automatically used by glTF meshes affected by skinned animation, although you can turn it off.
"NONE"
means that shape does not collide.
In Pascal, the equivalent is to set
TAbstractShapeNode.Collision
, like MyShapeNode.Collision := scBox;
.
Note that X3D has an alternative method of providing a different (usually simpler) shape for collision
purposes: Collision
node with enabled
and proxy
fields.
Why is this extension still useful?
The collision="BOX"
automatically works together with shape bboxCenter/Size
.
When bboxCenter/Size
are not provided (or indicate empty box), then box is auto calculated.
When bboxCenter/Size
are provided (and do not indicate empty box),
then they are used for both display optimization and for collisions.
So it's more comfortable in both cases.
It can be easily toggled to "DEFAULT"
(in Pascal: scDefault
) if needed by the author (e.g. if performance drop is acceptable and you want recalculate spatial structure during glTF skinned animation), as described here.
"DEFAULT"
meaning may change in the future when activated some global like NewPhysics
, as we move to using physics engine for all collision detection, and will not automatically construct mesh colliders for everything.