From 1268c217cc55f8a65f77c2ffa2afcfe7aae89366 Mon Sep 17 00:00:00 2001 From: Yaski Date: Thu, 26 Apr 2012 17:07:31 +0600 Subject: [PATCH] Some refactorings --- src/alternativa/engine3d/core/Camera3D.as | 10 +- .../shadows/DirectionalLightShadow.as | 5 +- .../engine3d/shadows/OmniLightShadow.as | 191 +++++++++--------- 3 files changed, 105 insertions(+), 101 deletions(-) diff --git a/src/alternativa/engine3d/core/Camera3D.as b/src/alternativa/engine3d/core/Camera3D.as index e3bf0b4..3e2eba1 100644 --- a/src/alternativa/engine3d/core/Camera3D.as +++ b/src/alternativa/engine3d/core/Camera3D.as @@ -1096,10 +1096,10 @@ public class Camera3D extends Object3D { value = 1000 * fpsUpdatePeriod / (time - previousPeriodTime); if (value > stageFrameRate) value = stageFrameRate; mod = value * 100 % 100; - fpsTextField.text = int(value) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00")); + fpsTextField.text = int(value) + "." + ((mod >= 10) ? mod.toString() : ((mod > 0) ? ("0" + mod) : "00")); value = 1000 / value; mod = value * 100 % 100; - frameTextField.text = int(value) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00")); + frameTextField.text = int(value) + "." + ((mod >= 10) ? mod.toString() : ((mod > 0) ? ("0" + mod) : "00")); previousPeriodTime = time; fpsUpdateCounter = 0; } @@ -1116,14 +1116,14 @@ public class Camera3D extends Object3D { if (methodTimeCount > 0) { value = methodTimeSum / methodTimeCount; mod = value * 100 % 100; - timerTextField.text = int(value) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00")); + timerTextField.text = int(value) + "." + ((mod >= 10) ? mod.toString() : ((mod > 0) ? ("0" + mod) : "00")); } else { timerTextField.text = ""; } if (cpuTimeCount > 0) { value = cpuTimeSum / cpuTimeCount; mod = value * 100 % 100; - cpuTextField.text = int(value) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00")); + cpuTextField.text = int(value) + "." + ((mod >= 10) ? mod.toString() : ((mod > 0) ? ("0" + mod) : "00")); } else { cpuTextField.text = ""; } @@ -1138,7 +1138,7 @@ public class Camera3D extends Object3D { var memory:int = System.totalMemory; value = memory / 1048576; mod = value * 100 % 100; - memoryTextField.text = int(value) + "." + ((mod >= 10) ? mod : ((mod > 0) ? ("0" + mod) : "00")); + memoryTextField.text = int(value) + "." + ((mod >= 10) ? mod.toString() : ((mod > 0) ? ("0" + mod) : "00")); // memory plot if (memory > maxMemory) maxMemory = memory; diff --git a/src/alternativa/engine3d/shadows/DirectionalLightShadow.as b/src/alternativa/engine3d/shadows/DirectionalLightShadow.as index dc76fcf..1e34ea2 100644 --- a/src/alternativa/engine3d/shadows/DirectionalLightShadow.as +++ b/src/alternativa/engine3d/shadows/DirectionalLightShadow.as @@ -30,7 +30,7 @@ package alternativa.engine3d.shadows { import alternativa.engine3d.resources.ExternalTextureResource; import alternativa.engine3d.resources.Geometry; import alternativa.engine3d.resources.TextureResource; - + import flash.display3D.Context3D; import flash.display3D.Context3DProgramType; import flash.display3D.Context3DTextureFormat; @@ -56,9 +56,6 @@ package alternativa.engine3d.shadows { private var renderer:Renderer = new Renderer(); - /** - * Debug mode. - */ /** * Degree of correcting offset of shadow map space. It need for getting rid of self-shadowing artifacts. */ diff --git a/src/alternativa/engine3d/shadows/OmniLightShadow.as b/src/alternativa/engine3d/shadows/OmniLightShadow.as index 3397742..f4d6f4a 100644 --- a/src/alternativa/engine3d/shadows/OmniLightShadow.as +++ b/src/alternativa/engine3d/shadows/OmniLightShadow.as @@ -14,14 +14,12 @@ package alternativa.engine3d.shadows { import alternativa.engine3d.core.Renderer; import alternativa.engine3d.core.Transform3D; import alternativa.engine3d.core.VertexAttributes; - import alternativa.engine3d.core.View; import alternativa.engine3d.materials.Material; import alternativa.engine3d.materials.ShaderProgram; import alternativa.engine3d.materials.TextureMaterial; import alternativa.engine3d.materials.compiler.Linker; import alternativa.engine3d.materials.compiler.Procedure; import alternativa.engine3d.materials.compiler.VariableType; - import alternativa.engine3d.objects.Joint; import alternativa.engine3d.objects.Mesh; import alternativa.engine3d.objects.Skin; import alternativa.engine3d.objects.Surface; @@ -42,17 +40,22 @@ package alternativa.engine3d.shadows { public class OmniLightShadow extends Shadow{ /** - * Степень корректирующего смещения пространства карты теней для избавления от артефактов самозатенения. + * Degree of correcting offset of shadow map space. It need for getting rid of self-shadowing artifacts. */ public var biasMultiplier:Number = 0.99; private var renderer:Renderer = new Renderer(); - - private var radius:Number = 1; + + // radius of the light source + private var radius:Number = 100; + + // cube map size private var _mapSize:Number; private var _pcfOffset:Number; private var cubeShadowMap:CubeTexture; + + // Sides cameras private var cameras:Vector. = new Vector.(); private var debugObject:Mesh; @@ -60,27 +63,30 @@ package alternativa.engine3d.shadows { private var _casters:Vector. = new Vector.(); - private var cachedContext:Context3D; - private var programs:Dictionary = new Dictionary(); - 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 private var objectToLightTransform:Transform3D = new Transform3D(); - + // casters count in edge private var prevActualCasterCountForEdge:Vector. = new Vector.(6); + private var cachedContext:Context3D; + private var programs:Dictionary = new Dictionary(); + /** * Создает экземпляр OmniLightShadow. * @param mapSize Размер карты теней. Должен быть степенью 2. * @param pcfOffset Смягчение границ тени. */ public function OmniLightShadow(mapSize:int = 128, pcfOffset:Number = 0) { - this.mapSize = mapSize; this.pcfOffset = pcfOffset; + vertexShadowProcedure = getVShader(); type = _pcfOffset > 0 ? "OS" : "os"; fragmentShadowProcedure = _pcfOffset > 0 ? getFShaderPCF() : getFShader(); @@ -89,11 +95,10 @@ package alternativa.engine3d.shadows { debugMaterial.alpha = 1.0; for (var i:int = 0; i < 6; i++) { - // создаем камеры + // Create cameras + // TODO: recalculate nearClipping var cam:Camera3D = new Camera3D(10, radius); cam.fov = 1.910633237; - cam.view = new View(radius, radius); - cam.renderer = renderer; cameras[i] = cam; prevActualCasterCountForEdge[i] = 0; @@ -124,9 +129,12 @@ package alternativa.engine3d.shadows { cameras[4].rotationX = 0; cameras[4].scaleY = -1; cameras[4].composeTransforms(); - } + // TODO: boundBox of light? + // TODO: remove setBoundSize + } + /** * @private */ @@ -134,91 +142,89 @@ package alternativa.engine3d.shadows { this.radius = value; for (var i:int = 0; i < 6; i++) { var cam:Camera3D = cameras[i]; - cam.view.width = cam.view.height = int (value); cam.farClipping = value; cam.calculateProjection(value,value); } } - private function createDebugCube(material:Material, context:Context3D):Mesh{ - var mesh:Mesh = new Mesh(); + private function createDebugObject(material:Material, context:Context3D):Mesh{ + var geometry:Geometry; + var mesh:Mesh; // TODO: определиться куб или сфера -// var geometry:Geometry = new Geometry(8); -// mesh.geometry = geometry; -// -// var attributes:Array = new Array(); -// attributes[0] = VertexAttributes.POSITION; -// attributes[1] = VertexAttributes.POSITION; -// attributes[2] = VertexAttributes.POSITION; -// geometry.addVertexStream(attributes); -// -// geometry.setAttributeValues(VertexAttributes.POSITION, Vector.([-0.5, -0.5, -0.5, -// 0.5, -0.5, -0.5, -// 0.5, 0.5, -0.5, -// -0.5, 0.5, -0.5, -// -0.5, -0.5, 0.5, -// 0.5, -0.5, 0.5, -// 0.5, 0.5, 0.5, -// -0.5, 0.5, 0.5])); -// -// geometry.indices = Vector.([ 0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 2, 0, -// 2, 6, 1, 1, 6, 2, 1, 6, 5, 5, 6, 1, -// 6, 4, 5, 5, 4, 6, 6, 4, 7, 7, 4, 6, -// 0, 7, 4, 4, 7, 0, 0, 7, 3, 3, 7, 0, -// 3, 6, 2, 2, 6, 3, 3, 7, 6, 6, 7, 3, -// 0, 5, 1, 1, 5, 0, 0, 4, 5, 5, 4, 0]); -// -// mesh.addSurface(material, 0, 24); - var sphere:GeoSphere = new GeoSphere(1, 4, false); - var geometry:Geometry = sphere.geometry; - mesh.geometry = geometry; - mesh.addSurface(material, 0, geometry.numTriangles); + var isBox:Boolean = false; + if (isBox) { + mesh = new Mesh(); + geometry = new Geometry(8); + mesh.geometry = geometry; - geometry.upload(context); + var attributes:Array = new Array(); + attributes[0] = VertexAttributes.POSITION; + attributes[1] = VertexAttributes.POSITION; + attributes[2] = VertexAttributes.POSITION; + geometry.addVertexStream(attributes); + geometry.setAttributeValues(VertexAttributes.POSITION, Vector.([ + -0.5, -0.5, -0.5, + 0.5, -0.5, -0.5, + 0.5, 0.5, -0.5, + -0.5, 0.5, -0.5, + -0.5, -0.5, 0.5, + 0.5, -0.5, 0.5, + 0.5, 0.5, 0.5, + -0.5, 0.5, 0.5])); + geometry.indices = Vector.([ + 0, 1, 2, 3, 0, 2, 2, 1, 0, 3, 2, 0, + 2, 6, 1, 1, 6, 2, 1, 6, 5, 5, 6, 1, + 6, 4, 5, 5, 4, 6, 6, 4, 7, 7, 4, 6, + 0, 7, 4, 4, 7, 0, 0, 7, 3, 3, 7, 0, + 3, 6, 2, 2, 6, 3, 3, 7, 6, 6, 7, 3, + 0, 5, 1, 1, 5, 0, 0, 4, 5, 5, 4, 0]); + mesh.addSurface(material, 0, 24); + } else { + mesh = new GeoSphere(1, 4, false); + mesh.setMaterialToAllSurfaces(material); + } + mesh.geometry.upload(context); return mesh; } - - // Вычисление шедоумапы + // Draw in shadow map override alternativa3d function process(camera:Camera3D):void { var i:int; var j:int; var caster:Object3D; var context:Context3D = camera.context3D; - var castersCount:int = _casters.length; - // Отсечение кастеров, тени которых не видны - // Обработка смены контекста + // Checking changed context if (context != cachedContext) { programs = new Dictionary(); cubeShadowMap = null; cachedContext = context; - for (i = 0; i < cameras.length; i++) { - cameras[i].context3D = cachedContext; - } } + // Culling invisible casters if (cubeShadowMap == null) { cubeShadowMap = context.createCubeTexture(_mapSize, Context3DTextureFormat.BGRA, true); debugMaterial.cubeMap = cubeShadowMap; + // TODO: not clear here for (i = 0; i < 6; i++) { context.setRenderToTexture(cubeShadowMap, true, 0, i); context.clear(1, 0, 0, 0.3); } } - // предрасчитаем некоторые матрицы трансформации - for (j = 0; j < castersCount; j++) { - caster = _casters[j]; + var castersCount:int = _casters.length; + // calculating some transformation matrices + for (i = 0; i < castersCount; i++) { + caster = _casters[i]; if (caster.transformChanged) caster.composeTransforms(); caster.lightToLocalTransform.combine(caster.cameraToLocalTransform, _light.localToCameraTransform); caster.localToLightTransform.combine(_light.cameraToLocalTransform, caster.localToCameraTransform); - if (caster.childrenList) - calculateChildrenTransforms(caster); + if (caster.childrenList != null) calculateChildrenTransforms(caster); + // TODO: repair skin // var skin:Skin = caster as Skin; // if (skin != null) { // // Расчет матриц джоинтов @@ -235,10 +241,9 @@ package alternativa.engine3d.shadows { } - - // Пробегаемся по 6-и камерам + // Iterate through six cameras for (i = 0; i < 6; i++) { - // камера соответствующая грани куба + // Cube side camera var edgeCamera:Camera3D = cameras[i]; // проверяем, есть ли видимые кастеры попадающие на грань куба @@ -259,9 +264,9 @@ package alternativa.engine3d.shadows { } } - if (actualCastersCount>0){ + if (actualCastersCount > 0) { // Настройка параметров рендеринга: - renderer.camera = edgeCamera; + renderer.camera = camera; context.setRenderToTexture(cubeShadowMap, true, 0, i); context.clear(1, 0, 0, 0.0); @@ -293,7 +298,7 @@ package alternativa.engine3d.shadows { if (actualCastersCount > 0) { // Создаем дебаговый объект, если он не создан if (debugObject == null) { - debugObject = createDebugCube(debugMaterial, camera.context3D); + debugObject = createDebugObject(debugMaterial, camera.context3D); debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius/12; debugObject.composeTransforms(); } @@ -308,21 +313,19 @@ package alternativa.engine3d.shadows { } } - // предрасчитывает матрицы для всех детей + // Precalculate children matrices // localToLightTransform, lightToLocalTransform, transform, и calculateTransform для Joint private function calculateChildrenTransforms(root:Object3D):void{ - var childrenList:Object3D = root.childrenList; - - for (var child:Object3D = childrenList; child != null; child = child.next) { + for (var child:Object3D = root.childrenList; child != null; child = child.next) { // расчет матриц трансформаций для объектов if (child.transformChanged) child.composeTransforms(); child.localToLightTransform.combine(root.localToLightTransform, child.transform); child.lightToLocalTransform.combine(child.inverseTransform, root.lightToLocalTransform); - if (child.childrenList) - calculateChildrenTransforms(child); - + if (child.childrenList != null) calculateChildrenTransforms(child); + + // TODO: repair skin // // расчет матриц трансформаций для скинов // var skin:Skin = child as Skin; // if (skin != null) { @@ -605,7 +608,7 @@ package alternativa.engine3d.shadows { shaderArr[line++] = "dp3 t0.x, t0.xyz, c0.xyz"; // декодируем, находим разницу между расстояниями и умножаем ее на большое число // рассчитываем значение тени - shaderArr[line++] = "sat t0, t0.x"; + shaderArr[line++] = "sat t0.x, t0.x"; shaderArr[line++] = "sub o0, c0.w, t0.x"; // shaderArr[line++] = "sat t0.x, t0.x"; @@ -631,33 +634,34 @@ package alternativa.engine3d.shadows { // допустимо использование временных переменных t0 t1 t2 t3 // v0 - sample - // ищем 2-а перпендикулярных вектора + // calculate 2 ortogonal vectors // (-y, x, 0) shaderArr[line++] = "mov t1.xyzw, v0.yxzw"; shaderArr[line++] = "mul t1.xyzw, t1.xyzw, c1.xyzz"; shaderArr[line++] = "crs t0.xyz, v0.xyz, t1.xyz"; - // нормируем их + // normalize vectors shaderArr[line++] = "nrm t0.xyz, t0.xyz"; shaderArr[line++] = "nrm t1.xyz, t1.xyz"; - // задаем оффсеты shaderArr[line++] = "dp3 t3.z, v0.xyz, v0.xyz"; - shaderArr[line++] = "sqt t3.z, t3.z"; // w: [0, radius] + shaderArr[line++] = "sqt t3.z, t3.z"; // distance + + // apply pcf offset shaderArr[line++] = "mul t0.w, c1.w, t3.z"; // с1.w = offset/radius shaderArr[line++] = "mul t0.xyz, t0.xyz, t0.w"; shaderArr[line++] = "mul t1.xyz, t1.xyz, t0.w"; // --------- {13 opcode} - // t0, t1 - перпендикуляры ↑→ - // t2 - текущий вектор + // t0, t1 - ortogonals ↑→ + // t2 - current vector - // в v0.w, t3.z расстояние до объекта - // t3.xy - результат из текстуры - // t3.w - сумма sat-ов + // t3.z distance to object + // t3.xy - result from shadow map + // t3.w - summ of sat - // первая точка + // first point shaderArr[line++] = "add t2.xyz, t0.xyz, t1.xyz"; shaderArr[line++] = "mul t2.xyz, t2.xyz, c2.xxx"; shaderArr[line++] = "add t2.xyz, t2.xyz, v0.xyz"; @@ -670,7 +674,7 @@ package alternativa.engine3d.shadows { //----- - for (j = 1; j<4; j++){ + for (j = 1; j < 4; j++) { shaderArr[line++] = "add t2.xyz, t2.xyz, t1.xyz"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; @@ -682,13 +686,13 @@ package alternativa.engine3d.shadows { //----- - for (i = 0; i<3; i++){ + for (i = 0; i < 3; i++) { shaderArr[line++] = "add t2.xyz, t2.xyz, t0.xyz"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число - for (j = 1; j<4; j++){ + for (j = 1; j < 4; j++){ shaderArr[line++] = (i%2 == 1)?("add t2.xyz, t2.xyz, t1.xyz"):("sub t2.xyz, t2.xyz, t1.xyz"); shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; @@ -701,13 +705,12 @@ package alternativa.engine3d.shadows { shaderArr[line++] = "sub o0, c1.y, t3.w"; - //--------- {73 opcode} + //--------- {73 opcodes} return Procedure.compileFromArray(shaderArr, "OmniShadowMapFragment"); } private static const componentByIndex:Array = ["x", "y", "z", "w"]; - /** * Добавляет object в список объектов, отбрасывающих тень. * @param object Добавляемый объект. @@ -718,6 +721,12 @@ package alternativa.engine3d.shadows { } } + public function removeCaster(object:Object3D):void { + var index:int = _casters.indexOf(object); + if (index < 0) throw new Error("Caster not found"); + _casters[index] = _casters.pop(); + } + /** * Очищает список объектов, отбрасывающих тень. */ @@ -790,8 +799,6 @@ import alternativa.engine3d.resources.Geometry; import flash.display3D.Context3D; import flash.display3D.Context3DBlendFactor; import flash.display3D.Context3DProgramType; -import flash.display3D.Program3D; - import flash.display3D.VertexBuffer3D; import flash.display3D.textures.CubeTexture; import flash.utils.Dictionary;