2015-08-21 3 views
0

Я работаю над тенями для 2D-накладных игр. Прямо сейчас тени - это просто спрайты с цветом (0,0,0,0,1), нарисованным над слоем над плитами.LibGDX Overlapping 2D Shadows

Проблема: когда многие сущности или деревья сгущаются вместе, тени перекрываются, образуя неестественно выглядящие темные области.

    (Picture)

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

+0

Я уже некоторое время искал что-то подобное. Я нашел небольшую полезную информацию, и методы, которые я нашел, были слишком тяжелыми для использования. – tobloef

ответ

0

Если вы не хотите иметь дело с проблемами сортировки, я думаю, вы можете сделать это с помощью шейдера. Но каждый объект должен быть либо затронут тенью, либо нет. Таким образом, высокие деревья могут быть отмечены как не получение тени, в то время как земля, трава и персонажи будут получать тень.

Сначала сделайте буфер рамки с прозрачным белым цветом. Нарисуйте все свои тени на нем как чистый черный.

Затем создайте шейдерный шейдер, чтобы нарисовать все в своем мире. Это зависит от того, что вам не нужны все четыре канала цвета спрайта, потому что нам нужен один из этих каналов, чтобы отмечать каждый спрайт как получение тени или нет. Например, если вы не используете RGB для оттенка ваших спрайтов, мы можем использовать R-канал. Или, если вы не угасание их и, мы могли бы использовать А. Я буду считать последний здесь:

Vertex шейдеров:

attribute vec4 a_position; 
attribute vec4 a_color; 
attribute vec2 a_texCoord0; 

varying vec2 v_texCoords; 
varying vec2 v_texCoordsShadowmap; 
varying vec4 v_color; 

uniform mat4 u_projTrans; 

void main() 
{ 
    v_texCoords = a_texCoord0; 
    v_color = a_color; 
    v_color.a = v_color.a * (255.0/254.0); //this is a correction due to color float precision (see SpriteBatch's default shader) 
    vec3 screenPosition = u_projTrans * a_position; 
    v_texCoordsShadowmap = (screenPosition.xy * 0.5) + 0.5; 
    gl_Position = screenPosition; 
} 

Фрагмент шейдеры:

#ifdef GL_ES 
    precision mediump float; 
#endif 

varying vec2 v_texCoords; 
varying vec2 v_texCoordsShadowmap; 
varying vec4 v_color; 

uniform sampler2D u_texture; 
uniform sampler2D u_textureShadowmap; 

void main() 
{ 
    vec4 textureColor = texture2D(u_texture, v_texCoords); 
    float shadowColor = texture2D(u_textureShadowmap, v_texCoordsShadowmap).r; 
    shadowColor = mix(shadowColor, 1.0, v_color.a); 
    textureColor.rgb *= shadowColor * v_color.rgb; 
    gl_FragColor = textureColor; 
} 

Они полностью непроверены и, вероятно, имеют ошибки. Убедитесь, что цветная текстура буфера назначена «u_textureShadowmap». И для всех ваших спрайтов установите альфа-версию своего цвета, исходя из того, сколько тени вы хотите, чтобы они наносили на них, что обычно будет 0 или 0,1 (в зависимости от яркости, которую вы использовали раньше).

+0

К сожалению, мне нужно использовать все 4 цветовых канала с моей игрой. Есть ли способ обойти это или использовать другой метод? – Anuken

+0

Думаю, вам придется их сортировать. Но если вы не используете Scene2D или TiledMapRenderer, я думаю, вы можете клонировать SpriteBatch и изменить его, чтобы включить в него один дополнительный атрибут вершины. – Tenfour04

+0

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

0

Нарисуйте свои тени в fbo с отключенным смешением.

Нарисовать фон, например. трава Нарисуйте текстуру теней от fbo Рисовать все остальные спрайты