Skip to content

Commit e66b110

Browse files
committed
Add texture burn-in support
Also use shader cache in texture copier and a transformation matrix for flipping instead of flags.
1 parent af479c0 commit e66b110

File tree

6 files changed

+232
-40
lines changed

6 files changed

+232
-40
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
278278
endif()
279279
message(STATUS " Use system GLM: ${ENABLE_SYSTEM_GLM}")
280280
message(STATUS " Use system projectM-eval: ${ENABLE_SYSTEM_PROJECTM_EVAL}")
281+
if(ENABLE_SYSTEM_PROJECTM_EVAL)
282+
message(STATUS " projectM-eval version: ${projectM-Eval_VERSION}")
283+
endif()
281284
message(STATUS " Link UI with shared lib: ${ENABLE_SHARED_LINKING}")
282285
message(STATUS "")
283286
message(STATUS "Targets and applications:")

src/libprojectM/MilkdropPreset/MilkdropPreset.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
105105
}
106106

107107
// y-flip the previous frame and assign the flipped texture as "main"
108-
m_flipTexture.Draw(m_framebuffer.GetColorAttachmentTexture(m_previousFrameBuffer, 0), nullptr, true, false);
108+
m_flipTexture.Draw(*renderContext.shaderCache, m_framebuffer.GetColorAttachmentTexture(m_previousFrameBuffer, 0), nullptr, true, false);
109109
m_state.mainTexture = m_flipTexture.Texture();
110110

111111
// We now draw to the current framebuffer.
@@ -146,7 +146,7 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
146146
m_border.Draw(m_perFrameContext);
147147

148148
// y-flip the image for final compositing again
149-
m_flipTexture.Draw(m_framebuffer.GetColorAttachmentTexture(m_currentFrameBuffer, 0), nullptr, true, false);
149+
m_flipTexture.Draw(*renderContext.shaderCache, m_framebuffer.GetColorAttachmentTexture(m_currentFrameBuffer, 0), nullptr, true, false);
150150
m_state.mainTexture = m_flipTexture.Texture();
151151

152152
// We no longer need the previous frame image, use it to render the final composite.
@@ -158,7 +158,7 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
158158
if (!m_finalComposite.HasCompositeShader())
159159
{
160160
// Flip texture again in "previous" framebuffer as old-school effects are still upside down.
161-
m_flipTexture.Draw(m_framebuffer.GetColorAttachmentTexture(m_previousFrameBuffer, 0), m_framebuffer, m_previousFrameBuffer, true, false);
161+
m_flipTexture.Draw(*renderContext.shaderCache, m_framebuffer.GetColorAttachmentTexture(m_previousFrameBuffer, 0), m_framebuffer, m_previousFrameBuffer, true, false);
162162
}
163163

164164
// Swap framebuffer IDs for the next frame.
@@ -178,7 +178,7 @@ void MilkdropPreset::DrawInitialImage(const std::shared_ptr<Renderer::Texture>&
178178
m_framebuffer.SetSize(renderContext.viewportSizeX, renderContext.viewportSizeY);
179179

180180
// Render to previous framebuffer, as this is the image used to draw the next frame on.
181-
m_flipTexture.Draw(image, m_framebuffer, m_previousFrameBuffer);
181+
m_flipTexture.Draw(*renderContext.shaderCache, image, m_framebuffer, m_previousFrameBuffer);
182182
}
183183

184184
void MilkdropPreset::BindFramebuffer()

src/libprojectM/ProjectM.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929

3030
#include <Renderer/CopyTexture.hpp>
3131
#include <Renderer/PresetTransition.hpp>
32-
#include <Renderer/TextureManager.hpp>
3332
#include <Renderer/ShaderCache.hpp>
33+
#include <Renderer/TextureManager.hpp>
3434
#include <Renderer/TransitionShaderManager.hpp>
3535

3636
#include <UserSprites/SpriteManager.hpp>
@@ -177,11 +177,11 @@ void ProjectM::RenderFrame(uint32_t targetFramebufferObject /*= 0*/)
177177
}
178178
else
179179
{
180-
m_textureCopier->Draw(m_activePreset->OutputTexture(), false, false);
180+
m_textureCopier->Draw(*renderContext.shaderCache, m_activePreset->OutputTexture(), false, false);
181181
}
182182

