kopia lustrzana https://github.com/jameshball/osci-render
Add noise and glow effects, and make upsampling button work
rodzic
7f12ee9490
commit
a106e09876
|
@ -119,9 +119,9 @@ OscirenderAudioProcessorEditor::OscirenderAudioProcessorEditor(OscirenderAudioPr
|
|||
visualiserSettingsWindow.setUsingNativeTitleBar(true);
|
||||
#endif
|
||||
visualiserSettings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiserSettings.setSize(550, 310);
|
||||
visualiserSettings.setSize(550, 370);
|
||||
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
|
||||
visualiserSettingsWindow.centreWithSize(550, 310);
|
||||
visualiserSettingsWindow.centreWithSize(550, 370);
|
||||
|
||||
tooltipDropShadow.setOwner(&tooltipWindow);
|
||||
}
|
||||
|
|
|
@ -149,13 +149,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
permanentEffects.push_back(thresholdEffect);
|
||||
permanentEffects.push_back(imageThreshold);
|
||||
permanentEffects.push_back(imageStride);
|
||||
permanentEffects.push_back(visualiserParameters.brightnessEffect);
|
||||
permanentEffects.push_back(visualiserParameters.intensityEffect);
|
||||
permanentEffects.push_back(visualiserParameters.persistenceEffect);
|
||||
permanentEffects.push_back(visualiserParameters.hueEffect);
|
||||
permanentEffects.push_back(visualiserParameters.saturationEffect);
|
||||
permanentEffects.push_back(visualiserParameters.focusEffect);
|
||||
permanentEffects.push_back(visualiserParameters.noiseEffect);
|
||||
|
||||
for (auto effect : visualiserParameters.effects) {
|
||||
permanentEffects.push_back(effect);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 26; i++) {
|
||||
addLuaSlider();
|
||||
|
@ -179,10 +176,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
booleanParameters.push_back(animateFrames);
|
||||
booleanParameters.push_back(animationSyncBPM);
|
||||
booleanParameters.push_back(invertImage);
|
||||
booleanParameters.push_back(visualiserParameters.graticuleEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.smudgesEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.upsamplingEnabled);
|
||||
booleanParameters.push_back(visualiserParameters.visualiserFullScreen);
|
||||
|
||||
for (auto parameter : visualiserParameters.booleans) {
|
||||
booleanParameters.push_back(parameter);
|
||||
}
|
||||
|
||||
for (auto parameter : booleanParameters) {
|
||||
addParameter(parameter);
|
||||
|
|
|
@ -51,13 +51,13 @@ SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p)
|
|||
visualiserSettingsWindow.setUsingNativeTitleBar(true);
|
||||
#endif
|
||||
visualiserSettings.setLookAndFeel(&getLookAndFeel());
|
||||
visualiserSettings.setSize(550, 340);
|
||||
visualiserSettings.setSize(550, 370);
|
||||
visualiserSettingsWindow.setContentNonOwned(&visualiserSettings, true);
|
||||
visualiserSettingsWindow.centreWithSize(550, 340);
|
||||
visualiserSettingsWindow.centreWithSize(550, 370);
|
||||
|
||||
menuBar.toFront(true);
|
||||
|
||||
setSize(725, 750);
|
||||
setSize(700, 750);
|
||||
setResizable(true, true);
|
||||
setResizeLimits(250, 250, 999999, 999999);
|
||||
}
|
||||
|
@ -72,12 +72,11 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
|
|||
}
|
||||
|
||||
void SosciPluginEditor::resized() {
|
||||
auto area = getLocalBounds();
|
||||
|
||||
auto topBar = area.removeFromTop(25).removeFromLeft(200);
|
||||
|
||||
auto topBar = getLocalBounds().removeFromTop(25).removeFromLeft(200);
|
||||
menuBar.setBounds(topBar);
|
||||
visualiser.setBounds(getLocalBounds());
|
||||
auto visualiserArea = getLocalBounds();
|
||||
visualiserArea.removeFromTop(25);
|
||||
visualiser.setBounds(visualiserArea);
|
||||
}
|
||||
|
||||
bool SosciPluginEditor::keyPressed(const juce::KeyPress& key) {
|
||||
|
|
|
@ -16,16 +16,12 @@ SosciAudioProcessor::SosciAudioProcessor()
|
|||
: AudioProcessor (BusesProperties().withInput("Input", juce::AudioChannelSet::namedChannelSet(3), true)
|
||||
.withOutput("Output", juce::AudioChannelSet::stereo(), true))
|
||||
#endif
|
||||
{
|
||||
{
|
||||
// locking isn't necessary here because we are in the constructor
|
||||
|
||||
allEffects.push_back(parameters.brightnessEffect);
|
||||
allEffects.push_back(parameters.intensityEffect);
|
||||
allEffects.push_back(parameters.persistenceEffect);
|
||||
allEffects.push_back(parameters.hueEffect);
|
||||
allEffects.push_back(parameters.saturationEffect);
|
||||
allEffects.push_back(parameters.focusEffect);
|
||||
allEffects.push_back(parameters.noiseEffect);
|
||||
for (auto effect : parameters.effects) {
|
||||
allEffects.push_back(effect);
|
||||
}
|
||||
|
||||
for (auto effect : allEffects) {
|
||||
for (auto effectParameter : effect->parameters) {
|
||||
|
@ -35,11 +31,10 @@ SosciAudioProcessor::SosciAudioProcessor()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
booleanParameters.push_back(parameters.graticuleEnabled);
|
||||
booleanParameters.push_back(parameters.smudgesEnabled);
|
||||
booleanParameters.push_back(parameters.upsamplingEnabled);
|
||||
booleanParameters.push_back(parameters.visualiserFullScreen);
|
||||
|
||||
for (auto parameter : parameters.booleans) {
|
||||
booleanParameters.push_back(parameter);
|
||||
}
|
||||
|
||||
for (auto parameter : booleanParameters) {
|
||||
addParameter(parameter);
|
||||
|
|
|
@ -6,6 +6,9 @@ uniform sampler2D uTexture2; //big glow
|
|||
uniform sampler2D uTexture3; //screen
|
||||
uniform float uExposure;
|
||||
uniform float uSaturation;
|
||||
uniform float uNoise;
|
||||
uniform float uTime;
|
||||
uniform float uGlow;
|
||||
uniform vec3 uColour;
|
||||
varying vec2 vTexCoord;
|
||||
varying vec2 vTexCoordCanvas;
|
||||
|
@ -16,10 +19,8 @@ vec3 desaturate(vec3 color, float factor) {
|
|||
return vec3(mix(color, gray, factor));
|
||||
}
|
||||
|
||||
/* Gradient noise from Jorge Jimenez's presentation: */
|
||||
/* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */
|
||||
float gradientNoise(in vec2 uv) {
|
||||
return fract(52.9829189 * fract(dot(uv, vec2(0.06711056, 0.00583715))));
|
||||
float noise(in vec2 uv, in float time) {
|
||||
return (fract(sin(dot(uv, vec2(12.9898,78.233)*2.0 + time)) * 43758.5453)) - 0.5;
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
@ -28,13 +29,13 @@ void main() {
|
|||
vec4 screen = texture2D(uTexture3, vTexCoord);
|
||||
vec4 tightGlow = texture2D(uTexture1, vTexCoord);
|
||||
vec4 scatter = texture2D(uTexture2, vTexCoord)+0.35;
|
||||
float light = line.r + 1.5*screen.g*screen.g*tightGlow.r;
|
||||
light += 0.4*scatter.g * (2.0+1.0*screen.g + 0.5*screen.r);
|
||||
float light = line.r + uGlow * 1.5 * screen.g * screen.g * tightGlow.r;
|
||||
light += uGlow * 0.4 * scatter.g * (2.0 + 1.0 * screen.g + 0.5 * screen.r);
|
||||
float tlight = 1.0-pow(2.0, -uExposure*light);
|
||||
float tlight2 = tlight*tlight*tlight;
|
||||
float tlight2 = tlight * tlight * tlight;
|
||||
gl_FragColor.rgb = mix(uColour, vec3(1.0), 0.3+tlight2*tlight2*0.5)*tlight;
|
||||
gl_FragColor.rgb = desaturate(gl_FragColor.rgb, 1.0 - uSaturation);
|
||||
gl_FragColor.rgb += (1.0 / 255.0) * gradientNoise(gl_FragCoord.xy) - (0.5 / 255.0);
|
||||
gl_FragColor.rgb += uNoise * noise(gl_FragCoord.xy, uTime);
|
||||
gl_FragColor.a = 1.0;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,11 +141,7 @@ void VisualiserComponent::haltRecording() {
|
|||
|
||||
void VisualiserComponent::resized() {
|
||||
auto area = getLocalBounds();
|
||||
if (visualiserOnly) {
|
||||
buttonRow = area.removeFromTop(25);
|
||||
} else {
|
||||
buttonRow = area.removeFromBottom(25);
|
||||
}
|
||||
buttonRow = area.removeFromBottom(25);
|
||||
if (parent == nullptr && !visualiserOnly) {
|
||||
fullScreenButton.setBounds(buttonRow.removeFromRight(30));
|
||||
}
|
||||
|
@ -230,7 +226,7 @@ void VisualiserComponent::newOpenGLContextCreated() {
|
|||
glGenBuffers(1, &vertexBuffer);
|
||||
setupTextures();
|
||||
|
||||
setupArrays(smoothedXSamples.size());
|
||||
setupArrays(xSamples.size() * RESAMPLE_RATIO);
|
||||
}
|
||||
|
||||
void VisualiserComponent::openGLContextClosing() {
|
||||
|
@ -255,7 +251,7 @@ void VisualiserComponent::openGLContextClosing() {
|
|||
}
|
||||
|
||||
void VisualiserComponent::handleAsyncUpdate() {
|
||||
{
|
||||
if (settings.parameters.upsamplingEnabled->getBoolValue()) {
|
||||
juce::CriticalSection::ScopedLockType lock(samplesLock);
|
||||
|
||||
int newResampledSize = xSamples.size() * RESAMPLE_RATIO;
|
||||
|
@ -280,6 +276,7 @@ void VisualiserComponent::handleAsyncUpdate() {
|
|||
|
||||
void VisualiserComponent::renderOpenGL() {
|
||||
if (openGLContext.isActive()) {
|
||||
time += 0.01f;
|
||||
juce::OpenGLHelpers::clear(juce::Colours::black);
|
||||
if (active) {
|
||||
juce::CriticalSection::ScopedLockType lock(samplesLock);
|
||||
|
@ -292,7 +289,11 @@ void VisualiserComponent::renderOpenGL() {
|
|||
|
||||
renderScale = (float) openGLContext.getRenderingScale();
|
||||
|
||||
drawLineTexture(smoothedXSamples, smoothedYSamples, smoothedZSamples);
|
||||
if (settings.parameters.upsamplingEnabled->getBoolValue()) {
|
||||
drawLineTexture(smoothedXSamples, smoothedYSamples, smoothedZSamples);
|
||||
} else {
|
||||
drawLineTexture(xSamples, ySamples, zSamples);
|
||||
}
|
||||
checkGLErrors("drawLineTexture");
|
||||
drawCRT();
|
||||
checkGLErrors("drawCRT");
|
||||
|
@ -312,7 +313,7 @@ void VisualiserComponent::viewportChanged(juce::Rectangle<int> area) {
|
|||
|
||||
float minDim = juce::jmin(realWidth, realHeight);
|
||||
float x = (realWidth - minDim) / 2 + area.getX() * renderScale + xOffset;
|
||||
float y = (realHeight - minDim) / 2 + area.getY() * renderScale + yOffset;
|
||||
float y = (realHeight - minDim) / 2 - area.getY() * renderScale + yOffset;
|
||||
|
||||
glViewport(juce::roundToInt(x), juce::roundToInt(y), juce::roundToInt(minDim), juce::roundToInt(minDim));
|
||||
}
|
||||
|
@ -567,9 +568,7 @@ void VisualiserComponent::drawLine(const std::vector<float>& xPoints, const std:
|
|||
if (settings.getUpsamplingEnabled()) {
|
||||
lineShader->setUniform("uIntensity", intensity);
|
||||
} else {
|
||||
// TODO: filter steps
|
||||
int steps = 6;
|
||||
lineShader->setUniform("uIntensity", (GLfloat) (intensity * (steps + 1.5)));
|
||||
lineShader->setUniform("uIntensity", (GLfloat) (intensity * RESAMPLE_RATIO * 1.5));
|
||||
}
|
||||
|
||||
lineShader->setUniform("uFadeAmount", fadeAmount);
|
||||
|
@ -642,6 +641,9 @@ void VisualiserComponent::drawCRT() {
|
|||
float brightness = std::pow(2, settings.getBrightness() - 2);
|
||||
outputShader->setUniform("uExposure", brightness);
|
||||
outputShader->setUniform("uSaturation", (float) settings.getSaturation());
|
||||
outputShader->setUniform("uNoise", (float) settings.getNoise());
|
||||
outputShader->setUniform("uTime", time);
|
||||
outputShader->setUniform("uGlow", (float) settings.getGlow());
|
||||
outputShader->setUniform("uResizeForCanvas", lineTexture.width / 1024.0f);
|
||||
juce::Colour colour = juce::Colour::fromHSV(settings.getHue() / 360.0f, 1.0, 1.0, 1.0);
|
||||
outputShader->setUniform("uColour", colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue());
|
||||
|
|
|
@ -84,6 +84,8 @@ private:
|
|||
|
||||
juce::OpenGLContext openGLContext;
|
||||
|
||||
float time = 0;
|
||||
|
||||
juce::Rectangle<int> buttonRow;
|
||||
juce::Rectangle<int> viewportArea;
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
|
|||
addAndMakeVisible(hue);
|
||||
addAndMakeVisible(saturation);
|
||||
addAndMakeVisible(focus);
|
||||
addAndMakeVisible(noise);
|
||||
addAndMakeVisible(glow);
|
||||
addAndMakeVisible(graticuleToggle);
|
||||
addAndMakeVisible(smudgeToggle);
|
||||
addAndMakeVisible(upsamplingToggle);
|
||||
|
@ -20,6 +22,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& parameters, int num
|
|||
hue.setSliderOnValueChange();
|
||||
saturation.setSliderOnValueChange();
|
||||
focus.setSliderOnValueChange();
|
||||
noise.setSliderOnValueChange();
|
||||
glow.setSliderOnValueChange();
|
||||
}
|
||||
|
||||
VisualiserSettings::~VisualiserSettings() {}
|
||||
|
@ -33,6 +37,8 @@ void VisualiserSettings::resized() {
|
|||
hue.setBounds(area.removeFromTop(rowHeight));
|
||||
saturation.setBounds(area.removeFromTop(rowHeight));
|
||||
focus.setBounds(area.removeFromTop(rowHeight));
|
||||
noise.setBounds(area.removeFromTop(rowHeight));
|
||||
glow.setBounds(area.removeFromTop(rowHeight));
|
||||
graticuleToggle.setBounds(area.removeFromTop(rowHeight));
|
||||
smudgeToggle.setBounds(area.removeFromTop(rowHeight));
|
||||
upsamplingToggle.setBounds(area.removeFromTop(rowHeight));
|
||||
|
|
|
@ -12,7 +12,7 @@ class VisualiserParameters {
|
|||
public:
|
||||
BooleanParameter* graticuleEnabled = new BooleanParameter("Show Graticule", "graticuleEnabled", VERSION_HINT, true, "Show the graticule or grid lines over the oscilloscope display.");
|
||||
BooleanParameter* smudgesEnabled = new BooleanParameter("Show Smudges", "smudgesEnabled", VERSION_HINT, true, "Adds a subtle layer of dirt/smudges to the oscilloscope display to make it look more realistic.");
|
||||
BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, false, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
|
||||
BooleanParameter* upsamplingEnabled = new BooleanParameter("Upsample Audio", "upsamplingEnabled", VERSION_HINT, true, "Upsamples the audio before visualising it to make it appear more realistic, at the expense of performance.");
|
||||
BooleanParameter* visualiserFullScreen = new BooleanParameter("Visualiser Fullscreen", "visualiserFullScreen", VERSION_HINT, false, "Makes the software visualiser fullscreen.");
|
||||
|
||||
std::shared_ptr<Effect> persistenceEffect = std::make_shared<Effect>(
|
||||
|
@ -68,9 +68,20 @@ public:
|
|||
"Noise",
|
||||
"Controls how much noise/grain is added to the oscilloscope display.",
|
||||
"noise",
|
||||
VERSION_HINT, 1.0, 0.01, 1.0
|
||||
VERSION_HINT, 0.1, 0.0, 1.0
|
||||
)
|
||||
);
|
||||
std::shared_ptr<Effect> glowEffect = std::make_shared<Effect>(
|
||||
new EffectParameter(
|
||||
"Glow",
|
||||
"Controls how much the light glows on the oscilloscope display.",
|
||||
"glow",
|
||||
VERSION_HINT, 0.3, 0.0, 1.0
|
||||
)
|
||||
);
|
||||
|
||||
std::vector<std::shared_ptr<Effect>> effects = {persistenceEffect, hueEffect, brightnessEffect, intensityEffect, saturationEffect, focusEffect, noiseEffect, glowEffect};
|
||||
std::vector<BooleanParameter*> booleans = {graticuleEnabled, smudgesEnabled, upsamplingEnabled, visualiserFullScreen};
|
||||
};
|
||||
|
||||
class VisualiserSettings : public juce::Component {
|
||||
|
@ -108,6 +119,10 @@ public:
|
|||
return parameters.noiseEffect->getActualValue();
|
||||
}
|
||||
|
||||
double getGlow() {
|
||||
return parameters.glowEffect->getActualValue() * 3;
|
||||
}
|
||||
|
||||
bool getGraticuleEnabled() {
|
||||
return parameters.graticuleEnabled->getBoolValue();
|
||||
}
|
||||
|
@ -130,6 +145,8 @@ private:
|
|||
EffectComponent hue{*parameters.hueEffect};
|
||||
EffectComponent saturation{*parameters.saturationEffect};
|
||||
EffectComponent focus{*parameters.focusEffect};
|
||||
EffectComponent noise{*parameters.noiseEffect};
|
||||
EffectComponent glow{*parameters.glowEffect};
|
||||
|
||||
jux::SwitchButton graticuleToggle{parameters.graticuleEnabled};
|
||||
jux::SwitchButton smudgeToggle{parameters.smudgesEnabled};
|
||||
|
|
Ładowanie…
Reference in New Issue