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 \
|
||||
raymarcher.o \
|
||||
bloom.o \
|
||||
dof.o \
|
||||
combine.o \
|
||||
profiling.o
|
||||
|
||||
DEMO_DEPS = $(DEMO:%.o=.%.d)
|
||||
|
|
2
TODO
2
TODO
|
@ -11,6 +11,8 @@ Post-processing:
|
|||
* Lens dirt
|
||||
|
||||
Technical:
|
||||
* Use program pipelines
|
||||
* Use uniform buffers
|
||||
* GLSL with includes
|
||||
* GLSL constants generator
|
||||
* Common handling for parameters
|
||||
|
|
24
bloom.cc
24
bloom.cc
|
@ -20,16 +20,13 @@ T_BloomPass::T_BloomPass(
|
|||
spHighpass_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||
spDownsample_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||
spBlur_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||
spCombine_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||
//
|
||||
txBlur0_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
||||
txBlur1_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) ,
|
||||
//
|
||||
filterParams_{ 1.6 , 1.2 , .95 } ,
|
||||
blurWeights_{ 0.324 , 0.232 , 0.0855 , 0.0205 } ,
|
||||
blurSize_{ 1.3 } ,
|
||||
combineStrength_( 0.45 ) ,
|
||||
combineAttenuation_( 0.3 )
|
||||
blurSize_{ 1.3 }
|
||||
{
|
||||
txBlur0_.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" );
|
||||
spDownsample_.addFile( "downsample.glsl" );
|
||||
spBlur_.addFile( "blur-pass.glsl" );
|
||||
spCombine_.addFile( "bloom-combine.glsl" );
|
||||
|
||||
spHighpass_.load( );
|
||||
spDownsample_.load( );
|
||||
spBlur_.load( );
|
||||
spCombine_.load( );
|
||||
}
|
||||
|
||||
void T_BloomPass::render( )
|
||||
|
@ -113,21 +108,6 @@ void T_BloomPass::render( )
|
|||
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( );
|
||||
}
|
||||
|
||||
|
@ -140,6 +120,4 @@ void T_BloomPass::makeUI( )
|
|||
ImGui::DragFloat3( "Filter" , filterParams_ , .01f , 0.1 , 10 );
|
||||
ImGui::DragFloat4( "Weights" , blurWeights_ , .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 makeUI( );
|
||||
|
||||
T_Texture& output( ) { return txBlur0_; }
|
||||
|
||||
private:
|
||||
T_Texture& input_;
|
||||
|
||||
T_ShaderProgram spHighpass_;
|
||||
T_ShaderProgram spDownsample_;
|
||||
T_ShaderProgram spBlur_;
|
||||
T_ShaderProgram spCombine_;
|
||||
|
||||
T_Texture txBlur0_ , txBlur1_;
|
||||
std::vector< T_Rendertarget > rtBlur0_ , rtBlur1_;
|
||||
|
@ -37,6 +38,4 @@ struct T_BloomPass
|
|||
float filterParams_[ 3 ];
|
||||
float blurWeights_[ 4 ];
|
||||
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 "texture.hh"
|
||||
#include "rendertarget.hh"
|
||||
#include "bloom.hh"
|
||||
#include "raymarcher.hh"
|
||||
#include "dof.hh"
|
||||
#include "bloom.hh"
|
||||
#include "combine.hh"
|
||||
#include "profiling.hh"
|
||||
|
||||
|
||||
|
@ -32,7 +34,9 @@ struct T_Main
|
|||
std::unique_ptr< T_ShaderProgram > spCopy;
|
||||
|
||||
std::unique_ptr< T_Raymarcher > raymarcher;
|
||||
std::unique_ptr< T_DoFPass > dofPass;
|
||||
std::unique_ptr< T_BloomPass > bloomPass;
|
||||
std::unique_ptr< T_CombinePass > combinePass;
|
||||
|
||||
void startIteration( );
|
||||
void handleCapture( );
|
||||
|
@ -66,8 +70,12 @@ T_Main::T_Main( )
|
|||
|
||||
initProgram( );
|
||||
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 ,
|
||||
raymarcher->output( ) );
|
||||
combinePass = std::make_unique< T_CombinePass >( watcher ,
|
||||
dofPass->output( ) , bloomPass->output( ) );
|
||||
}
|
||||
|
||||
void T_Main::mainLoop( )
|
||||
|
@ -166,7 +174,9 @@ void T_Main::makeUI( )
|
|||
|
||||
ImGui::Checkbox( "Profiler" , &T_Profiler::Profiler.uiEnabled( ) );
|
||||
raymarcher->makeUI( );
|
||||
dofPass->makeUI( );
|
||||
bloomPass->makeUI( );
|
||||
combinePass->makeUI( );
|
||||
|
||||
ImGui::End( );
|
||||
|
||||
|
@ -177,7 +187,9 @@ void T_Main::render( )
|
|||
{
|
||||
T_Profiler::Profiler.start( "Render" );
|
||||
raymarcher->render( );
|
||||
dofPass->render( );
|
||||
bloomPass->render( );
|
||||
combinePass->render( );
|
||||
glFinish( ); T_Profiler::Profiler.end( "Render" );
|
||||
|
||||
glUseProgram( 0 );
|
||||
|
|
2
map.glsl
2
map.glsl
|
@ -1,6 +1,6 @@
|
|||
vec2 map( vec3 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 ) ) );
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ layout( location = 7 ) uniform vec4 u_Render;
|
|||
vec3 camPos , lookAt , camUp;
|
||||
float nearPlane;
|
||||
|
||||
layout( location = 0 ) out vec4 color;
|
||||
layout( location = 0 ) out vec3 o_Color;
|
||||
layout( location = 1 ) out float o_Z;
|
||||
|
||||
void setCamFromUniforms( ) {
|
||||
camPos = u_CamPos;
|
||||
|
|
|
@ -18,24 +18,36 @@ T_Raymarcher::T_Raymarcher(
|
|||
__rd__ const uint32_t height )
|
||||
: camera_( ) , program_( GL_FRAGMENT_SHADER , watcher ) ,
|
||||
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( "map.glsl" );
|
||||
program_.addFile( "raymarcher.glsl" );
|
||||
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( )
|
||||
{
|
||||
PSTART( );
|
||||
if ( !( program_.activate( ) && rtOutput_.activate( ) ) ) {
|
||||
if ( ! rtOutput_.activate( ) ) {
|
||||
PEND( );
|
||||
return;
|
||||
}
|
||||
|
||||
glClearColor( 0 , 1 , 1 , 1 );
|
||||
glBindProgramPipeline( pipeline_ );
|
||||
glClearColor( 0 , 0 , 0 , 1 );
|
||||
glClear( GL_COLOR_BUFFER_BIT );
|
||||
enum {
|
||||
U_TIME = 0 ,
|
||||
|
@ -48,20 +60,21 @@ void T_Raymarcher::render( )
|
|||
U_RAYMARCHER = 7 ,
|
||||
};
|
||||
|
||||
glUniform1f( U_TIME , 0 );
|
||||
glUniform2f( U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) );
|
||||
glProgramUniform1f( program_.id( ) , U_TIME , 0 );
|
||||
glProgramUniform2f( program_.id( ) , U_RESOLUTION , rtOutput_.width( ) , rtOutput_.height( ) );
|
||||
|
||||
glUniform3fv( U_CAM_POS , 1 , &camera_.pos.x );
|
||||
glUniform3fv( U_LOOK_AT , 1 , &camera_.lookAt.x );
|
||||
glUniform3fv( U_CAM_UP , 1 , &camera_.up.x );
|
||||
glUniform1f( U_NEAR_PLANE , camera_.np );
|
||||
glProgramUniform3fv( program_.id( ) , U_CAM_POS , 1 , &camera_.pos.x );
|
||||
glProgramUniform3fv( program_.id( ) , U_LOOK_AT , 1 , &camera_.lookAt.x );
|
||||
glProgramUniform3fv( program_.id( ) , U_CAM_UP , 1 , &camera_.up.x );
|
||||
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 );
|
||||
|
||||
glRectf( -1, -1 , 1 , 1 );
|
||||
glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 );
|
||||
glBindProgramPipeline( 0 );
|
||||
|
||||
PEND( );
|
||||
}
|
||||
|
|
|
@ -77,7 +77,8 @@ void main( )
|
|||
bc = vec3( 0. );
|
||||
}
|
||||
|
||||
color = vec4( bc , 1 );
|
||||
o_Color = bc;
|
||||
o_Z = r.x;
|
||||
|
||||
/*
|
||||
if ( r.y == -2 ) {
|
||||
|
|
|
@ -27,13 +27,15 @@ struct T_Raymarcher
|
|||
T_Camera& camera( ) noexcept { return camera_; }
|
||||
|
||||
T_Texture& output( ) noexcept { return txOutput_; }
|
||||
T_Texture& depth( ) noexcept { return txDepth_; }
|
||||
|
||||
private:
|
||||
T_Camera camera_;
|
||||
|
||||
GLuint pipeline_;
|
||||
T_ShaderProgram program_;
|
||||
|
||||
T_Texture txOutput_;
|
||||
T_Texture txOutput_ , txDepth_;
|
||||
T_Rendertarget rtOutput_;
|
||||
|
||||
int rmIterations = 128;
|
||||
|
|
|
@ -56,8 +56,8 @@ T_Rendertarget T_RendertargetSetup::create( )
|
|||
glBindFramebuffer( GL_FRAMEBUFFER , id );
|
||||
for ( auto i = 0u ; i < nca ; i ++ ) {
|
||||
#ifdef INTRUSIVE_TRACES
|
||||
printf( "init fb %p att %d tx %p level %d\n" ,
|
||||
this , i ,
|
||||
printf( "init %p fb %d att %d tx %p level %d\n" ,
|
||||
this , id , i ,
|
||||
colorAttachments_[ i ].texture ,
|
||||
colorAttachments_[ i ].level );
|
||||
#endif
|
||||
|
@ -132,6 +132,10 @@ bool T_Rendertarget::activate( )
|
|||
for ( auto i = 0u ; i < nCats_ ; 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_ );
|
||||
glViewport( 0 , 0 , width_ , height_ );
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "externals.hh"
|
||||
#include "utilities.hh"
|
||||
#include "texture.hh"
|
||||
|
||||
|
||||
|
@ -62,13 +63,17 @@ T_Texture::T_Texture(
|
|||
|
||||
uint32_t w = width , h = height;
|
||||
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 );
|
||||
w >>= 1;
|
||||
h >>= 1;
|
||||
assert( w && h );
|
||||
}
|
||||
|
||||
assert( glGetError( ) == GL_NO_ERROR );
|
||||
GL_CHECK( );
|
||||
}
|
||||
|
||||
T_Texture::~T_Texture( )
|
||||
|
|
48
utilities.cc
48
utilities.cc
|
@ -339,16 +339,46 @@ void T_ShaderProgram::load( )
|
|||
}
|
||||
|
||||
T_ShaderCode sc( n );
|
||||
printf( "LOAD PROGRAM" );
|
||||
for ( auto i = 0u ; i < n ; i ++ ) {
|
||||
if ( chunksOrFiles_[ i ] ) {
|
||||
printf( " %d:(chunk)" , i );
|
||||
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 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
if ( errors_.size( ) == 0 ) {
|
||||
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( ) ) {
|
||||
|
@ -367,6 +397,22 @@ bool T_ShaderProgram::activate( ) const
|
|||
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 =================================================================*/
|
||||
|
||||
|
|
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]
|
||||
void updateAngle(
|
||||
__rw__ float& initial ,
|
||||
|
@ -143,6 +155,11 @@ struct T_ShaderProgram
|
|||
void load( );
|
||||
bool activate( ) const;
|
||||
|
||||
GLuint id( ) const { return program_; }
|
||||
|
||||
static T_ShaderProgram const& FullscreenQuad(
|
||||
__rw__ T_FilesWatcher& watcher );
|
||||
|
||||
private:
|
||||
T_WatchedFiles files_;
|
||||
|
||||
|
|
Loading…
Reference in a new issue