From 8b113323dc698eba3b7988a95a0be1dbf0aae7a3 Mon Sep 17 00:00:00 2001 From: Alexander Taylor Date: Sat, 15 Feb 2014 01:18:18 +0000 Subject: [PATCH] Added new effects and improved example --- examples/widgets/effectwidget.py | 126 +++++++++++++++++++++++++------ kivy/uix/effectwidget.py | 94 +++++++++++++++++++++-- 2 files changed, 193 insertions(+), 27 deletions(-) diff --git a/examples/widgets/effectwidget.py b/examples/widgets/effectwidget.py index be6a91f00..ded4577fb 100644 --- a/examples/widgets/effectwidget.py +++ b/examples/widgets/effectwidget.py @@ -20,6 +20,10 @@ from kivy.uix.effectwidget import (effect_monochrome, effect_blue, effect_green, effect_invert, + effect_mix, + effect_flash, + effect_blur_h, + effect_blur_v, effect_plasma) class EffectSpinner(Spinner): @@ -43,40 +47,115 @@ class SpinnerRow(BoxLayout): effects.append(effect_green) if text == 'invert': effects.append(effect_invert) + if text == 'mix': + effects.append(effect_mix) + if text == 'flash': + effects.append(effect_flash) + if text == 'blur_h': + effects.append(effect_blur_h) + if text == 'blur_v': + effects.append(effect_blur_v) if text == 'plasma': effects.append(effect_plasma) if self.effectwidget: self.effectwidget.effects = effects example = Builder.load_string(''' +#:import Vector kivy.vector.Vector BoxLayout: orientation: 'vertical' BoxLayout: EffectWidget: id: effect1 - Image: - size_hint: 1, 1 - pos_hint: {'x': 0, 'y': 0} - source: 'colours.png' - allow_stretch: True - keep_ratio: False - Button: - text: 'Hello world' - size_hint: None, None - size: 150, 100 - pos_hint: {'center_x': 0.25, 'center_y': 0.5} - on_press: print('Button pressed!') + Widget: + canvas: + Color: + rgba: 1, 0, 0, 1 + Ellipse: + pos: Vector(self.pos) + 0.5*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 1, 0.3, 1 + Ellipse: + pos: Vector(self.pos) + 0.1*Vector(self.size) + size: 0.6*Vector(self.size) + Color: + rgba: 0.5, 0.5, 0.2, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0, 0.6])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 1, 0.8, 0.1, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0.5, 0])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 0, 0.8, 1 + Line: + points: + [self.x, self.y, + self.x + self.width, self.y + 0.3*self.height, + self.x + 0.2*self.width, self.y + 0.1*self.height, + self.x + 0.85*self.width, self.y + 0.72*self.height, + self.x + 0.31*self.width, self.y + 0.6*self.height, + self.x, self.top] + width: 1 + Color: + rgba: 0, 0.9, 0.1, 1 + Line: + points: + [self.x + self.width, self.y + self.height, + self.x + 0.35*self.width, self.y + 0.6*self.height, + self.x + 0.7*self.width, self.y + 0.15*self.height, + self.x + 0.2*self.width, self.y + 0.22*self.height, + self.x + 0.3*self.width, self.y + 0.92*self.height] + width: 2 EffectWidget: id: effect2 - size: 100, 100 - Image: - id: im - pos: self.parent.pos - size: self.parent.size - source: 'colours2.png' - allow_stretch: True - keep_ratio: False - on_touch_down: print(self.size, self.pos) + Widget: + canvas: + Color: + rgba: 1, 0, 0, 1 + Ellipse: + pos: Vector(self.pos) + 0.5*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 1, 0.3, 1 + Ellipse: + pos: Vector(self.pos) + 0.1*Vector(self.size) + size: 0.6*Vector(self.size) + Color: + rgba: 0.5, 0.5, 0.2, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0, 0.6])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 1, 0.8, 0.1, 1 + Ellipse: + pos: Vector(self.pos) + Vector([0.5, 0])*Vector(self.size) + size: 0.4*Vector(self.size) + Color: + rgba: 0, 0, 0.8, 1 + Line: + points: + [self.x, self.y, + self.x + self.width, self.y + 0.3*self.height, + self.x + 0.2*self.width, self.y + 0.1*self.height, + self.x + 0.85*self.width, self.y + 0.72*self.height, + self.x + 0.31*self.width, self.y + 0.6*self.height, + self.x, self.top] + width: 1 + Color: + rgba: 0, 0.9, 0.1, 1 + Line: + points: + [self.x + self.width, self.y + self.height, + self.x + 0.35*self.width, self.y + 0.6*self.height, + self.x + 0.7*self.width, self.y + 0.15*self.height, + self.x + 0.2*self.width, self.y + 0.22*self.height, + self.x + 0.3*self.width, self.y + 0.92*self.height] + width: 2 + SpinnerRow: effectwidget: effect1 text: 'bg effects' @@ -100,7 +179,10 @@ BoxLayout: : text: 'none' - values: ['none', 'monochrome', 'red', 'blue', 'green', 'invert', 'plasma'] + values: + ['none', 'monochrome', + 'invert', 'plasma', 'mix', + 'flash', 'blur_h', 'blur_v'] ''') diff --git a/kivy/uix/effectwidget.py b/kivy/uix/effectwidget.py index c9a7dd291..bf19dbb04 100644 --- a/kivy/uix/effectwidget.py +++ b/kivy/uix/effectwidget.py @@ -13,7 +13,7 @@ draw children to Fbo and apply custom shader to a RenderContext. from kivy.clock import Clock from kivy.lang import Builder -from kivy.uix.floatlayout import FloatLayout +from kivy.uix.boxlayout import BoxLayout from kivy.properties import StringProperty, ObjectProperty, ListProperty from kivy.graphics import (RenderContext, Fbo, Color, Rectangle, Translate, PushMatrix, PopMatrix, @@ -54,7 +54,6 @@ void main (void){ gl_FragColor = frag_color * texture2D(texture0, tex_coord0); } ''' -# gl_FragColor = texture2D(texture0, tex_coord0); shader_footer_effect = ''' void main (void){ @@ -108,6 +107,86 @@ vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) } ''' +effect_mix = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + return vec4(color.z, color.x, color.y, 1.0); +} +''' + +effect_flash = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + return color * abs(sin(time)); +} +''' + +effect_blur_h = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + float dt = 0.5 * 1.0 / resolution.x; + vec4 sum = vec4(0.0); + sum += texture2D(texture, vec2(tex_coords.x - 4.0*dt, tex_coords.y)) * 0.05; + sum += texture2D(texture, vec2(tex_coords.x - 3.0*dt, tex_coords.y)) * 0.09; + sum += texture2D(texture, vec2(tex_coords.x - 2.0*dt, tex_coords.y)) * 0.12; + sum += texture2D(texture, vec2(tex_coords.x - dt, tex_coords.y)) * 0.15; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y)) * 0.16; + sum += texture2D(texture, vec2(tex_coords.x + dt, tex_coords.y)) * 0.15; + sum += texture2D(texture, vec2(tex_coords.x + 2.0*dt, tex_coords.y)) * 0.12; + sum += texture2D(texture, vec2(tex_coords.x + 3.0*dt, tex_coords.y)) * 0.09; + sum += texture2D(texture, vec2(tex_coords.x + 4.0*dt, tex_coords.y)) * 0.05; + return sum; +} +''' + +effect_blur_v = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + float dt = 0.5 * 1.0 / resolution.y; + vec4 sum = vec4(0.0); + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y - 4.0*dt)) * 0.05; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y - 3.0*dt)) * 0.09; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y - 2.0*dt)) * 0.12; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y - dt)) * 0.15; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y)) * 0.16; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y + dt)) * 0.15; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y + 2.0*dt)) * 0.12; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y + 3.0*dt)) * 0.09; + sum += texture2D(texture, vec2(tex_coords.x, tex_coords.y + 4.0*dt)) * 0.05; + return sum; +} +''' + +effect_postprocessing = ''' +vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) +{ + vec2 q = tex_coord0 * vec2(1, -1); + vec2 uv = 0.5 + (q-0.5);//*(0.9);// + 0.1*sin(0.2*time)); + + vec3 oricol = texture2D(texture0,vec2(q.x,1.0-q.y)).xyz; + vec3 col; + + col.r = texture2D(texture0,vec2(uv.x+0.003,-uv.y)).x; + col.g = texture2D(texture0,vec2(uv.x+0.000,-uv.y)).y; + col.b = texture2D(texture0,vec2(uv.x-0.003,-uv.y)).z; + + col = clamp(col*0.5+0.5*col*col*1.2,0.0,1.0); + + //col *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y); + + col *= vec3(0.8,1.0,0.7); + + col *= 0.9+0.1*sin(10.0*time+uv.y*1000.0); + + col *= 0.97+0.03*sin(110.0*time); + + float comp = smoothstep( 0.2, 0.7, sin(time) ); + //col = mix( col, oricol, clamp(-2.0+2.0*q.x+3.0*comp,0.0,1.0) ); + + gl_FragColor = vec4(col,1.0); +} +''' + effect_plasma = ''' vec4 effect(vec4 color, sampler2D texture, vec2 tex_coords, vec2 coords) { @@ -141,7 +220,7 @@ class EffectFbo(Fbo): raise Exception('failed') -class EffectWidget(FloatLayout): +class EffectWidget(BoxLayout): fs = StringProperty(None) @@ -193,8 +272,13 @@ class EffectWidget(FloatLayout): self.refresh_fbo_setup() def update_glsl(self, *largs): - self.canvas['time'] = Clock.get_boottime() - self.canvas['resolution'] = map(float, self.size) + time = Clock.get_boottime() + resolution = [float(size) for size in self.size] + self.canvas['time'] = time + self.canvas['resolution'] = resolution + for fbo in self.fbo_list: + fbo['time'] = time + fbo['resolution'] = resolution def on_effects(self, *args): self.refresh_fbo_setup()