From 441d463d93f1616806de32725cbca91595f05fed Mon Sep 17 00:00:00 2001 From: Yaski Date: Thu, 3 May 2012 20:55:13 +0600 Subject: [PATCH] Good culling of objects for CubeMap --- src/alternativa/engine3d/core/Light3D.as | 3 +- src/alternativa/engine3d/lights/OmniLight.as | 9 - src/alternativa/engine3d/loaders/ParserA3D.as | 10 +- .../engine3d/shadows/OmniLightShadow.as | 247 +++++++----------- 4 files changed, 101 insertions(+), 168 deletions(-) diff --git a/src/alternativa/engine3d/core/Light3D.as b/src/alternativa/engine3d/core/Light3D.as index d7864fa..31fae99 100644 --- a/src/alternativa/engine3d/core/Light3D.as +++ b/src/alternativa/engine3d/core/Light3D.as @@ -121,8 +121,9 @@ package alternativa.engine3d.core { * @private */ public function set shadow(value:Shadow):void { + if (_shadow != null) _shadow._light = null; _shadow = value; - _shadow._light = this; + if (value != null) value._light = this; } } } diff --git a/src/alternativa/engine3d/lights/OmniLight.as b/src/alternativa/engine3d/lights/OmniLight.as index abb1e2c..ee23aec 100644 --- a/src/alternativa/engine3d/lights/OmniLight.as +++ b/src/alternativa/engine3d/lights/OmniLight.as @@ -13,8 +13,6 @@ package alternativa.engine3d.lights { import alternativa.engine3d.core.Light3D; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.Transform3D; - import alternativa.engine3d.shadows.OmniLightShadow; - import alternativa.engine3d.shadows.Shadow; use namespace alternativa3d; @@ -202,12 +200,5 @@ package alternativa.engine3d.lights { return res; } - /** - * @private - */ - override public function set shadow(value:Shadow):void { - _shadow = value; - if (_shadow!=null) _shadow._light = this; - } } } diff --git a/src/alternativa/engine3d/loaders/ParserA3D.as b/src/alternativa/engine3d/loaders/ParserA3D.as index 873bca4..15a6e8c 100644 --- a/src/alternativa/engine3d/loaders/ParserA3D.as +++ b/src/alternativa/engine3d/loaders/ParserA3D.as @@ -58,7 +58,7 @@ public class ParserA3D extends Parser { * @param input ByteArray consists of A3D data. */ public function parse(input:ByteArray):void { -// try { + try { input.position = 0; var version:int = input.readByte(); if (version == 0) { @@ -69,10 +69,10 @@ public class ParserA3D extends Parser { // Bit of packing. It always equal to 1, because version 2 and above is always packed. parseVersionOver1(input); } -// } catch (e:Error) { -// e.message = "Parsing failed: " + e.message; -// throw e; -// } + } catch (e:Error) { + e.message = "Parsing failed: " + e.message; + throw e; + } } diff --git a/src/alternativa/engine3d/shadows/OmniLightShadow.as b/src/alternativa/engine3d/shadows/OmniLightShadow.as index 4c471f0..de82472 100644 --- a/src/alternativa/engine3d/shadows/OmniLightShadow.as +++ b/src/alternativa/engine3d/shadows/OmniLightShadow.as @@ -8,17 +8,15 @@ package alternativa.engine3d.shadows { import alternativa.engine3d.alternativa3d; -import alternativa.engine3d.core.BoundBox; -import alternativa.engine3d.core.Camera3D; -import alternativa.engine3d.core.CullingPlane; -import alternativa.engine3d.core.DrawUnit; + import alternativa.engine3d.core.BoundBox; + import alternativa.engine3d.core.Camera3D; + import alternativa.engine3d.core.DrawUnit; import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.Renderer; import alternativa.engine3d.core.Transform3D; import alternativa.engine3d.core.VertexAttributes; -import alternativa.engine3d.lights.OmniLight; -import alternativa.engine3d.lights.OmniLight; -import alternativa.engine3d.materials.Material; + import alternativa.engine3d.lights.OmniLight; + import alternativa.engine3d.materials.Material; import alternativa.engine3d.materials.ShaderProgram; import alternativa.engine3d.materials.TextureMaterial; import alternativa.engine3d.materials.compiler.Linker; @@ -40,9 +38,7 @@ import alternativa.engine3d.materials.Material; import flash.display3D.textures.CubeTexture; import flash.utils.Dictionary; -import spark.effects.easing.Elastic; - -use namespace alternativa3d; + use namespace alternativa3d; public class OmniLightShadow extends Shadow{ @@ -71,14 +67,9 @@ use namespace alternativa3d; private var _casters:Vector. = new Vector.(); - - private var castersInLight:Vector. = new Vector.(); - private var castersInLightCount:int; private var actualCasters:Vector. = new Vector.(); private var actualCastersCount:int; - // cube face -> caster - private var edgeCameraToCasterTransform:Transform3D = new Transform3D(); // caster -> cube face private var casterToEdgedCameraTransform:Transform3D = new Transform3D(); // object -> light @@ -95,12 +86,12 @@ use namespace alternativa3d; * @param pcfOffset Смягчение границ тени. */ public function OmniLightShadow(mapSize:int = 128, pcfOffset:Number = 0) { - sections = new SectionPlane(); - sections.next = new SectionPlane(); - sections.next.next = new SectionPlane(); - sections.next.next.next = new SectionPlane(); - sections.next.next.next.next = new SectionPlane(); - sections.next.next.next.next.next = new SectionPlane(); + sections = new SectionPlane(0x11, 0x22, 0xC); // RU + sections.next = new SectionPlane(0x12, 0x21, 0xC); // LU + sections.next.next = new SectionPlane(0x14, 0x28, 0x3); // FU + sections.next.next.next = new SectionPlane(0x18, 0x24, 0x3); // BU + sections.next.next.next.next = new SectionPlane(0x5, 0xA, 0x30); // RF + sections.next.next.next.next.next = new SectionPlane(0x9, 0x6, 0x30); // RB this.mapSize = mapSize; this.pcfOffset = pcfOffset; @@ -145,12 +136,6 @@ use namespace alternativa3d; cameras[4].rotationX = 0; cameras[4].scaleY = -1; cameras[4].composeTransforms(); - - // DUBFLR - - - // TODO: overwrite calculateFrustum function or setTransformConstants function - // TODO: 2 step culling. 1-culling by radius for light. 2-culling for current camera by 4 planes } private function createDebugObject(material:Material, context:Context3D):Mesh{ @@ -222,7 +207,6 @@ use namespace alternativa3d; cam.calculateProjection(radius, radius); } - var castersCount:int = _casters.length; actualCastersCount = 0; @@ -236,6 +220,7 @@ use namespace alternativa3d; parent = parent._parent; } + // TODO: remove Object3D.cameras, use something another if (visible) { // calculate transform matrices _light.lightToObjectTransform.combine(caster.cameraToLocalTransform, _light.localToCameraTransform); @@ -255,7 +240,7 @@ use namespace alternativa3d; } else { caster.cameras = 63; } - + // update Skin Joints matrices var skin:Skin = caster as Skin; if (skin != null) { @@ -275,24 +260,11 @@ use namespace alternativa3d; } } - // Iterate through six cameras for (i = 0; i < 6; i++) { // Cube side camera var edgeCamera:Camera3D = cameras[i]; - - // проверяем, есть ли видимые кастеры попадающие на грань куба -// var flipX:Boolean = edgeCamera.scaleX < 0; -// var flipY:Boolean = edgeCamera.scaleY < 0; -// edgeCamera.scaleX = 1; -// edgeCamera.scaleY = 1; -// edgeCamera.composeTransforms(); - -// if (flipX) edgeCamera.scaleX = -1; -// if (flipY) edgeCamera.scaleY = -1; -// edgeCamera.composeTransforms(); - var edgeBit:int = (1< 0) { // Настройка параметров рендеринга: @@ -305,7 +277,7 @@ use namespace alternativa3d; caster = actualCasters[j]; // Проверить находится ли кастер в зоне 4-х плоскостей - if (caster.cameras & edgeBit) { + if ((caster.cameras & edgeBit)) { // собираем матрицу перевода из кастера в пространство edgeCamera casterToEdgedCameraTransform.combine(edgeCamera.inverseTransform, caster.localToLightTransform); // Собираем драуколлы для кастера и его дочерних объектов @@ -313,7 +285,7 @@ use namespace alternativa3d; } } - if (renderer.drawUnits.length == 0) context.clear(0, 0, 0, 0.0); +// if (renderer.drawUnits.length == 0) context.clear(0, 0, 0, 0.0); // Отрисовка дроуколов renderer.render(context); @@ -322,9 +294,9 @@ use namespace alternativa3d; else{ // Если относительно одной из камер ничего не менялось, не вызываем отрисовочный вызов - if (prevActualCastersMask & edgeBit){ + if ((prevActualCastersMask & edgeBit)){ context.setRenderToTexture(cubeShadowMap, false, 0, i); - context.clear(0, 0, 0, 0); + context.clear(1, 0, 0, 0); prevActualCastersMask &= ~edgeBit; } @@ -347,13 +319,13 @@ use namespace alternativa3d; // } if (debug) { - if (actualCastersCount > 0 || true) { + if (actualCastersCount > 0) { // TODO: draw debug mesh always (DirectionalLightShadow) - // Создаем дебаговый объект, если он не создан + // Create debug object if needed if (debugObject == null) { debugObject = createDebugObject(debugMaterial, camera.context3D); - // TODO: select wright radius + // TODO: select right radius // debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius/12; debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius; debugObject.composeTransforms(); @@ -371,86 +343,81 @@ use namespace alternativa3d; private var sections:SectionPlane; - private function calculatePlanes(lightToObjectTransform:Transform3D):void { + private function calculatePlanes(transform:Transform3D):void { + // DUBFLR var planeRU:SectionPlane = sections; var planeLU:SectionPlane = sections.next; + var planeFU:SectionPlane = sections.next.next; + var planeBU:SectionPlane = sections.next.next.next; + var planeRF:SectionPlane = sections.next.next.next.next; + var planeRB:SectionPlane = sections.next.next.next.next.next; - sections.x = 0.707; - sections.z = 0.707; - sections.offset = sections.x*lightToObjectTransform.d + sections.z*lightToObjectTransform.l; + // TODO: reuse points + var ax:Number = transform.c - transform.a + transform.b; + var ay:Number = transform.g - transform.e + transform.f; + var az:Number = transform.k - transform.i + transform.j; + var bx:Number = transform.c - transform.a - transform.b; + var by:Number = transform.g - transform.e - transform.f; + var bz:Number = transform.k - transform.i - transform.j; + planeRU.x = bz * ay - by * az; + planeRU.y = bx * az - bz * ax; + planeRU.z = by * ax - bx * ay; + planeRU.offset = transform.d*planeRU.x + transform.h*planeRU.y + transform.l*planeRU.z; - //var RIGHT_SIDE:int = 0; + ax = transform.c + transform.a - transform.b; + ay = transform.g + transform.e - transform.f; + az = transform.k + transform.i - transform.j; + bx = transform.c + transform.a + transform.b; + by = transform.g + transform.e + transform.f; + bz = transform.k + transform.i + transform.j; + planeLU.x = bz * ay - by * az; + planeLU.y = bx * az - bz * ax; + planeLU.z = by * ax - bx * ay; + planeLU.offset = transform.d*planeLU.x + transform.h*planeLU.y + transform.l*planeLU.z; - sections.frontCameras = 0x11; - sections.backCameras = 0x22; -// sections.unused = 0x33; - sections.unused = 0xC; + ax = transform.c - transform.a - transform.b; + ay = transform.g - transform.e - transform.f; + az = transform.k - transform.i - transform.j; + bx = transform.c + transform.a - transform.b; + by = transform.g + transform.e - transform.f; + bz = transform.k + transform.i - transform.j; + planeFU.x = bz * ay - by * az; + planeFU.y = bx * az - bz * ax; + planeFU.z = by * ax - bx * ay; + planeFU.offset = transform.d*planeFU.x + transform.h*planeFU.y + transform.l*planeFU.z; - planeLU.x = -0.707; - planeLU.z = 0.707; - planeLU.offset = planeLU.x*lightToObjectTransform.d + planeLU.z*lightToObjectTransform.l; + ax = transform.c + transform.a + transform.b; + ay = transform.g + transform.e + transform.f; + az = transform.k + transform.i + transform.j; + bx = transform.c - transform.a + transform.b; + by = transform.g - transform.e + transform.f; + bz = transform.k - transform.i + transform.j; + planeBU.x = bz * ay - by * az; + planeBU.y = bx * az - bz * ax; + planeBU.z = by * ax - bx * ay; + planeBU.offset = transform.d*planeBU.x + transform.h*planeBU.y + transform.l*planeBU.z; - planeLU.frontCameras = 0x12; - planeLU.backCameras = 0x21; - planeLU.unused = 0xC; + ax = transform.a - transform.b + transform.c; + ay = transform.e - transform.f + transform.g; + az = transform.i - transform.j + transform.k; + bx = transform.a - transform.b - transform.c; + by = transform.e - transform.f - transform.g; + bz = transform.i - transform.j - transform.k; + planeRF.x = bz * ay - by * az; + planeRF.y = bx * az - bz * ax; + planeRF.z = by * ax - bx * ay; + planeRF.offset = transform.d*planeRF.x + transform.h*planeRF.y + transform.l*planeRF.z; -// var nearPlane:CullingPlane = sections; -// var farPlane:CullingPlane = nearPlane.next; -// var leftPlane:CullingPlane = farPlane.next; -// var rightPlane:CullingPlane = leftPlane.next; -// var topPlane:CullingPlane = rightPlane.next; -// var bottomPlane:CullingPlane = topPlane.next; -// -// var fa:Number = transform.a * correctionX; -// var fe:Number = transform.e * correctionX; -// var fi:Number = transform.i * correctionX; -// var fb:Number = transform.b * correctionY; -// var ff:Number = transform.f * correctionY; -// var fj:Number = transform.j * correctionY; -// -// var ax:Number = -fa - fb + transform.c; -// var ay:Number = -fe - ff + transform.g; -// var az:Number = -fi - fj + transform.k; -// var bx:Number = fa - fb + transform.c; -// var by:Number = fe - ff + transform.g; -// var bz:Number = fi - fj + transform.k; -// topPlane.x = bz * ay - by * az; -// topPlane.y = bx * az - bz * ax; -// topPlane.z = by * ax - bx * ay; -// topPlane.offset = transform.d * topPlane.x + transform.h * topPlane.y + transform.l * topPlane.z; -// // Right plane. -// ax = bx; -// ay = by; -// az = bz; -// bx = fa + fb + transform.c; -// by = fe + ff + transform.g; -// bz = fi + fj + transform.k; -// rightPlane.x = bz * ay - by * az; -// rightPlane.y = bx * az - bz * ax; -// rightPlane.z = by * ax - bx * ay; -// rightPlane.offset = transform.d * rightPlane.x + transform.h * rightPlane.y + transform.l * rightPlane.z; -// // Bottom plane. -// ax = bx; -// ay = by; -// az = bz; -// bx = -fa + fb + transform.c; -// by = -fe + ff + transform.g; -// bz = -fi + fj + transform.k; -// bottomPlane.x = bz*ay - by*az; -// bottomPlane.y = bx*az - bz*ax; -// bottomPlane.z = by*ax - bx*ay; -// bottomPlane.offset = transform.d*bottomPlane.x + transform.h*bottomPlane.y + transform.l*bottomPlane.z; -// // Left plane. -// ax = bx; -// ay = by; -// az = bz; -// bx = -fa - fb + transform.c; -// by = -fe - ff + transform.g; -// bz = -fi - fj + transform.k; -// leftPlane.x = bz*ay - by*az; -// leftPlane.y = bx*az - bz*ax; -// leftPlane.z = by*ax - bx*ay; -// leftPlane.offset = transform.d*leftPlane.x + transform.h*leftPlane.y + transform.l*leftPlane.z; + ax = transform.a + transform.b - transform.c; + ay = transform.e + transform.f - transform.g; + az = transform.i + transform.j - transform.k; + bx = transform.a + transform.b + transform.c; + by = transform.e + transform.f + transform.g; + bz = transform.i + transform.j + transform.k; + planeRB.x = bz * ay - by * az; + planeRB.y = bx * az - bz * ax; + planeRB.z = by * ax - bx * ay; + planeRB.offset = transform.d*planeRB.x + transform.h*planeRB.y + transform.l*planeRB.z; } private function recognizeObjectCameras(bb:BoundBox):int { @@ -537,37 +504,6 @@ use namespace alternativa3d; } } - -// // собирает список actualCasters для одной из 6-и камер -// private function calculateVisibility(root:Object3D, camera:Camera3D):void{ -// var casterCulling:int; -// -// if (root.visible) { -// // Вычисляем результат кулинга для объекта -// if (root.boundBox != null) { -// edgeCameraToCasterTransform.combine(root.lightToLocalTransform, camera.transform); -// camera.calculateFrustum(edgeCameraToCasterTransform); -// casterCulling = root.boundBox.checkFrustumCulling(camera.frustum, 63); -// } else { -// casterCulling = 63; -// } -// -// if (casterCulling <= 0) numCulled++; -// -// // добавляем кастер в список актуальных кастеров -// if (casterCulling >= 0) { -// actualCasters[actualCastersCount] = root; -// actualCastersCount++ -// } -// -// // Если есть дочерние объекты, -// // Проверяем их на кулинг -// for (var child:Object3D = root.childrenList; child != null; child = child.next) { -// calculateVisibility(child, camera); -// } -// } -// } - private function collectDraws(context:Context3D, caster:Object3D, edgeCamera:Camera3D):void{ // если объект является мешем, собираем для него дроуколы var mesh:Mesh = caster as Mesh; @@ -650,7 +586,6 @@ use namespace alternativa3d; } } - /** * @private * Процедура для передачи UV координат во фрагментный шейдер @@ -1122,4 +1057,10 @@ class SectionPlane { public var backCameras:int; public var unused:int = 63; + public function SectionPlane(frontCameras:int, backCameras:int, unused:int) { + this.frontCameras = frontCameras; + this.backCameras = backCameras; + this.unused = unused; + } + }