Reflection plane in Coverswitch and GLES
CoverSwitch uses new concept of combining a custom fragment shader with the built-in generic vertex shader. This shader is used to render the reflection plane on top of the reflected windows. The fragment shader uses two uniform colors for front and back and interpolates between them based on the texcoords (which are not used for texture lookup). The reflection plane vertices could be buffered.
This commit is contained in:
parent
a4e4752109
commit
ad070909a3
4 changed files with 88 additions and 23 deletions
|
@ -11,6 +11,11 @@ install( FILES
|
|||
coverswitch/coverswitch.desktop
|
||||
DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
|
||||
|
||||
install( FILES
|
||||
coverswitch/coverswitch-reflection.glsl
|
||||
DESTINATION ${DATA_INSTALL_DIR}/kwin )
|
||||
|
||||
|
||||
#######################################
|
||||
# Config
|
||||
|
||||
|
|
9
effects/coverswitch/coverswitch-reflection.glsl
Normal file
9
effects/coverswitch/coverswitch-reflection.glsl
Normal file
|
@ -0,0 +1,9 @@
|
|||
uniform vec4 u_frontColor;
|
||||
uniform vec4 u_backColor;
|
||||
|
||||
varying vec2 varyingTexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = u_frontColor*(1.0-varyingTexCoords.s) + u_backColor*varyingTexCoords.s;
|
||||
}
|
|
@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kapplication.h>
|
||||
#include <kcolorscheme.h>
|
||||
#include <kconfiggroup.h>
|
||||
#include <kglobal.h>
|
||||
#include <kstandarddirs.h>
|
||||
|
||||
#include <kwinglutils.h>
|
||||
|
||||
|
@ -65,11 +67,15 @@ CoverSwitchEffect::CoverSwitchEffect()
|
|||
captionFont.setPointSize( captionFont.pointSize() * 2 );
|
||||
captionFrame->setFont( captionFont );
|
||||
captionFrame->enableCrossFade( true );
|
||||
|
||||
const QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/coverswitch-reflection.glsl");
|
||||
m_reflectionShader = ShaderManager::instance()->loadFragmentShader(ShaderManager::GenericShader, fragmentshader);
|
||||
}
|
||||
|
||||
CoverSwitchEffect::~CoverSwitchEffect()
|
||||
{
|
||||
delete captionFrame;
|
||||
delete m_reflectionShader;
|
||||
}
|
||||
|
||||
bool CoverSwitchEffect::supported()
|
||||
|
@ -257,33 +263,28 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
|
|||
if( (!start && !stop) || ShaderManager::instance()->isValid() )
|
||||
paintScene( frontWindow, leftWindows, rightWindows, true );
|
||||
PaintClipper::pop( clip );
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA );
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glPolygonMode( GL_FRONT, GL_FILL );
|
||||
glPushMatrix();
|
||||
#endif
|
||||
QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
|
||||
// we can use a huge scale factor (needed to calculate the rearground vertices)
|
||||
// as we restrict with a PaintClipper painting on the current screen
|
||||
float reflectionScaleFactor = 100000 * tan( 60.0 * M_PI / 360.0f )/area.width();
|
||||
if( effects->numScreens() > 1 && area.x() != fullRect.x() )
|
||||
{
|
||||
// have to change the reflection area in horizontal layout and right screen
|
||||
glTranslatef( -area.x(), 0.0, 0.0 );
|
||||
}
|
||||
glTranslatef( area.x() + area.width()*0.5f, 0.0, 0.0 );
|
||||
float vertices[] = {
|
||||
-area.width()*0.5f, area.height(), 0.0,
|
||||
area.width()*0.5f, area.height(), 0.0,
|
||||
(float)area.width()*reflectionScaleFactor, area.height(), -5000,
|
||||
-(float)area.width()*reflectionScaleFactor, area.height(), -5000 };
|
||||
// foreground
|
||||
if( start )
|
||||
if (start) {
|
||||
mirrorColor[0][3] = timeLine.value();
|
||||
else if( stop )
|
||||
} else if (stop) {
|
||||
mirrorColor[0][3] = 1.0 - timeLine.value();
|
||||
glColor4fv( mirrorColor[0] );
|
||||
mirrorColor[0][3] = 1.0;
|
||||
} else {
|
||||
mirrorColor[0][3] = 1.0;
|
||||
}
|
||||
|
||||
int y = 0;
|
||||
// have to adjust the y values to fit OpenGL
|
||||
|
@ -302,20 +303,68 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
|
|||
// use scissor to restrict painting of the reflection plane to current screen
|
||||
glScissor( area.x(), y, area.width(), area.height() );
|
||||
glEnable( GL_SCISSOR_TEST );
|
||||
glBegin( GL_POLYGON );
|
||||
glVertex3f( vertices[0], vertices[1], vertices[2] );
|
||||
glVertex3f( vertices[3], vertices[4], vertices[5] );
|
||||
// rearground
|
||||
glColor4fv( mirrorColor[1] );
|
||||
glVertex3f( vertices[6], vertices[7], vertices[8] );
|
||||
glVertex3f( vertices[9], vertices[10], vertices[11] );
|
||||
glEnd();
|
||||
glDisable( GL_SCISSOR_TEST );
|
||||
|
||||
glPopMatrix();
|
||||
glDisable( GL_BLEND );
|
||||
ShaderManager *shaderManager = ShaderManager::instance();
|
||||
if (shaderManager->isValid() && m_reflectionShader->isValid()) {
|
||||
shaderManager->pushShader(m_reflectionShader);
|
||||
QMatrix4x4 windowTransformation;
|
||||
if (effects->numScreens() > 1 && area.x() != fullRect.x()) {
|
||||
// have to change the reflection area in horizontal layout and right screen
|
||||
windowTransformation.translate(-area.x(), 0.0, 0.0);
|
||||
}
|
||||
windowTransformation.translate(area.x() + area.width()*0.5f, 0.0, 0.0);
|
||||
m_reflectionShader->setUniform("windowTransformation", windowTransformation);
|
||||
m_reflectionShader->setUniform("u_frontColor", QVector4D(mirrorColor[0][0], mirrorColor[0][1], mirrorColor[0][2], mirrorColor[0][3]));
|
||||
m_reflectionShader->setUniform("u_backColor", QVector4D(mirrorColor[1][0], mirrorColor[1][1], mirrorColor[1][2], mirrorColor[1][3]));
|
||||
// TODO: make this one properly
|
||||
QVector<float> verts;
|
||||
QVector<float> texcoords;
|
||||
verts.reserve(18);
|
||||
texcoords.reserve(12);
|
||||
texcoords << 1.0 << 0.0;
|
||||
verts << vertices[6] << vertices[7] << vertices[8];
|
||||
texcoords << 1.0 << 0.0;
|
||||
verts << vertices[9] << vertices[10] << vertices[11];
|
||||
texcoords << 0.0 << 0.0;
|
||||
verts << vertices[0] << vertices[1] << vertices[2];
|
||||
texcoords << 0.0 << 0.0;
|
||||
verts << vertices[0] << vertices[1] << vertices[2];
|
||||
texcoords << 0.0 << 0.0;
|
||||
verts << vertices[3] << vertices[4] << vertices[5];
|
||||
texcoords << 1.0 << 0.0;
|
||||
verts << vertices[6] << vertices[7] << vertices[8];
|
||||
GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
|
||||
vbo->reset();
|
||||
vbo->setUseShader(true);
|
||||
vbo->setData(6, 3, verts.data(), texcoords.data());
|
||||
vbo->render(GL_TRIANGLES);
|
||||
|
||||
shaderManager->popShader();
|
||||
} else {
|
||||
#ifndef KWIN_HAVE_OPENGLES
|
||||
glPushMatrix();
|
||||
if( effects->numScreens() > 1 && area.x() != fullRect.x() )
|
||||
{
|
||||
// have to change the reflection area in horizontal layout and right screen
|
||||
glTranslatef( -area.x(), 0.0, 0.0 );
|
||||
}
|
||||
glTranslatef( area.x() + area.width()*0.5f, 0.0, 0.0 );
|
||||
glColor4fv( mirrorColor[0] );
|
||||
glBegin( GL_POLYGON );
|
||||
glVertex3f( vertices[0], vertices[1], vertices[2] );
|
||||
glVertex3f( vertices[3], vertices[4], vertices[5] );
|
||||
// rearground
|
||||
glColor4fv( mirrorColor[1] );
|
||||
glVertex3f( vertices[6], vertices[7], vertices[8] );
|
||||
glVertex3f( vertices[9], vertices[10], vertices[11] );
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
#endif
|
||||
}
|
||||
glDisable( GL_SCISSOR_TEST );
|
||||
glDisable( GL_BLEND );
|
||||
}
|
||||
paintScene( frontWindow, leftWindows, rightWindows );
|
||||
|
||||
if( effects->numScreens() > 1 )
|
||||
|
|
|
@ -102,6 +102,8 @@ class CoverSwitchEffect
|
|||
|
||||
bool primaryTabBox;
|
||||
bool secondaryTabBox;
|
||||
|
||||
GLShader *m_reflectionShader;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in a new issue