3d model in custom shader

Hey guys,

I’m having trouble in apply a custom shader to a 3d model. I’m using a simple shader that should paint the model with red to illustrate the problem.

test.h

>  class EnvironmentMapping : public Scene {


>   public:
EnvironmentMapping();
void setup();
void update();
void draw();
void reloadShader();
string title;
ofMatrix3x3 mat4ToMat3(ofMatrix4x4 mat4);
ofShader shader;
//this is our model we'll draw
ofxAssimpModelLoader model;
ofEasyCam cam;
ofImage texture[3];
ofParameter<ofVec3f> lightPos;
ofParameter<ofVec3f> baseColor;
ofParameter<float> mixRatio;
ofxPanel gui;
 };

test.cpp

EnvironmentMapping::EnvironmentMapping(){

title = "EnvironmentMapping";
ofDisableArbTex();

shader.load("shaders/"+title);
texture[0].load("textures/equirectangular_texture.jpg");




//now we load our model
model.loadModel("models/suzanne.obj");
model.enableNormals();

//model.setPosition(ofGetWidth()*.5, ofGetHeight() * 0.75, 0);

cam.setDistance(250);


gui.setup("multipleTexture","gui/"+title+".xml");
gui.add(lightPos.set("lightPosition", ofVec3f(0,0,0), ofVec3f(-800,-800,-800), ofVec3f(800,800,800)));
gui.add(baseColor.set("baseColor", ofVec3f(10,90,0), ofVec3f(0,0,0), ofVec3f(255,255,255)));
gui.add(mixRatio.set("mixRatio", 0.5,0.0,1.0));

    gui.loadFromFile("gui/"+title+".xml");

    
}

> //--------------------------------------------------------------
> void EnvironmentMapping::draw(){
>     ofBackgroundGradient(ofColor(50), ofColor(255));
ofEnableDepthTest();

cam.begin();
//texture[0].getTexture().bind();
shader.begin();


shader.setUniform3f("LightPosition",lightPos->x,lightPos->y,lightPos->z);

//cout<<ofGetCurrentNormalMatrix()<<endl;
model.draw(OF_MESH_FILL);
shader.end();
//texture[0].getTexture().unbind();
cam.end();

ofDisableDepthTest();
gui.draw();

}

shade.vert

version 150

// these are for the programmable pipeline system and are passed in
// by default from OpenFrameworks
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix;
uniform mat4 modelViewProjectionMatrix;

in vec4 position;
in vec4 color;
in vec4 normal;
in vec2 texcoord;
// this is the end of the default functionality

void main(){
    
    gl_Position=projectionMatrix * modelViewMatrix * position;
}


  
    **shader.frag**
    
    
 version 150
                
 out vec4 outputColor;
                
   void main(){                        
        outputColor=vec4(1.0,0.0,0.0,1.0);
   }

With this shader I would expect the model painted in red, but I got the following output:

Well, one year later but maybe it is useful to someone. It uses a fixed light.

In the ofApp.cpp file

shader.begin();
shader.setUniform4f("uMaterialColor", ofColor(materialColor));
yourObject.draw();
shader.end();

vertex shader

#version 150
out vec3 vecNormal;

in vec4 position;
in vec4 color;
in vec4 normal;

// these are passed in from OF programmable renderer
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix;
uniform mat4 normalMatrix;

void main(){
    vecNormal = normal.xzy;
    gl_Position = modelViewProjectionMatrix * position;
}

fragment shader

#version 150
in vec3 vecNormal;

out vec4 fragColor;

// these are passed in from OF programmable renderer
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix;
uniform mat4 normalMatrix;
// this is set in the OF app
uniform vec4 uMaterialColor;

void main(){
    vec3 light = vec3(0.5, 0.2, 1.0);
    light = normalize(light);

    // dot product
    float dProd = max(0.0, dot(vecNormal, light));

    //color
    vec4 color = uMaterialColor;
    vec4 col = vec4( vec3( dProd ) * vec3( color ), 1.0 );
    fragColor = col;
}
1 Like

To use a custom position for the light:

//setup method
gui.add(lightPos.set("lightPosition",
                         ofVec3f(400,300,200), ofVec3f(-800,-800,-800), ofVec3f(800,800,800)));

//draw method
shader.setUniform3f("uLightPosition", lightPos);

vertex shader

#version 150
out vec3 vecNormal;
out vec4 vecPosition;

in vec4 position;
in vec4 normal;

// these are passed in from OF programmable renderer
uniform mat4 modelViewProjectionMatrix;

void main(){
    // Since the light is in world coordinates, i need the vertex position in world
    // coordinates too.
    vecPosition = modelViewProjectionMatrix * position;

    vecNormal = normal.xzy;
    gl_Position = vecPosition;
}

fragment shader

#version 150
in vec3 vecNormal;
in vec4 vecPosition;
out vec4 fragColor;

// this are set in the OF app
uniform vec3 uLightPosition;
uniform vec4 uMaterialColor;

void main(){
    vec3 lightDirection = normalize(vecPosition.xyz - uLightPosition);
    float dProd = max(0.0, dot(vecNormal, lightDirection));

    //color
    vec4 color = uMaterialColor;
    vec4 col = vec4( vec3( dProd ) * vec3( color ), 1.0 );
    fragColor = col;
}

This example is not using ofLight. I think the best way to incorporate ofLight in a custom shader is simply copy the updateLights method from ofMaterial, https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/gl/ofMaterial.cpp and update the vertex and fragment shader code as in the file linked.