Automatically reloading GLSL shaders when coding widgets

Automatically reloading GLSL shaders when coding widgets

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
Beherith
Moderator
Posts: 5126
Joined: 26 Oct 2007, 16:21

Automatically reloading GLSL shaders when coding widgets

Post by Beherith »

Wouldnt it be nice if a widget would automatically detect changes to the code of a widget, recompile it and apply it upon success?

This code checks the shader sources every 0.25s, and tries to recompile it. So you can have Spring open in one window, your editor in the next, and just have to hit save on the shader code changes!

All the needed bits of this are supplied by the engine, so here is a bit of example code how:

Code: Select all



local luaShaderDir = "LuaUI/Widgets/Include/"
local LuaShader = VFS.Include(luaShaderDir.."LuaShader.lua")

local vsSrcPath = "LuaUI/Widgets/Shaders/decals_gl4.vert.glsl"
local fsSrcPath = "LuaUI/Widgets/Shaders/decals_gl4.frag.glsl"
local gsSrcPath = "LuaUI/Widgets/Shaders/decals_gl4.geom.glsl"

local lastshaderupdate = nil
local shaderSourceCache = {}
local function checkShaderUpdates(vssrcpath, fssrcpath, gssrcpath, shadername, delaytime)
	if lastshaderupdate == nil or 
		Spring.DiffTimers(Spring.GetTimer(), lastshaderupdate) > (delaytime or 0.25) then 
		lastshaderupdate = Spring.GetTimer()
		local vsSrcNew = vssrcpath and VFS.LoadFile(vssrcpath)
		local fsSrcNew = fssrcpath and VFS.LoadFile(fssrcpath)
		local gsSrcNew = gssrcpath and VFS.LoadFile(gssrcpath)
		if  vsSrcNew == shaderSourceCache.vsSrc and 
			fsSrcNew == shaderSourceCache.fsSrc and 
			gsSrcNew == shaderSourceCache.gsSrc then 
			--Spring.Echo("No change in shaders")
			return nil
		else
			local compilestarttime = Spring.GetTimer()
			shaderSourceCache.vsSrc = vsSrcNew
			shaderSourceCache.fsSrc = fsSrcNew
			shaderSourceCache.gsSrc = gsSrcNew
			
			local engineUniformBufferDefs = LuaShader.GetEngineUniformBufferDefs()
			if vsSrcNew then 
				vsSrcNew = vsSrcNew:gsub("//__ENGINEUNIFORMBUFFERDEFS__", engineUniformBufferDefs)
				vsSrcNew = vsSrcNew:gsub("//__DEFINES__", LuaShader.CreateShaderDefinesString(shaderConfig))
			end
			if fsSrcNew then 
				fsSrcNew = fsSrcNew:gsub("//__ENGINEUNIFORMBUFFERDEFS__", engineUniformBufferDefs)
				fsSrcNew = fsSrcNew:gsub("//__DEFINES__", LuaShader.CreateShaderDefinesString(shaderConfig))
			end
			if gsSrcNew then 
				gsSrcNew = gsSrcNew:gsub("//__ENGINEUNIFORMBUFFERDEFS__", engineUniformBufferDefs)
				gsSrcNew = gsSrcNew:gsub("//__DEFINES__", LuaShader.CreateShaderDefinesString(shaderConfig))
			end
			local reinitshader =  LuaShader(
				{
				vertex = vsSrcNew,
				fragment = fsSrcNew,
				geometry = gsSrcNew,
				uniformInt = {
					heightmapTex = 0,
					miniMapTex = 1,
					},
				uniformFloat = {
					fadeDistance = 3000,
				  },
				},
				shadername
			)
			local shaderCompiled = reinitshader:Initialize()
			
			
			Spring.Echo(shadername, " recompiled in ", Spring.DiffTimers(Spring.GetTimer(), compilestarttime, true), "ms at", Spring.GetGameFrame())
			if shaderCompiled then 
				return reinitshader
			else
				return nil
			end
		end
	end
	return nil
end

function widget:Update()
	decalShader = checkShaderUpdates(vsSrcPath, fsSrcPath, gsSrcPath, "Decals GL4") or decalShader
end


function widget:Initialize()
	decalShader = checkShaderUpdates(vsSrcPath, fsSrcPath, gsSrcPath, "Decals GL4") or decalShader
end
gajop
Moderator
Posts: 3049
Joined: 05 Aug 2009, 20:42

Re: Automatically reloading GLSL shaders when coding widgets

Post by gajop »

If you use spring-launcher, with https://github.com/gajop/springmon you can get that for any single-file widget & gadget
User avatar
Beherith
Moderator
Posts: 5126
Joined: 26 Oct 2007, 16:21

Re: Automatically reloading GLSL shaders when coding widgets

Post by Beherith »

Ok, that is honestly much better than what I'm doing, with major difference that mine doesnt reload the widget, _only_ the shader code, and it only replaces the existing shader if the compilation succeeded.
Post Reply

Return to “Lua Scripts”