Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Add drop shadow to a Sprite — Gideros Forum

Add drop shadow to a Sprite

totebototebo Member
edited January 2017 in General questions
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

Comments

  • 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

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • 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
  • But this can not generate the feather edge for the shadow
  • antixantix Member
    edited January 2017
    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 :)
  • piepie 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! :)
  • @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 :)

  • hgy29hgy29 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

    +1 -1 (+3 / -0 )Share on Facebook
  • @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

    +1 -1 (+1 / -0 )Share on Facebook
  • 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 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
    +1 -1 (+1 / -0 )Share on Facebook
  • YanYan Member
    edited January 2017
    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
    vk.com/yan_alex
  • hgy29hgy29 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}
  • YanYan Member
    edited January 2017
    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.
    vk.com/yan_alex
  • YanYan Member
    edited January 2017
    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 ?
    vk.com/yan_alex
  • hgy29hgy29 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
  • YanYan Member
    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 ! =)
    vk.com/yan_alex
Sign In or Register to comment.