Files
crushFX/Source/FilterView.cpp
2026-01-23 17:18:02 +13:00

226 lines
8.7 KiB
C++

/*
==============================================================================
FilterView.cpp
Created: 16 Jan 2026 5:06:31pm
Author: esca
==============================================================================
*/
#include <JuceHeader.h>
#include "FilterView.h"
#include "BinaryData.h"
#include "OpenGLUtils.h"
#include "juce_opengl/juce_opengl.h"
#include "juce_opengl/opengl/juce_gl.h"
//==============================================================================
FilterView::FilterView()
{
cutoff = &tempcutoff;
mix = &tempmix;
//generate filter arrays for first time
for(unsigned int i=0; i<FILTERVIEW_SAMPLECOUNT; i++){
filterVertices.push_back(Vertex{{0,0}, COLOUR});
filterIndices.push_back(i);
filterBackgroundVertices.push_back(Vertex{{0,0}, BGCOLOUR});
//BACKGROUND INDICES
if(i!=0&&i%2==0){
filterBackgroundIndices.insert(filterBackgroundIndices.end(), { i-2, i-1, i });
}
if(i!=1&&i%2!=0){
filterBackgroundIndices.insert(filterBackgroundIndices.end(), { i-2, i-1, i });
}
}
genFilterArrays();
float startingColour[4] = {128.0f, 255.0f, 255.0f, 255.0f};
backgroundVertices.push_back(VertexTexture{{-1, -1}, {255.0f, 255.0f, 255.0f, 255.0f}, {0.0f, 0.0f}});
backgroundVertices.push_back(VertexTexture{{-1, 1}, {255.0f, 255.0f, 255.0f, 255.0f}, {0.0f, 1.0f}});
backgroundVertices.push_back(VertexTexture{{1, -1}, {255.0f, 255.0f, 255.0f, 255.0f}, {1.0f, 0.0f}});
backgroundVertices.push_back(VertexTexture{{1, 1}, {255.0f, 255.0f, 255.0f, 255.0f}, {1.0f, 1.0f}});
backgroundIndices = {0,1,2,1,2,3};
setOpaque(true);
}
FilterView::~FilterView()
{
bgTexture.bind();
bgTexture.release();
shaderProgramFilter->release();
shaderProgramFilterFill->release();
shaderProgramBackground->release();
// ctx.detach(); //failing here
}
void FilterView::genFilterArrays(){
int i = 0;
float yposition = *mix;
for(Vertex &v : filterVertices){
float xposition = (float)i/FILTERVIEW_SAMPLECOUNT;
float deltaCutoff = xposition-*cutoff;
v.position[0] = xposition;
if(deltaCutoff>0){
v.position[1] = yposition-5*(deltaCutoff*deltaCutoff);
if(v.position[1]<0){
v.position[1]=0;
}
}
else v.position[1] = yposition;
i++;
}
vScale(filterVertices, 2, 2);
vTransform(filterVertices, -1, -1);
genFilterFillArrays();
}
void FilterView::genFilterFillArrays(){
for(unsigned int i = 0; i<FILTERVIEW_SAMPLECOUNT; i++){
if(i%2==0){
filterBackgroundVertices.at(i) = filterVertices.at(i);
filterBackgroundVertices.at(i).position[1]=-1;
}
else{
filterBackgroundVertices.at(i) = filterVertices.at(i-1);
}
}
}
void FilterView::paint (juce::Graphics& g)
{
ctx.triggerRepaint();
}
void FilterView::resized()
{
}
//OPENGL STUFF
void FilterView::newOpenGLContextCreated(){
background = juce::ImageCache::getFromMemory(BinaryData::panel_png, BinaryData::panel_pngSize);
background.duplicateIfShared();
bgTexture.loadImage(background);
//GENERATE BUFFERS
ctx.extensions.glGenBuffers(1, &vboBackground);
ctx.extensions.glGenBuffers(1, &iboBackground);
ctx.extensions.glGenBuffers(1, &vboFilterFill);
ctx.extensions.glGenBuffers(1, &iboFilterFill);
ctx.extensions.glGenBuffers(1, &vboFilter);
ctx.extensions.glGenBuffers(1, &iboFilter);
//BIND BACKGROUND BUFFERS
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboBackground);
ctx.extensions.glBufferData(juce::gl::GL_ARRAY_BUFFER, sizeof(VertexTexture)*backgroundVertices.size(), backgroundVertices.data(), juce::gl::GL_STATIC_DRAW);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboBackground);
ctx.extensions.glBufferData(juce::gl::GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * backgroundIndices.size(), backgroundIndices.data(), juce::gl::GL_STATIC_DRAW);
//BIND FILTER FILL BUFFERS
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboFilterFill);
ctx.extensions.glBufferData(juce::gl::GL_ARRAY_BUFFER, sizeof(Vertex)*filterBackgroundVertices.size(), filterBackgroundVertices.data(), juce::gl::GL_STATIC_DRAW);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboFilterFill);
ctx.extensions.glBufferData(juce::gl::GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * filterBackgroundIndices.size(), filterBackgroundIndices.data(), juce::gl::GL_STATIC_DRAW);
//BIND FILTER BUFFERS
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboFilter);
ctx.extensions.glBufferData(juce::gl::GL_ARRAY_BUFFER, sizeof(Vertex)*filterVertices.size(), filterVertices.data(), juce::gl::GL_STATIC_DRAW);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboFilter);
ctx.extensions.glBufferData(juce::gl::GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * filterIndices.size(), filterIndices.data(), juce::gl::GL_STATIC_DRAW);
//SHADERS
vertexShaderFilter = VERTEXSHADERFILTER;
fragmentShaderFilter = FRAGSHADERFILTER;
vertexShaderFilterFill = VERTEXSHADERFILTERFILL;
fragmentShaderFilterFill = FRAGSHADERFILTER;
vertexShaderBackground = VERTEXSHADERBACKGROUND;
fragmentShaderBackground = FRAGSHADERBACKGROUND;
//actually render the shaders now
shaderProgramBackground.reset(new juce::OpenGLShaderProgram(ctx));
shaderProgramBackground->addVertexShader(vertexShaderBackground);
shaderProgramBackground->addFragmentShader(fragmentShaderBackground);
shaderProgramBackground->link();
shaderProgramBackground->use();
shaderProgramFilterFill.reset(new juce::OpenGLShaderProgram(ctx));
shaderProgramFilterFill->addVertexShader(vertexShaderFilterFill);
shaderProgramFilterFill->addFragmentShader(fragmentShaderFilterFill);
shaderProgramFilterFill->link();
shaderProgramFilterFill->use();
shaderProgramFilter.reset(new juce::OpenGLShaderProgram(ctx));
shaderProgramFilter->addVertexShader(vertexShaderFilter);
shaderProgramFilter->addFragmentShader(fragmentShaderFilter);
shaderProgramFilter->link();
shaderProgramFilter->use();
}
void FilterView::renderOpenGL(){
juce::gl::glLineWidth(2.5f);
juce::OpenGLHelpers::clear(juce::Colours::black);
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboBackground);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboBackground);
//RENDER BACKGROUND
shaderProgramBackground->use();
bgTexture.bind();
juce::gl::glEnable(juce::gl::GL_BLEND);
juce::gl::glBlendFunc(juce::gl::GL_SRC_ALPHA, juce::gl::GL_ONE_MINUS_SRC_ALPHA);
ctx.extensions.glVertexAttribPointer(0, 2, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(VertexTexture), nullptr);
ctx.extensions.glEnableVertexAttribArray(0);
ctx.extensions.glVertexAttribPointer(1, 4, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(VertexTexture), (GLvoid*)(sizeof(float)*2));
ctx.extensions.glEnableVertexAttribArray(1);
ctx.extensions.glVertexAttribPointer(2, 2, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(VertexTexture), (GLvoid*)(sizeof(float)*6));
ctx.extensions.glEnableVertexAttribArray(2);
juce::gl::glDrawElements(juce::gl::GL_TRIANGLES, backgroundIndices.size(), juce::gl::GL_UNSIGNED_INT, nullptr);
//RENDER FILTER FILL
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboFilterFill);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboFilterFill);
shaderProgramFilterFill->use();
ctx.extensions.glVertexAttribPointer(0, 2, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(Vertex), nullptr);
ctx.extensions.glEnableVertexAttribArray(2);
ctx.extensions.glVertexAttribPointer(1, 4, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(float)*2));
ctx.extensions.glEnableVertexAttribArray(3);
juce::gl::glDrawElements(juce::gl::GL_TRIANGLES, filterBackgroundIndices.size(), juce::gl::GL_UNSIGNED_INT, nullptr);
//RENDER FILTER
ctx.extensions.glBindBuffer(juce::gl::GL_ARRAY_BUFFER, vboFilter);
ctx.extensions.glBindBuffer(juce::gl::GL_ELEMENT_ARRAY_BUFFER, iboFilter);
shaderProgramFilter->use();
ctx.extensions.glVertexAttribPointer(0, 2, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(Vertex), nullptr);
ctx.extensions.glEnableVertexAttribArray(2);
ctx.extensions.glVertexAttribPointer(1, 4, juce::gl::GL_FLOAT, juce::gl::GL_FALSE, sizeof(Vertex), (GLvoid*)(sizeof(float)*2));
ctx.extensions.glEnableVertexAttribArray(3);
juce::gl::glDrawElements(juce::gl::GL_LINE_STRIP, filterIndices.size(), juce::gl::GL_UNSIGNED_INT, nullptr);
}
void FilterView::openGLContextClosing(){
}