Lua Shader Examples

From GiderosMobile
Revision as of 08:01, 7 November 2023 by MoKaLux (talk | contribs)

Parent: Writing Lua Shaders


Requirements:
In order to use Lua Shaders you need to include luashader standard library in your projects
luashader standard library is available in your Gideros installation folder under Library

Shader Saturate - by Hgy29

function vssaturate(vVertex, vColor, vTexCoord) : Shader
	local vertex = hF4(vVertex, 0.0, 1.0)
	fTexCoord = vTexCoord
	return vMatrix * vertex
end
function fssaturate() : Shader
	local frad = (1 + sin(fTime*7)) * 0.5
	local frag = lF4(fColor) * texture2D(fTexture, fTexCoord)
	local coef = lF3(0.2125, 0.7154, 0.0721)
	local dp = dot(frag.rgb, coef)
	if fSwitch == 22 then -- switched via lua code
		frag.rgb = mix(frag.rgb, frag.rgb / dp, frad)
	end
	if (frag.a == 0.0) then discard() end
	return frag
end

local saturate = Shader.lua(vssaturate, fssaturate, 0,
	{
	{name="vMatrix", type=Shader.CMATRIX, sys=Shader.SYS_WVP, vertex=true},
	{name="fColor", type=Shader.CFLOAT4, sys=Shader.SYS_COLOR, vertex=false},
	{name="fTexture", type=Shader.CTEXTURE, vertex=false},
	{name="fTextureInfo", type=Shader.CFLOAT4, sys=Shader.SYS_TEXTUREINFO, vertex=false},
	{name="fTime", type=Shader.CFLOAT, sys=Shader.SYS_TIMER, vertex=false},
	{name="fSwitch", type=Shader.CINT, vertex=false}, -- Uniform value will be changed in lua code
	},
	{
	{name="vVertex", type=Shader.DFLOAT, mult=2, slot=0, offset=0},
	{name="vColor", type=Shader.DUBYTE, mult=4, slot=1, offset=0},
	{name="vTexCoord", type=Shader.DFLOAT, mult=2, slot=2, offset=0},
	},
	{
	{name="fTexCoord", type=Shader.CFLOAT2},
	}
)

-- bg color
application:setBackgroundColor(0x909090)
-- a texture and a bitmap
local tex = Texture.new("gfx/test.png")
local bmp = Bitmap.new(tex, true)
--local bmp2 = bmp:clone()
local bmp2 = Bitmap.new(tex, true)
-- position
bmp:setPosition(32*4, 32*4)
bmp2:setPosition(32*4, 32*8)
-- lua shader
bmp:setShader(saturate)
bmp2:setShader(saturate)
bmp:setShaderConstant("fSwitch", Shader.CINT, 1, 22) -- switch is on
bmp2:setShaderConstant("fSwitch", Shader.CINT, 1, -38) -- switch is off
-- order
stage:addChild(bmp)
stage:addChild(bmp2)

-- loop
stage:addEventListener(Event.ENTER_FRAME, function(e)
	bmp:setX(bmp:getX() + 0.5)
	if bmp:getX() > 400 then bmp:setX(-80) end
end)

Rain drops demo - by Hgy29

Rain drops shader effect

-- Custom shader for a plain colored pixel (BASIC PROGRAM)
local shader=StandardShaders:getShaderSpecification(Shader.SHADER_PROGRAM_BASIC)

-- We will need vertex position in fragment shader
function shader:vertexShader(vVertex,vColor,vTexCoord) : Shader
	local vertex = hF4(vVertex,0.0,1.0)
	fVertex=vVertex.xy
	return vMatrix*vertex
end

-- Fragment shader will compute caustics and ripples
function shader:fragmentShader() : Shader
	local tp = hF2(1.0/32.0,1.0/16.0)
	local mt = fVertex/1024.0
	local p = mod(mt*6.28, 6.28)-360.0
	local i = p
	local c = 1.0
	local inten = .005

	for n=1,3 do 
		local t = fTime*0.5 * (1.0 - (3.0 / hF1(n)))
		i = p + hF2(cos(t - i.x) + sin(t + i.y), sin(t - i.y) + cos(t + i.x))
		c += 1.0/length(hF2(p.x / (sin(i.x+t)/inten),p.y / (cos(i.y+t)/inten)))
	end
	for n=1,32 do
		local fr=fRippleT[n]
		if (fr>0.0) then
			local pd=length(fVertex-fRippleC[n])
			local rd=1.0-smoothstep(0.0,128.0,pd)
			if (rd>0.0) then
				local td=(fTime-fr)*10.0
				local dr=min(1.0,max(0.0,1.0-abs(td-(1.0-rd)*20.0)/10.0))
				c+=sin(rd*20.0+td)*rd*dr
			end
		end
	end
	c /= 3
	c = (1.5-c^.5)^4
	return lF4((hF4(c,c,c,1.0) + hF4(0.0, 0.3, 0.5, 1.0))*fColor)
end

-- Add our custom constants and inter-stage varibale
local NDROPS=32
table.insert(shader.uniforms,{name="fRippleC",type=Shader.CFLOAT2,vertex=false,mult=NDROPS})
table.insert(shader.uniforms,{name="fTime",type=Shader.CFLOAT,sys=Shader.SYS_TIMER,vertex=false})
table.insert(shader.uniforms,{name="fRippleT",type=Shader.CFLOAT,vertex=false,mult=NDROPS})
table.insert(shader.varying,{name="fVertex",type=Shader.CFLOAT2})

-- A plain blue screen wide Pixel with our shader
local ax,ay,aw,ah=application:getLogicalBounds()
local p=Pixel.new(0x5678CD,1,aw-ax,ah-ay) p:setPosition(ax,ay)
p:setShader(shader:build())
stage:addChild(p)

-- Main loop: create random rain drops
local drop=0
local dropsP,dropsT={},{}
for i=1,NDROPS do dropsP[i*2-1]=0 dropsP[i*2]=0 dropsT[i]=0 end
Core.asyncCall(function()
	while true do
		Core.yield(.05)
		drop+=1
		if drop==(NDROPS+1) then drop=1 end
		dropsP[drop*2-1]=math.random(aw-ax)
		dropsP[drop*2]=math.random(ah-ay)
		dropsT[drop]=os:timer()
		p:setShaderConstant("fRippleC",Shader.CFLOAT2,NDROPS,dropsP)
		p:setShaderConstant("fRippleT",Shader.CFLOAT,NDROPS,dropsT)
	end
end)