hey all,
i’m trying to port west langley’s three.js super area light example to OF (0.93), but to no avail.
http://jsfiddle.net/hh74z2ft/1/
i suspect the issue has to do with my surface’s normals or the test to see if the vertex is under the light, but i don’t completely understand the test that langley has written.
here’s what i have so far (using GLSL shader version 120). would be grateful if anybody could, ahem, shed some light on why it’s not working.
basic.vert
#version 120
varying vec3 vNormal; // in camera space
varying vec3 vViewPosition; // in camera space
void main() {
vec4 mViewPosition = (gl_ModelViewMatrix * gl_Vertex);
vViewPosition = -mViewPosition.xyz;
vNormal = normalize(gl_NormalMatrix * gl_Normal);
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
areaLight.frag
#version 120
#define NVERTS 4
uniform vec3 color;
uniform vec3 lightColor;
uniform float lightIntensity;
uniform vec3 lightverts[ NVERTS ]; // in local space
uniform mat4 viewMatrix;
uniform mat4 lightMatrixWorld;
varying vec3 vNormal; // in camera space
varying vec3 vViewPosition; // in camera space
void main() {
vec3 normal = normalize( vNormal );
vec4 lPosition[ NVERTS ];
vec3 lVector[ NVERTS ];
// stub in some ambient reflectance
vec3 ambient = color * vec3( 0.2 );
// direction vectors from point to area light corners
for( int i = 0; i < NVERTS; i ++ ) {
lPosition[ i ] = viewMatrix * lightMatrixWorld * vec4( lightverts[ i ], 1.0 ); // in camera space
lVector[ i ] = normalize( lPosition[ i ].xyz + vViewPosition.xyz ); // dir from vertex to areaLight
}
// bail if the point is on the wrong side of the light... there must be a better way...
float tmp = dot( lVector[ 0 ], cross( ( lPosition[ 2 ] - lPosition[ 0 ] ).xyz, ( lPosition[ 1 ] - lPosition[ 0 ] ).xyz ) );
/* uncomment to see if it passes the test
if( tmp > 0 ){
gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
} else{
gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
}
return;
*/
if ( tmp > 0.0 ) {
gl_FragColor = vec4( ambient, 1.0 );
return;
}
// vector irradiance at point
vec3 lightVec = vec3( 0.0 );
for( int i = 0; i < NVERTS; i ++ ) {
vec3 v0 = lVector[ i ];
vec3 v1 = lVector[ int( mod( float( i + 1 ), float( NVERTS ) ) ) ]; // ugh...
lightVec += acos( dot( v0, v1 ) ) * normalize( cross( v0, v1 ) );
}
// irradiance factor at point
float factor = max( dot( lightVec, normal ), 0.0 ) / ( 2.0 * 3.14159265 );
// frag color
vec3 diffuse = color * lightColor * lightIntensity * factor;
gl_FragColor = vec4( ambient + diffuse, 1.0 );
}
and the draw() call:
void ofApp::draw(){
ofDisableAlphaBlending();
ofEnableLighting();
ofEnableDepthTest();
ofBackground(0);
// mesh surface (to cast light on)
ofMesh surface;
surface.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
surface.addVertex(ofVec2f(-ofGetWidth()/2, -ofGetHeight()/2));
surface.addVertex(ofVec2f(ofGetWidth()/2, -ofGetHeight()/2));
surface.addVertex(ofVec2f(-ofGetWidth()/2, ofGetHeight()/2));
surface.addVertex(ofVec2f(ofGetWidth()/2, ofGetHeight()/2));
surface.addNormal((ofVec3f(0, 0, 1)));
surface.addNormal((ofVec3f(0, 0, 1)));
surface.addNormal((ofVec3f(0, 0, 1)));
surface.addNormal((ofVec3f(0, 0, 1)));
// light transformations
ofNode areaLightNode;
areaLightNode.setPosition(position);
areaLightNode.rotate(ofQuaternion(cos(ofGetElapsedTimef()*0.25)*180,ofVec3f(1, 0, 0)));
// light mesh
ofMesh lightMesh;
lightMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
lightMesh.addVertex(ofVec3f(-dimensions->x/2, -dimensions->y/2, 0));
lightMesh.addVertex(ofVec3f(dimensions->x/2, -dimensions->y/2, 0));
lightMesh.addVertex(ofVec3f(-dimensions->x/2, dimensions->y/2, 0));
lightMesh.addVertex(ofVec3f(dimensions->x/2, dimensions->y/2, 0));
vector<ofVec3f> & listPts = lightMesh.getVertices();
// draw the scene
ofCamera cam;
cam.setPosition(ofVec3f(0, 0, 800));
cam.lookAt( ofVec3f(0, 0, 0), ofVec3f(0, 1, 0));
cam.setNearClip(0.1);
cam.setFarClip(1000);
cam.setFov(60.0);
cam.begin();
// view matrix
ofMatrix4x4 viewMat = ofGetCurrentViewMatrix();
// light matrix
ofMatrix4x4 areaLightMat = areaLightNode.getGlobalTransformMatrix();
lightShader.begin();
lightShader.setUniform3f("color", matAmbientColor->r, matAmbientColor->g, matAmbientColor->b);
lightShader.setUniform3f("lightColor", lightColor->r, lightColor->g, lightColor->b);
lightShader.setUniform1f("lightIntensity", lightIntensity);
lightShader.setUniformMatrix4f("viewMatrix", viewMat);
lightShader.setUniformMatrix4f("lightMatrixWorld", areaLightMat);
// note: points should be in clockwise order
lightShader.setUniform3f("lightverts[0]", listPts[0].x, listPts[0].y, listPts[0].z);
lightShader.setUniform3f("lightverts[1]", listPts[1].x, listPts[1].y, listPts[1].z);
lightShader.setUniform3f("lightverts[2]", listPts[3].x, listPts[3].y, listPts[3].z);
lightShader.setUniform3f("lightverts[3]", listPts[2].x, listPts[2].y, listPts[2].z);
surface.draw();
lightShader.end();
ofDisableLighting();
// light debug-vew
ofPushMatrix();
ofMultMatrix(areaLightMat);
ofSetColor(ofColor::white);
lightMesh.drawWireframe();
ofPopMatrix();
cam.end();
ofDisableDepthTest();
gui.draw();
}