Created
September 18, 2020 07:07
-
-
Save Beherith/c2bfe6044d2ae5a50d21eeced3afae15 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
function widget:GetInfo() | |
return { | |
name = "Deferred rendering", | |
version = 3, | |
desc = "Collects and renders point and beam lights", | |
author = "beherith, aeonios", | |
date = "2015 Sept.", | |
license = "GPL V2", | |
layer = -99999990, | |
enabled = true | |
} | |
end | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
local glBeginEnd = gl.BeginEnd | |
local glBillboard = gl.Billboard | |
local glBlending = gl.Blending | |
local glCallList = gl.CallList | |
local glDeleteList = gl.DeleteList | |
local glClear = gl.Clear | |
local glColor = gl.Color | |
local glCreateList = gl.CreateList | |
local glCreateShader = gl.CreateShader | |
local glCreateTexture = gl.CreateTexture | |
local glDeleteShader = gl.DeleteShader | |
local glDeleteTexture = gl.DeleteTexture | |
local glDepthMask = gl.DepthMask | |
local glDepthTest = gl.DepthTest | |
local glGetShaderLog = gl.GetShaderLog | |
local glGetUniformLocation = gl.GetUniformLocation | |
local glGetViewSizes = gl.GetViewSizes | |
local glPopMatrix = gl.PopMatrix | |
local glPushMatrix = gl.PushMatrix | |
local glTexCoord = gl.TexCoord | |
local glTexture = gl.Texture | |
local glTexRect = gl.TexRect | |
local glRect = gl.Rect | |
local glRenderToTexture = gl.RenderToTexture | |
local glUniform = gl.Uniform | |
local glUniformInt = gl.UniformInt | |
local glUniformMatrix = gl.UniformMatrix | |
local glUseShader = gl.UseShader | |
local glVertex = gl.Vertex | |
local glTranslate = gl.Translate | |
local spEcho = Spring.Echo | |
local spGetCameraPosition = Spring.GetCameraPosition | |
local spWorldToScreenCoords = Spring.WorldToScreenCoords | |
local spGetGroundHeight = Spring.GetGroundHeight | |
local math_sqrt = math.sqrt | |
local math_min = math.min | |
local math_max = math.max | |
local glowImg = "LuaUI/Images/glow2.dds" | |
local beamGlowImg = ":n:LuaUI/Images/barglow-center.png" | |
local beamGlowEndImg = ":n:LuaUI/Images/barglow-edge.png" | |
local GLSLRenderer = true | |
local vsx, vsy | |
local ivsx = 1.0 | |
local ivsy = 1.0 | |
local screenratio = 1.0 | |
-- dynamic light shaders | |
local depthPointShader = nil | |
local depthBeamShader = nil | |
-- shader uniforms | |
local lightposlocPoint = nil | |
local lightcolorlocPoint = nil | |
local lightparamslocPoint = nil | |
local uniformEyePosPoint | |
local uniformViewPrjInvPoint | |
local lightposlocBeam = nil | |
local lightpos2locBeam = nil | |
local lightcolorlocBeam = nil | |
local lightparamslocBeam = nil | |
local uniformEyePosBeam | |
local uniformViewPrjInvBeam | |
local LightDL = nil | |
-------------------------------------------------------------------------------- | |
--Light falloff functions: http://gamedev.stackexchange.com/questions/56897/glsl-light-attenuation-color-and-intensity-formula | |
-------------------------------------------------------------------------------- | |
local verbose = false | |
local function VerboseEcho(...) | |
if verbose then | |
Spring.Echo(...) | |
end | |
end | |
local collectionFunctions = {} | |
local collectionFunctionCount = 0 | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
function widget:RecvLuaMsg(msg, playerID) | |
if msg:sub(1,18) == 'LobbyOverlayActive' then | |
chobbyInterface = (msg:sub(1,19) == 'LobbyOverlayActive1') | |
end | |
end | |
function widget:ViewResize() | |
vsx, vsy = gl.GetViewSizes() | |
ivsx = 1.0 / vsx --we can do /n here! | |
ivsy = 1.0 / vsy | |
if (Spring.GetMiniMapDualScreen() == 'left') then | |
vsx = vsx / 2 | |
end | |
if (Spring.GetMiniMapDualScreen() == 'right') then | |
vsx = vsx / 2 | |
end | |
screenratio = vsy / vsx --so we dont overdraw and only always draw a square | |
end | |
widget:ViewResize() | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
---------[[[NEW]]]----------------- | |
local luaShaderDir = "LuaUI/Widgets_BAR/Include/" | |
local vsSrc = [[ | |
#version 150 compatibility | |
uniform mat4 viewMat; | |
uniform mat4 projMat; | |
out DataVS { | |
vec4 colAtt; | |
vec4 attrib0; | |
vec4 attrib1; | |
}; | |
void main() { | |
gl_Position = gl_Vertex; | |
colAtt = gl_Color; | |
attrib0 = gl_Position; | |
attrib1 = gl_MultiTexCoord0; | |
} | |
]] | |
local gsSrc = [[ | |
#version 150 compatibility | |
uniform mat4 viewMat; | |
uniform mat4 projMat; | |
//uniform int lightType; | |
layout (points) in; | |
layout (triangle_strip, max_vertices = 24) out; | |
#line 41 | |
in DataVS { | |
vec4 colAtt; | |
vec4 attrib0; | |
vec4 attrib1; | |
} dataIn[]; | |
out DataGS { | |
vec4 colAtt; | |
vec4 attrib0; //gl_Vertex | |
vec4 attrib1; //gl_MultiTexCoord0 | |
}; | |
// Z-; Z+ are bottom top planes of frustum | |
void GenericFrustum(mat4 worldMat, vec4 zMinModelCenterPos, vec4 zMaxModelCenterPos, float zMinRadius, float zMaxRadius) { | |
mat4 MVP = projMat * viewMat * worldMat; | |
vec4 frustumPoints[8] = vec4[]( | |
//zMin (-- -+ +- ++) | |
MVP * (zMinModelCenterPos + vec4(-zMinRadius, -zMinRadius, 0.0, 0.0)), | |
MVP * (zMinModelCenterPos + vec4(-zMinRadius, zMinRadius, 0.0, 0.0)), | |
MVP * (zMinModelCenterPos + vec4( zMinRadius, -zMinRadius, 0.0, 0.0)), | |
MVP * (zMinModelCenterPos + vec4( zMinRadius, zMinRadius, 0.0, 0.0)), | |
//zMax (-- -+ +- ++) | |
MVP * (zMaxModelCenterPos + vec4(-zMaxRadius, -zMaxRadius, 0.0, 0.0)), | |
MVP * (zMaxModelCenterPos + vec4(-zMaxRadius, zMaxRadius, 0.0, 0.0)), | |
MVP * (zMaxModelCenterPos + vec4( zMaxRadius, -zMaxRadius, 0.0, 0.0)), | |
MVP * (zMaxModelCenterPos + vec4( zMaxRadius, zMaxRadius, 0.0, 0.0)) | |
); | |
#define MyEmitVertex(idx) \ | |
{ \ | |
gl_Position = frustumPoints[idx]; \ | |
colAtt = dataIn[0].colAtt; \ | |
attrib0 = dataIn[0].attrib0; \ | |
attrib1 = dataIn[0].attrib1; \ | |
EmitVertex(); \ | |
} | |
// Z- | |
MyEmitVertex(3); | |
MyEmitVertex(1); | |
MyEmitVertex(2); | |
MyEmitVertex(0); | |
EndPrimitive(); | |
// Z+ | |
MyEmitVertex(4); | |
MyEmitVertex(5); | |
MyEmitVertex(6); | |
MyEmitVertex(7); | |
EndPrimitive(); | |
// X- | |
MyEmitVertex(0); | |
MyEmitVertex(1); | |
MyEmitVertex(4); | |
MyEmitVertex(5); | |
EndPrimitive(); | |
// X+ | |
MyEmitVertex(3); | |
MyEmitVertex(2); | |
MyEmitVertex(7); | |
MyEmitVertex(6); | |
EndPrimitive(); | |
// Y- | |
MyEmitVertex(0); | |
MyEmitVertex(4); | |
MyEmitVertex(2); | |
MyEmitVertex(6); | |
EndPrimitive(); | |
// Y+ | |
MyEmitVertex(7); | |
MyEmitVertex(5); | |
MyEmitVertex(3); | |
MyEmitVertex(1); | |
EndPrimitive(); | |
} | |
void GetSphereBoundingShape(mat4 worldMat, vec4 modelCenterPos, float r) { | |
vec4 zMinModelCenterPos = modelCenterPos; zMinModelCenterPos.z -= r; | |
vec4 zMaxModelCenterPos = modelCenterPos; zMaxModelCenterPos.z += r; | |
GenericFrustum(worldMat, zMinModelCenterPos, zMaxModelCenterPos, r, r); | |
} | |
void GetBeamBoundingShape(mat4 worldMat, vec4 modelBeamStartPos, vec4 modelBeamEndPos, float r0, float r1) { | |
GenericFrustum(worldMat, modelBeamStartPos, modelBeamEndPos, r0, r1); | |
} | |
void GetConeBoundingShape(mat4 worldMat, vec4 modelBeamStartPos, float r, float phi) { | |
vec4 modelBeamEndPos = modelBeamStartPos; modelBeamEndPos.z += r; | |
float rFar = r * tan(0.5 * phi); | |
GenericFrustum(worldMat, modelBeamStartPos, modelBeamEndPos, 0.0, rFar); | |
} | |
mat4 GetDirectionMatrix(vec3 dirNorm) { | |
const vec3 up = vec3(0, 1, 0); | |
vec3 zaxis = dirNorm; | |
vec3 xaxis = normalize(cross(zaxis, up)); | |
xaxis = isnan(xaxis.x) ? vec3(1, 0, 0) : xaxis; | |
vec3 yaxis = cross(xaxis, zaxis); | |
return mat4( | |
vec4(xaxis.x, yaxis.x, zaxis.x, 0.0), | |
vec4(xaxis.y, yaxis.y, zaxis.y, 0.0), | |
vec4(xaxis.z, yaxis.z, zaxis.z, 0.0), | |
vec4(0.0, 0.0, 0.0, 1.0) | |
); | |
} | |
mat4 GetTranslationMatrix(vec3 xyz) { | |
mat4 trlMat = mat4(1.0); | |
trlMat[3] = vec4(xyz, 1.0); | |
return trlMat; | |
} | |
void main() { | |
vec3 pos0 = gl_in[0].gl_Position.xyz; | |
float r0 = gl_in[0].gl_Position.w; | |
vec3 pos1 = dataIn[0].attrib0.xyz; | |
float r1 = dataIn[0].attrib0.w; | |
const vec4 startModelPos = vec4(0.0, 0.0, 0.0, 1.0); | |
//if (dataIn[0].attrib1.a == 0) { // omni-dir light | |
if (1.0>0.0) { // omni-dir light | |
mat4 rotMat = GetDirectionMatrix(vec3(0, 1, 0)); | |
mat4 trlMat = GetTranslationMatrix(pos0); | |
mat4 worldMat = trlMat * rotMat; | |
GetSphereBoundingShape(worldMat, startModelPos, r0); | |
} | |
else if (dataIn[0].attrib1.a < 0) { // beam light | |
vec4 dirLen = vec4(pos1 - pos0, 0.0); | |
dirLen.w = length(dirLen.xyz); | |
dirLen.xyz /= dirLen.w; | |
vec4 endModelPos = vec4(0.0, 0.0, dirLen.w, 1.0); | |
mat4 rotMat = GetDirectionMatrix(dirLen.xyz); | |
mat4 trlMat = GetTranslationMatrix(pos0); | |
mat4 worldMat = trlMat * rotMat; | |
GetBeamBoundingShape(worldMat, startModelPos, endModelPos, r0, r1); | |
} | |
else if (dataIn[0].attrib1.a > 0) { // //cone light | |
mat4 rotMat = GetDirectionMatrix(normalize(pos1)); | |
mat4 trlMat = GetTranslationMatrix(pos0); | |
mat4 worldMat = trlMat * rotMat; | |
GetConeBoundingShape(worldMat, startModelPos, r0, r1); | |
} | |
} | |
]] | |
local fsSrc = [[ | |
#version 150 compatibility | |
//uniform int lightType; | |
uniform vec2 viewPortSize; | |
uniform sampler2D modelnormals; | |
uniform sampler2D modeldepths; | |
uniform sampler2D mapnormals; | |
uniform sampler2D mapdepths; | |
uniform sampler2D modelExtra; | |
uniform mat4 viewProjectionInv; | |
uniform vec3 eyePos; | |
in DataGS { | |
vec4 colAtt; //color.rgb, falloff | |
vec4 attrib0; //gl_vertex, worldpos.xyz, radius | |
vec4 attrib1; //gl_MultiTexCoord0, | |
//for point lights this is ==0 | |
//for beam lights: pos2.xyz, >-1 | |
//for cone lights its: dir.xyz, angle | |
}; | |
#define LIGHTCOLOR colAtt.rgb | |
#define FALLOFF colAtt.a | |
#define LIGHTPOS attrib0.xyz | |
#define LIGHTRADIUS attrib0.a | |
#define BEAMPOS attrib1.xyz | |
#define CONEDIR attrib1.xyz | |
#define CONEANGLE attrib1.a | |
#define LIGHTTYPE attrib1.a | |
#define CLIP_CONTROL 1 //TODO | |
float attenuate(float dist, float radius) { | |
// float raw = constant-linear * dist / radius - squared * dist * dist / (radius * radius); | |
// float att = clamp(raw, 0.0, 0.5); | |
float raw = 0.7 - 0.3 * dist / radius - FALLOFF * dist * dist / (radius * radius); | |
float att = clamp(raw, 0.0, 1.0); | |
return (att * att); | |
} | |
void main() { | |
vec2 uv = gl_FragCoord.xy / viewPortSize; | |
//gl_FragColor = !gl_FrontFacing ? vec4(colAtt.rgb, 1.0) : vec4(vec3(1.0), 1.0); | |
gl_FragColor = vec4(colAtt.rgb, 1.0); | |
gl_FragColor = vec4(uv, 0.0, 1.0); | |
float mapDepth = texture2D( mapdepths, uv).x; | |
float mdlDepth = texture2D(modeldepths, uv).x; | |
#if (CLIP_CONTROL == 1) | |
vec4 mappos4 = vec4( vec3(uv * 2.0 - 1.0, mapDepth), 1.0); | |
vec4 modelpos4 = vec4( vec3(uv * 2.0 - 1.0, mdlDepth), 1.0); | |
#else | |
vec4 mappos4 = vec4( vec3(uv, mapDepth) * 2.0 - 1.0, 1.0); | |
vec4 modelpos4 = vec4( vec3(uv, mdlDepth) * 2.0 - 1.0, 1.0); | |
#endif | |
vec4 map_normals4 = texture2D(mapnormals , uv) * 2.0 - 1.0; | |
vec4 model_normals4 = texture2D(modelnormals, uv) * 2.0 - 1.0; | |
vec4 model_extra4 = texture2D(modelExtra , uv) * 2.0 - 1.0; | |
float specularHighlight = 1.0; // default specular factor, for models it should be read | |
float model_lighting_multiplier = 1.0; //models recieve additional lighting, looks better. | |
float specularExponent = 10.0; //default specular power, for models it should be different TODO | |
if ((mappos4.z - modelpos4.z) > 0.0) { | |
// this means we are processing a model fragment, not a map fragment | |
if (model_extra4.a > 0.5) { | |
map_normals4 = model_normals4; | |
mappos4 = modelpos4; | |
model_lighting_multiplier = 1.5; | |
specularHighlight = specularHighlight + 2.0 * model_extra4.g; | |
} | |
} | |
mappos4 = viewProjectionInv * mappos4; | |
mappos4.xyz = mappos4.xyz / mappos4.w; | |
vec3 light_direction = normalize(LIGHTPOS - mappos4.xyz);; | |
float dist_light_here = dot(LIGHTPOS - mappos4.xyz, light_direction); | |
float cosphi = 0; | |
if (LIGHTTYPE <= -1) { // BEAM LIGHT | |
//distance( Point P, Segment P0:P1 ) http://geomalgorithms.com/a02-_lines.html | |
vec3 v = BEAMPOS - LIGHTPOS; | |
vec3 w = mappos4.xyz - LIGHTPOS; | |
float c1 = dot(v, w); | |
float c2 = dot(v, v); | |
if (c1 <= 0.0){ | |
w = LIGHTPOS; | |
} else if (c2 < c1) { | |
w = BEAMPOS.xyz; | |
} else { | |
w = LIGHTPOS + (c1 / c2) * v; | |
} | |
v = mappos4.xyz; | |
light_direction = normalize(w.xyz - v.xyz); | |
dist_light_here = dot(w - v, light_direction); | |
cosphi = max(0.0, dot(normalize(map_normals4.xyz), light_direction)); | |
} | |
else if(LIGHTTYPE > 0){ // CONE Light | |
//https://www.tomdalling.com/blog/modern-opengl/08-even-more-lighting-directional-lights-spotlights-multiple-lights/ | |
vec3 coneDirection = normalize(CONEDIR); | |
float spotlightfactor = dot(coneDirection,light_direction); | |
if (spotlightfactor < CONEANGLE) spotlightfactor = 0; | |
cosphi = spotlightfactor * max(0.0, dot(normalize(map_normals4.xyz), light_direction)); | |
} | |
else{ // POINT LIGHT | |
cosphi = max(0.0, dot(normalize(map_normals4.xyz), light_direction)); | |
} | |
float attenuation = attenuate(dist_light_here, LIGHTRADIUS); | |
vec3 viewDirection = normalize(vec3(eyePos - mappos4.xyz)); | |
// light source on the wrong side? | |
if (dot(map_normals4.xyz, light_direction) > 0.02) { | |
vec3 reflection = reflect(-1.0 * light_direction, map_normals4.xyz); | |
float glossiness = dot(reflection, viewDirection); | |
float highlight = pow(max(0.0, glossiness), 8.0); | |
specularHighlight *= (0.5 * highlight); | |
} else { | |
specularHighlight = 0.0; | |
} | |
//OK, our blending func is the following: Rr=Lr*Dr+1*Dr | |
float lightalpha = cosphi * attenuation + attenuation * specularHighlight; | |
//dont light underwater: | |
lightalpha = clamp(lightalpha, 0.0, lightalpha * ((mappos4.y + 50.0) * (0.02))); | |
gl_FragColor = vec4(LIGHTCOLOR * lightalpha * model_lighting_multiplier, 1.0); | |
//gl_FragColor.g = 1.0; | |
//gl_FragColor.r = cosphi; | |
//gl_FragColor.b = fract(dist_light_here*0.01); | |
gl_FragColor.r = uv.x; | |
gl_FragColor.g = uv.y; | |
//gl_FragColor.r = fract(mappos4.x * 0.001); | |
//gl_FragColor.g = fract(mappos4.y * 0.001); | |
//gl_FragColor.b = fract(mappos4.z * 0.001); | |
gl_FragColor.r = fract(mappos4.x * 0.01); | |
gl_FragColor.g = fract(mappos4.y * 0.01); | |
gl_FragColor.b = fract(mappos4.z * 0.01); | |
//gl_FragColor.xyz = vec3(map_normals4.xyz); | |
//#define DEBUG | |
#ifdef DEBUG | |
gl_FragColor = vec4(map_normals4.xyz, 1.0); //world normals debugging | |
gl_FragColor = vec4(fract(modelpos4.z * 0.01),sign(mappos4.z - modelpos4.z), 0.0, 1.0); //world pos debugging, very useful | |
if (length(LIGHTCOLOR * lightalpha * model_lighting_multiplier) < (1.0 / 256.0)){ //shows light boudaries | |
gl_FragColor=vec4(vec3(0.5, 0.0, 0.5), 0.0); | |
} | |
#endif | |
} | |
]] | |
----------------------------------------------------------------- | |
-- Global Variables | |
----------------------------------------------------------------- | |
local glBlending = gl.Blending | |
local glTexture = gl.Texture | |
local LuaShader = VFS.Include(luaShaderDir.."LuaShader.lua") | |
local vsx, vsy, vpx, vpy | |
local lightShader | |
local dlPoint, dlBeam, dlCone | |
-------[[[OLD]]]-------------------- | |
local vertSrc = [[ | |
void main(void) | |
{ | |
gl_TexCoord[0] = gl_MultiTexCoord0; | |
gl_Position = gl_Vertex; | |
} | |
]] | |
local fragSrc = [[ | |
//This code authored by Peter Sarkozy aka Beherith (mysterme@gmail.com ) | |
//License is GPL V2 | |
// old version with calced normals is 67 fps for 10 beamers full screen at 1440p | |
// new version with buffered normals is 88 fps for 10 beamers full screen at 1440p | |
//#define DEBUG | |
#define LIGHTRADIUS lightpos.w | |
uniform sampler2D modelnormals; | |
uniform sampler2D modeldepths; | |
uniform sampler2D mapnormals; | |
uniform sampler2D mapdepths; | |
uniform sampler2D modelExtra; | |
uniform vec3 eyePos; | |
uniform vec4 lightpos; | |
#if (BEAM_LIGHT == 1) | |
uniform vec4 lightpos2; | |
#endif | |
uniform vec4 lightcolor; | |
uniform mat4 viewProjectionInv; | |
float attenuate(float dist, float radius) { | |
// float raw = constant-linear * dist / radius - squared * dist * dist / (radius * radius); | |
// float att = clamp(raw, 0.0, 0.5); | |
float raw = 0.7 - 0.3 * dist / radius - lightcolor.a * dist * dist / (radius * radius); | |
float att = clamp(raw, 0.0, 1.0); | |
return (att * att); | |
} | |
void main(void) | |
{ | |
float mapDepth = texture2D( mapdepths, gl_TexCoord[0].st).x; | |
float mdlDepth = texture2D(modeldepths, gl_TexCoord[0].st).x; | |
#if (CLIP_CONTROL == 1) | |
vec4 mappos4 = vec4( vec3(gl_TexCoord[0].st * 2.0 - 1.0, mapDepth), 1.0); | |
vec4 modelpos4 = vec4( vec3(gl_TexCoord[0].st * 2.0 - 1.0, mdlDepth), 1.0); | |
#else | |
vec4 mappos4 = vec4( vec3(gl_TexCoord[0].st, mapDepth) * 2.0 - 1.0, 1.0); | |
vec4 modelpos4 = vec4( vec3(gl_TexCoord[0].st, mdlDepth) * 2.0 - 1.0, 1.0); | |
#endif | |
vec4 map_normals4 = texture2D(mapnormals , gl_TexCoord[0].st) * 2.0 - 1.0; | |
vec4 model_normals4 = texture2D(modelnormals, gl_TexCoord[0].st) * 2.0 - 1.0; | |
vec4 model_extra4 = texture2D(modelExtra , gl_TexCoord[0].st) * 2.0 - 1.0; | |
float specularHighlight = 1.0; | |
float model_lighting_multiplier = 1.0; //models recieve additional lighting, looks better. | |
if ((mappos4.z - modelpos4.z) > 0.0) { | |
// this means we are processing a model fragment, not a map fragment | |
if (model_extra4.a > 0.5) { | |
map_normals4 = model_normals4; | |
mappos4 = modelpos4; | |
model_lighting_multiplier = 1.5; | |
specularHighlight = specularHighlight + 2.0 * model_extra4.g; | |
} | |
} | |
mappos4 = viewProjectionInv * mappos4; | |
mappos4.xyz = mappos4.xyz / mappos4.w; | |
vec3 light_direction; | |
#if (BEAM_LIGHT == 0) | |
light_direction = normalize(lightpos.xyz - mappos4.xyz); | |
float dist_light_here = dot(lightpos.xyz - mappos4.xyz, light_direction); | |
float cosphi = max(0.0, dot(normalize(map_normals4.xyz), light_direction)); | |
float attenuation = attenuate(dist_light_here, LIGHTRADIUS); | |
#else | |
/*distance( Point P, Segment P0:P1 ) // http://geomalgorithms.com/a02-_lines.html | |
{ | |
v = P1 - P0 | |
w = P - P0 | |
if ( (c1 = w dot v) <= 0 ) // before P0 | |
return d(P, P0) | |
if ( (c2 = v dot v) <= c1 ) // after P1 | |
return d(P, P1) | |
b = c1 / c2 | |
Pb = P0 + bv | |
return d(P, Pb) | |
} | |
*/ | |
vec3 v = lightpos2.xyz - lightpos.xyz; | |
vec3 w = mappos4.xyz - lightpos.xyz; | |
float c1 = dot(v, w); | |
float c2 = dot(v, v); | |
if (c1 <= 0.0){ | |
v = mappos4.xyz; | |
w = lightpos.xyz; | |
} else if (c2 < c1) { | |
v = mappos4.xyz; | |
w = lightpos2.xyz; | |
} else { | |
w = lightpos.xyz + (c1 / c2) * v; | |
v = mappos4.xyz; | |
} | |
light_direction = normalize(w.xyz - v.xyz); | |
float dist_light_here = dot(w - v, light_direction); | |
float cosphi = max(0.0, dot(normalize(map_normals4.xyz), light_direction)); | |
// float attenuation = max(0.0, (1.0 * LIGHT_CONSTANT - LIGHT_SQUARED * (dist_light_here * dist_light_here) / (LIGHTRADIUS * LIGHTRADIUS) - LIGHT_LINEAR * (dist_light_here) / (LIGHTRADIUS))); | |
float attenuation = attenuate(dist_light_here, LIGHTRADIUS); | |
#endif | |
vec3 viewDirection = normalize(vec3(eyePos - mappos4.xyz)); | |
// light source on the wrong side? | |
if (dot(map_normals4.xyz, light_direction) > 0.02) { | |
vec3 reflection = reflect(-1.0 * light_direction, map_normals4.xyz); | |
float glossiness = dot(reflection, viewDirection); | |
float highlight = pow(max(0.0, glossiness), 8.0); | |
specularHighlight *= (0.5 * highlight); | |
} else { | |
specularHighlight = 0.0; | |
} | |
//OK, our blending func is the following: Rr=Lr*Dr+1*Dr | |
float lightalpha = cosphi * attenuation + attenuation * specularHighlight; | |
//dont light underwater: | |
lightalpha = clamp(lightalpha, 0.0, lightalpha * ((mappos4.y + 50.0) * (0.02))); | |
gl_FragColor = vec4(lightcolor.rgb * lightalpha * model_lighting_multiplier, 1.0); | |
gl_FragColor.r = 1.0; | |
#ifdef DEBUG | |
gl_FragColor = vec4(map_normals4.xyz, 1.0); //world normals debugging | |
gl_FragColor = vec4(fract(modelpos4.z * 0.01),sign(mappos4.z - modelpos4.z), 0.0, 1.0); //world pos debugging, very useful | |
if (length(lightcolor.rgb * lightalpha * model_lighting_multiplier) < (1.0 / 256.0)){ //shows light boudaries | |
gl_FragColor=vec4(vec3(0.5, 0.0, 0.5), 0.0); | |
} | |
#endif | |
} | |
]] | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
local function DeferredLighting_RegisterFunction(func) | |
collectionFunctionCount = collectionFunctionCount + 1 | |
collectionFunctions[collectionFunctionCount] = func | |
return collectionFunctionCount | |
end | |
local function DeferredLighting_UnRegisterFunction(functionID) | |
collectionFunctions[functionID] = nil | |
end | |
local function PrepareLightDisplayLists() | |
if dlPoint then | |
gl.DeleteList(dlPoint) | |
dlPoint = nil | |
end | |
if dlBeam then | |
gl.DeleteList(dlBeam) | |
dlBeam = nil | |
end | |
if dlCone then | |
gl.DeleteList(dlCone) | |
dlCone = nil | |
end | |
dlBeam = gl.CreateList( function() --800, 130, 2700 | |
gl.BeginEnd(GL.POINTS, function () | |
gl.Color(0, 1, 0, 1) --green, unit fallofffactor | |
gl.Vertex(1000, 250, 1000, 250) | |
gl.MultiTexCoord(0, 1000, 250 , 2000, -2.0) -- | |
end) | |
end) | |
dlPoint = gl.CreateList( function() | |
gl.BeginEnd(GL.POINTS, function () | |
gl.Color(1, 0, 1, 1) --blue, unit fallofffactor | |
gl.Vertex(2000, 150, 1000, 150) | |
gl.MultiTexCoord(0, 0, 0 , 0, 0) -- | |
gl.Color(0, 1, 0, 1) --green, unit fallofffactor | |
gl.Vertex(3000, 250, 1000, 250) | |
gl.MultiTexCoord(0, 0, 0 , 0, 0) -- | |
end) | |
end) | |
dlCone = gl.CreateList( function() | |
gl.BeginEnd(GL.POINTS, function () | |
gl.Color(1, 1, 0, 1) --yellow, unit fallofffactor | |
gl.Vertex(4000, 250, 1000, 250) | |
gl.MultiTexCoord(0, 200, 250 , 1600, 1.0) -- | |
end) | |
end) | |
end | |
function widget:Initialize() | |
local vsx, vsy, vpx, vpy = Spring.GetViewGeometry() | |
widget:ViewResize() | |
------[[[NEW]]----- | |
lightShader = LuaShader({ | |
vertex = vsSrc, | |
geometry = gsSrc, | |
fragment = fsSrc, | |
uniformFloat = { | |
viewPortSize = {vsx, vsy}, | |
eyePos = {0,0,0}, | |
}, | |
}, "Light Volume Shader2") | |
lightShader:Initialize() | |
PrepareLightDisplayLists() | |
if (glCreateShader == nil) then | |
Spring.Echo('Deferred Rendering requires shader support!') | |
widgetHandler:RemoveWidget(self) | |
return | |
end | |
Spring.SetConfigInt("AllowDeferredMapRendering", 1) | |
Spring.SetConfigInt("AllowDeferredModelRendering", 1) | |
if (Spring.GetConfigString("AllowDeferredMapRendering") == '0' or Spring.GetConfigString("AllowDeferredModelRendering") == '0') then | |
Spring.Echo('Deferred Rendering (gfx_deferred_rendering.lua) requires AllowDeferredMapRendering and AllowDeferredModelRendering to be enabled in springsettings.cfg!') | |
widgetHandler:RemoveWidget(self) | |
return | |
end | |
if ((not forceNonGLSL) and Spring.GetMiniMapDualScreen() ~= 'left') then --FIXME dualscreen | |
if (not glCreateShader) then | |
spEcho("gfx_deferred_rendering.lua: Shaders not found, removing self.") | |
GLSLRenderer = false | |
widgetHandler:RemoveWidget(self) | |
return | |
else | |
depthPointShader = depthPointShader or glCreateShader({ | |
defines = { | |
"#version 150 compatibility\n", | |
"#define BEAM_LIGHT 0\n", | |
"#define CLIP_CONTROL " .. (Platform ~= nil and Platform.glSupportClipSpaceControl and 1 or 0) .. "\n" | |
}, | |
vertex = vertSrc, | |
fragment = fragSrc, | |
uniformInt = { | |
modelnormals = 0, | |
modeldepths = 1, | |
mapnormals = 2, | |
mapdepths = 3, | |
modelExtra = 4, | |
}, | |
}) | |
if (not depthPointShader) then | |
spEcho(glGetShaderLog()) | |
spEcho("gfx_deferred_rendering.lua: Bad depth point shader, removing self.") | |
GLSLRenderer = false | |
widgetHandler:RemoveWidget(self) | |
return | |
else | |
lightposlocPoint = glGetUniformLocation(depthPointShader, "lightpos") | |
lightcolorlocPoint = glGetUniformLocation(depthPointShader, "lightcolor") | |
uniformEyePosPoint = glGetUniformLocation(depthPointShader, 'eyePos') | |
uniformViewPrjInvPoint = glGetUniformLocation(depthPointShader, 'viewProjectionInv') | |
end | |
--fragSrc = "#define BEAM_LIGHT \n" .. fragSrc | |
depthBeamShader = depthBeamShader or glCreateShader({ | |
defines = { | |
"#version 150 compatibility\n", | |
"#define BEAM_LIGHT 1\n", | |
"#define CLIP_CONTROL " .. (Platform ~= nil and Platform.glSupportClipSpaceControl and 1 or 0) .. "\n" | |
}, | |
vertex = vertSrc, | |
fragment = fragSrc, | |
uniformInt = { | |
modelnormals = 0, | |
modeldepths = 1, | |
mapnormals = 2, | |
mapdepths = 3, | |
modelExtra = 4, | |
}, | |
}) | |
if (not depthBeamShader) then | |
spEcho(glGetShaderLog()) | |
spEcho("gfx_deferred_rendering.lua: Bad depth beam shader, removing self.") | |
GLSLRenderer = false | |
widgetHandler:RemoveWidget(self) | |
return | |
else | |
lightposlocBeam = glGetUniformLocation(depthBeamShader, 'lightpos') | |
lightpos2locBeam = glGetUniformLocation(depthBeamShader, 'lightpos2') | |
lightcolorlocBeam = glGetUniformLocation(depthBeamShader, 'lightcolor') | |
uniformEyePosBeam = glGetUniformLocation(depthBeamShader, 'eyePos') | |
uniformViewPrjInvBeam = glGetUniformLocation(depthBeamShader, 'viewProjectionInv') | |
end | |
WG.DeferredLighting_RegisterFunction = DeferredLighting_RegisterFunction | |
WG.DeferredLighting_UnRegisterFunction = DeferredLighting_UnRegisterFunction | |
end | |
screenratio = vsy / vsx --so we dont overdraw and only always draw a square | |
else | |
GLSLRenderer = false | |
end | |
end | |
function widget:Shutdown() | |
if (GLSLRenderer) then | |
if (glDeleteShader) then | |
glDeleteShader(depthPointShader) | |
glDeleteShader(depthBeamShader) | |
end | |
end | |
end | |
local drawarea = 0 | |
local function DrawLightType(lights, lightsCount, lighttype) -- point = 0 beam = 1 | |
--Spring.Echo('Camera FOV = ', Spring.GetCameraFOV()) -- default TA cam fov = 45 | |
--set uniforms: | |
local cpx, cpy, cpz = spGetCameraPosition() | |
if lighttype == 0 then --point | |
glUseShader(depthPointShader) | |
glUniform(uniformEyePosPoint, cpx, cpy, cpz) | |
glUniformMatrix(uniformViewPrjInvPoint, "viewprojectioninverse") | |
else --beam | |
glUseShader(depthBeamShader) | |
glUniform(uniformEyePosBeam, cpx, cpy, cpz) | |
glUniformMatrix(uniformViewPrjInvBeam, "viewprojectioninverse") | |
end | |
glTexture(0, "$model_gbuffer_normtex") | |
glTexture(1, "$model_gbuffer_zvaltex") | |
glTexture(2, "$map_gbuffer_normtex") | |
glTexture(3, "$map_gbuffer_zvaltex") | |
glTexture(4, "$model_gbuffer_spectex") | |
local cx, cy, cz = spGetCameraPosition() | |
for i = 1, lightsCount do | |
local light = lights[i] | |
local param = light.param | |
if verbose then | |
VerboseEcho('gfx_deferred_rendering.lua: Light being drawn:', i) | |
Spring.Utilities.TableEcho(light) | |
end | |
if lighttype == 0 then -- point | |
local lightradius = param.radius | |
local falloffsquared = param.falloffsquared or 1.0 | |
--Spring.Echo("Drawlighttype position = ", light.px, light.py, light.pz) | |
local groundheight = math_max(0, spGetGroundHeight(light.px, light.pz)) | |
local sx, sy, sz = spWorldToScreenCoords(light.px, groundheight, light.pz) -- returns x, y, z, where x and y are screen pixels, and z is z buffer depth. | |
sx = sx/vsx | |
sy = sy/vsy --since FOV is static in the Y direction, the Y ratio is the correct one | |
--local dist_sq = (light.px-cx)^2 + (groundheight-cy)^2 + (light.pz-cz)^2 | |
local dist_sq = (light.px-cx)^2 + (groundheight-cy)^2 + (light.pz-cz)^2 | |
local ratio = lightradius / math_sqrt(dist_sq) * 1.5 | |
glUniform(lightposlocPoint, light.px, light.py, light.pz, param.radius) --in world space | |
glUniform(lightcolorlocPoint, param.r * light.colMult, param.g * light.colMult, param.b * light.colMult, falloffsquared) | |
local tx1 = (sx-0.5)*2-ratio*screenratio | |
local ty1 = (sy-0.5)*2-ratio | |
local tx2 = (sx-0.5)*2+ratio*screenratio | |
local ty2 = (sy-0.5)*2+ratio | |
drawarea = drawarea + ( math_min( 1 , tx2)- math_max(-1 , tx1)) * (math_min( 1 , ty2) - math_max(-1 , ty1))*0.25 | |
--PtaQ uncomment this if you want to debug: | |
--Spring.Echo(string.format("sx=%.4f sy = %.4f dist_sq=%.1f ratio = %.4f, {%.4f : %.4f}-{%.4f : %.4f}",sx,sy,dist_sq,ratio,tx1,ty1,tx2,ty2)) | |
glTexRect( | |
math_max(-1 , tx1), | |
math_max(-1 , ty1), | |
math_min( 1 , tx2), | |
math_min( 1 , ty2), | |
math_max( 0 , sx - 0.5*ratio*screenratio), | |
math_max( 0 , sy - 0.5*ratio), | |
math_min( 1 , sx + 0.5*ratio*screenratio), | |
math_min( 1 , sy + 0.5*ratio) | |
) -- screen size goes from -1, -1 to 1, 1; uvs go from 0, 0 to 1, 1 | |
end | |
if lighttype == 1 then -- beam | |
local lightradius = 0 | |
local falloffsquared = param.falloffsquared or 1.0 | |
local px = light.px+light.dx*0.5 | |
local py = light.py+light.dy*0.5 | |
local pz = light.pz+light.dz*0.5 | |
local lightradius = param.radius + math_sqrt(light.dx*light.dx + light.dy*light.dy + light.dz*light.dz)*0.5 | |
VerboseEcho("Drawlighttype position = ", light.px, light.py, light.pz) | |
local sx, sy, sz = spWorldToScreenCoords(px, py, pz) -- returns x, y, z, where x and y are screen pixels, and z is z buffer depth. | |
sx = sx/vsx | |
sy = sy/vsy --since FOV is static in the Y direction, the Y ratio is the correct one | |
local dist_sq = (px-cx)^2 + (py-cy)^2 + (pz-cz)^2 | |
local ratio = lightradius / math_sqrt(dist_sq) | |
ratio = ratio*2 | |
glUniform(lightposlocBeam, light.px, light.py, light.pz, param.radius) --in world space | |
glUniform(lightpos2locBeam, light.px+light.dx, light.py+light.dy+24, light.pz+light.dz, param.radius) --in world space, the magic constant of +24 in the Y pos is needed because of our beam distance calculator function in GLSL | |
glUniform(lightcolorlocBeam, param.r * light.colMult, param.g * light.colMult, param.b * light.colMult, falloffsquared) | |
--TODO: use gl.Shape instead, to avoid overdraw | |
local tx1 = (sx-0.5)*2-ratio*screenratio | |
local ty1 = (sy-0.5)*2-ratio | |
local tx2 = (sx-0.5)*2+ratio*screenratio | |
local ty2 = (sy-0.5)*2+ratio | |
drawarea = drawarea + ( math_min( 1 , tx2)- math_max(-1 , tx1)) * (math_min( 1 , ty2) - math_max(-1 , ty1))*0.25 | |
glTexRect( | |
math_max(-1 , tx1), | |
math_max(-1 , ty1), | |
math_min( 1 , tx2), | |
math_min( 1 , ty2), | |
math_max( 0 , sx - 0.5*ratio*screenratio), | |
math_max( 0 , sy - 0.5*ratio), | |
math_min( 1 , sx + 0.5*ratio*screenratio), | |
math_min( 1 , sy + 0.5*ratio) | |
) -- screen size goes from -1, -1 to 1, 1; uvs go from 0, 0 to 1, 1 | |
end | |
end | |
glUseShader(0) | |
glTexture(0, false) | |
glTexture(1, false) | |
glTexture(2, false) | |
glTexture(3, false) | |
glTexture(4, false) | |
end | |
local function renderToTextureFunc(tex, s, t) | |
glTexture(tex) | |
glTexRect(-1 * s, -1 * t, 1 * s, 1 * t) | |
glTexture(false) | |
end | |
local function mglRenderToTexture(FBOTex, tex, s, t) | |
glRenderToTexture(FBOTex, renderToTextureFunc, tex, s, t) | |
end | |
local beamLights = {} | |
local beamLightCount = 0 | |
local pointLights = {} | |
local pointLightCount = 0 | |
function widget:Update() | |
beamLights = {} | |
beamLightCount = 0 | |
pointLights = {} | |
pointLightCount = 0 | |
for i = 1, collectionFunctionCount do | |
if collectionFunctions[i] then | |
beamLights, beamLightCount, pointLights, pointLightCount = collectionFunctions[i](beamLights, beamLightCount, pointLights, pointLightCount) | |
end | |
end | |
end | |
-- adding a glow to Cannon projectiles | |
--[[ | |
function widget:DrawWorld() | |
local lights = pointLights | |
glBlending(GL.SRC_ALPHA, GL.ONE) | |
gl.Texture(glowImg) | |
local size = 1 | |
for i = 1, pointLightCount do | |
local light = lights[i] | |
local param = light.param | |
if param.gib == nil and param.type == "Cannon" then | |
size = param.glowradius * 0.44 | |
gl.PushMatrix() | |
local colorMultiplier = 1 / math_max(param.r, param.g, param.b) | |
gl.Color(param.r*colorMultiplier, param.g*colorMultiplier, param.b*colorMultiplier, 0.015 + (size/4000)) | |
gl.Translate(light.px, light.py, light.pz) | |
gl.Billboard(true) | |
gl.TexRect(-(size/2), -(size/2), (size/2), (size/2)) | |
gl.PopMatrix() | |
end | |
end | |
gl.Billboard(false) | |
gl.Texture(false) | |
glBlending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) | |
end | |
]]-- | |
local GL_KEEP = 0x1E00 | |
local GL_ZERO = 0x0000 | |
local GL_INCR = 0x1E02 | |
local GL_INCR_WRAP = 0x8507 | |
local GL_DECR_WRAP = 0x8508 | |
local function LightVolumePass1() | |
gl.StencilTest(true) | |
gl.Culling(GL.BACK) | |
gl.ColorMask(false, false, false, false) | |
gl.DepthTest(GL.LEQUAL) | |
gl.StencilOp(GL_ZERO, GL_INCR, GL_ZERO) | |
gl.StencilFunc(GL.ALWAYS, 0, 0xFF) | |
if dlPoint then | |
--lightShader:SetUniformIntAlways("lightType", 0) | |
gl.CallList(dlPoint) | |
end | |
if dlBeam then | |
--lightShader:SetUniformIntAlways("lightType", 1) | |
gl.CallList(dlBeam) | |
end | |
if dlCone then | |
--lightShader:SetUniformIntAlways("lightType", 2) | |
gl.CallList(dlCone) | |
end | |
if LightDL then | |
--lightShader:SetUniformIntAlways("lightType", 2) | |
gl.CallList(LightDL) | |
end | |
end | |
local function LightVolumePass2() | |
gl.Culling(GL.FRONT) | |
gl.ColorMask(true, true, true, true) | |
gl.DepthTest(GL.GEQUAL) | |
gl.StencilOp(GL_ZERO, GL_ZERO, GL_ZERO) | |
gl.StencilFunc(GL.EQUAL, 0, 0xFF) | |
glBlending(GL.SRC_ALPHA, GL.ONE) | |
glTexture(0, "$model_gbuffer_normtex") | |
glTexture(1, "$model_gbuffer_zvaltex") | |
glTexture(2, "$map_gbuffer_normtex") | |
glTexture(3, "$map_gbuffer_zvaltex") | |
glTexture(4, "$model_gbuffer_spectex") | |
if dlPoint then | |
--lightShader:SetUniformIntAlways("lightType", 0) | |
gl.CallList(dlPoint) | |
end | |
if dlBeam then | |
--lightShader:SetUniformIntAlways("lightType", 1) | |
gl.CallList(dlBeam) | |
end | |
if dlCone then | |
--lightShader:SetUniformIntAlways("lightType", 2) | |
gl.CallList(dlCone) | |
end | |
if LightDL then | |
--lightShader:SetUniformIntAlways("lightType", 2) | |
gl.CallList(LightDL) | |
end | |
--Spring.Echo("Drawing",dlPoint,dlBeam,dlCone,LightDL) | |
--cleanup | |
gl.StencilTest(false) | |
gl.DepthTest(GL.LEQUAL) | |
gl.Culling(false) | |
glTexture(0, false) | |
glTexture(1, false) | |
glTexture(2, false) | |
glTexture(3, false) | |
glTexture(4, false) | |
glBlending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) | |
end | |
function widget:DrawWorld() | |
lightShader:ActivateWith( function () | |
lightShader:SetUniformMatrix("viewMat", "camera") | |
lightShader:SetUniformMatrix("projMat", "projection") | |
lightShader:SetUniformMatrix("viewProjectionInv","viewprojectioninverse") -- TODO GET THE FUCKING INVERSE OF THIS SHIT! | |
local cpx, cpy, cpz = spGetCameraPosition() | |
lightShader:SetUniformAlways("eyePos", cpx, cpy, cpz) | |
--LightVolumePass1() | |
LightVolumePass2() | |
--LightVolumePassSimple() | |
--LightVolumePassDebug() | |
--LightVolumePass1B() | |
--LightVolumePass2B() | |
end) | |
end | |
function widget:DrawScreenEffects() | |
if not (GLSLRenderer) then | |
Spring.Echo('Removing deferred rendering widget: failed to use GLSL shader') | |
widgetHandler:RemoveWidget(self) | |
return | |
end | |
drawarea = 0 | |
--glBlending(GL.DST_COLOR, GL.ONE) -- Set add blending mode | |
glBlending(GL.SRC_ALPHA, GL.ONE) | |
if beamLightCount > 0 then | |
--DrawLightType(beamLights, beamLightCount, 1) | |
end | |
--glBlending(GL.ONE_MINUS_SRC_COLOR, GL.ONE) | |
if pointLightCount > 0 then | |
--DrawLightType(pointLights, pointLightCount, 0) | |
end | |
if drawarea> 0.01 then | |
Spring.Echo(string.format("Total Draw Area for dynamic lights = %.3f, beams=%d, points=%d, cones=%d",drawarea,beamLightCount,pointLightCount,0)) | |
end | |
drawarea = 0 | |
glBlending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA) | |
end | |
function widget:Update() | |
CreateLightDisplayList() | |
end | |
function CreateLightDisplayList() | |
if not (GLSLRenderer) then | |
Spring.Echo('Removing deferred rendering widget: failed to use GLSL shader') | |
widgetHandler:RemoveWidget(self) | |
return | |
end | |
if LightDL then | |
glDeleteList(LightDL) | |
LightDL = nil | |
end | |
local allLights = pointLights | |
local allLightsCount = pointLightCount | |
for i = 1, beamLightCount do | |
allLights[i+allLightsCount] = beamLights[i] | |
allLightsCount = allLightsCount + 1 | |
end | |
for i = 1, beamLightCount do | |
allLights[i+allLightsCount] = beamLights[i] | |
allLightsCount = allLightsCount + 1 | |
end | |
LightDL = glCreateList( function() | |
gl.BeginEnd(GL.POINTS, function() | |
local light_index = 0 | |
--gl.Color(0, -1, 1, 1) -- R, G, B, fallofffactor | |
--gl.MultiTexCoord(i, 2738, 140, 4519, 32) | |
--for point lights this is ==0 | |
--for beam lights: pos2.xyz, >-1 | |
--for cone lights its: dir.xyz, angle | |
--gl.Vertex(2556, 140, 4753, 40) -- index of point, lightpos.xyz, light radius | |
for i = 1, allLightsCount do | |
local light = allLights[i] | |
local param = light.param | |
local falloffsquared = param.falloffsquared or 1.0 | |
gl.Color( | |
param.r * light.colMult, | |
param.g * light.colMult, | |
param.b * light.colMult, | |
falloffsquared) | |
if light.beam then | |
gl.MultiTexCoord(light_index,light.dx,light.dy, light.dz, -2.0) | |
elseif light.cone then | |
gl.MultiTexCoord(light_index,light.dx,light.dy, light.dz, 0.3) | |
else | |
gl.MultiTexCoord(light_index,0,0,0,0) | |
end | |
light_index = light_index + 1 | |
gl.Vertex(light.px, light.py, light.pz, param.radius) | |
end | |
end ) | |
end ) | |
end | |
---TODO: 2020 september 17 | |
-- 1. fix light collection functions, do not separate beams | |
-- 2. Decide wether to drawworld or drawscreeneffects | |
-- 3. Decide wether all particles should contribute - is dlist creation worse than gl.vertex? | |
-- 4. build up dlist of all lights | |
-- 5. readd glow to cannon projectiles | |
-- 6. pass eyepos and projMatinv to fragment shader | |
-- 7. check light radii for sanity | |
-- a. luaify attenuate function for worst case | |
-- 8. premultiply light intensity with light color | |
-- 9. pass linear falloff to fragment shader | |
-- 10. add a function to each lightdef, that runs per sim frame | |
-- a. should allow removal of self | |
-- b. can a function operate on the table that it was included in? | |
-- 11. prevent flickering lights from non-sim flickering | |
-- 12. what is clip control and do we need it? | |
---TODO: 2020 september 17 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment