Three.js: THREE.Points: shader error with receiveShadow = true

Created on 5 Dec 2015  路  16Comments  路  Source: mrdoob/three.js

In r73 (I don't know in previous versions):

var points = new THREE.Points( geometry, material );
points.receiveShadow = true;

Throws "THREE.WebGLShader: gl.getShaderInfoLog() vertex ERROR: 0:234: 'transformed' : undeclared identifier".
I can see the 'transformed' in THREE.ShaderChunk[ "worldpos_vertex" ], but THREE.ShaderChunk[ 'begin_vertex'] is not listed in THREE.ShaderLib.points.vertexShader

Bug

All 16 comments

Partial solution:

In ShaderLib.js redefine the THREE.ShaderLib[ 'points' ] vertex shader like so:

        vertexShader: [

            "uniform float size;",
            "uniform float scale;",

            THREE.ShaderChunk[ "common" ],
            THREE.ShaderChunk[ "color_pars_vertex" ],
            THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
            THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],

            "void main() {",

                THREE.ShaderChunk[ "color_vertex" ],
                THREE.ShaderChunk[ "begin_vertex" ],
                THREE.ShaderChunk[ "project_vertex" ],

            "   #ifdef USE_SIZEATTENUATION",
            "       gl_PointSize = size * ( scale / - mvPosition.z );",
            "   #else",
            "       gl_PointSize = size;",
            "   #endif",

                THREE.ShaderChunk[ "logdepthbuf_vertex" ],
                THREE.ShaderChunk[ "worldpos_vertex" ],
                THREE.ShaderChunk[ "shadowmap_vertex" ],

            "}"

        ].join( "\n" ),

Points will receive shadows, but still do not cast shadows, as far as I can tell.

Thanks @WestLangley, it works now.

@arnaldof Are you able to cast shadows with THREE.Points?

@WestLangley points does not cast shadows, I tested it for you. I don't need that feature but maybe somebody does.

Points and Line cast shadows, but shadowmapping does not take the point size or line width into consideration.

Adding gl_PointSize = 10.0; to depthRGBA's vertex shaders gets something going.

screen shot 2015-12-09 at 16 07 47

However, it's going to be difficult to match the shadowed particle size with the visible particle size as each camera (shadow and user) has different dimensions.

Trying to get the shadow color to look right is also tricky...

I'm thinking we should remove shadow support in MeshBasicMaterial and PointsMaterial and keep these materials simple.

We should then rename PointsMaterial to PointsBasicMaterial and add PointsStandardMaterial with shadow support.

@WestLangley?

However, it's going to be difficult to match the shadowed particle size with the visible particle size as each camera (shadow and user) has different dimensions.

Correct. Same for linewidth.

I'm thinking we should remove shadow support in MeshBasicMaterial and PointsMaterial and keep these materials simple.

That seems reasonable. Note that LineBasicMaterial uses the MeshBasicMaterial shader, too.

We should then rename PointsMaterial to PointsBasicMaterial and add PointsStandardMaterial with shadow support.

I don't think so. MeshStandardMaterial is a PBR material. I would not use the term PointsStandardMaterial, and would just leave it at PointsMaterial, which does not respond to lights. Whether you retain shadow support for PointsMaterial is up to you.

I don't think so. MeshStandardMaterial is a PBR material. I would not use the term PointsStandardMaterial, and would just leave it at PointsMaterial, which does not respond to lights. Whether you retain shadow support for PointsMaterial is up to you.

The idea was to split PointsMaterial in two. One that has no shadows (basic) and another one that has lighting (shadows + ambientlight). So, instead of naming it PointsLitMaterial I was trying to align the material names somehow.

However, it's going to be difficult to match the shadowed particle size with the visible particle size as each camera (shadow and user) has different dimensions.

Correct. Same for linewidth.

For that reason, I am not sure it makes sense to support shadows for points and lines. The only way it could ever _properly_ work is if point size and line width were in world units (not pixels) -- and could be attenuated in world units.

Also, I am not sure it makes sense for materials that do not respond to lights to cast shadows. That includes, MeshBasicMaterial, LineBasicMaterial, and PointsMaterial.

What features would you like to support? Then we can figure what materials we need, and their names.

Yeah, I'm still trying to figure that out.

I think letting *BasicMaterial cast shadow is not a problem as the user can control that with .castShadow. It's also less code, otherwise we would have to add another exclusion condition in WebGLShadowMap.

Receiving shadow however is different as that requires extra code (specially because of the ambient color in shadowed areas). In the screenshot I posted the shadow in the particles shouldn't be so dark. In order to fix that we need to make the material more complicated.

People expect diffuse color to not be modulated when using *BasicMaterial. The problem is that we broke that rule when adding shadow support. Even then, that was fine until we started improving shadows.

With *BasicMaterials we can't just do vec3 outgoingColor = vec3( diffuse * shadowMask + ambientLightColor ) because then ambientLightColor will affect the diffuse.

Actually, maybe a simpler solution by now would be doing vec3 outgoingColor = vec3( mix( diffuse, ambientLightColor, shadowMask ) ). It will, at least, look better than just black.

I do not think it makes sense to support shadows for primitives that can't be sized in world units. There is no way to get the shadow size correct.

Yep, we can't make it automatic. But we can add something like a multiplier parameter to the shadow which would then be applied to linewidth and particle scale when rendering the depth texture. Then people will have to tweak that parameter until it looks right for their case. Better than nothing.

This guy had to figure out his way with custom shaders:

https://twitter.com/edankwan/status/674628600709193730
http://blog.edankwan.com/post/three-js-advanced-tips-shadow

But we can add something like a multiplier parameter to the shadow

Yes, that would be a work-around, I guess.

Or, we can tell users to specify a customDepthMaterial, and provide a three.js example to demonstrate.

We can also do both 馃榿

Hmm... Even with the ambient color "fixed", it actually doesn't look super great, because the shadowmap affects the whole particle when only its center is occluded...

screen shot 2015-12-10 at 21 45 04

I've spent a bit trying to get something interesting with a lot of particles, but doesn't seem to be worth it. I think I'll leave this one for now...

Was this page helpful?
0 / 5 - 0 ratings