Shader does not work with openframeworks


#1

I’d like to port the following fragment shader program, but it does not work.
I do not know where is wrong, so someone please help me.

ofApp.cpp

#include "ofApp.h"
ofShader shader;

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0);
    shader.load("","dot.frag");
}

//--------------------------------------------------------------
void ofApp::update(){   
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofClear(0);        
    shader.begin();
    shader.setUniform2f("iResolution", ofGetWidth(), ofGetHeight());
    shader.setUniform1f("iGlobalTime", ofGetElapsedTimef());
    ofRect(0, 0, ofGetWidth(), ofGetHeight());
    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::gotMessage(ofMessage msg){}
void ofApp::dragEvent(ofDragInfo dragInfo){}

dot.frag
#version 120

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 iResolution;
uniform float iGlobalTime;

vec3 cam_origin;
mat3 cam_rotation;
vec2 frag_coord;
float time=0.0;

vec3 rotateX(float a, vec3 v){
    return vec3(v.x, cos(a) * v.y + sin(a) * v.z, cos(a) * v.z - sin(a) * v.y);
}

vec3 rotateY(float a, vec3 v){
    return vec3(cos(a) * v.x + sin(a) * v.z, v.y, cos(a) * v.z - sin(a) * v.x);
}

float orbIntensity(vec3 p){
    if(length(p) < 4.0)
        return 1.0;
    return smoothstep(0.25, 1.0, cos(p.x * 10.0) * sin(p.y * 5.0) * cos(p.z * 7.0)) * 0.2 *
				step(length(p), 17.0);
}

vec3 project(vec3 p){
    mat3 cam_rotation_t = mat3(vec3(cam_rotation[0].x, cam_rotation[1].x, cam_rotation[2].x),
                               vec3(cam_rotation[0].y, cam_rotation[1].y, cam_rotation[2].y),
                               vec3(cam_rotation[0].z, cam_rotation[1].z, cam_rotation[2].z));
    p = cam_rotation_t * (p - cam_origin);
    return vec3(p.xy / p.z, p.z);
}

float orb(float rad, vec3 coord){
    return 1.0 - smoothstep(0.5, 0.55, distance(coord.xy, frag_coord) / rad);
}

float orbShadow(float rad, vec3 coord){
    return 1.0 - smoothstep(0.4, 1.1, distance(coord.xy, frag_coord) / rad) *
    mix(1.0,0.99,orb(rad,coord));
}

vec3 traverseUniformGrid(vec3 ro, vec3 rd){
    vec3 increment = vec3(1.0) / rd;
    vec3 intersection = ((floor(ro) + floor(rd * 0.5 + vec3(0.5))) - ro) * increment;
    
    increment = abs(increment);
    ro += rd * 1e-3;
    
    vec4 accum = vec4(0.0,0.0,0.0,1.0);
    
    for(int i = 0; i < 40; i += 1){
        vec3 rp = floor(ro + rd * min(intersection.x, min(intersection.y, intersection.z)));
        
        float orb_intensity = orbIntensity(rp);
        
        if(orb_intensity > 1e-3){
            vec3 coord = project(rp + vec3(0.5));
            
            if(coord.z > 1.0){
                float rad = 0.55 / coord.z;// * (1.0 - smoothstep(0.0, 50.0, length(rp)));
                rad *= 1.0 + 0.5 * sin(rp.x + time * 1.0) * cos(rp.y + time * 2.0) * cos(rp.z);
                float dist = distance(rp + vec3(0.5), ro);
                float c = smoothstep(1.0, 2.5, dist);
                float a = orb(rad, coord) * c;
                float b = orbShadow(rad, coord) * c;
                
                accum.rgb += accum.a * a * 1.5 *
                mix(vec3(1.0), vec3(0.4, 1.0, 0.5) * 0.5, 0.5 + 0.5 * cos(rp.x)) * exp(-dist * dist * 0.008);
                
                accum.a *= 1.0 - b;
            }
        }
        
        intersection += increment * step(intersection.xyz, intersection.yxy)
        * step(intersection.xyz,intersection.zzx);
    }
    
    accum.rgb += accum.a * vec3(0.02);
    
    return accum.rgb;
}

void main(void){
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    frag_coord = uv * 2.0 - vec2(1.0);
    frag_coord.x *= iResolution.x / iResolution.y;
    
    float time0=iGlobalTime,time1=time0+0.04;
    
    gl_FragColor.rgb = vec3(0.0);
    
    for(int n=0;n<4;n+=1){
        time=mix(time0,time1,(float(n))/4.0)*0.7;
        
        cam_origin = rotateX(time * 0.3,rotateY(time * 0.5, vec3(0.0, 0.0, -10.0)));
        
        vec3 cam_w = normalize(vec3(cos(time) * 10.0, 0.0, 0.0) - cam_origin);
        vec3 cam_u = normalize(cross(cam_w, vec3(0.0, 1.0, 0.0)));
        vec3 cam_v = normalize(cross(cam_u, cam_w));
        
        cam_rotation = mat3(cam_u, cam_v, cam_w);
        
        vec3 ro = cam_origin,rd = cam_rotation * vec3(frag_coord, 1.0);
        
        gl_FragColor.rgb += traverseUniformGrid(ro, rd);
    }
    
    gl_FragColor.rgb *= 0.5 + 0.5*pow( 16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y), 0.1 );
    
    gl_FragColor.rgb = sqrt(gl_FragColor.rgb / 4.0 * 0.8);
}

If you run this dot.frag program with Visual Studio Code, it looks like the following.

What is wrong with making this shader work on Openframeworks?


#2

Probably the OpenGL version that you are using in OF does not support this GLSL version that you are loading in visual studio.

OpenGL has different versions, and each version comes with a sligthly different GLSL syntax. The shaders that are you loading in visual studio is for version 120, meaning OpenGL 2.1.

With OF 0.9 comes the programmable pipeline, you can select which OpenGL version you want to use in the main.cpp file

// main.cpp (openFrameworks 0.9)
int main(){
    ofGLWindowSettings settings;
    settings.setGLVersion(4,5); /// < select your GL Version here
    ofCreateWindow(settings); ///< create your window here
    ofRunApp(new ofApp());
}

More infos about OF 0.9 and the programmable pipeline here http://blog.openframeworks.cc/post/133400454159/openframeworks-090-opengl-45