-- $Id: UnitPieceLight.lua 3171 2008-11-06 09:06:29Z det $ ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- local UnitPieceLight = {} UnitPieceLight.__index = UnitPieceLight local depthtex, offscreentex, blurtex local offscreen4, offscreen8 local blur4, blur8 local depthShader local blurShader local uniformScreenXY, uniformPixelSize, uniformDirection local GL_DEPTH_BITS = 0x0D56 local GL_DEPTH_COMPONENT = 0x1902 local GL_DEPTH_COMPONENT16 = 0x81A5 local GL_DEPTH_COMPONENT24 = 0x81A6 local GL_DEPTH_COMPONENT32 = 0x81A7 ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function UnitPieceLight.GetInfo() return { name = "UnitPieceLight", backup = "", --// backup class, if this class doesn't work (old cards,ati's,etc.) desc = "", layer = 32, --// extreme simply z-ordering :x --// gfx requirement fbo = true, shader = true, rtt = true, ctt = true, ms = 0, } end UnitPieceLight.Default = { layer = 32, life = math.huge, worldspace = true, piecenum = 0, colormap = { {1,1,1,0} }, repeatEffect = true, --// internal color = {1,1,1,0}, } ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function UnitPieceLight:BeginDraw() gl.CopyToTexture(depthtex, 0, 0, 0, 0, vsx, vsy) gl.Texture(depthtex) gl.UseShader(depthShader) gl.Uniform(uniformScreenXY, math.ceil(vsx*0.5),math.ceil(vsy*0.5) ) gl.RenderToTexture(offscreentex, gl.Clear, GL.COLOR_BUFFER_BIT ,0,0,0,0) end function UnitPieceLight:EndDraw() gl.Color(1,1,1,1) gl.UseShader(0) gl.RenderToTexture(offscreen4, function() gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0) gl.Texture(offscreentex) gl.TexRect(-1,1,1,-1) end) gl.Texture(offscreentex) gl.UseShader(blurShader) gl.RenderToTexture(blurtex, function() gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0) gl.Uniform(uniformDirection, 1,0 ) gl.Uniform(uniformPixelSize, 1.0/math.ceil(vsx*0.5) ) gl.TexRect(-1-0.25/vsx,1+0.25/vsy,1+0.25/vsx,-1-0.25/vsy) end) gl.Texture(blurtex) gl.RenderToTexture(offscreentex, function() gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0) gl.Uniform(uniformDirection, 0,1 ) gl.Uniform(uniformPixelSize, math.ceil(vsy*0.5) ) gl.TexRect(-1-0.25/vsx,1+0.25/vsy,1+0.25/vsx,-1-0.25/vsy) end) gl.Texture(offscreen4) gl.RenderToTexture(blur4, function() gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0) gl.Uniform(uniformDirection, 1,0 ) gl.Uniform(uniformPixelSize, 1.0/math.ceil(vsx*0.25) ) gl.TexRect(-1-0.125/vsx,1+0.125/vsy,1+0.125/vsx,-1-0.125/vsy) end) gl.Texture(blur4) gl.RenderToTexture(offscreen4, function() gl.Clear(GL.COLOR_BUFFER_BIT,0,0,0,0) gl.Uniform(uniformDirection, 0,1 ) gl.Uniform(uniformPixelSize, 1.0/math.ceil(vsy*0.25) ) gl.TexRect(-1-0.125/vsx,1+0.125/vsy,1+0.125/vsx,-1-0.125/vsy) end) gl.UseShader(0) gl.Blending(GL.ONE,GL.ONE) gl.MatrixMode(GL.PROJECTION); gl.PushMatrix(); gl.LoadIdentity() gl.MatrixMode(GL.MODELVIEW); gl.PushMatrix(); gl.LoadIdentity() gl.Texture(offscreentex) gl.TexRect(-1-0.5/vsx,1+0.5/vsy,1+0.5/vsx,-1-0.5/vsy) gl.Texture(offscreen4) gl.TexRect(-1-0.5/vsx,1+0.5/vsy,1+0.5/vsx,-1-0.5/vsy) gl.MatrixMode(GL.PROJECTION); gl.PopMatrix() gl.MatrixMode(GL.MODELVIEW); gl.PopMatrix() gl.Blending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) gl.Texture(false) gl.UseShader(0) end function UnitPieceLight:Draw() gl.Color(self.color) gl.RenderToTexture(offscreentex, function() gl.PushMatrix() gl.ResetMatrices() gl.UnitMultMatrix(self.unit) gl.UnitPieceMultMatrix(self.unit,self.piecenum) gl.UnitPiece(self.unit,self.piecenum) gl.PopMatrix() end) end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function UnitPieceLight:Update() self.life = self.life + self.life_incr self.color = {GetColor(self.colormap,self.life)} end -- used if repeatEffect=true; function UnitPieceLight:ReInitialize() self.life = 0 self.dieGameFrame = self.dieGameFrame + self.clife end function UnitPieceLight.Initialize() depthShader = gl.CreateShader({ fragment = [[ uniform sampler2D tex0; uniform vec2 screenXY; void main(void) { vec2 texCoord = vec2( gl_FragCoord.x/screenXY.x , gl_FragCoord.y/screenXY.y ); float depth = texture2D(tex0, texCoord ).z; if (depth <= gl_FragCoord.z-0.0005) { discard; } gl_FragColor = gl_Color; } ]], uniformInt = { tex0 = 0, }, uniform = { screenXY = {math.ceil(vsx*0.5),math.ceil(vsy*0.5)}, }, }) if (depthShader == nil) then print(PRIO_MAJOR,"LUPS->UnitPieceLights: Critical Shader Error: DepthShader: "..gl.GetShaderLog()) return false end blurShader = gl.CreateShader({ fragment = [[ float kernel[7]; uniform sampler2D tex0; uniform float pixelsize; uniform vec2 dir; void InitKernel(void) { kernel[0] = 0.013; kernel[1] = 0.054; kernel[2] = 0.069; kernel[3] = 0.129; kernel[4] = 0.212; kernel[5] = 0.301; kernel[6] = 0.372; } void main(void) { InitKernel(); vec2 texCoord = vec2(gl_TextureMatrix[0] * gl_TexCoord[0]); gl_FragColor = vec4(0.0); int n,i; i=1; for(n=6; n >= 0; --n){ gl_FragColor += kernel[n] * texture2D(tex0, texCoord.st + dir * float(i)*pixelsize ); ++i; } gl_FragColor += 0.4 * texture2D(tex0, texCoord ); i = -7; for(n=0; n <= 6; ++n){ gl_FragColor += kernel[n] * texture2D(tex0, texCoord.st + dir * float(i)*pixelsize ); ++i; } } ]], uniformInt = { tex0 = 0, pixelsize = 1.0/math.ceil(vsx*0.5), }, }) if (blurShader == nil) then print(PRIO_MAJOR,"LUPS->UnitPieceLights: Critical Shader Error: BlurShader: "..gl.GetShaderLog()) return false end uniformScreenXY = gl.GetUniformLocation(depthShader, 'screenXY') uniformPixelSize = gl.GetUniformLocation(blurShader, 'pixelsize') uniformDirection = gl.GetUniformLocation(blurShader, 'dir') UnitPieceLight.ViewResize(vsx, vsy) end function UnitPieceLight.Finalize() gl.DeleteTexture(depthtex) if (gl.DeleteTextureFBO) then gl.DeleteTextureFBO(offscreentex) gl.DeleteTextureFBO(blurtex) end if (gl.DeleteShader) then gl.DeleteShader(depthShader or 0) gl.DeleteShader(blurShader or 0) end end function UnitPieceLight.ViewResize(vsx, vsy) gl.DeleteTexture(depthtex or 0) gl.DeleteTextureFBO(offscreentex or 0) gl.DeleteTextureFBO(blurtex or 0) gl.DeleteTextureFBO(offscreen4 or 0) gl.DeleteTextureFBO(blur4 or 0) depthtex = gl.CreateTexture(vsx,vsy, { border = false, format = GL_DEPTH_COMPONENT24, min_filter = GL.NEAREST, mag_filter = GL.NEAREST, }) offscreentex = gl.CreateTexture(math.ceil(vsx*0.5),math.ceil(vsy*0.5), { border = false, min_filter = GL.LINEAR, mag_filter = GL.LINEAR, wrap_s = GL.CLAMP_TO_BORDER, wrap_t = GL.CLAMP_TO_BORDER, fbo = true, }) offscreen4 = gl.CreateTexture(math.ceil(vsx*0.25),math.ceil(vsy*0.25), { border = false, min_filter = GL.LINEAR, mag_filter = GL.LINEAR, wrap_s = GL.CLAMP_TO_BORDER, wrap_t = GL.CLAMP_TO_BORDER, fbo = true, }) blurtex = gl.CreateTexture(math.ceil(vsx*0.5),math.ceil(vsy*0.5), { border = false, min_filter = GL.LINEAR, mag_filter = GL.LINEAR, wrap_s = GL.CLAMP_TO_BORDER, wrap_t = GL.CLAMP_TO_BORDER, fbo = true, }) blur4 = gl.CreateTexture(math.ceil(vsx*0.25),math.ceil(vsy*0.25), { border = false, min_filter = GL.LINEAR, mag_filter = GL.LINEAR, wrap_s = GL.CLAMP_TO_BORDER, wrap_t = GL.CLAMP_TO_BORDER, fbo = true, }) end function UnitPieceLight:Visible() local ux,uy,uz = Spring.GetUnitViewPosition(self.unit) if not ux then return false end local pos = {0,0,0} pos[1],pos[2],pos[3] = pos[1]+ux,pos[2]+uy,pos[3]+uz local radius = 300 + Spring.GetUnitRadius(self.unit) local losState = Spring.GetUnitLosState(self.unit, LocalAllyTeamID) return (losState and losState.los)and(Spring.IsSphereInView(pos[1],pos[2],pos[3],radius)) end function UnitPieceLight:Valid() local ux = Spring.GetUnitViewPosition(self.unit) if (ux) then return true else return false end end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function UnitPieceLight:CreateParticle() self.clife = self.life self.life_incr = 1/self.life self.life = 0 self.dieGameFrame = Spring.GetGameFrame() + self.clife end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function UnitPieceLight.Create(Options) local newObject = MergeTable(Options, UnitPieceLight.Default) setmetatable(newObject,UnitPieceLight) -- make handle lookup newObject:CreateParticle() return newObject end function UnitPieceLight:Destroy() end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- return UnitPieceLight