Difference between revisions of "Sprite:setStencilOperation"

From GiderosMobile
 
(12 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
__NOTOC__
 
__NOTOC__
 
'''Available since:''' Gideros 2017.6<br/>
 
'''Available since:''' Gideros 2017.6<br/>
 +
'''Class:''' [[Sprite]]<br/>
 +
 
=== Description ===
 
=== Description ===
Allows to set a stencil operation to be used when drawing this sprite.<br />
+
Allows to set a stencil operation to be used when drawing this sprite.
    The table can contain the following fields:<br />
+
<syntaxhighlight lang="lua">
    <ul>
+
Sprite:setStencilOperation(op)
    <li><b>stencilClear</b>: (boolean) whether the stencil should be cleared beforehand.</li>
+
</syntaxhighlight>
    <li><b>stencilMask</b>: (integer) the mask value used in stencil operations.</li>
+
 
    <li><b>stencilWriteMask</b>: (integer) the mask value used when writing to stencil.</li>
+
 
    <li><b>stencilRef</b>: (integer) the reference value used in stencil operations.</li>
+
The '''op''' table can contain the following fields:
    <li><b>stencilFunc</b>: (integer) the stencil function to use.</li>
+
*'''stencilClear''': (boolean) whether the stencil should be cleared beforehand
    <li><b>stencilFail</b>: (integer) the stencil operation when stencil test failed.</li>
+
*'''stencilMask''': (integer) the mask value used in stencil operations
    <li><b>depthFail</b>: (integer) the stencil operation when depth test failed.</li>
+
*'''stencilWriteMask''': (integer) the mask value used when writing to stencil
    <li><b>depthPass</b>: (integer) the stencil operation when depth test has passed.</li>
+
*'''stencilClearValue''': (integer) the value used to fill then stencil when clearing
    </ul><br />
+
*'''stencilRef''': (integer) the reference value used in stencil operations
    Stencil function and operations code are defined in Sprite.STENCIL_xxx fields and correspond to the GL_xxx relevant values in OpenGL stencil documentation.
+
*'''stencilFunc''': (integer) the stencil function to use
<source lang="lua">
+
*'''stencilFail''': (integer) the stencil operation when stencil test failed
  Sprite:setStencilOperation(op)
+
*'''depthFail''': (integer) the stencil operation when depth test failed
</source>
+
*'''depthPass''': (integer) the stencil operation when depth test has passed
'''op''': (table) A table containing the stencil operation settings, or nil to disable stencil ''''''<br/>
+
*'''depthMask''': (boolean) whether depth buffer should be written or not (true by default)
 +
 
 +
Stencil function and operations code are defined in Sprite.STENCIL_xxx fields and correspond to the GL_xxx relevant values in OpenGL stencil documentation https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFunc.xhtml.
 +
 
 +
=== Parameters ===
 +
'''op''': (table) a table containing the stencil operation settings, or nil to disable stencil
 +
 
 +
=== Examples ===
 +
'''A glowing ticket effect''':
 +
<syntaxhighlight lang="lua">
 +
-- STENCILOPERATION @hgy29
 +
local bg = Bitmap.new(Texture.new("gfx/vip/background.png"))
 +
local ticket = Bitmap.new(Texture.new("gfx/vip/ticket.png"))
 +
local text = Bitmap.new(Texture.new("gfx/vip/text.png"))
 +
local fx1 = Bitmap.new(Texture.new("gfx/vip/fx1.png"))
 +
local fx2 = Bitmap.new(Texture.new("gfx/vip/fx2.png"))
 +
   
 +
stage:addChild(bg) bg:setScale(0.5)
 +
stage:addChild(ticket) ticket:setPosition(80,20) ticket:setScale(0.5)
 +
ticket:addChild(fx1) fx1:setX(-100)
 +
fx1:addChild(fx2) fx2:setX(-100)
 +
ticket:addChild(text)
 +
 +
-- Use auto layout on ticket to center text automatically
 +
ticket:setLayoutParameters{ rowWeights = {1}, columnWeights = {1} }
 +
text:setLayoutConstraints{}
 +
 
 +
-- Use stencil for masking glow:
 +
-- 1) Clear stencil and set it to '1' for every pixel drawn on 'ticket'
 +
