From 872ed6f93178571e0d5ceb93e3d852e589cdb5e5 Mon Sep 17 00:00:00 2001 From: HomeWorld Date: Sat, 4 Oct 2014 01:09:59 +0300 Subject: [PATCH] Use a separate texture when scene transitioning. Get rid of 1+ DrawSprite call(s) during scene transition. --- OBS.vcxproj | 1 + OBS.vcxproj.filters | 3 ++ Source/OBS.h | 4 +- Source/OBSCapture.cpp | 12 ++++++ Source/OBSVideoCapture.cpp | 56 +++++++++++++++----------- rundir/shaders/SceneTransition.pShader | 43 ++++++++++++++++++++ 6 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 rundir/shaders/SceneTransition.pShader diff --git a/OBS.vcxproj b/OBS.vcxproj index ddb204b60..73d2fa8f1 100644 --- a/OBS.vcxproj +++ b/OBS.vcxproj @@ -334,6 +334,7 @@ + diff --git a/OBS.vcxproj.filters b/OBS.vcxproj.filters index 97e43b437..95d9a3003 100644 --- a/OBS.vcxproj.filters +++ b/OBS.vcxproj.filters @@ -263,6 +263,9 @@ Resources + + Shaders + diff --git a/Source/OBS.h b/Source/OBS.h index 2e1d42818..7c883b10c 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -628,11 +628,13 @@ class OBS Texture *mainRenderTextures[NUM_RENDER_BUFFERS]; Texture *yuvRenderTextures[NUM_RENDER_BUFFERS]; + Texture *lastRenderTexture; Texture *transitionTexture; + bool bTransitioning; float transitionAlpha; - Shader *mainVertexShader, *mainPixelShader, *yuvScalePixelShader; + Shader *mainVertexShader, *mainPixelShader, *yuvScalePixelShader, *transitionPixelShader; Shader *solidVertexShader, *solidPixelShader; //--------------------------------------------------- diff --git a/Source/OBSCapture.cpp b/Source/OBSCapture.cpp index 914b5eeed..805fc7564 100644 --- a/Source/OBSCapture.cpp +++ b/Source/OBSCapture.cpp @@ -571,12 +571,17 @@ void OBS::Start(bool recordingOnly, bool replayBufferOnly) solidVertexShader = CreateVertexShaderFromFile(TEXT("shaders/DrawSolid.vShader")); solidPixelShader = CreatePixelShaderFromFile(TEXT("shaders/DrawSolid.pShader")); + transitionPixelShader = CreatePixelShaderFromFile(TEXT("shaders/SceneTransition.pShader")); + if(!mainVertexShader || !mainPixelShader) CrashError(TEXT("Unable to load DrawTexture shaders")); if(!solidVertexShader || !solidPixelShader) CrashError(TEXT("Unable to load DrawSolid shaders")); + if (!transitionPixelShader) + CrashError(TEXT("Unable to load SceneTransition shader")); + //------------------------------------------------------------------ CTSTR lpShader; @@ -608,6 +613,8 @@ void OBS::Start(bool recordingOnly, bool replayBufferOnly) yuvRenderTextures[i] = CreateRenderTarget(outputCX, outputCY, GS_BGRA, FALSE); } + transitionTexture = CreateRenderTarget(baseCX, baseCY, GS_BGRA, FALSE); + //------------------------------------------------------------- D3D10_TEXTURE2D_DESC td; @@ -1092,11 +1099,15 @@ void OBS::Stop(bool overrideKeepRecording, bool stopReplayBuffer) delete transitionTexture; transitionTexture = NULL; + delete lastRenderTexture; + lastRenderTexture = NULL; + //------------------------------------------------------------- delete mainVertexShader; delete mainPixelShader; delete yuvScalePixelShader; + delete transitionPixelShader; delete solidVertexShader; delete solidPixelShader; @@ -1104,6 +1115,7 @@ void OBS::Stop(bool overrideKeepRecording, bool stopReplayBuffer) mainVertexShader = NULL; mainPixelShader = NULL; yuvScalePixelShader = NULL; + transitionPixelShader = NULL; solidVertexShader = NULL; solidPixelShader = NULL; diff --git a/Source/OBSVideoCapture.cpp b/Source/OBSVideoCapture.cpp index 4493f64c9..7d44d5a5d 100644 --- a/Source/OBSVideoCapture.cpp +++ b/Source/OBSVideoCapture.cpp @@ -525,17 +525,13 @@ void OBS::DrawPreview(const Vect2 &renderFrameSize, const Vect2 &renderFrameOffs ClearColorBuffer(GetSysColor(COLOR_BTNFACE)); if(bTransitioning) - { - BlendFunction(GS_BLEND_ONE, GS_BLEND_ZERO); DrawSprite(transitionTexture, 0xFFFFFFFF, renderFrameOffset.x, renderFrameOffset.y, renderFrameOffset.x + renderFrameSize.x, renderFrameOffset.y + renderFrameSize.y); - BlendFunction(GS_BLEND_FACTOR, GS_BLEND_INVFACTOR, transitionAlpha); - } - - DrawSprite(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, - renderFrameOffset.x, renderFrameOffset.y, - renderFrameOffset.x + renderFrameSize.x, renderFrameOffset.y + renderFrameSize.y); + else + DrawSprite(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, + renderFrameOffset.x, renderFrameOffset.y, + renderFrameOffset.x + renderFrameSize.x, renderFrameOffset.y + renderFrameSize.y); } const float yuvFullMat[][16] = { @@ -622,6 +618,8 @@ void OBS::MainCaptureLoop() HANDLE hMatrix = yuvScalePixelShader->GetParameterByName(TEXT("yuvMat")); HANDLE hScaleVal = yuvScalePixelShader->GetParameterByName(TEXT("baseDimensionI")); + HANDLE hTransitionTime = transitionPixelShader->GetParameterByName(TEXT("transitionTime")); + //---------------------------------------- // x264 input buffers @@ -918,12 +916,12 @@ void OBS::MainCaptureLoop() if(bTransitioning) { - if(!transitionTexture) + if(!lastRenderTexture) { - transitionTexture = CreateTexture(baseCX, baseCY, GS_BGRA, NULL, FALSE, TRUE); - if(transitionTexture) + lastRenderTexture = CreateTexture(baseCX, baseCY, GS_BGRA, NULL, FALSE, TRUE); + if(lastRenderTexture) { - D3D10Texture *d3dTransitionTex = static_cast(transitionTexture); + D3D10Texture *d3dTransitionTex = static_cast(lastRenderTexture); D3D10Texture *d3dSceneTex = static_cast(mainRenderTextures[lastRenderTarget]); GetD3D()->CopyResource(d3dTransitionTex->texture, d3dSceneTex->texture); } @@ -932,8 +930,8 @@ void OBS::MainCaptureLoop() } else if(transitionAlpha >= 1.0f) { - delete transitionTexture; - transitionTexture = NULL; + delete lastRenderTexture; + lastRenderTexture = NULL; bTransitioning = false; } @@ -941,13 +939,27 @@ void OBS::MainCaptureLoop() if(bTransitioning) { - EnableBlending(TRUE); - transitionAlpha += float(fSeconds)*5.0f; + transitionAlpha += float(fSeconds) * 5.0f; if(transitionAlpha > 1.0f) transitionAlpha = 1.0f; + + SetRenderTarget(transitionTexture); + + Shader *oldPixelShader = GetCurrentPixelShader(); + LoadPixelShader(transitionPixelShader); + + transitionPixelShader->SetFloat(hTransitionTime, transitionAlpha); + LoadTexture(mainRenderTextures[curRenderTarget], 1U); + + DrawSpriteEx(lastRenderTexture, 0xFFFFFFFF, + 0, 0, baseSize.x, baseSize.y, 0.0f, 0.0f, 1.0f, 1.0f); + + LoadTexture(nullptr, 1U); + LoadPixelShader(oldPixelShader); } - else - EnableBlending(FALSE); + + EnableBlending(FALSE); + //------------------------------------ // render the mini view thingy @@ -1049,13 +1061,9 @@ void OBS::MainCaptureLoop() //because outputSize can be trimmed by up to three pixels due to 128-bit alignment. //using the scale function with outputSize can cause slightly inaccurate scaled images if(bTransitioning) - { - BlendFunction(GS_BLEND_ONE, GS_BLEND_ZERO); DrawSpriteEx(transitionTexture, 0xFFFFFFFF, 0.0f, 0.0f, scaleSize.x, scaleSize.y, 0.0f, 0.0f, 1.0f, 1.0f); - BlendFunction(GS_BLEND_FACTOR, GS_BLEND_INVFACTOR, transitionAlpha); - } - - DrawSpriteEx(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, 0.0f, 0.0f, outputSize.x, outputSize.y, 0.0f, 0.0f, 1.0f, 1.0f); + else + DrawSpriteEx(mainRenderTextures[curRenderTarget], 0xFFFFFFFF, 0.0f, 0.0f, outputSize.x, outputSize.y, 0.0f, 0.0f, 1.0f, 1.0f); //------------------------------------ diff --git a/rundir/shaders/SceneTransition.pShader b/rundir/shaders/SceneTransition.pShader new file mode 100644 index 000000000..a81d4266e --- /dev/null +++ b/rundir/shaders/SceneTransition.pShader @@ -0,0 +1,43 @@ +/******************************************************************************** + Copyright (C) 2014 Hugh Bailey + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +********************************************************************************/ + + +uniform Texture2D prevTexture; +uniform Texture2D currTexture; + +uniform float4 outputColor; +uniform float transitionTime; + +SamplerState textureSampler +{ + AddressU = Clamp; + AddressV = Clamp; + Filter = Linear; +}; + +struct VertData +{ + float4 pos : SV_Position; + float2 texCoord : TexCoord0; +}; + +float4 main(VertData input) : SV_Target +{ + float3 color = lerp(prevTexture.Sample(textureSampler, input.texCoord).rgb, currTexture.Sample(textureSampler, input.texCoord).rgb, transitionTime); + return float4(color, 1.0f) * outputColor; +}