local node = Node:extend('nodes.shadertoy', {}) local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 20) function node:init(config) node.super.init(self, config) self.prevShaderData = nil self.path = self.path or "test.glsl" self.resolution = self.resolution or {1280, 720} self:loadShader() end function node:beforeEnter() self:loadShader() if self.iSystem and self.iSystem.iGlobalTime then print("Resetting time") self.iSystem.iGlobalTime = 0 end end function node:loadShader() local iSystem = {} local header = "" local ender=[[ vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) { vec2 fragCoord = texture_coords * iResolution.xy; mainImage( color, fragCoord ); return color; } ]] local file = io.open(self.path, "r") if file == nil then self.shaderLoadError = self.path .. " does not exist" return end local shaderData = file:read("*all") if self.prevShaderData == shaderData then print("Shader didn't change, not reloading") return end self.prevShaderData = shaderData shaderData = string.gsub(shaderData,"texture2D","Texel") shaderData = string.gsub(shaderData,"iTime","iGlobalTime") shaderData = string.gsub(shaderData,"precision highp float;","") if string.find(shaderData,"iGlobalTime") then iSystem.iGlobalTime=0 if not string.find(shaderData,"number iGlobalTime") then header="extern number iGlobalTime;\n"..header end end -- TODO -- if string.find(shaderData,"iChannel") then -- iSystem.iChannel={} -- for k,v in pairs(shaderChannel) do -- header="extern Image iChannel"..k..";\n"..header -- end -- end if string.find(shaderData,"iMouse") then iSystem.iMouse = {0, 0, -1, -1} header = "extern vec4 iMouse;\n"..header end if string.find(shaderData,"iResolution") then iSystem.iResolution = {self.resolution[1], self.resolution[2],1} header = "extern vec3 iResolution;\n"..header end shaderData = header..shaderData if not string.find(shaderData,"vec4 effect") then shaderData = shaderData.."\n"..ender end print("Shader loaded, compiling...") self.shaderLoadError = nil shaderLoaded, shader = pcall(love.graphics.newShader, shaderData) if not shaderLoaded then print("Shader compile failed:", shader) self.shaderLoadError = shader else self.shader = shader if iSystem.iResolution then self.shader:send("iResolution",iSystem.iResolution) end self.iSystem = iSystem self.canvas = love.graphics.newCanvas(self.resolution[1], self.resolution[2]) self.renderCanvas = love.graphics.newCanvas(self.resolution[1], self.resolution[2]) end end function node:update(dt) if self.shader ~= nil then if self.iSystem.iGlobalTime then self.iSystem.iGlobalTime=self.iSystem.iGlobalTime+dt self.shader:send("iGlobalTime", self.iSystem.iGlobalTime) end end end function node:render() love.graphics.setColor( 0, 0, 0 ) love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight()) if self.shader ~= nil then oldCanvas = love.graphics.getCanvas( ) love.graphics.setColor( 1.0, 1.0, 1.0 ) self.canvas:renderTo(function () love.graphics.setShader(self.shader) love.graphics.draw(self.renderCanvas) love.graphics.setShader() end) love.graphics.setCanvas(oldCanvas) love.graphics.draw(self.canvas,0,0,math.pi,love.graphics.getWidth() / self.resolution[1], love.graphics.getHeight() / self.resolution[2], self.resolution[1], self.resolution[2]) end if self.shaderLoadError ~= nil then love.graphics.setColor(1.0, 0.0, 0.0, 1.0) love.graphics.setFont(smallFont) love.graphics.printf(self.shaderLoadError, 0, 0.1*love.graphics.getHeight(), love.graphics.getWidth(), 'left'); end end return node