Quick Links: Gideros Home | Download Gideros | Developer Guide
Add drop shadow to a Sprite
  • If a single-colour sprite it too light in my game I want to apply a drop shadow to it. The intensity should depend on the average RGB lightness.

    image

    Option 1: Use a bitmap dropshadow and control the intensity with alpha. This is not ideal, because I have to create a drop shadow bitmap for every object that needs it.

    Option 2: SHADERS! Surely this must be possible using a shader? They are still a mystery to me, so I wouldn't know where to start.

    Option 3: Maybe there is a better way still?

    drop_shadow.png
    650 x 301 - 23K
    My Gideros games: www.totebo.com
  • SinisterSoftSinisterSoft +1 -1 (+1 / -0 )
    Maintainer
    Maybe this will work:

    Anchor point in the middle, make a second sprite with the same texture, set colour transform to 0,0,0 then alpha to 0.5, make it very slightly larger and draw it first.

    Likes: antix

  • Cheers sinister. I think maybe drop shadows are a bit overkill for shaders. May just stick to the extra bitmap, so I have full control of how it looks.
    My Gideros games: www.totebo.com
  • Xman +1 -1
    Member
    But this can not generate the feather edge for the shadow
  • antixantix +1 -1
    Member
    I think Shaders would be the only way to create a drop-shadow with feathering. If you get it working share the results, I could use a Shader that makes blurry stuff :)
    Check out my DevBlog, my GitHub, and my games Falling Animals | Breaky Wall | Exetor
  • pie +1 -1
    Member
    The Bloom example included in gideros seems to be a good starting point, even this one could be interesting to start writing your own (never tried it yet, but since it's coming from hgy29 I believe it will work :) )
    http://giderosmobile.com/forum/discussion/6682/radial-blur-effect-class#Item_1

    otherwise there is shadertoy

    http://giderosmobile.com/forum/discussion/6667/shadertoy-viewer-beta-shaders-from-www-shadertoy-com-in-gideros/p1

    there should be a drop shadow here! :)
  • antixantix +1 -1
    Member
    @pie the first one seems viable. You could make a sprite a bit larger than the original image, blur it, draw it to a rendertarget, and you would have your drop shadow.

    I should really have a look at all those other shaders sometime too :)

    Check out my DevBlog, my GitHub, and my games Falling Animals | Breaky Wall | Exetor
  • hgy29hgy29 +1 -1 (+3 / -0 )
    Maintainer
    Again quick try:
    local DropShadowVShader=
    [[
    attribute vec4 POSITION0;
    attribute vec2 TEXCOORD0;
     
    uniform mat4 g_MVPMatrix;
     
    varying mediump vec2 texCoord;
     
    void main()
    {
    gl_Position = g_MVPMatrix * POSITION0;
    texCoord = TEXCOORD0;
    }
    ]]
     
    local DropShadowFShader=[[
    uniform lowp sampler2D gTex;
    uniform mediump vec4 maskInfo;
     
    varying mediump vec2 texCoord;
    uniform mediump vec4 fTexSize;
     
    #ifdef GLES2
    precision mediump float;
    #endif
     
    void main()
    {
    vec4 texc= texture2D(gTex, texCoord);
    mediump float shadow=0.0;
    mediump vec2 centerDir=normalize((fTexSize.xy/2.0-texCoord)/fTexSize.xy)*fTexSize.zw;
    for (int k=0;k<=15;k++)
    {
    vec4 p=texture2D(gTex, texCoord+centerDir*float(k));
    shadow=shadow+p.a;
    }
    shadow=pow(2.0,shadow/16.0)-1.0;
    if (shadow<=0.0) discard;
    vec4 frag=mix(vec4(0.3,0.3,0.3,shadow),texc,texc.a);
    gl_FragColor = frag;
    }
    ]]
     
    local DropShadowShaderAttrs=
    {
    {name="POSITION0",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
    {name="vColor",type=Shader.DUBYTE,mult=0,slot=1,offset=0},
    {name="TEXCOORD0",type=Shader.DFLOAT,mult=2,slot=2,offset=0}
    }
     
    local DropShadowShaderConstants={
    {name="g_MVPMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP, vertex=true},
    {name="fTexSize",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=false},
    {name="gTex",type=Shader.CTEXTURE,mult=1,vertex=false}
    }
     
     
    local DropShadowShader= Shader.new(
    DropShadowVShader,DropShadowFShader,
    Shader.FLAG_FROM_CODE,DropShadowShaderConstants,DropShadowShaderAttrs)
     
    local piece=Bitmap.new(Texture.new("shape.png",true))
    piece:setShader(DropShadowShader)
     
    application:setBackgroundColor(0xFFFFFF)
     
    stage:addChild(piece)
    piece:setPosition(50,50)

    Likes: pie, antix, Xman

  • keszegh +1 -1 (+1 / -0 )
    Member
    @hgy29, your nice shader examples should be collected somewhere visible, on the reference page or adding it always to a shader example project (added to the examples of gideros visible upon startup).

    Likes: pie

  • Xman +1 -1
    Member
    these shader for common effect may consider to included into the engine, and exported by Shader.SHADOW, Shader.BLUR, for easy to use as sprite:setShader(Shader.SHADOW)
  • hgy29hgy29 +1 -1 (+1 / -0 )
    Maintainer
    I had the idea to make them available as a plugin, since the new plugin system makes it easy to integrate into a final app. @Sinistersoft thinks I should write a book too :)

    But gideros needs a little more work to make them easy to use, in particular blur effect needs a rendertarget, and it would be good if gideros could automatically cache pre-rendered sprite hierarchy in a rendertarget for that purpose, when needed.
    But we need to be careful: what about nested effects/recursive render targets ?

    Gideros should also expose more internal state to the shaders: actual texture bounds, generalized support for texture regions, etc
  • Yan +1 -1
    Member
    hgy29 said:

    I had the idea to make them available as a plugin, since the new plugin system makes it easy to integrate into a final app. @Sinistersoft thinks I should write a book too :)

    But gideros needs a little more work to make them easy to use, in particular blur effect needs a rendertarget, and it would be good if gideros could automatically cache pre-rendered sprite hierarchy in a rendertarget for that purpose, when needed.
    But we need to be careful: what about nested effects/recursive render targets ?

    Gideros should also expose more internal state to the shaders: actual texture bounds, generalized support for texture regions, etc




    How can I provide a custom data to shader, to achieve those lighting effects (now I got only raycast version of lightning, want to remake this on shaders)

    https://www.shadertoy.com/view/XldGRS

    https://www.shadertoy.com/view/XldGRS

    https://www.shadertoy.com/view/4tcSzl

    and so on. I found a good topic about:

    http://giderosmobile.com/forum/discussion/6667/shadertoy-viewer-beta-shaders-from-www-shadertoy-com-in-gideros/p1

    But didnt tried this lib yet
  • hgy29hgy29 +1 -1
    Maintainer
    You can supply your own 'attribute' data by using Mesh sprite, and setting generic arrays:
    -- Set normal coordinates as attribute n°3
    mesh:setGenericArray(3,Shader.DFLOAT,3,#obj.normals/3,obj.normals)


    You'll need to declare your new attribute when creating the shader:
    {name="NORMAL0",type=Shader.DFLOAT,mult=3,slot=3,offset=0}

  • Yan +1 -1
    Member
    hgy29 said:

    You can supply your own 'attribute' data by using Mesh sprite, and setting generic arrays:

    -- Set normal coordinates as attribute n°3
    mesh:setGenericArray(3,Shader.DFLOAT,3,#obj.normals/3,obj.normals)


    You'll need to declare your new attribute when creating the shader:
    {name="NORMAL0",type=Shader.DFLOAT,mult=3,slot=3,offset=0}



    Does this two different approches ? Is the second is regular ? I just want to pass some light source data: radius, intense and position. Can I just use a custom normal attribute to pass this values, as you showed in 2nd example.

    Im not good in lowlevel programming, so I need the easiest approach, cause Meshs are hard for me now.
  • Yan +1 -1
    Member
    I noticed that in shadertoy player, that they ported to Gideros, they using setConstant func to provide extra data to shader subprogram, is this a right way ?
  • hgy29hgy29 +1 -1
    Maintainer
    Yes, if you need to pass some value that doesn't depend on actual geometry (constant or uniform), then you should use shader:setConstant() or sprite:setShaderConstant
  • Yan +1 -1
    Member
    hgy29 said:

    Yes, if you need to pass some value that doesn't depend on actual geometry (constant or uniform), then you should use shader:setConstant() or sprite:setShaderConstant



    Nice thank you, again ! =)

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Login with Facebook Sign In with Google Sign In with OpenID

In this Discussion

Top Posters