From e979de43fb06a8faed09a84dad59dfc3eb90f3a6 Mon Sep 17 00:00:00 2001 From: Rivo Laks Date: Wed, 18 Apr 2007 19:44:49 +0000 Subject: [PATCH] Another demo effect which uses shader and render target to turn your screen into a liquid, wavy surface. Soon we'll have more silly effects than Beryl/Compiz ;-) svn path=/branches/work/kwin_composite/; revision=655575 --- effects/CMakeLists.txt | 4 ++ effects/data/liquid.frag | 50 +++++++++++++++ effects/data/liquid.vert | 7 +++ effects/demo_liquid.cpp | 122 ++++++++++++++++++++++++++++++++++++ effects/demo_liquid.desktop | 4 ++ effects/demo_liquid.h | 51 +++++++++++++++ 6 files changed, 238 insertions(+) create mode 100644 effects/data/liquid.frag create mode 100644 effects/data/liquid.vert create mode 100644 effects/demo_liquid.cpp create mode 100644 effects/demo_liquid.desktop create mode 100644 effects/demo_liquid.h diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index f5999ea899..01054bacff 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -46,6 +46,7 @@ if(OPENGL_FOUND) ) SET(kwin4_effect_tests_sources ${kwin4_effect_tests_sources} test_fbo.cpp + demo_liquid.cpp ) install( FILES @@ -54,6 +55,7 @@ if(OPENGL_FOUND) trackmouse.desktop wavywindows.desktop test_fbo.desktop + demo_liquid.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin/effects ) install( FILES @@ -62,6 +64,8 @@ if(OPENGL_FOUND) data/explosion.vert data/explosion-start.png data/explosion-end.png + data/liquid.frag + data/liquid.vert DESTINATION ${DATA_INSTALL_DIR}/kwin ) endif(OPENGL_FOUND) diff --git a/effects/data/liquid.frag b/effects/data/liquid.frag new file mode 100644 index 0000000000..39ee0fce61 --- /dev/null +++ b/effects/data/liquid.frag @@ -0,0 +1,50 @@ +uniform sampler2D sceneTex; +uniform float displayWidth; +uniform float displayHeight; +uniform float time; + +varying vec2 pos; + + +#define DEG2RAD (6.2832/360.0) + + +// Converts pixel coordinates to texture coordinates +vec2 pix2tex(vec2 pix) +{ + return vec2(pix.x / displayWidth, 1.0 - pix.y / displayHeight); +} + +float wave(vec2 pos, vec2 wave_dir, float wave_length, float wave_speed) +{ + return sin(((pos.x * wave_dir.x) + (pos.y * wave_dir.y)) * 6.2832 / wave_length + + time * wave_speed * 6.2832 / wave_length); +} + +vec2 displacement(float wave_angle, float wave_length, float wave_speed, float wave_height) +{ + vec2 wave_dir = vec2(cos(wave_angle * DEG2RAD), sin(wave_angle * DEG2RAD)); + return wave_dir * (wave(pos, wave_dir, wave_length, wave_speed) * wave_height); +} + +// Only for debugging +float wave_color(float wave_angle, float wave_length, float wave_speed, float wave_height) +{ + vec2 wave_dir = vec2(cos(wave_angle * DEG2RAD), sin(wave_angle * DEG2RAD)); + return wave(pos, wave_dir, wave_length, wave_speed) * 0.5 + 0.5; +} + +void main() +{ + vec2 texpos = pos; + texpos += displacement( 20.0, 250.0, 120.0, 4.0); + texpos += displacement(-40.0, 350.0, 100.0, 4.0); + texpos += displacement(240.0, 1000.0, 100.0, 12.0); + texpos += displacement(160.0, 50.0, 30.0, 2.0); + + vec3 tex = texture2D(sceneTex, pix2tex(texpos)).rgb; + //tex.r = wave_color( 20, 250, 150, 4); // debug + + gl_FragColor = vec4(tex, 1.0); +} + diff --git a/effects/data/liquid.vert b/effects/data/liquid.vert new file mode 100644 index 0000000000..55d169df80 --- /dev/null +++ b/effects/data/liquid.vert @@ -0,0 +1,7 @@ +varying vec2 pos; + +void main() +{ + pos = gl_Vertex.xy; + gl_Position = ftransform(); +} diff --git a/effects/demo_liquid.cpp b/effects/demo_liquid.cpp new file mode 100644 index 0000000000..00d7248f83 --- /dev/null +++ b/effects/demo_liquid.cpp @@ -0,0 +1,122 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Rivo Laks + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + + +#include "demo_liquid.h" + +#include + +#include +#include + +#include + + +namespace KWin +{ + +KWIN_EFFECT( Demo_Liquid, LiquidEffect ); +KWIN_EFFECT_SUPPORTED( Demo_Liquid, LiquidEffect::supported() ); + + +LiquidEffect::LiquidEffect() : Effect() + { + mTime = 0.0f; + mValid = loadData(); + } + +bool LiquidEffect::loadData() + { + // Create texture and render target + mTexture = new GLTexture(displayWidth(), displayHeight()); + mTexture->setFilter(GL_LINEAR_MIPMAP_LINEAR); + + mRenderTarget = new GLRenderTarget(mTexture); + if( !mRenderTarget->valid() ) + return false; + + QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/liquid.frag"); + QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/liquid.vert"); + if(fragmentshader.isEmpty() || vertexshader.isEmpty()) + { + kError() << k_funcinfo << "Couldn't locate shader files" << endl; + return false; + } + mShader = new GLShader(vertexshader, fragmentshader); + if(!mShader->isValid()) + { + kError() << k_funcinfo << "The shader failed to load!" << endl; + return false; + } + mShader->bind(); + mShader->setUniform("sceneTex", 0); + mShader->setUniform("displayWidth", (float)displayWidth()); + mShader->setUniform("displayHeight", (float)displayHeight()); + mShader->unbind(); + + return true; + } + +bool LiquidEffect::supported() + { + return hasGLExtension("GL_EXT_framebuffer_object") && + GLShader::fragmentShaderSupported() && + (effects->compositingType() == OpenGLCompositing); + } + + +void LiquidEffect::prePaintScreen( int* mask, QRegion* region, int time ) + { + mTime += time / 1000.0f; + if(mValid) + { + *mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; + // Start rendering to texture + mRenderTarget->enable(); + } + + effects->prePaintScreen(mask, region, time); + } + +void LiquidEffect::postPaintScreen() + { + // Call the next effect. + effects->postPaintScreen(); + + if(mValid) + { + // Disable render texture + mRenderTarget->disable(); + mTexture->bind(); + + // Use the shader + mShader->bind(); + mShader->setUniform("time", mTime); + + // Render fullscreen quad with screen contents + glBegin(GL_QUADS); + glVertex2f(0.0, displayHeight()); + glVertex2f(displayWidth(), displayHeight()); + glVertex2f(displayWidth(), 0.0); + glVertex2f(0.0, 0.0); + glEnd(); + + mShader->unbind(); + mTexture->unbind(); + + // Make sure the animation continues + effects->addRepaintFull(); + } + + } + + +} // namespace + diff --git a/effects/demo_liquid.desktop b/effects/demo_liquid.desktop new file mode 100644 index 0000000000..9bc7f79ca4 --- /dev/null +++ b/effects/demo_liquid.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Demo_Liquid +X-KDE-Library=kwin4_effect_tests diff --git a/effects/demo_liquid.h b/effects/demo_liquid.h new file mode 100644 index 0000000000..2c00e09c8e --- /dev/null +++ b/effects/demo_liquid.h @@ -0,0 +1,51 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Rivo Laks + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + +#ifndef KWIN_DEMO_LIQUID_H +#define KWIN_DEMO_LIQUID_H + +// Include with base class for effects. +#include + +namespace KWin +{ + +class GLRenderTarget; +class GLTexture; +class GLShader; + +/** + * Turns your desktop into a wavy (liquid) surface + **/ +class LiquidEffect : public Effect + { + public: + LiquidEffect(); + + virtual void prePaintScreen( int* mask, QRegion* region, int time ); + virtual void postPaintScreen(); + + static bool supported(); + + protected: + bool loadData(); + + private: + GLTexture* mTexture; + GLRenderTarget* mRenderTarget; + GLShader* mShader; + bool mValid; + + float mTime; + }; + +} // namespace + +#endif