Skip to content

Instantly share code, notes, and snippets.

@lhog
Created Jul 10, 2018
Embed
What would you like to do?
function gadget:GetInfo()
return {
name = "Lava Gadget 2.3",
desc = "lava",
author = "knorke, Beherith, The_Yak, Anarchid, Kloot, Gajop, ivand",
date = "Feb 2011, Nov 2013",
license = "GNU GPL, v2 or later",
layer = -3,
enabled = true
}
end
-----------------
if (gadgetHandler:IsSyncedCode()) then
else --- UNSYCNED:
--local GL_LUMINANCE32F_ARB = 0x8818
--reconsider size
local lavaHeightMapTexX, lavaHeightMapTexY = 5 * Game.mapX * 64, 5 * Game.mapY * 64
local lavaHeightMapTex
local lavaHeightMapFBO
local lavaHeightMapSrc = VFS.LoadFile("LuaRules\\Gadgets\\Shaders\\lavaHeightMap.glsl", VFS.ZIP)
local lavaHeightMapShader
local lavaHeightMapShaderTimeLoc
local lavaDrawShader
local lavaDrawShaderTimeLoc
local lavaSurfaceDrawList
local gf = 0
local function InitLavaHeightMap()
lavaHeightMapTex = gl.CreateTexture(lavaHeightMapTexX, lavaHeightMapTexY, {
border = false,
min_filter = GL.LINEAR,
mag_filter = GL.LINEAR,
wrap_s = GL.CLAMP_TO_EDGE,
wrap_t = GL.CLAMP_TO_EDGE,
fbo = true,
})
lavaHeightMapFBO = gl.CreateFBO({color0 = lavaHeightMapTex})
lavaHeightMapShader = gl.CreateShader({
uniform = {
lavaHeightMapTexX = lavaHeightMapTexX,
lavaHeightMapTexY = lavaHeightMapTexY,
},
fragment = lavaHeightMapSrc
})
Spring.Echo(lavaHeightMapTexX, lavaHeightMapTexY, lavaHeightMapTex, lavaHeightMapFBO, lavaHeightMapShader)
Spring.Echo("GL_ARB_tessellation_shader", gl.HasExtension("GL_ARB_tessellation_shader"))
Spring.Echo("SunDir", gl.GetSun("pos"))
Spring.Echo("ambient",gl.GetSun("ambient" ,"unit"))
Spring.Echo("diffuse",gl.GetSun("diffuse" ,"unit"))
Spring.Echo("specular",gl.GetSun("specular" ,"unit"))
local shLog = gl.GetShaderLog() or ""
if shLog ~= "" then
Spring.Echo("lavaHeightMapShader warnings/errors\n"..shLog)
end
if lavaHeightMapShader then
lavaHeightMapShaderTimeLoc = gl.GetUniformLocation(lavaHeightMapShader, "time")
end
-- TODO, read sun params from mapinfo.lua!
local sdx, sdy, sdz = gl.GetSun("pos")
lavaDrawShader = gl.CreateShader({
uniform = {
lavaHeightMapTexX = lavaHeightMapTexX,
lavaHeightMapTexY = lavaHeightMapTexY,
["lightInfo.DirPos"] = { sdx, sdy, sdz, 0.0 },
["lightInfo.La"] = { gl.GetSun("ambient") },
["lightInfo.Ld"] = { gl.GetSun("diffuse") },
["lightInfo.Ls"] = { gl.GetSun("specular") },
--[[
--["materialInfo.Emmission"] = {0.015, 0.017, 0.024},
["materialInfo.Emmission"] = {0.0, 0.0, 0.0},
--["materialInfo.Ka"] = {0.0, 0.0, 0.0},
["materialInfo.Ka"] = {0.1, 0.1, 0.1},
--["materialInfo.Ka"] = {0.015, 0.017, 0.024},
--["materialInfo.Kd"] = {1.0, 1.0, 1.0},
--["materialInfo.Kd"] = {0.15, 0.17, 0.24},
["materialInfo.Kd"] = {0.8, 0.8, 0.8},
["materialInfo.Ks"] = {10.0, 10.0, 10.0},
["materialInfo.Shininess"] = 128.0,
]]--
--[[
["materialInfo.Ka"] = {0.25, 0.148, 0.06475},
["materialInfo.Kd"] = {0.4, 0.2368, 0.1036},
["materialInfo.Ks"] = {0.774597, 0.458561, 0.200621},
["materialInfo.Shininess"] = 76.8,
]]--
["materialInfo.Ka"] = {0.24725, 0.2245, 0.0645},
["materialInfo.Kd"] = {0.34615, 0.3143, 0.0903},
["materialInfo.Ks"] = {0.797357, 0.723991, 0.208006},
["materialInfo.Shininess"] = 83.2,
},
uniformInt = {
lavaHeightMapTex = 0,
},
vertex = [[
#version 150 compatibility
uniform vec3 CameraPos;
out Data
{
//vec4 eyeFragPos;
vec4 worldFragPos;
vec3 cameraDir;
vec2 uv;
};
void main()
{
uv = (gl_TextureMatrix[0] * gl_MultiTexCoord0).st;
worldFragPos = vec4(gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0);
vec4 eyeFragPos = gl_ModelViewMatrix * worldFragPos;
cameraDir = normalize(CameraPos - worldFragPos.xyz); //worldspace
gl_Position = gl_ProjectionMatrix * eyeFragPos;
}
]],
fragment = [[
#version 150 compatibility
uniform sampler2D lavaHeightMapTex;
uniform float time;
struct LightInfo {
vec4 DirPos; //support both Directional (vec3 direction vector, w == 0.0) and Point light (vec3 position vector, w != 0.0). World Space
vec3 La;
vec3 Ld;
vec3 Ls;
};
uniform LightInfo lightInfo;
struct MaterialInfo {
vec3 Ka;
vec3 Kd;
vec3 Ks;
float Shininess;
};
uniform MaterialInfo materialInfo;
in Data
{
//vec4 eyeFragPos;
vec4 worldFragPos;
vec3 cameraDir;
vec2 uv;
};
/////////////////////////////
vec4 Perlin3D_Deriv( vec3 P )
{
// https://github.com/BrianSharpe/Wombat/blob/master/Perlin3D_Deriv.glsl
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
vec3 Pf_min1 = Pf - 1.0;
// clamp the domain
Pi.xyz = Pi.xyz - floor(Pi.xyz * ( 1.0 / 69.0 )) * 69.0;
vec3 Pi_inc1 = step( Pi, vec3( 69.0 - 1.5 ) ) * ( Pi + 1.0 );
// calculate the hash
vec4 Pt = vec4( Pi.xy, Pi_inc1.xy ) + vec2( 50.0, 161.0 ).xyxy;
Pt *= Pt;
Pt = Pt.xzxz * Pt.yyww;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS + Pi.zzz * ZINC ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS + Pi_inc1.zzz * ZINC ) );
vec4 hashx0 = fract( Pt * lowz_mod.xxxx );
vec4 hashx1 = fract( Pt * highz_mod.xxxx );
vec4 hashy0 = fract( Pt * lowz_mod.yyyy );
vec4 hashy1 = fract( Pt * highz_mod.yyyy );
vec4 hashz0 = fract( Pt * lowz_mod.zzzz );
vec4 hashz1 = fract( Pt * highz_mod.zzzz );
// calculate the gradients
vec4 grad_x0 = hashx0 - 0.49999;
vec4 grad_y0 = hashy0 - 0.49999;
vec4 grad_z0 = hashz0 - 0.49999;
vec4 grad_x1 = hashx1 - 0.49999;
vec4 grad_y1 = hashy1 - 0.49999;
vec4 grad_z1 = hashz1 - 0.49999;
vec4 norm_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 );
vec4 norm_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 );
grad_x0 *= norm_0;
grad_y0 *= norm_0;
grad_z0 *= norm_0;
grad_x1 *= norm_1;
grad_y1 *= norm_1;
grad_z1 *= norm_1;
// calculate the dot products
vec4 dotval_0 = vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0;
vec4 dotval_1 = vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1;
// C2 Interpolation
vec3 blend = Pf * Pf * Pf * (Pf * (Pf * 6.0 - 15.0) + 10.0);
vec3 blendDeriv = Pf * Pf * (Pf * (Pf * 30.0 - 60.0) + 30.0);
// the following is based off Milo Yips derivation, but modified for parallel execution
// http://stackoverflow.com/a/14141774
// Convert our data to a more parallel format
vec4 dotval0_grad0 = vec4( dotval_0.x, grad_x0.x, grad_y0.x, grad_z0.x );
vec4 dotval1_grad1 = vec4( dotval_0.y, grad_x0.y, grad_y0.y, grad_z0.y );
vec4 dotval2_grad2 = vec4( dotval_0.z, grad_x0.z, grad_y0.z, grad_z0.z );
vec4 dotval3_grad3 = vec4( dotval_0.w, grad_x0.w, grad_y0.w, grad_z0.w );
vec4 dotval4_grad4 = vec4( dotval_1.x, grad_x1.x, grad_y1.x, grad_z1.x );
vec4 dotval5_grad5 = vec4( dotval_1.y, grad_x1.y, grad_y1.y, grad_z1.y );
vec4 dotval6_grad6 = vec4( dotval_1.z, grad_x1.z, grad_y1.z, grad_z1.z );
vec4 dotval7_grad7 = vec4( dotval_1.w, grad_x1.w, grad_y1.w, grad_z1.w );
// evaluate common constants
vec4 k0_gk0 = dotval1_grad1 - dotval0_grad0;
vec4 k1_gk1 = dotval2_grad2 - dotval0_grad0;
vec4 k2_gk2 = dotval4_grad4 - dotval0_grad0;
vec4 k3_gk3 = dotval3_grad3 - dotval2_grad2 - k0_gk0;
vec4 k4_gk4 = dotval5_grad5 - dotval4_grad4 - k0_gk0;
vec4 k5_gk5 = dotval6_grad6 - dotval4_grad4 - k1_gk1;
vec4 k6_gk6 = (dotval7_grad7 - dotval6_grad6) - (dotval5_grad5 - dotval4_grad4) - k3_gk3;
// calculate final noise + deriv
float u = blend.x;
float v = blend.y;
float w = blend.z;
vec4 result = dotval0_grad0
+ u * ( k0_gk0 + v * k3_gk3 )
+ v * ( k1_gk1 + w * k5_gk5 )
+ w * ( k2_gk2 + u * ( k4_gk4 + v * k6_gk6 ) );
result.y += dot( vec4( k0_gk0.x, k3_gk3.x * v, vec2( k4_gk4.x, k6_gk6.x * v ) * w ), vec4( blendDeriv.x ) );
result.z += dot( vec4( k1_gk1.x, k3_gk3.x * u, vec2( k5_gk5.x, k6_gk6.x * u ) * w ), vec4( blendDeriv.y ) );
result.w += dot( vec4( k2_gk2.x, k4_gk4.x * u, vec2( k5_gk5.x, k6_gk6.x * u ) * v ), vec4( blendDeriv.z ) );
return result * 1.1547005383792515290182975610039; // scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
}
vec4 SimplexPerlin3D_Deriv(vec3 P)
{
// https://github.com/BrianSharpe/Wombat/blob/master/SimplexPerlin3D_Deriv.glsl
// simplex math constants
const float SKEWFACTOR = 1.0/3.0;
const float UNSKEWFACTOR = 1.0/6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_TETRAHADRON_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 )
// establish our grid cell.
P *= SIMPLEX_TETRAHADRON_HEIGHT; // scale space so we can have an approx feature size of 1.0
vec3 Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
// Find the vectors to the corners of our simplex tetrahedron
vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 Pi_1 = min( g.xyz, l.zxy );
vec3 Pi_2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
vec3 x3 = x0 - SIMPLEX_CORNER_POS;
// pack them into a parallel-friendly arrangement
vec4 v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
vec4 v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
vec4 v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
// clamp the domain of our grid cell
Pi.xyz = Pi.xyz - floor(Pi.xyz * ( 1.0 / 69.0 )) * 69.0;
vec3 Pi_inc1 = step( Pi, vec3( 69.0 - 1.5 ) ) * ( Pi + 1.0 );
// generate the random vectors
vec4 Pt = vec4( Pi.xy, Pi_inc1.xy ) + vec2( 50.0, 161.0 ).xyxy;
Pt *= Pt;
vec4 V1xy_V2xy = mix( Pt.xyxy, Pt.zwzw, vec4( Pi_1.xy, Pi_2.xy ) );
Pt = vec4( Pt.x, V1xy_V2xy.xz, Pt.z ) * vec4( Pt.y, V1xy_V2xy.yw, Pt.w );
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + Pi.zzz * ZINC.xyz ) );
vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + Pi_inc1.zzz * ZINC.xyz ) );
Pi_1 = ( Pi_1.z < 0.5 ) ? lowz_mods : highz_mods;
Pi_2 = ( Pi_2.z < 0.5 ) ? lowz_mods : highz_mods;
vec4 hash_0 = fract( Pt * vec4( lowz_mods.x, Pi_1.x, Pi_2.x, highz_mods.x ) ) - 0.49999;
vec4 hash_1 = fract( Pt * vec4( lowz_mods.y, Pi_1.y, Pi_2.y, highz_mods.y ) ) - 0.49999;
vec4 hash_2 = fract( Pt * vec4( lowz_mods.z, Pi_1.z, Pi_2.z, highz_mods.z ) ) - 0.49999;
// normalize random gradient vectors
vec4 norm = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 );
hash_0 *= norm;
hash_1 *= norm;
hash_2 *= norm;
// evaluate gradients
vec4 grad_results = hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z;
// evaulate the kernel weights ( use (0.5-x*x)^3 instead of (0.6-x*x)^4 to fix discontinuities )
vec4 m = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
m = max(0.5 - m, 0.0);
vec4 m2 = m*m;
vec4 m3 = m*m2;
// calc the derivatives
vec4 temp = -6.0 * m2 * grad_results;
float xderiv = dot( temp, v1234_x ) + dot( m3, hash_0 );
float yderiv = dot( temp, v1234_y ) + dot( m3, hash_1 );
float zderiv = dot( temp, v1234_z ) + dot( m3, hash_2 );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
// sum and return all results as a vec3
return vec4( dot( m3, grad_results ), xderiv, yderiv, zderiv ) * FINAL_NORMALIZATION;
}
/////////////////////////////
vec3 CalcADS(vec3 norm)
{
vec3 nnorm = normalize(norm);
vec3 s;
if( lightInfo.DirPos.w == 0.0 )
s = normalize(lightInfo.DirPos.xyz);
else
s = normalize(lightInfo.DirPos.xyz - worldFragPos.xyz);
vec3 v = normalize(-worldFragPos.xyz);
vec3 r = reflect( -s, nnorm );
float sDotN = max( dot(s, nnorm), 0.0 );
vec3 Ia = lightInfo.La * materialInfo.Ka;
vec3 Id = lightInfo.Ld * materialInfo.Kd * sDotN;
vec3 Is = vec3(0.0);
if( sDotN > 0.0 )
Is = lightInfo.Ls * materialInfo.Ks * pow( max( dot(r,v), 0.0 ), materialInfo.Shininess );
return Ia + Id + Is;
}
#if 0
#define noise(uvHm) Perlin3D_Deriv(vec3(uvHm, time))
#else
#define noise(uvHm) SimplexPerlin3D_Deriv(vec3(uvHm, time))
#endif
void main()
{
vec4 val;
//val = texture(lavaHeightMapTex, uv);
vec2 uvHm = uv * vec2(64.0);
vec4 pn = noise(uvHm);
#if 0
val = pn.yzwx;
#else
#define offval 0.001
const vec2 off = vec2(offval, 0.0);
const vec2 size = vec2(offval + offval, 0.0);
float s11 = pn.x;
float s01 = noise( uvHm - vec2(-off.x, off.y) ).x;
float s21 = noise( uvHm - vec2( off.x, off.y) ).x;
float s10 = noise( uvHm - vec2( off.y, -off.x) ).x;
float s12 = noise( uvHm - vec2( off.y, off.x) ).x;
vec3 va = normalize(vec3(size.x, s21-s01, size.y));
vec3 vb = normalize(vec3(size.y, s12-s10, -size.x));
val = vec4( cross(va,vb), s11 );
#endif
//val.xyz = normalize(vec3(0.1, 0.8, 0.1));
vec3 lightIntensity = CalcADS(val.xyz);
//gl_FragColor = vec4(val.www, 1.0);
//gl_FragColor = mix(vec4(lightIntensity, 1.0), vec4(val.xyz, 1.0), val.w);
gl_FragColor = vec4(lightIntensity, 1.0);
//gl_FragColor = vec4(val.xyz, 1.0);
}
]]
})
local shLog = gl.GetShaderLog() or ""
if shLog ~= "" then
Spring.Echo("lavaDrawShader warnings/errors\n"..shLog)
end
if lavaDrawShader then
lavaDrawShaderTimeLoc = gl.GetUniformLocation(lavaDrawShader, "time")
lavaDrawShaderCameraPosLoc = gl.GetUniformLocation(lavaDrawShader, "time")
end
return (lavaHeightMapTex ~= nil) and (lavaHeightMapFBO ~= nil) and (lavaHeightMapShader ~= nil) and (lavaDrawShader ~= nil) and gl.IsValidFBO(lavaHeightMapFBO)
end
local saveLavaHeightMapTexOnce = true
local function UpdateLavaHeightMap()
if gl.UseShader(lavaHeightMapShader) then
gl.Uniform(lavaHeightMapShaderTimeLoc, 0.01 * gf)
gl.ActiveFBO(lavaHeightMapFBO, function()
gl.DepthTest(false)
gl.Blending(false)
gl.TexRect(-1, -1, 1, 1)
end)
gl.UseShader(0)
end
end
local function DrawFlatMesh(x1, z1, x2, z2, tiles, uvmul)
local xstep = (x2 - x1) / tiles
local zstep = (z2 - z1) / tiles
for xi = 0, tiles - 1 do
local x = x1 + xi * xstep
for zi = 0, tiles - 1 do
local z = z1 + zi * zstep
--top-left
gl.TexCoord( (xi + 0) / tiles * uvmul, (zi + 0) / tiles * uvmul)
gl.Vertex(x, 0, z)
--top-right
gl.TexCoord( (xi + 1) / tiles * uvmul, (zi + 0) / tiles * uvmul)
gl.Vertex(x + xstep, 0, z)
--bottom-right
gl.TexCoord( (xi + 1) / tiles * uvmul, (zi + 1) / tiles * uvmul)
gl.Vertex(x + xstep, 0, z + zstep)
--bottom-left
gl.TexCoord( (xi + 0) / tiles * uvmul, (zi + 1) / tiles * uvmul)
gl.Vertex(x, 0, z + zstep)
end
end
end
local function InitLavaSurfaceDrawList()
lavaSurfaceDrawList = gl.CreateList(function ()
gl.BeginEnd(GL.QUADS, DrawFlatMesh, -2*Game.mapX*512, -2*Game.mapY*512, 3*Game.mapX*512, 3*Game.mapY*512, 512, 1)
end)
end
function gadget:DrawGenesis()
if not lavaSurfaceDrawList then
InitLavaSurfaceDrawList()
end
UpdateLavaHeightMap()
end
function gadget:DrawWorldPreUnit()
gl.DepthTest(true)
gl.DepthMask(true)
if gl.Texture(0, lavaHeightMapTex) then
if gl.UseShader(lavaDrawShader) then
gl.Uniform(lavaDrawShaderTimeLoc, 0.01 * gf)
local cx, cy, cz = Spring.GetCameraPosition()
gl.Uniform(lavaDrawShaderCameraPosLoc, cx, cy, cz)
gl.CallList(lavaSurfaceDrawList)
gl.UseShader(0)
end
gl.Texture(0, false)
end
gl.DepthTest(false)
gl.DepthMask(false)
end
function gadget:GameFrame(frame)
gf = frame
end
function gadget:Initialize()
if not InitLavaHeightMap() then
Spring.Echo("Failed to InitLavaHeightMap()")
gadgetHandler:RemoveGadget()
end
end
function gadget:Shutdown()
if (lavaSurfaceDrawList) then
gl.DeleteList(lavaSurfaceDrawList)
end
if (lavaHeightMapTex) then
gl.DeleteTextureFBO(lavaHeightMapTex)
end
if (lavaHeightMapFBO) then
gl.DeleteFBO(lavaHeightMapFBO)
end
if (lavaHeightMapShader) then
gl.DeleteShader(lavaHeightMapShader)
end
if (lavaDrawShader) then
gl.DeleteShader(lavaDrawShader)
end
end
end --- UNSYCNED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment