| 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 |