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
This commit is contained in:
Rivo Laks 2007-04-18 19:44:49 +00:00
parent e93ce53928
commit e979de43fb
6 changed files with 238 additions and 0 deletions

View file

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

50
effects/data/liquid.frag Normal file
View file

@ -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);
}

7
effects/data/liquid.vert Normal file
View file

@ -0,0 +1,7 @@
varying vec2 pos;
void main()
{
pos = gl_Vertex.xy;
gl_Position = ftransform();
}

122
effects/demo_liquid.cpp Normal file
View file

@ -0,0 +1,122 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
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 <kwinglutils.h>
#include <QString>
#include <KStandardDirs>
#include <kdebug.h>
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

View file

@ -0,0 +1,4 @@
[Desktop Entry]
Encoding=UTF-8
Name=Demo_Liquid
X-KDE-Library=kwin4_effect_tests

51
effects/demo_liquid.h Normal file
View file

@ -0,0 +1,51 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
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 <kwineffects.h>
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