Partial bloom (missing highpass filter)
This commit is contained in:
parent
83f885fa52
commit
f1628c0cd5
11 changed files with 258 additions and 19 deletions
20
bloom-combine.glsl
Normal file
20
bloom-combine.glsl
Normal 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
26
blur-pass.glsl
Normal 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;
|
||||
}
|
11
copy.glsl
11
copy.glsl
|
@ -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
110
main.cc
|
@ -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( );
|
||||
}
|
||||
|
||||
|
||||
|
|
2
map.glsl
2
map.glsl
|
@ -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 ) ) );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. );
|
||||
}
|
||||
|
|
|
@ -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( ) ,
|
||||
|
|
|
@ -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:
|
||||
|
|
71
texture.cc
71
texture.cc
|
@ -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 );
|
||||
}
|
||||
|
|
24
texture.hh
24
texture.hh
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue