Exponential Shadow Mapping

Hey guys, I put together an example for using ESM shadow maps in OF.

It’s basically an add-on as its own class, but left out the ofx prefix. It should be compatible with current OF rendering, but let me know if you run into any problems. Hope it’s of use to someone - I added comments to help make it a bit more legible.

Screenshot: http://www.flickr.com/photos/85184046@N07/8283730333/
Source: https://github.com/jacres/of-ESMShadowMapping

cheers!
James

@jimmyacres

hey - this looks really nice!
we’re actually trying to gather a collection of nice shader based examples for the next OF release.

would be great to get you’re input on this.
we have a GH issue - for gathering shader examples here:
https://github.com/openframeworks/openFrameworks/issues/1396

Hey Theo,

Thanks! Getting some more shader examples in there is a great idea. I’ll get involved with the discussion on github and see where I can contribute.

hey @james looks very nice! works great for me with my Nvidia gt 540 on my laptop but with my intel integrated graphic card instead i have weird result (due to the fact i think a minor openGL version supported). Should be fine have a ofShadow class with different type of shadow as in OpenSceneGraph with shadow mapping, stencil shadow, volume shadow…

Great idea about the multiple shadow types - would be a bit of work, but could definitely be useful!

Curious - what type of results are you getting with the intel integrated card? I only have Nvidia cards (desktop & laptop), but I’ve heard of some weird things on ATI with some of the things I’ve been working on - wondering if it’s something I’m doing or just driver/compatibility issues.

Curious - what type of results are you getting with the intel integrated card?

i will post a screenshot when i have a bit of time @james, i think that for the intel is due to a minor OpenGL version (and it’s not possible to upgrade to major driver…) for the ATI honestly i don’t know . Sometimes i red of some discrepances about Nvidia and ATI glcalls. ( but more in the GLSL code…)

I’ve heard that the Intel Integrated graphics cards don’t do for() loops very well so its compiler unrolls the loops and that can lead to a lot of weirdness especially if you’re doing texture lookups in there. I’m guessing that whichever fragment shader you’re doing the blurring in has some of that in it?

Hey

This is really cool and in the most part it runs fine on C::B windows OF 0073. I had to add

  
  
#undef near   
#undef far   
  

in shadowMapLight.cpp to get it to compile. I do get a few glitches at certain angles of the light. The attached image shows them.

Thanks for sharing

Thanks Joshua - thanks for letting me know. I’ll read up on the unrolling of loops

I think I may have found the problem… I haven’t tried it out yet, but I was having problems with something else I was working (on ATI cards and intel integrated) and it was a stupid mistake on my part (as usual :))

I had been doing things like this:

vec4 ambient = material1.ambient;
vec4 diffuse;
vec4 specular;

if ( lambert > 0.0 ) {
ambient += gl_LightSource[0].ambient;
diffuse += gl_LightSource[0].diffuse * material1.diffuse * lambert;
specular += material1.specular * pow(max(dot(R, V), 0.0), material1.shininess);
}

I hadn’t been assigning values to diffuse/specular before adding to them - they don’t default to vec4(0, 0, 0, 0)

The following small change fixed another project for ATI/intel cards… guess the nvidia driver is a bit more lax…

vec4 ambient = material1.ambient;
vec4 diffuse = vec4(0, 0, 0, 1);
vec4 specular = vec4(0, 0, 0, 1);

if ( lambert > 0.0 ) {
ambient += gl_LightSource[0].ambient;
diffuse += gl_LightSource[0].diffuse * material1.diffuse * lambert;
specular += material1.specular * pow(max(dot(R, V), 0.0), material1.shininess);
}

Hey Brendan - thanks for letting me know about cb/win… weird that you’re getting that artifacting.

Would you mind trying the change from the above reply to Joshua (in mainScene.frag)?

Hey James

The update for the frag worked a treat - no glitches at all now

Awesome! I’ll update the repo. Thanks for trying that out

how can I draw scene with ESM to texture, using ofFbo?
I need it for grab scene and send it via syphon

I try use the code below, but texture looks like a glitch (image in attached file)

method setup():

  
  
//....  
fbo.allocate(ofGetWidth(), ofGetHeight());  
//....  
  

  
  
void testApp::draw() {  
    fbo.begin();  
    ofBackground(0,0,0);  
      
    glEnable( GL_DEPTH_TEST );  
      
    ofDisableAlphaBlending();  
      
    if (!m_bPaused) {  
        m_angle += 0.25f;  
    }  
      
    m_shadowLight.lookAt( ofVec3f(0.0,0.0,0.0) );  
    m_shadowLight.orbit( m_angle, -30.0, 50.0f, ofVec3f(0.0,0.0,0.0) );  
  
    m_shadowLight.enable();  
     
    // render linear depth buffer from light view  
    m_shadowLight.beginShadowMap();  
      
    drawObjects();  
      
    m_shadowLight.endShadowMap();  
      
    // render final scene  
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
    
    m_shader.begin();  
  
    m_shadowLight.bindShadowMapTexture(0); // bind shadow map texture to unit 0  
    m_shader.setUniform1i("u_ShadowMap", 0); // set uniform to unit 0  
    m_shader.setUniform1f("u_LinearDepthConstant", m_shadowLight.getLinearDepthScalar()); // set near/far linear scalar  
    m_shader.setUniformMatrix4f("u_ShadowTransMatrix", m_shadowLight.getShadowMatrix(m_cam)); // specify our shadow matrix  
      
    m_cam.begin();  
      
    m_shadowLight.enable();  
        drawObjects();  
    m_shadowLight.disable();  
      
    if ( m_bDrawLight ) {  
        glDisable(GL_CULL_FACE);  
        m_shadowLight.draw();  
        glEnable(GL_CULL_FACE);  
    }  
      
    m_cam.end();  
      
    m_shadowLight.unbindShadowMapTexture();  
  
    m_shader.end();  
      
  
    // Debug shadowmap  
    if ( m_bDrawDepth ) {  
        m_shadowLight.debugShadowMap();  
    }  
	fbo.end();  
	  
    //send fbo texture via syphon  
    mainOutputSyphonServer.publishTexture(&fbo.getTextureReference());  
      
    // draw info string  
    ofDisableLighting();  
    glDisable(GL_CULL_FACE);  
    glDisable(GL_DEPTH_TEST);  
    ofSetColor(255, 0, 0, 255);  
    ofDrawBitmapString("Press SPACE to toggle rendering the shadow map texture (linear depth map)\nPress L to toggle drawing the light\nPress P to toggle pause", ofPoint(15, 20));  
}  
  

I’ve been playing around with this – it’s pretty great and runs well on Windows in oF 0.8. I’ve worked a lot with 2D in Processing and programmed a lot in ruby, python, and several other languages, but I’m new to oF, GLSL, and programming in 3D.

Tweaking the code is helping me learn, though. Here’s an initial question that I have…

Is it possible to use this code with a scene that is in color? If so, what do I need to tweak to allow that? I’ve been playing around trying to figure it out, but haven’t yet determined what’s going on. I suspect that the shader is only processing information for greyscale, but I don’t see where that is happening.

Thanks!

Sorry for necroposting, but does anyone can help me to render color objects with this addon?
What should I change in the code to achieve it?

Thanks,

Yiannis

1 Like

Never mind, I found how to do it.
For anyone that might be interested, you have to edit at the mainScene.frag, at the material structure, the second property (diffuse) to accept a variable that will be the colour of the object.

from:

material material1 = material(
    vec4(0.075, 0.075, 0.075, 1.0),
    vec4(1.0, 1.0, 1.0, 1.0),
    vec4(1.0, 1.0, 1.0, 1.0),
    250.0
);

to

material material1 = material(
    vec4(0.075, 0.075, 0.075, 1.0),
    u_Colour,
    vec4(1.0, 1.0, 1.0, 1.0),
    250.0
);

and define the u_Colour at the top. Then from your app’s code use this to set the color.

m_shader.setUniform4f("u_Colour", it->color ); // set Colour

Yiannis