ticket:setStencilOperation{
 +
stencilClear = true, stenciMask = 1, stencilWriteMask = 1, stencilRef = 1,
 +
stencilFunc = Sprite.STENCIL_ALWAYS, depthPass = Sprite.STENCIL_REPLACE
 +
}
 +
--2) Only draw fx1/fx2 if stencil isn't 0
 +
fx1:setStencilOperation{
 +
stencilClear = false, stencilMask = 1, stencilRef = 0,
 +
stencilFunc = Sprite.STENCIL_NOTEQUAL
 +
}
 +
 +
local dir = 1
 +
stage:addEventListener(Event.ENTER_FRAME, function()
 +
if fx1:getX() > 450 then dir = -1
 +
elseif fx1:getX() < -100 then dir = 1
 +
end
 +
fx1:setX(fx1:getX() + dir*5)
 +
end)
 +
</syntaxhighlight>
 +
 
 +
'''Fill sprite with color''':
 +
<syntaxhighlight lang="lua">
 +
local star=Bitmap.new(Texture.new("gfx/clock_hand_m.png",true))
 +
stage:addChild(star)
 +
 +
local bluestar_tex=RenderTarget.new(star:getWidth(),star:getHeight())
 +
local bluestar=Bitmap.new(bluestar_tex)
 +
stage:addChild(bluestar) bluestar:setX(160)
 +
 +
--Here is the magic
 +
-- Clear our render target to all alpha
 +
bluestar_tex:clear(0x000000,0)
 +
--[[Gideros don't draw pixels with alpha value of 0,
 +
they are discarded at early stage. Use the stencil to get a
 +
footprint of visible pixels of source image]]
 +
star:setStencilOperation{ stencilClear=true, stencilWriteMask=1,
 +
stencilFunc=Sprite.STENCIL_ALWAYS,depthPass=Sprite.STENCIL_INCR }
 +
bluestar_tex:draw(star)
 +
--Render the footprint in the color we want
 +
local mask=Pixel.new(0x0000FF,1,star:getWidth(),star:getHeight())
 +
mask:setStencilOperation{ stencilClear=false, stencilMask=1, stencilWriteMask=1,
 +
stencilRef=0, stencilFunc=Sprite.STENCIL_NOTEQUAL,
 +
depthPass=Sprite.STENCIL_KEEP,
 +
stencilFail=Sprite.STENCIL_KEEP}
 +
bluestar_tex:draw(mask)
 +
 +
--[[ The result is possibly enough here, but we lost the smoothed edges of
 +
the original texture in the process. We can restore them with a smart alpha
 +
blending trick:]]
 +
star:setBlendMode(Sprite.ZERO,Sprite.SRC_ALPHA)
 +
bluestar_tex:draw(star)
 +
 +
--Restore our initial bitmap blending mode, to show it on screen as usual
 +
star:setBlendMode(Sprite.ALPHA)
 +
</syntaxhighlight>
 +
 
 +
{{Sprite}}

Latest revision as of 09:53, 7 November 2023

Available since: Gideros 2017.6
Class: Sprite

Description

Allows to set a stencil operation to be used when drawing this sprite.

Sprite:setStencilOperation(op)


The op table can contain the following fields:

  • stencilClear: (boolean) whether the stencil should be cleared beforehand
  • stencilMask: (integer) the mask value used in stencil operations
  • stencilWriteMask: (integer) the mask value used when writing to stencil
  • stencilClearValue: (integer) the value used to fill then stencil when clearing
  • stencilRef: (integer) the reference value used in stencil operations
  • stencilFunc: (integer) the stencil function to use
  • stencilFail: (integer) the stencil operation when stencil test failed
  • depthFail: (integer) the stencil operation when depth test failed
  • depthPass: (integer) the stencil operation when depth test has passed
  • depthMask: (boolean) whether depth buffer should be written or not (true by default)

