Import vertex shader variables into ofApp.cpp

I would like to port the following code to ofApp.cpp and read it.
How should I describe it?

attribute float vertexId; 
uniform float vertexCount;
uniform vec2 resolution; 
uniform float time;
uniform sampler2D sound; // data from the music Nx240, alpha only
                         // 240 rows of history (4secs @60fps)

#define PI05 1.570796326795
#define PI   3.1415926535898

float hash(float x) {
  return fract(sin(x) * 43758.5453123);
}

vec3 rotX(vec3 p, float rad) {
  vec2 sc = sin(vec2(rad, rad + PI05));
  vec3 rp = p;
  rp.y = p.y * sc.y + p.z * -sc.x;
  rp.z = p.y * sc.x + p.z *  sc.y;
  return rp;
}

vec3 rotY(vec3 p, float rad) {
  vec2 sc = sin(vec2(rad, rad + PI05));
  vec3 rp = p;
  rp.x =  p.x *  sc.y + p.z *  sc.x;
  rp.z =  p.x * -sc.x + p.z *  sc.y;
  return rp;
}

vec3 rotZ(vec3 p, float rad) {
  vec2 sc = sin(vec2(rad, rad + PI05));
  vec3 rp = p;
  rp.x =  p.x *  sc.x + p.y * sc.y;
  rp.y =  p.x * -sc.y + p.y * sc.x;
  return rp;
}

vec4 perspective(vec3 p, float fov, float near, float far) {
  vec4 pp = vec4(p, -p.z);
  pp.xy *= vec2(resolution.y / resolution.x, 1.0) / tan(radians(fov * 0.5));
  pp.z = (-p.z * (far + near) - 2.0 * far * near) / (far - near);
  return pp;
}

mat4 lookat(vec3 eye, vec3 look, vec3 up) {
  vec3 z = normalize(eye - look);
  vec3 x = normalize(cross(up, z));
  vec3 y = cross(z, x);
  return mat4(x.x, y.x, z.x, 0.0, x.y, y.y, z.y, 0.0, x.z, y.z, z.z, 0.0, 0.0, 0.0, 0.0, 1.0) * 
    mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -eye.x, -eye.y, -eye.z, 1.0);
}

