From ede948a2f828c2b1510fa0ac7a4192c128cac52d Mon Sep 17 00:00:00 2001 From: cupe Date: Mon, 11 Jul 2016 18:12:49 +0200 Subject: [PATCH 1/2] added texFFTIntegrated texture --- src/main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 50063ad7..059049c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -122,6 +122,7 @@ int main() int nDebugOutputHeight = 200; int nTexPreviewWidth = 64; float fFFTSmoothingFactor = 0.9f; // higher value, smoother FFT + float fFFTSlightSmoothingFactor = 0.6f; // higher value, smoother FFT char szConfig[65535]; FILE * fConf = fopen("config.json","rb"); @@ -193,6 +194,7 @@ int main() Renderer::Texture * texFFT = Renderer::Create1DR32Texture( FFT_SIZE ); Renderer::Texture * texFFTSmoothed = Renderer::Create1DR32Texture( FFT_SIZE ); + Renderer::Texture * texFFTIntegrated = Renderer::Create1DR32Texture( FFT_SIZE ); bool shaderInitSuccessful = false; char szShader[65535]; @@ -264,6 +266,11 @@ int main() static float fftDataSmoothed[FFT_SIZE]; memset(fftDataSmoothed, 0, sizeof(float) * FFT_SIZE); + static float fftDataSlightlySmoothed[FFT_SIZE]; + memset(fftDataSlightlySmoothed, 0, sizeof(float) * FFT_SIZE); + static float fftDataIntegrated[FFT_SIZE]; + memset(fftDataIntegrated, 0, sizeof(float) * FFT_SIZE); + // if we want to do some sort of frame capturing code // (for e.g. sending frames through the network) // we'd do it here, and then below. @@ -372,15 +379,26 @@ int main() if (FFT::GetFFT(fftData)) { Renderer::UpdateR32Texture( texFFT, fftData ); + + const static float maxIntegralValue = 1024.0f; for ( int i = 0; i < FFT_SIZE; i++ ) { fftDataSmoothed[i] = fftDataSmoothed[i] * fFFTSmoothingFactor + (1 - fFFTSmoothingFactor) * fftData[i]; + + fftDataSlightlySmoothed[i] = fftDataSlightlySmoothed[i] * fFFTSlightSmoothingFactor + (1 - fFFTSlightSmoothingFactor) * fftData[i]; + fftDataIntegrated[i] = fftDataIntegrated[i] + fftDataSlightlySmoothed[i]; + if (fftDataIntegrated[i] > maxIntegralValue) { + fftDataIntegrated[i] -= maxIntegralValue; + } } + Renderer::UpdateR32Texture( texFFTSmoothed, fftDataSmoothed ); + Renderer::UpdateR32Texture( texFFTIntegrated, fftDataIntegrated ); } Renderer::SetShaderTexture( "texFFT", texFFT ); Renderer::SetShaderTexture( "texFFTSmoothed", texFFTSmoothed ); + Renderer::SetShaderTexture( "texFFTIntegrated", texFFTIntegrated ); for (std::map::iterator it = textures.begin(); it != textures.end(); it++) { From ab53aa6d8552bfb58d1a92e55c949121591af160 Mon Sep 17 00:00:00 2001 From: cupe Date: Sat, 4 Mar 2023 14:28:17 +0100 Subject: [PATCH 2/2] render-to-texture instead of pixel readback, use 32bit texture as back buffer to allow better feedback effects/ no functional change for the user except fp32 RGBA in texPreviousFrame (was 8bit before) --- src/Renderer.h | 7 ++++ src/main.cpp | 21 ++++++++-- src/platform_glfw/Renderer.cpp | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/src/Renderer.h b/src/Renderer.h index 8a2d24a6..a375759c 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -96,6 +96,7 @@ void RenderFullscreenQuad(); bool ReloadShader( const char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize ); void SetShaderConstant( const char * szConstName, float x ); void SetShaderConstant( const char * szConstName, float x, float y ); +void SetShaderConstant( const char * szConstName, unsigned int num, float* data ); void StartTextRendering(); void SetTextRenderingViewport( Scintilla::PRectangle rect ); @@ -106,6 +107,7 @@ bool GrabFrame( void * pPixelBuffer ); // input buffer must be able to hold w * void Close(); Texture * CreateRGBA8Texture(); +Texture * CreateBackbufferTexture(); Texture * CreateRGBA8TextureFromFile( const char * szFilename ); Texture * CreateA8TextureFromData( int w, int h, const unsigned char * data ); Texture * Create1DR32Texture( int w ); @@ -114,6 +116,11 @@ void SetShaderTexture( const char * szTextureName, Texture * tex ); void BindTexture( Texture * tex ); // temporary function until all the quad rendering is moved to the renderer void ReleaseTexture( Texture * tex ); +void BindFramebuffer(); +void UnbindFramebuffer(); +void AttachBackbufferTexture( Texture * tex ); +void BlitFramebufferToScreen(); + void CopyBackbufferToTexture( Texture * tex ); void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d ); diff --git a/src/main.cpp b/src/main.cpp index 9c011539..c6d1f921 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -318,7 +318,8 @@ int main( int argc, const char * argv[] ) return 0; } - Renderer::Texture * texPreviousFrame = Renderer::CreateRGBA8Texture(); + Renderer::Texture * texFrontBuffer = Renderer::CreateBackbufferTexture(); + Renderer::Texture * texBackBuffer = Renderer::CreateBackbufferTexture(); Renderer::Texture * texFFT = Renderer::Create1DR32Texture( FFT_SIZE ); Renderer::Texture * texFFTSmoothed = Renderer::Create1DR32Texture( FFT_SIZE ); Renderer::Texture * texFFTIntegrated = Renderer::Create1DR32Texture( FFT_SIZE ); @@ -549,16 +550,27 @@ int main( int argc, const char * argv[] ) Renderer::SetShaderTexture( "texFFT", texFFT ); Renderer::SetShaderTexture( "texFFTSmoothed", texFFTSmoothed ); Renderer::SetShaderTexture( "texFFTIntegrated", texFFTIntegrated ); - Renderer::SetShaderTexture( "texPreviousFrame", texPreviousFrame ); + Renderer::SetShaderTexture( "texPreviousFrame", texFrontBuffer ); for ( std::map::iterator it = textures.begin(); it != textures.end(); it++ ) { Renderer::SetShaderTexture( it->first.c_str(), it->second ); } + + Renderer::AttachBackbufferTexture(texBackBuffer); + Renderer::BindFramebuffer(); + Renderer::RenderFullscreenQuad(); + + Renderer::UnbindFramebuffer(); + + Renderer::BlitFramebufferToScreen(); - Renderer::CopyBackbufferToTexture( texPreviousFrame ); + // swap front and back buffer: + Renderer::Texture * temp = texBackBuffer; + texBackBuffer = texFrontBuffer; + texFrontBuffer = temp; Renderer::StartTextRendering(); @@ -633,7 +645,8 @@ int main( int argc, const char * argv[] ) MIDI::Close(); FFT::Close(); - Renderer::ReleaseTexture( texPreviousFrame ); + Renderer::ReleaseTexture( texBackBuffer ); + Renderer::ReleaseTexture( texFrontBuffer ); Renderer::ReleaseTexture( texFFT ); Renderer::ReleaseTexture( texFFTSmoothed ); for ( std::map::iterator it = textures.begin(); it != textures.end(); it++ ) diff --git a/src/platform_glfw/Renderer.cpp b/src/platform_glfw/Renderer.cpp index 15f8be2b..9d537063 100644 --- a/src/platform_glfw/Renderer.cpp +++ b/src/platform_glfw/Renderer.cpp @@ -176,10 +176,20 @@ GLuint glhFullscreenQuadVA = 0; GLuint glhGUIVB = 0; GLuint glhGUIVA = 0; GLuint glhGUIProgram = 0; +GLuint glhFramebuffer = 0; int nWidth = 0; int nHeight = 0; +void checkError() +{ + GLenum err; + while((err = glGetError()) != GL_NO_ERROR) + { + printf( "GL error %d\n", err ); + } +} + void MatrixOrthoOffCenterLH( float * pout, float l, float r, float b, float t, float zn, float zf ) { memset( pout, 0, sizeof( float ) * 4 * 4 ); @@ -328,6 +338,8 @@ bool Open( Renderer::Settings * settings ) glGenVertexArrays( 1, &glhFullscreenQuadVA ); + glGenFramebuffers(1, &glhFramebuffer); + glhVertexShader = glCreateShader( GL_VERTEX_SHADER ); const char * szVertexShader = @@ -643,6 +655,14 @@ void RenderFullscreenQuad() glUseProgram( 0 ); } +void BlitFramebufferToScreen() +{ + glBindFramebuffer(GL_READ_FRAMEBUFFER, glhFramebuffer); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + checkError(); +} + bool ReloadShader( const char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize ) { GLuint prg = glCreateProgram(); @@ -699,6 +719,15 @@ void SetShaderConstant( const char * szConstName, float x, float y ) } } +void SetShaderConstant( const char * szConstName, unsigned int num, float* data ) +{ + GLint location = glGetUniformLocation( theShader, szConstName ); + if ( location != -1 ) + { + glProgramUniform1fv( theShader, location, num, data); + } +} + struct GLTexture : public Texture { GLuint ID; @@ -732,6 +761,34 @@ Texture * CreateRGBA8Texture() return tex; } +Texture * CreateBackbufferTexture() +{ + void * data = NULL; + GLenum internalFormat = GL_RGBA32F; + GLenum srcFormat = GL_RGBA; + GLenum format = GL_FLOAT; + + GLuint glTexId = 0; + glGenTextures( 1, &glTexId ); + glBindTexture( GL_TEXTURE_2D, glTexId ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glTexImage2D( GL_TEXTURE_2D, 0, internalFormat, nWidth, nHeight, 0, srcFormat, format, nullptr ); + + GLTexture * tex = new GLTexture(); + tex->width = nWidth; + tex->height = nHeight; + tex->ID = glTexId; + tex->type = TEXTURETYPE_2D; + tex->unit = textureUnit++; + checkError(); + return tex; +} + Texture * CreateRGBA8TextureFromFile( const char * szFilename ) { int comp = 0; @@ -957,6 +1014,26 @@ void BindTexture( Texture * tex ) } } +void BindFramebuffer() +{ + glBindFramebuffer(GL_FRAMEBUFFER, glhFramebuffer); + checkError(); +} + +void UnbindFramebuffer() +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); + checkError(); +} + +void AttachBackbufferTexture( Texture * tex ) +{ + BindFramebuffer(); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ( (GLTexture *) tex )->ID, 0); + checkError(); + UnbindFramebuffer(); +} + void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d ) { if ( !lastModeIsQuad )