Quick Links: Gideros Home | Download Gideros | Developer Guide
Add drop shadow to a Sprite
  • totebototebo +1 -1 (+0 / -1 )
    Member
    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

    Dislikes: IvanUxe

    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 OpenID

In this Discussion

Top Posters