فهرست منبع

add faster area light clamping.

Ben Houston 9 سال پیش
والد
کامیت
f96f6e4eb8
2فایلهای تغییر یافته به همراه74 افزوده شده و 94 حذف شده
  1. 74 70
      src/renderers/shaders/ShaderChunk/lights.glsl
  2. 0 24
      src/renderers/shaders/ShaderChunk/math.glsl

+ 74 - 70
src/renderers/shaders/ShaderChunk/lights.glsl

@@ -31,6 +31,7 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 
 #endif
 
+
 #if MAX_POINT_LIGHTS > 0
 
 	struct PointLight {
@@ -56,6 +57,7 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 
 #endif
 
+
 #if MAX_SPOT_LIGHTS > 0
 
 	struct SpotLight {
@@ -87,76 +89,6 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 
 #endif
 
-#define MAX_AREA_LIGHTS 0 
-
-#if MAX_AREA_LIGHTS > 0
-
-	struct HemisphereLight {
-	  vec3 position;
-	  vec3 width;
-	  vec3 height;
-	  vec3 color;
-	  //sampler2D image;
-	  float distance;
-	  float decay;
-	};
-
-	uniform AreaLight areaLights[ MAX_AREA_LIGHTS ];
-
-	void getAreaIncidentLight( const in AreaLight areaLight, const in GeometricContext geometry, out IncidentLight diffuseIncidentLight, out IncidentLight specularIncidentLight ) {
-	
-		float widthLength = length( areaLight.width );
-		float heightLength = length( areaLight.height );
-
-		vec3 widthDir = areaLight.width / widthLength;
-		vec3 heightDir = areaLight.height / heightLength;
-		vec3 areaLightDirection = normalize( cross( widthDir, heightDir ) );
-
-		// project onto plane and calculate direction from center to the projection.
-		vec3 planePosition = projectOnPlane( viewDir, areaLight.position, areaLightDirection ),  // projection in plane
-		vec3 planeOffset = planePosition - areaLight.position;
-
-		// calculate distance from area:
-		vec2 planeOffsetUV = vec2( dot( planeOffset, widthDir ), dot( planeOffset, heightDir ) );
-		vec2 clampedPlaneOffsetUV = vec2( clamp( planeOffsetUV.x, -widthLength, widthLength ), clamp( planeOffsetUV.y, -heightLength, heightLength ) );
-		vec3 clampedPlanePosition = areaLight.position + ( widthDir * clampedPlaneOffsetUV.x + heightDir * clampedPlaneOffsetUV.y );
-
-		vec3 positionToLight = ( clampedPlanePosition - geometry.position );
-		float lightDistance = length( positionToLight );
-
-		diffuseIncidentLight.color = areaLight.color[ i ] * calcLightAttenuation( lightDistance, areaLight.distance, areaLight.decay ) * 0.01;
-		diffuseIncidentLight.direction = positionToLight / lightDistance;
-
-
-		vec3 reflectDir = reflect( geometry.viewDir, geometry.normal );
-		planePosition = linePlaneIntersect( geometry.position, reflectDir, areaLight.osition[ i ], areaLightNormal[ i ] );
-		float specAngle = dot( reflectDir, direction );
-		
-		if( dot( geometry.position - areaLight.position, areaLightDirection ) >= 0.0 && specAngle > 0.0 ) {
-
-			planeOffset = planePosition - areaLight.position;
-			planeOffsetUV = vec2( dot( planeOffset, widthDir ), dot( planeOffset, heightDir ) );
-			clampedPlaneOffsetUV = vec2( clamp( planeOffsetUV.x, -widthLength, widthLength ), clamp( planeOffsetUV.y, -heightLength, heightLength ) );
-			clampedPlanePosition = areaLight.position + ( widthDir * clampedPlaneOffsetUV.x + heightDir * clampedPlaneOffsetUV.y );
-
-			positionToLight = ( clampedPlanePosition - geometry.position );
-			lightDistance = length( positionToLight );
-
-			specularIncidentLight.color = areaLight.color[ i ] * calcLightAttenuation( lightDistance, areaLight.distance, areaLight.decay ) * 0.01;
-			specularIncidentLight.direction = positionToLight / lightDistance;
-
-		}
-		else {
-
-			specularIncidentLight.color = vec3( 0.0 );
-			specularIncidentLight.direction = vec3( 1.0, 0.0, 0.0 );
-
-		}
-
-	}
-
-#endif
-
 
 #if MAX_HEMI_LIGHTS > 0
 
@@ -205,3 +137,75 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 	}
 
 #endif
+
+
+#define MAX_AREA_LIGHTS 0 
+
+#if MAX_AREA_LIGHTS > 0
+
+	struct HemisphereLight {
+	  vec3 position;	// NOTE: top left of area light, not the center
+	  vec3 width;
+	  vec3 height;
+	  vec3 color;
+	  //sampler2D image;
+	  float distance;
+	  float decay;
+	};
+
+	uniform AreaLight areaLights[ MAX_AREA_LIGHTS ];
+
+	vec3 clampToAreaLight( const in mat3 worldToPlaneMat, const in vec3 lightPositionPlaneCoord, const in vec3 point ) {
+
+		// convert into "plane space" from world space
+		var pointPlaneCoord = worldToPlaneMat * point;
+
+		// clamp point plane coords to positive unit in plane space.
+		pointPlaneCoord.xy = clamp( positionPlaneCoord.xy - lightPositionPlaneCoord.xy, 0.0, 1.0 ) + lightPositionPlaneCoord.xy;
+		pointPlaneCoord.z = lightPositionPlaneOffset; // project onto plane in plane coordinate space
+
+		// convert out of "plane space" into world space
+		return positionPlaneCoord * worldToPlaneMat;
+
+	}
+
+	void getAreaIncidentLight( const in AreaLight areaLight, const in GeometricContext geometry, out IncidentLight diffuseIncidentLight, out IncidentLight specularIncidentLight ) {
+	
+		vec3 areaLightDirection = normalize( cross( widthDir, heightDir ) );
+		// NOTE: width and height are purposely not normalized, this is necessary because plane space is scaled based on width/height size.
+		mat3 worldToPlaneMat = mat3( areaLight.width, areaLight.height, areaLightDirection );
+		vec3 lightPositionPlaneCoord = worldToPlaneMat * areaLight.position;
+
+		vec3 clampedPlanePosition = clampToAreaLight( worldToPlaneMat, lightPositionPlaneCoord, geometry.position );
+
+		vec3 positionToLight = ( clampedPlanePosition - geometry.position );
+		float lightDistance = length( positionToLight );
+
+		diffuseIncidentLight.color = areaLight.color[ i ] * calcLightAttenuation( lightDistance, areaLight.distance, areaLight.decay ) * 0.01;
+		diffuseIncidentLight.direction = positionToLight / lightDistance;
+
+		vec3 reflectDir = reflect( geometry.viewDir, geometry.normal );
+		float specAngle = dot( reflectDir, direction );
+		
+		if( dot( geometry.position - areaLight.position, areaLightDirection ) >= 0.0 && specAngle > 0.0 ) {
+
+			lightPositionPlaneCoord = linePlaneIntersect( geometry.position, reflectDir, areaLight.position, areaLight.normal );
+			clampedPlanePosition = clampToAreaLight( worldToPlaneMat, lightPositionPlaneCoord, lightPositionPlaneCoord );
+
+			positionToLight = ( clampedPlanePosition - geometry.position );
+			lightDistance = length( positionToLight );
+
+			specularIncidentLight.color = areaLight.color[ i ] * calcLightAttenuation( lightDistance, areaLight.distance, areaLight.decay );
+			specularIncidentLight.direction = positionToLight / lightDistance;
+
+		}
+		else {
+
+			specularIncidentLight.color = vec3( 0.0 );
+			specularIncidentLight.direction = vec3( 1.0, 0.0, 0.0 );
+
+		}
+
+	}
+
+#endif

+ 0 - 24
src/renderers/shaders/ShaderChunk/math.glsl

@@ -11,30 +11,6 @@ vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {
 
 }
 
-/*
-struct Plane {
-	vec3	normal;
-	float	constant;	
-}
-
-vec3 Plane_distanceToPoint( const in Plane plane, in vec3 point ) {
-
-	return dot( plane.normal, point );
-
-}
-
-vec3 Plane_orthoPoint( const in Plane plane, in vec3 point ) {
-
-	return plane.normal * Plane_distanceToPoint( plane, point );
-
-}
-
-vec3 Plane_projectPoint( const in Plane plane, in vec3 point ) {
-
-	return point - Plane_orthoPoint( plane, point );
-
-}*/
-
 vec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {
 
 	float distance = dot( planeNormal, point - pointOnPlane );