183183
// Draw user sprites
184-
m_spriteManager->Draw(audioData, renderContext, targetFramebufferObject, { m_activePreset, m_transitioningPreset });
184+
m_spriteManager->Draw(audioData, renderContext, targetFramebufferObject, {m_activePreset, m_transitioningPreset});
185185

186186
m_frameCount++;
187187
m_previousFrameVolume = audioData.vol;
@@ -312,6 +312,23 @@ auto ProjectM::UserSpriteIdentifiers() const -> std::vector<uint32_t>
312312
return m_spriteManager->ActiveSpriteIdentifiers();
313313
}
314314

315+
void ProjectM::BurnInTexture(uint32_t openGlTextureId, int left, int top, int width, int height)
316+
{
317+
if (m_activePreset)
318+
{
319+
m_activePreset->BindFramebuffer();
320+
m_textureCopier->Draw(*m_shaderCache, openGlTextureId, m_windowWidth, m_windowHeight, left, top, width, height);
321+
}
322+
323+
if (m_transitioningPreset)
324+
{
325+
m_transitioningPreset->BindFramebuffer();
326+
m_textureCopier->Draw(*m_shaderCache, openGlTextureId, m_windowWidth, m_windowHeight, left, top, width, height);
327+
}
328+
329+
Renderer::Framebuffer::Unbind();
330+
}
331+
315332
void ProjectM::SetPresetLocked(bool locked)
316333
{
317334
// ToDo: Add a preset switch timer separate from the display timer and reset to 0 when

src/libprojectM/ProjectM.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,16 @@ class PROJECTM_EXPORT ProjectM
246246
*/
247247
auto UserSpriteIdentifiers() const -> std::vector<uint32_t>;
248248

249+
/**
250+
* @brief Draws the given texture on the active preset's main texture to get a "burn-in" effect.
251+
* @param openGlTextureId The OpenGL texture to draw onto the active preset(s).
252+
* @param left Left coordinate in pixels on the destination texture.
253+
* @param top Top coordinate in pixels on the destination texture.
254+
* @param width Width of the final image on the destination texture in pixels, can be negative to flip it horizontally.
255+
* @param height Height of the final image on the destination texture in pixels, can be negative to flip it vertically.
256+
*/
257+
void BurnInTexture(uint32_t openGlTextureId, int left, int top, int width, int height);
258+
249259
private:
250260
void Initialize();
251261

src/libprojectM/Renderer/CopyTexture.cpp

Lines changed: 145 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,11 @@ layout(location = 2) in vec2 tex_coord;
1717
1818
out vec2 fragment_tex_coord;
1919
20-
uniform ivec2 flip;
20+
uniform mat4 vertex_transformation;
2121
2222
void main() {
23-
gl_Position = vec4(position, 0.0, 1.0);
23+
gl_Position = vec4(position, 0.0, 1.0) * vertex_transformation;
2424
fragment_tex_coord = tex_coord;
25-
if (flip.x > 0)
26-
{
27-
fragment_tex_coord.s = 1.0 - fragment_tex_coord.s;
28-
}
29-
if (flip.y > 0)
30-
{
31-
fragment_tex_coord.t = 1.0 - fragment_tex_coord.t;
32-
}
3325
}
3426
)";
3527

@@ -53,13 +45,6 @@ CopyTexture::CopyTexture()
5345
{
5446
m_framebuffer.CreateColorAttachment(0, 0);
5547

56-
std::string vertexShader(ShaderVersion);
57-
std::string fragmentShader(ShaderVersion);
58-
vertexShader.append(CopyTextureVertexShader);
59-
fragmentShader.append(CopyTextureFragmentShader);
60-
61-
m_shader.CompileProgram(vertexShader, fragmentShader);
62-
6348
m_mesh.SetRenderPrimitiveType(Mesh::PrimitiveType::TriangleStrip);
6449

6550
m_mesh.SetVertexCount(4);
@@ -78,7 +63,9 @@ CopyTexture::CopyTexture()
7863
m_mesh.Update();
7964
}
8065