vec3 hsv2rgb(vec3 c) {
  c = vec3(c.x, clamp(c.yz, 0.0, 1.0));
  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void main() {
  float t = vertexId + time;
  vec4 p = vec4(0.0, 0.0, 0.0, 1.0);
  p.xyz = fract(sin(vec3(t, 0.0, t+0.25)) * 12345.6789);

  float snd = texture2D(sound, p.xz * vec2(0.75, 1.0)).a;

  p.y = pow(snd, 2.0);
  p.xz = p.xz * 2.0 - 1.0;

  float rt = time * 0.25;
  mat4 m = lookat(vec3(cos(rt) * 2.5, 1.0, sin(rt) * 1.5), vec3(0.0, 0.25, 0.0), vec3(0.0, 1.0, 0.0));
  p = m * p;

  vec4 pp = perspective(p.xyz, 60.0, 0.2, 4.0);

  gl_Position = pp;
  gl_PointSize = 10.0 / length(p.xyz);

  v_color = vec4(hsv2rgb(vec3(snd, 1.0, 1.0)), 1.0);
}

Please tell me how to write the code in ofApp.cpp to load these shaders.

https://vimeo.com/212993101

Is this what you want to draw?

Maybe you could get better answers if you bring more details such as how’s output looks like something like that. You can try this code out, just swap your ofApp.cpp with this one then it will work. make sure to have your audio file in your bin folder and change the line

beat.load("J Dilla - Life (Instrumental).mp3");

I grabbed fft example from openframeworks sound/fft example, I don’t know who made this example but love your choice on beat sample from dilla :slight_smile:

I believe there must be a better way to pass fft and history of fft to shader. but I just passed it as an attribute vertex array.

#include "ofApp.h"
#define GLSL(version, shader)  "#version " #version "\n" #shader

ofShader shader;
ofCamera cam;
ofMesh mesh;
int num_vertices;

float * fftHistory;
float * fftSmooth;
ofSoundPlayer beat;

void ofApp::setup(){
    num_vertices = 256 * 256;
    ofDisableArbTex();
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    
    std::string vert = GLSL(120,
        attribute float vertexId;
        attribute float sound;
        uniform float vertexCount;
        uniform float time;
        uniform vec2 resolution;
                            
        const float PI05 = 1.570796326795;
                            
        float hash(float x) {
            return fract(sin(x) * 43758.5453123);
        }
        
        vec3 rotX(vec3 p, float rad) {
            vec2 sc = sin(vec2(rad, rad + PI05));
            vec3 rp = p;
            rp.y = p.y * sc.y + p.z * -sc.x;
            rp.z = p.y * sc.x + p.z *  sc.y;
            return rp;
        }
        
        vec3 rotY(vec3 p, float rad) {
            vec2 sc = sin(vec2(rad, rad + PI05));
            vec3 rp = p;
            rp.x =  p.x *  sc.y + p.z *  sc.x;
            rp.z =  p.x * -sc.x + p.z *  sc.y;
            return rp;
        }
        
        vec3 rotZ(vec3 p, float rad) {
            vec2 sc = sin(vec2(rad, rad + PI05));
            vec3 rp = p;
            rp.x =  p.x *  sc.x + p.y * sc.y;
            rp.y =  p.x * -sc.y + p.y * sc.x;
            return rp;
        }
        
        vec4 perspective(vec3 p, float fov, float near, float far) {
            vec4 pp = vec4(p, -p.z);
            pp.xy *= vec2(resolution.y / resolution.x, 1.0) / tan(radians(fov * 0.5));
            pp.z = (-p.z * (far + near) - 2.0 * far * near) / (far - near);
            return pp;
        }
        
        mat4 lookat(vec3 eye, vec3 look, vec3 up) {
            vec3 z = normalize(eye - look);
            vec3 x = normalize(cross(up, z));
            vec3 y = cross(z, x);
            return mat4(x.x, y.x, z.x, 0.0, x.y, y.y, z.y, 0.0, x.z, y.z, z.z, 0.0, 0.0, 0.0, 0.0, 1.0) * 
            mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -eye.x, -eye.y, -eye.z, 1.0);
        }
        
        vec3 hsv2rgb(vec3 c) {
            c = vec3(c.x, clamp(c.yz, 0.0, 1.0));
            vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
            vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
            return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
        }
                            
        void main(){
            float t = vertexId + time*.000000001;
            vec4 p = vec4(0.0, 0.0, 0.0, 1.0);
            p.xyz = fract(sin(vec3(t, 0.0, t+0.25)) * 12345.6789);
            
            float snd = sound * .2;
            
            p.y = pow(snd, 2.0)*.2;
            p.xz = p.xz * 2.0 - 1.0;
            
            float rt = time * 0.25;
            mat4 m = lookat(vec3(cos(rt) * 2.5, 1.0, sin(rt) * 1.5), vec3(0.0, 0.25, 0.0), vec3(0.0, 1.0, 0.0));
            p = m * p;
            
            vec4 pp = perspective(p.xyz, 60.0, 0.2, 4.0);
            
            gl_Position = gl_ModelViewProjectionMatrix * pp;
            gl_PointSize = snd*5.+.5;
            
            float hue = snd * vertexId/vertexCount;
            gl_FrontColor = vec4(hsv2rgb(vec3(hue, 1.0, 1.0)), 1.0);
        }
    );
    
    std::string frag = GLSL(120,
        void main(){
            gl_FragColor = gl_Color;
        }
    );
    shader.setupShaderFromSource(GL_VERTEX_SHADER, vert);
    shader.setupShaderFromSource(GL_FRAGMENT_SHADER, frag);
    shader.linkProgram();
    
    int _s = std::sqrt(num_vertices);
    for(int i = 0; i < _s ; i++){
        for(int j = 0; j < _s; j++){
                mesh.addVertex(ofVec3f(0));
                mesh.addIndex(j+i*_s);
        }
    }
    
    cam.setPosition(ofVec3f(0,0,2.f));
    cam.setNearClip(.0001f);
    cam.lookAt(ofVec3f(0));
    
    // codes modified from openframeworks soundPlayerFFTExample example
    //
    // the fft needs to be smoothed out, so we create an array of floats
    // for that purpose:
    beat.load("J Dilla - Life (Instrumental).mp3");
    beat.play();
    beat.setLoop(true);
    
    int fftHistorySize = num_vertices;
    int fftSmoothSize = (int)(std::sqrt(fftHistorySize));
    fftHistory = new float[fftHistorySize];
    fftSmooth = new float[fftSmoothSize];
    for (int i = 0; i < fftHistorySize; i++)
        fftHistory[i] = 0;
    for (int i = 0; i < fftSmoothSize; i++)
        fftSmooth[i] = 0;
}

