glTF icon indicating copy to clipboard operation
glTF copied to clipboard

KHR_lights_shadows extension

Open takahirox opened this issue 3 years ago • 10 comments

Working repository https://github.com/takahirox/KHR_lights_shadows

I would like to propose KHR_lights_shadows extension that allows to define whether a mesh casts or receives shadows and whether a light casts shadows against KHR_lights_punctual extension.

Rendering with shadows needs a lot of calculation. It is a common technique to select objects which cast or receive shadows in a scene. KHR_lights_punctual extension has the capability of defining lights but doesn't have the capability of defining shadows.

This KHR_lights_shadows extension provides a way to let applications or engines know what meshes should cast or receive shadows and what lights should cast shadows.

Note that this extension doesn't define shadow rendering techniques (ie. Shadow Map) or shadow types (ie. PCF). They should be application or engine specific (or another extension).

And also it doesn't define whether a mesh is visible and doesn't define whether a light is active.

Examples

Define whether a mesh casts/receives shadows in glTF.mesh.

"meshes": [{
    "primitives": [
        ...
    ],
    "extensions": {
        "KHR_lights_shadows": {
            "castShadows": false,
            "receiveShadows": true
        }
    }
}, {
    "primitives": [
        ...
    ],
    "extensions": {
        "KHR_lights_shadows": {
            "castShadows": false,
            "receiveShadows": true
        }
    }
}]

Define whether a light casts shadows in glTF.extensions.KHR_lights_punctual.light.extensions.KHR_lights_shadows.

"extensions": {
    "KHR_lights_punctual": {
        "lights": [{
            "type": ...,
            "color": ...,
            "extensions": {
                "KHR_lights_shadows": {
                    "castShadows": true
                }
            }
        }]
    }
}]

Update: I have moved the extension from under mesh to under mesh.primitive. Please refer to the following comments for the details.

takahirox avatar Oct 30 '22 22:10 takahirox

I just wanted to provide some feedback on this proposal specifically around the location of the castShadows, receiveShadows properties on the mesh, with respect to the discussion here: https://github.com/takahirox/KHR_lights_shadows/issues/12

So if I am not mistaken, typically receiving shadows requires a shader compilation change. Up until this point the actual mesh information has not been required to compile the shader as the primitive and material has been sufficient. Other mesh information (joints, morph weights) can be inferred from the attributes on the primitive (JOINTS, WEIGHTS). By placing this property on the mesh, this will require passing this adjacent information to the shader compilation code for each primitive. This can lead to more complex code especially when generating sets of primitives for instanced drawing. Because of this I would propose that this information be placed on the primitive instead.

The other property castShadows would also be more effective on the primitive. During the shadow map creation pass it would be trivial to filter primitives to where castShadows is true.

Just my two cents as a non KHR member. Also, I must admit that I have not researched how other engines do this.

Otherwise I really like this proposal, simple and effective.

  • Edit, realized my link to the relevant discussion was incorrect.

shannon avatar Oct 31 '22 00:10 shannon

I agree that cast/receive shadows should be on primitive as they are an individual draw calls, and have own shadow/shader/render states.

Also, what are the default values? For consistent rendering across engines, if they implement such extension, it is best to describe the default values.

Maksims avatar Oct 31 '22 13:10 Maksims

Assigning to materials, rather than primitives, might also solve that issue? Similar to material.doubleSided=true. Although then casting and receiving properties might end up in different locations..

donmccurdy avatar Oct 31 '22 14:10 donmccurdy

Yea I think it could be placed on the material since it referenced by the primitive anyways. However, normally the shadow map pass doesn't need other material information as it is rendering depth only and really only needs the geometry. So yea it would be best to keep castShadow on the primitive, and at that point, you might as well keep them together.

shannon avatar Oct 31 '22 15:10 shannon

FYI

X3D 4 puts 2 attributed on any light node:

https://www.web3d.org/specifications/X3Dv4Draft/ISO-IEC19775-1v4-DIS/Part01/components/lighting.html#Shadows

and a field allows Shapes to cast or not 17.2.2.8 Shadows

Geometric objects can cast shadows, meaning that the amount of light reaching a given surface is decreased if a light source is obscured by occluding geometry. Intervening geometry is only considered for occlusion effects when the X3DShapeNode field castShadow is TRUE.

Multiple light sources can have shadows enabled. Lighting contributions from each light source, and the intensity of corresponding shadows that reduce light available at end points, are each computed independently before reaching lit surface points.

High-fidelity physical effects such as umbra, penumbra and antumbra may be optionally applied. X3D browser implementations are allowed some variations in shadow rendering.

On Mon, Oct 31, 2022 at 4:01 PM Shannon Poole @.***> wrote:

Yea I think it could be placed on the material since it referenced by the primitive anyways. However, normally the shadow map pass doesn't need other material information as it is rendering depth only and really only needs the geometry. So yea it would be best to keep castShadow on the primitive, and at that point, you might as well keep them together.

— Reply to this email directly, view it on GitHub https://github.com/KhronosGroup/glTF/pull/2220#issuecomment-1297220125, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB2TSM3HIDFBP6MEOCRGK5TWF7NMXANCNFSM6AAAAAARSRNS3E . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Nicholas F. Polys, Ph.D.

Director of Visual Computing Virginia Tech Research Computing

Affiliate Professor Virginia Tech Department of Computer Science https://people.cs.vt.edu/~npolys/ https://people.cs.vt.edu/~npolys/

npolys avatar Oct 31 '22 15:10 npolys

Assigning to materials, rather than primitives, might also solve that issue? Similar to material.doubleSided=true. Although then casting and receiving properties might end up in different locations..

I'm afraid this will be limiting then. There are often generic materials reused over many objects, while they can have own states like shadow casts and so on.

One of the best way, would be to check many engines, and look how they allow to set such setting and where.

Maksims avatar Oct 31 '22 19:10 Maksims

Thanks for the feedbacks. They make sense to me. I moved the extension from under mesh to under mesh.primitive.

Regarding mesh.primitive vs material, please let me know any software, workflows, engines that don't greatly fit to the extension under mesh.primitive if you folks know.

In Three.js, THREE.Mesh, which corresponds to mesh.primirive in glTF, can have cast/receiveShadows properties while THREE.Material, which corresponds to material in glTF, can't.

takahirox avatar Oct 31 '22 20:10 takahirox

Thanks for the feedbacks. They make sense to me. I moved the extension from under mesh to under mesh.primitive.

Regarding mesh.primitive vs material, please let me know any software, workflows, engines that don't greatly fit to the extension under mesh.primitive if you folks know.

In Three.js, THREE.Mesh, which corresponds to mesh.primirive in glTF, can have cast/receiveShadows properties while THREE.Material, which corresponds to material in glTF, can't.

Same with PlayCanvas engine, it controls shadow cast/receive on MeshInstance/primitive, and not on material.

Maksims avatar Nov 06 '22 15:11 Maksims

Ok – it seems like there's a convention here then, I'm happy going with that.

donmccurdy avatar Nov 12 '22 15:11 donmccurdy

This extension seems relatively straightforward and might be useful to many people. Although I'm not a member of the Khronos Group, I'm curious: what could be done to move its development forward?

The0Dev avatar Nov 20 '24 22:11 The0Dev