81-
void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, bool flipVertical, bool flipHorizontal)
66+
void CopyTexture::Draw(ShaderCache& shaderCache,
67+
const std::shared_ptr<class Texture>& originalTexture,
68+
bool flipVertical, bool flipHorizontal)
8269
{
8370
if (originalTexture == nullptr)
8471
{
@@ -87,10 +74,12 @@ void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, bo
8774

8875
// Just bind the texture and draw it to the currently bound buffer.
8976
originalTexture->Bind(0);
90-
Copy(flipVertical, flipHorizontal);
77+
Copy(shaderCache, flipVertical, flipHorizontal);
9178
}
9279

93-
void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, const std::shared_ptr<class Texture>& targetTexture,
80+
void CopyTexture::Draw(ShaderCache& shaderCache,
81+
const std::shared_ptr<class Texture>& originalTexture,
82+
const std::shared_ptr<class Texture>& targetTexture,
9483
bool flipVertical, bool flipHorizontal)
9584
{
9685
if (originalTexture == nullptr ||
@@ -128,7 +117,7 @@ void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, co
128117
m_framebuffer.GetAttachment(0, TextureAttachment::AttachmentType::Color, 0)->Texture(targetTexture);
129118
}
130119

131-
Copy(flipVertical, flipHorizontal);
120+
Copy(shaderCache, flipVertical, flipHorizontal);
132121

133122
// Rebind our internal texture.
134123
if (targetTexture)
@@ -139,7 +128,9 @@ void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, co
139128
Framebuffer::Unbind();
140129
}
141130

142-
void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, Framebuffer& framebuffer, int framebufferIndex,
131+
void CopyTexture::Draw(ShaderCache& shaderCache,
132+
const std::shared_ptr<class Texture>& originalTexture,
133+
Framebuffer& framebuffer, int framebufferIndex,
143134
bool flipVertical, bool flipHorizontal)
144135
{
145136
if (originalTexture == nullptr //
@@ -162,7 +153,7 @@ void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, Fr
162153
// Draw from unflipped texture
163154
originalTexture->Bind(0);
164155

165-
Copy(flipVertical, flipHorizontal);
156+
Copy(shaderCache, flipVertical, flipHorizontal);
166157

167158
// Swap texture attachments
168159
auto tempAttachment = framebuffer.GetAttachment(framebufferIndex, TextureAttachment::AttachmentType::Color, 0);
@@ -174,6 +165,74 @@ void CopyTexture::Draw(const std::shared_ptr<class Texture>& originalTexture, Fr
174165
Framebuffer::Unbind();
175166
}
176167

168+
void CopyTexture::Draw(ShaderCache& shaderCache,
169+
const std::shared_ptr<struct Texture>& originalTexture,
170+
const std::shared_ptr<struct Texture>& targetTexture,
171+
int left, int top, int width, int height)
172+
{
173+
if (originalTexture == nullptr ||
174+
originalTexture->Empty() ||
175+
targetTexture == nullptr ||
176+
targetTexture->Empty() ||
177+
originalTexture == targetTexture)
178+
{
179+
return;
180+
}
181+
182+
UpdateTextureSize(targetTexture->Width(), targetTexture->Height());
183+
184+
if (m_width == 0 || m_height == 0)
185+
{
186+
return;
187+
}
188+
189+
std::shared_ptr<class Texture> internalTexture;
190+
191+
m_framebuffer.Bind(0);
192+
193+
// Draw from original texture
194+
originalTexture->Bind(0);
195+
internalTexture = m_framebuffer.GetColorAttachmentTexture(0, 0);
196+
m_framebuffer.GetAttachment(0, TextureAttachment::AttachmentType::Color, 0)->Texture(targetTexture);
197+
198+
Copy(shaderCache, left, top, width, height);
199+
200+
// Rebind our internal texture.
201+
m_framebuffer.GetAttachment(0, TextureAttachment::AttachmentType::Color, 0)->Texture(internalTexture);
202+
203+
Framebuffer::Unbind();
204+
}
205+
206+
void CopyTexture::Draw(ShaderCache& shaderCache,
207+
GLuint originalTexture,
208+
int viewportWidth, int viewportHeight,
209+
int left, int top, int width, int height)
210+
{
211+
if (originalTexture == 0)
212+
{
213+
return;
214+
}
215+
216+
if (viewportWidth == 0 || viewportHeight == 0)
217+
{
218+
return;
219+
}
220+
221+
int oldWidth = m_width;
222+
int oldHeight = m_height;
223+
224+
m_width = viewportWidth;
225+
m_height = viewportHeight;
226+
227+
// Draw from original texture
228+
glActiveTexture(GL_TEXTURE0);
229+
glBindTexture(GL_TEXTURE_2D, originalTexture);
230+
Copy(shaderCache, left, top, width, height);
231+
232+
m_width = oldWidth;
233+
m_height = oldHeight;
234+
}
235+
177236
auto CopyTexture::Texture() -> std::shared_ptr<class Texture>
178237
{
179238
return m_framebuffer.GetColorAttachmentTexture(0, 0);
@@ -193,11 +252,18 @@ void CopyTexture::UpdateTextureSize(int width, int height)
193252
m_framebuffer.SetSize(m_width, m_height);
194253
}
195254

196-
void CopyTexture::Copy(bool flipVertical, bool flipHorizontal)
255+
void CopyTexture::Copy(ShaderCache& shaderCache,
256+
bool flipVertical, bool flipHorizontal)
197257
{
198-
m_shader.Bind();
199-
m_shader.SetUniformInt("texture_sampler", 0);
200-
m_shader.SetUniformInt2("flip", {flipHorizontal ? 1 : 0, flipVertical ? 1 : 0});
258+
glm::mat4x4 flipMatrix(1.0);
259+
260+
flipMatrix[0][0] = flipHorizontal ? -1.0 : 1.0;
261+
flipMatrix[1][1] = flipVertical ? -1.0 : 1.0;
262+
263+
std::shared_ptr<Shader> shader = BindShader(shaderCache);
264+
265+
shader->SetUniformInt("texture_sampler", 0);
266+
shader->SetUniformMat4x4("vertex_transformation", flipMatrix);
201267

202268
m_sampler.Bind(0);
203269

@@ -209,5 +275,57 @@ void CopyTexture::Copy(bool flipVertical, bool flipHorizontal)
209275
Shader::Unbind();
210276
}
211277

278+
void CopyTexture::Copy(ShaderCache& shaderCache,
279+
int left, int top, int width, int height)
280+
{
281+
glm::mat4x4 translationMatrix(1.0);
282+
translationMatrix[0][0] = static_cast<float>(width) / static_cast<float>(m_width);
283+
translationMatrix[1][1] = static_cast<float>(height) / static_cast<float>(m_height);
284+
285+
translationMatrix[3][0] = static_cast<float>(left) / static_cast<float>(m_width);
286+
translationMatrix[3][1] = static_cast<float>(top) / static_cast<float>(m_height);
287+
288+
std::shared_ptr<Shader> shader = BindShader(shaderCache);
289+
290+
shader->SetUniformInt("texture_sampler", 0);
291+
shader->SetUniformMat4x4("vertex_transformation", translationMatrix);
292+
293+
m_sampler.Bind(0);
294+
295+
m_mesh.Draw();
296+
297+
Mesh::Unbind();
298+
Sampler::Unbind(0);
299+
Shader::Unbind();
300+
}
301+
302+
std::shared_ptr<Shader> CopyTexture::BindShader(ShaderCache& shaderCache)
303+
{
304+
auto shader = m_shader.lock();
305+
306+
if (!shader)
307+
{
308+
shader = shaderCache.Get("copy_texture");
309+
}
310+
311+
if (!shader)
312+
{
313+
std::string vertexShader(ShaderVersion);
314+
std::string fragmentShader(ShaderVersion);
315+
vertexShader.append(CopyTextureVertexShader);
316+
fragmentShader.append(CopyTextureFragmentShader);
317+
318+
shader = std::make_shared<Shader>();
319+
shader->CompileProgram(vertexShader, fragmentShader);
320+
321+
m_shader = shader;
322+
shaderCache.Insert("copy_texture", shader);
323+
}
324+
325+
shader->Bind();
326+
327+
return shader;
328+
}
329+
212330
} // namespace Renderer
213331
} // namespace libprojectM

0 commit comments

Comments
 (0)