From 26b8a0b05f2984365ea778ffcec37e50f630fea8 Mon Sep 17 00:00:00 2001 From: maltsev Date: Fri, 30 Mar 2012 18:12:11 +0600 Subject: [PATCH] Removes old shadow classes --- .../shadows/DirectionalShadowRenderer.as | 540 ------------ .../engine3d/shadows/OmniShadowRenderer.as | 798 ------------------ .../OmniShadowRendererDebugMaterial.as | 162 ---- .../engine3d/shadows/ShadowRenderer.as | 184 ---- .../engine3d/shadows/ShadowsSystem.as | 96 --- .../engine3d/shadows/SpotShadowRenderer.as | 656 -------------- .../engine3d/shadows/StaticShadowRenderer.as | 569 ------------- 7 files changed, 3005 deletions(-) delete mode 100644 src/alternativa/engine3d/shadows/DirectionalShadowRenderer.as delete mode 100644 src/alternativa/engine3d/shadows/OmniShadowRenderer.as delete mode 100644 src/alternativa/engine3d/shadows/OmniShadowRendererDebugMaterial.as delete mode 100644 src/alternativa/engine3d/shadows/ShadowRenderer.as delete mode 100644 src/alternativa/engine3d/shadows/ShadowsSystem.as delete mode 100644 src/alternativa/engine3d/shadows/SpotShadowRenderer.as delete mode 100644 src/alternativa/engine3d/shadows/StaticShadowRenderer.as diff --git a/src/alternativa/engine3d/shadows/DirectionalShadowRenderer.as b/src/alternativa/engine3d/shadows/DirectionalShadowRenderer.as deleted file mode 100644 index ffdf234..0000000 --- a/src/alternativa/engine3d/shadows/DirectionalShadowRenderer.as +++ /dev/null @@ -1,540 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.BoundBox; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.DrawUnit; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.core.Transform3D; - import alternativa.engine3d.core.VertexAttributes; - import alternativa.engine3d.lights.DirectionalLight; - 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.Mesh; - import alternativa.engine3d.objects.Surface; - import alternativa.engine3d.primitives.Box; - import alternativa.engine3d.resources.ExternalTextureResource; - import alternativa.engine3d.resources.TextureResource; - - import flash.display3D.Context3D; - import flash.display3D.Context3DProgramType; - import flash.display3D.Context3DTextureFormat; - import flash.display3D.Context3DTriangleFace; - import flash.display3D.Program3D; - import flash.display3D.textures.Texture; - import flash.geom.Matrix3D; - import flash.geom.Vector3D; - - use namespace alternativa3d; - - /** - * @private - */ - public class DirectionalShadowRenderer extends ShadowRenderer { - - public var offset:Vector3D = new Vector3D(); - - public var caster:Object3D; - - private var context:Context3D; - - private var shadowMap:Texture; - private var _worldSize:Number; - - private var light:DirectionalLight; - alternativa3d var globalToShadowMap:Matrix3D = new Matrix3D(); - - private var debugObject:Mesh; - public var debugMaterial:TextureMaterial = new TextureMaterial(); - private var debugTexture:TextureResource = new ExternalTextureResource("null"); -// private var debugTexture:TextureResource = new BitmapTextureResource(new BitmapData(4, 4, false, 0xFF0000)); - - private static const constants:Vector. = Vector.([ -// 255, 255*0.98, 100, 1 - 255, 255*0.96, 100, 1 - ]); - - private var pcfOffset:Number = 0; - private var pcfOffsets:Vector.; - - public function DirectionalShadowRenderer(context:Context3D, size:int, worldSize:Number, pcfSize:Number = 0) { - this.context = context; - this._worldSize = worldSize; - this.pcfOffset = pcfSize/worldSize/255; -// this.pcfOffset = pcfSize; - if (pcfOffset > 0) { - pcfOffsets = Vector.([ - -pcfOffset, -pcfOffset, 0, 1/4, - -pcfOffset, pcfOffset, 0, 1, - pcfOffset, -pcfOffset, 0, 1, - pcfOffset, pcfOffset, 0, 1 - ]); - } - this.shadowMap = context.createTexture(size, size, Context3DTextureFormat.BGRA, true); - debugTexture._texture = this.shadowMap; - debugMaterial.diffuseMap = debugTexture; - debugMaterial.alpha = 0.9; - // TODO: fix - debugMaterial.transparentPass = true; - debugMaterial.opaquePass = false; - debugMaterial.alphaThreshold = 1.1; - -// debugTexture.upload(context); - - debugObject = new Box(worldSize, worldSize, 1, 1, 1, 1, false, debugMaterial); - debugObject.geometry.upload(context); - } - - public function get worldSize():Number { - return _worldSize; - } - - public function set worldSize(value:Number):void { - _worldSize = value; - var newDebug:Mesh = new Box(_worldSize, _worldSize, 1, 1, 1, 1, false, debugMaterial); - newDebug.geometry.upload(context); - if (debugObject._parent != null) { - debugObject._parent.addChild(newDebug); - debugObject._parent.removeChild(debugObject); - } - debugObject = newDebug; - } - - private var _debug:Boolean = false; - public function setLight(value:DirectionalLight):void { - light = value; - if (_debug) { - light.addChild(debugObject); - } - } - - override public function get debug():Boolean { - return _debug; - } - - override public function set debug(value:Boolean):void { - _debug = value; - if (_debug) { - if (light != null) { - light.addChild(debugObject); - } - } else { - if (debugObject._parent != null) { - debugObject._parent.removeChild(debugObject); - } - } - } - - private static var matrix:Matrix3D = new Matrix3D(); - override alternativa3d function cullReciever(boundBox:BoundBox, object:Object3D):Boolean { - copyMatrixFromTransform(matrix, object.localToGlobalTransform); - matrix.append(this.globalToShadowMap); - return cullObjectImplementation(boundBox, matrix); - } - - private var lightProjectionMatrix:Matrix3D = new Matrix3D(); - private var uvMatrix:Matrix3D = new Matrix3D(); - private var center:Vector3D = new Vector3D(); - override public function update():void { - active = true; - var root:Object3D; - // Расчитываем матрицу объекта -// if (caster.transformChanged) { - caster.localToCameraTransform.compose(caster._x, caster._y, caster._z, caster._rotationX, caster._rotationY, caster._rotationZ, caster._scaleX, caster._scaleY, caster._scaleZ); -// } else { -// caster.localToCameraTransform.copy(caster.transform); -// } - root = caster; - while (root._parent != null) { - root = root._parent; -// if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); -// } - caster.localToCameraTransform.append(root.localToGlobalTransform); - } - - // Расчитываем матрицу лайта - light.localToGlobalTransform.compose(light._x, light._y, light._z, light._rotationX, light._rotationY, light._rotationZ, light._scaleX, light._scaleY, light._scaleZ); - root = light; - while (root._parent != null) { - root = root._parent; -// if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); -// } - light.localToGlobalTransform.append(root.localToGlobalTransform); - } - light.globalToLocalTransform.copy(light.localToGlobalTransform); - light.globalToLocalTransform.invert(); - - // Получаем матрицу перевода из объекта в лайт - caster.localToCameraTransform.append(light.globalToLocalTransform); - - // Расчет матрицы проецирования - var t:Transform3D = caster.localToCameraTransform; - center.x = t.a*offset.x + t.b*offset.y + t.c*offset.z + t.d; - center.y = t.e*offset.x + t.f*offset.y + t.g*offset.z + t.h; - center.z = t.i*offset.x + t.j*offset.y + t.k*offset.z + t.l; -// var center:Vector3D = new Vector3D(caster.localToCameraTransform.d, caster.localToCameraTransform.h, caster.localToCameraTransform.l); - - calculateShadowMapProjection(lightProjectionMatrix, uvMatrix, center, _worldSize, _worldSize, _worldSize); - copyMatrixFromTransform(globalToShadowMap, light.globalToLocalTransform); - globalToShadowMap.append(uvMatrix); - - debugObject.x = center.x; - debugObject.y = center.y; - debugObject.z = center.z - _worldSize/2; -// trace("center", center); - - debugMaterial.diffuseMap = null; - - // Рисуем в шедоумапу - context.setRenderToTexture(shadowMap, true, 0, 0); -// context.clear(1); - context.clear(1, 1, 1, 1); - cleanContext(context); - drawObjectToShadowMap(context, caster, light, lightProjectionMatrix); - context.setRenderToBackBuffer(); - cleanContext(context); - debugMaterial.diffuseMap = debugTexture; - } - - private static var transformToMatrixRawData:Vector. = new Vector.(16); - alternativa3d static function copyMatrixFromTransform(matrix:Matrix3D, transform:Transform3D):void { - transformToMatrixRawData[0] = transform.a; - transformToMatrixRawData[1] = transform.e; - transformToMatrixRawData[2] = transform.i; - transformToMatrixRawData[3] = 0; - transformToMatrixRawData[4] = transform.b; - transformToMatrixRawData[5] = transform.f; - transformToMatrixRawData[6] = transform.j; - transformToMatrixRawData[7] = 0; - transformToMatrixRawData[8] = transform.c; - transformToMatrixRawData[9] = transform.g; - transformToMatrixRawData[10] = transform.k; - transformToMatrixRawData[11] = 0; - transformToMatrixRawData[12] = transform.d; - transformToMatrixRawData[13] = transform.h; - transformToMatrixRawData[14] = transform.l; - transformToMatrixRawData[15] = 1; -// matrix.copyRawDataFrom(transformToMatrixRawData); - matrix.rawData = transformToMatrixRawData; - } - - alternativa3d static function drawObjectToShadowMap(context:Context3D, object:Object3D, light:DirectionalLight, projection:Matrix3D):void { - if (object is Mesh) { - drawMeshToShadowMap(context, Mesh(object), projection); - } - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - if (child.visible && child.useShadow) { - if (child.transformChanged) child.composeTransforms(); - child.localToCameraTransform.combine(object.localToCameraTransform, child.transform); - drawObjectToShadowMap(context, child, light, projection); - } - } - } - - private static var drawProjection:Matrix3D = new Matrix3D(); - private static var directionalShadowMapProgram:Program3D; - private static function drawMeshToShadowMap(context:Context3D, mesh:Mesh, projection:Matrix3D):void { - if (mesh.geometry == null || mesh.geometry.numTriangles == 0 || !mesh.geometry.isUploaded) { - return; - } - - copyMatrixFromTransform(drawProjection, mesh.localToCameraTransform); - drawProjection.append(projection); - if (directionalShadowMapProgram == null) directionalShadowMapProgram = initMeshToShadowMapProgram(context); - context.setProgram(directionalShadowMapProgram); - - context.setVertexBufferAt(0, mesh.geometry.getVertexBuffer(VertexAttributes.POSITION), mesh.geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]); - - context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, drawProjection, true); - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, Vector.([255, 0, 0, 1])); - context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.([1/255, 0, 0, 1])); - - context.setCulling(Context3DTriangleFace.BACK); - - for (var i:int = 0; i < mesh._surfacesLength; i++) { - var surface:Surface = mesh._surfaces[i]; - if (surface.material == null || !surface.material.canDrawInShadowMap) continue; - context.drawTriangles(mesh.geometry._indexBuffer, surface.indexBegin, surface.numTriangles); - } - context.setVertexBufferAt(0, null); - } - - private static function initMeshToShadowMapProgram(context3d:Context3D):Program3D { - var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); - var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); - var proc:Procedure = Procedure.compileFromArray([ - "#a0=a0", - "#c4=c4", - "#v0=v0", - "m44 t0, a0, c0", - "mul v0, t0, c4.x", - "mov o0, t0" - ]); - proc.assignVariableName(VariableType.CONSTANT, 0, "c0", 4); - vLinker.addProcedure(proc); - - fLinker.addProcedure(Procedure.compileFromArray([ - "#v0=v0", - "#c0=c0", - "mov t0.xy, v0.zz", - "frc t0.y, v0.z", - "sub t0.x, v0.z, t0.y", - "mul t0.x, t0.x, c0.x", - "mov t0.z, c0.z", - "mov t0.w, c0.w", - "mov o0, t0" - ])); - var program:Program3D = context3d.createProgram(); -// trace("VERTEX"); -// trace(A3DUtils.disassemble(vLinker.getByteCode())); -// trace("FRAGMENT"); -// trace(A3DUtils.disassemble(fLinker.getByteCode())); - fLinker.varyings = vLinker.varyings; - vLinker.link(); - fLinker.link(); - program.upload(vLinker.data, fLinker.data); - return program; - } - - // должен быть заполнен нулями - private var rawData:Vector. = new Vector.(16); - private function calculateShadowMapProjection(matrix:Matrix3D, uvMatrix:Matrix3D, offset:Vector3D, width:Number, height:Number, length:Number):void { - var halfW:Number = width/2; - var halfH:Number = height/2; - var halfL:Number = length/2; - var frustumMinX:Number = offset.x - halfW; - var frustumMaxX:Number = offset.x + halfW; - var frustumMinY:Number = offset.y - halfH; - var frustumMaxY:Number = offset.y + halfH; - var frustumMinZ:Number = offset.z - halfL; - var frustumMaxZ:Number = offset.z + halfL; - - // Считаем матрицу проецирования - rawData[0] = 2/(frustumMaxX - frustumMinX); - rawData[5] = 2/(frustumMaxY - frustumMinY); - rawData[10]= 1/(frustumMaxZ - frustumMinZ); - rawData[12] = (-0.5 * (frustumMaxX + frustumMinX) * rawData[0]); - rawData[13] = (-0.5 * (frustumMaxY + frustumMinY) * rawData[5]); - rawData[14]= -frustumMinZ/(frustumMaxZ - frustumMinZ); - rawData[15]= 1; - matrix.rawData = rawData; - - rawData[0] = 1/((frustumMaxX - frustumMinX)); -// if (useSingle) { -// rawData[5] = 1/((frustumMaxY - frustumMinY)); -// } else { - rawData[5] = -1/((frustumMaxY - frustumMinY)); -// } - rawData[12] = 0.5 - (0.5 * (frustumMaxX + frustumMinX) * rawData[0]); - rawData[13] = 0.5 - (0.5 * (frustumMaxY + frustumMinY) * rawData[5]); - uvMatrix.rawData = rawData; - } - -/* - private static const fullVShader:Procedure = initFullVShader(); - private static function initFullVShader():Procedure { - var shader:Procedure = Procedure.compileFromArray([ - "m44 o0, a0, c0", - // Координата вершины в локальном пространстве - "m44 v0, a0, c4", - ]); - shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPosition"); - shader.assignVariableName(VariableType.CONSTANT, 0, "cPROJ", 4); - shader.assignVariableName(VariableType.CONSTANT, 4, "cTOSHADOW", 4); - shader.assignVariableName(VariableType.VARYING, 0, "vSHADOWSAMPLE"); - return shader; - } -*/ - private static function initVShader(index:int):Procedure { - var shader:Procedure = Procedure.compileFromArray([ - "m44 v0, a0, c0" - ]); - shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPosition"); - shader.assignVariableName(VariableType.CONSTANT, 0, index + "cTOSHADOW", 4); - shader.assignVariableName(VariableType.VARYING, 0, index + "vSHADOWSAMPLE"); - return shader; - } - private static function initFShader(mult:Boolean, usePCF:Boolean, index:int, grayScale:Boolean = false):Procedure { - var i:int; - var line:int = 0; - var shaderArr:Array = []; - var numPass:uint = (usePCF) ? 4 : 1; - for (i = 0; i < numPass; i++) { - // Расстояние - shaderArr[line++] = "mov t0.w, v0.z"; - shaderArr[line++] = "mul t0.w, t0.w, c4.y"; // bias [0.99] * 255 - - if (usePCF) { - // Добавляем смещение - shaderArr[line++] = "mul t1, c" + (i + 6).toString() + ", t0.w"; - shaderArr[line++] = "add t1, v0, t1"; - shaderArr[line++] = "tex t1, t1, s0 <2d,clamp,near,nomip>"; - } else { - shaderArr[line++] = "tex t1, v0, s0 <2d,clamp,near,nomip>"; - } - - // Восстанавливаем расстояние - shaderArr[line++] = "mul t1.w, t1.x, c4.x"; // * 255 - shaderArr[line++] = "add t1.w, t1.w, t1.y"; - - // Перекрытие тенью - shaderArr[line++] = "sub t2.z, t1.w, t0.w"; - shaderArr[line++] = "mul t2.z, t2.z, c4.z"; // smooth [10000] - shaderArr[line++] = "sat t2.z, t2.z"; - - // Добавляем маску и прозрачность, затем sat - if (grayScale) { - shaderArr[line++] = "add t2, t2.zzzz, t1.zzzz"; // маска тени - } else { - shaderArr[line++] = "add t2.z, t2.z, t1.z"; // маска тени - shaderArr[line++] = "add t2, t2.zzzz, c5"; // цвет тени - } - shaderArr[line++] = "sat t2, t2"; - - if (usePCF) { - if (i == 0) { - shaderArr[line++] = "mov t3, t2"; - } else { - shaderArr[line++] = "add t3, t3, t2"; - } - } - } - if (usePCF) { - shaderArr[line++] = "mul t2, t3, c6.w"; - } - if (grayScale) { - shaderArr[line++] = "mov o0.w, t2.x"; - } else { - if (mult) { - shaderArr[line++] = "mul t0.xyz, i0.xyz, t2.xyz"; - shaderArr[line++] = "mov t0.w, i0.w"; - shaderArr[line++] = "mov o0, t0"; - } else { - shaderArr[line++] = "mov o0, t2"; - } - } - var shader:Procedure = Procedure.compileFromArray(shaderArr, "DirectionalShadowMap"); - shader.assignVariableName(VariableType.VARYING, 0, index + "vSHADOWSAMPLE"); - shader.assignVariableName(VariableType.CONSTANT, 4, index + "cConstants", 1); - if (!grayScale) shader.assignVariableName(VariableType.CONSTANT, 5, index + "cShadowColor", 1); - if (usePCF) { - for (i = 0; i < numPass; i++) { - shader.assignVariableName(VariableType.CONSTANT, i + 6, "cDPCF" + i.toString(), 1); - } - } - shader.assignVariableName(VariableType.SAMPLER, 0, index + "sSHADOWMAP"); - return shader; - } - - override public function getVShader(index:int = 0):Procedure { - return initVShader(index); - } - override public function getFShader(index:int = 0):Procedure { - return initFShader(false, (pcfOffset > 0), index); - } -// override public function getMultFShader():Procedure { -// return initFShader(true, (pcfOffset > 0), 0); -// } -// override public function getMultVShader():Procedure { -// return initVShader(0); -// } - - override public function getFIntensityShader():Procedure { - return initFShader(false, (pcfOffset > 0), 0, true); - } - - private static const objectToShadowMap:Matrix3D = new Matrix3D(); - private static const localToGlobal:Transform3D = new Transform3D(); - private static const vector:Vector. = new Vector.(16, false); - override public function applyShader(drawUnit:DrawUnit, program:ShaderProgram, object:Object3D, camera:Camera3D, index:int = 0):void { - // Считаем матрицу перевода в лайт из объекта - localToGlobal.combine(camera.localToGlobalTransform, object.localToCameraTransform); - copyMatrixFromTransform(objectToShadowMap, localToGlobal); - objectToShadowMap.append(globalToShadowMap); - objectToShadowMap.copyRawDataTo(vector, 0, true); -// objectToShadowMap.transpose(); - -// drawUnit.setVertexConstantsFromVector(program.vertexShader.getVariableIndex(index + "cTOSHADOW"), objectToShadowMap.rawData, 4) - drawUnit.setVertexConstantsFromVector(program.vertexShader.getVariableIndex(index + "cTOSHADOW"), vector, 4) - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex(index + "cConstants"), constants, 1); - if (program.fragmentShader.containsVariable(index + "cShadowColor")) { -// drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex(index + "cShadowColor"), camera.ambient, 1); - // В дальнейшем яркость тени увеличтся в два раза - drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex(index + "cShadowColor"), camera.ambient[0]/2, camera.ambient[1]/2, camera.ambient[2]/2, 1); - } - - if (pcfOffset > 0) { -// destination.addFragmentConstantSet(program.fragmentShader.getVariableIndex(index + "cPCF0"), pcfOffsets, pcfOffsets.length/4); - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex("cDPCF0"), pcfOffsets, pcfOffsets.length/4); - } - drawUnit.setTextureAt(program.fragmentShader.getVariableIndex(index + "sSHADOWMAP"), shadowMap); - } - -// override public function getTextureIndex(fLinker:Linker):int { -// return fLinker.getVariableIndex("sSHADOWMAP"); -// } - -// private static var program:ShaderProgram; -// private static var programPCF:ShaderProgram; -// private static function initMeshProgram(context:Context3D, usePCF:Boolean):ShaderProgram { -// var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); -// vLinker.addProcedure(fullVShader); -// -// var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); -// if (usePCF) { -// fLinker.addProcedure(pcfFShader); -// } else { -// fLinker.addProcedure(fShader); -// } -// -// vLinker.setOppositeLinker(fLinker); -// fLinker.setOppositeLinker(vLinker); -// -//// trace("[VERTEX]"); -//// trace(AgalUtils.disassemble(vLinker.getByteCode())); -//// trace("[FRAGMENT]"); -//// trace(AgalUtils.disassemble(fLinker.getByteCode())); -// -// var result:ShaderProgram; -// if (usePCF) { -// programPCF = new ShaderProgram(vLinker, fLinker); -// result = programPCF; -// } else { -// program = new ShaderProgram(vLinker, fLinker); -// result = program; -// } -// return result; -// } - -// override public function drawShadow(mesh:Mesh, camera:Camera3D, texture:Texture):void { -// var context3d:Context3D = camera.view._context3d; -// -// var linkedProgram:ShaderProgram; -// if (pcfOffset > 0) { -// linkedProgram = (programPCF == null) ? initMeshProgram(context3d, true) : programPCF; -// } else { -// linkedProgram = (program == null) ? initMeshProgram(context3d, false) : program; -// } -// var vLinker:Linker = linkedProgram.vLinker; -// var fLinker:Linker = linkedProgram.fLinker; -// context3d.setProgram(linkedProgram.program); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), mesh.geometry.vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); -// context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, vLinker.getVariableIndex("cPROJ"), mesh.projectionMatrix, true); -// applyShader(context3d, linkedProgram, mesh, camera); -// context3d.setVertexBufferAt(1, null); -// -// context3d.setCulling(Context3DTriangleFace.FRONT); -// context3d.drawTriangles(mesh.geometry.indexBuffer, 0, mesh.geometry.numTriangles); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), null); -// context.setTextureAt(getTextureIndex(fLinker), texture); -// } - - } -} diff --git a/src/alternativa/engine3d/shadows/OmniShadowRenderer.as b/src/alternativa/engine3d/shadows/OmniShadowRenderer.as deleted file mode 100644 index 270ac8f..0000000 --- a/src/alternativa/engine3d/shadows/OmniShadowRenderer.as +++ /dev/null @@ -1,798 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.BoundBox; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.DrawUnit; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.core.Transform3D; - import alternativa.engine3d.core.VertexAttributes; - import alternativa.engine3d.core.View; - import alternativa.engine3d.lights.OmniLight; - import alternativa.engine3d.materials.FillMaterial; - import alternativa.engine3d.materials.ShaderProgram; - import alternativa.engine3d.materials.compiler.Linker; - import alternativa.engine3d.materials.compiler.Procedure; - import alternativa.engine3d.materials.compiler.VariableType; - import alternativa.engine3d.objects.Mesh; - import alternativa.engine3d.objects.Surface; - import alternativa.engine3d.primitives.GeoSphere; - import alternativa.engine3d.resources.Geometry; - - import flash.display3D.Context3D; - import flash.display3D.Context3DProgramType; - import flash.display3D.Context3DTextureFormat; - import flash.display3D.Context3DTriangleFace; - import flash.display3D.Program3D; - import flash.display3D.textures.CubeTexture; - import flash.geom.Vector3D; - - use namespace alternativa3d; - - /** - * @private - */ - public class OmniShadowRenderer extends ShadowRenderer { - -// [Embed("geosphere.A3D", mimeType="application/octet-stream")] private static const ModelClass:Class; - private static const debugGeometry:Geometry = createDebugGeometry(); - private static function createDebugGeometry():Geometry { -// var parser:ParserA3D = new ParserA3D(); -// parser.parse(new ModelClass()); -// var mesh:Mesh = Mesh(parser.getObjectByName("sphere")); -// return mesh.geometry; - var geo:GeoSphere = new GeoSphere(0.5, 4); - return geo.geometry; - } - - private var caster:Object3D; - private var casterBounds:BoundBox = new BoundBox(); - - private var pcfOffset:Number = 0; - - private var context:Context3D; - - public var omnies:Vector.; - - private var shadowMap:CubeTexture; - private var shadowMapSize:int; - private var cameras:Vector. = new Vector.(); - private var clearBits:uint = 0xFF; - - private var currentOmni:OmniLight = new OmniLight(0, 0, 0); - - private static const constants:Vector. = Vector.([ - 255, 0.97, 10000, 1/255 - ]); - private static const offset:Number = 0.005; - private static const pcfOffsets:Vector. = Vector.([ - -offset, -offset, -offset, 1/8, - -offset, -offset, offset, 1, - -offset, offset, -offset, 1, - -offset, offset, offset, 1, - offset, -offset, -offset, 1, - offset, -offset, offset, 1, - offset, offset, -offset, 1, - offset, offset, offset, 1, - ]); - - public function OmniShadowRenderer(context:Context3D, size:int, pcfSize:Number = 0) { - this.context = context; - this.pcfOffset = pcfSize; - shadowMapSize = size; - shadowMap = context.createCubeTexture(size, Context3DTextureFormat.BGRA, true); - debugGeometry.upload(context); - - for (var i:int = 0; i < 6; i++) { - var cam:Camera3D = new Camera3D(1, 100); - cam.fov = 1.910633237; - cam.view = new View(size, size); - cameras[i] = cam; - } - // Left - cameras[1].rotationY = -Math.PI/2; - cameras[1].scaleY = -1; - // Right - cameras[0].rotationY = Math.PI/2; - cameras[0].scaleY = -1; - // Back - cameras[3].rotationX = -Math.PI/2; - cameras[3].rotationZ = Math.PI; - cameras[3].scaleX = -1; - // Front - cameras[2].rotationX = -Math.PI/2; - cameras[2].scaleY = -1; - // Bottom - cameras[5].rotationX = Math.PI; - cameras[5].scaleX = -1; - // Top - cameras[4].rotationX = 0; - cameras[4].scaleY = -1; - } - - alternativa3d override function cullReciever(boundBox:BoundBox, object:Object3D):Boolean { -// tempBounds.reset(); -// object.localToCameraTransform.copy(object.localToGlobalTransform); -// StaticShadowRenderer.calculateBoundBox(tempBounds, object, false); - var bounds:BoundBox = object.boundBox; - object.globalToLocalTransform.copy(object.localToGlobalTransform); - object.globalToLocalTransform.invert(); - var inverseMatrix:Transform3D = object.globalToLocalTransform; - -// trace(object.scaleX, object.scaleY, object.scaleZ); - var ox:Number = inverseMatrix.a*currentOmni._x + inverseMatrix.b*currentOmni._y + inverseMatrix.c*currentOmni._z + inverseMatrix.d; - var oy:Number = inverseMatrix.e*currentOmni._x + inverseMatrix.f*currentOmni._y + inverseMatrix.g*currentOmni._z + inverseMatrix.h; - var oz:Number = inverseMatrix.i*currentOmni._x + inverseMatrix.j*currentOmni._y + inverseMatrix.k*currentOmni._z + inverseMatrix.l; - var radius:Number = currentOmni.attenuationEnd; - if (ox + radius > bounds.minX && ox - radius < bounds.maxX && oy + radius > bounds.minY && oy - radius < bounds.maxY && oz + radius > bounds.minZ && oz - radius < bounds.maxZ) { - return true; - } - return false; - } - - alternativa3d override function get needMultiplyBlend():Boolean { - return true; - } - - public var debugObject:Mesh = new Mesh(); - // TODO: repair -// private var debugMaterial:OmniShadowRendererDebugMaterial = new OmniShadowRendererDebugMaterial(); - private var debugMaterial:Object; - - public function setCaster(object:Object3D):void { - caster = object; - object.localToCameraTransform.identity(); - StaticShadowRenderer.calculateBoundBox(casterBounds, object); - - debugObject.geometry = debugGeometry; -// debugObject.addSurface(debugMaterial, 0, debugGeometry.numTriangles); - debugObject.addSurface(new FillMaterial(0xFFFFFF), 0, debugGeometry.numTriangles); - debugObject.scaleX = 400; - debugObject.scaleY = 400; - debugObject.scaleZ = 400; - } - - private var culledOmnies:Vector. = new Vector.(); - - private var influences:Vector. = new Vector.(); - private static const inverseMatrix:Transform3D = new Transform3D(); - -// private static const omniLocalCoords:Vector. = new Vector.(3); - - override public function update():void { - // Расчет матрицы объекта - caster.localToGlobalTransform.compose(caster._x, caster._y, caster._z, caster._rotationX, caster._rotationY, caster._rotationZ, caster._scaleX, caster._scaleY, caster._scaleZ); - var root:Object3D = caster; - while (root._parent != null) { - root = root._parent; - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); - caster.localToGlobalTransform.append(root.localToGlobalTransform); - } - // Расчет матрицы перевода в объект - caster.globalToLocalTransform.copy(caster.localToGlobalTransform); - caster.globalToLocalTransform.invert(); - -/** -// // Вычисление множителя масштаба -// caster.inverseCameraMatrix.transformVectors(sIn, sOut); -// var dx:Number = sOut[0] - sOut[3]; -// var dy:Number = sOut[1] - sOut[4]; -// var dz:Number = sOut[2] - sOut[5]; -// var scale:Number = Math.sqrt(dx*dx + dy*dy + dz*dz);*/ - -// var selectedOmni:OmniLight; -// var selectedOmniInfluence:Number = -1; - var influenceSum:Number = 0; - - var omni:OmniLight; - - culledOmnies.length = 0; - influences.length = 0; - // Куллинг источников света и нахождение основного - for each (omni in omnies) { - // Вычисление глобальной позиции омника - inverseMatrix.identity(); - var parent:Object3D = omni._parent; - if (parent != null) { - parent.localToGlobalTransform.compose(parent._x, parent._y, parent._z, parent._rotationX, parent._rotationY, parent._rotationZ, parent._scaleX, parent._scaleY, parent._scaleZ); - root = parent; - while (root._parent != null) { - if (root == caster || parent == caster) { - throw new Error("Caster can not be parent of light"); - } - root = root._parent; - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); - parent.localToGlobalTransform.append(root.localToGlobalTransform); - } - inverseMatrix.append(parent.localToGlobalTransform); - } - inverseMatrix.append(caster.globalToLocalTransform); - - var ox:Number = inverseMatrix.a*omni._x + inverseMatrix.b*omni._y + inverseMatrix.c*omni._z + inverseMatrix.d; - var oy:Number = inverseMatrix.e*omni._x + inverseMatrix.f*omni._y + inverseMatrix.g*omni._z + inverseMatrix.h; - var oz:Number = inverseMatrix.i*omni._x + inverseMatrix.j*omni._y + inverseMatrix.k*omni._z + inverseMatrix.l; - - // Использовать описывающий баунд-бокс объекта - // Куллинг - if (ox + omni.attenuationEnd > casterBounds.minX && ox - omni.attenuationEnd < casterBounds.maxX && oy + omni.attenuationEnd > casterBounds.minY && oy - omni.attenuationEnd < casterBounds.maxY && oz + omni.attenuationEnd > casterBounds.minZ && oz - omni.attenuationEnd < casterBounds.maxZ) { - // В зоне действия источника - // Считаем степень влияния - var d:Number = Math.sqrt(ox*ox + oy*oy + oz*oz)/omni.attenuationEnd - 0.1; - var influence:Number; - if (d > 1) { - influence = 0; - } else { - influence = omni.intensity*calcBrightness(omni.color) * (1 - d); - } -// if (influence > selectedOmniInfluence) { -// selectedOmni = omni; -// selectedOmniInfluence = influence; -// } - influenceSum += influence; - influences.push(influence); - culledOmnies.push(omni); - } - } - debugMaterial.texture = null; - - var i:int; - var surface:uint; - var drawed:int = 0; -/** if (selectedOmni == null || influenceSum <= 0) {*/ - if (culledOmnies.length == 0 || influenceSum <= 0) { - // Ни один источник не влияет - for (i = 0; i < 6; i++) { - surface = 1 << i; - if (clearBits & surface) { - context.setRenderToTexture(shadowMap, true, 0, i); -// context.clear(1); - context.clear(1, 1, 1, 1); -// trace("clear", i); - clearBits &= ~surface; - } - } -// trace("INVISIBLE"); - } else { - currentOmni._x = 0; - currentOmni._y = 0; - currentOmni._z = 0; - currentOmni.attenuationEnd = 0; - for (i = 0; i < culledOmnies.length; i++) { - var weight:Number = influences[i]/influenceSum; - omni = culledOmnies[i]; - // Считаем матрицу перевода в глобальное пространство из омника - omni.localToGlobalTransform.identity(); - omni.localToGlobalTransform.d = omni.x; - omni.localToGlobalTransform.h = omni.y; - omni.localToGlobalTransform.l = omni.z; - root = omni; - while (root._parent != null) { - root = root._parent; - if (root.transformChanged) root.composeTransforms(); - omni.localToGlobalTransform.append(root.transform); - } - currentOmni._x += omni.localToGlobalTransform.d*weight; - currentOmni._y += omni.localToGlobalTransform.h*weight; - currentOmni._z += omni.localToGlobalTransform.l*weight; - currentOmni.attenuationEnd += omni.attenuationEnd*weight; - } - currentOmni.localToGlobalTransform.identity(); - currentOmni.localToGlobalTransform.d = currentOmni._x; - currentOmni.localToGlobalTransform.h = currentOmni._y; - currentOmni.localToGlobalTransform.l = currentOmni._z; - -// constants[3] = 0.5*1/255; - constants[3] = 1.0/255; -/** // Расчитываем яркость тени -// var weight:Number = (selectedOmniInfluence > 0) ? 1 - (influenceSum - selectedOmniInfluence)/influenceSum : 0; -// trace(weight, influenceSum, selectedOmniInfluence); -// trace(weight); -// var weight:Number = 1; -// if (weight > 0) { -// constants[3] = (1 + (1 - weight)*5)/255; -// } else { -// constants[3] = 1/255; -// } -// // Считаем матрицу перевода в глобальное пространство из омника -// selectedOmni.cameraMatrix.identity(); -// selectedOmni.cameraMatrix.appendTranslation(selectedOmni.x, selectedOmni.y, selectedOmni.z); -//// selectedOmni.composeMatrix(); -// root = selectedOmni; -// while (root._parent != null) { -// root = root._parent; -// root.composeMatrix(); -// selectedOmni.cameraMatrix.append(root.cameraMatrix); -// } -//// // Матрица родителя уже посчитана -//// if (omni._parent != null) { -//// omni.cameraMatrix.append(omni._parent.cameraMatrix); -//// } -// selectedOmni.globalCoords[0] = 0; -// selectedOmni.globalCoords[1] = 0; -// selectedOmni.globalCoords[2] = 0; -// selectedOmni.cameraMatrix.transformVectors(selectedOmni.globalCoords, selectedOmni.globalCoords); */ - // Записываем параметры омника в константы - - debugObject.x = currentOmni._x; - debugObject.y = currentOmni._y; - debugObject.z = currentOmni._z; - - cleanContext(context); - for (i = 0; i < 6; i++) { - surface = 1 << i; - context.setRenderToTexture(shadowMap, true, 0, i); -// trace("SIDE:", i); - if (renderToOmniShadowMap(currentOmni, cameras[i])) { - drawed++; - clearBits |= surface; - } else { - if (clearBits & surface) { -// trace("clear", i); - context.clear(1, 1, 1, 1); -// context.clear(1, 1, 1, 1); - clearBits &= ~surface; - } - } - } -// trace("NUMSIDES:", drawed); - debugMaterial.texture = shadowMap; - } - context.setRenderToBackBuffer(); - cleanContext(context); - active = drawed > 0; - } - - private function calcBrightness(color:uint):Number { - var r:uint = color & 0xFF; - var g:uint = (color >> 8) & 0xFF; - var b:uint = (color >> 16) & 0xFF; - var result:uint = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b); - return result/255; - } - -// private var axises:Vector. = Vector.([ -// 1, 0, 0, -// 0, 1, 0, -// ]); -// private var globalAxises:Vector. = new Vector.(6); - - public function renderToOmniShadowMap(omni:OmniLight, camera:Camera3D):Boolean { - camera.nearClipping = 1; - camera.farClipping = omni.attenuationEnd; - // Расчёт параметров проецирования - camera.calculateProjection(camera.view._width, camera.view._height); - - if (camera.transformChanged) camera.composeTransforms(); - // Считаем омник родительским объектом камеры - camera.localToGlobalTransform.combine(omni.localToGlobalTransform, camera.transform); - camera.globalToLocalTransform.copy(camera.localToGlobalTransform); - camera.globalToLocalTransform.invert(); - - caster.localToCameraTransform.compose(caster._x, caster._y, caster._z, caster._rotationX, caster._rotationY, caster._rotationZ, caster._scaleX, caster._scaleY, caster._scaleZ); - var root:Object3D = caster; - while (root._parent != null) { - root = root._parent; - if (root.transformChanged) root.composeTransforms(); - caster.localToCameraTransform.append(root.transform); - } - caster.localToCameraTransform.append(camera.globalToLocalTransform); - -/** if (pcfOffset > 0.1) { -// axises[0] = pcfOffset; -// // Считаем преобразования PCF -// camera.globalMatrix.transformVectors(axises, globalAxises); -// pcfOffsets[0] = -pcfOffset*globalAxises[0]; -// pcfOffsets[1] = -pcfOffset*globalAxises[1]; -// pcfOffsets[2] = -pcfOffset*globalAxises[2]; -// pcfOffsets[4] = pcfOffset*globalAxises[0]; -// pcfOffsets[5] = pcfOffset*globalAxises[1]; -// pcfOffsets[6] = pcfOffset*globalAxises[2]; -// pcfOffsets[8] = -pcfOffset*globalAxises[3]; -// pcfOffsets[9] = -pcfOffset*globalAxises[4]; -// pcfOffsets[10] = -pcfOffset*globalAxises[5]; -// pcfOffsets[12] = pcfOffset*globalAxises[3]; -// pcfOffsets[13] = pcfOffset*globalAxises[4]; -// pcfOffsets[14] = pcfOffset*globalAxises[5]; - } */ - - // Отрисовка в шедоумапу - if (cullingInCamera(caster, casterBounds)) { - context.clear(1, 1, 0, 1); - drawObjectToShadowMap(context, caster, camera); - return true; - } - return false; - } - - private static const points:Vector. = Vector.([ - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D() - ]); - private static const boundVertices:Vector. = new Vector.(24); - alternativa3d function cullingInCamera(object:Object3D, objectBounds:BoundBox):Boolean { - var i:int; - var infront:Boolean; - var behind:Boolean; - // Заполнение - var point:Vector3D; - var bb:BoundBox = objectBounds; - point = points[0]; - point.x = bb.minX; - point.y = bb.minY; - point.z = bb.minZ; - point = points[1]; - point.x = bb.minX; - point.y = bb.minY; - point.z = bb.maxZ; - point = points[2]; - point.x = bb.minX; - point.y = bb.maxY; - point.z = bb.minZ; - point = points[3]; - point.x = bb.minX; - point.y = bb.maxY; - point.z = bb.maxZ; - point = points[4]; - point.x = bb.maxX; - point.y = bb.minY; - point.z = bb.minZ; - point = points[5]; - point.x = bb.maxX; - point.y = bb.minY; - point.z = bb.maxZ; - point = points[6]; - point.x = bb.maxX; - point.y = bb.maxY; - point.z = bb.minZ; - point = points[7]; - point.x = bb.maxX; - point.y = bb.maxY; - point.z = bb.maxZ; - // Коррекция под 90 градусов - var transform:Transform3D = object.localToCameraTransform; - for (i = 0; i < 8; i++) { - point = points[i]; - var x:Number = transform.a*point.x + transform.b*point.y + transform.c*point.z + transform.d; - var y:Number = transform.e*point.x + transform.f*point.y + transform.g*point.z + transform.h; - var z:Number = transform.i*point.x + transform.j*point.y + transform.k*point.z + transform.l; - var index:int = 3*i; - boundVertices[int(index++)] = x; - boundVertices[int(index++)] = y; - boundVertices[index] = z; - } - - // Куллинг - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { - if (-boundVertices[i] < boundVertices[int(i + 2)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("L", infront); - if (!infront) return false; - } - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { - if (boundVertices[i] < boundVertices[int(i + 2)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("R", infront); - if (!infront) return false; - } - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { - if (-boundVertices[i] < boundVertices[int(i + 1)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("U", infront); - if (!infront) return false; - } - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { - if (boundVertices[i] < boundVertices[int(i + 1)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("D", infront); - if (!infront) return false; - } - return true; - } - - alternativa3d static function drawObjectToShadowMap(context:Context3D, object:Object3D, camera:Camera3D):void { - if (object is Mesh) { - drawMeshToShadowMap(context, Mesh(object), camera); - } - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - if (child.visible) { - if (child.transformChanged) child.composeTransforms(); - child.localToCameraTransform.combine(object.localToCameraTransform, child.transform); - drawObjectToShadowMap(context, child, camera); - } - } - } - - private static function copyRawFromTransform(raw:Vector., transform:Transform3D):void { - raw[0] = transform.a; - raw[1] = transform.b; - raw[2] = transform.c; - raw[3] = transform.d; - raw[4] = transform.e; - raw[5] = transform.f; - raw[6] = transform.g; - raw[7] = transform.h; - raw[8] = transform.i; - raw[9] = transform.j; - raw[10] = transform.k; - raw[11] = transform.l; - raw[12] = 0; - raw[13] = 0; - raw[14] = 0; - raw[15] = 1; - } - - private static var shadowMapProgram:Program3D; - private static var projectionVector:Vector. = new Vector.(16); - private static function drawMeshToShadowMap(context:Context3D, mesh:Mesh, camera:Camera3D):void { - if (mesh.geometry == null || mesh.geometry.numTriangles == 0 || !mesh.geometry.isUploaded) { - return; - } - - // TODO : update to new logic - if (shadowMapProgram == null) shadowMapProgram = initMeshToShadowMapProgram(context); - context.setProgram(shadowMapProgram); - - context.setVertexBufferAt(0, mesh.geometry.getVertexBuffer(VertexAttributes.POSITION), mesh.geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]); - - // TODO: uncomment -// camera.composeProjectionMatrix(projectionVector, 0, mesh.localToCameraTransform); - - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 0, projectionVector, 4); - - copyRawFromTransform(projectionVector, mesh.localToCameraTransform); - - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, projectionVector, 4); - - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 8, Vector.([Math.sqrt(255)/camera.farClipping, 0, 0, 1])); - context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.([1/255, 0, 0, 1])); - - context.setCulling(Context3DTriangleFace.BACK); - for (var i:int = 0; i < mesh._surfacesLength; i++) { - var surface:Surface = mesh._surfaces[i]; - if (surface.material == null) continue; - context.drawTriangles(mesh.geometry._indexBuffer, surface.indexBegin, surface.numTriangles); - } - context.setVertexBufferAt(0, null); - } - - private static function initMeshToShadowMapProgram(context3d:Context3D):Program3D { - var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); - var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); - var proc:Procedure = Procedure.compileFromArray([ - "#a0=a0", - "#c8=c8", - "#v0=v0", - "m44 o0, a0, c0", - "m44 t0, a0, c4", - "mul t0, t0, c8.x", - "mov v0, t0" - ]); - proc.assignVariableName(VariableType.CONSTANT, 0, "c0", 4); - proc.assignVariableName(VariableType.CONSTANT, 4, "c4", 4); - vLinker.addProcedure(proc); - - fLinker.addProcedure(Procedure.compileFromArray([ - "#v0=v0", - "#c0=c0", - "mov t0.zw, c0.z \n", - "dp3 t1.w, v0.xyz, v0.xyz \n", - "frc t0.y, t1.w", - "sub t0.x, t1.w, t0.y", - "mul t0.x, t0.x, c0.x", - "mov o0, to" - ])); - var program:Program3D = context3d.createProgram(); -// trace("VERTEX"); -// trace(A3DUtils.disassemble(vLinker.getByteCode())); -// trace("FRAGMENT"); -// trace(A3DUtils.disassemble(fLinker.getByteCode())); - fLinker.varyings = vLinker.varyings; - vLinker.link(); - fLinker.link(); - program.upload(vLinker.data, fLinker.data); - return program; - } - - private static function initVShader():Procedure { - var shader:Procedure = Procedure.compileFromArray([ - // Координата вершины в глобальном пространстве - "m44 v0, a0, c0" - ]); - shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPosition"); - shader.assignVariableName(VariableType.CONSTANT, 0, "cGLOBALMATRIX", 4); - shader.assignVariableName(VariableType.VARYING, 0, "vPOSITION"); - return shader; - } - - private static function initFShader(mult:Boolean, usePCF:Boolean):Procedure { - var line:int = 0; - var shaderArr:Array = []; - var numPass:uint = (usePCF) ? 8 : 1; - for (var i:int = 0; i < numPass; i++) { - // Вектор от источника света к точке - shaderArr[line++] = "sub t0.xyz, v0.xyz, c4.xyz"; - - // Квадрат расстояния - shaderArr[line++] = "dp3 t0.w, t0.xyz, t0.xyz"; - shaderArr[line++] = "mul t0.w, t0.w, c4.w"; // * (255 / radius^2) - shaderArr[line++] = "mul t0.w, t0.w, c5.y"; // bias [0.95] - - // Квадрат расстояния из карты теней - shaderArr[line++] = "nrm t0.xyz, t0.xyz"; - - if (usePCF) { - shaderArr[line++] = "add t0.xyz, t0.xyz, c" + (i + 6).toString(); - } - - shaderArr[line++] = "tex t1, t0, s0 "; - shaderArr[line++] = "mov t3, t1"; - shaderArr[line++] = "mul t1.w, t1.x, c5.x"; // 255 - shaderArr[line++] = "add t1.w, t1.w, t1.y"; - - // Перекрытие тенью - shaderArr[line++] = "sub t2.z, t1.w, t0.w"; - shaderArr[line++] = "mul t2.z, t2.z, c5.z"; // smooth [10000] - shaderArr[line++] = "sat t2.z, t2.z"; - -// // Затухание тени по расстоянию - shaderArr[line++] = "mul t1.x, t0.w, c5.w"; // div 255 - shaderArr[line++] = "add t2.z, t2.z, t1.x"; - if (i == 0) { - shaderArr[line++] = "sat t2.x, t2.z"; - } else { - shaderArr[line++] = "sat t2.z, t2.z"; - shaderArr[line++] = "add t2.x, t2.x, t2.z"; - } - } - if (usePCF) { - shaderArr[line++] = "mul t2.x, t2.x, c6.w"; - } - if (mult) { - shaderArr.push("mul t0.xyz, i0.xyz, t2.x"); -// shaderArr.push("mul t0.xyz, t1.w, c5.w"); - shaderArr.push("mov t0.w, i0.w"); - shaderArr.push("mov o0, t0"); - } else { - shaderArr.push("mov o0, t2.xxxx"); - } - var shader:Procedure = Procedure.compileFromArray(shaderArr, "OmniShadowMap"); - shader.assignVariableName(VariableType.VARYING, 0, "vPOSITION"); - shader.assignVariableName(VariableType.CONSTANT, 4, "cOmni", 1); - shader.assignVariableName(VariableType.CONSTANT, 5, "cConstants", 1); - if (usePCF) { - shader.assignVariableName(VariableType.CONSTANT, 6, "cPCF0", 1); - shader.assignVariableName(VariableType.CONSTANT, 7, "cPCF1", 1); - shader.assignVariableName(VariableType.CONSTANT, 8, "cPCF2", 1); - shader.assignVariableName(VariableType.CONSTANT, 9, "cPCF3", 1); - shader.assignVariableName(VariableType.CONSTANT, 10, "cPCF4", 1); - shader.assignVariableName(VariableType.CONSTANT, 11, "cPCF5", 1); - shader.assignVariableName(VariableType.CONSTANT, 12, "cPCF6", 1); - shader.assignVariableName(VariableType.CONSTANT, 13, "cPCF7", 1); - } - shader.assignVariableName(VariableType.SAMPLER, 0, "sCUBE"); - return shader; - } - - override public function getVShader(index:int = 0):Procedure { - return initVShader(); - } - - override public function getFShader(index:int = 0):Procedure { - return initFShader(false, pcfOffset > 0); - } - - private static const globalMatrix:Transform3D = new Transform3D(); - override public function applyShader(drawUnit:DrawUnit, program:ShaderProgram, object:Object3D, camera:Camera3D, index:int = 0):void { - var fLinker:Linker = program.fragmentShader; - - globalMatrix.combine(camera.localToGlobalTransform, object.localToCameraTransform); - - var mIndex:int = program.vertexShader.getVariableIndex("cGLOBALMATRIX"); - drawUnit.setVertexConstantsFromNumbers(mIndex, globalMatrix.a, globalMatrix.b, globalMatrix.c, globalMatrix.d); - drawUnit.setVertexConstantsFromNumbers(mIndex+1, globalMatrix.e, globalMatrix.f, globalMatrix.g, globalMatrix.h); - drawUnit.setVertexConstantsFromNumbers(mIndex+2, globalMatrix.i, globalMatrix.j, globalMatrix.k, globalMatrix.l); - drawUnit.setVertexConstantsFromNumbers(mIndex+3, 0, 0, 0, 1); - -// destination.addFragmentConstantSet(fLinker.getVariableIndex("cOmni"), omniPos, 1); - drawUnit.setFragmentConstantsFromNumbers(fLinker.getVariableIndex("cOmni"), currentOmni._x, currentOmni._y, currentOmni._z, 255/currentOmni.attenuationEnd/currentOmni.attenuationEnd); - drawUnit.setFragmentConstantsFromVector(fLinker.getVariableIndex("cConstants"), constants, 1); - if (pcfOffset > 0) { - drawUnit.setVertexConstantsFromVector(fLinker.getVariableIndex("cPCF0"), pcfOffsets, 8); - } - drawUnit.setTextureAt(fLinker.getVariableIndex("sCUBE"), shadowMap); - } - -// private static var program:LinkedProgram; -// private static var programPCF:LinkedProgram; -// private static function initMeshProgram(context:Context3D, usePCF:Boolean):LinkedProgram { -// var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); -// vLinker.addShader(vShader); -// -// var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); -// if (usePCF) { -// fLinker.addShader(pcfFShader); -// } else { -// fLinker.addShader(fShader); -// } -// -// vLinker.setOppositeLinker(fLinker); -// fLinker.setOppositeLinker(vLinker); -// -// trace("[VERTEX]"); -// trace(AgalUtils.disassemble(vLinker.getByteCode())); -// trace("[FRAGMENT]"); -// trace(AgalUtils.disassemble(fLinker.getByteCode())); -// -// var result:LinkedProgram; -// if (usePCF) { -// programPCF = new LinkedProgram(); -// result = programPCF; -// } else { -// program = new LinkedProgram(); -// result = program; -// } -// result.vLinker = vLinker; -// result.fLinker = fLinker; -// result.program = context.createProgram(); -// result.program.upload(vLinker.getByteCode(), fLinker.getByteCode()); -// -// return result; -// } -// -// override public function drawShadow(mesh:Mesh, camera:Camera3D, texture:Texture):void { -// var context3d:Context3D = camera.view._context3d; -// -// var linkedProgram:LinkedProgram; -// if (pcfOffset > 0) { -// linkedProgram = (programPCF == null) ? initMeshProgram(context3d, true) : programPCF; -// } else { -// linkedProgram = (program == null) ? initMeshProgram(context3d, false) : program; -// } -// var vLinker:Linker = linkedProgram.vLinker; -// var fLinker:Linker = linkedProgram.fLinker; -// context3d.setProgram(linkedProgram.program); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), mesh.geometry.vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); -// context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, vLinker.getVariableIndex("cPROJ"), mesh.projectionMatrix, true); -// applyShader(context3d, linkedProgram, mesh, camera); -// context3d.setVertexBufferAt(1, null); -// -// context3d.setCulling(Context3DTriangleFace.FRONT); -// context3d.drawTriangles(mesh.geometry.indexBuffer, 0, mesh.geometry.numTriangles); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), null); -// context.setTextureAt(getTextureIndex(fLinker), texture); -// } - - } -} diff --git a/src/alternativa/engine3d/shadows/OmniShadowRendererDebugMaterial.as b/src/alternativa/engine3d/shadows/OmniShadowRendererDebugMaterial.as deleted file mode 100644 index 6dfd11a..0000000 --- a/src/alternativa/engine3d/shadows/OmniShadowRendererDebugMaterial.as +++ /dev/null @@ -1,162 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.Light3D; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.materials.*; - import alternativa.engine3d.materials.compiler.Linker; - import alternativa.engine3d.materials.compiler.Procedure; - import alternativa.engine3d.materials.compiler.VariableType; - import alternativa.engine3d.objects.Surface; - import alternativa.engine3d.resources.Geometry; - - import flash.display3D.Context3DProgramType; - import flash.display3D.textures.CubeTexture; - import flash.utils.Dictionary; - - use namespace alternativa3d; - - /** - * @private - */ - public class OmniShadowRendererDebugMaterial extends Material { - - alternativa3d override function get canDrawInShadowMap():Boolean { - return false; - } - - static alternativa3d const _samplerSetProcedure:Procedure = new Procedure( - [ - "#v0=vUV", - "#s0=sTexture", - "#c0=cAlpha", - "tex t0, v0, s0 ", - "mov t0.w, c0.w", - "mov o0, t0" - ]); - - static alternativa3d const _samplerSetProcedureDiffuseAlpha:Procedure = new Procedure( - [ - "#v0=vUV", - "#s0=sTexture", - "#c0=cAlpha", - "tex t0, v0, s0 ", - "mul t0.w, t0.w, c0.w", - "mov o0, t0" - ]); - - static alternativa3d const _passUVProcedure:Procedure = new Procedure(["#v0=vUV", "#a0=aNORMAL", "mov v0, a0"]); - private static var _programs:Dictionary = new Dictionary(); - /** - * Текстура - */ - public var texture:CubeTexture; - /** - * Прозрачность - */ - public var alpha:Number = 1; - /** - * Использование alpha канала текстуры - */ - public var useDiffuseAlphaChannel:Boolean = false; - - /** - * Создает экземпляр материала - * @param texture текстура - * @param alpha прозрачность - */ - public function OmniShadowRendererDebugMaterial(texture:CubeTexture = null, alpha:Number = 1) { - this.texture = texture; - this.alpha = alpha; - } - - private function setupProgram(targetObject:Object3D):Vector. { - var optionsPrograms:Vector. = new Vector.(); - - var vertexLinker:Linker = new Linker(Context3DProgramType.VERTEX); - var positionVar:String = "aPosition"; - vertexLinker.declareVariable(positionVar, VariableType.ATTRIBUTE); - if (targetObject.transformProcedure != null) { - positionVar = appendPositionTransformProcedure(targetObject.transformProcedure, vertexLinker); - } - vertexLinker.addProcedure(_projectProcedure); - vertexLinker.setInputParams(_projectProcedure, positionVar); - vertexLinker.addProcedure(_passUVProcedure); - vertexLinker.link(); - - var fragmentLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); - fragmentLinker.addProcedure(_samplerSetProcedure); - fragmentLinker.varyings = vertexLinker.varyings; - optionsPrograms[optionsPrograms.length] = new ShaderProgram(vertexLinker, fragmentLinker); - - var fragmentLinkerDiffuseAlpha:Linker = new Linker(Context3DProgramType.FRAGMENT); - fragmentLinkerDiffuseAlpha.addProcedure(_samplerSetProcedureDiffuseAlpha); - fragmentLinkerDiffuseAlpha.varyings = vertexLinker.varyings; - optionsPrograms[optionsPrograms.length] = new ShaderProgram(vertexLinker, fragmentLinkerDiffuseAlpha); - -// trace(A3DUtils.disassemble(fragmentLinker.getByteCode())); - - _programs[targetObject.transformProcedure] = optionsPrograms; - return optionsPrograms; - } - - /** - * @private - */ - override alternativa3d function collectDraws(camera:Camera3D, surface:Surface, geometry:Geometry, lights:Vector., lightsLength:int, objectRenderPriority:int = -1):void { - // TODO: repair - /* - destination.isValid = destination.isValid && texture != null; - - var optionsPrograms:Vector. = _programs[transformHolder.transformProcedure]; - if(!optionsPrograms) optionsPrograms = setupProgram(transformHolder); - var program:ShaderProgram; - if(!useDiffuseAlphaChannel){ - program = optionsPrograms[0]; - }else { - program = optionsPrograms[1]; - } - - if (!destination.isValid) { - return; - } - - if (alpha < 1 || useDiffuseAlphaChannel) { - destination.blendModeSource = Context3DBlendFactor.SOURCE_ALPHA; - destination.blendModeDestination = Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA; - destination.renderPriority = Renderer.TRANSPARENT_SORT; - } else { - destination.blendModeSource = Context3DBlendFactor.ONE; - destination.blendModeDestination = Context3DBlendFactor.ZERO; - destination.renderPriority = Renderer.OPAQUE; - } - - destination.program = program; - geometry.setAttribute(destination, VertexAttributes.POSITION, program.vertexShader.getVariableIndex("aPosition")); - geometry.setAttribute(destination, VertexAttributes.NORMAL, program.vertexShader.getVariableIndex("aNORMAL")); - camera.composeProjectionMatrix(destination.constantSetVertexVectorValues, program.vertexShader.getVariableIndex("cProjMatrix") << 2, transformHolder.localToCameraTransform); - destination.constantSetVertexRegistersCount = destination.constantSetVertexVectorValues.length >> 2; - destination.addTextureSet(program.fragmentShader.getVariableIndex("sTexture"), texture); - destination.addFragmentConstantVector(program.fragmentShader.getVariableIndex("cAlpha"), 0, 0, 0, alpha); - destination.cullingMode = cullingMode; - */ - } - - /** - * @inheritDoc - */ - override public function clone():Material { - var res:OmniShadowRendererDebugMaterial = new OmniShadowRendererDebugMaterial(texture, alpha); - res.clonePropertiesFrom(this); - return res; - } - - override protected function clonePropertiesFrom(source:Material):void { - super.clonePropertiesFrom(source); - var t:OmniShadowRendererDebugMaterial = OmniShadowRendererDebugMaterial(source); - texture = t.texture; - alpha = t.alpha; - } - } -} diff --git a/src/alternativa/engine3d/shadows/ShadowRenderer.as b/src/alternativa/engine3d/shadows/ShadowRenderer.as deleted file mode 100644 index 5c7b712..0000000 --- a/src/alternativa/engine3d/shadows/ShadowRenderer.as +++ /dev/null @@ -1,184 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.BoundBox; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.DrawUnit; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.materials.ShaderProgram; - import alternativa.engine3d.materials.compiler.Procedure; - - import flash.display3D.Context3D; - import flash.display3D.Context3DBlendFactor; - import flash.display3D.Context3DCompareMode; - import flash.geom.Matrix3D; - - use namespace alternativa3d; - - /** - * @private - */ - public class ShadowRenderer { - - alternativa3d var shaderKey:String; - private static var counter:int = 0; - - public var active:Boolean = false; - - public function ShadowRenderer() { - counter++; - shaderKey = "M" + counter.toString(); - } - - alternativa3d function get needMultiplyBlend():Boolean { - return false; - } - - public function update():void {} - - // Нет входных, выходных параметров - public function getVShader(index:int = 0):Procedure {return null} - public function getFShader(index:int = 0):Procedure {return null} - - public function getFIntensityShader():Procedure { throw new Error("Not implemented") }; - -// public function getMultVShader():Procedure {return null}; -// // i0 - input color -// // o0 - shadowed result -// public function getMultFShader():Procedure {return null}; - - public function applyShader(destination:DrawUnit, program:ShaderProgram, object:Object3D, camera:Camera3D, index:int = 0):void {} -// public function drawShadow(mesh:Mesh, camera:Camera3D, texture:Texture):void {} - -// public function getTextureIndex(fLinker:Linker):int {return 0}; - - public function get debug():Boolean { return false } - public function set debug(value:Boolean):void { } - - alternativa3d function cullReciever(boundBox:BoundBox, object:Object3D):Boolean { - return false; - } - - protected function cleanContext(context:Context3D):void { - context.setTextureAt(0, null); - context.setTextureAt(1, null); - context.setTextureAt(2, null); - context.setTextureAt(3, null); - context.setTextureAt(4, null); - context.setTextureAt(5, null); - context.setTextureAt(6, null); - context.setTextureAt(7, null); - context.setVertexBufferAt(1, null); - context.setVertexBufferAt(2, null); - context.setVertexBufferAt(3, null); - context.setVertexBufferAt(4, null); - context.setVertexBufferAt(5, null); - context.setVertexBufferAt(6, null); - context.setVertexBufferAt(7, null); - context.setDepthTest(true, Context3DCompareMode.LESS); - context.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ZERO); - } - - static private const boundVertices:Vector. = new Vector.(24); - alternativa3d function cullObjectImplementation(bounds:BoundBox, matrix:Matrix3D):Boolean { - var i:int; - var infront:Boolean; - var behind:Boolean; - // Заполнение - boundVertices[0] = bounds.minX; - boundVertices[1] = bounds.minY; - boundVertices[2] = bounds.minZ; - boundVertices[3] = bounds.maxX; - boundVertices[4] = bounds.minY; - boundVertices[5] = bounds.minZ; - boundVertices[6] = bounds.minX; - boundVertices[7] = bounds.maxY; - boundVertices[8] = bounds.minZ; - boundVertices[9] = bounds.maxX; - boundVertices[10] = bounds.maxY; - boundVertices[11] = bounds.minZ; - boundVertices[12] = bounds.minX; - boundVertices[13] = bounds.minY; - boundVertices[14] = bounds.maxZ; - boundVertices[15] = bounds.maxX; - boundVertices[16] = bounds.minY; - boundVertices[17] = bounds.maxZ; - boundVertices[18] = bounds.minX; - boundVertices[19] = bounds.maxY; - boundVertices[20] = bounds.maxZ; - boundVertices[21] = bounds.maxX; - boundVertices[22] = bounds.maxY; - boundVertices[23] = bounds.maxZ; - - // Трансформация в камеру - matrix.transformVectors(boundVertices, boundVertices); - // Куллинг - for (i = 2, infront = false, behind = false; i <= 23; i += 3) { - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - if (!infront) return false; - } - // left - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - if (!infront) return false; - } - // right - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { - if (boundVertices[i] < 1) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - if (!infront) return false; - } - // up - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - if (!infront) return false; - } - // down - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { - if (boundVertices[i] < 1) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - if (!infront) return false; - } - return true; - } - - } -} diff --git a/src/alternativa/engine3d/shadows/ShadowsSystem.as b/src/alternativa/engine3d/shadows/ShadowsSystem.as deleted file mode 100644 index 0481d04..0000000 --- a/src/alternativa/engine3d/shadows/ShadowsSystem.as +++ /dev/null @@ -1,96 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.Object3D; - - import flash.utils.Dictionary; - - use namespace alternativa3d; - - /** - * @private - */ - public class ShadowsSystem { - - private static const MAX_SHADOWMAPS:int = 3; -// private static const MAX_SHADOWMAPS:int = 4; - - public var renderers:Vector. = new Vector.(); - - private var containers:Dictionary = new Dictionary(); - - public function ShadowsSystem() { - } - - private var numShadowed:int; - - private var numActiveRenderers:int; - private var activeRenderers:Vector. = new Vector.(); - - private var maxShadows:int; - - public function update(root:Object3D):void { - if (renderers.length == 0) return; - numActiveRenderers = 0; - var num:int = renderers.length; - for (var i:int = 0; i < num; i++) { - var renderer:ShadowRenderer = renderers[i]; - renderer.update(); - if (renderer.active) { - activeRenderers[numActiveRenderers] = renderer; - numActiveRenderers++; - } - } - // Пробегаемся иерархически по объектам и проверяем наложение на них тени - if (root.transformChanged) root.composeTransforms(); - root.localToGlobalTransform.copy(root.transform); - numShadowed = 0; - maxShadows = 0; - recursive(root); -// trace("SHADOWED:", numShadowed, ":", maxShadows); - } - - private function recursive(object:Object3D):void { - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - var value:Vector. = null; - var numRenderers:int = 0; - if (child.visible) { - if (child.transformChanged) child.composeTransforms(); - child.localToGlobalTransform.combine(object.localToGlobalTransform, child.transform); - for (var i:int = 0; i < numActiveRenderers; i++) { - var renderer:ShadowRenderer = activeRenderers[i]; - if (child.useShadow) { - if (child.boundBox == null || renderer.cullReciever(child.boundBox, child)) { - numShadowed++; - if (value == null) { - value = containers[child]; - if (value == null) { - value = new Vector.(); - containers[child] = value; - } else { - value.length = 0; - } - } - value[numRenderers] = renderer; - numRenderers++; - } - } - } - recursive(child); - } - setRenderers(child, value, numRenderers); - } - } - - private function setRenderers(object:Object3D, renderers:Vector., numShadowRenderers:int):void { - if (numShadowRenderers > maxShadows) maxShadows = numShadowRenderers; - if (numShadowRenderers > MAX_SHADOWMAPS) { - numShadowRenderers = MAX_SHADOWMAPS; - renderers.length = MAX_SHADOWMAPS; - } - object.shadowRenderers = renderers; - object.numShadowRenderers = numShadowRenderers; - } - - } -} diff --git a/src/alternativa/engine3d/shadows/SpotShadowRenderer.as b/src/alternativa/engine3d/shadows/SpotShadowRenderer.as deleted file mode 100644 index 965e5a1..0000000 --- a/src/alternativa/engine3d/shadows/SpotShadowRenderer.as +++ /dev/null @@ -1,656 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.BoundBox; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.DrawUnit; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.core.Transform3D; - import alternativa.engine3d.core.VertexAttributes; - import alternativa.engine3d.lights.SpotLight; - 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.Mesh; - import alternativa.engine3d.objects.Surface; - import alternativa.engine3d.primitives.Box; - import alternativa.engine3d.resources.TextureResource; - - import flash.display3D.Context3D; - import flash.display3D.Context3DProgramType; - import flash.display3D.Context3DTextureFormat; - import flash.display3D.Context3DTriangleFace; - import flash.display3D.Program3D; - import flash.display3D.textures.Texture; - import flash.geom.Matrix3D; - - use namespace alternativa3d; - - /** - * @private - */ - public class SpotShadowRenderer extends ShadowRenderer { - - public var caster:Object3D; - - private var context:Context3D; - - private var shadowMap:Texture; - - private var light:SpotLight; - - private var debugObject:Mesh; - public var debugMaterial:TextureMaterial = new TextureMaterial(); - private var debugTexture:TextureResource = new TextureResource(); - - private var globalToShadowMap:Matrix3D = new Matrix3D(); - - private static const constants:Vector. = Vector.([ - 255, 255*0.96, 100, 1 - ]); - - private var pcfSize:Number = 0; - private var pcfOffset:Number = 0; - private var pcfOffsets:Vector.; - - public function SpotShadowRenderer(context:Context3D, size:int, pcfSize:Number = 0) { - this.context = context; - this.shadowMap = context.createTexture(size, size, Context3DTextureFormat.BGRA, true); - this.pcfSize = pcfSize; - debugTexture._texture = this.shadowMap; -// debugMaterial.diffuseMap = debugTexture; - debugMaterial.alpha = 0.9; - debugMaterial.opaquePass = false; - debugMaterial.transparentPass = true; - debugMaterial.alphaThreshold = 1.1; - } - - public function setLight(value:SpotLight):void { - light = value; - var width:Number = 2*Math.sin(light.falloff*0.5)*light.attenuationEnd; - this.pcfOffset = pcfSize/width/255; - if (pcfOffset > 0) { - pcfOffsets = Vector.([ - -pcfOffset, -pcfOffset, 0, 1/4, - -pcfOffset, pcfOffset, 0, 1, - pcfOffset, -pcfOffset, 0, 1, - pcfOffset, pcfOffset, 0, 1 - ]); - } - debugObject = new Box(width, width, 1, 1, 1, 1, false, debugMaterial); - debugObject.rotationX = Math.PI; - debugObject.geometry.upload(context); - if (_debug) { - light.addChild(debugObject); - } - } - - private var _debug:Boolean = false; - override public function get debug():Boolean { - return _debug; - } - - override public function set debug(value:Boolean):void { - _debug = value; - if (_debug) { - if (light != null) { - light.addChild(debugObject); - } - } else { - if (debugObject != null && debugObject._parent != null) { - debugObject._parent.removeChild(debugObject); - } - } - } - - private static var matrix:Matrix3D = new Matrix3D(); - override alternativa3d function cullReciever(boundBox:BoundBox, object:Object3D):Boolean { - copyMatrixFromTransform(matrix, object.localToGlobalTransform); - matrix.append(this.globalToShadowMap); - return cullObjectImpl(boundBox, matrix); - } - private function cullCaster(boundBox:BoundBox, objectToGlobal:Transform3D):Boolean { - copyMatrixFromTransform(matrix, objectToGlobal); - matrix.append(this.globalToShadowMap); - return cullObjectImpl(boundBox, matrix, light.attenuationEnd); - } - - private var projection:ProjectionTransform3D = new ProjectionTransform3D(); - private var uvProjection:Matrix3D = new Matrix3D(); - override public function update():void { - // Считаем матрицу перевода в лайт - var root:Object3D; - // Расчитываем матрицу объекта для перевода в глобал - // if (caster.transformChanged) { - caster.localToGlobalTransform.compose(caster._x, caster._y, caster._z, caster._rotationX, caster._rotationY, caster._rotationZ, caster._scaleX, caster._scaleY, caster._scaleZ); - // } else { - // caster.localToCameraTransform.copy(caster.transform); - // } - root = caster; - while (root._parent != null) { - root = root._parent; - // if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); - // } - caster.localToGlobalTransform.append(root.localToGlobalTransform); - } - - // Расчитываем матрицу лайта - light.localToGlobalTransform.compose(light._x, light._y, light._z, light._rotationX, light._rotationY, light._rotationZ, light._scaleX, light._scaleY, light._scaleZ); - root = light; - while (root._parent != null) { - root = root._parent; - // if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); - // } - light.localToGlobalTransform.append(root.localToGlobalTransform); - } - light.globalToLocalTransform.copy(light.localToGlobalTransform); - light.globalToLocalTransform.invert(); - - // Получаем матрицу перевода из объекта в лайт - caster.localToCameraTransform.combine(light.globalToLocalTransform, caster.localToGlobalTransform); -// caster.localToCameraTransform.append(light.globalToLocalTransform); - - // Считаем матрицу проецирования - calculateProjection(projection, uvProjection, light.falloff, 1, light.attenuationEnd); -// globalToShadowMap.copy(light.globalToLocalTransform); - copyMatrixFromTransform(globalToShadowMap, light.globalToLocalTransform); - globalToShadowMap.append(uvProjection); - - debugMaterial.diffuseMap = null; - -// trace("TEST:", testCasterCulling(caster)); - if (!testCasterCulling(caster)) { - active = false; - return; - } - active = true; - - // Рисуем в шедоумапу - context.setRenderToTexture(shadowMap, true, 0, 0); - // context.clear(1); - context.clear(1, 1, 1, 1); - cleanContext(context); - drawObjectToShadowMap(context, caster, projection); - context.setRenderToBackBuffer(); - cleanContext(context); - debugMaterial.diffuseMap = debugTexture; - } - - private function testCasterCulling(object:Object3D):Boolean { - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - if (child.visible) { - if (child.transformChanged) child.composeTransforms(); - child.localToGlobalTransform.combine(object.localToGlobalTransform, child.transform); - if (child.boundBox == null || cullCaster(child.boundBox, child.localToGlobalTransform)) { - return true; - } - if (testCasterCulling(child)) { - return true; - } - } - } - return false; - } - - static private const boundVertices:Vector. = new Vector.(24); - alternativa3d function cullObjectImpl(bounds:BoundBox, matrix:Matrix3D, far:Number = 0):Boolean { - var i:int; - var infront:Boolean; - var behind:Boolean; - // Заполнение - boundVertices[0] = bounds.minX; - boundVertices[1] = bounds.minY; - boundVertices[2] = bounds.minZ; - boundVertices[3] = bounds.maxX; - boundVertices[4] = bounds.minY; - boundVertices[5] = bounds.minZ; - boundVertices[6] = bounds.minX; - boundVertices[7] = bounds.maxY; - boundVertices[8] = bounds.minZ; - boundVertices[9] = bounds.maxX; - boundVertices[10] = bounds.maxY; - boundVertices[11] = bounds.minZ; - boundVertices[12] = bounds.minX; - boundVertices[13] = bounds.minY; - boundVertices[14] = bounds.maxZ; - boundVertices[15] = bounds.maxX; - boundVertices[16] = bounds.minY; - boundVertices[17] = bounds.maxZ; - boundVertices[18] = bounds.minX; - boundVertices[19] = bounds.maxY; - boundVertices[20] = bounds.maxZ; - boundVertices[21] = bounds.maxX; - boundVertices[22] = bounds.maxY; - boundVertices[23] = bounds.maxZ; - - // Трансформация в камеру - matrix.transformVectors(boundVertices, boundVertices); - // Куллинг - // left - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { -// trace("POS", boundVertices[i], boundVertices[int(i + 2)]); - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("L", infront); - if (!infront) return false; - } - // right - for (i = 0, infront = false, behind = false; i <= 21; i += 3) { - if (boundVertices[i] < boundVertices[int(i + 2)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("R", infront); - if (!infront) return false; - } - // up - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { -// if (-boundVertices[i] < boundVertices[int(i + 1)]) { - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("U", infront); - if (!infront) return false; - } - // down - for (i = 1, infront = false, behind = false; i <= 22; i += 3) { - if (boundVertices[i] < boundVertices[int(i + 1)]) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { -// trace("D", infront); - if (!infront) return false; - } - if (far > 0) { - for (i = 2, infront = false, behind = false; i <= 23; i += 3) { - if (boundVertices[i] < far) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - // trace("N", infront); - if (!infront) return false; - } - } - for (i = 2, infront = false, behind = false; i <= 23; i += 3) { - if (boundVertices[i] > 0) { - infront = true; - if (behind) break; - } else { - behind = true; - if (infront) break; - } - } - if (behind) { - // trace("N", infront); - if (!infront) return false; - } - return true; - } - - // должен быть заполнен нулями - private var rawData:Vector. = new Vector.(16); - private var m:Matrix3D = new Matrix3D(); - private function calculateProjection(projection:ProjectionTransform3D, uvProjection:Matrix3D, fov:Number, nearClipping:Number, farClipping:Number):void { - var viewSize:Number = 1; - var focalLength:Number = viewSize/Math.tan(fov*0.5); - projection.m0 = focalLength/viewSize; - projection.m5 = -focalLength/viewSize; - projection.m10 = farClipping/(farClipping - nearClipping); - projection.m14 = -nearClipping*projection.m10; - - for (var i:int = 0; i < 16; i++) { - rawData[i] = 0; - } - - // TODO: предумножить матрицы - - rawData[0] = projection.m0; - rawData[5] = -projection.m5; - rawData[10]= projection.m10; - rawData[11]= 1; - rawData[14]= projection.m14; - uvProjection.rawData = rawData; - -// 0.5f, 0.0f, 0.0f, 0.0f, -// 0.0f, 0.5f, 0.0f, 0.0f, -// 0.0f, 0.0f, 0.5f, 0.0f, -// 0.5f, 0.5f, 0.5f, 1.0f - - rawData[0] = 0.5; - rawData[12] = 0.5; - rawData[5] = 0.5; - rawData[13] = 0.5; - rawData[10] = 0.5; - rawData[14] = 0.5; - rawData[11] = 0; - rawData[15] = 1; - m.rawData = rawData; - uvProjection.append(m); - } - - private var transformToMatrixRawData:Vector. = new Vector.(16); - private function copyMatrixFromTransform(matrix:Matrix3D, transform:Transform3D):void { - transformToMatrixRawData[0] = transform.a; - transformToMatrixRawData[1] = transform.e; - transformToMatrixRawData[2] = transform.i; - transformToMatrixRawData[3] = 0; - transformToMatrixRawData[4] = transform.b; - transformToMatrixRawData[5] = transform.f; - transformToMatrixRawData[6] = transform.j; - transformToMatrixRawData[7] = 0; - transformToMatrixRawData[8] = transform.c; - transformToMatrixRawData[9] = transform.g; - transformToMatrixRawData[10] = transform.k; - transformToMatrixRawData[11] = 0; - transformToMatrixRawData[12] = transform.d; - transformToMatrixRawData[13] = transform.h; - transformToMatrixRawData[14] = transform.l; - transformToMatrixRawData[15] = 1; - matrix.rawData = transformToMatrixRawData; - } - - alternativa3d static function drawObjectToShadowMap(context:Context3D, object:Object3D, projection:ProjectionTransform3D):void { - if (object is Mesh) { - drawMeshToShadowMap(context, Mesh(object), projection); - } - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - if (child.visible) { - if (child.transformChanged) child.composeTransforms(); - child.localToCameraTransform.combine(object.localToCameraTransform, child.transform); - drawObjectToShadowMap(context, child, projection); - } - } - } - - private static var shadowMapProgram:Program3D; - private static var projectionVector:Vector. = new Vector.(16); - private static function drawMeshToShadowMap(context:Context3D, mesh:Mesh, projection:ProjectionTransform3D):void { - if (mesh.geometry == null || mesh.geometry.numTriangles == 0 || !mesh.geometry.isUploaded) { - return; - } - - if (shadowMapProgram == null) shadowMapProgram = initMeshToShadowMapProgram(context); - context.setProgram(shadowMapProgram); - - context.setVertexBufferAt(0, mesh.geometry.getVertexBuffer(VertexAttributes.POSITION), mesh.geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]); - - var transform:Transform3D = mesh.localToCameraTransform; - projectionVector[0] = transform.a*projection.m0; - projectionVector[1] = transform.b*projection.m0; - projectionVector[2] = transform.c*projection.m0; - projectionVector[3] = transform.d*projection.m0; - projectionVector[4] = transform.e*projection.m5; - projectionVector[5] = transform.f*projection.m5; - projectionVector[6] = transform.g*projection.m5; - projectionVector[7] = transform.h*projection.m5; - projectionVector[8] = transform.i*projection.m10; - projectionVector[9] = transform.j*projection.m10; - projectionVector[10] = transform.k*projection.m10; - projectionVector[11] = transform.l*projection.m10 + projection.m14; - projectionVector[12] = transform.i; - projectionVector[13] = transform.j; - projectionVector[14] = transform.k; - projectionVector[15] = transform.l; - - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 0, projectionVector, 4); - context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 4, Vector.([255, 0, 0, 1])); - context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.([1/255, 0, 0, 1])); - - context.setCulling(Context3DTriangleFace.BACK); - for (var i:int = 0; i < mesh._surfacesLength; i++) { - var surface:Surface = mesh._surfaces[i]; - if (surface.material == null) continue; - context.drawTriangles(mesh.geometry._indexBuffer, surface.indexBegin, surface.numTriangles); - } - context.setVertexBufferAt(0, null); - } - - private static function initMeshToShadowMapProgram(context3d:Context3D):Program3D { - var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); - var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); - var proc:Procedure = Procedure.compileFromArray([ - "#a0=a0", - "#c4=c4", - "#v0=v0", - "m44 t0, a0, c0", - "mul v0, t0, c4.x", - "mov o0, t0" - ]); - proc.assignVariableName(VariableType.CONSTANT, 0, "c0", 4); - vLinker.addProcedure(proc); - - fLinker.addProcedure(Procedure.compileFromArray([ - "#v0=v0", - "#c0=c0", - "mov t0.xy, v0.zz", - "frc t0.y, v0.z", - "sub t0.x, v0.z, t0.y", - "mul t0.x, t0.x, c0.x", - "mov t0.z, c0.z", - "mov t0.w, c0.w", - "mov o0, t0" - ])); - var program:Program3D = context3d.createProgram(); -// trace("VERTEX"); -// trace(A3DUtils.disassemble(vLinker.getByteCode())); -// trace("FRAGMENT"); -// trace(A3DUtils.disassemble(fLinker.getByteCode())); - fLinker.varyings = vLinker.varyings; - vLinker.link(); - fLinker.link(); - program.upload(vLinker.data, fLinker.data); - return program; - } - - // Rendering with shadow - private static function initVShader(index:int):Procedure { - var shader:Procedure = Procedure.compileFromArray([ - "m44 v0, a0, c0", - "mov v1, a0" - ]); - shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPosition"); - shader.assignVariableName(VariableType.CONSTANT, 0, index + "cTOSHADOW", 4); - shader.assignVariableName(VariableType.VARYING, 0, index + "vSHADOWSAMPLE"); - shader.assignVariableName(VariableType.VARYING, 1, "vPosition"); - return shader; - } - - private static function initFShader(mult:Boolean, usePCF:Boolean, index:int):Procedure { - var i:int; - var line:int = 0; - var shaderArr:Array = []; - var numPass:uint = (usePCF) ? 4 : 1; - for (i = 0; i < numPass; i++) { - // Расстояние - shaderArr[line++] = "mov t0.w, v0.z"; - shaderArr[line++] = "div t2, v0, v0.w"; - shaderArr[line++] = "mul t0.w, t0.w, c4.y"; // bias [0.99] * 255 - - if (usePCF) { - // Добавляем смещение - shaderArr[line++] = "mul t1, c" + (i + 9).toString() + ", t0.w"; -// shaderArr[line++] = "add t1, v0, t1"; - shaderArr[line++] = "add t1, t2, t1"; - shaderArr[line++] = "tex t1, t1, s0 <2d,clamp,near,nomip>"; - } else { -// shaderArr[line++] = "tex t1, v0, s0 <2d,clamp,near,nomip>"; - shaderArr[line++] = "tex t1, t2, s0 <2d,clamp,near,nomip>"; - } - - // Восстанавливаем расстояние - shaderArr[line++] = "mul t1.w, t1.x, c4.x"; // * 255 - shaderArr[line++] = "add t1.w, t1.w, t1.y"; - - // Перекрытие тенью - shaderArr[line++] = "sub t2.z, t1.w, t0.w"; - shaderArr[line++] = "mul t2.z, t2.z, c4.z"; // smooth [10000] - shaderArr[line++] = "sat t2.z, t2.z"; - - // Добавляем маску и прозрачность, затем sat - shaderArr[line++] = "add t2.z, t2.z, t1.z"; // маска тени - shaderArr[line++] = "add t2, t2.zzzz, c5"; // цвет тени - - // Плавный уход в прозрачность ------------- - shaderArr[line++] = "#c6=c" + index + "Spot"; - shaderArr[line++] = "#c7=c" + index + "Direction"; - shaderArr[line++] = "#c8=c" + index + "Geometry"; - shaderArr[line++] = "#v1=vPosition"; - // Считаем вектор из точки к свету - - // Вектор из точки к свету - shaderArr[line++] = "sub t0, c6, v1"; -// shaderArr[line++] = "sub t0, v1, c6"; - // Квадрат расстояния до точки - shaderArr[line++] = "dp3 t0.w, t0, t0"; - // Расстояние до точки - shaderArr[line++] = "sqt t0.w, t0.w"; - - // Нормализованное направление к источнику - shaderArr[line++] = "nrm t0.xyz, t0.xyz"; - // cos(Угол) между направлением к точке и направлением спота - shaderArr[line++] = "dp3 t0.y, t0.xyz, c7.xyz"; -// // cos(угол) - cos(falloff*0.5) - shaderArr[line++] = "sub t0.y, t0.y, c8.w"; -// // Делим на (cos(hotspot*0.5) - cos(falloff*0.5)) - shaderArr[line++] = "div t0.y, t0.y, c8.z"; - - // Минус atenuationBegin - shaderArr[line++] = "sub t0.w, t0.w, c8.y"; // len = len - atenuationBegin - // Делим на (atenuationEnd - atenuationBegin) - shaderArr[line++] = "div t0.w, t0.w, c8.x"; // att = len/radius - // 1 - соотношение между расстоянием до точки и максимальным расстоянием - shaderArr[line++] = "sub t0.w, c6.w, t0.w"; // att = 1 - len/radius - - shaderArr[line++] = "mul t0.w, t0.y, t0.w"; -// shaderArr[line++] = "mov t0.w, t0.y"; - shaderArr[line++] = "sub t0.w, c7.w, t0.w"; -// shaderArr[line++] = "mov t2, t0.wwww"; - shaderArr[line++] = "sat t0.w, t0.w"; - shaderArr[line++] = "add t2, t2, t0.wwww"; - // ----------------------------------------------------- - - shaderArr[line++] = "sat t2, t2"; - - if (usePCF) { - if (i == 0) { - shaderArr[line++] = "mov t3, t2"; - } else { - shaderArr[line++] = "add t3, t3, t2"; - } - } - } - if (usePCF) { - shaderArr[line++] = "mul t2, t3, c9.w"; - } - if (mult) { - shaderArr[line++] = "mul t0.xyz, i0.xyz, t2.xyz"; - shaderArr[line++] = "mov t0.w, i0.w"; - shaderArr[line++] = "mov o0, t0"; - } else { - shaderArr[line++] = "mov o0, t2"; -// shaderArr[line++] = "mov o0, t1"; - } - var shader:Procedure = Procedure.compileFromArray(shaderArr); - shader.assignVariableName(VariableType.VARYING, 0, index + "vSHADOWSAMPLE"); - shader.assignVariableName(VariableType.CONSTANT, 4, index + "cConstants", 1); - shader.assignVariableName(VariableType.CONSTANT, 5, index + "cShadowColor", 1); - if (usePCF) { - for (i = 0; i < numPass; i++) { - shader.assignVariableName(VariableType.CONSTANT, i + 9, "cSPCF" + i.toString(), 1); - } - } - shader.assignVariableName(VariableType.SAMPLER, 0, index + "sSHADOWMAP"); - return shader; - } - - override public function getFShader(index:int = 0):Procedure { - return initFShader(false, (pcfOffset > 0), index); - } - override public function getVShader(index:int = 0):Procedure { - return initVShader(index); - } - - private static const objectToShadowMap:Matrix3D = new Matrix3D(); - private static const localToGlobal:Transform3D = new Transform3D(); - override public function applyShader(drawUnit:DrawUnit, program:ShaderProgram, object:Object3D, camera:Camera3D, index:int = 0):void { - // Считаем матрицу перевода в лайт из объекта - localToGlobal.combine(camera.localToGlobalTransform, object.localToCameraTransform); - copyMatrixFromTransform(objectToShadowMap, localToGlobal); - objectToShadowMap.append(globalToShadowMap); - -// var casterPos:Vector3D = new Vector3D(caster.localToGlobalTransform.d, caster.localToGlobalTransform.h, caster.localToGlobalTransform.l); -// var p:Vector3D = objectToShadowMap.transformVector(casterPos); -// p.scaleBy(1/p.w); -// trace("caster pos:", p); - - objectToShadowMap.transpose(); - - drawUnit.setVertexConstantsFromVector(program.vertexShader.getVariableIndex(index + "cTOSHADOW"), objectToShadowMap.rawData, 4); - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex(index + "cConstants"), constants, constants.length/4); - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex(index + "cShadowColor"), camera.ambient, 1); - if (pcfOffset > 0) { - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex("cSPCF0"), pcfOffsets, pcfOffsets.length/4); - } - drawUnit.setTextureAt(program.fragmentShader.getVariableIndex(index + "sSHADOWMAP"), shadowMap); - -// localToGlobal.combine(light.cameraToLocalTransform, object.localToCameraTransform); - localToGlobal.combine(object.cameraToLocalTransform, light.localToCameraTransform); -// localToGlobal.invert(); - - // Настройки затухания - var transform:Transform3D = localToGlobal; - drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + index + "Spot"), transform.d, transform.h, transform.l, 1); - var rScale:Number = Math.sqrt(transform.a * transform.a + transform.e * transform.e + transform.i * transform.i); - rScale += Math.sqrt(transform.b * transform.b + transform.f * transform.f + transform.j * transform.j); - var dLen:Number = Math.sqrt(transform.c * transform.c + transform.g * transform.g + transform.k * transform.k); - rScale += dLen; - rScale /= 3; - drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + index + "Direction"), -transform.c / dLen, -transform.g / dLen, -transform.k / dLen, 0.5); - - var falloff:Number = Math.cos(light.falloff * 0.5); - var hotspot:Number = Math.cos(light.hotspot * 0.5); - - drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("c" + index + "Geometry"), light.attenuationEnd * rScale - light.attenuationBegin * rScale, light.attenuationBegin * rScale, hotspot == falloff ? 0.000001 : hotspot - falloff, falloff); - } - - } -} - -class ProjectionTransform3D { - public var m0:Number; - public var m5:Number; - public var m10:Number; - public var m14:Number; -} diff --git a/src/alternativa/engine3d/shadows/StaticShadowRenderer.as b/src/alternativa/engine3d/shadows/StaticShadowRenderer.as deleted file mode 100644 index 18449ac..0000000 --- a/src/alternativa/engine3d/shadows/StaticShadowRenderer.as +++ /dev/null @@ -1,569 +0,0 @@ -package alternativa.engine3d.shadows { - - import alternativa.engine3d.alternativa3d; - import alternativa.engine3d.core.BoundBox; - import alternativa.engine3d.core.Camera3D; - import alternativa.engine3d.core.DrawUnit; - import alternativa.engine3d.core.Object3D; - import alternativa.engine3d.core.Transform3D; - import alternativa.engine3d.lights.DirectionalLight; - import alternativa.engine3d.materials.ShaderProgram; - import alternativa.engine3d.materials.TextureMaterial; - import alternativa.engine3d.materials.compiler.Procedure; - import alternativa.engine3d.materials.compiler.VariableType; - import alternativa.engine3d.objects.Mesh; - import alternativa.engine3d.primitives.Box; - import alternativa.engine3d.resources.ExternalTextureResource; - import alternativa.engine3d.resources.TextureResource; - - import flash.display3D.Context3D; - import flash.display3D.Context3DTextureFormat; - import flash.display3D.textures.Texture; - import flash.geom.Matrix3D; - import flash.geom.Vector3D; - import flash.utils.Dictionary; - - use namespace alternativa3d; - - /** - * @private - */ - public class StaticShadowRenderer extends ShadowRenderer { - - public var context:Context3D; - - private const alpha:Number = 0.7; - - private var bounds:BoundBox = new BoundBox(); - private var partSize:Number; - private var partsShadowMaps:Vector.> = new Vector.>(); - private var partsUVMatrices:Vector.> = new Vector.>(); - - private var light:DirectionalLight; - private var globalToLight:Transform3D = new Transform3D(); - - private var _debug:Boolean = false; - private var debugContainer:Object3D; - - private var _recievers:Dictionary = new Dictionary(); - public function addReciever(object:Object3D):void { - _recievers[object] = true; - } - public function removeReciever(object:Object3D):void { - delete _recievers[object]; - } - - private static const constants:Vector. = Vector.([ - // 255, 255*0.99, 100, 1/255 -// 255, 255*0.96, 100, 1 - 255, 255, 1000, 1 - ]); - - private var pcfOffset:Number = 0; - private static var pcfOffsets:Vector.; - - public function dispose():void { - for each (var textures:Vector. in partsShadowMaps) { - for each (var texture:Texture in textures) { - texture.dispose(); - } - } - partsShadowMaps.length = 0; - partsUVMatrices.length = 0; - } - - public function StaticShadowRenderer(context:Context3D, partSize:int, pcfSize:Number = 0) { - this.context = context; - this.partSize = partSize; - this.pcfOffset = pcfSize; - constants[3] = 1 - alpha; - } - - override alternativa3d function cullReciever(boundBox:BoundBox, object:Object3D):Boolean { - return _recievers[object]; - } - - private var lightProjectionMatrix:Matrix3D = new Matrix3D(); - public function calculateShadows(object:Object3D, light:DirectionalLight, widthPartsCount:int = 1, heightPartsCount:int = 1, overlap:Number = 0):void { - this.light = light; - - var root:Object3D; - // Расчитываем матрицу объекта -// if (object.transformChanged) { - object.localToCameraTransform.compose(object._x, object._y, object._z, object._rotationX, object._rotationY, object._rotationZ, object._scaleX, object._scaleY, object._scaleZ); -// } else { -// object.localToCameraTransform.copy(caster.transform); -// } - root = object; - while (root._parent != null) { - root = root._parent; -// if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); -// } - object.localToCameraTransform.append(root.localToGlobalTransform); - } - - // Расчитываем матрицу лайта - light.localToGlobalTransform.compose(light._x, light._y, light._z, light._rotationX, light._rotationY, light._rotationZ, light._scaleX, light._scaleY, light._scaleZ); - root = light; - while (root._parent != null) { - root = root._parent; -// if (root.transformChanged) { - root.localToGlobalTransform.compose(root._x, root._y, root._z, root._rotationX, root._rotationY, root._rotationZ, root._scaleX, root._scaleY, root._scaleZ); -// } - light.localToGlobalTransform.append(root.localToGlobalTransform); - } - light.globalToLocalTransform.copy(light.localToGlobalTransform); - light.globalToLocalTransform.invert(); - - globalToLight.copy(light.globalToLocalTransform); - - // Получаем матрицу перевода из объекта в лайт - object.localToCameraTransform.append(light.globalToLocalTransform); - - bounds.reset(); - calculateBoundBox(bounds, object); - - var frustumMinX:Number = bounds.minX; - var frustumMaxX:Number = bounds.maxX; - var frustumMinY:Number = bounds.minY; - var frustumMaxY:Number = bounds.maxY; - var frustumMinZ:Number = bounds.minZ; - var frustumMaxZ:Number = bounds.maxZ; - - // Считаем шаг - var halfOverlap:Number = overlap*0.5; - var partWorldWidth:Number = (frustumMaxX - frustumMinX)/widthPartsCount; - var partWorldHeight:Number = (frustumMaxY - frustumMinY)/heightPartsCount; - - debugContainer = new Object3D(); - if (_debug) { - light.addChild(debugContainer); - } - - // Создаем шэдоумапы и рендерим - for (var xIndex:int = 0; xIndex < widthPartsCount; xIndex++) { - var maps:Vector. = new Vector.(); - var matrices:Vector. = new Vector.(); - for (var yIndex:int = 0; yIndex < heightPartsCount; yIndex++) { - var leftX:Number = frustumMinX + xIndex*partWorldWidth; - var leftY:Number = frustumMinY + yIndex*partWorldHeight; - - var width:Number; - var height:Number; - if (xIndex == 0) { - width = partWorldWidth + halfOverlap; - } else if (xIndex == (widthPartsCount - 1)) { - leftX -= halfOverlap; - width = partWorldWidth + halfOverlap; - } else { - leftX -= halfOverlap; - width = partWorldWidth + overlap; - } - if (yIndex == 0) { - height = partWorldHeight + halfOverlap; - } else if (yIndex == (heightPartsCount - 1)) { - leftY -= halfOverlap; - height = partWorldHeight + halfOverlap; - } else { - leftY -= halfOverlap; - height = partWorldHeight + overlap; - } - - var uvMatrix:Matrix3D = new Matrix3D(); - calculateShadowMapProjection(lightProjectionMatrix, uvMatrix, leftX, leftY, frustumMinZ, leftX + width, leftY + height, frustumMaxZ); - - var shadowMap:Texture = context.createTexture(partSize, partSize, Context3DTextureFormat.BGRA, true); - // Рисуем в шедоумапу - context.setRenderToTexture(shadowMap, true, 0, 0); - context.clear(1, 1, 1, 0.5); - cleanContext(context); - DirectionalShadowRenderer.drawObjectToShadowMap(context, object, light, lightProjectionMatrix); - cleanContext(context); - - maps.push(shadowMap); - matrices.push(uvMatrix); - - var texture:TextureResource = new ExternalTextureResource(null); - texture._texture = shadowMap; - var material:TextureMaterial = new TextureMaterial(texture); - material.opaquePass = false; - material.transparentPass = true; - material.alphaThreshold = 1.1; - var debugObject:Mesh = new Box(width, height, 1, 1, 1, 1, false, material); -// var debugObject:Mesh = new Box(width, height, 1, 1, 1, 1, false, new FillMaterial()); - debugObject.geometry.upload(context); - debugObject.x = leftX + width/2; - debugObject.y = leftY + height/2; - debugObject.z = frustumMinZ; - debugContainer.addChild(debugObject); - } - partsShadowMaps.push(maps); - partsUVMatrices.push(matrices); - } - context.setRenderToBackBuffer(); - if (pcfOffset > 0) { - var offset:Number = pcfOffset/partWorldWidth; -// pcfOffsets = Vector.([ -// -offset, -offset, 0, 1/4, -// -offset, offset, 0, 1, -// offset, -offset, 0, 1, -// offset, offset, 0, 1, -// ]); - pcfOffsets = Vector.([ - -offset, -offset, 0, 1/4, - -offset, offset, 0, 1, - offset, -offset, 0, 1, - offset, offset, 0, 1 - ]); - } - } - - private static const points:Vector. = Vector.([ - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D(), - new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D() - ]); - alternativa3d static function calculateBoundBox(boundBox:BoundBox, object:Object3D, hierarchy:Boolean = true):void { - // Считаем баунды объекта в лайте - var point:Vector3D; - if (object.boundBox != null) { - var bb:BoundBox = object.boundBox; - point = points[0]; - point.x = bb.minX; - point.y = bb.minY; - point.z = bb.minZ; - point = points[1]; - point.x = bb.minX; - point.y = bb.minY; - point.z = bb.maxZ; - point = points[2]; - point.x = bb.minX; - point.y = bb.maxY; - point.z = bb.minZ; - point = points[3]; - point.x = bb.minX; - point.y = bb.maxY; - point.z = bb.maxZ; - point = points[4]; - point.x = bb.maxX; - point.y = bb.minY; - point.z = bb.minZ; - point = points[5]; - point.x = bb.maxX; - point.y = bb.minY; - point.z = bb.maxZ; - point = points[6]; - point.x = bb.maxX; - point.y = bb.maxY; - point.z = bb.minZ; - point = points[7]; - point.x = bb.maxX; - point.y = bb.maxY; - point.z = bb.maxZ; - var transform:Transform3D = object.localToCameraTransform; - for (var i:int = 0; i < 8; i++) { - point = points[i]; - var x:Number = transform.a*point.x + transform.b*point.y + transform.c*point.z + transform.d; - var y:Number = transform.e*point.x + transform.f*point.y + transform.g*point.z + transform.h; - var z:Number = transform.i*point.x + transform.j*point.y + transform.k*point.z + transform.l; - if (x < boundBox.minX) { - boundBox.minX = x; - } - if (x > boundBox.maxX) { - boundBox.maxX = x; - } - if (y < boundBox.minY) { - boundBox.minY = y; - } - if (y > boundBox.maxY) { - boundBox.maxY = y; - } - if (z < boundBox.minZ) { - boundBox.minZ = z; - } - if (z > boundBox.maxZ) { - boundBox.maxZ = z; - } - } - } - if (hierarchy) { - // Пробегаемся по дочерним объектам - for (var child:Object3D = object.childrenList; child != null; child = child.next) { - if (child.visible) { - if (child.transformChanged) { - child.composeTransforms(); - } - child.localToCameraTransform.combine(object.localToCameraTransform, child.transform); - calculateBoundBox(boundBox, child); - } - } - } - } - - private var rawData:Vector. = new Vector.(16); - private function calculateShadowMapProjection(matrix:Matrix3D, uvMatrix:Matrix3D, frustumMinX:Number, frustumMinY:Number, frustumMinZ:Number, frustumMaxX:Number, frustumMaxY:Number, frustumMaxZ:Number):void { - // Считаем матрицу проецирования - rawData[0] = 2/(frustumMaxX - frustumMinX); - rawData[5] = 2/(frustumMaxY - frustumMinY); - rawData[10]= 1/(frustumMaxZ - frustumMinZ); - rawData[12] = (-0.5 * (frustumMaxX + frustumMinX) * rawData[0]); - rawData[13] = (-0.5 * (frustumMaxY + frustumMinY) * rawData[5]); - rawData[14]= -frustumMinZ/(frustumMaxZ - frustumMinZ); - rawData[15]= 1; - matrix.rawData = rawData; - - rawData[0] = 1/((frustumMaxX - frustumMinX)); - // if (useSingle) { - // rawData[5] = 1/((frustumMaxY - frustumMinY)); - // } else { - rawData[5] = -1/((frustumMaxY - frustumMinY)); - // } - rawData[12] = 0.5 - (0.5 * (frustumMaxX + frustumMinX) * rawData[0]); - rawData[13] = 0.5 - (0.5 * (frustumMaxY + frustumMinY) * rawData[5]); - uvMatrix.rawData = rawData; - } - - override public function get debug():Boolean { - return _debug; - } - - override public function set debug(value:Boolean):void { - _debug = value; - if (debugContainer != null) { - if (value) { - if (light != null) { - light.addChild(debugContainer); - } - } else { - if (debugContainer._parent != null) { - debugContainer.removeFromParent(); - } - } - } - } - -// private static const vShader:Procedure = initVShader(index); - private static function initVShader(index:int):Procedure { - var shader:Procedure = Procedure.compileFromArray([ -// "m44 o0, a0, c0", -// Координата вершины в локальном пространстве - "m44 v0, a0, c4" - ]); - shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPosition"); - shader.assignVariableName(VariableType.CONSTANT, 0, "cPROJ", 4); - shader.assignVariableName(VariableType.CONSTANT, 4, "cTOSHADOW", 4); - shader.assignVariableName(VariableType.VARYING, 0, "vSHADOWSAMPLE"); - return shader; - } -// private static const multVShader:Procedure = initMultVShader(); -// private static function initMultVShader():Procedure { -// var shader:Procedure = Procedure.compileFromArray([ -// "m44 v0, a0, c0", -// ]); -// shader.assignVariableName(VariableType.ATTRIBUTE, 0, "aPOSITION"); -// shader.assignVariableName(VariableType.CONSTANT, 0, "cTOSHADOW", 4); -// shader.assignVariableName(VariableType.VARYING, 0, "vSHADOWSAMPLE"); -// return shader; -// } -// private static const fShader:Procedure = initFShader(false, false, index); -// private static const pcfFShader:Procedure = initFShader(false, true, index); - // i0 - input color - // o0 - shadowed result -// private static const multFShader:Procedure = initFShader(true, false, index); -// private static const pcfMultFShader:Procedure = initFShader(true, true, index); - private static function initFShader(mult:Boolean, usePCF:Boolean, index:int, grayScale:Boolean = false):Procedure { - var i:int; - var line:int = 0; - var shaderArr:Array = []; - var numPass:uint = (usePCF) ? 4 : 1; - for (i = 0; i < numPass; i++) { - // Расстояние - shaderArr[line++] = "mov t0.w, v0.z"; - shaderArr[line++] = "mul t0.w, t0.w, c4.y"; // bias [0.99] * 255 - - if (usePCF) { - // Добавляем смещение -// shaderArr[line++] = "mul t1, c" + (i + 5).toString() + ", t0.w"; - shaderArr[line++] = "add t1, v0, c" + (i + 5).toString() + ""; - // shaderArr[line++] = "add t1, v0, c" + (i + 5).toString(); - shaderArr[line++] = "tex t1, t1, s0 <2d,clamp,near,nomip>"; - } else { - shaderArr[line++] = "tex t1, v0, s0 <2d,clamp,near,nomip>"; - } - - // Восстанавливаем расстояние - shaderArr[line++] = "mul t1.w, t1.x, c4.x"; // * 255 - shaderArr[line++] = "add t1.w, t1.w, t1.y"; - - // Перекрытие тенью - shaderArr[line++] = "sub t2.z, t1.w, t0.w"; - shaderArr[line++] = "mul t2.z, t2.z, c4.z"; // smooth [10000] - shaderArr[line++] = "sat t2.z, t2.z"; - - // Добавляем маску и прозрачность, затем sat -// shaderArr[line++] = "add t2.z, t2.z, t1.z"; // маска тени -// shaderArr[line++] = "add t2.z, t2.z, c4.w"; // вес тени - shaderArr[line++] = "sat t2.z, t2.z"; - - if (usePCF) { - if (i == 0) { - shaderArr[line++] = "mov t2.x, t2.z"; - } else { - shaderArr[line++] = "add t2.x, t2.x, t2.z"; - } - } - } - if (usePCF) { - shaderArr[line++] = "mul t2.z, t2.x, c5.w"; - } - if (grayScale) { - shaderArr.push("mov o0.w, t2.z"); - } else { - if (mult) { - shaderArr.push("mul t0.xyz, i0.xyz, t2.z"); - shaderArr.push("mov t0.w, i0.w"); - shaderArr.push("mov o0, t0"); - } else { - shaderArr.push("mov t0, t2.z"); - shaderArr.push("mov o0, t0"); - } - } - var shader:Procedure = Procedure.compileFromArray(shaderArr, "StaticShadowMap"); - shader.assignVariableName(VariableType.VARYING, 0, "vSHADOWSAMPLE"); - shader.assignVariableName(VariableType.CONSTANT, 4, "cConstants", 1); - if (usePCF) { - for (i = 0; i < numPass; i++) { - shader.assignVariableName(VariableType.CONSTANT, i + 5, "cPCF" + i.toString(), 1); - } - } - shader.assignVariableName(VariableType.SAMPLER, 0, "sSHADOWMAP"); - return shader; - } - - override public function getVShader(index:int = 0):Procedure { - return initVShader(index); - } - override public function getFShader(index:int = 0):Procedure { - return initFShader(false, (pcfOffset > 0), index); - } - -// override public function getMultFShader():Procedure { -// return (pcfOffset > 0) ? pcfMultFShader : multFShader; -// } -// override public function getMultVShader():Procedure { -// return multVShader; -// } - - override public function getFIntensityShader():Procedure { - return initFShader(false, (pcfOffset > 0), 0, true); - } - - private static const objectToShadowMap:Transform3D = new Transform3D(); - private static const objectToUVMap:Matrix3D = new Matrix3D(); - override public function applyShader(drawUnit:DrawUnit, program:ShaderProgram, object:Object3D, camera:Camera3D, index:int = 0):void { - // Считаем матрицу перевода в лайт из объекта - - objectToShadowMap.combine(camera.localToGlobalTransform, object.localToCameraTransform); - objectToShadowMap.append(globalToLight); - -// objectToShadowMap.identity(); -// objectToShadowMap.append(object.cameraMatrix); -// objectToShadowMap.append(camera.globalMatrix); -// objectToShadowMap.append(globalToLight); - - // Получаем индекс шедоумапы -// var coords:Vector3D = objectToShadowMap.position; - var coords:Vector3D = new Vector3D(objectToShadowMap.d, objectToShadowMap.h, objectToShadowMap.l); - var xIndex:int = (coords.x - bounds.minX)/(bounds.maxX - bounds.minX)*partsShadowMaps.length; - - xIndex = (xIndex < 0) ? 0 : ((xIndex >= partsShadowMaps.length) ? partsShadowMaps.length - 1 : xIndex); - var maps:Vector. = partsShadowMaps[xIndex]; - var matrices:Vector. = partsUVMatrices[xIndex]; - - var yIndex:int = (coords.y - bounds.minY)/(bounds.maxY - bounds.minY)*maps.length; - yIndex = (yIndex < 0) ? 0 : ((yIndex >= maps.length) ? maps.length - 1 : yIndex); - -// trace(xIndex, yIndex); - - var shadowMap:Texture = maps[yIndex]; - var uvMatrix:Matrix3D = matrices[yIndex]; - - DirectionalShadowRenderer.copyMatrixFromTransform(objectToUVMap, objectToShadowMap); - objectToUVMap.append(uvMatrix); - objectToUVMap.transpose(); -// objectToShadowMap.append(uvMatrix); - - drawUnit.setVertexConstantsFromVector(program.vertexShader.getVariableIndex("cTOSHADOW"), objectToUVMap.rawData, 4); - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex("cConstants"), constants, 1); - if (pcfOffset > 0) { - drawUnit.setFragmentConstantsFromVector(program.fragmentShader.getVariableIndex("cPCF0"), pcfOffsets, pcfOffsets.length >> 2) - } - drawUnit.setTextureAt(program.fragmentShader.getVariableIndex("sSHADOWMAP"), shadowMap); - } - -// private static var program:LinkedProgram; -// private static var programPCF:LinkedProgram; -// private static function initMeshProgram(context:Context3D, usePCF:Boolean):LinkedProgram { -// var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); -// vLinker.addShader(vShader); -// -// var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); -// if (usePCF) { -// fLinker.addShader(pcfFShader); -// } else { -// fLinker.addShader(fShader); -// } -// -// vLinker.setOppositeLinker(fLinker); -// fLinker.setOppositeLinker(vLinker); -// -//// trace("[VERTEX]"); -//// trace(AgalUtils.disassemble(vLinker.getByteCode())); -//// trace("[FRAGMENT]"); -//// trace(AgalUtils.disassemble(fLinker.getByteCode())); -// -// var result:LinkedProgram; -// if (usePCF) { -// programPCF = new LinkedProgram(); -// result = programPCF; -// } else { -// program = new LinkedProgram(); -// result = program; -// } -// result.vLinker = vLinker; -// result.fLinker = fLinker; -// result.program = context.createProgram(); -// result.program.upload(vLinker.getByteCode(), fLinker.getByteCode()); -// -// return result; -// } -// -// override public function drawShadow(mesh:Mesh, camera:Camera3D, texture:Texture):void { -// var context3d:Context3D = camera.view._context3d; -// -// var linkedProgram:LinkedProgram; -// if (pcfOffset > 0) { -// linkedProgram = (programPCF == null) ? initMeshProgram(context3d, true) : programPCF; -// } else { -// linkedProgram = (program == null) ? initMeshProgram(context3d, false) : program; -// } -// var vLinker:Linker = linkedProgram.vLinker; -// var fLinker:Linker = linkedProgram.fLinker; -// context3d.setProgram(linkedProgram.program); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), mesh.geometry.vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3); -// context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, vLinker.getVariableIndex("cPROJ"), mesh.projectionMatrix, true); -// applyShader(context3d, linkedProgram, mesh, camera); -// context3d.setVertexBufferAt(1, null); -// -// context3d.setCulling(Context3DTriangleFace.FRONT); -// context3d.drawTriangles(mesh.geometry.indexBuffer, 0, mesh.geometry.numTriangles); -// -// context3d.setVertexBufferAt(vLinker.getVariableIndex("aPOSITION"), null); -// context.setTextureAt(getTextureIndex(fLinker), texture); -// } - - } -}