Stencil function and operations code are defined in Sprite.STENCIL_xxx fields and correspond to the GL_xxx relevant values in OpenGL stencil documentation https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFunc.xhtml.

Parameters

op: (table) a table containing the stencil operation settings, or nil to disable stencil

Examples

A glowing ticket effect:

-- STENCILOPERATION @hgy29
local bg = Bitmap.new(Texture.new("gfx/vip/background.png"))
local ticket = Bitmap.new(Texture.new("gfx/vip/ticket.png"))
local text = Bitmap.new(Texture.new("gfx/vip/text.png"))
local fx1 = Bitmap.new(Texture.new("gfx/vip/fx1.png"))
local fx2 = Bitmap.new(Texture.new("gfx/vip/fx2.png"))
 
stage:addChild(bg) bg:setScale(0.5)
stage:addChild(ticket) ticket:setPosition(80,20) ticket:setScale(0.5)
ticket:addChild(fx1) fx1:setX(-100)
fx1:addChild(fx2) fx2:setX(-100)
ticket:addChild(text)
 
-- Use auto layout on ticket to center text automatically
ticket:setLayoutParameters{ rowWeights = {1}, columnWeights = {1} }
text:setLayoutConstraints{}

-- Use stencil for masking glow:
-- 1) Clear stencil and set it to '1' for every pixel drawn on 'ticket'
ticket:setStencilOperation{
	stencilClear = true, stenciMask = 1, stencilWriteMask = 1, stencilRef = 1,
	stencilFunc = Sprite.STENCIL_ALWAYS, depthPass = Sprite.STENCIL_REPLACE
}
--2) Only draw fx1/fx2 if stencil isn't 0
fx1:setStencilOperation{
	stencilClear = false, stencilMask = 1, stencilRef = 0,
	stencilFunc = Sprite.STENCIL_NOTEQUAL
}
 
local dir = 1
stage:addEventListener(Event.ENTER_FRAME, function()
	if fx1:getX() > 450 then dir = -1
	elseif fx1:getX() < -100 then dir = 1
	end
	fx1:setX(fx1:getX() + dir*5)
end)

Fill sprite with color:

local star=Bitmap.new(Texture.new("gfx/clock_hand_m.png",true))
stage:addChild(star)
 
local bluestar_tex=RenderTarget.new(star:getWidth(),star:getHeight())
local bluestar=Bitmap.new(bluestar_tex)
stage:addChild(bluestar) bluestar:setX(160)
 
--Here is the magic
-- Clear our render target to all alpha
bluestar_tex:clear(0x000000,0)
--[[Gideros don't draw pixels with alpha value of 0, 
they are discarded at early stage. Use the stencil to get a
footprint of visible pixels of source image]]
star:setStencilOperation{ stencilClear=true, stencilWriteMask=1,
	stencilFunc=Sprite.STENCIL_ALWAYS,depthPass=Sprite.STENCIL_INCR }
bluestar_tex:draw(star)
--Render the footprint in the color we want
local mask=Pixel.new(0x0000FF,1,star:getWidth(),star:getHeight())
mask:setStencilOperation{ stencilClear=false, stencilMask=1, stencilWriteMask=1, 
	stencilRef=0, stencilFunc=Sprite.STENCIL_NOTEQUAL,
	depthPass=Sprite.STENCIL_KEEP,
	stencilFail=Sprite.STENCIL_KEEP}
bluestar_tex:draw(mask)
 
--[[ The result is possibly enough here, but we lost the smoothed edges of
the original texture in the process. We can restore them with a smart alpha
blending trick:]]
star:setBlendMode(Sprite.ZERO,Sprite.SRC_ALPHA)
bluestar_tex:draw(star)
 
--Restore our initial bitmap blending mode, to show it on screen as usual
star:setBlendMode(Sprite.ALPHA)