1

Is there a feature, option, or some shader, that allows sprites to cast and receive shadows? Also including that sprite's alpha channel is not rendered as a shadow.

I have all my assets as transparent PNGs, and I am using sprites in three.js to map the textures onto sprites. This is working great apart from the problem of shadows. Ideally, it would be great that shadow casted from the sprite does not include the PNG's alpha channel*, so that light passes through the alpha channel of the png, although I am finding little research on this in the documentations of threejs.

*I am thinking of a similar style to PaRappa the Rapper or Adventure Xpress.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
bitten
  • 2,463
  • 2
  • 25
  • 44

2 Answers2

2

Sprites in three.js do not cast shadows.

A work-around is to use PlaneBufferGeometry and keep it facing the camera like so:

scene.add( plane );

then in the render loop,

plane.lookAt( camera.position );

If you want the plane not to cast a shadow wherever the plane's texture is transparent, you need to create a custom depth material. An example of doing so can be see in this three.js example.

Without creating a custom depth material, the plane will appear solid from the point of view of the light.

three.js r.76

WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • Thanks for the great information! I do not neccesarily want each plane to face the camera, though. See this reference: http://i.imgur.com/fzjmvg5.png. (using your advice and creating the objects with `PlaneBufferGeometry` I'm able to create the images and have it with transparency so thanks, all that's lacking in the reference image are shadows). Is it necessary to use `lookAt`? – bitten May 13 '16 at 19:07
  • Use `lookAt()` only if you want to. – WestLangley May 13 '16 at 19:29
  • Great thanks. So I am looking at `view-source:http://threejs.org/examples/webgl_animation_cloth.html` and giving my meshes (from `PlaneBufferGeometry` and `MeshPhongMaterial`) a `customDepthMaterial`, even using the code from the example, and I still see no shadows. I added a cube in my scene to show that I have lights, and as you can see the shadow are being cast from the cube but not my PBG's: http://i.imgur.com/jAeWhRJ.png. I am really using the same code from the example, inc the vertex and fragment shaders, and all cloth related code. – bitten May 13 '16 at 20:00
  • Here is my object code: http://pastebin.com/51JXLSTX. The vertex shader and fragment shader I took from the example: http://pastebin.com/Wqaqv31q. What am I doing wrong here? Thanks. – bitten May 13 '16 at 20:01
  • Please, I answered your original question. If you are not able to get your code to work after significant effort, then please make a new post with your new question. – WestLangley May 13 '16 at 20:07
  • It seems like I am still on topic, coming from the same question of how to use the shader to exclude the alpha channel of the PNG though, but, fair enough. Still, thanks for the information again. – bitten May 13 '16 at 21:13
  • Sorry. I can answer questions about three.js, but I can't help you debug your code. I hope you understand... – WestLangley May 13 '16 at 21:53
  • I understand. Is it strange that my planebuffergeometry, with a texture mapped to it, is not casting a shadow? Does threejs support casting shadows from a planebuffergeometry? (this is less of a debug question, less of a 'is my code broken', and more of a general question, more of a 'is this even possible in threejs'). You do not have to debug my code, and apologises ahead for asking so much. – bitten May 15 '16 at 17:54
  • http://stackoverflow.com/questions/21797681/three-shadermaterial-is-seen-inverted-by-the-shadow-camera/21841979#21841979 There have been many changes in how shadows are rendered in three.js, so it depends on your version... Or try cubes instead of planes... Or set double-sided material and have your planes face away from the light. Experiment. – WestLangley May 15 '16 at 18:19
2

These are the shaders I ended up using.

Fragment shader. You can change the pixel.a which is the alpha value of the pixel. The fragment shader is discarded on this pixel if the alpha value falls below 0.5 (thus leaving it to appear transparent).

#include <packing>

uniform sampler2D texture;
varying vec2 vUV;

void main() {

    vec4 pixel = texture2D( texture, vUV );
    if ( pixel.a < 0.5 ) discard;
    gl_FragData[ 0 ] = packDepthToRGBA( gl_FragCoord.z );

}

Vertex shader. This is nothing special, I thought I would leave this here just incase your vertex shader is causing issues, this one I can confirm to be compatible with the above fragment shader.

varying vec2 vUV;

void main() {

    vUV = uv;
    vec4 mvPosition = modelViewMatrix * vec4( position, 1 );
    gl_Position = projectionMatrix * mvPosition;

}
bitten
  • 2,463
  • 2
  • 25
  • 44