Created
March 16, 2017 14:18
-
-
Save axjxwright/9da8ccb52bd917d9266405b7a7ffbdd9 to your computer and use it in GitHub Desktop.
Quick and dirty drop shadow example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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