ASDoc for shadows

This commit is contained in:
artem pecheny
2012-07-30 14:57:28 +06:00
parent cf4ad582f1
commit cffd3bf50d
2 changed files with 1102 additions and 1088 deletions

View File

@@ -43,9 +43,9 @@ package alternativa.engine3d.shadows {
use namespace alternativa3d; use namespace alternativa3d;
/** /**
* Class of shadow, that is created by one source of light(<code>DirectionalLight</code>). Shadow is rendered in fixed volume. * Class of the shadow, that is created by one source of light(<code>DirectionalLight</code>). Shadow is rendered in fixed volume.
* For binding of shadow to light source you need: * For binding of shadow to light source you need:
* 1) to set <code>DirectionalLightShadow</code> as a value of property <code>shadow</code> of light source; * 1) to set instance of the <code>DirectionalLightShadow</code> as a value of property <code>shadow</code> of light source;
* 2) to add <code>Object3D</code> to corresponding list, using the method <code>addCaster()</code>. * 2) to add <code>Object3D</code> to corresponding list, using the method <code>addCaster()</code>.
* *
* @see #addCaster() * @see #addCaster()
@@ -820,7 +820,7 @@ package alternativa.engine3d.shadows {
} }
/** /**
* Clears the list of objects, that cast shadow. * Clears the list of objects, which cast shadow.
*/ */
public function clearCasters():void { public function clearCasters():void {
_casters.length = 0; _casters.length = 0;

View File

@@ -40,7 +40,18 @@ package alternativa.engine3d.shadows {
use namespace alternativa3d; use namespace alternativa3d;
public class OmniLightShadow extends Shadow{ /**
* Class of the shadow, that is created by one source of light(<code>OmniLight</code>). Shadow is rendered in fixed volume.
* For binding of shadow to light source you need:
* 1) to set instance of the <code>OmniLight</code> as a value of property <code>shadow</code> of light source;
* 2) to add <code>Object3D</code> to corresponding list, using the method <code>addCaster()</code>.
*
* @see #addCaster()
* @see alternativa.engine3d.lights.OmniLight#shadow
* @see #farBoundPosition
*/
public class OmniLightShadow extends Shadow {
// TODO: calculate bias automaticaly // TODO: calculate bias automaticaly
/** /**
@@ -70,7 +81,7 @@ package alternativa.engine3d.shadows {
private var cameras:Vector.<Camera3D> = new Vector.<Camera3D>(); private var cameras:Vector.<Camera3D> = new Vector.<Camera3D>();
private var debugObject:Mesh; private var debugObject:Mesh;
private var debugMaterial:ShadowDebugMaterial; private var debugMaterial:ShadowDebugMaterial;
private var _casters:Vector.<Object3D> = new Vector.<Object3D>(); private var _casters:Vector.<Object3D> = new Vector.<Object3D>();
@@ -111,26 +122,26 @@ package alternativa.engine3d.shadows {
debugMaterial.alpha = 0.3; debugMaterial.alpha = 0.3;
for (var i:int = 0; i < 6; i++) { for (var i:int = 0; i < 6; i++) {
var cam:Camera3D = new Camera3D(radius/1000, radius); var cam:Camera3D = new Camera3D(radius / 1000, radius);
cam.fov = 1.910633237; cam.fov = 1.910633237;
cameras[i] = cam; cameras[i] = cam;
} }
// Left // Left
cameras[1].rotationY = -Math.PI/2; cameras[1].rotationY = -Math.PI / 2;
cameras[1].scaleY = -1; cameras[1].scaleY = -1;
cameras[1].composeTransforms(); cameras[1].composeTransforms();
// Right // Right
cameras[0].rotationY = Math.PI/2; cameras[0].rotationY = Math.PI / 2;
cameras[0].scaleY = -1; cameras[0].scaleY = -1;
cameras[0].composeTransforms(); cameras[0].composeTransforms();
// Back // Back
cameras[3].rotationX = -Math.PI/2; cameras[3].rotationX = -Math.PI / 2;
cameras[3].rotationZ = Math.PI; cameras[3].rotationZ = Math.PI;
cameras[3].scaleX = -1; cameras[3].scaleX = -1;
cameras[3].composeTransforms(); cameras[3].composeTransforms();
// Front // Front
cameras[2].rotationX = -Math.PI/2; cameras[2].rotationX = -Math.PI / 2;
cameras[2].scaleY = -1; cameras[2].scaleY = -1;
cameras[2].composeTransforms(); cameras[2].composeTransforms();
// Bottom // Bottom
@@ -143,7 +154,7 @@ package alternativa.engine3d.shadows {
cameras[4].composeTransforms(); cameras[4].composeTransforms();
} }
private function createDebugObject(material:Material, context:Context3D):Mesh{ private function createDebugObject(material:Material, context:Context3D):Mesh {
var geometry:Geometry; var geometry:Geometry;
var mesh:Mesh; var mesh:Mesh;
if (DEBUG_TYPE == "Box") { if (DEBUG_TYPE == "Box") {
@@ -186,7 +197,7 @@ package alternativa.engine3d.shadows {
triangles.push(c, b, a); triangles.push(c, b, a);
} }
mesh.geometry.indices = triangles; mesh.geometry.indices = triangles;
mesh.getSurface(0).numTriangles = triangles.length/3; mesh.getSurface(0).numTriangles = triangles.length / 3;
mesh.setMaterialToAllSurfaces(material); mesh.setMaterialToAllSurfaces(material);
} }
mesh.geometry.upload(context); mesh.geometry.upload(context);
@@ -218,7 +229,7 @@ package alternativa.engine3d.shadows {
radius = OmniLight(_light).attenuationEnd; radius = OmniLight(_light).attenuationEnd;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
var cam:Camera3D = cameras[i]; var cam:Camera3D = cameras[i];
cam.nearClipping = radius/1000; cam.nearClipping = radius / 1000;
cam.farClipping = radius; cam.farClipping = radius;
cam.calculateProjection(1, 1); cam.calculateProjection(1, 1);
} }
@@ -242,7 +253,7 @@ package alternativa.engine3d.shadows {
caster.localToLightTransform.combine(_light.cameraToLocalTransform, caster.localToCameraTransform); caster.localToLightTransform.combine(_light.cameraToLocalTransform, caster.localToCameraTransform);
// collect actualCasters for light // collect actualCasters for light
if (caster.boundBox == null || OmniLight(_light).checkBound(caster)){ if (caster.boundBox == null || OmniLight(_light).checkBound(caster)) {
actualCasters[actualCastersCount] = caster; actualCasters[actualCastersCount] = caster;
actualCastersCount++; actualCastersCount++;
@@ -280,7 +291,7 @@ package alternativa.engine3d.shadows {
// Cube side camera // Cube side camera
var edgeCamera:Camera3D = cameras[i]; var edgeCamera:Camera3D = cameras[i];
var edgeBit:int = (1<<i); var edgeBit:int = (1 << i);
if (actualCastersCount > 0) { if (actualCastersCount > 0) {
// Настройка параметров рендеринга: // Настройка параметров рендеринга:
renderer.camera = camera; renderer.camera = camera;
@@ -306,10 +317,10 @@ package alternativa.engine3d.shadows {
renderer.render(context); renderer.render(context);
prevActualCastersMask |= edgeBit; prevActualCastersMask |= edgeBit;
} }
else{ else {
// Если относительно одной из камер ничего не менялось, не вызываем отрисовочный вызов // Если относительно одной из камер ничего не менялось, не вызываем отрисовочный вызов
if ((prevActualCastersMask & edgeBit)){ if ((prevActualCastersMask & edgeBit)) {
context.setRenderToTexture(cubeShadowMap, false, 0, i); context.setRenderToTexture(cubeShadowMap, false, 0, i);
context.clear(1, 0, 0, 0); context.clear(1, 0, 0, 0);
@@ -331,7 +342,7 @@ package alternativa.engine3d.shadows {
if (debugObject == null) { if (debugObject == null) {
debugObject = createDebugObject(debugMaterial, camera.context3D); debugObject = createDebugObject(debugMaterial, camera.context3D);
} }
debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius*debugRadiusScale; debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius * debugRadiusScale;
debugObject.composeTransforms(); debugObject.composeTransforms();
// Формируем матрицу трансформации для debugObject // Формируем матрицу трансформации для debugObject
@@ -344,15 +355,15 @@ package alternativa.engine3d.shadows {
actualCasters.length = 0; actualCasters.length = 0;
} }
private function collectActualChildren(root:Object3D):void{ private function collectActualChildren(root:Object3D):void {
for (var child:Object3D = root.childrenList; child != null; child = child.next) { for (var child:Object3D = root.childrenList; child != null; child = child.next) {
if (child.visible){ if (child.visible) {
// calculate transform matrices // calculate transform matrices
_light.lightToObjectTransform.combine(child.cameraToLocalTransform, _light.localToCameraTransform); _light.lightToObjectTransform.combine(child.cameraToLocalTransform, _light.localToCameraTransform);
child.localToLightTransform.combine(_light.cameraToLocalTransform, child.localToCameraTransform); child.localToLightTransform.combine(_light.cameraToLocalTransform, child.localToCameraTransform);
// collect actualCasters for light // collect actualCasters for light
if (child.boundBox == null || OmniLight(_light).checkBound(child)){ if (child.boundBox == null || OmniLight(_light).checkBound(child)) {
actualCasters[actualCastersCount] = child; actualCasters[actualCastersCount] = child;
actualCastersCount++; actualCastersCount++;
@@ -508,46 +519,45 @@ package alternativa.engine3d.shadows {
if (plane.x >= 0) if (plane.x >= 0)
if (plane.y >= 0) if (plane.y >= 0)
if (plane.z >= 0) { if (plane.z >= 0) {
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.maxX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.minY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.minX * plane.x + bb.minY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else { } else {
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.maxX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.minX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
else
if (plane.z >= 0) {
if (bb.maxX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.maxX*plane.x + bb.minY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras;
} }
else if (plane.z >= 0) {
if (bb.maxX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else {
if (bb.maxX * plane.x + bb.minY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.minX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
}
else if (plane.y >= 0) else if (plane.y >= 0)
if (plane.z >= 0) { if (plane.z >= 0) {
if (bb.minX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.minX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.minY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.maxX * plane.x + bb.minY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else { } else {
if (bb.minX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.minX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.maxX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
} }
else if (plane.z >= 0) { else if (plane.z >= 0) {
if (bb.minX*plane.x + bb.minY*plane.y + bb.maxZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.minX * plane.x + bb.minY * plane.y + bb.maxZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.minZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.maxX * plane.x + bb.maxY * plane.y + bb.minZ * plane.z < plane.offset) result |= plane.backCameras;
} else { } else {
if (bb.minX*plane.x + bb.minY*plane.y + bb.minZ*plane.z >= plane.offset) result = plane.frontCameras; if (bb.minX * plane.x + bb.minY * plane.y + bb.minZ * plane.z >= plane.offset) result = plane.frontCameras;
if (bb.maxX*plane.x + bb.maxY*plane.y + bb.maxZ*plane.z < plane.offset) result |= plane.backCameras; if (bb.maxX * plane.x + bb.maxY * plane.y + bb.maxZ * plane.z < plane.offset) result |= plane.backCameras;
} }
culling &= result | plane.unusedBits; culling &= result | plane.unusedBits;
} }
return culling; return culling;
} }
private function collectDraws(context:Context3D, caster:Object3D, edgeCamera:Camera3D):void{ private function collectDraws(context:Context3D, caster:Object3D, edgeCamera:Camera3D):void {
// если объект является мешем, собираем для него дроуколы // если объект является мешем, собираем для него дроуколы
var mesh:Mesh = caster as Mesh; var mesh:Mesh = caster as Mesh;
if (mesh != null && mesh.geometry != null) { if (mesh != null && mesh.geometry != null) {
var program:ShaderProgram; var program:ShaderProgram;
var programListByTransformProcedure:Vector.<ShaderProgram>; var programListByTransformProcedure:Vector.<ShaderProgram>;
var skin:Skin = mesh as Skin; var skin:Skin = mesh as Skin;
// пробегаемся по сурфейсам // пробегаемся по сурфейсам
@@ -617,7 +627,7 @@ package alternativa.engine3d.shadows {
drawUnit.setProjectionConstants(edgeCamera, program.vertexShader.getVariableIndex("cProjMatrix"), casterToEdgedCameraTransform); drawUnit.setProjectionConstants(edgeCamera, program.vertexShader.getVariableIndex("cProjMatrix"), casterToEdgedCameraTransform);
drawUnit.setVertexConstantsFromTransform(program.vertexShader.getVariableIndex("cCasterToOmni"), caster.localToLightTransform); drawUnit.setVertexConstantsFromTransform(program.vertexShader.getVariableIndex("cCasterToOmni"), caster.localToLightTransform);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 255/radius, 1); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cConstants"), 1 / 255, 0, 255 / radius, 1);
renderer.addDrawUnit(drawUnit, Renderer.OPAQUE); renderer.addDrawUnit(drawUnit, Renderer.OPAQUE);
} }
@@ -654,74 +664,73 @@ package alternativa.engine3d.shadows {
private function getProgram(transformProcedure:Procedure, programListByTransformProcedure:Vector.<ShaderProgram>, context:Context3D, alphaTest:Boolean, useDiffuseAlpha:Boolean):ShaderProgram { private function getProgram(transformProcedure:Procedure, programListByTransformProcedure:Vector.<ShaderProgram>, context:Context3D, alphaTest:Boolean, useDiffuseAlpha:Boolean):ShaderProgram {
var key:int = (alphaTest ? (useDiffuseAlpha ? 1 : 2) : 0); var key:int = (alphaTest ? (useDiffuseAlpha ? 1 : 2) : 0);
var program:ShaderProgram = programListByTransformProcedure[key]; var program:ShaderProgram = programListByTransformProcedure[key];
if (program == null) { if (program == null) {
var vLinker:Linker = new Linker(Context3DProgramType.VERTEX); var vLinker:Linker = new Linker(Context3DProgramType.VERTEX);
var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); var fLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
var positionVar:String = "aPosition"; var positionVar:String = "aPosition";
vLinker.declareVariable(positionVar, VariableType.ATTRIBUTE); vLinker.declareVariable(positionVar, VariableType.ATTRIBUTE);
if (alphaTest) { if (alphaTest) {
vLinker.addProcedure(passUVProcedure); vLinker.addProcedure(passUVProcedure);
} }
if (transformProcedure != null) { if (transformProcedure != null) {
var newPosVar:String = "tTransformedPosition"; var newPosVar:String = "tTransformedPosition";
vLinker.declareVariable(newPosVar); vLinker.declareVariable(newPosVar);
vLinker.addProcedure(transformProcedure, positionVar); vLinker.addProcedure(transformProcedure, positionVar);
vLinker.setOutputParams(transformProcedure, newPosVar); vLinker.setOutputParams(transformProcedure, newPosVar);
positionVar = newPosVar; positionVar = newPosVar;
} }
var proc:Procedure = Procedure.compileFromArray([ var proc:Procedure = Procedure.compileFromArray([
"#v0=vDistance", "#v0=vDistance",
"m34 t0.xyz, i0, c2", "m34 t0.xyz, i0, c2",
"mov v0, t0.xyzx", "mov v0, t0.xyzx",
"m44 o0, i0, c0" "m44 o0, i0, c0"
]); ]);
proc.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4); proc.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4);
proc.assignVariableName(VariableType.CONSTANT, 2, "cCasterToOmni", 3); proc.assignVariableName(VariableType.CONSTANT, 2, "cCasterToOmni", 3);
vLinker.addProcedure(proc, positionVar); vLinker.addProcedure(proc, positionVar);
if (alphaTest) { if (alphaTest) {
if (useDiffuseAlpha) { if (useDiffuseAlpha) {
fLinker.addProcedure(diffuseAlphaTestProcedure); fLinker.addProcedure(diffuseAlphaTestProcedure);
} else { } else {
fLinker.addProcedure(opacityAlphaTestProcedure); fLinker.addProcedure(opacityAlphaTestProcedure);
} }
} }
fLinker.addProcedure(Procedure.compileFromArray([ fLinker.addProcedure(Procedure.compileFromArray([
"#v0=vDistance", // xyz "#v0=vDistance", // xyz
"#c0=cConstants", // 1/255, 0, 255/radius, 1 "#c0=cConstants", // 1/255, 0, 255/radius, 1
// calculate distance // calculate distance
"dp3 t0.z, v0.xyz, v0.xyz", "dp3 t0.z, v0.xyz, v0.xyz",
"sqt t0.z, t0.z", // x: [0, radius] "sqt t0.z, t0.z", // x: [0, radius]
"mul t0.z, t0.z, c0.z", // x: [0, 255] "mul t0.z, t0.z, c0.z", // x: [0, 255]
// codeing // codeing
"frc t0.y, t0.z", "frc t0.y, t0.z",
"sub t0.x, t0.z, t0.y", "sub t0.x, t0.z, t0.y",
"mul t0.x, t0.x, c0.x", "mul t0.x, t0.x, c0.x",
"mov t0.w, c0.w", "mov t0.w, c0.w",
"mov o0, t0" "mov o0, t0"
])); ]));
program = new ShaderProgram(vLinker, fLinker); program = new ShaderProgram(vLinker, fLinker);
fLinker.varyings = vLinker.varyings; fLinker.varyings = vLinker.varyings;
programListByTransformProcedure[key] = program; programListByTransformProcedure[key] = program;
program.upload(context); program.upload(context);
} }
return program; return program;
} }
//------------- ShadowMap Shader in material---------- //------------- ShadowMap Shader in material----------
/** /**
@@ -737,12 +746,12 @@ package alternativa.engine3d.shadows {
// Устанавливаем коеффициенты // Устанавливаем коеффициенты
if (_pcfOffset > 0) { if (_pcfOffset > 0) {
var offset:Number = Math.tan(_pcfOffset/180*Math.PI)/3; var offset:Number = Math.tan(_pcfOffset / 180 * Math.PI) / 3;
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3/2, 1/16, 0, 0); drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cPCFOffsets"), -3 / 2, 1 / 16, 0, 0);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset); drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -1, 1, 0, offset);
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER/255, biasMultiplier*DIFFERENCE_MULTIPLIER/radius, 10); drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cDecode"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER / 255, biasMultiplier * DIFFERENCE_MULTIPLIER / radius, 10);
} else { } else {
drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER/255, biasMultiplier*DIFFERENCE_MULTIPLIER/radius, 1.0); drawUnit.setFragmentConstantsFromNumbers(fragmentLinker.getVariableIndex("cConstants"), -DIFFERENCE_MULTIPLIER, -DIFFERENCE_MULTIPLIER / 255, biasMultiplier * DIFFERENCE_MULTIPLIER / radius, 1.0);
} }
} }
@@ -834,7 +843,7 @@ package alternativa.engine3d.shadows {
// shaderArr[line++] = "mov t3.z, t0.w"; // shaderArr[line++] = "mov t3.z, t0.w";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число shaderArr[line++] = "dp3 o0." + componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
//----- //-----
@@ -842,7 +851,7 @@ package alternativa.engine3d.shadows {
shaderArr[line++] = "add t2.xyz, t2.xyz, t1.xyz"; shaderArr[line++] = "add t2.xyz, t2.xyz, t1.xyz";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число shaderArr[line++] = "dp3 o0." + componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
} }
shaderArr[line++] = "sat o0, o0"; shaderArr[line++] = "sat o0, o0";
@@ -854,13 +863,13 @@ package alternativa.engine3d.shadows {
shaderArr[line++] = "add t2.xyz, t2.xyz, t0.xyz"; shaderArr[line++] = "add t2.xyz, t2.xyz, t0.xyz";
shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число shaderArr[line++] = "dp3 o0." + componentByIndex[0] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
for (j = 1; j < 4; j++){ for (j = 1; j < 4; j++) {
shaderArr[line++] = (i%2 == 1)?("add t2.xyz, t2.xyz, t1.xyz"):("sub t2.xyz, t2.xyz, t1.xyz"); shaderArr[line++] = (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 <cube, nearest>"; shaderArr[line++] = "tex t3.xy, t2.xyz, s0 <cube, nearest>";
shaderArr[line++] = "dp3 o0." +componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число shaderArr[line++] = "dp3 o0." + componentByIndex[j] + ", t3.xyz, c0.xyz"; // декодируем, вычитаем, умножаем на большое число
} }
shaderArr[line++] = "sat o0, o0"; shaderArr[line++] = "sat o0, o0";
shaderArr[line++] = "dp4 o0.x, o0, c2.y"; shaderArr[line++] = "dp4 o0.x, o0, c2.y";
@@ -876,8 +885,8 @@ package alternativa.engine3d.shadows {
private static const componentByIndex:Array = ["x", "y", "z", "w"]; private static const componentByIndex:Array = ["x", "y", "z", "w"];
/** /**
* Добавляет <code>object</code> в список объектов, отбрасывающих тень. * Adds given object to list of objects, that cast shadow.
* @param object Добавляемый объект. * @param object Added object.
*/ */
public function addCaster(object:Object3D):void { public function addCaster(object:Object3D):void {
if (_casters.indexOf(object) < 0) { if (_casters.indexOf(object) < 0) {
@@ -885,6 +894,10 @@ package alternativa.engine3d.shadows {
} }
} }
/**
* Removes given object from shadow casters list.
* @param object Object which should be removed from shadow casters list.
*/
public function removeCaster(object:Object3D):void { public function removeCaster(object:Object3D):void {
var index:int = _casters.indexOf(object); var index:int = _casters.indexOf(object);
if (index < 0) throw new Error("Caster not found"); if (index < 0) throw new Error("Caster not found");
@@ -892,14 +905,15 @@ package alternativa.engine3d.shadows {
} }
/** /**
* Очищает список объектов, отбрасывающих тень. * Clears the list of objects, that cast shadow.
*/ */
public function clearCasters():void { public function clearCasters():void {
_casters.length = 0; _casters.length = 0;
} }
/** /**
* Качество тени. Задает разрешение shadowmap. Может принимать значения от <code>2</code> до <code>11</code>. * Set resolution of shadow map. This property can get value of power of 2 (up to 2048).
* OmniLightShadow uses 6 shadow maps.
*/ */
public function get mapSize():int { public function get mapSize():int {
return _mapSize; return _mapSize;
@@ -916,7 +930,7 @@ package alternativa.engine3d.shadows {
} else if (value > 1024) { } else if (value > 1024) {
throw new ArgumentError("Map size exceeds maximum value 1024."); throw new ArgumentError("Map size exceeds maximum value 1024.");
} }
if ((Math.log(value)/Math.LN2 % 1) != 0) { if ((Math.log(value) / Math.LN2 % 1) != 0) {
throw new ArgumentError("Map size must be power of two."); throw new ArgumentError("Map size must be power of two.");
} }
if (cubeShadowMap != null) { if (cubeShadowMap != null) {
@@ -927,8 +941,7 @@ package alternativa.engine3d.shadows {
} }
/** /**
* Смещение Percentage Closer Filtering. Этот способ фильтрации используется для смягчения границ тени. * Offset of Percentage Closer Filtering. This way of filtering is used for mitigation of shadow bounds.
* 1 pcfOffset equivalent 1 degree for all blur
*/ */
public function get pcfOffset():Number { public function get pcfOffset():Number {
return _pcfOffset; return _pcfOffset;
@@ -971,6 +984,7 @@ import flash.utils.Dictionary;
class ShadowDebugMaterial extends Material { class ShadowDebugMaterial extends Material {
use namespace alternativa3d; use namespace alternativa3d;
/** /**
* Прозрачность. * Прозрачность.
* Является дополнительным множителем к прозрачности текстуры. * Является дополнительным множителем к прозрачности текстуры.
@@ -1015,7 +1029,7 @@ class ShadowDebugMaterial extends Material {
drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aPosition"), positionBuffer, geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]); drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aPosition"), positionBuffer, geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]);
// Установка констант // Установка констант
drawUnit.setProjectionConstants(camera, program.vertexShader.getVariableIndex("cProjMatrix"), object.localToCameraTransform); drawUnit.setProjectionConstants(camera, program.vertexShader.getVariableIndex("cProjMatrix"), object.localToCameraTransform);
drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cDecode"), 1, 1/255, 0, alpha); drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cDecode"), 1, 1 / 255, 0, alpha);
drawUnit.setTextureAt(program.fragmentShader.getVariableIndex("sCubeMap"), cubeMap); drawUnit.setTextureAt(program.fragmentShader.getVariableIndex("sCubeMap"), cubeMap);
// Отправка на отрисовку // Отправка на отрисовку