From 9fd9a6cc4a243543b41408b911607aff7d233241 Mon Sep 17 00:00:00 2001 From: DarkGod <darkgod@net-core.org> Date: Wed, 12 Feb 2014 01:19:43 +0100 Subject: [PATCH] All fullscreen effects can be enabled at once now (underwater, blur, wobbling, ...) --- game/modules/tome/class/Game.lua | 9 +- game/modules/tome/class/Player.lua | 25 +-- .../tome/data/gfx/shaders/main_fbo.frag | 88 ---------- .../tome/data/gfx/shaders/main_fbo/blur.frag | 25 +++ .../tome/data/gfx/shaders/main_fbo/blur.lua | 28 +++ .../data/gfx/shaders/main_fbo/motionblur.frag | 69 ++++++++ .../data/gfx/shaders/main_fbo/motionblur.lua | 28 +++ .../data/gfx/shaders/main_fbo/underwater.frag | 84 +++++++++ .../data/gfx/shaders/main_fbo/underwater.lua | 28 +++ .../data/gfx/shaders/main_fbo/wobbling.frag | 165 ++++++++++++++++++ .../data/gfx/shaders/main_fbo/wobbling.lua | 29 +++ src/core_lua.c | 90 ++++++++++ 12 files changed, 567 insertions(+), 101 deletions(-) create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/blur.frag create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/blur.lua create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/motionblur.frag create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/motionblur.lua create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/underwater.frag create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/underwater.lua create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/wobbling.frag create mode 100644 game/modules/tome/data/gfx/shaders/main_fbo/wobbling.lua diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 7383250a01..c6e2337a50 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -514,6 +514,13 @@ function _M:createFBOs() self.fbo = core.display.newFBO(Map.viewport.width, Map.viewport.height) if self.fbo then self.fbo_shader = Shader.new("main_fbo") + self.posteffects = { + wobbling = Shader.new("main_fbo/wobbling"), + underwater = Shader.new("main_fbo/underwater"), + motionblur = Shader.new("main_fbo/motionblur"), + blur = Shader.new("main_fbo/blur"), + } + self.posteffects_use = { self.fbo_shader.shad } if not self.fbo_shader.shad then self.fbo = nil self.fbo_shader = nil end self.fbo2 = core.display.newFBO(Map.viewport.width, Map.viewport.height) end @@ -1392,7 +1399,7 @@ function _M:displayMap(nb_keyframes) self.fbo2:use(false, self.full_fbo) _2DNoise:bind(1, false) - self.fbo2:toScreen(map.display_x, map.display_y, map.viewport.width, map.viewport.height, self.fbo_shader.shad) + self.fbo2:postEffects(self.fbo, self.full_fbo, map.display_x, map.display_y, map.viewport.width, map.viewport.height, unpack(self.posteffects_use)) if self.target then self.target:display(nil, nil, self.full_fbo, nb_keyframes) end -- Basic display; no FBOs diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index ad6259aaf3..b29488f322 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -374,6 +374,9 @@ end --- Funky shader stuff function _M:updateMainShader() if game.fbo_shader then + local effects = {} + local pf = game.posteffects + -- Set shader HP warning if self.life ~= self.shader_old_life then if self.life < self.max_life / 2 then game.fbo_shader:setUniform("hp_warning", 1 - (self.life / self.max_life)) @@ -408,28 +411,26 @@ function _M:updateMainShader() end -- Blur shader - if self:attr("confused") and self.confused >= 1 then game.fbo_shader:setUniform("blur", 2) --- elseif game:hasDialogUp() then game.fbo_shader:setUniform("blur", 3) - else game.fbo_shader:setUniform("blur", 0) -- Disable + if self:attr("confused") and self.confused >= 1 then pf.blur.shad:uniBlur(2) effects[pf.blur.shad] = true end -- Moving Blur shader - if self:attr("invisible") then game.fbo_shader:setUniform("motionblur", 3) - elseif self:attr("lightning_speed") then game.fbo_shader:setUniform("motionblur", 2) - elseif game.level and game.level.data and game.level.data.motionblur then game.fbo_shader:setUniform("motionblur", game.level.data.motionblur) - else game.fbo_shader:setUniform("motionblur", 0) -- Disable + if self:attr("invisible") then pf.motionblur.shad:uniMotionblur(3) effects[pf.motionblur.shad] = true + elseif self:attr("lightning_speed") then pf.motionblur.shad:uniMotionblur(2) effects[pf.motionblur.shad] = true + elseif game.level and game.level.data and game.level.data.motionblur then pf.motionblur.shad:uniMotionblur(game.level.data.motionblur) effects[pf.motionblur.shad] = true end -- Underwater shader - if game.level and game.level.data and game.level.data.underwater then game.fbo_shader:setUniform("underwater", 1) - else game.fbo_shader:setUniform("underwater", 0) -- Disable + if game.level and game.level.data and game.level.data.underwater then effects[pf.underwater.shad] = true end -- Wobbling shader - if self:attr("stunned") and self.stunned >= 1 then game.fbo_shader:setUniform("wobbling", 1) - elseif self:attr("dazed") and self.dazed >= 1 then game.fbo_shader:setUniform("wobbling", 0.7) - else game.fbo_shader:setUniform("wobbling", 0) -- Disable + if self:attr("stunned") and self.stunned >= 1 then pf.wobbling.shad:uniWobbling(1) effects[pf.wobbling.shad] = true + elseif self:attr("dazed") and self.dazed >= 1 then pf.wobbling.shad:uniWobbling(0.7) effects[pf.wobbling.shad] = true end + + game.posteffects_use = table.keys(effects) + game.posteffects_use[#game.posteffects_use+1] = game.fbo_shader.shad end end diff --git a/game/modules/tome/data/gfx/shaders/main_fbo.frag b/game/modules/tome/data/gfx/shaders/main_fbo.frag index 4eb1a25d3e..cb595315d4 100644 --- a/game/modules/tome/data/gfx/shaders/main_fbo.frag +++ b/game/modules/tome/data/gfx/shaders/main_fbo.frag @@ -271,30 +271,6 @@ void main(void) sample /= (blur*2.0) * (blur*2.0); gl_FragColor = sample; } - else if (underwater > 0.0) - { - vec2 p = (vec2(gl_FragCoord.x - mapCoord.x, texSize.y - gl_FragCoord.y - mapCoord.y)) / texSize.xy, c1 = p, c2 = p; - float cc1 = col(c1); - - c2.x += texSize.x/delta; - float dx = emboss*(cc1-col(c2))/delta; - - c2.x = p.x; - c2.y += texSize.y/delta; - float dy = emboss*(cc1-col(c2))/delta; - - c1.x += dx*2.; - c1.y = -(c1.y+dy*2.); - - float alpha = 1.+dot(dx,dy)*intence; - - float ddx = dx - reflectionCutOff; - float ddy = dy - reflectionCutOff; - if (ddx > 0. && ddy > 0.) alpha = pow(alpha, ddx*ddy*reflectionIntence); - - vec4 col = texture2D(tex,c1)*(alpha); - gl_FragColor = col; - } if (colorize.r > 0.0 || colorize.g > 0.0 || colorize.b > 0.0) { @@ -335,67 +311,3 @@ void main(void) gl_FragColor = mix(gl_FragColor, solipsism_warning_color, dist); } } - -/*uniform sampler2D tex; -uniform vec2 texSize; -int blursize = 5; - -void main(void) -{ - vec2 offset = 1.0/texSize; - - // Center Pixel - vec4 sample = vec4(0.0,0.0,0.0,0.0); - float factor = ((float(blursize)*2.0)+1.0); - factor = factor*factor; - - for(int i = -blursize; i <= blursize; i++) - { - for(int j = -blursize; j <= blursize; j++) - { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); - } - } - sample /= float((blursize*2) * (blursize*2)); - - float grey = sample.r*0.3+sample.g*0.59+sample.b*0.11; - vec3 color = vec3(1, 0, 0); - gl_FragColor = vec4(vec3(color*grey),1.0); -} -*/ -/* -uniform sampler2D tex; -uniform sampler3D noiseVol; -uniform float tick; -float do_blur = 3.0; -uniform vec2 texSize; - -void main(void) -{ - if (do_blur > 0.0) - { - vec2 offset = 1.0/texSize; - offset.y += texture3D(noiseVol, vec3(gl_TexCoord[0].xy, tick/100000))/30; - - // Center Pixel - vec4 sample = vec4(0.0,0.0,0.0,0.0); - float factor = ((float(do_blur)*2.0)+1.0); - factor = factor*factor; - - for(int i = -do_blur; i <= do_blur; i++) - { - for(int j = -do_blur; j <= do_blur; j++) - { - sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); - } - } - sample /= float((do_blur*2) * (do_blur*2)); - - gl_FragColor = sample; - } - - float grey = gl_FragColor.r*0.3+gl_FragColor.g*0.59+gl_FragColor.b*0.11; - vec3 color = vec3(1, 0, 0); - gl_FragColor = vec4(vec3(color*grey),1.0); -} -*/ diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/blur.frag b/game/modules/tome/data/gfx/shaders/main_fbo/blur.frag new file mode 100644 index 0000000000..492d77f4f3 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/blur.frag @@ -0,0 +1,25 @@ +uniform float blur; +uniform float tick; +uniform vec2 texSize; +uniform sampler2D tex; + +void main(void) +{ + int blursize = int(blur); + vec2 offset = 1.0/texSize; + + // Center Pixel + vec4 sample = vec4(0.0,0.0,0.0,0.0); + float factor = ((float(blursize)*2.0)+1.0); + factor = factor*factor; + + for(int i = -blursize; i <= blursize; i++) + { + for(int j = -blursize; j <= blursize; j++) + { + sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + } + } + sample /= (blur*2.0) * (blur*2.0); + gl_FragColor = sample; +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/blur.lua b/game/modules/tome/data/gfx/shaders/main_fbo/blur.lua new file mode 100644 index 0000000000..08847b5d91 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/blur.lua @@ -0,0 +1,28 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +return { + frag = "main_fbo/blur", + vert = nil, + args = { + tex = { texture = 0 }, + }, + clone = false, + permanent = true, +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.frag b/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.frag new file mode 100644 index 0000000000..508bb84284 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.frag @@ -0,0 +1,69 @@ +uniform float motionblur; +uniform float tick; +uniform sampler2D noisevol; +uniform vec2 texSize; +uniform sampler2D tex; +uniform vec2 mapCoord; + +void main(void) +{ + gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); + + int blursize = int(motionblur); + vec2 offset = 0.8/texSize; + + float fTime0_X = tick / 20000.0; + float coord = gl_TexCoord[0].x + gl_TexCoord[0].y * texSize[0]; + float noisy1 = texture2D(noisevol,vec2(coord,fTime0_X)).r; + float noisy2 = texture2D(noisevol,vec2(coord/5.0,fTime0_X/1.5)).r; + float noisy3 = texture2D(noisevol,vec2(coord/7.0,fTime0_X/2.0)).r; + float noisy = (noisy1+noisy2+noisy3)/3.0; + + // Center Pixel + vec4 sample = vec4(0.0,0.0,0.0,0.0); + float factor = ((float(blursize)*2.0)+1.0); + factor = factor*factor; + + if (noisy < 0.25) + { + for(int i = -blursize; i <= 0; i++) + { + for(int j = -blursize; j <= 0; j++) + { + sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + } + } + } + else if (noisy < 0.50) + { + for(int i = 0; i <= blursize; i++) + { + for(int j = 0; j <= blursize; j++) + { + sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + } + } + } + else if (noisy < 0.75) + { + for(int i = 0; i <= blursize; i++) + { + for(int j = -blursize; j <= 0; j++) + { + sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + } + } + } + else + { + for(int i = -blursize; i <= 0; i++) + { + for(int j = 0; j <= blursize; j++) + { + sample += texture2D(tex, vec2(gl_TexCoord[0].xy+vec2(float(i)*offset.x, float(j)*offset.y))); + } + } + } + sample /= float((motionblur*1.5) * (motionblur*0.5)); + gl_FragColor = sample; +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.lua b/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.lua new file mode 100644 index 0000000000..4ca6ca12c3 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/motionblur.lua @@ -0,0 +1,28 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +return { + frag = "main_fbo/motionblur", + vert = nil, + args = { + tex = { texture = 0 }, + }, + clone = false, + permanent = true, +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/underwater.frag b/game/modules/tome/data/gfx/shaders/main_fbo/underwater.frag new file mode 100644 index 0000000000..ba413ab5f6 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/underwater.frag @@ -0,0 +1,84 @@ +uniform float tick; +uniform vec2 texSize; +uniform sampler2D tex; + +// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012. +// +// Attribution-ShareAlike CC License. + +#ifdef GL_ES +precision highp float; +#endif + +uniform vec2 mapCoord; + +const float PI = 3.1415926535897932; + +// play with these parameters to custimize the effect +// =================================================== + +//speed +const float speed = 0.05; +const float speed_x = 0.3; +const float speed_y = 0.3; + +// refraction +const float emboss = 0.05; +const float intensity = 0.4; +const int steps = 6; +const float frequency = 100.0; +const int angle = 7; // better when a prime + +// reflection +const float delta = 60.; +const float intence = 700.; + +const float reflectionCutOff = 0.012; +const float reflectionIntence = 200000.; + +// =================================================== + +float time = tick / 30000.0; + +float col(vec2 coord) +{ + float delta_theta = 2.0 * PI / float(angle); + float col = 0.0; + float theta = 0.0; + for (int i = 0; i < steps; i++) + { + vec2 adjc = coord; + theta = delta_theta*float(i); + adjc.x += cos(theta)*time*speed + time * speed_x; + adjc.y -= sin(theta)*time*speed - time * speed_y; + col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity; + } + + return cos(col); +} + +void main(void) +{ + gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); + vec2 p = (vec2(gl_FragCoord.x - mapCoord.x, texSize.y - gl_FragCoord.y - mapCoord.y)) / texSize.xy, c1 = p, c2 = p; + float cc1 = col(c1); + + c2.x += texSize.x/delta; + float dx = emboss*(cc1-col(c2))/delta; + + c2.x = p.x; + c2.y += texSize.y/delta; + float dy = emboss*(cc1-col(c2))/delta; + + c1.x += dx*2.; + c1.y = -(c1.y+dy*2.); + + float alpha = 1.+dot(dx,dy)*intence; + + float ddx = dx - reflectionCutOff; + float ddy = dy - reflectionCutOff; + if (ddx > 0. && ddy > 0.) alpha = pow(alpha, ddx*ddy*reflectionIntence); + + vec4 col = texture2D(tex,c1)*(alpha); + gl_FragColor = col; +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/underwater.lua b/game/modules/tome/data/gfx/shaders/main_fbo/underwater.lua new file mode 100644 index 0000000000..75f8754ef3 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/underwater.lua @@ -0,0 +1,28 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +return { + frag = "main_fbo/underwater", + vert = nil, + args = { + tex = { texture = 0 }, + }, + clone = false, + permanent = true, +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.frag b/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.frag new file mode 100644 index 0000000000..b00ca0cb3c --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.frag @@ -0,0 +1,165 @@ +uniform float wobbling; +uniform float tick; +uniform sampler2D noisevol; +uniform vec2 texSize; +uniform sampler2D tex; +uniform vec2 mapCoord; + +const float PI = 3.1415926535897932; + +// play with these parameters to custimize the effect +// =================================================== + +//speed +const float speed = 0.05; +const float speed_x = 0.3; +const float speed_y = 0.3; + +// refraction +const float emboss = 0.05; +const float intensity = 0.4; +const int steps = 6; +const float frequency = 100.0; +const int angle = 7; // better when a prime + +// reflection +const float delta = 60.; +const float intence = 700.; + +const float reflectionCutOff = 0.012; +const float reflectionIntence = 200000.; + +float time = tick / 30000.0; + +float col(vec2 coord) +{ + float delta_theta = 2.0 * PI / float(angle); + float col = 0.0; + float theta = 0.0; + for (int i = 0; i < steps; i++) + { + vec2 adjc = coord; + theta = delta_theta*float(i); + adjc.x += cos(theta)*time*speed + time * speed_x; + adjc.y -= sin(theta)*time*speed - time * speed_y; + col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity; + } + + return cos(col); +} + +vec4 permute( vec4 x ) { + + return mod( ( ( x * 34.0 ) + 1.0 ) * x, 289.0 ); + +} + +vec4 taylorInvSqrt( vec4 r ) { + + return 1.79284291400159 - 0.85373472095314 * r; + +} + +float snoise( vec3 v ) { + + const vec2 C = vec2( 1.0 / 6.0, 1.0 / 3.0 ); + const vec4 D = vec4( 0.0, 0.5, 1.0, 2.0 ); + + // First corner + + vec3 i = floor( v + dot( v, C.yyy ) ); + vec3 x0 = v - i + dot( i, C.xxx ); + + // Other corners + + vec3 g = step( x0.yzx, x0.xyz ); + vec3 l = 1.0 - g; + vec3 i1 = min( g.xyz, l.zxy ); + vec3 i2 = max( g.xyz, l.zxy ); + + vec3 x1 = x0 - i1 + 1.0 * C.xxx; + vec3 x2 = x0 - i2 + 2.0 * C.xxx; + vec3 x3 = x0 - 1. + 3.0 * C.xxx; + + // Permutations + + i = mod( i, 289.0 ); + vec4 p = permute( permute( permute( + i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) ) + + i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) ) + + i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) ); + + // Gradients + // ( N*N points uniformly over a square, mapped onto an octahedron.) + + float n_ = 1.0 / 7.0; // N=7 + + vec3 ns = n_ * D.wyz - D.xzx; + + vec4 j = p - 49.0 * floor( p * ns.z *ns.z ); // mod(p,N*N) + + vec4 x_ = floor( j * ns.z ); + vec4 y_ = floor( j - 7.0 * x_ ); // mod(j,N) + + vec4 x = x_ *ns.x + ns.yyyy; + vec4 y = y_ *ns.x + ns.yyyy; + vec4 h = 1.0 - abs( x ) - abs( y ); + + vec4 b0 = vec4( x.xy, y.xy ); + vec4 b1 = vec4( x.zw, y.zw ); + + + vec4 s0 = floor( b0 ) * 2.0 + 1.0; + vec4 s1 = floor( b1 ) * 2.0 + 1.0; + vec4 sh = -step( h, vec4( 0.0 ) ); + + vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; + vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; + + vec3 p0 = vec3( a0.xy, h.x ); + vec3 p1 = vec3( a0.zw, h.y ); + vec3 p2 = vec3( a1.xy, h.z ); + vec3 p3 = vec3( a1.zw, h.w ); + + // Normalise gradients + + vec4 norm = taylorInvSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) ); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + + vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 ); + m = m * m; + return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ), + dot( p2, x2 ), dot( p3, x3 ) ) ); + +} + + +vec2 snoise2(vec3 pos) +{ + return vec2(snoise(pos), snoise(pos + vec3(0.0, 0.0, 1.0))); +} + +void main(void) +{ + float scaledTime = tick / 5000.0; + vec2 coord = gl_TexCoord[0].xy; + coord.x *= texSize.x / texSize.y; + vec2 offset = + snoise2(vec3(coord / 2.0, scaledTime / 0.25)) * 0.33 * 3.0 + + snoise2(vec3(coord / 2.0, scaledTime / 2.0)) * 0.0 + + snoise2(vec3(coord / 4.0, scaledTime / 4.0)) * 0.0; + + offset.x *= texSize.x / texSize.y; + + float ratio = clamp(1.5 * pow(length(vec2(0.5, 0.5) - gl_TexCoord[0].xy) / (0.7071), 2.0), 0.0, 1.0); //sqrt(2) / 2 = 0.7071 + ratio *= (1.0 + snoise2(vec3(coord / 2.0, scaledTime / 0.25 + 10.0))) * 0.5; + + gl_FragColor = + texture2D(tex, gl_TexCoord[0].xy) * (1.0 - ratio) + + texture2D(tex, gl_TexCoord[0].xy + offset * 0.01 * wobbling) * ratio; +} diff --git a/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.lua b/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.lua new file mode 100644 index 0000000000..3f16a9ff41 --- /dev/null +++ b/game/modules/tome/data/gfx/shaders/main_fbo/wobbling.lua @@ -0,0 +1,29 @@ +-- ToME - Tales of Maj'Eyal +-- Copyright (C) 2009 - 2014 Nicolas Casalini +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-- Nicolas Casalini "DarkGod" +-- darkgod@te4.org + +return { + frag = "main_fbo/wobbling", + vert = nil, + args = { + tex = { texture = 0 }, + noisevol = { texture = 1 }, + }, + clone = false, + permanent = true, +} diff --git a/src/core_lua.c b/src/core_lua.c index 57cf4951d9..b5047a9e43 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -2665,6 +2665,95 @@ static int gl_fbo_toscreen(lua_State *L) return 0; } +static int gl_fbo_posteffects(lua_State *L) +{ + lua_fbo *fbo = (lua_fbo*)auxiliar_checkclass(L, "gl{fbo}", 1); + lua_fbo *fbo2 = (lua_fbo*)auxiliar_checkclass(L, "gl{fbo}", 2); + lua_fbo *fbo_final = (lua_fbo*)auxiliar_checkclass(L, "gl{fbo}", 3); + lua_fbo *tmpfbo; + lua_fbo *srcfbo = fbo; + lua_fbo *dstfbo = fbo2; + int x = luaL_checknumber(L, 4); + int y = luaL_checknumber(L, 5); + int w = luaL_checknumber(L, 6); + int h = luaL_checknumber(L, 7); + + glDisable(GL_BLEND); + + GLfloat colors[4*4] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + }; + glColorPointer(4, GL_FLOAT, 0, colors); + + GLfloat texcoords[2*4] = { + 0, 1, + 0, 0, + 1, 0, + 1, 1, + }; + glTexCoordPointer(2, GL_FLOAT, 0, texcoords); + + GLfloat vertices[2*4] = { + 0, 0, + 0, h, + w, h, + w, 0, + }; + glVertexPointer(2, GL_FLOAT, 0, vertices); + + // Set the viewport and save the old one + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, fbo->w, fbo->h); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, fbo->w, fbo->h, 0, -1001, 1001); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + tglClearColor(0, 0, 0, 1); + + int shad_idx = 8; + while (lua_isuserdata(L, shad_idx) && lua_isuserdata(L, shad_idx+1)) { + shader_type *s = (shader_type*)lua_touserdata(L, shad_idx); + useShader(s, fbo->w, fbo->h, w, h, 1, 1, 1, 1); + + tglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstfbo->fbo); + glClear(GL_COLOR_BUFFER_BIT); + tglBindTexture(GL_TEXTURE_2D, srcfbo->texture); + glDrawArrays(GL_QUADS, 0, 4); + + shad_idx++; + tmpfbo = srcfbo; + srcfbo = dstfbo; + dstfbo = tmpfbo; + } + + // Bind final fbo (must have bee previously activated) + shader_type *s = (shader_type*)lua_touserdata(L, shad_idx); + useShader(s, fbo_final->w, fbo_final->h, w, h, 1, 1, 1, 1); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopAttrib(); + tglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_final->fbo); + glClear(GL_COLOR_BUFFER_BIT); + tglBindTexture(GL_TEXTURE_2D, srcfbo->texture); + vertices[0] = x; vertices[1] = y; + vertices[2] = x; vertices[3] = y + h; + vertices[4] = x + w; vertices[5] = y + h; + vertices[6] = x + w; vertices[7] = y; + glDrawArrays(GL_QUADS, 0, 4); + + tglUseProgramObject(0); + + glEnable(GL_BLEND); + return 0; +} + static int gl_fbo_is_active(lua_State *L) { lua_pushboolean(L, fbo_active); @@ -3051,6 +3140,7 @@ static const struct luaL_Reg gl_fbo_reg[] = { {"__gc", gl_free_fbo}, {"toScreen", gl_fbo_toscreen}, + {"postEffects", gl_fbo_posteffects}, {"use", gl_fbo_use}, {"png", gl_fbo_to_png}, {NULL, NULL}, -- GitLab