Ok, folks. In SVN 6991, it is now possible to use this shader properly, with a minor change (I found that I have to multiply the normals by the normal matrix before the results are right).
Here is the resulting source. Tested, seems to be working well, and I've corrected the efficiency problems, I think:
Code: Select all
function gadget:GetInfo()
return {
name = "GLSL Lighting",
desc = "The P.U.R.E. GLSL Realtime lighting implementation.",
author = "Argh",
date = "November 7, 2008",
license = "Public Domain, or the least-restrictive rights in your country of residence",
layer = 0,
enabled = true -- loaded by default?
}
end
if (gadgetHandler:IsSyncedCode()) then
----------------------------------------------------------------------------------------------------------SYNCED
local function CreateLightMe(u, ud, team, p, r, g, b, a)
p = Spring.GetUnitScriptPiece(u,p)
r = r / 255
g = g / 255
b = b / 255
a = a / 255
SendToUnsynced("CreateLight",u, ud, team, p, r, g, b, a)
end
local function DestroyLightMe(u, ud, team)
SendToUnsynced("DestroyLight",u, ud, team)
end
function gadget:Initialize()
gadgetHandler:RegisterGlobal("CreateLightMe", CreateLightMe)
gadgetHandler:RegisterGlobal("DestroyLightMe", DestroyLightMe)
end
function gadget:UnitDestroyed(u,ud,team)
SendToUnsynced("DestroyLight",u, ud, team)
end
----------------------------------------------------------------------------------------------------------END SYNCED
else
----------------------------------------------------------------------------------------------------------UNSYNCED
local UseShader = 0
local LP
function gadget:Initialize()
GLSL_LIGHT_Shader = gl.CreateShader({
vertex = [[
varying vec4 diffuse;
void main()
{
gl_Position = ftransform();
vec3 normal = gl_NormalMatrix * gl_Normal;
vec3 lightVector = gl_LightSource[1].position.xyz - (gl_ModelViewMatrix * gl_Vertex);
float dist = length(lightVector);
float attenuation = 1.0 / (gl_LightSource[1].constantAttenuation +
gl_LightSource[1].linearAttenuation * dist +
gl_LightSource[1].quadraticAttenuation * dist * dist);
lightVector = normalize(lightVector);
float nxDir = max(0.0, dot(normal, lightVector));
diffuse = gl_FrontMaterial.diffuse * nxDir * attenuation;
}
]],
fragment = [[
varying vec4 diffuse;
void main()
{
gl_FragColor = (gl_LightSource[1].ambient + diffuse);
}
]],
})
if (GLSL_LIGHT_Shader == nil) then
Spring.Echo("GLSL Light Shader Failed"..gl.GetShaderLog())
return false
else
Spring.Echo("GLSL Light Shader Succeeded")
UseShader = 1;
end
end
local tinsert = table.insert
local tremove = table.remove
local LightList = {piece, red, green, blue, alpha}
local GetUnitPiecePosDir = Spring.GetUnitPiecePosDir
function gadget:RecvFromSynced(name, u, ud, team, p, r, g, b, a)
if name == "CreateLight" then
if LightList[u] ~= nil then
LightList[u] = nil
Spring.Echo("table removed")
end
tinsert(LightList,u,{piece = p, red = r, green = g, blue = b, alpha = a})
end
if name == "DestroyLight" then
if LightList[u] ~= nil then
LightList[u] = nil
Spring.Echo("table removed by Destroy")
end
end
end
function gadget:DrawWorld()
if UseShader == 1 then
local myIDList = Spring.GetVisibleUnits(-1,3000,false)
if myIDList[1] ~= nil then
for _,myID in ipairs(myIDList) do
if (Spring.IsUnitVisible(myID)) then
if LightList[myID] ~= nil then
gl.DepthTest(GL.LEQUAL)
gl.Culling(GL.BACK)
gl.Blending(true)
gl.Lighting(true)
local x,y,z = Spring.GetUnitPiecePosDir(myID,LightList[myID].piece)
gl.Light(1,GL.POSITION,x,y,z,1)
gl.Material ({
ambient = {0, 0, 0, 0},
diffuse = {LightList[myID].red,LightList[myID].green,LightList[myID].blue,LightList[myID].alpha},
ambidiff = {0, 0, 0, 0},
emission = {0, 0, 0, 0},
specular = {0, 0, 0, 0},
shininess = 10
})
gl.UseShader(GLSL_LIGHT_Shader)
gl.PolygonOffset(-3,-3)
gl.Unit(myID,true)
gl.Light(0,false)
gl.PolygonOffset(0,0)
gl.ResetState()
gl.Lighting(false)
end
end
end
end
end
end
----------------------------------------------------------------------------------------------------------END
end
To test and implement on the BOS side, just add lua_CreateLightMe and lua_DestroyLightMe, and then feed it arguments like this:
Code: Select all
call-script lua_CreateLightMe(flare, 255, 255, 128, 160);
sleep 200;
call-script lua_DestroyLightMe();
Will create a point-light source with RGBA values (255,255,128,160) then destroy that point-light source after 200ms. Have fun, it's finally working in all respects