Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Quick and dirty drop shadow example
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
using namespace ci;
using namespace ci::app;
using namespace std;
struct Shape
{
float rotation;
float scale;
vec2 position;
gl::VboMeshRef mesh;
};
class DropShadowApp : public App
{
public:
void setup ( ) override;
void update ( ) override;
void draw ( ) override;
void loadShaders ( );
void loadBuffers ( );
void renderShapes ( bool shadow );
protected:
std::vector<Shape> _shapes;
gl::FboRef _buffers[2];
gl::GlslProgRef _blurH;
gl::GlslProgRef _blurV;
int _blurIterations{8};
float _blurStrength{0.41f};
vec2 _shadowDistance{30};
float _shadowPower{0.5f};
};
void DropShadowApp::setup()
{
_shapes =
{
{
0.0f,
1.0f,
vec2(200, 200),
gl::VboMesh::create( geom::Rect().rect ( Rectf ( -100, -100, 100, 100 ) ) )
},
{
0.0f,
2.0f,
vec2(500, 200),
gl::VboMesh::create( geom::Circle().radius(40.0f) )
}
};
loadShaders();
loadBuffers();
}
void DropShadowApp::loadShaders ( )
{
auto vertex = CI_GLSL(150,
uniform mat4 ciModelViewProjection;
in vec4 ciPosition;
in vec2 ciTexCoord0;
out vec2 UV;
void main ( )
{
gl_Position = ciModelViewProjection * ciPosition;
UV = ciTexCoord0;
}
);
auto fragment = CI_GLSL(150,
in vec2 UV;
uniform sampler2D uScene;
uniform vec2 uResolution;
uniform vec2 uDirection;
out vec4 FinalColor;
vec4 Blur ( sampler2D image, vec2 uv, vec2 resolution, vec2 direction )
{
vec2 off1 = vec2(1.411764705882353) * direction;
vec2 off2 = vec2(3.2941176470588234) * direction;
vec2 off3 = vec2(5.176470588235294) * direction;
vec4 color = vec4(0.0);
color += texture(image, uv) * 0.1964825501511404;
color += texture(image, uv + (off1 / resolution)) * 0.2969069646728344;
color += texture(image, uv - (off1 / resolution)) * 0.2969069646728344;
color += texture(image, uv + (off2 / resolution)) * 0.09447039785044732;
color += texture(image, uv - (off2 / resolution)) * 0.09447039785044732;
color += texture(image, uv + (off3 / resolution)) * 0.010381362401148057;
color += texture(image, uv - (off3 / resolution)) * 0.010381362401148057;
return color;
}
void main ( )
{
FinalColor = Blur ( uScene, UV, uResolution, uDirection );
});
_blurH = gl::GlslProg::create( vertex, fragment );
_blurH->uniform ( "uScene", 0 );
_blurH->uniform ( "uResolution", vec2 ( getWindowSize() ) );
_blurV = gl::GlslProg::create( vertex, fragment );
_blurV->uniform ( "uScene", 0 );
_blurV->uniform ( "uResolution", vec2 ( getWindowSize() ) );
}
void DropShadowApp::loadBuffers ( )
{
_buffers[0] = gl::Fbo::create( getWindowWidth(), getWindowHeight(), true );
_buffers[1] = gl::Fbo::create( getWindowWidth(), getWindowHeight(), true );
}
void DropShadowApp::renderShapes ( bool shadow )
{
auto render = [&]
{
for ( auto& shape : _shapes )
{
gl::ScopedModelMatrix mat;
gl::translate ( shape.position );
gl::rotate( shape.rotation );
gl::scale ( vec2(shape.scale) );
gl::draw ( shape.mesh );
}
};
if ( shadow )
{
gl::context()->pushBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
{
gl::ScopedMatrices mat;
gl::pushViewport( _buffers[1]->getSize() );
{
gl::ScopedFramebuffer buffer ( _buffers[1] );
gl::setMatricesWindow( _buffers[1]->getSize() );
gl::clear ( ColorAf ( 0, 0, 0, 0 ) );
gl::ScopedColor color ( Colorf ( 0, 0, 0 ) );
gl::ScopedGlslProg shader ( gl::getStockShader( gl::ShaderDef().color() ) );
render();
}
gl::popViewport();
}
{
gl::ScopedMatrices mat;
for ( int i = 0; i < _blurIterations; i++ )
{
int index = 0;
auto& ping = _buffers[index];
auto& pong = _buffers[1 - index];
float d = (_blurIterations - i - 1) * _blurStrength;
_blurH->uniform ( "uDirection", vec2(d, 0) );
_blurV->uniform ( "uDirection", vec2(0, d) );
gl::pushViewport( ping->getSize() );
{
gl::ScopedGlslProg shader ( _blurH );
gl::ScopedFramebuffer buffer ( ping );
gl::ScopedTextureBind tex0 ( pong->getColorTexture(), 0 );
gl::setMatricesWindow( ping->getSize());
gl::clear ( ColorAf ( 1, 1, 1, 0 ) );
gl::drawSolidRect( ping->getBounds() );
}
{
gl::ScopedGlslProg shader ( _blurV );
gl::ScopedFramebuffer buffer ( pong );
gl::ScopedTextureBind tex0 ( ping->getColorTexture(), 0 );
gl::setMatricesWindow( pong->getSize());
gl::clear ( ColorAf ( 1, 1, 1, 0 ) );
gl::drawSolidRect( pong->getBounds() );
}
index = 1 - index;
gl::popViewport();
}
}
gl::context()->popBlendFuncSeparate();
}else
{
gl::ScopedColor color ( Colorf ( 1, 0, 0 ) );
gl::ScopedGlslProg shader ( gl::getStockShader( gl::ShaderDef().color() ) );
render();
}
}
void DropShadowApp::update()
{
for ( auto& shape : _shapes )
{
shape.rotation += toRadians( 1.0f );
shape.scale = 1.0f + std::sin ( getElapsedSeconds() * 0.8f ) * 0.5f;
}
}
void DropShadowApp::draw()
{
gl::clear( Colorf::white() );
gl::setMatricesWindow ( getWindowSize() );
{
renderShapes( true );
gl::ScopedColor color ( ColorAf ( 1, 1, 1, _shadowPower ) );
gl::draw ( _buffers[1]->getColorTexture(), _shadowDistance );
}
renderShapes(false);
}
CINDER_APP( DropShadowApp, RendererGl ( RendererGl::Options().msaa( 16 ) ) )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment