Partial bloom (missing highpass filter)

This commit is contained in:
Emmanuel BENOîT 2017-09-30 17:58:48 +02:00
parent 83f885fa52
commit f1628c0cd5
11 changed files with 258 additions and 19 deletions

20
bloom-combine.glsl Normal file
View file

@ -0,0 +1,20 @@
#version 450 core
layout( location = 0 ) uniform sampler2D u_MainInput;
layout( location = 1 ) uniform sampler2D u_BlurInput;
layout( location = 2 ) uniform vec2 u_OutputSize;
layout( location = 0 ) out vec3 color;
void main( void )
{
vec2 tmp = gl_FragCoord.xy / u_OutputSize;
float f = .8;
color = textureLod( u_MainInput , tmp , 0 ).rgb;
for ( int i = 0 ; i < 5 ; i ++ ) {
color += f * textureLod( u_BlurInput , tmp , i ).rgb;
f *= .90;
}
color = color / ( color + 1. );
color = pow( color , vec3( 2.2 ) );
}

26
blur-pass.glsl Normal file
View file

@ -0,0 +1,26 @@
#version 450 core
layout( location = 0 ) uniform sampler2D u_InputTexture;
layout( location = 1 ) uniform vec2 u_OutputSize;
layout( location = 2 ) uniform vec2 u_InputSize;
layout( location = 3 ) uniform int u_SourceLOD;
layout( location = 4 ) uniform vec2 u_Direction;
layout( location = 5 ) uniform vec3 u_Weights;
layout( location = 0 ) out vec3 color;
void main( void )
{
vec2 tmp = gl_FragCoord.xy / u_OutputSize;
vec2 displace1 = vec2( 2.5 ) * u_Direction / u_InputSize;
vec2 displace2 = vec2( 5. ) * u_Direction / u_InputSize;
float wt = u_Weights.x + u_Weights.y * 2 + u_Weights.z * 2;
color = u_Weights.x * textureLod( u_InputTexture , tmp , u_SourceLOD ).xyz
+ u_Weights.y * (
textureLod( u_InputTexture , tmp + displace1 , u_SourceLOD ).xyz
+ textureLod( u_InputTexture , tmp - displace1 , u_SourceLOD ).xyz )
+ u_Weights.z * (
textureLod( u_InputTexture , tmp + displace2 , u_SourceLOD ).xyz
+ textureLod( u_InputTexture , tmp - displace2 , u_SourceLOD ).xyz );
color /= wt;
}

View file

@ -1,13 +1,20 @@
#version 450 core
layout( location = 0 ) uniform sampler2D u_InputTexture;
layout( location = 1 ) uniform int u_LOD;
layout( location = 0 ) out vec4 color;
void main( void )
{
#if 1
vec2 ts = textureSize( u_InputTexture , u_LOD );
vec2 tmp = gl_FragCoord.xy / vec2( 1280. , 720. );
color = textureLod( u_InputTexture , tmp , 0 );
//color.xy *= .75 + tmp * .25;
ivec2 pos = ivec2( ts * tmp );
color = texelFetch( u_InputTexture , pos , u_LOD );
#else
vec2 tmp = gl_FragCoord.xy / vec2( 1280. , 720. );
color = textureLod( u_InputTexture , tmp , float( u_LOD ) );
#endif
}

110
main.cc
View file

@ -30,10 +30,15 @@ struct T_Main
T_FilesWatcher watcher;
std::unique_ptr< T_ShaderProgram > spRaymarch;
std::unique_ptr< T_ShaderProgram > spCopy;
std::unique_ptr< T_ShaderProgram > spBlur;
std::unique_ptr< T_ShaderProgram > spBloomCombine;
std::unique_ptr< T_Texture > txRaymarchOutput;
std::unique_ptr< T_Rendertarget > rtRaymarchOutput;
std::unique_ptr< T_Texture > txBlur0 , txBlur1;
std::vector< std::unique_ptr< T_Rendertarget > > rtBlur0 , rtBlur1;
void startIteration( );
void handleCapture( );
void makeUI( );
@ -65,10 +70,22 @@ T_Main::T_Main( )
ImGui_ImplSdl_Init( window );
initProgram( );
txRaymarchOutput = std::make_unique< T_Texture >(
1280 , 720 , E_TexType::RGBA8 );
1280 , 720 , E_TexType::RGB16F );
rtRaymarchOutput = std::make_unique < T_Rendertarget >(
T_RendertargetSetup( ).add( *txRaymarchOutput ).create( ) );
txBlur0 = std::make_unique< T_Texture >( 1280 , 720 , E_TexType::RGB16F , 5 );
txBlur0->wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
txBlur1 = std::make_unique< T_Texture >( 1280 , 720 , E_TexType::RGB16F , 5 );
txBlur1->wrap( E_TexWrap::CLAMP_EDGE ).samplingMode( E_TexSampling::LINEAR );
for ( int i = 0 ; i < 5 ; i ++ ) {
rtBlur0.push_back( std::make_unique< T_Rendertarget >(
T_RendertargetSetup( ).add( *txBlur0 , i ).create( ) ) );
rtBlur1.push_back( std::make_unique< T_Rendertarget >(
T_RendertargetSetup( ).add( *txBlur1 , i ).create( ) ) );
}
}
void T_Main::mainLoop( )
@ -165,6 +182,8 @@ void T_Main::makeUI( )
void T_Main::render( )
{
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
if ( spRaymarch->activate( ) && rtRaymarchOutput->activate( ) ) {
glClearColor( 0 , 1 , 1 , 1 );
glClear( GL_COLOR_BUFFER_BIT );
@ -179,7 +198,6 @@ void T_Main::render( )
U_RENDER = 7 ,
};
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
glUniform1f( U_TIME , 0 );
glUniform2f( U_RESOLUTION , dspSize.x , dspSize.y );
@ -194,16 +212,91 @@ void T_Main::render( )
glRectf( -1, -1 , 1 , 1 );
}
if ( spBlur->activate( ) ) {
enum {
U_TEXTURE = 0 ,
U_OUTPUT_SIZE = 1 ,
U_INPUT_SIZE = 2 ,
U_SOURCE_LOD = 3 ,
U_DIRECTION = 4 ,
U_WEIGHTS = 5 ,
};
glUniform3f( U_WEIGHTS , 0.5 , 0.25 , 0.125 );
for ( int i = 0 ; i < 5 ; i ++ ) {
// IB RMO B0 B1 B0 B1 B0
// OB B0/0 B1/0 B0/1 B1/1 B0/2 B1/2
// SLOD: 0 0 0 1 1 2
// IW: W W W W/2 W/2 W/4
// OW: W W W/2 W/2 W/4 W/4
T_TextureBinding tb( 0 );
uint32_t w , h;
if ( i == 0 ) {
tb.set( U_TEXTURE , *txRaymarchOutput );
w = txRaymarchOutput->width( );
h = txRaymarchOutput->height( );
} else {
tb.set( U_TEXTURE , *txBlur1 );
w = txBlur1->width( ) >> ( i - 1 );
h = txBlur1->height( ) >> ( i - 1 );
}
const uint32_t slod = i > 0 ? ( i - 1 ) : 0;
rtBlur0[ i ]->activate( );
#ifdef INTRUSIVE_TRACES
printf( "BLUR %d/H IT %p SLOD %d IS %dx%d OS %dx%d\n" ,
i , &(*( i == 0 ? txRaymarchOutput : txBlur1 ) ) ,
slod , w , h , rtBlur0[ i ]->width( ) , rtBlur0[ i ]->height( ) );
#endif
glUniform2f( U_OUTPUT_SIZE , rtBlur0[ i ]->width( ) , rtBlur0[ i ]->height( ) );
glUniform1i( U_SOURCE_LOD , slod );
glUniform2f( U_INPUT_SIZE , w , h );
glUniform2f( U_DIRECTION , 1 , 0 );
tb.bind( );
glRectf( -1 , -1 , 1 , 1 );
rtBlur1[ i ]->activate( );
tb.set( U_TEXTURE , *txBlur0 );
tb.bind( );
glUniform2f( U_DIRECTION , 0 , 1 );
glUniform1i( U_SOURCE_LOD , i );
glUniform2f( U_INPUT_SIZE ,
rtBlur0[ i ]->width( ) ,
rtBlur0[ i ]->height( ) );
glRectf( -1 , -1 , 1 , 1 );
#ifdef INTRUSIVE_TRACES
printf( "BLUR %d/V IT %p SLOD %d IS %dx%d OS %dx%d\n" ,
i , &(*( txBlur0 ) ) ,
i , rtBlur0[ i ]->width( ) , rtBlur0[ i ]->height( ) ,
rtBlur0[ i ]->width( ) , rtBlur0[ i ]->height( ) );
#endif
}
}
T_Rendertarget::MainOutput( );
glClearColor( 1 , 0 , 1 , 1 );
glClear( GL_COLOR_BUFFER_BIT );
#if 0
if ( spCopy->activate( ) ) {
T_TextureBinding tb( 0 );
tb.set( 0 , *txRaymarchOutput );
tb.set( 0 , *txBlur1 );
tb.bind( );
glUniform1i( 1 , 3 );
glRectf( -1, -1 , 1 , 1 );
glBindTexture( GL_TEXTURE_2D , 0 );
}
#else
if ( spBloomCombine->activate( ) ) {
T_TextureBinding main( 0 ) , blur( 1 );
main.set( 0 , *txRaymarchOutput );
main.bind( );
blur.set( 1 , *txBlur1 );
blur.bind( );
glUniform2f( 2 , dspSize.x , dspSize.y );
glRectf( -1, -1 , 1 , 1 );
glBindTexture( GL_TEXTURE_2D , 0 );
}
#endif
glUseProgram( 0 );
ImGui::Render( );
@ -220,10 +313,17 @@ void T_Main::initProgram( )
spRaymarch->addFile( "raymarcher.glsl" );
spRaymarch->load( );
spCopy = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER ,
watcher );
spCopy = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , watcher );
spCopy->addFile( "copy.glsl" );
spCopy->load( );
spBlur = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , watcher );
spBlur->addFile( "blur-pass.glsl" );
spBlur->load( );
spBloomCombine = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , watcher );
spBloomCombine->addFile( "bloom-combine.glsl" );
spBloomCombine->load( );
}

View file

@ -2,5 +2,5 @@ vec2 map( vec3 pos )
{
vec3 q = pos;
q.xy = mod( q.xy + 2. , 4. ) - 2.;
return vec2( length( q ) - 2.1 , 0. );
return vec2( length( q ) - 1.8 , step( 0. , 1.9 - length( pos.xy ) ) );
}

View file

@ -12,7 +12,8 @@ layout( location = 7 ) uniform vec4 u_Render;
vec3 camPos , lookAt , camUp;
float nearPlane;
out vec4 color;
layout( location = 0 ) out vec4 color;
void setCamFromUniforms( ) {
camPos = u_CamPos;
lookAt = u_LookAt;

View file

@ -70,6 +70,9 @@ void main( )
float si = pow( clamp( ndoth , 0 , 1 ) , 4 ) ,
di = .6 + .3 * clamp( ndotl , 0 , 1 );
bc = mix( bc * di , vec3( 1. ) , si );
if ( r.y >= 1. ) {
bc += vec3( 5. , .1 , 4. ) * 4;
}
} else {
bc = vec3( 0. );
}

View file

@ -55,6 +55,10 @@ T_Rendertarget T_RendertargetSetup::create( )
glGenFramebuffers( 1 , &id );
glBindFramebuffer( GL_FRAMEBUFFER , id );
for ( auto i = 0u ; i < nca ; i ++ ) {
printf( "init fb %p att %d tx %p level %d\n" ,
this , i ,
colorAttachments_[ i ].texture ,
colorAttachments_[ i ].level );
glFramebufferTexture( GL_FRAMEBUFFER ,
GL_COLOR_ATTACHMENT0 + i ,
colorAttachments_[ i ].texture->id( ) ,

View file

@ -60,6 +60,9 @@ struct T_Rendertarget
bool activate( );
uint32_t width( ) const { return width_; }
uint32_t height( ) const { return height_; }
static void MainOutput( );
private:

View file

@ -7,7 +7,7 @@ T_Texture::T_Texture(
__rd__ const uint32_t height ,
__rd__ const E_TexType type ,
__rd__ const uint32_t levels )
: width_( width ) , height_( height )
: levels_( levels ) , width_( width ) , height_( height )
{
assert( levels > 0 );
@ -28,6 +28,18 @@ T_Texture::T_Texture(
dt = GL_FLOAT;
break;
case E_TexType::RGB8:
ifmt = GL_RGB8;
fmt = GL_RGB;
dt = GL_UNSIGNED_BYTE;
break;
case E_TexType::RGB16F:
ifmt = GL_RGB16F;
fmt = GL_RGB;
dt = GL_FLOAT;
break;
case E_TexType::R8:
ifmt = GL_R8;
fmt = GL_RED;
@ -41,11 +53,16 @@ T_Texture::T_Texture(
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_LOD , 0 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAX_LOD , levels - 1 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , levels - 1 );
glTexParameterf( GL_TEXTURE_2D , GL_TEXTURE_MIN_LOD , 0 );
glTexParameterf( GL_TEXTURE_2D , GL_TEXTURE_MAX_LOD , levels - 1 );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST );
uint32_t w = width , h = height;
for ( auto i = 0u ; i < levels ; i ++ ) {
printf( "init tx %p l %d w %d h %d\n" , this , i , w , h );
glTexImage2D( GL_TEXTURE_2D , i , ifmt , w , h , 0 , fmt , dt , nullptr );
w >>= 1;
h >>= 1;
@ -53,8 +70,6 @@ T_Texture::T_Texture(
}
assert( glGetError( ) == GL_NO_ERROR );
glBindTexture( GL_TEXTURE_2D , 0 );
}
T_Texture::~T_Texture( )
@ -63,6 +78,48 @@ T_Texture::~T_Texture( )
}
T_Texture& T_Texture::samplingMode(
__rd__ const E_TexSampling mode )
{
glBindTexture( GL_TEXTURE_2D , id_ );
GLenum min , max;
switch ( mode ) {
case E_TexSampling::NEAREST:
min = levels_ > 1 ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
max = GL_NEAREST;
break;
case E_TexSampling::LINEAR:
min = levels_ > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
max = GL_LINEAR;
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , min );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , max );
return *this;
}
T_Texture& T_Texture::wrap(
__rd__ const E_TexWrap mode )
{
GLenum gm;
switch ( mode ) {
case E_TexWrap::REPEAT:
gm = GL_REPEAT;
break;
case E_TexWrap::CLAMP_EDGE:
gm = GL_CLAMP_TO_EDGE;
break;
case E_TexWrap::CLAMP_BORDER:
gm = GL_CLAMP_TO_BORDER;
break;
}
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , gm );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , gm );
return *this;
}
/*============================================================================*/
@ -87,8 +144,8 @@ void T_TextureBinding::set(
void T_TextureBinding::bind( ) const
{
glActiveTexture( GL_TEXTURE0 + binding_ );
glBindTexture( GL_TEXTURE_2D , texture_ ? texture_->id( ) : 0 );
glBindTextureUnit( binding_ ,
texture_ ? texture_->id( ) : 0 );
glUniform1i( uniform_ , binding_ );
assert( glGetError( ) == GL_NO_ERROR );
}

View file

@ -4,14 +4,26 @@
#endif
enum class E_TexType
{
enum class E_TexType {
RGBA8 ,
RGBA16F ,
RGB8 ,
RGB16F ,
R8 ,
R16F ,
};
enum class E_TexSampling {
NEAREST ,
LINEAR ,
};
enum class E_TexWrap {
REPEAT ,
CLAMP_EDGE ,
CLAMP_BORDER
};
struct T_Texture
{
T_Texture( ) = delete;
@ -25,13 +37,19 @@ struct T_Texture
__rd__ const uint32_t levels = 1 );
~T_Texture( );
T_Texture& samplingMode(
__rd__ const E_TexSampling mode );
T_Texture& wrap(
__rd__ const E_TexWrap mode );
GLuint id( ) const noexcept { return id_; }
uint32_t levels( ) const noexcept { return levels_; }
uint32_t width( ) const noexcept { return width_; }
uint32_t height( ) const noexcept { return height_; }
private:
GLuint id_;
uint32_t width_ , height_;
uint32_t levels_ , width_ , height_;
};
struct T_TextureBinding