diff --git a/nodes/shadertoy.lua b/nodes/shadertoy.lua new file mode 100644 index 0000000..af0e3b7 --- /dev/null +++ b/nodes/shadertoy.lua @@ -0,0 +1,118 @@ +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.path = self.path or "test.glsl" + self.resolution = self.resolution or {1280, 720} + + self:loadShader() +end + +function node:beforeEnter() + self:loadShader() +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 = love.filesystem.newFile(self.path) + file:open("r") + local shaderData = file:read() + + 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') + + self.shaderLoadError = nil + shaderLoaded, self.shader = pcall(love.graphics.newShader, shaderData) + if not shaderLoaded then + print('Shader load failed:', self.shader) + self.shaderLoadError = self.shader + self.shader = nil + else + print(shaderLoaded, self.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.shaderLoadError ~= nil then + print('render!') + 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'); + elseif 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 +end + +return node