Add reflection/glow for vector display

pre-release-3
James H Ball 2024-12-28 21:23:56 +00:00
rodzic 538662a971
commit 8c139112cd
9 zmienionych plików z 138 dodań i 34 usunięć

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 6.3 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 931 KiB

Wyświetl plik

@ -0,0 +1,33 @@
std::string glowFragmentShader = R"(
uniform sampler2D uTexture0;
uniform vec2 uOffset;
uniform vec2 uScale;
varying vec2 vTexCoord;
void main() {
vec2 texCoord = (vTexCoord - 0.5) / uScale + uOffset + 0.5;
vec2 reflectionLinePos1 = (texCoord - 0.5) / 0.875 + 0.5;
vec2 reflectionLinePos2 = (texCoord - 0.5) / 1.125 + 0.5;
vec2 reflectionLinePos3 = (texCoord - 0.5) / 1.375 + 0.5;
vec2 reflectionLinePos4 = (texCoord - 0.5) / 1.625 + 0.5;
vec2 reflectionLinePos5 = (texCoord - 0.5) / 1.875 + 0.5;
vec2 distVec = (texCoord - 0.5);
float dist = dot(distVec, distVec);
float decay = 1.0 - dist;
vec4 sum = vec4(0.0);
sum += texture2D(uTexture0, reflectionLinePos1);
sum += texture2D(uTexture0, reflectionLinePos2);
sum += texture2D(uTexture0, reflectionLinePos3);
sum += texture2D(uTexture0, reflectionLinePos4);
sum += texture2D(uTexture0, reflectionLinePos5);
sum *= 3.0 * pow(decay, 4.0);
gl_FragColor = sum;
gl_FragColor.a = 1.0;
}
)";

Wyświetl plik

@ -0,0 +1,11 @@
std::string glowVertexShader = R"(
attribute vec2 aPos;
varying vec2 vTexCoord;
void main() {
gl_Position = vec4(aPos, 0.0, 1.0);
vTexCoord = (0.5*aPos+0.5);
}
)";

Wyświetl plik

