mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-02-05 01:35:43 +00:00
Working on getting stuff being rendered again, focus on default waveform.
Fixed many typos, errors and crashes on the way.
This commit is contained in:
10
src/libprojectM/Audio/AudioConstants.hpp
Normal file
10
src/libprojectM/Audio/AudioConstants.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace libprojectM {
|
||||
namespace Audio {
|
||||
|
||||
static constexpr int WaveformSamples = 576; //!< Number of waveform data samples available for rendering a frame.
|
||||
static constexpr int SpectrumSamples = 512; //!< Number of spectrum analyzer samples.
|
||||
|
||||
} // namespace Audio
|
||||
} // namespace libprojectM
|
||||
@ -67,6 +67,27 @@ auto BeatDetect::GetPCMScale() const noexcept -> float
|
||||
}
|
||||
|
||||
|
||||
auto BeatDetect::GetFrameAudioData() const -> FrameAudioData
|
||||
{
|
||||
FrameAudioData data{};
|
||||
|
||||
pcm.GetPcm(data.waveformLeft.data(), CHANNEL_L, WaveformSamples);
|
||||
pcm.GetPcm(data.waveformRight.data(), CHANNEL_R, WaveformSamples);
|
||||
pcm.GetSpectrum(data.spectrumLeft.data(), CHANNEL_L, SpectrumSamples);
|
||||
|
||||
data.vol = vol;
|
||||
data.volAtt = volAtt;
|
||||
|
||||
data.bass = bass;
|
||||
data.bassAtt = bassAtt;
|
||||
data.mid = mid;
|
||||
data.midAtt = midAtt;
|
||||
data.treb = treb;
|
||||
data.trebAtt = trebAtt;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto BeatDetect::CalculateBeatStatistics() -> void
|
||||
{
|
||||
volOld = vol;
|
||||
@ -115,6 +136,7 @@ auto BeatDetect::CalculateBeatStatistics() -> void
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto BeatDetect::LowPassFilter::Update(float nextValue) noexcept -> void
|
||||
{
|
||||
m_current -= m_buffer[m_bufferPos] / bufferLength;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "FrameAudioData.hpp"
|
||||
#include "PCM.hpp"
|
||||
|
||||
#include <array>
|
||||
@ -50,6 +51,13 @@ public:
|
||||
[[nodiscard]]
|
||||
auto GetPCMScale() const noexcept -> float;
|
||||
|
||||
/**
|
||||
* @brief Returns a filled FrameAudioData structure for the current frame.
|
||||
* @return A FrameAudioData structure with waveform, spectrum beat detection data.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
auto GetFrameAudioData() const -> FrameAudioData;
|
||||
|
||||
float beatSensitivity{1.f};
|
||||
|
||||
float treb{0.f};
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "AudioConstants.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ add_library(projectM_main OBJECT
|
||||
resource.h
|
||||
wipemalloc.cpp
|
||||
wipemalloc.h
|
||||
)
|
||||
Audio/AudioConstants.hpp)
|
||||
|
||||
target_link_libraries(projectM_main
|
||||
PUBLIC
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "BlurTexture.hpp"
|
||||
|
||||
#include <Renderer/StaticGlShaders.h>
|
||||
#include <Renderer/StaticGlShaders.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
Border::Border()
|
||||
Border::Border(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
RenderItem::Init();
|
||||
}
|
||||
@ -11,54 +12,60 @@ Border::Border()
|
||||
void Border::InitVertexAttrib()
|
||||
{
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*) 0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void Border::Draw(RenderContext& context)
|
||||
void Border::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
//Draw Borders
|
||||
float of = outer_size * .5;
|
||||
float iff = inner_size * .5;
|
||||
float texof = 1.0 - of;
|
||||
// Draw Borders
|
||||
float const outerBorderSize = static_cast<float>(*presetPerFrameContext.ob_size) * .5f;
|
||||
float const innerBorderSize = static_cast<float>(*presetPerFrameContext.ib_size) * .5f;
|
||||
float const texelOffset = 1.0f - outerBorderSize;
|
||||
|
||||
float points[40] = {
|
||||
std::array<std::array<float, 4>, 10> const points = {{
|
||||
// Outer
|
||||
0, 0, of, 0,
|
||||
0, 1, of, texof,
|
||||
1, 1, texof, texof,
|
||||
1, 0, texof, of,
|
||||
of, 0, of, of,
|
||||
{0.0f, 0.0f, outerBorderSize, 0.0f},
|
||||
{0.0f, 1.0f, outerBorderSize, texelOffset},
|
||||
{1.0f, 1.0f, texelOffset, texelOffset},
|
||||
{1.0f, 0.0f, texelOffset, outerBorderSize},
|
||||
{outerBorderSize, 0.0f, outerBorderSize, outerBorderSize},
|
||||
|
||||
// Inner
|
||||
of, of, of + iff, of,
|
||||
of, texof, of + iff, texof - iff,
|
||||
texof, texof, texof - iff, texof - iff,
|
||||
texof, of, texof - iff, of + iff,
|
||||
of + iff, of, of + iff, of + iff,
|
||||
};
|
||||
{outerBorderSize, outerBorderSize, outerBorderSize + innerBorderSize, outerBorderSize},
|
||||
{outerBorderSize, texelOffset, outerBorderSize + innerBorderSize, texelOffset - innerBorderSize},
|
||||
{texelOffset, texelOffset, texelOffset - innerBorderSize, texelOffset - innerBorderSize},
|
||||
{texelOffset, outerBorderSize, texelOffset - innerBorderSize, outerBorderSize + innerBorderSize},
|
||||
{outerBorderSize + innerBorderSize, outerBorderSize, outerBorderSize + innerBorderSize, outerBorderSize + innerBorderSize},
|
||||
}};
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 40, NULL, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 40, points, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 40, points.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
glVertexAttrib4f(1,
|
||||
static_cast<float>(*presetPerFrameContext.ob_r),
|
||||
static_cast<float>(*presetPerFrameContext.ob_g),
|
||||
static_cast<float>(*presetPerFrameContext.ob_b),
|
||||
static_cast<float>(*presetPerFrameContext.ob_a));
|
||||
|
||||
glVertexAttrib4f(1, outer_r, outer_g, outer_b, outer_a * masterAlpha);
|
||||
|
||||
//no additive drawing for borders
|
||||
// No additive drawing for borders
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
|
||||
|
||||
glVertexAttrib4f(1, inner_r, inner_g, inner_b, inner_a * masterAlpha);
|
||||
glVertexAttrib4f(1,
|
||||
static_cast<float>(*presetPerFrameContext.ib_r),
|
||||
static_cast<float>(*presetPerFrameContext.ib_g),
|
||||
static_cast<float>(*presetPerFrameContext.ib_b),
|
||||
static_cast<float>(*presetPerFrameContext.ib_a));
|
||||
|
||||
// 1st pass for inner
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 10, 10);
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "PerFrameContext.hpp"
|
||||
#include "PresetState.hpp"
|
||||
|
||||
#include "Renderer/RenderItem.hpp"
|
||||
|
||||
/**
|
||||
@ -8,29 +11,18 @@
|
||||
class Border : public RenderItem
|
||||
{
|
||||
public:
|
||||
Border() = delete;
|
||||
|
||||
/**
|
||||
* Constructor. Initializes the required OpenGL data structures.
|
||||
*/
|
||||
Border();
|
||||
explicit Border(PresetState& presetState);
|
||||
|
||||
void InitVertexAttrib();
|
||||
void InitVertexAttrib() override;
|
||||
|
||||
/**
|
||||
* Draws the border.
|
||||
* @param context The render context data.
|
||||
* @param presetPerFrameContext The per-frame context variables.
|
||||
*/
|
||||
void Draw(RenderContext &context);
|
||||
void Draw(const PerFrameContext& presetPerFrameContext);
|
||||
|
||||
float outer_size{ 0.0 }; //!< Outer border width
|
||||
float outer_r{ 0.0 }; //!< Outer border color, red channel.
|
||||
float outer_g{ 0.0 }; //!< Outer border color, green channel.
|
||||
float outer_b{ 0.0 }; //!< Outer border color, blue channel.
|
||||
float outer_a{ 0.0 }; //!< Outer border color, alpha channel.
|
||||
|
||||
float inner_size{ 0.0 }; //!< Inner border width
|
||||
float inner_r{ 0.0 }; //!< Inner border color, red channel.
|
||||
float inner_g{ 0.0 }; //!< Inner border color, green channel.
|
||||
float inner_b{ 0.0 }; //!< Inner border color, blue channel.
|
||||
float inner_a{ 0.0 }; //!< Inner border color, alpha channel.
|
||||
private:
|
||||
PresetState& m_presetState; //!< The global preset state.
|
||||
};
|
||||
|
||||
@ -4,14 +4,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Audio/AudioConstants.hpp>
|
||||
|
||||
static constexpr int QVarCount = 32; //!< Number of Q variables available.
|
||||
static constexpr int TVarCount = 8; //!< Number of T variables available.
|
||||
|
||||
static constexpr int CustomWaveformCount = 4; //!< Number of custom waveforms (expression-driven) which can be used in a preset.
|
||||
static constexpr int CustomShapeCount = 4; //!< Number of custom shapes (expression-driven) which can be used in a preset.
|
||||
|
||||
static constexpr int WaveformSamples = 576; //!< Number of waveform data samples available for rendering a frame.
|
||||
static constexpr int SpectrumSamples = 512; //!< Number of spectrum analyzer samples.
|
||||
|
||||
static constexpr int RenderWaveformSamples = 480; //!< Number of custom waveform data samples available for rendering a frame.
|
||||
static constexpr int WaveformMaxPoints = 512; //!< Maximum number of waveform points.
|
||||
|
||||
@ -156,7 +156,7 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (m_image.empty())
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_presetState.renderContext.textureManager->getMainTexture()->texID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_presetState.mainTextureId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -170,7 +170,7 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
else
|
||||
{
|
||||
// No texture found, fall back to main texture.
|
||||
glBindTexture(GL_TEXTURE_2D, m_presetState.renderContext.textureManager->getMainTexture()->texID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_presetState.mainTextureId);
|
||||
}
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
@ -191,11 +191,9 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (*m_perFrameContext.sides + 2), vertexData.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
glUseProgram(m_presetState.renderContext.programID_v2f_c4f_t2f);
|
||||
|
||||
glUniformMatrix4fv(m_presetState.renderContext.uniform_v2f_c4f_t2f_vertex_transformation, 1, GL_FALSE,
|
||||
glm::value_ptr(m_presetState.renderContext.mat_ortho));
|
||||
glUniform1i(m_presetState.renderContext.uniform_v2f_c4f_t2f_frag_texture_sampler, 0);
|
||||
m_presetState.texturedShader.Bind();
|
||||
m_presetState.texturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
m_presetState.texturedShader.SetUniformInt("texture_sampler", 0);
|
||||
|
||||
glBindVertexArray(m_vaoID_texture);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, *m_perFrameContext.sides + 2);
|
||||
@ -211,10 +209,8 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(ShapeVertexShaderData) * (*m_perFrameContext.sides + 2), vertexData.data(), GL_DYNAMIC_DRAW);
|
||||
|
||||
glUseProgram(m_presetState.renderContext.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(m_presetState.renderContext.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE,
|
||||
glm::value_ptr(m_presetState.renderContext.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glBindVertexArray(m_vaoID_not_texture);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, *m_perFrameContext.sides + 2);
|
||||
@ -231,10 +227,9 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
points[i].y = vertexData[i + 1].point_y;
|
||||
}
|
||||
|
||||
glUseProgram(m_presetState.renderContext.programID_v2f_c4f);
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glUniformMatrix4fv(m_presetState.renderContext.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE,
|
||||
glm::value_ptr(m_presetState.renderContext.mat_ortho));
|
||||
glVertexAttrib4f(1,
|
||||
*m_perFrameContext.border_r,
|
||||
*m_perFrameContext.border_g,
|
||||
@ -288,7 +283,6 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floatPair) * (*m_perFrameContext.sides), points.data(), GL_DYNAMIC_DRAW);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, *m_perFrameContext.sides);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +292,8 @@ void CustomShape::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
#if USE_GLES == 0
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
#endif
|
||||
glUseProgram(0);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
void CustomShape::LoadPerFrameEvaluationVariables(const PerFrameContext& presetPerFrameContext)
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
static constexpr int CustomWaveformMaxSamples = std::max(RenderWaveformSamples, SpectrumSamples);
|
||||
static constexpr int CustomWaveformMaxSamples = std::max(RenderWaveformSamples, libprojectM::Audio::SpectrumSamples);
|
||||
|
||||
CustomWaveform::CustomWaveform(PresetState& presetState)
|
||||
: RenderItem()
|
||||
@ -72,12 +72,12 @@ void CustomWaveform::CompileCodeAndRunInitExpressions(const PerFrameContext& pre
|
||||
void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
// Some safety assertions if someone plays around and changes the values in the wrong way.
|
||||
static_assert(WaveformMaxPoints <= SpectrumSamples, "CustomWaveformMaxPoints is larger than SpectrumSamples");
|
||||
static_assert(WaveformMaxPoints <= WaveformSamples, "CustomWaveformMaxPoints is larger than WaveformSamples");
|
||||
static_assert(WaveformMaxPoints <= libprojectM::Audio::SpectrumSamples, "CustomWaveformMaxPoints is larger than SpectrumSamples");
|
||||
static_assert(WaveformMaxPoints <= libprojectM::Audio::WaveformSamples, "CustomWaveformMaxPoints is larger than WaveformSamples");
|
||||
static_assert(RenderWaveformSamples <= WaveformMaxPoints, "CustomWaveformSamples is larger than CustomWaveformMaxPoints");
|
||||
|
||||
int sampleCount{m_samples};
|
||||
int const maxSampleCount{m_spectrum ? SpectrumSamples : RenderWaveformSamples};
|
||||
int const maxSampleCount{m_spectrum ? libprojectM::Audio::SpectrumSamples : RenderWaveformSamples};
|
||||
sampleCount = std::min(sampleCount, maxSampleCount);
|
||||
sampleCount -= m_sep;
|
||||
|
||||
@ -163,9 +163,8 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
std::vector<ColoredPoint> pointsSmoothed(sampleCount * 2);
|
||||
auto smoothedVertexCount = SmoothWave(pointsTransformed.data(), sampleCount, pointsSmoothed.data());
|
||||
|
||||
glUseProgram(m_presetState.renderContext.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(m_presetState.renderContext.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(m_presetState.renderContext.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
if (m_additive)
|
||||
{
|
||||
@ -242,7 +241,7 @@ void CustomWaveform::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glUseProgram(0);
|
||||
Shader::Unbind();
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
@ -2,43 +2,44 @@
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
DarkenCenter::DarkenCenter()
|
||||
DarkenCenter::DarkenCenter(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
RenderItem::Init();
|
||||
}
|
||||
|
||||
void DarkenCenter::InitVertexAttrib()
|
||||
{
|
||||
float points_colors[6][6] = {
|
||||
{ 0.5, 0.5, 0, 0, 0, (3.0f / 32.0f) * masterAlpha },
|
||||
{ 0.45, 0.5, 0, 0, 0, 0 },
|
||||
{ 0.5, 0.45, 0, 0, 0, 0 },
|
||||
{ 0.55, 0.5, 0, 0, 0, 0 },
|
||||
{ 0.5, 0.55, 0, 0, 0, 0 },
|
||||
{ 0.45, 0.5, 0, 0, 0, 0 }};
|
||||
std::array<std::array<float, 6>, 6> points_colors = {{{0.5, 0.5, 0, 0, 0, 3.0f / 32.0f},
|
||||
{0.45, 0.5, 0, 0, 0, 0},
|
||||
{0.5, 0.45, 0, 0, 0, 0},
|
||||
{0.55, 0.5, 0, 0, 0, 0},
|
||||
{0.5, 0.55, 0, 0, 0, 0},
|
||||
{0.45, 0.5, 0, 0, 0, 0}}};
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*) 0); // points
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 6, (void*) (sizeof(float) * 2)); // colors
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 6, nullptr); // points
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 6, reinterpret_cast<void*>(sizeof(float) * 2)); // colors
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points_colors), points_colors, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points_colors), points_colors.data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
|
||||
void DarkenCenter::Draw(RenderContext& context)
|
||||
void DarkenCenter::Draw()
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "PresetState.hpp"
|
||||
|
||||
#include "Renderer/RenderItem.hpp"
|
||||
|
||||
/**
|
||||
@ -8,17 +10,17 @@
|
||||
class DarkenCenter : public RenderItem
|
||||
{
|
||||
public:
|
||||
DarkenCenter() = delete;
|
||||
|
||||
/**
|
||||
* Constructor. Initializes the required OpenGL data structures.
|
||||
*/
|
||||
DarkenCenter();
|
||||
explicit DarkenCenter(PresetState& presetState);
|
||||
|
||||
void InitVertexAttrib();
|
||||
|
||||
/**
|
||||
* Applies the darkening area.
|
||||
* @param context The render context data.
|
||||
*/
|
||||
void Draw(RenderContext &context);
|
||||
void Draw();
|
||||
|
||||
private:
|
||||
PresetState& m_presetState; //!< The global preset state.
|
||||
};
|
||||
|
||||
@ -4,130 +4,100 @@
|
||||
|
||||
#include "Renderer/ShaderEngine.hpp"
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
Filters::Filters(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
RenderItem::Init();
|
||||
}
|
||||
|
||||
void Brighten::InitVertexAttrib() {
|
||||
float points[4][2] = {{-0.5, -0.5},
|
||||
{-0.5, 0.5},
|
||||
{ 0.5, 0.5},
|
||||
{ 0.5, -0.5}};
|
||||
void Filters::InitVertexAttrib()
|
||||
{
|
||||
std::array<std::array<float, 2>, 4> points = {{{-0.5, -0.5},
|
||||
{-0.5, 0.5},
|
||||
{0.5, 0.5},
|
||||
{0.5, -0.5}}};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points.data(), GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void Brighten::Draw(RenderContext &context)
|
||||
void Filters::Brighten()
|
||||
{
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glBlendFunc(GL_ZERO, GL_DST_COLOR);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBlendFunc(GL_ZERO, GL_DST_COLOR);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
void Darken::InitVertexAttrib() {
|
||||
float points[4][2] = {{-0.5, -0.5},
|
||||
{-0.5, 0.5},
|
||||
{ 0.5, 0.5},
|
||||
{ 0.5, -0.5}};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void Darken::Draw(RenderContext &context)
|
||||
void Filters::Darken()
|
||||
{
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
glBlendFunc(GL_ZERO, GL_DST_COLOR);
|
||||
glBlendFunc(GL_ZERO, GL_DST_COLOR);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
void Invert::InitVertexAttrib() {
|
||||
float points[4][2] = {{-0.5, -0.5},
|
||||
{-0.5, 0.5},
|
||||
{ 0.5, 0.5},
|
||||
{ 0.5, -0.5}};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void Invert::Draw(RenderContext &context)
|
||||
void Filters::Invert()
|
||||
{
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
void Solarize::InitVertexAttrib() {
|
||||
float points[4][2] = {{-0.5, -0.5},
|
||||
{-0.5, 0.5},
|
||||
{ 0.5, 0.5},
|
||||
{ 0.5, -0.5}};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void Solarize::Draw(RenderContext &context)
|
||||
void Filters::Solarize()
|
||||
{
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_COLOR);
|
||||
glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_COLOR);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glBlendFunc(GL_DST_COLOR, GL_ONE);
|
||||
glDrawArrays(GL_TRIANGLE_FAN,0,4);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBlendFunc(GL_DST_COLOR, GL_ONE);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
@ -1,35 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "Renderer/RenderItem.hpp"
|
||||
#include "PresetState.hpp"
|
||||
|
||||
class Brighten : public RenderItem
|
||||
#include <Renderer/RenderItem.hpp>
|
||||
|
||||
class Filters : public RenderItem
|
||||
{
|
||||
public:
|
||||
Brighten(){ Init(); }
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
};
|
||||
Filters() = delete;
|
||||
explicit Filters(PresetState& presetState);
|
||||
|
||||
class Darken : public RenderItem
|
||||
{
|
||||
public:
|
||||
Darken(){ Init(); }
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
};
|
||||
|
||||
class Invert : public RenderItem
|
||||
{
|
||||
public:
|
||||
Invert(){ Init(); }
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
};
|
||||
/**
|
||||
* @brief Brightens the image
|
||||
*/
|
||||
void Brighten();
|
||||
|
||||
class Solarize : public RenderItem
|
||||
{
|
||||
public:
|
||||
Solarize(){ Init(); }
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
void Darken();
|
||||
|
||||
void Invert();
|
||||
|
||||
void Solarize();
|
||||
|
||||
private:
|
||||
PresetState& m_presetState; //!< The global preset state.
|
||||
};
|
||||
|
||||
@ -34,7 +34,11 @@
|
||||
MilkdropPreset::MilkdropPreset(std::istream& presetData)
|
||||
: m_perFrameContext(m_state.globalMemory, &m_state.globalRegisters)
|
||||
, m_perPixelContext(m_state.globalMemory, &m_state.globalRegisters)
|
||||
, m_motionVectors(m_state)
|
||||
, m_waveform(m_state)
|
||||
, m_darkenCenter(m_state)
|
||||
, m_border(m_state)
|
||||
, m_filters(m_state)
|
||||
{
|
||||
Load(presetData);
|
||||
}
|
||||
@ -44,7 +48,11 @@ MilkdropPreset::MilkdropPreset(const std::string& absoluteFilePath)
|
||||
: m_absoluteFilePath(absoluteFilePath)
|
||||
, m_perFrameContext(m_state.globalMemory, &m_state.globalRegisters)
|
||||
, m_perPixelContext(m_state.globalMemory, &m_state.globalRegisters)
|
||||
, m_motionVectors(m_state)
|
||||
, m_waveform(m_state)
|
||||
, m_darkenCenter(m_state)
|
||||
, m_border(m_state)
|
||||
, m_filters(m_state)
|
||||
{
|
||||
Load(absoluteFilePath);
|
||||
}
|
||||
@ -139,6 +147,7 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
|
||||
{
|
||||
m_state.audioData = audioData;
|
||||
m_state.renderContext = renderContext;
|
||||
m_state.mainTextureId = m_framebuffer.GetColorAttachmentTexture(1, 0);
|
||||
|
||||
// Update framebuffer size if needed
|
||||
m_framebuffer.SetSize(renderContext.viewportSizeX, renderContext.viewportSizeY);
|
||||
@ -147,27 +156,24 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
|
||||
PerFrameUpdate();
|
||||
|
||||
// Motion vector field. Drawn to the previous frame texture before warping it.
|
||||
m_framebuffer.Bind(1);
|
||||
// ToDo: Move this to the draw call and pass in the per-frame context.
|
||||
m_motionVectors.r = static_cast<float>(*m_perFrameContext.mv_r);
|
||||
m_motionVectors.g = static_cast<float>(*m_perFrameContext.mv_g);
|
||||
m_motionVectors.b = static_cast<float>(*m_perFrameContext.mv_b);
|
||||
m_motionVectors.a = static_cast<float>(*m_perFrameContext.mv_a);
|
||||
m_motionVectors.length = static_cast<float>(*m_perFrameContext.mv_l);
|
||||
m_motionVectors.x_num = static_cast<float>(*m_perFrameContext.mv_x);
|
||||
m_motionVectors.y_num = static_cast<float>(*m_perFrameContext.mv_y);
|
||||
m_motionVectors.x_offset = static_cast<float>(*m_perFrameContext.mv_dx);
|
||||
m_motionVectors.y_offset = static_cast<float>(*m_perFrameContext.mv_dy);
|
||||
m_motionVectors.Draw(renderContext);
|
||||
//m_framebuffer.Bind(1);
|
||||
m_motionVectors.Draw(m_perFrameContext);
|
||||
|
||||
// We now draw to the first framebuffer, but read from the second one for warping.
|
||||
m_framebuffer.BindRead(1);
|
||||
m_framebuffer.BindDraw(0);
|
||||
//m_framebuffer.BindRead(1);
|
||||
//m_framebuffer.BindDraw(0);
|
||||
|
||||
// TEST: Copy for now, no warp
|
||||
//glBlitFramebuffer(0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// 0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
// Draw previous frame image warped via per-pixel mesh and warp shader
|
||||
// ToDo: ComputeGridAlphaValues
|
||||
// ToDo: Per-Pixel and warp stuff
|
||||
|
||||
//m_framebuffer.Bind(0);
|
||||
|
||||
// Draw audio-data-related stuff
|
||||
for (auto& shape : m_customShapes)
|
||||
{
|
||||
@ -177,23 +183,35 @@ void MilkdropPreset::RenderFrame(const libprojectM::Audio::FrameAudioData& audio
|
||||
{
|
||||
wave->Draw(m_perFrameContext);
|
||||
}
|
||||
m_waveform.Draw();
|
||||
m_waveform.Draw(m_perFrameContext);
|
||||
|
||||
// ToDo: Sprite drawing would go here.
|
||||
// Done in DrawSprites() in Milkdrop
|
||||
if (*m_perFrameContext.darken_center > 0)
|
||||
{
|
||||
m_darkenCenter.Draw();
|
||||
}
|
||||
m_border.Draw(m_perFrameContext);
|
||||
|
||||
// Todo: Song title anim would go here
|
||||
|
||||
// Copy pixels from framebuffer index 0 to 1
|
||||
m_framebuffer.BindRead(0);
|
||||
m_framebuffer.BindDraw(1);
|
||||
glBlitFramebuffer(0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
//m_framebuffer.BindRead(0);
|
||||
//m_framebuffer.BindDraw(1);
|
||||
//glBlitFramebuffer(0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// 0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
// ToDo: Apply composite shader
|
||||
m_framebuffer.Bind(0);
|
||||
//m_framebuffer.Bind(0);
|
||||
|
||||
// ToDo: Draw user sprites (can have evaluated code)
|
||||
|
||||
// TEST: Copy result to default framebuffer
|
||||
//glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
//glBlitFramebuffer(0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// 0, 0, renderContext.viewportSizeX, renderContext.viewportSizeY,
|
||||
// GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -107,5 +107,9 @@ private:
|
||||
std::array<std::unique_ptr<CustomWaveform>, CustomWaveformCount> m_customWaveforms; //!< Custom waveforms in this preset.
|
||||
std::array<std::unique_ptr<CustomShape>, CustomShapeCount> m_customShapes; //!< Custom shapes in this preset.
|
||||
|
||||
DarkenCenter m_darkenCenter; //!< Center darkening effect.
|
||||
Border m_border; //!< Inner/outer borders.
|
||||
Filters m_filters; //!< Various post-processing filters, applied if no composite shader is used.
|
||||
|
||||
friend class MilkdropPresetFactory;
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
#include "PresetState.hpp"
|
||||
|
||||
#include "Renderer/StaticGlShaders.h"
|
||||
#include "Renderer/StaticGlShaders.hpp"
|
||||
|
||||
#include <GLSLGenerator.h>
|
||||
#include <HLSLParser.h>
|
||||
|
||||
@ -2,74 +2,164 @@
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
MotionVectors::MotionVectors()
|
||||
MotionVectors::MotionVectors(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
RenderItem::Init();
|
||||
}
|
||||
|
||||
void MotionVectors::InitVertexAttrib() {
|
||||
void MotionVectors::InitVertexAttrib()
|
||||
{
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
void MotionVectors::Draw(const RenderContext& context)
|
||||
void MotionVectors::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
// ToDo: Implement the actual Milkdop behaviour here, including reverse propagation.
|
||||
float intervalx=1.0/x_num;
|
||||
float intervaly=1.0/y_num;
|
||||
int countX = static_cast<int>(*presetPerFrameContext.mv_x);
|
||||
int countY = static_cast<int>(*presetPerFrameContext.mv_y);
|
||||
|
||||
if (countX <= 0 || countY <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float divertX = static_cast<float>(*presetPerFrameContext.mv_x) - static_cast<float>(countX);
|
||||
float divertY = static_cast<float>(*presetPerFrameContext.mv_y) - static_cast<float>(countY);
|
||||
|
||||
if (countX > 64)
|
||||
{
|
||||
countX = 64;
|
||||
divertX = 0.0f;
|
||||
}
|
||||
if (countY > 48)
|
||||
{
|
||||
countY = 48;
|
||||
divertY = 0.0f;
|
||||
}
|
||||
|
||||
auto divertX2 = static_cast<float>(*presetPerFrameContext.mv_dx);
|
||||
auto divertY2 = static_cast<float>(*presetPerFrameContext.mv_dy);
|
||||
|
||||
auto lengthMultiplier = static_cast<float>(*presetPerFrameContext.mv_l);
|
||||
|
||||
// Clamp X/Y diversions to 0..1
|
||||
if (divertX < 0.0f)
|
||||
{
|
||||
divertX = 0.0f;
|
||||
}
|
||||
if (divertX > 1.0f)
|
||||
{
|
||||
divertX = 1.0f;
|
||||
}
|
||||
if (divertY < 0.0f)
|
||||
{
|
||||
divertY = 0.0f;
|
||||
}
|
||||
if (divertY > 1.0f)
|
||||
{
|
||||
divertY = 1.0f;
|
||||
}
|
||||
|
||||
float const inverseWidth = 1.0f / static_cast<float>(m_presetState.viewportWidth);
|
||||
float const minimalLength = 1.0f * inverseWidth;
|
||||
|
||||
struct Point {
|
||||
float x{};
|
||||
float y{};
|
||||
};
|
||||
|
||||
std::vector<Point> lineVertices(static_cast<std::size_t>(countX + 1) * 2); // countX + 1 lines for each grid row, 2 vertices each.
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
if (x_num + y_num < 600)
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glVertexAttrib4f(1,
|
||||
static_cast<float>(*presetPerFrameContext.mv_r),
|
||||
static_cast<float>(*presetPerFrameContext.mv_g),
|
||||
static_cast<float>(*presetPerFrameContext.mv_b),
|
||||
static_cast<float>(*presetPerFrameContext.mv_a));
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
|
||||
for (int y = 0; y < countY; y++)
|
||||
{
|
||||
int size = x_num * y_num ;
|
||||
float const posY = (static_cast<float>(y) + 0.25f) / (static_cast<float>(countY) + divertY + 0.25f - 1.0f) - divertY2;
|
||||
|
||||
floatPair *points = new float[size][2];
|
||||
|
||||
for (int x=0;x<(int)x_num;x++)
|
||||
if (posY > 0.0001f && posY < 0.9999f)
|
||||
{
|
||||
for(int y=0;y<(int)y_num;y++)
|
||||
int vertex = 0;
|
||||
for (int x = 0; x < countX; x++)
|
||||
{
|
||||
float lx, ly;
|
||||
lx = x_offset+x*intervalx;
|
||||
ly = y_offset+y*intervaly;
|
||||
float const posX = (static_cast<float>(x) + 0.25f) / (static_cast<float>(countX) + divertX + 0.25f - 1.0f) + divertX2;
|
||||
|
||||
points[(x * (int)y_num) + y][0] = lx;
|
||||
points[(x * (int)y_num) + y][1] = ly;
|
||||
if (posX > 0.0001f && posX < 0.9999f)
|
||||
{
|
||||
float posX2{};
|
||||
float posY2{};
|
||||
|
||||
// Uses the warp mesh texture transformation to get the motion direction of this point.
|
||||
ReversePropagatePoint(posX, posY, posX2, posY2);
|
||||
|
||||
// Enforce minimum trail length
|
||||
{
|
||||
float distX = posX2 - posX;
|
||||
float distY = posY2 - posY;
|
||||
|
||||
distX *= lengthMultiplier;
|
||||
distY *= lengthMultiplier;
|
||||
|
||||
float length = sqrtf(distX * distX + distY * distY);
|
||||
if (length > minimalLength)
|
||||
{
|
||||
}
|
||||
else if (length > 0.00000001f)
|
||||
{
|
||||
length = minimalLength / length;
|
||||
distX *= length;
|
||||
distY *= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
distX = minimalLength;
|
||||
distY = minimalLength;
|
||||
}
|
||||
|
||||
posX2 = posX + distX;
|
||||
posY2 = posY + distY;
|
||||
}
|
||||
|
||||
// Assign line vertices
|
||||
lineVertices.at(vertex).x = posX * 2.0f - 1.0f;
|
||||
lineVertices.at(vertex).y = posY * 2.0f - 1.0f;
|
||||
lineVertices.at(vertex + 1).x = posX2 * 2.0f - 1.0f;
|
||||
lineVertices.at(vertex + 1).y = posY2 * 2.0f - 1.0f;
|
||||
|
||||
vertex += 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a row of lines.
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(Point) * lineVertices.size(), lineVertices.data(), GL_DYNAMIC_DRAW);
|
||||
glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(lineVertices.size()));
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floatPair) * size, nullptr, GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(floatPair) * size, points, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
delete[] points;
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
|
||||
#ifndef GL_TRANSITION
|
||||
if (length <= 0.0) {
|
||||
glPointSize(1.0);
|
||||
} else {
|
||||
glPointSize(length);
|
||||
}
|
||||
#endif
|
||||
|
||||
glUniform1f(context.uniform_v2f_c4f_vertex_point_size, length);
|
||||
glVertexAttrib4f(1, r, g, b, a * masterAlpha);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
|
||||
// ToDo: Milkdrop draws lines in the direction of motion, not just points!
|
||||
glDrawArrays(GL_POINTS,0,size);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
Shader::Unbind();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void MotionVectors::ReversePropagatePoint(float posX1, float posY1, float& posX2, float& posY2)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "PerFrameContext.hpp"
|
||||
#include "PresetState.hpp"
|
||||
|
||||
#include "Renderer/RenderItem.hpp"
|
||||
|
||||
/**
|
||||
@ -14,28 +17,20 @@
|
||||
class MotionVectors : public RenderItem
|
||||
{
|
||||
public:
|
||||
MotionVectors() = delete;
|
||||
|
||||
/**
|
||||
* Constructor. Initializes the required OpenGL data structures.
|
||||
*/
|
||||
MotionVectors();
|
||||
explicit MotionVectors(PresetState& presetState);
|
||||
|
||||
void InitVertexAttrib();
|
||||
|
||||
/**
|
||||
* Redners the motion vectors.
|
||||
* @param context The render context data.
|
||||
* @param presetPerFrameContext The per-frame context variables.
|
||||
*/
|
||||
void Draw(const RenderContext &context);
|
||||
void Draw(const PerFrameContext& presetPerFrameContext);
|
||||
|
||||
float r{ 0.0 }; //!< Red color channel of the motion vectors (mv_r).
|
||||
float g{ 0.0 }; //!< Green color channel of the motion vectors (mv_g).
|
||||
float b{ 0.0 }; //!< Blue color channel of the motion vectors (mv_b).
|
||||
float a{ 0.0 }; //!< Alpha channel of the motion vectors (mv_a).
|
||||
float length{ 0.0 }; //!< Line length of the motion vectors (mv_l).
|
||||
float x_num{ 0.0 }; //!< Horizontal grid size (integer part of mv_x).
|
||||
float y_num{ 0.0 }; //!< Vertical grid size (integer part of mv_y).
|
||||
float x_offset{ 0.0 }; //!< Horizontal grid offset (mv_dx).
|
||||
float y_offset{ 0.0 }; //!< Vertical grid offset (mv_dy).
|
||||
private:
|
||||
void ReversePropagatePoint(float posX1, float posY1, float& posX2, float&posY2);
|
||||
|
||||
PresetState& m_presetState; //!< The global preset state.
|
||||
};
|
||||
|
||||
@ -2,9 +2,18 @@
|
||||
|
||||
#include "PresetFileParser.hpp"
|
||||
|
||||
#include "Renderer/StaticGlShaders.hpp"
|
||||
|
||||
const glm::mat4 PresetState::orthogonalProjection = glm::ortho(0.0f, 1.0f, 0.0f, 1.0f, -40.0f, 40.0f);
|
||||
|
||||
PresetState::PresetState()
|
||||
: globalMemory(projectm_eval_memory_buffer_create())
|
||||
{
|
||||
auto staticShaders = StaticGlShaders::Get();
|
||||
untexturedShader.CompileProgram(staticShaders->GetV2fC4fVertexShader(),
|
||||
staticShaders->GetV2fC4fFragmentShader());
|
||||
texturedShader.CompileProgram(staticShaders->GetV2fC4fT2fVertexShader(),
|
||||
staticShaders->GetV2fC4fT2fFragmentShader());
|
||||
}
|
||||
|
||||
PresetState::~PresetState()
|
||||
|
||||
@ -7,11 +7,15 @@
|
||||
|
||||
#include "Constants.hpp"
|
||||
|
||||
#include "Audio/FrameAudioData.hpp"
|
||||
#include <Audio/FrameAudioData.hpp>
|
||||
|
||||
#include <Renderer/RenderContext.hpp>
|
||||
#include <Renderer/Shader.hpp>
|
||||
|
||||
#include <projectm-eval.h>
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
class PresetFileParser;
|
||||
@ -146,4 +150,11 @@ public:
|
||||
|
||||
std::string warpShader; //!< Warp shader code.
|
||||
std::string compositeShader; //!< Composite shader code.
|
||||
|
||||
Shader untexturedShader; //!< Shader used to draw untextured primitives, e.g. waveforms.
|
||||
Shader texturedShader; //!< Shader used to draw textured primitives, e.g. textured shapes and the warp mesh.
|
||||
|
||||
int mainTextureId{}; //!< ID of the previous frame texture.
|
||||
|
||||
static const glm::mat4 orthogonalProjection;
|
||||
};
|
||||
|
||||
@ -9,64 +9,80 @@
|
||||
#include "Renderer/ShaderEngine.hpp"
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
VideoEcho::VideoEcho(): a(0), zoom(1), orientation(Normal)
|
||||
VideoEcho::VideoEcho(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
Init();
|
||||
RenderItem::Init();
|
||||
}
|
||||
|
||||
VideoEcho::~VideoEcho()
|
||||
void VideoEcho::InitVertexAttrib()
|
||||
{
|
||||
}
|
||||
|
||||
void VideoEcho::InitVertexAttrib() {
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)0); // Positions
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, nullptr); // Positions
|
||||
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)(sizeof(float)*2)); // Textures
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, reinterpret_cast<void*>(sizeof(float) * 2)); // Textures
|
||||
}
|
||||
|
||||
void VideoEcho::Draw(RenderContext &context)
|
||||
void VideoEcho::Draw(PerFrameContext& perFrameContext)
|
||||
{
|
||||
int flipx=1, flipy=1;
|
||||
switch (orientation)
|
||||
{
|
||||
case Normal: flipx=1;flipy=1;break;
|
||||
case FlipX: flipx=-1;flipy=1;break;
|
||||
case FlipY: flipx=1;flipy=-1;break;
|
||||
case FlipXY: flipx=-1;flipy=-1;break;
|
||||
default: flipx=1;flipy=1; break;
|
||||
}
|
||||
int orientation = static_cast<int>(m_presetState.videoEchoOrientation) % 4;
|
||||
int flipX;
|
||||
int flipY;
|
||||
switch (orientation)
|
||||
{
|
||||
case 0:
|
||||
flipX = 1;
|
||||
flipY = 1;
|
||||
break;
|
||||
case 1:
|
||||
flipX = -1;
|
||||
flipY = 1;
|
||||
break;
|
||||
case 2:
|
||||
flipX = 1;
|
||||
flipY = -1;
|
||||
break;
|
||||
case 3:
|
||||
flipX = -1;
|
||||
flipY = -1;
|
||||
break;
|
||||
default:
|
||||
flipX = 1;
|
||||
flipY = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
float buffer_data[8][2] = {
|
||||
{-0.5f*flipx, -0.5f*flipy},
|
||||
{-0.5f * flipX, -0.5f * flipY},
|
||||
{0.0, 1.0},
|
||||
|
||||
{-0.5f*flipx, 0.5f*flipy},
|
||||
{-0.5f * flipX, 0.5f * flipY},
|
||||
{0.0, 0.0},
|
||||
|
||||
{ 0.5f*flipx, 0.5f*flipy},
|
||||
{0.5f * flipX, 0.5f * flipY},
|
||||
{1.0, 0.0},
|
||||
|
||||
{ 0.5f*flipx, -0.5f*flipy},
|
||||
{1.0, 1.0}
|
||||
};
|
||||
{0.5f * flipX, -0.5f * flipY},
|
||||
{1.0, 1.0}};
|
||||
|
||||
glm::mat4 mat_first_translation = glm::mat4(1.0);
|
||||
mat_first_translation[3][0] = -0.5;
|
||||
mat_first_translation[3][1] = -0.5;
|
||||
|
||||
glm::mat4 mat_scale = glm::mat4(1.0);
|
||||
mat_scale[0][0] = 1.0/zoom;
|
||||
mat_scale[1][1] = 1.0/zoom;
|
||||
glm::mat4 mat_scale = glm::mat4(1.0);
|
||||
mat_scale[0][0] = 1.0f / static_cast<float>(m_presetState.videoEchoZoom);
|
||||
mat_scale[1][1] = 1.0f / static_cast<float>(m_presetState.videoEchoZoom);
|
||||
|
||||
glm::mat4 mat_second_translation = glm::mat4(1.0);
|
||||
glm::mat4 mat_second_translation = glm::mat4(1.0);
|
||||
mat_second_translation[3][0] = 0.5;
|
||||
mat_second_translation[3][1] = 0.5;
|
||||
|
||||
for (int i = 1; i < 8; i+=2) {
|
||||
for (int i = 1; i < 8; i += 2)
|
||||
{
|
||||
glm::vec4 texture = glm::vec4(buffer_data[i][0], buffer_data[i][1], 0, 1);
|
||||
texture = mat_first_translation * texture;
|
||||
texture = mat_scale * texture;
|
||||
@ -84,16 +100,14 @@ void VideoEcho::Draw(RenderContext &context)
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glUseProgram(context.programID_v2f_c4f_t2f);
|
||||
|
||||
glUniformMatrix4fv(context.uniform_v2f_c4f_t2f_vertex_transformation, 1, GL_FALSE, glm::value_ptr(context.mat_ortho));
|
||||
glUniform1i(context.uniform_v2f_c4f_t2f_frag_texture_sampler, 0);
|
||||
|
||||
m_presetState.texturedShader.Bind();
|
||||
m_presetState.texturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
m_presetState.texturedShader.SetUniformInt("texture_sampler", 0);
|
||||
|
||||
//Now Blend the Video Echo
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, a * masterAlpha);
|
||||
glVertexAttrib4f(1, 1.0, 1.0, 1.0, static_cast<float>(m_presetState.videoEchoAlpha));
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
|
||||
@ -102,5 +116,5 @@ void VideoEcho::Draw(RenderContext &context)
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "projectM-opengl.h"
|
||||
#include "Renderer/RenderItem.hpp"
|
||||
#include "PerFrameContext.hpp"
|
||||
#include "PresetState.hpp"
|
||||
|
||||
enum Orientation
|
||||
{
|
||||
Normal=0, FlipX, FlipY, FlipXY
|
||||
};
|
||||
#include "projectM-opengl.h"
|
||||
|
||||
#include <Renderer/RenderItem.hpp>
|
||||
|
||||
class VideoEcho: public RenderItem
|
||||
{
|
||||
public:
|
||||
VideoEcho();
|
||||
virtual ~VideoEcho();
|
||||
VideoEcho() = delete;
|
||||
explicit VideoEcho(PresetState& presetState);
|
||||
|
||||
float a;
|
||||
float zoom;
|
||||
Orientation orientation;
|
||||
void InitVertexAttrib() override;
|
||||
|
||||
void InitVertexAttrib();
|
||||
void Draw(RenderContext &context);
|
||||
void Draw(PerFrameContext& perFrameContext);
|
||||
private:
|
||||
PresetState& m_presetState; //!< The global preset state.
|
||||
};
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "Waveform.hpp"
|
||||
|
||||
#include "PerFrameContext.hpp"
|
||||
#include "PresetState.hpp"
|
||||
|
||||
#include "Audio/BeatDetect.hpp"
|
||||
@ -13,36 +14,54 @@ Waveform::Waveform(PresetState& presetState)
|
||||
: RenderItem()
|
||||
, m_presetState(presetState)
|
||||
{
|
||||
Init();
|
||||
SetMode();
|
||||
RenderItem::Init();
|
||||
}
|
||||
|
||||
Waveform::~Waveform()
|
||||
{
|
||||
delete[] wave1Vertices;
|
||||
delete[] wave2Vertices;
|
||||
delete[] m_wave1Vertices;
|
||||
delete[] m_wave2Vertices;
|
||||
}
|
||||
|
||||
void Waveform::InitVertexAttrib()
|
||||
{
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
|
||||
}
|
||||
|
||||
void Waveform::Draw()
|
||||
void Waveform::Draw(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
std::array<WaveformVertex, RenderWaveformSamples * 2> smoothedWave;
|
||||
WaveformMath();
|
||||
|
||||
#if USE_GLES == 0
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
#endif
|
||||
glLineWidth(1);
|
||||
|
||||
m_presetState.untexturedShader.Bind();
|
||||
m_presetState.untexturedShader.SetUniformMat4x4("vertex_transformation", m_presetState.orthogonalProjection);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
// Additive wave drawing (vice overwrite)
|
||||
glEnable(GL_BLEND);
|
||||
if (m_presetState.additiveWaves)
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
WaveformMath(presetPerFrameContext);
|
||||
|
||||
std::vector<WaveformVertex> smoothedWave(m_samples * 2);
|
||||
|
||||
for (int waveIndex = 0; waveIndex < 2; waveIndex++)
|
||||
{
|
||||
auto* const waveVertices = (waveIndex == 0) ? wave1Vertices : wave2Vertices;
|
||||
auto* const waveVertices = (waveIndex == 0) ? m_wave1Vertices : m_wave2Vertices;
|
||||
if (!waveVertices)
|
||||
{
|
||||
continue;
|
||||
@ -52,24 +71,12 @@ void Waveform::Draw()
|
||||
// Instead of using the "break" index like Milkdrop, we simply have two separate arrays.
|
||||
const auto smoothedSamples = SmoothWave(waveVertices, smoothedWave.data());
|
||||
|
||||
glUseProgram(m_presetState.renderContext.programID_v2f_c4f);
|
||||
|
||||
m_tempAlpha = m_presetState.waveAlpha;
|
||||
m_tempAlpha = static_cast<float>(*presetPerFrameContext.wave_a);
|
||||
if (m_presetState.modWaveAlphaByvolume)
|
||||
{
|
||||
ModulateOpacityByVolume();
|
||||
}
|
||||
MaximizeColors();
|
||||
|
||||
// Additive wave drawing (vice overwrite)
|
||||
if (m_presetState.additiveWaves)
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
ModulateOpacityByVolume(presetPerFrameContext);
|
||||
}
|
||||
MaximizeColors(presetPerFrameContext);
|
||||
|
||||
// Always draw "thick" dots.
|
||||
const auto iterations = m_presetState.waveThick || m_presetState.waveDots ? 4 : 1;
|
||||
@ -80,9 +87,6 @@ void Waveform::Draw()
|
||||
|
||||
GLuint drawType = m_presetState.waveDots ? GL_POINTS : (m_loop ? GL_LINE_LOOP : GL_LINE_STRIP);
|
||||
|
||||
glBindVertexArray(m_vaoID);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vboID);
|
||||
|
||||
// If thick outline is used, draw the shape four times with slight offsets
|
||||
// (top left, top right, bottom right, bottom left).
|
||||
for (auto iteration = 0; iteration < iterations; iteration++)
|
||||
@ -117,15 +121,17 @@ void Waveform::Draw()
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(WaveformVertex) * smoothedSamples, smoothedWave.data(), GL_DYNAMIC_DRAW);
|
||||
glDrawArrays(drawType, 0, smoothedSamples);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
glUseProgram(0);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
void Waveform::ModulateOpacityByVolume()
|
||||
void Waveform::ModulateOpacityByVolume(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
//modulate volume by opacity
|
||||
//
|
||||
@ -138,23 +144,15 @@ void Waveform::ModulateOpacityByVolume()
|
||||
}
|
||||
else if (m_presetState.audioData.vol >= m_presetState.modWaveAlphaEnd)
|
||||
{
|
||||
m_tempAlpha = m_presetState.waveAlpha;
|
||||
m_tempAlpha = static_cast<float>(*presetPerFrameContext.wave_a);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tempAlpha = m_presetState.waveAlpha * ((m_presetState.audioData.vol - m_presetState.modWaveAlphaStart) / (m_presetState.modWaveAlphaEnd - m_presetState.modWaveAlphaStart));
|
||||
m_tempAlpha = static_cast<float>(*presetPerFrameContext.wave_a) * ((m_presetState.audioData.vol - m_presetState.modWaveAlphaStart) / (m_presetState.modWaveAlphaEnd - m_presetState.modWaveAlphaStart));
|
||||
}
|
||||
}
|
||||
|
||||
void Waveform::SetMode()
|
||||
{
|
||||
if (m_presetState.waveMode <= 8)
|
||||
{
|
||||
m_mode = static_cast<Mode>(m_presetState.waveMode);
|
||||
}
|
||||
}
|
||||
|
||||
void Waveform::MaximizeColors()
|
||||
void Waveform::MaximizeColors(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
//wave color brightening
|
||||
//
|
||||
@ -209,12 +207,12 @@ void Waveform::MaximizeColors()
|
||||
m_tempAlpha = 1.0f;
|
||||
}
|
||||
|
||||
if (m_presetState.maximizeWaveColor)
|
||||
if (*presetPerFrameContext.wave_brighten)
|
||||
{
|
||||
constexpr float fMaximizeWaveColorAmount = 1.0f;
|
||||
float cr{m_presetState.waveR};
|
||||
float cg{m_presetState.waveG};
|
||||
float cb{m_presetState.waveB};
|
||||
float cr{static_cast<float>(*presetPerFrameContext.wave_r)};
|
||||
float cg{static_cast<float>(*presetPerFrameContext.wave_g)};
|
||||
float cb{static_cast<float>(*presetPerFrameContext.wave_b)};
|
||||
|
||||
float max = cr;
|
||||
if (max < cg)
|
||||
@ -232,28 +230,34 @@ void Waveform::MaximizeColors()
|
||||
cb = cb / max * fMaximizeWaveColorAmount + cb * (1.0f - fMaximizeWaveColorAmount);
|
||||
}
|
||||
|
||||
glVertexAttrib4f(1, cr, cg, cb, m_tempAlpha * masterAlpha);
|
||||
glVertexAttrib4f(1, cr, cg, cb, m_tempAlpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttrib4f(1, m_presetState.waveR, m_presetState.waveG, m_presetState.waveB, m_tempAlpha * masterAlpha);
|
||||
glVertexAttrib4f(1,
|
||||
static_cast<float>(*presetPerFrameContext.wave_r),
|
||||
static_cast<float>(*presetPerFrameContext.wave_g),
|
||||
static_cast<float>(*presetPerFrameContext.wave_b),
|
||||
m_tempAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Waveform::WaveformMath()
|
||||
void Waveform::WaveformMath(const PerFrameContext& presetPerFrameContext)
|
||||
{
|
||||
constexpr float PI{3.14159274101257324219f};
|
||||
constexpr size_t audioSamples{512};
|
||||
|
||||
delete[] wave1Vertices;
|
||||
wave1Vertices = nullptr;
|
||||
|
||||
delete[] wave2Vertices;
|
||||
wave2Vertices = nullptr;
|
||||
delete[] m_wave1Vertices;
|
||||
m_wave1Vertices = nullptr;
|
||||
delete[] m_wave2Vertices;
|
||||
m_wave2Vertices = nullptr;
|
||||
|
||||
// NOTE: Buffer size is always 512 samples, waveform points 480 or less since some waveforms use a positive offset!
|
||||
std::array<float, WaveformMaxPoints> pcmDataL{0.0f};
|
||||
std::array<float, WaveformMaxPoints> pcmDataR{0.0f};
|
||||
std::array<float, audioSamples> pcmDataL{0.0f};
|
||||
std::array<float, audioSamples> pcmDataR{0.0f};
|
||||
|
||||
m_mode = static_cast<Mode>(m_presetState.waveMode % 9);
|
||||
|
||||
if (m_mode != Mode::SpectrumLine)
|
||||
{
|
||||
@ -299,7 +303,7 @@ void Waveform::WaveformMath()
|
||||
|
||||
m_loop = false;
|
||||
|
||||
float mysteryWaveParam = m_presetState.waveParam;
|
||||
float mysteryWaveParam = static_cast<float>(*presetPerFrameContext.wave_mystery);
|
||||
|
||||
if ((m_mode == Mode::Circle || m_mode == Mode::XYOscillationSpiral || m_mode == Mode::DerivativeLine) && (mysteryWaveParam < 1.0f || mysteryWaveParam > 1.0f))
|
||||
{
|
||||
@ -309,53 +313,56 @@ void Waveform::WaveformMath()
|
||||
mysteryWaveParam = mysteryWaveParam * 2 - 1;
|
||||
}
|
||||
|
||||
auto const waveX = static_cast<float>(*presetPerFrameContext.wave_x);
|
||||
auto const waveY = static_cast<float>(*presetPerFrameContext.wave_y);
|
||||
|
||||
switch (m_mode)
|
||||
{
|
||||
|
||||
case Mode::Circle: {
|
||||
m_loop = true;
|
||||
|
||||
int const samples = RenderWaveformSamples / 2;
|
||||
m_samples = RenderWaveformSamples / 2;
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
|
||||
const int sampleOffset{(RenderWaveformSamples - samples) / 2};
|
||||
const int sampleOffset{(RenderWaveformSamples - m_samples) / 2};
|
||||
|
||||
const float inverseSamplesMinusOne{1.0f / static_cast<float>(samples)};
|
||||
const float inverseSamplesMinusOne{1.0f / static_cast<float>(m_samples)};
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
float radius = 0.5f + 0.4f * pcmDataR[i + sampleOffset] + mysteryWaveParam;
|
||||
float const angle = static_cast<float>(i) * inverseSamplesMinusOne * 6.28f + m_presetState.renderContext.time * 0.2f;
|
||||
if (i < samples / 10)
|
||||
if (i < m_samples / 10)
|
||||
{
|
||||
float mix = static_cast<float>(i) / (static_cast<float>(samples) * 0.1f);
|
||||
float mix = static_cast<float>(i) / (static_cast<float>(m_samples) * 0.1f);
|
||||
mix = 0.5f - 0.5f * cosf(mix * 3.1416f);
|
||||
float const radius2 = 0.5f + 0.4f * pcmDataR[i + samples + sampleOffset] + mysteryWaveParam;
|
||||
float const radius2 = 0.5f + 0.4f * pcmDataR[i + m_samples + sampleOffset] + mysteryWaveParam;
|
||||
radius = radius2 * (1.0f - mix) + radius * (mix);
|
||||
}
|
||||
|
||||
radius *= 0.5f;
|
||||
|
||||
wave1Vertices[i].x = radius * cosf(angle) * aspectY + m_presetState.waveX;
|
||||
wave1Vertices[i].y = radius * sinf(angle) * aspectX + m_presetState.waveY;
|
||||
m_wave1Vertices[i].x = radius * cosf(angle) * aspectY + waveX;
|
||||
m_wave1Vertices[i].y = radius * sinf(angle) * aspectX + waveY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Mode::XYOscillationSpiral: //circularly moving waveform
|
||||
{
|
||||
int const samples = RenderWaveformSamples / 2;
|
||||
m_samples = RenderWaveformSamples / 2;
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
float const radius = (0.53f + 0.43f * pcmDataR[i] + mysteryWaveParam) * 0.5f;
|
||||
float const angle = pcmDataL[i + 32] * PI * 0.5f + m_presetState.renderContext.time * 2.3f;
|
||||
|
||||
wave1Vertices[i].x = radius * cosf(angle) * aspectY + m_presetState.waveX;
|
||||
wave1Vertices[i].y = radius * sinf(angle) * aspectX + m_presetState.waveY;
|
||||
m_wave1Vertices[i].x = radius * cosf(angle) * aspectY + waveX;
|
||||
m_wave1Vertices[i].y = radius * sinf(angle) * aspectX + waveY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -363,69 +370,69 @@ void Waveform::WaveformMath()
|
||||
case Mode::Blob2:
|
||||
case Mode::Blob3: { // Both "centered spiro" waveforms are identical. Only difference is the alpha value.
|
||||
// Alpha calculation is handled in MaximizeColors().
|
||||
int const samples = RenderWaveformSamples;
|
||||
m_samples = RenderWaveformSamples;
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
wave1Vertices[i].x = 0.5f * pcmDataR[i] * aspectY + m_presetState.waveX;
|
||||
wave1Vertices[i].y = 0.5f * pcmDataL[i + 32] * aspectX + m_presetState.waveY;
|
||||
m_wave1Vertices[i].x = 0.5f * pcmDataR[i] * aspectY + waveX;
|
||||
m_wave1Vertices[i].y = 0.5f * pcmDataL[i + 32] * aspectX + waveY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Mode::DerivativeLine: {
|
||||
int samples = RenderWaveformSamples;
|
||||
m_samples = RenderWaveformSamples;
|
||||
|
||||
if (samples > m_presetState.renderContext.viewportSizeX / 3)
|
||||
if (m_samples > m_presetState.renderContext.viewportSizeX / 3)
|
||||
{
|
||||
samples /= 3;
|
||||
m_samples /= 3;
|
||||
}
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
|
||||
int const sampleOffset = (RenderWaveformSamples - samples) / 2;
|
||||
int const sampleOffset = (RenderWaveformSamples - m_samples) / 2;
|
||||
|
||||
const float w1 = 0.45f + 0.5f * (mysteryWaveParam * 0.5f + 0.5f);
|
||||
const float w2 = 1.0f - w1;
|
||||
|
||||
const float inverseSamples = 1.0f / static_cast<float>(samples);
|
||||
const float inverseSamples = 1.0f / static_cast<float>(m_samples);
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
assert((i + 25 + sampleOffset) < 512);
|
||||
wave1Vertices[i].x = (-1.0f + 2.0f * (i * inverseSamples)) * 0.5f + m_presetState.waveX;
|
||||
wave1Vertices[i].y = pcmDataL[i + sampleOffset] * 0.235f + m_presetState.waveY;
|
||||
wave1Vertices[i].x += pcmDataR[i + 25 + sampleOffset] * 0.22f;
|
||||
m_wave1Vertices[i].x = (-1.0f + 2.0f * (i * inverseSamples)) * 0.5f + waveX;
|
||||
m_wave1Vertices[i].y = pcmDataL[i + sampleOffset] * 0.235f + waveY;
|
||||
m_wave1Vertices[i].x += pcmDataR[i + 25 + sampleOffset] * 0.22f;
|
||||
|
||||
// Momentum
|
||||
if (i > 1)
|
||||
{
|
||||
wave1Vertices[i].x =
|
||||
wave1Vertices[i].x * w2 + w1 * (wave1Vertices[i - 1].x * 2.0f - wave1Vertices[i - 2].x);
|
||||
wave1Vertices[i].y =
|
||||
wave1Vertices[i].y * w2 + w1 * (wave1Vertices[i - 1].y * 2.0f - wave1Vertices[i - 2].y);
|
||||
m_wave1Vertices[i].x =
|
||||
m_wave1Vertices[i].x * w2 + w1 * (m_wave1Vertices[i - 1].x * 2.0f - m_wave1Vertices[i - 2].x);
|
||||
m_wave1Vertices[i].y =
|
||||
m_wave1Vertices[i].y * w2 + w1 * (m_wave1Vertices[i - 1].y * 2.0f - m_wave1Vertices[i - 2].y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Mode::ExplosiveHash: {
|
||||
int const samples = RenderWaveformSamples;
|
||||
m_samples = RenderWaveformSamples;
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
|
||||
const float cosineRotation = cosf(m_presetState.renderContext.time * 0.3f);
|
||||
const float sineRotation = sinf(m_presetState.renderContext.time * 0.3f);
|
||||
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
const float x0 = (pcmDataR[i] * pcmDataL[i + 32] + pcmDataL[i] * pcmDataR[i + 32]);
|
||||
const float y0 = (pcmDataR[i] * pcmDataR[i] - pcmDataL[i + 32] * pcmDataL[i + 32]);
|
||||
wave1Vertices[i].x = ((x0 * cosineRotation - y0 * sineRotation) * 0.5f * aspectY) + m_presetState.waveX;
|
||||
wave1Vertices[i].y = ((x0 * sineRotation + y0 * cosineRotation) * 0.5f * aspectX) + m_presetState.waveY;
|
||||
m_wave1Vertices[i].x = ((x0 * cosineRotation - y0 * sineRotation) * 0.5f * aspectY) + waveX;
|
||||
m_wave1Vertices[i].y = ((x0 * sineRotation + y0 * cosineRotation) * 0.5f * aspectX) + waveY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -434,40 +441,39 @@ void Waveform::WaveformMath()
|
||||
case Mode::DoubleLine:
|
||||
case Mode::SpectrumLine: // Unfinished
|
||||
{
|
||||
int samples;
|
||||
if (m_mode == Mode::SpectrumLine)
|
||||
{
|
||||
samples = 256;
|
||||
m_samples = 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
samples = RenderWaveformSamples / 2;
|
||||
m_samples = RenderWaveformSamples / 2;
|
||||
|
||||
if (samples > m_presetState.renderContext.viewportSizeX / 3)
|
||||
if (m_samples > m_presetState.viewportWidth / 3)
|
||||
{
|
||||
samples /= 3;
|
||||
m_samples /= 3;
|
||||
}
|
||||
}
|
||||
|
||||
wave1Vertices = new WaveformVertex[samples]();
|
||||
m_wave1Vertices = new WaveformVertex[m_samples]();
|
||||
if (m_mode == Mode::DoubleLine)
|
||||
{
|
||||
wave2Vertices = new WaveformVertex[samples]();
|
||||
m_wave2Vertices = new WaveformVertex[m_samples]();
|
||||
}
|
||||
|
||||
const int sampleOffset = (RenderWaveformSamples - samples) / 2;
|
||||
const int sampleOffset = (RenderWaveformSamples - m_samples) / 2;
|
||||
|
||||
const float angle = PI * 0.5f * mysteryWaveParam; // from -PI/2 to PI/2
|
||||
float dx = cosf(angle);
|
||||
float dy = sinf(angle);
|
||||
|
||||
std::array<float, 2> edgeX{
|
||||
m_presetState.waveX * cosf(angle + PI * 0.5f) - dx * 3.0f,
|
||||
m_presetState.waveX * cosf(angle + PI * 0.5f) + dx * 3.0f};
|
||||
waveX * cosf(angle + PI * 0.5f) - dx * 3.0f,
|
||||
waveX * cosf(angle + PI * 0.5f) + dx * 3.0f};
|
||||
|
||||
std::array<float, 2> edgeY{
|
||||
m_presetState.waveX * sinf(angle + PI * 0.5f) - dy * 3.0f,
|
||||
m_presetState.waveX * sinf(angle + PI * 0.5f) + dy * 3.0f};
|
||||
waveX * sinf(angle + PI * 0.5f) - dy * 3.0f,
|
||||
waveX * sinf(angle + PI * 0.5f) + dy * 3.0f};
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@ -521,8 +527,8 @@ void Waveform::WaveformMath()
|
||||
}
|
||||
}
|
||||
|
||||
dx = (edgeX[1] - edgeX[0]) / static_cast<float>(samples);
|
||||
dy = (edgeY[1] - edgeY[0]) / static_cast<float>(samples);
|
||||
dx = (edgeX[1] - edgeX[0]) / static_cast<float>(m_samples);
|
||||
dy = (edgeY[1] - edgeY[0]) / static_cast<float>(m_samples);
|
||||
|
||||
const float angle2 = atan2f(dy, dx);
|
||||
const float perpetualDX = cosf(angle2 + PI * 0.5f);
|
||||
@ -530,37 +536,37 @@ void Waveform::WaveformMath()
|
||||
|
||||
if (m_mode == Mode::Line)
|
||||
{
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
wave1Vertices[i].x =
|
||||
m_wave1Vertices[i].x =
|
||||
edgeX[0] + dx * static_cast<float>(i) + perpetualDX * 0.25f * pcmDataL[i + sampleOffset];
|
||||
wave1Vertices[i].y =
|
||||
m_wave1Vertices[i].y =
|
||||
edgeY[0] + dy * static_cast<float>(i) + perpetualDY * 0.25f * pcmDataL[i + sampleOffset];
|
||||
}
|
||||
}
|
||||
else if (m_mode == Mode::SpectrumLine)
|
||||
{
|
||||
for (int i = 0; i < samples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
const float f = 0.1f * logf(pcmDataL[i * 2] + pcmDataL[i * 2 + 1]);
|
||||
wave1Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) + perpetualDX * f;
|
||||
wave1Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) + perpetualDY * f;
|
||||
m_wave1Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) + perpetualDX * f;
|
||||
m_wave1Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) + perpetualDY * f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float const separation = powf(m_presetState.waveY * 0.25f + 0.25f, 2.0f);
|
||||
for (int i = 0; i < samples; i++)
|
||||
float const separation = powf(waveY * 0.25f + 0.25f, 2.0f);
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
wave1Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) +
|
||||
perpetualDX * (0.25f * pcmDataL[i + sampleOffset] + separation);
|
||||
wave1Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) +
|
||||
perpetualDY * (0.25f * pcmDataL[i + sampleOffset] + separation);
|
||||
m_wave1Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) +
|
||||
perpetualDX * (0.25f * pcmDataL[i + sampleOffset] + separation);
|
||||
m_wave1Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) +
|
||||
perpetualDY * (0.25f * pcmDataL[i + sampleOffset] + separation);
|
||||
|
||||
wave2Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) +
|
||||
perpetualDX * (0.25f * pcmDataR[i + sampleOffset] - separation);
|
||||
wave2Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) +
|
||||
perpetualDY * (0.25f * pcmDataR[i + sampleOffset] - separation);
|
||||
m_wave2Vertices[i].x = edgeX[0] + dx * static_cast<float>(i) +
|
||||
perpetualDX * (0.25f * pcmDataR[i + sampleOffset] - separation);
|
||||
m_wave2Vertices[i].y = edgeY[0] + dy * static_cast<float>(i) +
|
||||
perpetualDY * (0.25f * pcmDataR[i + sampleOffset] - separation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -571,15 +577,15 @@ void Waveform::WaveformMath()
|
||||
}
|
||||
|
||||
// Reverse all Y coordinates to stay consistent with the pre-VMS milkdrop
|
||||
for (int i = 0; i < RenderWaveformSamples; i++)
|
||||
for (int i = 0; i < m_samples; i++)
|
||||
{
|
||||
if (wave1Vertices)
|
||||
if (m_wave1Vertices)
|
||||
{
|
||||
wave1Vertices[i].y = 1.0f - wave1Vertices[i].y;
|
||||
m_wave1Vertices[i].y = 1.0f - m_wave1Vertices[i].y;
|
||||
}
|
||||
if (wave2Vertices)
|
||||
if (m_wave2Vertices)
|
||||
{
|
||||
wave2Vertices[i].y = 1.0f - wave2Vertices[i].y;
|
||||
m_wave2Vertices[i].y = 1.0f - m_wave2Vertices[i].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -597,10 +603,10 @@ int Waveform::SmoothWave(const Waveform::WaveformVertex* inputVertices,
|
||||
int indexBelow = 0;
|
||||
int indexAbove2 = 1;
|
||||
|
||||
for (auto inputIndex = 0; inputIndex < RenderWaveformSamples - 1; inputIndex++)
|
||||
for (auto inputIndex = 0; inputIndex < m_samples - 1; inputIndex++)
|
||||
{
|
||||
int const indexAbove = indexAbove2;
|
||||
indexAbove2 = std::min(RenderWaveformSamples - 1, inputIndex + 2);
|
||||
indexAbove2 = std::min(m_samples - 1, inputIndex + 2);
|
||||
outputVertices[outputIndex] = inputVertices[inputIndex];
|
||||
outputVertices[outputIndex + 1].x = (c1 * inputVertices[indexBelow].x + c2 * inputVertices[inputIndex].x + c3 * inputVertices[indexAbove].x + c4 * inputVertices[indexAbove2].x) * inverseSum;
|
||||
outputVertices[outputIndex + 1].y = (c1 * inputVertices[indexBelow].y + c2 * inputVertices[inputIndex].y + c3 * inputVertices[indexAbove].y + c4 * inputVertices[indexAbove2].y) * inverseSum;
|
||||
@ -608,7 +614,7 @@ int Waveform::SmoothWave(const Waveform::WaveformVertex* inputVertices,
|
||||
outputIndex += 2;
|
||||
}
|
||||
|
||||
outputVertices[outputIndex] = inputVertices[RenderWaveformSamples - 1];
|
||||
outputVertices[outputIndex] = inputVertices[m_samples - 1];
|
||||
|
||||
return outputIndex + 1;
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ public:
|
||||
Waveform(PresetState& presetState);
|
||||
~Waveform() override;
|
||||
|
||||
void Draw();
|
||||
void Draw(const PerFrameContext& presetPerFrameContext);
|
||||
|
||||
void InitVertexAttrib() override;
|
||||
|
||||
@ -40,9 +40,9 @@ private:
|
||||
|
||||
void SetMode();
|
||||
|
||||
void MaximizeColors();
|
||||
void ModulateOpacityByVolume();
|
||||
void WaveformMath();
|
||||
void MaximizeColors(const PerFrameContext& presetPerFrameContext);
|
||||
void ModulateOpacityByVolume(const PerFrameContext& presetPerFrameContext);
|
||||
void WaveformMath(const PerFrameContext& presetPerFrameContext);
|
||||
|
||||
/**
|
||||
* @brief Does a better-than-linear smooth on a wave.
|
||||
@ -50,19 +50,19 @@ private:
|
||||
* Roughly doubles the number of points.
|
||||
*
|
||||
* @param inputVertices Pointer to an array of vertices to be smoothed.
|
||||
* @param vertexCount Number of vertices/points in the input data.
|
||||
* @param outputVertices Pointer to a buffer that will receive the smoothed data. Must be able to hold 2 * vertexCount vertices.
|
||||
* @return The number of vertices in outputVertices after smoothing.
|
||||
*/
|
||||
static auto SmoothWave(const WaveformVertex* inputVertices, WaveformVertex* outputVertices) -> int;
|
||||
auto SmoothWave(const WaveformVertex* inputVertices, WaveformVertex* outputVertices) -> int;
|
||||
|
||||
PresetState& m_presetState;
|
||||
PresetState& m_presetState; //!< The preset state.
|
||||
|
||||
Mode m_mode{Mode::Line};
|
||||
Mode m_mode{Mode::Line}; //!< Line drawing mode.
|
||||
|
||||
float m_tempAlpha{0.0f};
|
||||
bool m_loop{false};
|
||||
float m_tempAlpha{0.0f}; //!< Calculated alpha value.
|
||||
bool m_loop{false}; //!< true if the waveform is a closed loop.
|
||||
int m_samples{}; //!< Number of samples in the current waveform. Depends on the mode.
|
||||
|
||||
WaveformVertex* wave1Vertices{nullptr};
|
||||
WaveformVertex* wave2Vertices{nullptr};
|
||||
WaveformVertex* m_wave1Vertices{nullptr};
|
||||
WaveformVertex* m_wave2Vertices{nullptr};
|
||||
};
|
||||
|
||||
@ -42,7 +42,7 @@ void WaveformPerPointContext::RegisterBuiltinVariables()
|
||||
for (int t = 0; t < TVarCount; t++)
|
||||
{
|
||||
std::string tvar = "t" + std::to_string(t + 1);
|
||||
q_vars[t] = projectm_eval_context_register_variable(perPointCodeContext, tvar.c_str());
|
||||
t_vars[t] = projectm_eval_context_register_variable(perPointCodeContext, tvar.c_str());
|
||||
}
|
||||
|
||||
REG_VAR(bass);
|
||||
|
||||
@ -98,12 +98,14 @@ void ProjectM::LoadPresetData(std::istream& presetData, bool smoothTransition)
|
||||
void ProjectM::SetTexturePaths(std::vector<std::string> texturePaths)
|
||||
{
|
||||
m_textureSearchPaths = std::move(texturePaths);
|
||||
m_renderer->SetTextureSearchPaths(m_textureSearchPaths);
|
||||
m_textureManager = std::make_unique<TextureManager>(m_textureSearchPaths);
|
||||
//m_renderer->SetTextureSearchPaths(m_textureSearchPaths);
|
||||
}
|
||||
|
||||
void ProjectM::ResetTextures()
|
||||
{
|
||||
m_renderer->ResetTextures();
|
||||
m_textureManager = std::make_unique<TextureManager>(m_textureSearchPaths);
|
||||
//m_renderer->ResetTextures();
|
||||
}
|
||||
|
||||
void ProjectM::DumpDebugImageOnNextFrame(const std::string& outputFile)
|
||||
@ -179,6 +181,23 @@ void ProjectM::RenderFrame()
|
||||
}
|
||||
|
||||
// ToDo: Call the to-be-implemented render method in Renderer
|
||||
auto audio = m_beatDetect->GetFrameAudioData();
|
||||
|
||||
RenderContext ctx{};
|
||||
ctx.viewportSizeX = m_windowWidth;
|
||||
ctx.viewportSizeY = m_windowHeight;
|
||||
ctx.time = m_timeKeeper->GetRunningTime();
|
||||
ctx.progress = m_timeKeeper->PresetProgressA();
|
||||
ctx.fps = m_targetFps;
|
||||
ctx.frame = m_count;
|
||||
ctx.aspectX = (m_windowHeight > m_windowWidth) ? static_cast<float>(m_windowWidth) / static_cast<float>(m_windowHeight) : 1.0f;
|
||||
ctx.aspectY = (m_windowWidth > m_windowHeight) ? static_cast<float>(m_windowHeight) / static_cast<float>(m_windowWidth) : 1.0f;
|
||||
ctx.invAspectX = 1.0f / ctx.aspectX;
|
||||
ctx.invAspectY = 1.0f / ctx.aspectY;
|
||||
|
||||
m_activePreset->RenderFrame(audio, ctx);
|
||||
|
||||
m_count++;
|
||||
}
|
||||
|
||||
void ProjectM::Reset()
|
||||
@ -213,6 +232,8 @@ void ProjectM::Initialize()
|
||||
*m_beatDetect,
|
||||
m_textureSearchPaths);
|
||||
|
||||
m_textureManager = std::make_unique<TextureManager>(m_textureSearchPaths);
|
||||
|
||||
m_presetFactoryManager->initialize();
|
||||
|
||||
/* Set the seed to the current time in seconds */
|
||||
|
||||
@ -60,6 +60,8 @@ class Func;
|
||||
|
||||
class Renderer;
|
||||
|
||||
class TextureManager;
|
||||
|
||||
class Preset;
|
||||
|
||||
class TimeKeeper;
|
||||
@ -256,6 +258,7 @@ private:
|
||||
std::unique_ptr<PresetFactoryManager> m_presetFactoryManager; //!< Provides access to all available preset factories.
|
||||
|
||||
std::unique_ptr<Renderer> m_renderer; //!< The Preset renderer.
|
||||
std::unique_ptr<TextureManager> m_textureManager; //!< The texture manager.
|
||||
std::unique_ptr<libprojectM::Audio::BeatDetect> m_beatDetect; //!< The beat detection class.
|
||||
std::unique_ptr<Preset> m_activePreset; //!< Currently loaded preset.
|
||||
std::unique_ptr<Preset> m_transitioningPreset; //!< Destination preset when smooth preset switching.
|
||||
|
||||
@ -106,6 +106,22 @@ void Framebuffer::CreateColorAttachment(int framebufferIndex, int attachmentInde
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Framebuffer::GetColorAttachmentTexture(int framebufferIndex, int attachmentIndex) const
|
||||
{
|
||||
if (framebufferIndex < 0 || framebufferIndex >= static_cast<int>(m_framebufferIds.size()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto& attachment = m_attachments.at(framebufferIndex);
|
||||
if (attachment.find(GL_COLOR_ATTACHMENT0 + attachmentIndex) == attachment.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return attachment.at(GL_COLOR_ATTACHMENT0 + attachmentIndex).TextureId();
|
||||
}
|
||||
|
||||
void Framebuffer::CreateDepthAttachment(int framebufferIndex)
|
||||
{
|
||||
if (framebufferIndex < 0 || framebufferIndex >= static_cast<int>(m_framebufferIds.size()))
|
||||
|
||||
@ -77,22 +77,34 @@ public:
|
||||
/**
|
||||
* @brief Adds a new color attachment to the framebuffer.
|
||||
* The texture is always created in RGBA format.
|
||||
* @param framebufferIndex The framebuffer index.
|
||||
* @param index The index of the attachment, at least indices 0-7 are guaranteed to be available.
|
||||
*/
|
||||
void CreateColorAttachment(int framebufferIndex, int attachmentIndex);
|
||||
|
||||
/**
|
||||
* @brief Returns the texture ID of the given framebuffer and color attachment.
|
||||
* @param framebufferIndex The framebuffer index.
|
||||
* @param attachmentIndex The index of the attachment to return the texture for.
|
||||
* @return The texture ID or 0 if no texture is assigned.
|
||||
*/
|
||||
auto GetColorAttachmentTexture(int framebufferIndex, int attachmentIndex) const -> GLuint;
|
||||
|
||||
/**
|
||||
* @brief Adds a depth attachment to the framebuffer.
|
||||
* @param framebufferIndex The framebuffer index.
|
||||
*/
|
||||
void CreateDepthAttachment(int framebufferIndex);
|
||||
|
||||
/**
|
||||
* @brief Adds a stencil buffer attachment to the framebuffer.
|
||||
* @param framebufferIndex The framebuffer index.
|
||||
*/
|
||||
void CreateStencilAttachment(int framebufferIndex);
|
||||
|
||||
/**
|
||||
* @brief Adds a depth stencil buffer attachment to the framebuffer.
|
||||
* @param framebufferIndex The framebuffer index.
|
||||
*/
|
||||
void CreateDepthStencilAttachment(int framebufferIndex);
|
||||
|
||||
|
||||
@ -26,11 +26,5 @@ public:
|
||||
|
||||
TextureManager* textureManager{nullptr}; //!< Holds all loaded textures for shader access.
|
||||
|
||||
GLuint programID_v2f_c4f{0}; //!< Vertex shader program ID (no texture coordinates)
|
||||
GLuint programID_v2f_c4f_t2f{0}; //!< Vertex shader program ID (with texture coordinates)
|
||||
GLint uniform_v2f_c4f_vertex_transformation{0}; //!< Uniform location of the vertex shader transformation parameter (untextured output)
|
||||
GLint uniform_v2f_c4f_vertex_point_size{0}; //!< Uniform location of the vertex shader point size parameter (untextured output)
|
||||
GLint uniform_v2f_c4f_t2f_vertex_transformation{0}; //!< Uniform location of the vertex shader transformation parameter (textured output)
|
||||
GLint uniform_v2f_c4f_t2f_frag_texture_sampler{0}; //!< Uniform location of the vertex shader transformation parameter (textured output)
|
||||
glm::mat4 mat_ortho{0.0}; //!< Orthographic projection matrix.
|
||||
};
|
||||
|
||||
@ -109,7 +109,7 @@ Renderer::Renderer(int viewportWidth, int viewportHeight, int meshX, int meshY,
|
||||
|
||||
void Renderer::ResetTextures()
|
||||
{
|
||||
m_textureManager = std::make_unique<TextureManager>(m_textureSearchPaths, m_mainTextureSizeX, m_mainTextureSizeY);
|
||||
//m_textureManager = std::make_unique<TextureManager>(m_textureSearchPaths);
|
||||
}
|
||||
|
||||
void Renderer::SetTextureSearchPaths(std::vector<std::string>& textureSearchPaths)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "ShaderEngine.hpp"
|
||||
|
||||
#include "StaticGlShaders.h"
|
||||
#include "StaticGlShaders.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "StaticGlShaders.h"
|
||||
#include "StaticGlShaders.hpp"
|
||||
|
||||
#include "projectM-opengl.h"
|
||||
|
||||
|
||||
@ -15,10 +15,8 @@
|
||||
#define GL_TEXTURE_IMAGE_FORMAT 0x828F
|
||||
#endif
|
||||
|
||||
#define NUM_BLUR_TEX 6
|
||||
|
||||
|
||||
TextureManager::TextureManager(std::vector<std::string>& textureSearchPaths, int texSizeX, int texSizeY)
|
||||
TextureManager::TextureManager(std::vector<std::string>& textureSearchPaths)
|
||||
: m_textureDirectories(textureSearchPaths)
|
||||
{
|
||||
FileScanner fileScanner = FileScanner(m_textureDirectories, m_extensions);
|
||||
@ -29,41 +27,6 @@ TextureManager::TextureManager(std::vector<std::string>& textureSearchPaths, int
|
||||
|
||||
Preload();
|
||||
|
||||
// Create main texture and associated samplers
|
||||
m_mainTexture = new Texture("main", texSizeX, texSizeY, false);
|
||||
m_mainTexture->getSampler(GL_REPEAT, GL_LINEAR);
|
||||
m_mainTexture->getSampler(GL_REPEAT, GL_NEAREST);
|
||||
m_mainTexture->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
|
||||
m_mainTexture->getSampler(GL_CLAMP_TO_EDGE, GL_NEAREST);
|
||||
m_textures["main"] = m_mainTexture;
|
||||
|
||||
// Initialize blur textures
|
||||
int w = texSizeX;
|
||||
int h = texSizeY;
|
||||
for (int i=0; i<NUM_BLUR_TEX; i++)
|
||||
{
|
||||
// main VS = 1024
|
||||
// blur0 = 512
|
||||
// blur1 = 256 <- user sees this as "blur1"
|
||||
// blur2 = 128
|
||||
// blur3 = 128 <- user sees this as "blur2"
|
||||
// blur4 = 64
|
||||
// blur5 = 64 <- user sees this as "blur3"
|
||||
if (!(i&1) || (i<2))
|
||||
{
|
||||
w = std::max(16, w / 2);
|
||||
h = std::max(16, h / 2);
|
||||
}
|
||||
int w2 = ((w+3)/16)*16;
|
||||
int h2 = ((h+3)/4)*4;
|
||||
|
||||
std::string texname = "blur" + std::to_string(i/2+1) + ((i%2) ? "" : "doNOTuseME");
|
||||
Texture * textureBlur = new Texture(texname, w2, h2, false);
|
||||
textureBlur->getSampler(GL_CLAMP_TO_EDGE, GL_LINEAR);
|
||||
m_textures[texname] = textureBlur;
|
||||
m_blurTextures.push_back(textureBlur);
|
||||
}
|
||||
|
||||
auto noise = std::make_unique<MilkdropNoise>();
|
||||
|
||||
#if !USE_GLES
|
||||
@ -388,19 +351,3 @@ void TextureManager::ExtractTextureSettings(const std::string qualifiedName, GLi
|
||||
name = qualifiedName;
|
||||
}
|
||||
}
|
||||
|
||||
const Texture * TextureManager::getMainTexture() const {
|
||||
return m_mainTexture;
|
||||
}
|
||||
|
||||
const std::vector<Texture*> & TextureManager::getBlurTextures() const {
|
||||
return m_blurTextures;
|
||||
}
|
||||
|
||||
|
||||
void TextureManager::updateMainTexture()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_mainTexture->texID);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_mainTexture->width, m_mainTexture->height);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
@ -15,17 +15,12 @@ public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param textureSearchPaths List of paths to search for textures. These paths are search in the given order.
|
||||
* @param texSizeX Width of the main texture. Does not influence the size of loaded textures!
|
||||
* @param texSizeY Height of the main texture. Does not influence the size of loaded textures!
|
||||
*/
|
||||
TextureManager(std::vector<std::string>& textureSearchPaths, int texSizeX, int texSizeY);
|
||||
TextureManager(std::vector<std::string>& textureSearchPaths);
|
||||
~TextureManager();
|
||||
|
||||
TextureSamplerDesc tryLoadingTexture(const std::string name);
|
||||
TextureSamplerDesc getTexture(const std::string fullName, const GLenum defaultWrap, const GLenum defaultFilter);
|
||||
const Texture* getMainTexture() const;
|
||||
const std::vector<Texture*>& getBlurTextures() const;
|
||||
void updateMainTexture();
|
||||
TextureSamplerDesc getRandomTextureName(std::string rand_name);
|
||||
void clearRandomTextures();
|
||||
|
||||
@ -38,8 +33,6 @@ private:
|
||||
|
||||
std::vector<std::string>& m_textureDirectories;
|
||||
std::map<std::string, Texture*> m_textures;
|
||||
std::vector<Texture*> m_blurTextures;
|
||||
Texture* m_mainTexture;
|
||||
std::vector<std::string> m_randomTextures;
|
||||
std::vector<std::string> m_extensions{".jpg", ".jpeg", ".dds", ".png", ".tga", ".bmp", ".dib"};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user