From 4c91f688bb11b240bb0336db11511585202af1a6 Mon Sep 17 00:00:00 2001 From: nusan Date: Sun, 31 Jan 2021 18:28:07 +0100 Subject: [PATCH] Merge main repo "add support for texture that contains the contents of the previous frame" submit --- .gitignore | 1 + src/Renderer.h | 4 ++ src/main.cpp | 12 ++++ src/platform_glfw/Renderer.cpp | 65 +++++++++++++++++----- src/platform_w32_dx11/Renderer.cpp | 74 +++++++++++++++++++------ src/platform_w32_dx9/Renderer.cpp | 89 +++++++++++++++++++++--------- 6 files changed, 185 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index fc924e90..67907ad2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ Bonzomatic .obj tmp build +build.* .vs .DS_Store diff --git a/src/Renderer.h b/src/Renderer.h index 1d3ad423..e5a1ea74 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -60,6 +60,7 @@ namespace Renderer TEXTURETYPE type; }; + Texture * CreateRGBA8Texture(); Texture * CreateRGBA8TextureFromFile( const char * szFilename ); Texture * CreateA8TextureFromData( int w, int h, const unsigned char * data ); Texture * Create1DR32Texture( int w ); @@ -67,6 +68,9 @@ namespace Renderer 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 CopyBackbufferToTexture(Texture * tex); + struct Vertex { Vertex( float _x, float _y, unsigned int _c = 0xFFFFFFFF, float _u = 0.0, float _v = 0.0) : diff --git a/src/main.cpp b/src/main.cpp index e39ce991..dcc8c115 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -409,6 +409,7 @@ int main(int argc, const char *argv[]) return 0; } + Renderer::Texture * texPreviousFrame = Renderer::CreateRGBA8Texture(); Renderer::Texture * texFFT = Renderer::Create1DR32Texture( FFT_SIZE ); Renderer::Texture * texFFTSmoothed = Renderer::Create1DR32Texture( FFT_SIZE ); Renderer::Texture * texFFTIntegrated = Renderer::Create1DR32Texture( FFT_SIZE ); @@ -517,6 +518,7 @@ int main(int argc, const char *argv[]) Timer::Start(); float shaderTimeOffset = 0; float fNextTick = 0.1f; + float fLastTimeMS = Timer::GetTime(); float oldtime = Timer::GetTime() / 1000.0; while (!Renderer::WantsToQuit()) { @@ -705,6 +707,10 @@ int main(int argc, const char *argv[]) Renderer::SetShaderConstant( "fGlobalTime", time + shaderTimeOffset); Renderer::SetShaderConstant( "v2Resolution", Renderer::nWidth, Renderer::nHeight ); + float fTime = Timer::GetTime(); + Renderer::SetShaderConstant("fFrameTime", (fTime - fLastTimeMS) / 1000.0f); + fLastTimeMS = fTime; + if (Network::CanGrabMidiControls()) { for (auto it = networkParamCache.begin(); it != networkParamCache.end(); it++) { @@ -749,6 +755,7 @@ int main(int argc, const char *argv[]) Renderer::SetShaderTexture( "texFFT", texFFT ); Renderer::SetShaderTexture( "texFFTSmoothed", texFFTSmoothed ); Renderer::SetShaderTexture( "texFFTIntegrated", texFFTIntegrated ); + Renderer::SetShaderTexture( "texPreviousFrame", texPreviousFrame ); for (std::map::iterator it = textures.begin(); it != textures.end(); it++) { @@ -757,6 +764,8 @@ int main(int argc, const char *argv[]) Renderer::RenderFullscreenQuad(); + Renderer::CopyBackbufferToTexture(texPreviousFrame); + int TexPreviewOffset = bTexPreviewVisible ? nTexPreviewWidth + nMargin : 0; if (needEditorUpdate || Renderer::nSizeChanged) { @@ -870,6 +879,8 @@ int main(int argc, const char *argv[]) if (Renderer::nSizeChanged) { + Renderer::ReleaseTexture(texPreviousFrame); + texPreviousFrame = Renderer::CreateRGBA8Texture(); Capture::CaptureResize(Renderer::nWidth, Renderer::nHeight); } Renderer::nSizeChanged = false; @@ -904,6 +915,7 @@ int main(int argc, const char *argv[]) Network::Release(); + Renderer::ReleaseTexture(texPreviousFrame); 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 b7929fa1..6e8af514 100644 --- a/src/platform_glfw/Renderer.cpp +++ b/src/platform_glfw/Renderer.cpp @@ -124,10 +124,12 @@ namespace Renderer "\n" "uniform float fGlobalTime; // in seconds\n" "uniform vec2 v2Resolution; // viewport resolution (in pixels)\n" + "uniform float fFrameTime; // duration of the last frame, in seconds\n" "\n" "uniform sampler1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n" "uniform sampler1D texFFTSmoothed; // this one has longer falloff and less harsh transients\n" "uniform sampler1D texFFTIntegrated; // this is continually increasing\n" + "uniform sampler2D texPreviousFrame; // screenshot of the previous frame\n" "{%textures:begin%}" // leave off \n here "uniform sampler2D {%textures:name%};\n" "{%textures:end%}" // leave off \n here @@ -139,27 +141,27 @@ namespace Renderer "\n" "vec4 plas( vec2 v, float time )\n" "{\n" - " float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" - " return vec4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" + "\tfloat c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" + "\treturn vec4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" "}\n" "void main(void)\n" "{\n" - " vec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);\n" - " uv -= 0.5;\n" - " uv /= vec2(v2Resolution.y / v2Resolution.x, 1);\n" + "\tvec2 uv = vec2(gl_FragCoord.x / v2Resolution.x, gl_FragCoord.y / v2Resolution.y);\n" + "\tuv -= 0.5;\n" + "\tuv /= vec2(v2Resolution.y / v2Resolution.x, 1);\n" "\n" - " vec2 m;\n" - " m.x = atan(uv.x / uv.y) / 3.14;\n" - " m.y = 1 / length(uv) * .2;\n" - " float d = m.y;\n" + "\tvec2 m;\n" + "\tm.x = atan(uv.x / uv.y) / 3.14;\n" + "\tm.y = 1 / length(uv) * .2;\n" + "\tfloat d = m.y;\n" "\n" - " float f = texture( texFFT, d ).r * 100;\n" - " m.x += sin( fGlobalTime ) * 0.1;\n" - " m.y += fGlobalTime * 0.25;\n" + "\tfloat f = texture( texFFT, d ).r * 100;\n" + "\tm.x += sin( fGlobalTime ) * 0.1;\n" + "\tm.y += fGlobalTime * 0.25;\n" "\n" - " vec4 t = plas( m * 3.14, fGlobalTime ) / d;\n" - " t = clamp( t, 0.0, 1.0 );\n" - " out_color = f + t;\n" + "\tvec4 t = plas( m * 3.14, fGlobalTime ) / d;\n" + "\tt = clamp( t, 0.0, 1.0 );\n" + "\tout_color = f + t;\n" "}"; GLFWwindow * mWindow = NULL; @@ -733,6 +735,32 @@ namespace Renderer }; int textureUnit = 0; + + Texture * CreateRGBA8Texture() + { + void * data = NULL; + GLenum internalFormat = GL_SRGB8_ALPHA8; + GLenum srcFormat = GL_FLOAT; + GLenum format = GL_UNSIGNED_BYTE; + + 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); + + GLTexture * tex = new GLTexture(); + tex->width = nWidth; + tex->height = nHeight; + tex->ID = glTexId; + tex->type = TEXTURETYPE_2D; + tex->unit = textureUnit++; + return tex; + } + Texture * CreateRGBA8TextureFromFile( const char * szFilename ) { int comp = 0; @@ -858,6 +886,13 @@ namespace Renderer glDeleteTextures(1, &((GLTexture*)tex)->ID ); } + void CopyBackbufferToTexture(Texture * tex) + { + glActiveTexture(GL_TEXTURE0 + ((GLTexture *)tex)->unit); + glBindTexture(GL_TEXTURE_2D, ((GLTexture *)tex)->ID); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, nWidth, nHeight, 0); + } + ////////////////////////////////////////////////////////////////////////// // text rendering diff --git a/src/platform_w32_dx11/Renderer.cpp b/src/platform_w32_dx11/Renderer.cpp index 254df3a4..6ca8c19e 100644 --- a/src/platform_w32_dx11/Renderer.cpp +++ b/src/platform_w32_dx11/Renderer.cpp @@ -113,40 +113,42 @@ namespace Renderer "Texture1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n" "Texture1D texFFTSmoothed; // this one has longer falloff and less harsh transients\n" "Texture1D texFFTIntegrated; // this is continually increasing\n" + "Texture2D texPreviousFrame; // screenshot of the previous frame\n" "SamplerState smp;\n" "\n" "cbuffer constants\n" "{\n" - " float fGlobalTime; // in seconds\n" - " float2 v2Resolution; // viewport resolution (in pixels)\n" + "\tfloat fGlobalTime; // in seconds\n" + "\tfloat2 v2Resolution; // viewport resolution (in pixels)\n" + "\tfloat fFrameTime; // duration of the last frame, in seconds\n" "{%midi:begin%}" - " float {%midi:name%};\n" + "\tfloat {%midi:name%};\n" "{%midi:end%}" "}\n" "\n" "float4 plas( float2 v, float time )\n" "{\n" - " float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" - " return float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" + "\tfloat c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" + "\treturn float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" "}\n" "float4 main( float4 position : SV_POSITION, float2 TexCoord : TEXCOORD ) : SV_TARGET\n" "{\n" - " float2 uv = TexCoord;\n" - " uv -= 0.5;\n" - " uv /= float2(v2Resolution.y / v2Resolution.x, 1);" + "\tfloat2 uv = TexCoord;\n" + "\tuv -= 0.5;\n" + "\tuv /= float2(v2Resolution.y / v2Resolution.x, 1);" "\n" - " float2 m;\n" - " m.x = atan(uv.x / uv.y) / 3.14;\n" - " m.y = 1 / length(uv) * .2;\n" - " float d = m.y;\n" + "\tfloat2 m;\n" + "\tm.x = atan(uv.x / uv.y) / 3.14;\n" + "\tm.y = 1 / length(uv) * .2;\n" + "\tfloat d = m.y;\n" "\n" - " float f = texFFT.Sample( smp, d ).r * 100;\n" - " m.x += sin( fGlobalTime ) * 0.1;\n" - " m.y += fGlobalTime * 0.25;\n" + "\tfloat f = texFFT.Sample( smp, d ).r * 100;\n" + "\tm.x += sin( fGlobalTime ) * 0.1;\n" + "\tm.y += fGlobalTime * 0.25;\n" "\n" - " float4 t = plas( m * 3.14, fGlobalTime ) / d;\n" - " t = saturate( t );\n" - " return f + t;\n" + "\tfloat4 t = plas( m * 3.14, fGlobalTime ) / d;\n" + "\tt = saturate( t );\n" + "\treturn f + t;\n" "}"; char defaultVertexShader[65536] = @@ -917,6 +919,35 @@ namespace Renderer } int textureUnit = 0; + + Renderer::Texture * CreateRGBA8Texture() + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC)); + desc.Width = nWidth; + desc.Height = nHeight; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.SampleDesc.Count = 1; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ID3D11Texture2D * pTex = NULL; + + if (pDevice->CreateTexture2D(&desc, NULL, &pTex) != S_OK) + return NULL; + + DX11Texture * tex = new DX11Texture(); + tex->width = nWidth; + tex->height = nHeight; + tex->pTexture = pTex; + tex->type = TEXTURETYPE_2D; + tex->format = desc.Format; + CreateResourceView(tex); + return tex; + + } + Texture * CreateRGBA8TextureFromFile( const char * szFilename ) { int comp = 0; @@ -1062,6 +1093,13 @@ namespace Renderer delete tex; } + void CopyBackbufferToTexture(Texture * tex) + { + ID3D11Resource * pTex = ((DX11Texture *)tex)->pTexture; + + pContext->CopySubresourceRegion(pTex, 0, 0, 0, 0, pBackBuffer, 0, NULL); + } + ////////////////////////////////////////////////////////////////////////// // text rendering diff --git a/src/platform_w32_dx9/Renderer.cpp b/src/platform_w32_dx9/Renderer.cpp index 6c9ab8ea..3db4bc2c 100644 --- a/src/platform_w32_dx9/Renderer.cpp +++ b/src/platform_w32_dx9/Renderer.cpp @@ -117,6 +117,8 @@ namespace Renderer "// this one has longer falloff and less harsh transients\n" "texture texFFTIntegratedT; sampler1D texFFTIntegrated = sampler_state { Texture = ; }; \n" "// this is continually increasing\n" + "texture texPreviousFrameT; sampler2D texPreviousFrame = sampler_state { Texture = ; }; \n" + "// screenshot of the previous frame\n" "\n" "{%textures:begin%}" // leave off \n here "texture raw{%textures:name%}; sampler2D {%textures:name%} = sampler_state { Texture = ; };\n" @@ -126,31 +128,32 @@ namespace Renderer "float {%midi:name%};\n" "{%midi:end%}" "float fGlobalTime; // in seconds\n" + "float fFrameTime; // duration of the last frame, in seconds\n" "float2 v2Resolution; // viewport resolution (in pixels)\n" "\n" "float4 plas( float2 v, float time )\n" "{\n" - " float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" - " return float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" + "\tfloat c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n" + "\treturn float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n" "}\n" "float4 main( float2 TexCoord : TEXCOORD0 ) : COLOR0\n" "{\n" - " float2 uv = TexCoord;\n" - " uv -= 0.5;\n" - " uv /= float2(v2Resolution.y / v2Resolution.x, 1);" + "\tfloat2 uv = TexCoord;\n" + "\tuv -= 0.5;\n" + "\tuv /= float2(v2Resolution.y / v2Resolution.x, 1);" "\n" - " float2 m;\n" - " m.x = atan(uv.x / uv.y) / 3.14;\n" - " m.y = 1 / length(uv) * .2;\n" - " float d = m.y;\n" + "\tfloat2 m;\n" + "\tm.x = atan(uv.x / uv.y) / 3.14;\n" + "\tm.y = 1 / length(uv) * .2;\n" + "\tfloat d = m.y;\n" "\n" - " float f = tex1D( texFFT, d ).r * 100;\n" - " m.x += sin( fGlobalTime ) * 0.1;\n" - " m.y += fGlobalTime * 0.25;\n" + "\tfloat f = tex1D( texFFT, d ).r * 100;\n" + "\tm.x += sin( fGlobalTime ) * 0.1;\n" + "\tm.y += fGlobalTime * 0.25;\n" "\n" - " float4 t = plas( m * 3.14, fGlobalTime ) / d;\n" - " t = saturate( t );\n" - " return f + t;\n" + "\tfloat4 t = plas( m * 3.14, fGlobalTime ) / d;\n" + "\tt = saturate( t );\n" + "\treturn f + t;\n" "}"; char defaultVertexShader[65536] = "struct VS_INPUT_PP { float3 Pos : POSITION0; float2 TexCoord : TEXCOORD0; };\n" @@ -496,11 +499,12 @@ namespace Renderer D3DDECL_END() }; - static float pQuad[] = { - -1.0, -1.0, 0.0, 0.0, 0.0, - -1.0, 1.0, 0.0, 0.0, 1.0, - 1.0, -1.0, 0.0, 1.0, 0.0, - 1.0, 1.0, 0.0, 1.0, 1.0, + static float pQuad[] = + { + -1.0, -1.0, 0.0, 0.0 + 0.5 / (float)nWidth, 0.0 + 0.5 / (float)nHeight, + -1.0, 1.0, 0.0, 0.0 + 0.5 / (float)nWidth, 1.0 + 0.5 / (float)nHeight, + 1.0, -1.0, 0.0, 1.0 + 0.5 / (float)nWidth, 0.0 + 0.5 / (float)nHeight, + 1.0, 1.0, 0.0, 1.0 + 0.5 / (float)nWidth, 1.0 + 0.5 / (float)nHeight, }; pDevice->CreateVertexBuffer( 4 * 5 * sizeof(float), D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_TEX1, D3DPOOL_DEFAULT, &pFullscreenQuadVB, NULL); @@ -639,6 +643,24 @@ namespace Renderer }; int textureUnit = 0; + + Renderer::Texture * CreateRGBA8Texture() + { + LPDIRECT3DTEXTURE9 pTex = NULL; + pDevice->CreateTexture(nWidth, nHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTex, NULL); + + if (!pTex) + return NULL; + + DX9Texture * tex = new DX9Texture(); + tex->pTexture = pTex; + tex->width = nWidth; + tex->height = nHeight; + tex->type = TEXTURETYPE_2D; + return tex; + + } + Texture * CreateRGBA8TextureFromFile( const char * szFilename ) { LPDIRECT3DTEXTURE9 pTex = NULL; @@ -646,8 +668,8 @@ namespace Renderer HRESULT h = D3DXCreateTextureFromFileExA( pDevice, szFilename, - D3DX_DEFAULT, - D3DX_DEFAULT, + D3DX_DEFAULT_NONPOW2, + D3DX_DEFAULT_NONPOW2, 0, NULL, D3DFMT_FROM_FILE, @@ -750,6 +772,24 @@ namespace Renderer return tex; } + void ReleaseTexture(Texture * tex) + { + ((DX9Texture *)tex)->pTexture->Release(); + delete tex; + } + + void CopyBackbufferToTexture(Texture * tex) + { + LPDIRECT3DTEXTURE9 pTex = ((DX9Texture *)tex)->pTexture; + LPDIRECT3DSURFACE9 pSurf = NULL; + pTex->GetSurfaceLevel(0, &pSurf); + if (pSurf) + { + HRESULT res = pDevice->StretchRect(pBackBuffer, NULL, pSurf, NULL, D3DTEXF_LINEAR); + pSurf->Release(); + } + } + ////////////////////////////////////////////////////////////////////////// // text rendering @@ -780,11 +820,6 @@ namespace Renderer pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE ); } - void ReleaseTexture( Texture * tex ) - { - ((DX9Texture *)tex)->pTexture->Release(); - delete tex; - } int bufferPointer = 0; unsigned char buffer[GUIQUADVB_SIZE * sizeof(float) * 6];