@ -4,6 +4,8 @@ uniform sampler2D uTexture0; //line
uniform sampler2D uTexture1; //tight glow
uniform sampler2D uTexture2; //big glow
uniform sampler2D uTexture3; //screen
uniform sampler2D uTexture4; //reflection
uniform sampler2D uTexture5; //screen glow
uniform float uExposure;
uniform float uSaturation;
uniform float uNoise;
@ -43,6 +45,13 @@ void main() {
vec4 screen = texture2D(uTexture3, vTexCoord);
vec4 tightGlow = texture2D(uTexture1, linePos);
vec4 scatter = texture2D(uTexture2, linePos) + (1.0 - uRealScreen) * max(uAmbient - 0.35, 0.0);
if (uRealScreen > 0.5) {
vec4 reflection = texture2D(uTexture4, vTexCoord);
vec4 screenGlow = texture2D(uTexture5, vTexCoord);
scatter += screenGlow * reflection * max(1.0 - uAmbient, 0.0);
}
float light = line.r + uGlow * 1.5 * screen.g * screen.g * tightGlow.r;
light += uGlow * 0.3 * scatter.g * (2.0 + 1.0 * screen.g + 0.5 * screen.r);
float tlight = 1.0-pow(2.0, -uExposure*light);

Wyświetl plik

@ -4,6 +4,8 @@
#include "BlurVertexShader.glsl"
#include "WideBlurFragmentShader.glsl"
#include "WideBlurVertexShader.glsl"
#include "GlowFragmentShader.glsl"
#include "GlowVertexShader.glsl"
#include "LineFragmentShader.glsl"
#include "LineVertexShader.glsl"
#include "OutputFragmentShader.glsl"
@ -359,7 +361,7 @@ void VisualiserComponent::initialiseSharedTexture() {
sharedTextureSender->setSharedTextureId(renderTexture.id);
sharedTextureSender->setDrawFunction([this] {
setShader(texturedShader.get());
drawTexture(renderTexture);
drawTexture({renderTexture});
});
}
@ -416,6 +418,11 @@ void VisualiserComponent::newOpenGLContextCreated() {
wideBlurShader->addFragmentShader(wideBlurFragmentShader);
wideBlurShader->link();
glowShader = std::make_unique<juce::OpenGLShaderProgram>(openGLContext);
glowShader->addVertexShader(juce::OpenGLHelpers::translateVertexShaderToV3(glowVertexShader));
glowShader->addFragmentShader(glowFragmentShader);
glowShader->link();
glGenBuffers(1, &vertexBuffer);
glGenBuffers(1, &quadIndexBuffer);
glGenBuffers(1, &vertexIndexBuffer);
@ -437,12 +444,16 @@ void VisualiserComponent::openGLContextClosing() {
glDeleteTextures(1, &blur2Texture.id);
glDeleteTextures(1, &blur3Texture.id);
glDeleteTextures(1, &blur4Texture.id);
glDeleteTextures(1, &glowTexture.id);
glDeleteTextures(1, &renderTexture.id);
screenOpenGLTexture.release();
reflectionOpenGLTexture.release();
simpleShader.reset();
texturedShader.reset();
blurShader.reset();
wideBlurShader.reset();
glowShader.reset();
lineShader.reset();
outputShader.reset();
}
@ -494,7 +505,7 @@ void VisualiserComponent::renderOpenGL() {
// render texture to screen
activateTargetTexture(std::nullopt);
setShader(texturedShader.get());
drawTexture(renderTexture);
drawTexture({renderTexture});
}
}
@ -568,8 +579,10 @@ void VisualiserComponent::setupTextures() {
blur2Texture = makeTexture(512, 512);
blur3Texture = makeTexture(128, 128);
blur4Texture = makeTexture(128, 128);
glowTexture = makeTexture(512, 512);
renderTexture = makeTexture(1024, 1024);
reflectionTexture = createReflectionTexture();
screenTexture = createScreenTexture();
glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind
@ -683,31 +696,17 @@ void VisualiserComponent::setShader(juce::OpenGLShaderProgram* program) {
program->use();
}
void VisualiserComponent::drawTexture(std::optional<Texture> texture0, std::optional<Texture> texture1, std::optional<Texture> texture2, std::optional<Texture> texture3) {
void VisualiserComponent::drawTexture(std::vector<std::optional<Texture>> textures) {
using namespace juce::gl;
glEnableVertexAttribArray(glGetAttribLocation(currentShader->getProgramID(), "aPos"));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture0.value().id);
currentShader->setUniform("uTexture0", 0);
if (texture1.has_value()) {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture1.value().id);
currentShader->setUniform("uTexture1", 1);
}
if (texture2.has_value()) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, texture2.value().id);
currentShader->setUniform("uTexture2", 2);
}
if (texture3.has_value()) {
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texture3.value().id);
currentShader->setUniform("uTexture3", 3);
for (int i = 0; i < textures.size(); ++i) {
if (textures[i].has_value()) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, textures[i].value().id);
currentShader->setUniform(("uTexture" + juce::String(i)).toStdString().c_str(), i);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
@ -822,35 +821,53 @@ void VisualiserComponent::drawCRT() {
activateTargetTexture(blur1Texture);
setShader(texturedShader.get());
texturedShader->setUniform("uResizeForCanvas", lineTexture.width / 1024.0f);
drawTexture(lineTexture);
drawTexture({lineTexture});
//horizontal blur 256x256
//horizontal blur 512x512
activateTargetTexture(blur2Texture);
setShader(blurShader.get());
blurShader->setUniform("uOffset", 1.0f / 512.0f, 0.0f);
drawTexture(blur1Texture);
drawTexture({blur1Texture});
//vertical blur 256x256
//vertical blur 512x512
activateTargetTexture(blur1Texture);
blurShader->setUniform("uOffset", 0.0f, 1.0f / 512.0f);
drawTexture(blur2Texture);
drawTexture({blur2Texture});
//preserve blur1 for later
activateTargetTexture(blur3Texture);
setShader(texturedShader.get());
texturedShader->setUniform("uResizeForCanvas", 1.0f);
drawTexture(blur1Texture);
drawTexture({blur1Texture});
//horizontal blur 128x128
activateTargetTexture(blur4Texture);
setShader(wideBlurShader.get());
wideBlurShader->setUniform("uOffset", 1.0f / 128.0f, 0.0f);
drawTexture(blur3Texture);
drawTexture({blur3Texture});
//vertical blur 128x128
activateTargetTexture(blur3Texture);
wideBlurShader->setUniform("uOffset", 0.0f, 1.0f / 128.0f);
drawTexture(blur4Texture);
drawTexture({blur4Texture});
// create glow texture
activateTargetTexture(glowTexture);
setShader(glowShader.get());
setOffsetAndScale(glowShader.get());
drawTexture({blur3Texture});
// blur the glow texture to blend it nicely. blur3Texture and blur1Texture are reserved, so we can't use them
// horizontal 512x512
activateTargetTexture(blur2Texture);
setShader(wideBlurShader.get());
wideBlurShader->setUniform("uOffset", 1.0f / 512.0f, 0.0f);
drawTexture({glowTexture});
// vertical 512x512
activateTargetTexture(glowTexture);
wideBlurShader->setUniform("uOffset", 0.0f, 1.0f / 512.0f);
drawTexture({blur2Texture});
activateTargetTexture(renderTexture);
setShader(outputShader.get());
@ -866,7 +883,7 @@ void VisualiserComponent::drawCRT() {
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());
drawTexture(lineTexture, blur1Texture, blur3Texture, screenTexture);
drawTexture({lineTexture, blur1Texture, blur3Texture, screenTexture, reflectionTexture, glowTexture});
}
void VisualiserComponent::setOffsetAndScale(juce::OpenGLShaderProgram* shader) {
@ -882,10 +899,23 @@ void VisualiserComponent::setOffsetAndScale(juce::OpenGLShaderProgram* shader) {
scale = { 1.0f };
}
shader->setUniform("uOffset", (float) offset.x, (float) offset.y);
checkGLErrors("test 4");
shader->setUniform("uScale", (float) scale.x, (float) scale.y);
}
Texture VisualiserComponent::createReflectionTexture() {
using namespace juce::gl;
if (settings.getScreenType() == ScreenType::VectorDisplay) {
reflectionOpenGLTexture.loadImage(vectorDisplayReflectionImage);
} else {
reflectionOpenGLTexture.loadImage(emptyReflectionImage);
}
Texture texture = { reflectionOpenGLTexture.getTextureID(), reflectionOpenGLTexture.getWidth(), reflectionOpenGLTexture.getHeight() };
return texture;
}
Texture VisualiserComponent::createScreenTexture() {
using namespace juce::gl;
@ -1000,6 +1030,7 @@ void VisualiserComponent::renderScope(const std::vector<float>& xPoints, const s
if (screenType != settings.getScreenType()) {
screenType = settings.getScreenType();
reflectionTexture = createReflectionTexture();
screenTexture = createScreenTexture();
}

Wyświetl plik

@ -168,13 +168,18 @@ private:
Texture blur2Texture;
Texture blur3Texture;
Texture blur4Texture;
Texture glowTexture;
Texture renderTexture;
juce::OpenGLTexture screenOpenGLTexture;
juce::OpenGLTexture reflectionOpenGLTexture;
juce::Image screenTextureImage = juce::ImageFileFormat::loadFrom(BinaryData::noise_jpg, BinaryData::noise_jpgSize);
juce::Image emptyScreenImage = juce::ImageFileFormat::loadFrom(BinaryData::empty_jpg, BinaryData::empty_jpgSize);
juce::Image oscilloscopeImage = juce::ImageFileFormat::loadFrom(BinaryData::real_jpg, BinaryData::real_jpgSize);
juce::Image vectorDisplayImage = juce::ImageFileFormat::loadFrom(BinaryData::vector_display_jpg, BinaryData::vector_display_jpgSize);
juce::Image emptyReflectionImage = juce::ImageFileFormat::loadFrom(BinaryData::no_reflection_jpg, BinaryData::no_reflection_jpgSize);
juce::Image vectorDisplayReflectionImage = juce::ImageFileFormat::loadFrom(BinaryData::vector_display_reflection_jpg, BinaryData::vector_display_reflection_jpgSize);
OsciPoint REAL_SCREEN_OFFSET = { 0.02, -0.15 };
OsciPoint REAL_SCREEN_SCALE = { 0.6 };
@ -183,12 +188,14 @@ private:
float VECTOR_DISPLAY_FISH_EYE = 0.5;
Texture screenTexture;
Texture reflectionTexture;
std::optional<Texture> targetTexture = std::nullopt;
std::unique_ptr<juce::OpenGLShaderProgram> simpleShader;
std::unique_ptr<juce::OpenGLShaderProgram> texturedShader;
std::unique_ptr<juce::OpenGLShaderProgram> blurShader;
std::unique_ptr<juce::OpenGLShaderProgram> wideBlurShader;
std::unique_ptr<juce::OpenGLShaderProgram> glowShader;
std::unique_ptr<juce::OpenGLShaderProgram> lineShader;
std::unique_ptr<juce::OpenGLShaderProgram> outputShader;
juce::OpenGLShaderProgram* currentShader;
@ -214,7 +221,7 @@ private:
void saveTextureToQOI(Texture texture, const juce::File& file);
void activateTargetTexture(std::optional<Texture> texture);
void setShader(juce::OpenGLShaderProgram* program);
void drawTexture(std::optional<Texture> texture0, std::optional<Texture> texture1 = std::nullopt, std::optional<Texture> texture2 = std::nullopt, std::optional<Texture> texture3 = std::nullopt);
void drawTexture(std::vector<std::optional<Texture>> textures);
void setAdditiveBlending();
void setNormalBlending();
void drawLine(const std::vector<float>& xPoints, const std::vector<float>& yPoints, const std::vector<float>& zPoints);
@ -227,6 +234,7 @@ private:
int renderAudioFile(juce::File& sourceAudio, int method = 1, int width = 1024, int height = 1024);
Texture createScreenTexture();
Texture createReflectionTexture();
juce::File audioFile;

Wyświetl plik

@ -33,10 +33,14 @@
</GROUP>
<GROUP id="{F3C16D02-63B4-E3DA-7498-901173C37D6C}" name="oscilloscope">
<FILE id="qpPhpN" name="empty.jpg" compile="0" resource="1" file="Resources/oscilloscope/empty.jpg"/>
<FILE id="RgmiPU" name="no_reflection.jpg" compile="0" resource="1"
file="Resources/oscilloscope/no_reflection.jpg"/>
<FILE id="dNtZYs" name="noise.jpg" compile="0" resource="1" file="Resources/oscilloscope/noise.jpg"/>
<FILE id="FyEDbA" name="real.jpg" compile="0" resource="1" file="Resources/oscilloscope/real.jpg"/>
<FILE id="QrCP4w" name="vector_display.jpg" compile="0" resource="1"
file="Resources/oscilloscope/vector_display.jpg"/>
<FILE id="s3VNsJ" name="vector_display_reflection.jpg" compile="0"
resource="1" file="Resources/oscilloscope/vector_display_reflection.jpg"/>
</GROUP>
<GROUP id="{82BCD6F1-A8BF-F30B-5587-81EE70168883}" name="svg">
<FILE id="rl17ZK" name="cog.svg" compile="0" resource="1" file="Resources/svg/cog.svg"/>
@ -606,6 +610,10 @@
file="Source/visualiser/BlurFragmentShader.glsl" xcodeResource="0"/>
<FILE id="c59gvD" name="BlurVertexShader.glsl" compile="0" resource="0"
file="Source/visualiser/BlurVertexShader.glsl" xcodeResource="0"/>
<FILE id="dma1IP" name="GlowFragmentShader.glsl" compile="0" resource="0"
file="Source/visualiser/GlowFragmentShader.glsl"/>
<FILE id="ytSpvX" name="GlowVertexShader.glsl" compile="0" resource="0"
file="Source/visualiser/GlowVertexShader.glsl"/>
<FILE id="WZFPXF" name="LineFragmentShader.glsl" compile="0" resource="0"
file="Source/visualiser/LineFragmentShader.glsl" xcodeResource="0"/>
<FILE id="iS2Ipw" name="LineVertexShader.glsl" compile="0" resource="0"

Wyświetl plik

@ -22,10 +22,14 @@
</GROUP>
<GROUP id="{F3C16D02-63B4-E3DA-7498-901173C37D6C}" name="oscilloscope">
<FILE id="qpPhpN" name="empty.jpg" compile="0" resource="1" file="Resources/oscilloscope/empty.jpg"/>
<FILE id="ZgcesA" name="no_reflection.jpg" compile="0" resource="1"
file="Resources/oscilloscope/no_reflection.jpg"/>
<FILE id="dNtZYs" name="noise.jpg" compile="0" resource="1" file="Resources/oscilloscope/noise.jpg"/>
<FILE id="xxXx4Q" name="real.jpg" compile="0" resource="1" file="Resources/oscilloscope/real.jpg"/>
<FILE id="bdQp0Q" name="vector_display.jpg" compile="0" resource="1"
file="Resources/oscilloscope/vector_display.jpg"/>
<FILE id="XojumY" name="vector_display_reflection.jpg" compile="0"
resource="1" file="Resources/oscilloscope/vector_display_reflection.jpg"/>
</GROUP>
<GROUP id="{82BCD6F1-A8BF-F30B-5587-81EE70168883}" name="svg">
<FILE id="rl17ZK" name="cog.svg" compile="0" resource="1" file="Resources/svg/cog.svg"/>