Depth of field!!!
This commit is contained in:
parent
96122a6487
commit
b2be3dcb8c
23 changed files with 441 additions and 48 deletions
2
Makefile
2
Makefile
|
@ -15,6 +15,8 @@ DEMO = \
|
||||||
rendertarget.o \
|
rendertarget.o \
|
||||||
raymarcher.o \
|
raymarcher.o \
|
||||||
bloom.o \
|
bloom.o \
|
||||||
|
dof.o \
|
||||||
|
combine.o \
|
||||||
profiling.o
|
profiling.o
|
||||||
|
|
||||||
DEMO_DEPS = $(DEMO:%.o=.%.d)
|
DEMO_DEPS = $(DEMO:%.o=.%.d)
|
||||||
|
|
2
TODO
2
TODO
|
@ -11,6 +11,8 @@ Post-processing:
|
||||||
* Lens dirt
|
* Lens dirt
|
||||||
|
|
||||||
Technical:
|
Technical:
|
||||||
|
* Use program pipelines
|
||||||
|
* Use uniform buffers
|
||||||
* GLSL with includes
|
* GLSL with includes
|
||||||
* GLSL constants generator
|
* GLSL constants generator
|
||||||
* Common handling for parameters
|
* Common handling for parameters
|
||||||
|
|
24
bloom.cc
24
bloom.cc
|
@ -20,16 +20,13 @@ T_BloomPass::T_BloomPass(
|
||||||
spHighpass_( GL_FRAGMENT_SHADER , watcher ) ,
|
spHighpass_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
spDownsample_( GL_FRAGMENT_SHADER , watcher ) ,
|
spDownsample_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
spBlur_( GL_FRAGMENT_SHADER , watcher ) ,
|
spBlur_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
spCombine_( GL_FRAGMENT_SHADER , watcher ) ,
|
|
||||||
//
|
//
|
||||||
txBlur0_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
txBlur0_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
||||||
txBlur1_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
txBlur1_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
||||||
//
|
//
|
||||||
filterParams_{ 1.6 , 1.2 , .95 } ,
|
filterParams_{ 1.6 , 1.2 , .95 } ,
|
||||||
blurWeights_{ 0.324 , 0.232 , 0.0855 , 0.0205 } ,
|
blurWeights_{ 0.324 , 0.232 , 0.0855 , 0.0205 } ,
|
||||||
blurSize_{ 1.3 } ,
|
blurSize_{ 1.3 }
|
||||||
combineStrength_( 0.45 ) ,
|
|
||||||
combineAttenuation_( 0.3 )
|
|
||||||
{
|
{
|
||||||
txBlur0_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
txBlur0_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
||||||
txBlur1_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
txBlur1_.wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
|
||||||
|
@ -42,12 +39,10 @@ T_BloomPass::T_BloomPass(
|
||||||
spHighpass_.addFile( "bloom-highpass.glsl" );
|
spHighpass_.addFile( "bloom-highpass.glsl" );
|
||||||
spDownsample_.addFile( "downsample.glsl" );
|
spDownsample_.addFile( "downsample.glsl" );
|
||||||
spBlur_.addFile( "blur-pass.glsl" );
|
spBlur_.addFile( "blur-pass.glsl" );
|
||||||
spCombine_.addFile( "bloom-combine.glsl" );
|
|
||||||
|
|
||||||
spHighpass_.load( );
|
spHighpass_.load( );
|
||||||
spDownsample_.load( );
|
spDownsample_.load( );
|
||||||
spBlur_.load( );
|
spBlur_.load( );
|
||||||
spCombine_.load( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_BloomPass::render( )
|
void T_BloomPass::render( )
|
||||||
|
@ -113,21 +108,6 @@ void T_BloomPass::render( )
|
||||||
glRectf( -1 , -1 , 1 , 1 );
|
glRectf( -1 , -1 , 1 , 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
T_Rendertarget::MainOutput( );
|
|
||||||
glClearColor( 1 , 0 , 1 , 1 );
|
|
||||||
glClear( GL_COLOR_BUFFER_BIT );
|
|
||||||
if ( spCombine_.activate( ) ) {
|
|
||||||
T_TextureBinding main( 0 ) , blur( 1 );
|
|
||||||
main.set( 0 , input_ );
|
|
||||||
main.bind( );
|
|
||||||
blur.set( 1 , txBlur0_ );
|
|
||||||
blur.bind( );
|
|
||||||
glUniform2f( 2 , input_.width( ) , input_.height( ) );
|
|
||||||
glUniform2f( 3 , combineStrength_ , combineAttenuation_ );
|
|
||||||
glRectf( -1, -1 , 1 , 1 );
|
|
||||||
glBindTexture( GL_TEXTURE_2D , 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
PEND( );
|
PEND( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +120,4 @@ void T_BloomPass::makeUI( )
|
||||||
ImGui::DragFloat3( "Filter" , filterParams_ , .01f , 0.1 , 10 );
|
ImGui::DragFloat3( "Filter" , filterParams_ , .01f , 0.1 , 10 );
|
||||||
ImGui::DragFloat4( "Weights" , blurWeights_ , .001f , 0. , 10 );
|
ImGui::DragFloat4( "Weights" , blurWeights_ , .001f , 0. , 10 );
|
||||||
ImGui::DragFloat( "Blur size" , &blurSize_ , .001f , 0. , 10 );
|
ImGui::DragFloat( "Blur size" , &blurSize_ , .001f , 0. , 10 );
|
||||||
ImGui::DragFloat( "Initial strength" , &combineStrength_ , .001f , 0. , 10 );
|
|
||||||
ImGui::DragFloat( "Attenuation" , &combineAttenuation_ , .001f , 0. , 1 );
|
|
||||||
}
|
}
|
||||||
|
|
5
bloom.hh
5
bloom.hh
|
@ -23,13 +23,14 @@ struct T_BloomPass
|
||||||
void render( );
|
void render( );
|
||||||
void makeUI( );
|
void makeUI( );
|
||||||
|
|
||||||
|
T_Texture& output( ) { return txBlur0_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T_Texture& input_;
|
T_Texture& input_;
|
||||||
|
|
||||||
T_ShaderProgram spHighpass_;
|
T_ShaderProgram spHighpass_;
|
||||||
T_ShaderProgram spDownsample_;
|
T_ShaderProgram spDownsample_;
|
||||||
T_ShaderProgram spBlur_;
|
T_ShaderProgram spBlur_;
|
||||||
T_ShaderProgram spCombine_;
|
|
||||||
|
|
||||||
T_Texture txBlur0_ , txBlur1_;
|
T_Texture txBlur0_ , txBlur1_;
|
||||||
std::vector< T_Rendertarget > rtBlur0_ , rtBlur1_;
|
std::vector< T_Rendertarget > rtBlur0_ , rtBlur1_;
|
||||||
|
@ -37,6 +38,4 @@ struct T_BloomPass
|
||||||
float filterParams_[ 3 ];
|
float filterParams_[ 3 ];
|
||||||
float blurWeights_[ 4 ];
|
float blurWeights_[ 4 ];
|
||||||
float blurSize_;
|
float blurSize_;
|
||||||
float combineStrength_;
|
|
||||||
float combineAttenuation_;
|
|
||||||
};
|
};
|
||||||
|
|
59
combine.cc
Normal file
59
combine.cc
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "externals.hh"
|
||||||
|
#include "utilities.hh"
|
||||||
|
#include "texture.hh"
|
||||||
|
#include "rendertarget.hh"
|
||||||
|
#include "combine.hh"
|
||||||
|
#include "bloom.hh"
|
||||||
|
#include "profiling.hh"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::string Name_( "Combine" );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PSTART() T_Profiler::Profiler.start( Name_ )
|
||||||
|
#define PEND() do { glFinish( ); T_Profiler::Profiler.end( Name_ ); } while ( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
T_CombinePass::T_CombinePass(
|
||||||
|
__rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rw__ T_Texture& image ,
|
||||||
|
__rw__ T_Texture& bloom )
|
||||||
|
: txImage_( image ) , txBloom_( bloom ) ,
|
||||||
|
program_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
|
bloomStrength_( 0.45 ) ,
|
||||||
|
bloomAttenuation_( 0.3 )
|
||||||
|
{
|
||||||
|
program_.addFile( "combine.glsl" );
|
||||||
|
program_.load( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_CombinePass::render( )
|
||||||
|
{
|
||||||
|
PSTART( );
|
||||||
|
T_Rendertarget::MainOutput( );
|
||||||
|
glClearColor( 1 , 0 , 1 , 1 );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
if ( program_.activate( ) ) {
|
||||||
|
T_TextureBinding main( 0 ) , blur( 1 );
|
||||||
|
main.set( 0 , txImage_ );
|
||||||
|
main.bind( );
|
||||||
|
blur.set( 1 , txBloom_ );
|
||||||
|
blur.bind( );
|
||||||
|
glUniform2f( 2 , txImage_.width( ) , txImage_.height( ) );
|
||||||
|
glUniform2f( 3 , bloomStrength_ , bloomAttenuation_ );
|
||||||
|
glRectf( -1, -1 , 1 , 1 );
|
||||||
|
glBindTexture( GL_TEXTURE_2D , 0 );
|
||||||
|
}
|
||||||
|
PEND( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_CombinePass::makeUI( )
|
||||||
|
{
|
||||||
|
if ( !ImGui::CollapsingHeader( "Combine" ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::DragFloat( "Bloom strength" , &bloomStrength_ , .001f , 0. , 10 );
|
||||||
|
ImGui::DragFloat( "Bloom attenuation" , &bloomAttenuation_ , .001f , 0. , 1 );
|
||||||
|
}
|
||||||
|
|
34
combine.hh
Normal file
34
combine.hh
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef REAL_BUILD
|
||||||
|
# define REAL_BUILD
|
||||||
|
# include "externals.hh"
|
||||||
|
# include "texture.hh"
|
||||||
|
# include "rendertarget.hh"
|
||||||
|
# include "utilities.hh"
|
||||||
|
# undef REAL_BUILD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct T_CombinePass
|
||||||
|
{
|
||||||
|
T_CombinePass( ) = delete;
|
||||||
|
T_CombinePass( T_CombinePass const& ) = delete;
|
||||||
|
T_CombinePass( T_CombinePass&& ) = delete;
|
||||||
|
|
||||||
|
T_CombinePass( __rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rw__ T_Texture& image ,
|
||||||
|
__rw__ T_Texture& bloom );
|
||||||
|
|
||||||
|
void render( );
|
||||||
|
void makeUI( );
|
||||||
|
|
||||||
|
private:
|
||||||
|
T_Texture& txImage_;
|
||||||
|
T_Texture& txBloom_;
|
||||||
|
|
||||||
|
T_ShaderProgram program_;
|
||||||
|
|
||||||
|
float bloomStrength_;
|
||||||
|
float bloomAttenuation_;
|
||||||
|
};
|
||||||
|
|
61
dof-common.glsl
Normal file
61
dof-common.glsl
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
//#define USE_RANDOM
|
||||||
|
|
||||||
|
layout( location = 0 ) uniform sampler2D u_Input;
|
||||||
|
layout( location = 1 ) uniform sampler2D u_Depth;
|
||||||
|
layout( location = 2 ) uniform vec4 u_Parameters;
|
||||||
|
layout( location = 3 ) uniform float u_Samples;
|
||||||
|
layout( location = 4 ) uniform vec3 u_ResolutionTime;
|
||||||
|
|
||||||
|
#define uSharpDist (u_Parameters.x)
|
||||||
|
#define uSharpRange (u_Parameters.y)
|
||||||
|
#define uBlurFalloff (u_Parameters.z)
|
||||||
|
#define uMaxBlur (u_Parameters.w)
|
||||||
|
|
||||||
|
#define uResolution (u_ResolutionTime.xy)
|
||||||
|
#define uTime (u_ResolutionTime.z)
|
||||||
|
|
||||||
|
float CoC( float z )
|
||||||
|
{
|
||||||
|
return uMaxBlur * min( 1 ,
|
||||||
|
max( 0 , abs( z - uSharpDist ) - uSharpRange ) / uBlurFalloff );
|
||||||
|
}
|
||||||
|
|
||||||
|
layout( location = 0 ) out vec3 o_Color;
|
||||||
|
|
||||||
|
float hash1( vec2 p )
|
||||||
|
{
|
||||||
|
p = fract(p * vec2(5.3987, 5.4421));
|
||||||
|
p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
|
||||||
|
return fract(p.x * p.y * 95.4307);
|
||||||
|
}
|
||||||
|
|
||||||
|
// z: z at UV
|
||||||
|
// coc: blur radius at UV
|
||||||
|
// uv: initial coordinate
|
||||||
|
// blurvec: smudge direction
|
||||||
|
vec3 depthDirectionalBlur( float z , float coc , vec2 uv , vec2 blurvec )
|
||||||
|
{
|
||||||
|
vec3 sumcol = vec3( 0. );
|
||||||
|
for ( int i = 0 ; i < u_Samples ; i++ ) {
|
||||||
|
float r = i;
|
||||||
|
#ifdef USE_RANDOM
|
||||||
|
r += hash1( uv + float( i + uTime ) ) - .5;
|
||||||
|
#endif
|
||||||
|
r = r / float( u_Samples - 1 ) - .5;
|
||||||
|
vec2 p = uv + r * coc * blurvec;
|
||||||
|
vec3 smpl = texture( u_Input , p ).xyz;
|
||||||
|
float sz = texture( u_Depth , p ).x;
|
||||||
|
if ( sz < z ) {
|
||||||
|
// if sample is closer consider it's CoC
|
||||||
|
p = uv + r * min( coc , CoC( sz ) ) * blurvec;
|
||||||
|
p = uv + r * CoC( sz ) * blurvec;
|
||||||
|
smpl = texture( u_Input , p ).xyz;
|
||||||
|
}
|
||||||
|
sumcol += smpl;
|
||||||
|
}
|
||||||
|
sumcol /= float( u_Samples );
|
||||||
|
sumcol = max( sumcol , 0. );
|
||||||
|
return sumcol;
|
||||||
|
}
|
8
dof-pass1.glsl
Normal file
8
dof-pass1.glsl
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = gl_FragCoord.xy / uResolution;
|
||||||
|
vec2 blurvec = vec2( 0 , 1 ) / uResolution;
|
||||||
|
|
||||||
|
float z = texture( u_Depth , uv ).x;
|
||||||
|
o_Color = depthDirectionalBlur( z , CoC( z ) , uv , blurvec );
|
||||||
|
}
|
15
dof-pass2.glsl
Normal file
15
dof-pass2.glsl
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 uv = gl_FragCoord.xy / uResolution;
|
||||||
|
float z = texture( u_Depth , uv ).x;
|
||||||
|
|
||||||
|
vec2 blurdir = vec2( 1.0 , 0.577350269189626 );
|
||||||
|
vec2 blurvec = normalize( blurdir ) / uResolution;
|
||||||
|
vec3 color0 = depthDirectionalBlur( z , CoC( z ) , uv , blurvec );
|
||||||
|
|
||||||
|
blurdir.x = -1;
|
||||||
|
blurvec = normalize( blurdir ) / uResolution;
|
||||||
|
vec3 color1 = depthDirectionalBlur( z , CoC( z ) , uv , blurvec );
|
||||||
|
|
||||||
|
o_Color = min( color0 , color1 );
|
||||||
|
}
|
81
dof.cc
Normal file
81
dof.cc
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
#include "externals.hh"
|
||||||
|
#include "utilities.hh"
|
||||||
|
#include "texture.hh"
|
||||||
|
#include "rendertarget.hh"
|
||||||
|
#include "dof.hh"
|
||||||
|
#include "profiling.hh"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static const std::string Name_( "DoF" );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PSTART() T_Profiler::Profiler.start( Name_ )
|
||||||
|
#define PEND() do { glFinish( ); T_Profiler::Profiler.end( Name_ ); } while ( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
T_DoFPass::T_DoFPass(
|
||||||
|
__rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rw__ T_Texture& imageInput ,
|
||||||
|
__rw__ T_Texture& depthInput )
|
||||||
|
: imageInput_( imageInput ) , depthInput_( depthInput ) ,
|
||||||
|
spPass1_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
|
spPass2_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
|
txPass1_( imageInput.width( ) , imageInput.height( ) ,
|
||||||
|
E_TexType::RGB16F ) ,
|
||||||
|
txOutput_( imageInput.width( ) , imageInput.height( ) ,
|
||||||
|
E_TexType::RGB16F ) ,
|
||||||
|
rtPass1_( T_RendertargetSetup( ).add( txPass1_ ).create( ) ) ,
|
||||||
|
rtPass2_( T_RendertargetSetup( ).add( txOutput_ ).create( ) ) ,
|
||||||
|
filterParams_{ 10 , 2 , 5 , 16 } ,
|
||||||
|
nSamples_( 16 )
|
||||||
|
{
|
||||||
|
spPass1_.addFile( "dof-common.glsl" );
|
||||||
|
spPass1_.addFile( "dof-pass1.glsl" );
|
||||||
|
spPass1_.load( );
|
||||||
|
|
||||||
|
spPass2_.addFile( "dof-common.glsl" );
|
||||||
|
spPass2_.addFile( "dof-pass2.glsl" );
|
||||||
|
spPass2_.load( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_DoFPass::render( )
|
||||||
|
{
|
||||||
|
PSTART( );
|
||||||
|
enum {
|
||||||
|
U_INPUT = 0 ,
|
||||||
|
U_DEPTH = 1 ,
|
||||||
|
U_PARAMS = 2 ,
|
||||||
|
U_SAMPLES = 3 ,
|
||||||
|
U_RES_TIME = 4
|
||||||
|
};
|
||||||
|
T_TextureBinding tb0( 0 ) , tb1( 1 );
|
||||||
|
if ( spPass1_.activate( ) && rtPass1_.activate( ) ) {
|
||||||
|
tb0.set( U_INPUT , imageInput_ );
|
||||||
|
tb1.set( U_DEPTH , depthInput_ );
|
||||||
|
tb0.bind( );
|
||||||
|
tb1.bind( );
|
||||||
|
glUniform4fv( U_PARAMS , 1 , filterParams_ );
|
||||||
|
glUniform1f( U_SAMPLES , nSamples_ );
|
||||||
|
glUniform3f( U_RES_TIME , imageInput_.width( ) ,
|
||||||
|
imageInput_.height( ) ,
|
||||||
|
0 );
|
||||||
|
glRectf( -1 , -1 , 1 , 1 );
|
||||||
|
}
|
||||||
|
if ( spPass2_.activate( ) && rtPass2_.activate( ) ) {
|
||||||
|
tb0.set( U_INPUT , txPass1_ );
|
||||||
|
tb1.set( U_DEPTH , depthInput_ );
|
||||||
|
tb0.bind( );
|
||||||
|
tb1.bind( );
|
||||||
|
glUniform4fv( U_PARAMS , 1 , filterParams_ );
|
||||||
|
glUniform1f( U_SAMPLES , nSamples_ );
|
||||||
|
glUniform3f( U_RES_TIME , imageInput_.width( ) ,
|
||||||
|
imageInput_.height( ) ,
|
||||||
|
0 );
|
||||||
|
glRectf( -1 , -1 , 1 , 1 );
|
||||||
|
}
|
||||||
|
PEND( );
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_DoFPass::makeUI( )
|
||||||
|
{
|
||||||
|
}
|
41
dof.hh
Normal file
41
dof.hh
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef REAL_BUILD
|
||||||
|
# define REAL_BUILD
|
||||||
|
# include "externals.hh"
|
||||||
|
# include "texture.hh"
|
||||||
|
# include "rendertarget.hh"
|
||||||
|
# include "utilities.hh"
|
||||||
|
# undef REAL_BUILD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct T_DoFPass
|
||||||
|
{
|
||||||
|
T_DoFPass( ) = delete;
|
||||||
|
T_DoFPass( T_DoFPass const& ) = delete;
|
||||||
|
T_DoFPass( T_DoFPass&& ) = delete;
|
||||||
|
|
||||||
|
T_DoFPass( __rw__ T_FilesWatcher& watcher ,
|
||||||
|
__rw__ T_Texture& imageInput ,
|
||||||
|
__rw__ T_Texture& depthInput );
|
||||||
|
|
||||||
|
void render( );
|
||||||
|
void makeUI( );
|
||||||
|
|
||||||
|
T_Texture& output( ) { return txOutput_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T_Texture& imageInput_;
|
||||||
|
T_Texture& depthInput_;
|
||||||
|
|
||||||
|
T_ShaderProgram spPass1_;
|
||||||
|
T_ShaderProgram spPass2_;
|
||||||
|
|
||||||
|
T_Texture txPass1_ , txOutput_;
|
||||||
|
T_Rendertarget rtPass1_ , rtPass2_;
|
||||||
|
|
||||||
|
// SharpDist/SharpRange/Falloff/MaxBlur
|
||||||
|
float filterParams_[ 4 ];
|
||||||
|
int nSamples_;
|
||||||
|
};
|
||||||
|
|
12
fsquad.glsl
Normal file
12
fsquad.glsl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#version 450 core
|
||||||
|
|
||||||
|
out gl_PerVertex {
|
||||||
|
vec4 gl_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main( void )
|
||||||
|
{
|
||||||
|
gl_Position = vec4(
|
||||||
|
vec2( gl_VertexID >> 1 , gl_VertexID & 1 ) * 2 - 1 ,
|
||||||
|
0 , 1 );
|
||||||
|
}
|
14
main.cc
14
main.cc
|
@ -4,8 +4,10 @@
|
||||||
#include "utilities.hh"
|
#include "utilities.hh"
|
||||||
#include "texture.hh"
|
#include "texture.hh"
|
||||||
#include "rendertarget.hh"
|
#include "rendertarget.hh"
|
||||||
#include "bloom.hh"
|
|
||||||
#include "raymarcher.hh"
|
#include "raymarcher.hh"
|
||||||
|
#include "dof.hh"
|
||||||
|
#include "bloom.hh"
|
||||||
|
#include "combine.hh"
|
||||||
#include "profiling.hh"
|
#include "profiling.hh"
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +34,9 @@ struct T_Main
|
||||||
std::unique_ptr< T_ShaderProgram > spCopy;
|
std::unique_ptr< T_ShaderProgram > spCopy;
|
||||||
|
|
||||||
std::unique_ptr< T_Raymarcher > raymarcher;
|
std::unique_ptr< T_Raymarcher > raymarcher;
|
||||||
|
std::unique_ptr< T_DoFPass > dofPass;
|
||||||
std::unique_ptr< T_BloomPass > bloomPass;
|
std::unique_ptr< T_BloomPass > bloomPass;
|
||||||
|
std::unique_ptr< T_CombinePass > combinePass;
|
||||||
|
|
||||||
void startIteration( );
|
void startIteration( );
|
||||||
void handleCapture( );
|
void handleCapture( );
|
||||||
|
@ -66,8 +70,12 @@ T_Main::T_Main( )
|
||||||
|
|
||||||
initProgram( );
|
initProgram( );
|
||||||
raymarcher = std::make_unique< T_Raymarcher >( watcher , 1280 , 720 );
|
raymarcher = std::make_unique< T_Raymarcher >( watcher , 1280 , 720 );
|
||||||
|
dofPass = std::make_unique< T_DoFPass >( watcher ,
|
||||||
|
raymarcher->output( ) , raymarcher->depth( ) );
|
||||||
bloomPass = std::make_unique< T_BloomPass >( watcher ,
|
bloomPass = std::make_unique< T_BloomPass >( watcher ,
|
||||||
raymarcher->output( ) );
|
raymarcher->output( ) );
|
||||||
|
combinePass = std::make_unique< T_CombinePass >( watcher ,
|
||||||
|
dofPass->output( ) , bloomPass->output( ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void T_Main::mainLoop( )
|
void T_Main::mainLoop( )
|
||||||
|
@ -166,7 +174,9 @@ void T_Main::makeUI( )
|
||||||
|
|
||||||
ImGui::Checkbox( "Profiler" , &T_Profiler::Profiler.uiEnabled( ) );
|
ImGui::Checkbox( "Profiler" , &T_Profiler::Profiler.uiEnabled( ) );
|
||||||
raymarcher->makeUI( );
|
raymarcher->makeUI( );
|
||||||
|
dofPass->makeUI( );
|
||||||
bloomPass->makeUI( );
|
bloomPass->makeUI( );
|
||||||
|
combinePass->makeUI( );
|
||||||
|
|
||||||
ImGui::End( );
|
ImGui::End( );
|
||||||
|
|
||||||
|
@ -177,7 +187,9 @@ void T_Main::render( )
|
||||||
{
|
{
|
||||||
T_Profiler::Profiler.start( "Render" );
|
T_Profiler::Profiler.start( "Render" );
|
||||||
raymarcher->render( );
|
raymarcher->render( );
|
||||||
|
dofPass->render( );
|
||||||
bloomPass->render( );
|
bloomPass->render( );
|
||||||
|
combinePass->render( );
|
||||||
glFinish( ); T_Profiler::Profiler.end( "Render" );
|
glFinish( ); T_Profiler::Profiler.end( "Render" );
|
||||||
|
|
||||||
glUseProgram( 0 );
|
glUseProgram( 0 );
|
||||||
|
|
2
map.glsl
2
map.glsl
|
@ -1,6 +1,6 @@
|
||||||
vec2 map( vec3 pos )
|
vec2 map( vec3 pos )
|
||||||
{
|
{
|
||||||
vec3 q = pos;
|
vec3 q = pos;
|
||||||
q.xy = mod( q.xy + 2. , 4. ) - 2.;
|
q.xy = mod( q.xy + 4. , 8. ) - 4.;
|
||||||
return vec2( length( q ) - 1.8 , step( 0. , 1.9 - length( pos.xy ) ) );
|
return vec2( length( q ) - 1.8 , step( 0. , 1.9 - length( pos.xy ) ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ layout( location = 7 ) uniform vec4 u_Render;
|
||||||
vec3 camPos , lookAt , camUp;
|
vec3 camPos , lookAt , camUp;
|
||||||
float nearPlane;
|
float nearPlane;
|
||||||
|
|
||||||
layout( location = 0 ) out vec4 color;
|
layout( location = 0 ) out vec3 o_Color;
|
||||||
|
layout( location = 1 ) out float o_Z;
|
||||||
|
|
||||||
void setCamFromUniforms( ) {
|
void setCamFromUniforms( ) {
|
||||||
camPos = u_CamPos;
|
camPos = u_CamPos;
|
||||||
|
|
|
@ -18,24 +18,36 @@ T_Raymarcher::T_Raymarcher(
|
||||||
__rd__ const uint32_t height )
|
__rd__ const uint32_t height )
|
||||||
: camera_( ) , program_( GL_FRAGMENT_SHADER , watcher ) ,
|
: camera_( ) , program_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||||
txOutput_( width , height , E_TexType::RGB16F ) ,
|
txOutput_( width , height , E_TexType::RGB16F ) ,
|
||||||
rtOutput_( T_RendertargetSetup( ).add( txOutput_ ).create( ) )
|
txDepth_( width , height , E_TexType::R16F ) ,
|
||||||
|
rtOutput_( T_RendertargetSetup( )
|
||||||
|
.add( txOutput_ )
|
||||||
|
.add( txDepth_ )
|
||||||
|
.create( ) )
|
||||||
{
|
{
|
||||||
|
glGenProgramPipelines( 1 , &pipeline_ );
|
||||||
|
|
||||||
program_.addFile( "raymarch-header.glsl" );
|
program_.addFile( "raymarch-header.glsl" );
|
||||||
program_.addFile( "map.glsl" );
|
program_.addFile( "map.glsl" );
|
||||||
program_.addFile( "raymarcher.glsl" );
|
program_.addFile( "raymarcher.glsl" );
|
||||||
program_.load( );
|
program_.load( );
|
||||||
|
|
||||||
|
auto& fsq( T_ShaderProgram::FullscreenQuad( watcher ) );
|
||||||
|
glUseProgramStages( pipeline_ , GL_VERTEX_SHADER_BIT , fsq.id( ) );
|
||||||
|
glUseProgramStages( pipeline_ , GL_FRAGMENT_SHADER_BIT , program_.id( ) );
|
||||||
|
assert( glGetError( ) == GL_NO_ERROR );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void T_Raymarcher::render( )
|
void T_Raymarcher::render( )
|
||||||
{
|
{
|
||||||
PSTART( );
|
PSTART( );
|
||||||
if ( !( program_.activate( ) && rtOutput_.activate( ) ) ) {
|
if ( ! rtOutput_.activate( ) ) {
|
||||||
PEND( );
|
PEND( );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glClearColor( 0 , 1 , 1 , 1 );
|
glBindProgramPipeline( pipeline_ );
|
||||||
|
glClearColor( 0 , 0 , 0 , 1 );
|
||||||
glClear( GL_COLOR_BUFFER_BIT );
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
enum {
|
enum {
|
||||||
U_TIME = 0 ,
|
U_TIME = 0 ,
|
||||||
|
@ -48,20 +60,21 @@ void T_Raymarcher::render( )
|
||||||
U_RAYMARCHER = 7 ,
|
U_RAYMARCHER = 7 ,
|
||||||
};
|
};
|
||||||
|
|
||||||
glUniform1f( U_TIME , 0 );
|
glProgramUniform1f( program_.id( ) , U_TIME , 0 );
|
||||||
glUniform2f( U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) );
|
glProgramUniform2f( program_.id( ) , U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) );
|
||||||
|
|
||||||
glUniform3fv( U_CAM_POS , 1 , &camera_.pos.x );
|
glProgramUniform3fv( program_.id( ) , U_CAM_POS , 1 , &camera_.pos.x );
|
||||||
glUniform3fv( U_LOOK_AT , 1 , &camera_.lookAt.x );
|
glProgramUniform3fv( program_.id( ) , U_LOOK_AT , 1 , &camera_.lookAt.x );
|
||||||
glUniform3fv( U_CAM_UP , 1 , &camera_.up.x );
|
glProgramUniform3fv( program_.id( ) , U_CAM_UP , 1 , &camera_.up.x );
|
||||||
glUniform1f( U_NEAR_PLANE , camera_.np );
|
glProgramUniform1f( program_.id( ) , U_NEAR_PLANE , camera_.np );
|
||||||
|
|
||||||
glUniform3f( U_LIGHT_DIR , 0 , 1 , 1 );
|
glProgramUniform3f( program_.id( ) , U_LIGHT_DIR , 0 , 1 , 1 );
|
||||||
|
|
||||||
glUniform4f( U_RAYMARCHER , rmIterations , rmStep ,
|
glProgramUniform4f( program_.id( ) , U_RAYMARCHER , rmIterations , rmStep ,
|
||||||
rmEpsilon , rmMaxDist );
|
rmEpsilon , rmMaxDist );
|
||||||
|
|
||||||
glRectf( -1, -1 , 1 , 1 );
|
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
||||||
|
glBindProgramPipeline( 0 );
|
||||||
|
|
||||||
PEND( );
|
PEND( );
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,8 @@ void main( )
|
||||||
bc = vec3( 0. );
|
bc = vec3( 0. );
|
||||||
}
|
}
|
||||||
|
|
||||||
color = vec4( bc , 1 );
|
o_Color = bc;
|
||||||
|
o_Z = r.x;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if ( r.y == -2 ) {
|
if ( r.y == -2 ) {
|
||||||
|
|
|
@ -27,13 +27,15 @@ struct T_Raymarcher
|
||||||
T_Camera& camera( ) noexcept { return camera_; }
|
T_Camera& camera( ) noexcept { return camera_; }
|
||||||
|
|
||||||
T_Texture& output( ) noexcept { return txOutput_; }
|
T_Texture& output( ) noexcept { return txOutput_; }
|
||||||
|
T_Texture& depth( ) noexcept { return txDepth_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T_Camera camera_;
|
T_Camera camera_;
|
||||||
|
|
||||||
|
GLuint pipeline_;
|
||||||
T_ShaderProgram program_;
|
T_ShaderProgram program_;
|
||||||
|
|
||||||
T_Texture txOutput_;
|
T_Texture txOutput_ , txDepth_;
|
||||||
T_Rendertarget rtOutput_;
|
T_Rendertarget rtOutput_;
|
||||||
|
|
||||||
int rmIterations = 128;
|
int rmIterations = 128;
|
||||||
|
|
|
@ -56,8 +56,8 @@ T_Rendertarget T_RendertargetSetup::create( )
|
||||||
glBindFramebuffer( GL_FRAMEBUFFER , id );
|
glBindFramebuffer( GL_FRAMEBUFFER , id );
|
||||||
for ( auto i = 0u ; i < nca ; i ++ ) {
|
for ( auto i = 0u ; i < nca ; i ++ ) {
|
||||||
#ifdef INTRUSIVE_TRACES
|
#ifdef INTRUSIVE_TRACES
|
||||||
printf( "init fb %p att %d tx %p level %d\n" ,
|
printf( "init %p fb %d att %d tx %p level %d\n" ,
|
||||||
this , i ,
|
this , id , i ,
|
||||||
colorAttachments_[ i ].texture ,
|
colorAttachments_[ i ].texture ,
|
||||||
colorAttachments_[ i ].level );
|
colorAttachments_[ i ].level );
|
||||||
#endif
|
#endif
|
||||||
|
@ -132,6 +132,10 @@ bool T_Rendertarget::activate( )
|
||||||
for ( auto i = 0u ; i < nCats_ ; i ++ ) {
|
for ( auto i = 0u ; i < nCats_ ; i ++ ) {
|
||||||
buffers_.push_back( GL_COLOR_ATTACHMENT0 + i );
|
buffers_.push_back( GL_COLOR_ATTACHMENT0 + i );
|
||||||
}
|
}
|
||||||
|
#ifdef INTRUSIVE_TRACES
|
||||||
|
printf( "fb %d: created buffers (%d items)\n" , id_ ,
|
||||||
|
int( buffers_.size( ) ) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
glBindFramebuffer( GL_FRAMEBUFFER , id_ );
|
glBindFramebuffer( GL_FRAMEBUFFER , id_ );
|
||||||
glViewport( 0 , 0 , width_ , height_ );
|
glViewport( 0 , 0 , width_ , height_ );
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "externals.hh"
|
#include "externals.hh"
|
||||||
|
#include "utilities.hh"
|
||||||
#include "texture.hh"
|
#include "texture.hh"
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,13 +63,17 @@ T_Texture::T_Texture(
|
||||||
|
|
||||||
uint32_t w = width , h = height;
|
uint32_t w = width , h = height;
|
||||||
for ( auto i = 0u ; i < levels ; i ++ ) {
|
for ( auto i = 0u ; i < levels ; i ++ ) {
|
||||||
|
#ifdef INTRUSIVE_TRACES
|
||||||
|
printf( "init %p txid %d lv %d sz %dx%d\n" , this , id_ ,
|
||||||
|
i , w , h );
|
||||||
|
#endif
|
||||||
glTexImage2D( GL_TEXTURE_2D , i , ifmt , w , h , 0 , fmt , dt , nullptr );
|
glTexImage2D( GL_TEXTURE_2D , i , ifmt , w , h , 0 , fmt , dt , nullptr );
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
h >>= 1;
|
h >>= 1;
|
||||||
assert( w && h );
|
assert( w && h );
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( glGetError( ) == GL_NO_ERROR );
|
GL_CHECK( );
|
||||||
}
|
}
|
||||||
|
|
||||||
T_Texture::~T_Texture( )
|
T_Texture::~T_Texture( )
|
||||||
|
|
48
utilities.cc
48
utilities.cc
|
@ -339,16 +339,46 @@ void T_ShaderProgram::load( )
|
||||||
}
|
}
|
||||||
|
|
||||||
T_ShaderCode sc( n );
|
T_ShaderCode sc( n );
|
||||||
|
printf( "LOAD PROGRAM" );
|
||||||
for ( auto i = 0u ; i < n ; i ++ ) {
|
for ( auto i = 0u ; i < n ; i ++ ) {
|
||||||
if ( chunksOrFiles_[ i ] ) {
|
if ( chunksOrFiles_[ i ] ) {
|
||||||
|
printf( " %d:(chunk)" , i );
|
||||||
sc.setPart( i , parts_[ i ].c_str( ) );
|
sc.setPart( i , parts_[ i ].c_str( ) );
|
||||||
} else if ( sc.loadPart( i , parts_[ i ].c_str( ) , errors_ ) ) {
|
} else {
|
||||||
|
printf( " %d:%s" , i , parts_[ i ].c_str( ) );
|
||||||
|
if ( sc.loadPart( i , parts_[ i ].c_str( ) , errors_ ) ) {
|
||||||
files_.watch( parts_[ i ] );
|
files_.watch( parts_[ i ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
printf( "\n" );
|
||||||
|
|
||||||
if ( errors_.size( ) == 0 ) {
|
if ( errors_.size( ) == 0 ) {
|
||||||
program_ = sc.createProgram( programType_ , errors_ );
|
program_ = sc.createProgram( programType_ , errors_ );
|
||||||
|
if ( program_ != 0 ) {
|
||||||
|
GLint x;
|
||||||
|
glGetProgramInterfaceiv( program_ , GL_PROGRAM_OUTPUT ,
|
||||||
|
GL_ACTIVE_RESOURCES , &x );
|
||||||
|
printf( "-> LOADED (%d output(s)" , x );
|
||||||
|
for ( int i = 0 ; i < x ; i ++ ) {
|
||||||
|
static const GLenum query[] = {
|
||||||
|
GL_NAME_LENGTH , GL_LOCATION
|
||||||
|
};
|
||||||
|
int output[ 2 ];
|
||||||
|
glGetProgramResourceiv( program_ , GL_PROGRAM_OUTPUT ,
|
||||||
|
i , 2 , query , 2 , nullptr ,
|
||||||
|
output );
|
||||||
|
|
||||||
|
char rName[ output[ 0 ] + 1 ];
|
||||||
|
glGetProgramResourceName( program_ ,
|
||||||
|
GL_PROGRAM_OUTPUT , i ,
|
||||||
|
sizeof( rName ) , nullptr ,
|
||||||
|
rName );
|
||||||
|
printf( "%s %s@%d" , i == 0 ? ":" : "" , rName ,
|
||||||
|
output[ 1 ] );
|
||||||
|
}
|
||||||
|
printf( ")\n" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( errors_.size( ) ) {
|
if ( errors_.size( ) ) {
|
||||||
|
@ -367,6 +397,22 @@ bool T_ShaderProgram::activate( ) const
|
||||||
return program_ != 0;
|
return program_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::unique_ptr< T_ShaderProgram > FsQuad_;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_ShaderProgram const& T_ShaderProgram::FullscreenQuad(
|
||||||
|
__rw__ T_FilesWatcher& watcher )
|
||||||
|
{
|
||||||
|
if ( !FsQuad_ ) {
|
||||||
|
FsQuad_ = std::make_unique< T_ShaderProgram >(
|
||||||
|
GL_VERTEX_SHADER , watcher );
|
||||||
|
FsQuad_->addFile( "fsquad.glsl" );
|
||||||
|
FsQuad_->load( );
|
||||||
|
}
|
||||||
|
return *FsQuad_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*= T_Camera =================================================================*/
|
/*= T_Camera =================================================================*/
|
||||||
|
|
||||||
|
|
17
utilities.hh
17
utilities.hh
|
@ -15,6 +15,18 @@ inline void reenableButtons( )
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define GL_CHECK( ) \
|
||||||
|
do { \
|
||||||
|
auto err_( glGetError( ) ); \
|
||||||
|
if ( err_ != GL_NO_ERROR ) { \
|
||||||
|
fprintf( stderr , "GL error %x in %s:%d\n" , \
|
||||||
|
err_ , __FILE__ , __LINE__ ); \
|
||||||
|
abort( ); \
|
||||||
|
} \
|
||||||
|
} while ( 0 )
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// Add some value to an angle, keeping it in [-180;180]
|
// Add some value to an angle, keeping it in [-180;180]
|
||||||
void updateAngle(
|
void updateAngle(
|
||||||
__rw__ float& initial ,
|
__rw__ float& initial ,
|
||||||
|
@ -143,6 +155,11 @@ struct T_ShaderProgram
|
||||||
void load( );
|
void load( );
|
||||||
bool activate( ) const;
|
bool activate( ) const;
|
||||||
|
|
||||||
|
GLuint id( ) const { return program_; }
|
||||||
|
|
||||||
|
static T_ShaderProgram const& FullscreenQuad(
|
||||||
|
__rw__ T_FilesWatcher& watcher );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T_WatchedFiles files_;
|
T_WatchedFiles files_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue