|
@@ -6,13 +6,9 @@ class LightBuffer {
|
|
|
|
|
|
public var defaultForwardShader = new h3d.shader.pbr.DefaultForward();
|
|
|
|
|
|
- var MAX_DIR_LIGHT = 2;
|
|
|
- var MAX_SPOT_LIGHT = 10;
|
|
|
- var MAX_POINT_LIGHT = 25;
|
|
|
var MAX_DIR_SHADOW = 1;
|
|
|
var MAX_SPOT_SHADOW = 2;
|
|
|
var MAX_POINT_SHADOW = 2;
|
|
|
- var MAX_CASCADE_COUNT = 4;
|
|
|
|
|
|
var pointLightsShadow : Array<PointLight> = [];
|
|
|
var spotLightsShadow : Array<SpotLight> = [];
|
|
@@ -27,50 +23,41 @@ class LightBuffer {
|
|
|
final SPOT_LIGHT_INFO_SIZE = 8;
|
|
|
final DIR_LIGHT_INFO_SIZE = 5;
|
|
|
final CASCADE_SHADOW_INFO_SIZE = 13;
|
|
|
-
|
|
|
+ final BUFFER_MAX_SIZE = 4096;
|
|
|
|
|
|
public function new() {
|
|
|
createBuffers();
|
|
|
}
|
|
|
|
|
|
function createBuffers() {
|
|
|
- var stride = 4;
|
|
|
- var size = 0;
|
|
|
- size += MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE;
|
|
|
- size += MAX_POINT_LIGHT * POINT_LIGHT_INFO_SIZE;
|
|
|
- size += MAX_SPOT_LIGHT * SPOT_LIGHT_INFO_SIZE;
|
|
|
- size += CASCADE_SHADOW_INFO_SIZE;
|
|
|
- size = hxd.Math.imax(1, size); // Avoid empty buffer
|
|
|
- lightInfos = new hxd.FloatBuffer(size * stride);
|
|
|
- defaultForwardShader.lightInfos = new h3d.Buffer(size, hxd.BufferFormat.make([{ name : "uniformData", type : DVec4 }]), [UniformBuffer, Dynamic]);
|
|
|
- defaultForwardShader.BUFFER_SIZE = size;
|
|
|
- defaultForwardShader.dirLightStride = DIR_LIGHT_INFO_SIZE * MAX_DIR_LIGHT;
|
|
|
- defaultForwardShader.pointLightStride = POINT_LIGHT_INFO_SIZE * MAX_POINT_LIGHT;
|
|
|
- defaultForwardShader.spotLightStride = SPOT_LIGHT_INFO_SIZE * MAX_SPOT_LIGHT;
|
|
|
+ lightInfos = new hxd.FloatBuffer(BUFFER_MAX_SIZE << 2);
|
|
|
+ defaultForwardShader.lightInfos = new h3d.Buffer(BUFFER_MAX_SIZE, hxd.BufferFormat.make([{ name : "uniformData", type : DVec4 }]), [UniformBuffer, Dynamic]);
|
|
|
}
|
|
|
|
|
|
public function setBuffers( s : h3d.shader.pbr.DefaultForward ) {
|
|
|
s.lightInfos = defaultForwardShader.lightInfos;
|
|
|
- s.dirLightStride = defaultForwardShader.dirLightStride;
|
|
|
s.pointLightStride = defaultForwardShader.pointLightStride;
|
|
|
s.spotLightStride = defaultForwardShader.spotLightStride;
|
|
|
+ s.cascadeLightStride = defaultForwardShader.cascadeLightStride;
|
|
|
s.cameraPosition = defaultForwardShader.cameraPosition;
|
|
|
s.emissivePower = defaultForwardShader.emissivePower;
|
|
|
- s.BUFFER_SIZE = defaultForwardShader.BUFFER_SIZE;
|
|
|
|
|
|
s.pointLightCount = defaultForwardShader.pointLightCount;
|
|
|
s.spotLightCount = defaultForwardShader.spotLightCount;
|
|
|
s.dirLightCount = defaultForwardShader.dirLightCount;
|
|
|
- s.DIR_SHADOW_COUNT = defaultForwardShader.DIR_SHADOW_COUNT;
|
|
|
- s.POINT_SHADOW_COUNT = defaultForwardShader.POINT_SHADOW_COUNT;
|
|
|
- s.SPOT_SHADOW_COUNT = defaultForwardShader.SPOT_SHADOW_COUNT;
|
|
|
+ s.pointShadowCount = defaultForwardShader.pointShadowCount;
|
|
|
+ s.spotShadowCount = defaultForwardShader.spotShadowCount;
|
|
|
+ s.dirShadowCount = defaultForwardShader.dirShadowCount;
|
|
|
+ s.MAX_DIR_SHADOW_COUNT = defaultForwardShader.MAX_DIR_SHADOW_COUNT;
|
|
|
+ s.MAX_POINT_SHADOW_COUNT = defaultForwardShader.MAX_POINT_SHADOW_COUNT;
|
|
|
+ s.MAX_SPOT_SHADOW_COUNT = defaultForwardShader.MAX_SPOT_SHADOW_COUNT;
|
|
|
s.CASCADE_COUNT = defaultForwardShader.CASCADE_COUNT;
|
|
|
|
|
|
- for( i in 0 ... defaultForwardShader.POINT_SHADOW_COUNT )
|
|
|
+ for( i in 0 ... defaultForwardShader.MAX_POINT_SHADOW_COUNT )
|
|
|
s.pointShadowMaps[i] = defaultForwardShader.pointShadowMaps[i];
|
|
|
- for( i in 0 ... defaultForwardShader.SPOT_SHADOW_COUNT )
|
|
|
+ for( i in 0 ... defaultForwardShader.MAX_SPOT_SHADOW_COUNT )
|
|
|
s.spotShadowMaps[i] = defaultForwardShader.spotShadowMaps[i];
|
|
|
- for( i in 0 ... defaultForwardShader.DIR_SHADOW_COUNT )
|
|
|
+ for( i in 0 ... defaultForwardShader.MAX_DIR_SHADOW_COUNT )
|
|
|
s.dirShadowMaps[i] = defaultForwardShader.dirShadowMaps[i];
|
|
|
for ( i in 0... defaultForwardShader.CASCADE_COUNT )
|
|
|
s.cascadeShadowMaps[i] = defaultForwardShader.cascadeShadowMaps[i];
|
|
@@ -100,10 +87,16 @@ class LightBuffer {
|
|
|
b[i+3] = 1;
|
|
|
}
|
|
|
|
|
|
- function sortingCriteria ( l1 : Light, l2 : Light, cameraTarget : Vector ) {
|
|
|
+ function sortingCriteria ( l1 : Light, l2 : Light, cameraTarget : h3d.Vector ) {
|
|
|
+ var dirL1 = Std.isOfType(l1, DirLight);
|
|
|
+ var dirL2 = Std.isOfType(l2, DirLight);
|
|
|
+ if ( dirL1 && !dirL2 )
|
|
|
+ return -1;
|
|
|
+ if ( dirL2 && !dirL1 )
|
|
|
+ return 1;
|
|
|
var d1 = l1.getAbsPos().getPosition().sub(cameraTarget).length();
|
|
|
var d2 = l2.getAbsPos().getPosition().sub(cameraTarget).length();
|
|
|
- return d1 > d2 ? 1 : -1;
|
|
|
+ return d1 == d2 ? 0 : (d1 > d2 ? 1 : -1);
|
|
|
}
|
|
|
|
|
|
public function sortLights ( ctx : h3d.scene.RenderContext ) : Array<Light> @:privateAccess {
|
|
@@ -112,12 +105,12 @@ class LightBuffer {
|
|
|
if ( l == null )
|
|
|
return null;
|
|
|
while ( l != null ) {
|
|
|
- if (l.enableForward) {
|
|
|
+ if (l.enableForward && l.inFrustum(ctx.camera.frustum)) {
|
|
|
lights.push(l);
|
|
|
}
|
|
|
l = Std.downcast(l.next, Light);
|
|
|
}
|
|
|
- lights.sort(function(l1,l2) { return sortingCriteria(l1, l2, @:privateAccess ctx.camera.target); });
|
|
|
+ lights.sort(function(l1,l2) { return sortingCriteria(l1, l2, ctx.camera.target); });
|
|
|
return lights;
|
|
|
}
|
|
|
|
|
@@ -140,16 +133,22 @@ class LightBuffer {
|
|
|
var pointLightCount = 0;
|
|
|
var spotLightCount = 0;
|
|
|
|
|
|
+ var curSize = 0;
|
|
|
for (l in lights) {
|
|
|
var dl = Std.downcast(l, DirLight);
|
|
|
if (dl != null) {
|
|
|
- if (dirLightCount + dirShadowCount < MAX_DIR_LIGHT) {
|
|
|
+ if ( curSize + DIR_LIGHT_INFO_SIZE < BUFFER_MAX_SIZE ) {
|
|
|
+ curSize += DIR_LIGHT_INFO_SIZE;
|
|
|
var hasShadow = dl.shadows != null && dl.shadows.enabled && dl.shadows.mode != None && shadows;
|
|
|
if (hasShadow && dirShadowCount < MAX_DIR_SHADOW) {
|
|
|
var cascade = Std.downcast(dl.shadows, CascadeShadowMap);
|
|
|
- if ( cascade != null )
|
|
|
- cascadeLight = dl;
|
|
|
- else
|
|
|
+ if ( cascade != null ) {
|
|
|
+ curSize -= DIR_LIGHT_INFO_SIZE;
|
|
|
+ if ( curSize + CASCADE_SHADOW_INFO_SIZE < BUFFER_MAX_SIZE ) {
|
|
|
+ curSize += CASCADE_SHADOW_INFO_SIZE;
|
|
|
+ cascadeLight = dl;
|
|
|
+ }
|
|
|
+ } else
|
|
|
dirLightsShadow.push(dl);
|
|
|
dirShadowCount++;
|
|
|
} else {
|
|
@@ -161,7 +160,8 @@ class LightBuffer {
|
|
|
|
|
|
var pl = Std.downcast(l, PointLight);
|
|
|
if (pl != null) {
|
|
|
- if (pointLightCount + pointShadowCount < MAX_POINT_LIGHT) {
|
|
|
+ if ( curSize + POINT_LIGHT_INFO_SIZE < BUFFER_MAX_SIZE ) {
|
|
|
+ curSize += POINT_LIGHT_INFO_SIZE;
|
|
|
var hasShadow = pl.shadows != null && pl.shadows.enabled && pl.shadows.mode != None && shadows;
|
|
|
if (hasShadow && pointShadowCount < MAX_POINT_SHADOW) {
|
|
|
pointLightsShadow.push(pl);
|
|
@@ -176,7 +176,8 @@ class LightBuffer {
|
|
|
|
|
|
var sl = Std.downcast(l, SpotLight);
|
|
|
if (sl != null) {
|
|
|
- if (spotLightCount + spotShadowCount < MAX_SPOT_LIGHT) {
|
|
|
+ if ( curSize + SPOT_LIGHT_INFO_SIZE < BUFFER_MAX_SIZE ) {
|
|
|
+ curSize += SPOT_LIGHT_INFO_SIZE;
|
|
|
var hasShadow = sl.shadows != null && sl.shadows.enabled && sl.shadows.mode != None && shadows;
|
|
|
if (hasShadow && spotShadowCount < MAX_SPOT_SHADOW) {
|
|
|
spotLightsShadow.push(sl);
|
|
@@ -217,10 +218,11 @@ class LightBuffer {
|
|
|
fillLights(lights, pbrRenderer.shadows);
|
|
|
|
|
|
// Dir Light With Shadow
|
|
|
+ var stride = 0;
|
|
|
for (li in 0...dirLightsShadow.length) {
|
|
|
var dl = dirLightsShadow[li];
|
|
|
- var i = li * DIR_LIGHT_INFO_SIZE * 4;
|
|
|
var pbr = @:privateAccess dl.pbr;
|
|
|
+ var i = stride << 2;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = 1.0;
|
|
|
fillVector(lightInfos, pbr.lightDir, i+4);
|
|
@@ -230,23 +232,26 @@ class LightBuffer {
|
|
|
fillFloats(lightInfos, mat._11, mat._21, mat._31, mat._41, i+8);
|
|
|
fillFloats(lightInfos, mat._12, mat._22, mat._32, mat._42, i+12);
|
|
|
fillFloats(lightInfos, mat._13, mat._23, mat._33, mat._43, i+16);
|
|
|
+ stride += DIR_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
// Dir Light
|
|
|
for (li in 0...dirLights.length) {
|
|
|
var dl = dirLights[li];
|
|
|
- var i = (li + dirLightsShadow.length) * DIR_LIGHT_INFO_SIZE * 4;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess dl.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = -1.0;
|
|
|
fillVector(lightInfos, pbr.lightDir, i+4);
|
|
|
+ stride += DIR_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
+ s.pointLightStride = stride;
|
|
|
+
|
|
|
// Point Light With Shadows
|
|
|
for (li in 0...pointLightsShadow.length) {
|
|
|
var pl = pointLightsShadow[li];
|
|
|
- var offset = MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE * 4;
|
|
|
- var i = li * POINT_LIGHT_INFO_SIZE * 4 + offset;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess pl.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = pbr.pointSize;
|
|
@@ -256,13 +261,13 @@ class LightBuffer {
|
|
|
lightInfos[i+9] = 1.0;
|
|
|
lightInfos[i+10] = pl.shadows.bias;
|
|
|
s.pointShadowMaps[li] = pl.shadows.getShadowTex();
|
|
|
+ stride += POINT_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
// Point Light
|
|
|
for (li in 0...pointLights.length) {
|
|
|
var pl = pointLights[li];
|
|
|
- var offset = MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE * 4;
|
|
|
- var i = (li + pointLightsShadow.length) * POINT_LIGHT_INFO_SIZE * 4 + offset;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess pl.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = pbr.pointSize;
|
|
@@ -270,13 +275,15 @@ class LightBuffer {
|
|
|
lightInfos[i+7] = pbr.invLightRange4;
|
|
|
lightInfos[i+8] = pl.range;
|
|
|
lightInfos[i+9] = -1.0;
|
|
|
+ stride += POINT_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
+ s.spotLightStride = stride;
|
|
|
+
|
|
|
// Spot Light With Shadow
|
|
|
for (li in 0...spotLightsShadow.length) {
|
|
|
var sl = spotLightsShadow[li];
|
|
|
- var offset = (MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE + MAX_POINT_LIGHT * POINT_LIGHT_INFO_SIZE) * 4 ;
|
|
|
- var i = li * SPOT_LIGHT_INFO_SIZE * 4 + offset;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess sl.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = pbr.range;
|
|
@@ -293,13 +300,13 @@ class LightBuffer {
|
|
|
fillFloats(lightInfos, mat._13, mat._23, mat._33, mat._43, i+24);
|
|
|
fillFloats(lightInfos, mat._14, mat._24, mat._34, mat._44, i+28);
|
|
|
s.spotShadowMaps[li] = sl.shadows.getShadowTex();
|
|
|
+ stride += SPOT_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
// Spot Light
|
|
|
for (li in 0...spotLights.length) {
|
|
|
var sl = spotLights[li];
|
|
|
- var offset = (MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE + MAX_POINT_LIGHT * POINT_LIGHT_INFO_SIZE) * 4 ;
|
|
|
- var i = (li + spotLightsShadow.length) * SPOT_LIGHT_INFO_SIZE * 4 + offset;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess sl.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = pbr.range;
|
|
@@ -309,12 +316,14 @@ class LightBuffer {
|
|
|
lightInfos[i+12] = pbr.angle;
|
|
|
lightInfos[i+13] = pbr.fallOff;
|
|
|
lightInfos[i+14] = -1.0;
|
|
|
+ stride += SPOT_LIGHT_INFO_SIZE;
|
|
|
}
|
|
|
|
|
|
+ s.cascadeLightStride = stride;
|
|
|
+
|
|
|
// Cascade shadows
|
|
|
if ( cascadeLight != null ) {
|
|
|
- var offset = (MAX_DIR_LIGHT * DIR_LIGHT_INFO_SIZE + MAX_POINT_LIGHT * POINT_LIGHT_INFO_SIZE + MAX_SPOT_LIGHT * SPOT_LIGHT_INFO_SIZE) * 4 ;
|
|
|
- var i = offset;
|
|
|
+ var i = stride << 2;
|
|
|
var pbr = @:privateAccess cascadeLight.pbr;
|
|
|
fillVector(lightInfos, pbr.lightColor, i);
|
|
|
lightInfos[i+3] = 0.0;
|
|
@@ -337,9 +346,12 @@ class LightBuffer {
|
|
|
s.dirLightCount = dirLights.length;
|
|
|
s.pointLightCount = pointLights.length;
|
|
|
s.spotLightCount = spotLights.length;
|
|
|
- s.DIR_SHADOW_COUNT = MAX_DIR_SHADOW;
|
|
|
- s.POINT_SHADOW_COUNT = MAX_POINT_SHADOW;
|
|
|
- s.SPOT_SHADOW_COUNT = MAX_SPOT_SHADOW;
|
|
|
+ s.MAX_DIR_SHADOW_COUNT = MAX_DIR_SHADOW;
|
|
|
+ s.MAX_POINT_SHADOW_COUNT = MAX_POINT_SHADOW;
|
|
|
+ s.MAX_SPOT_SHADOW_COUNT = MAX_SPOT_SHADOW;
|
|
|
+ s.dirShadowCount = dirLightsShadow.length;
|
|
|
+ s.pointShadowCount = pointLightsShadow.length;
|
|
|
+ s.spotShadowCount = spotLightsShadow.length;
|
|
|
s.lightInfos.uploadFloats(lightInfos, 0, s.lightInfos.vertices, 0);
|
|
|
pointLights = [];
|
|
|
spotLights = [];
|