void ofApp::update(){
    ofSoundUpdate();
    
    int _s = std::sqrt(num_vertices);
    for(int i = 1; i < _s ; i++){
        for(int j = 0; j < _s; j++){
            fftHistory[i*_s+j] = fftHistory[(i-1)*_s+j];
        }
    }
    
    float * val = ofSoundGetSpectrum(_s);
    for(int i = 0; i < _s; i++){
        // let the smoothed calue sink to zero:
        fftSmooth[i] *= 0.96f;
        // take the max, either the smoothed or the incoming:
        if (fftSmooth[i] < val[i]) fftSmooth[i] = val[i];
        
        fftHistory[i] = fftSmooth[i];
    }
}

void ofApp::draw(){
    ofClear(0);
    shader.begin();
    {
        float _verticesId[ num_vertices ];
        for (int i = 0; i < num_vertices; i++)
            _verticesId[i] = (float)i;
        GLint _vertexId = shader.getAttributeLocation("vertexId");
        glEnableVertexAttribArray(_vertexId);
        glVertexAttribPointer(_vertexId, 1, GL_FLOAT, 0, 0, _verticesId);
        
        GLint _soundTex = shader.getAttributeLocation("sound");
        glEnableVertexAttribArray(_soundTex);
        glVertexAttribPointer(_soundTex, 1, GL_FLOAT, 0, 0, fftHistory);
        
        shader.setUniform1f("vertexCount", (float)num_vertices);
        shader.setUniform1f("time", ofGetElapsedTimef());
        shader.setUniform2f("resolution", ofGetWidth(), ofGetHeight());
        
        ofPushMatrix();
        {
            cam.begin();
            mesh.draw(OF_MESH_POINTS);
            cam.end();
        }
        ofPopMatrix();
    }
    shader.end();
}

void ofApp::keyPressed(int key){}
void ofApp::keyReleased(int key){}
void ofApp::mouseMoved(int x, int y ){}
void ofApp::mouseDragged(int x, int y, int button){}
void ofApp::mousePressed(int x, int y, int button){}
void ofApp::mouseReleased(int x, int y, int button){}
void ofApp::mouseEntered(int x, int y){}
void ofApp::mouseExited(int x, int y){}
void ofApp::windowResized(int w, int h){}
void ofApp::dragEvent(ofDragInfo dragInfo){}
void ofApp::gotMessage(ofMessage msg){}

*p.s. I’m a self-taught programmer and my background is in 3d graphic design. I know 3d computer graphics pipeline quiet well but not in a way of computer graphics programming. So my code possibly not be the correct or efficient, please feel free to point out if there’s something wrong or inefficient, this is why I decided to start to participate in this community cause I would love to learn :slight_smile:

All the best,
av

Thank you!
You solved my biggest question!!
I would like to study various things from this source code again!!!

It is an additional question,
When you want to display this code with LINES instead of POINTS, where should I change and how should I change it?

Hey, you can try mesh.draw(OF_MESH_WIREFRAME) but it will most likely not be what you want.

I have no idea what kind of line you want to draw for this sketch but If you want to draw a line with wireframe rendering you need to deal with a specific order in drawing vertices and my code isn’t designed for that.

This documentation would be helpful.
http://openframeworks.cc/documentation/3d/ofMesh/

I understood WireFrame well! It is!

Another question is, is not it a uniform reaction of this square, is it possible to respond like a spectrum from the edge?
Any color is acceptable.

I’ll need to organize the fft history and vertices array to do that. Maybe i’ll get back with an example of it later but not sooner :sweat_smile: