three.js: как разрешить прозрачным спрайтам png отбрасывать и получать тени?

Я не уверен, возможно ли это, но я подумал, что стоит спросить: есть ли функция, опция или какой-то шейдер, который позволяет спрайтам отбрасывать и получать тени? Также включение альфа-канала этого спрайта не отображается как тень.

У меня все активы в виде прозрачных PNG, и я использую спрайты в three.js для сопоставления текстур на спрайтах. Это отлично работает, если не считать проблемы с тенями. В идеале было бы здорово, если бы тень, отбрасываемая из спрайта, не включала альфа-канал PNG *, чтобы свет проходил через альфа-канал PNG, хотя я нахожу мало исследований по этому поводу в документации threejs.

Возможно, это невозможно под threejs, или вообще, что понятно, но заранее спасибо.

* Я думаю о стиле, похожем на PaRappa the Rapper или Adventure Xpress.


person bitten    schedule 12.05.2016    source источник


Ответы (2)


Спрайты в three.js не отбрасывают тени.

Чтобы решить эту проблему, используйте PlaneBufferGeometry и держите его лицом к камере следующим образом:

scene.add( plane );

затем в цикле рендеринга

plane.lookAt( camera.position );

Если вы хотите, чтобы плоскость не отбрасывала тень там, где текстура плоскости прозрачна, вам необходимо создать материал с настраиваемой глубиной. Пример этого можно увидеть в этом примере three.js.

Без создания материала с нестандартной глубиной плоскость будет казаться твердой с точки зрения света.

three.js r.76

person WestLangley    schedule 12.05.2016
comment
Спасибо за отличную информацию! Однако я не обязательно хочу, чтобы каждый самолет был обращен к камере. См. Эту ссылку: i.imgur.com/fzjmvg5.png. (используя ваш совет и создавая объекты с PlaneBufferGeometry, я могу создавать изображения и получать их с прозрачностью, поэтому спасибо, все, чего не хватает в эталонном изображении, - это тени). Обязательно ли использовать lookAt? - person bitten; 13.05.2016
comment
Используйте lookAt(), только если хотите. - person WestLangley; 13.05.2016
comment
Большое спасибо. Итак, я смотрю на view-source:http://threejs.org/examples/webgl_animation_cloth.html и ставлю своим сеткам (из PlaneBufferGeometry и MeshPhongMaterial) customDepthMaterial, даже используя код из примера, и все еще не вижу теней. Я добавил куб в свою сцену, чтобы показать, что у меня есть источники света, и, как вы можете видеть, тень отбрасывается из куба, но не из моих PBG: i.imgur.com/jAeWhRJ.png. Я действительно использую тот же код из примера, включая вершинные и фрагментные шейдеры, а также весь код, связанный с тканью. - person bitten; 13.05.2016
comment
Вот мой объектный код: pastebin.com/51JXLSTX. Вершинный шейдер и фрагментный шейдер я взял из примера: pastebin.com/Wqaqv31q. Что я здесь делаю не так? Спасибо. - person bitten; 13.05.2016
comment
Пожалуйста, я ответил на ваш первоначальный вопрос. Если вы не можете заставить свой код работать после значительных усилий, напишите новый вопрос со своим новым вопросом. - person WestLangley; 13.05.2016
comment
Похоже, что я все еще в теме, исходя из того же вопроса о том, как использовать шейдер для исключения альфа-канала PNG, но, достаточно справедливо. Тем не менее, еще раз спасибо за информацию. - person bitten; 14.05.2016
comment
Прости. Я могу ответить на вопросы о three.js, но не могу помочь вам отладить ваш код. Надеюсь, ты понимаешь ... - person WestLangley; 14.05.2016
comment
Я понимаю. Странно ли, что моя плоская буферная геометрия с наложенной на нее текстурой не отбрасывает тень? Поддерживает ли threejs отбрасывание теней от геометрического буфера плоскости? (это не столько вопрос отладки, сколько вопрос «не работает ли мой код?» и больше общий вопрос, больше «возможно ли это в threejs?»). Вам не нужно отлаживать мой код, и заранее извиняюсь за то, что просили так много. - person bitten; 15.05.2016
comment
stackoverflow.com/questions/21797681/ В three.js внесено много изменений в способ рендеринга теней, поэтому это зависит от вашей версии ... Или попробуйте кубики вместо плоскостей ... Или установите двусторонний материал и ваши самолеты должны быть обращены в сторону от света. Экспериментируйте. - person WestLangley; 15.05.2016

Вот те шейдеры, которые я в итоге использовал.

Фрагментный шейдер. Вы можете изменить pixel.a, который является альфа-значением пикселя. Фрагментный шейдер отбрасывается на этом пикселе, если значение альфа опускается ниже 0,5 (таким образом, он остается прозрачным).

#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 );

}

Вершинный шейдер. В этом нет ничего особенного, я подумал, что оставлю это здесь, на тот случай, если ваш вершинный шейдер вызывает проблемы, я могу подтвердить, что он совместим с вышеуказанным фрагментным шейдером.

varying vec2 vUV;

void main() {

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

}
person bitten    schedule 15.07.2016