diff --git a/src/alternativa/engine3d/lights/OmniLight.as b/src/alternativa/engine3d/lights/OmniLight.as index cb9b502..c9db019 100644 --- a/src/alternativa/engine3d/lights/OmniLight.as +++ b/src/alternativa/engine3d/lights/OmniLight.as @@ -32,7 +32,7 @@ package alternativa.engine3d.lights { /** * Distance from at which falloff is complete. */ - public var attenuationEnd:Number; + public var _attenuationEnd:Number; /** * Creates a OmniLight object. @@ -211,5 +211,19 @@ package alternativa.engine3d.lights { var omniShadow:OmniLightShadow = value as OmniLightShadow; if (omniShadow!=null) omniShadow.setBoundSize(this.attenuationEnd*1.5); } + + public function get attenuationEnd():Number{ + return _attenuationEnd; + } + + /** + * @private + */ + public function set attenuationEnd(value:Number):void{ + // TODO: recalculate BoundBox + _attenuationEnd = value; + var omniShadow:OmniLightShadow = shadow as OmniLightShadow; + if (omniShadow!=null) omniShadow.setBoundSize(this._attenuationEnd*1.0); + } } } diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 4459e88..8431c8b 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -467,13 +467,22 @@ package alternativa.engine3d.materials { // i3 - ambient // i2 - shadow-test - source.push("mul t0.xw, t0.xw, i2.xw"); + source.push("mul t0.xw, t0.xwww, i2.xxxx"); source.push("mul t0.xyz, c1.xyz, t0.xxx"); // t = color*t source.push("mul t1.xyz, t0.xyz, t1.w"); source.push("add o1.xyz, o1.xyz, t1.xyz"); source.push("mul t0.xyz, t0.xyz, t0.www"); source.push("add o0.xyz, t0.xyz, i3.xyz"); + +// source.push("mov o1, t1"); +// source.push("mov o1, c1"); +// source.push("mov o1, i2"); +// source.push("mov o1, i3"); +// source.push("sub o1, t0, t0"); +// +// source.push("mov o0.xyz, i2.x"); +// source.push("div o0.w, i2.x, i2.x"); } else { // Считаем вектор из точки к свету diff --git a/src/alternativa/engine3d/shadows/OmniLightShadow.as b/src/alternativa/engine3d/shadows/OmniLightShadow.as index caf9a0f..3397742 100644 --- a/src/alternativa/engine3d/shadows/OmniLightShadow.as +++ b/src/alternativa/engine3d/shadows/OmniLightShadow.as @@ -48,7 +48,7 @@ package alternativa.engine3d.shadows { private var renderer:Renderer = new Renderer(); - private var boundSize:Number = 1; + private var radius:Number = 1; private var _mapSize:Number; private var _pcfOffset:Number; @@ -90,9 +90,9 @@ package alternativa.engine3d.shadows { for (var i:int = 0; i < 6; i++) { // создаем камеры - var cam:Camera3D = new Camera3D(1, boundSize); + var cam:Camera3D = new Camera3D(10, radius); cam.fov = 1.910633237; - cam.view = new View(boundSize, boundSize); + cam.view = new View(radius, radius); cam.renderer = renderer; cameras[i] = cam; @@ -131,7 +131,7 @@ package alternativa.engine3d.shadows { * @private */ alternativa3d function setBoundSize(value:Number):void{ - this.boundSize = value; + this.radius = value; for (var i:int = 0; i < 6; i++) { var cam:Camera3D = cameras[i]; cam.view.width = cam.view.height = int (value); @@ -216,23 +216,23 @@ package alternativa.engine3d.shadows { caster.lightToLocalTransform.combine(caster.cameraToLocalTransform, _light.localToCameraTransform); caster.localToLightTransform.combine(_light.cameraToLocalTransform, caster.localToCameraTransform); - var skin:Skin = caster as Skin; - if (skin != null) { - // Расчет матриц джоинтов - for (var child:Object3D = skin.childrenList; child != null; child = child.next) { - if (child.transformChanged) child.composeTransforms(); - // Записываем в localToGlobalTransform матрицу перевода в скин - child.localToGlobalTransform.copy(child.transform); - if (child is Joint) { - Joint(child).calculateTransform(); - } - skin.calculateJointsTransforms(child); - } - } - else{ - if (caster.childrenList) - calculateChildrenTransforms(caster); - } + if (caster.childrenList) + calculateChildrenTransforms(caster); + +// var skin:Skin = caster as Skin; +// if (skin != null) { +// // Расчет матриц джоинтов +// for (var child:Object3D = skin.childrenList; child != null; child = child.next) { +// if (child.transformChanged) child.composeTransforms(); +// // Записываем в localToGlobalTransform матрицу перевода в скин +// child.localToGlobalTransform.copy(child.transform); +// if (child is Joint) { +// Joint(child).calculateTransform(); +// } +// skin.calculateJointsTransforms(child); +// } +// } + } @@ -294,7 +294,7 @@ package alternativa.engine3d.shadows { // Создаем дебаговый объект, если он не создан if (debugObject == null) { debugObject = createDebugCube(debugMaterial, camera.context3D); - debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = boundSize/12; + debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius/12; debugObject.composeTransforms(); } @@ -320,24 +320,23 @@ package alternativa.engine3d.shadows { child.localToLightTransform.combine(root.localToLightTransform, child.transform); child.lightToLocalTransform.combine(child.inverseTransform, root.lightToLocalTransform); - // расчет матриц трансформаций для скинов - var skin:Skin = child as Skin; - if (skin != null) { - // Расчет матриц джоинтов - for (var skinChild:Object3D = skin.childrenList; skinChild != null; skinChild = skinChild.next) { - if (skinChild.transformChanged) skinChild.composeTransforms(); - // Записываем в localToGlobalTransform матрицу перевода в скин - skinChild.localToGlobalTransform.copy(skinChild.transform); - if (skinChild is Joint) { - Joint(skinChild).calculateTransform(); - } - skin.calculateJointsTransforms(skinChild); - } - } - else{ - if (child.childrenList) - calculateChildrenTransforms(child); - } + if (child.childrenList) + calculateChildrenTransforms(child); + +// // расчет матриц трансформаций для скинов +// var skin:Skin = child as Skin; +// if (skin != null) { +// // Расчет матриц джоинтов +// for (var skinChild:Object3D = skin.childrenList; skinChild != null; skinChild = skinChild.next) { +// if (skinChild.transformChanged) skinChild.composeTransforms(); +// // Записываем в localToGlobalTransform матрицу перевода в скин +// skinChild.localToGlobalTransform.copy(skinChild.transform); +// if (skinChild is Joint) { +// Joint(skinChild).calculateTransform(); +// } +// skin.calculateJointsTransforms(skinChild); +// } +// } } } @@ -357,26 +356,14 @@ package alternativa.engine3d.shadows { casterCulling = 63; } - // Если Кулинг кастера дает положительный результат, тогда - if (casterCulling){ - if (skin){ - actualCasters[actualCastersCount++] = root; - } - else{ - var childrenList:Object3D = root.childrenList; - // Если есть дочерние объекты, - if(childrenList!=null){ - // Проверяем их на кулинг - for (var child:Object3D = childrenList; child != null; child = child.next) { - calculateVisibility(child, camera); - } - } - // Если дочерних объектов нет - else{ - // добавляем кастер в список актуальных кастеров - actualCasters[actualCastersCount++] = root; - } - } + // добавляем кастер в список актуальных кастеров + if (casterCulling) + actualCasters[actualCastersCount++] = root; + + // Если есть дочерние объекты, + // Проверяем их на кулинг + for (var child:Object3D = root.childrenList; child != null; child = child.next) { + calculateVisibility(child, camera); } } } @@ -458,17 +445,11 @@ package alternativa.engine3d.shadows { drawUnit.setProjectionConstants(edgeCamera, program.vertexShader.getVariableIndex("cProjMatrix"), casterToEdgedCameraTransform); drawUnit.setVertexConstantsFromTransform(program.vertexShader.getVariableIndex("cCasterToOmni"), caster.localToLightTransform); - drawUnit.setVertexConstantsFromNumbers(program.vertexShader.getVariableIndex("cScale"), 255/boundSize, 0, 0, 1); - drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 0, 1); + drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 255/radius, 1); renderer.addDrawUnit(drawUnit, Renderer.OPAQUE); } } - - var child:Object3D; - for (child = caster.childrenList; child != null; child = child.next) { - if (!(child as Joint) && child.visible) collectDraws(context, child, edgeCamera); - } } @@ -525,15 +506,10 @@ package alternativa.engine3d.shadows { } var proc:Procedure = Procedure.compileFromArray([ - "#c1=cScale", "#v0=vDistance", "m34 t0.xyz, i0, c2", - "dp3 t0.x, t0.xyz, t0.xyz", - "sqt t0.x, t0.x", // x: [0, boundSize] - "mul t0.x, t0.x, c1.x", // x: [0, 255] - "mov t0.w, c1.w", - "mov v0, t0", + "mov v0, t0.xyzx", "m44 o0, i0, c0" ]); @@ -550,13 +526,18 @@ package alternativa.engine3d.shadows { } } fLinker.addProcedure(Procedure.compileFromArray([ - "#v0=vDistance", // x: [0, 255] - "#c0=cConstants", // 1/255, 0, 0, 1 - "frc t0.y, v0.x", - "sub t0.x, v0.x, t0.y", + "#v0=vDistance", // xyz + "#c0=cConstants", // 1/255, 0, 255/radius, 1 + // calculate distance + "dp3 t0.z, v0.xyz, v0.xyz", + "sqt t0.z, t0.z", // x: [0, radius] + "mul t0.z, t0.z, c0.z", // x: [0, 255] + // codeing + "frc t0.y, t0.z", + "sub t0.x, t0.z, t0.y", "mul t0.x, t0.x, c0.x", - "mov t0.zw, c0.zw", + "mov t0.w, c0.w", "mov o0, t0" ])); program = new ShaderProgram(vLinker, fLinker); @@ -570,7 +551,7 @@ package alternativa.engine3d.shadows { - //------------- ShadowMap Shader ---------- + //------------- ShadowMap Shader in material---------- /** * @private @@ -587,13 +568,14 @@ package alternativa.engine3d.shadows { // TODO: сделать множитель более корректный. Возможно 65536 (разрешающая способность глубины буфера). if (_pcfOffset > 0) { - var offset:Number = _pcfOffset*0.0175; //1 градус + var offset:Number = _pcfOffset*0.0175; //TODO: make equivalent 1 offset ~ 1 degree drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3/2, 1/16, 0, 0); - drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset/boundSize); - drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -10000, -10000/255, biasMultiplier*10000/boundSize, 10); + drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset/radius); + drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -10000, -10000/255, biasMultiplier*10000/radius, 10); } else{ - drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -10000, -10000/255, biasMultiplier*10000/boundSize, 1); + drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -10000, -10000/255, biasMultiplier*10000/radius, 1.0); +// drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -100000, -100000/255, 1/radius, 1); } } @@ -602,11 +584,8 @@ package alternativa.engine3d.shadows { "#v0=vSample", "m34 t0.xyz, i0, c0", - "dp3 t0.w, t0.xyz, t0.xyz", - "sqt t0.w, t0.w", // w: [0, boundSize] -// "div t0.xyz, t0.xyz, t0.w", // norm - "mov v0, t0" + "mov v0, t0.xyz" ], "OmniShadowMapVertex"); shader.assignVariableName(VariableType.CONSTANT, 0, "cObjectToLightTransform", 3); return shader; @@ -620,14 +599,20 @@ package alternativa.engine3d.shadows { ]; var line:int = 3; // Расстояние - shaderArr[line++] = "mov t0.z, v0.w"; // w: [0, boundSize] - shaderArr[line++] = "tex t0.xy, v0, s0 "; + shaderArr[line++] = "dp3 t0.z, v0.xyz, v0.xyz"; + shaderArr[line++] = "sqt t0.z, t0.z"; // w: [0, radius] + shaderArr[line++] = "tex t0.xy, v0, s0 "; shaderArr[line++] = "dp3 t0.x, t0.xyz, c0.xyz"; // декодируем, находим разницу между расстояниями и умножаем ее на большое число // рассчитываем значение тени shaderArr[line++] = "sat t0, t0.x"; shaderArr[line++] = "sub o0, c0.w, t0.x"; +// shaderArr[line++] = "sat t0.x, t0.x"; +// shaderArr[line++] = "sub t0.x, c0.w, t0.x"; +// shaderArr[line++] = "sat t0.x, t0.x"; +// shaderArr[line++] = "mov o0, t0.x"; + return Procedure.compileFromArray(shaderArr, "OmniShadowMapFragment"); } @@ -645,7 +630,6 @@ package alternativa.engine3d.shadows { // допустимо использование временных переменных t0 t1 t2 t3 // v0 - sample - // v0.w - length(sample) [0, boundSize] // ищем 2-а перпендикулярных вектора // (-y, x, 0) @@ -659,7 +643,9 @@ package alternativa.engine3d.shadows { shaderArr[line++] = "nrm t1.xyz, t1.xyz"; // задаем оффсеты - shaderArr[line++] = "mul t0.w, c1.w, v0.w"; // с1.w = offset/boundSize + shaderArr[line++] = "dp3 t3.z, v0.xyz, v0.xyz"; + shaderArr[line++] = "sqt t3.z, t3.z"; // w: [0, radius] + shaderArr[line++] = "mul t0.w, c1.w, t3.z"; // с1.w = offset/radius shaderArr[line++] = "mul t0.xyz, t0.xyz, t0.w"; shaderArr[line++] = "mul t1.xyz, t1.xyz, t0.w"; // --------- {13 opcode} @@ -677,9 +663,9 @@ package alternativa.engine3d.shadows { shaderArr[line++] = "add t2.xyz, t2.xyz, v0.xyz"; // получаем длинну из шадоумапы [0, 1] - shaderArr[line++] = "mov t3.z, v0.w"; +// shaderArr[line++] = "mov t3.z, t0.w"; - shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; + shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число //----- @@ -687,7 +673,7 @@ package alternativa.engine3d.shadows { for (j = 1; j<4; j++){ shaderArr[line++] = "add t2.xyz, t2.xyz, t1.xyz"; - shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; + shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число } @@ -699,13 +685,13 @@ package alternativa.engine3d.shadows { for (i = 0; i<3; i++){ shaderArr[line++] = "add t2.xyz, t2.xyz, t0.xyz"; - shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; + shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число for (j = 1; j<4; j++){ shaderArr[line++] = (i%2 == 1)?("add t2.xyz, t2.xyz, t1.xyz"):("sub t2.xyz, t2.xyz, t1.xyz"); - shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; + shaderArr[line++] = "tex t3.xy, t2.xyz, s0 "; shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число } shaderArr[line++] = "sat o0, o0";