From ce0ebaa8f29358b1b8c5b3aedc83d05587dc9c29 Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Fri, 8 Jun 2012 18:38:14 +0600 Subject: [PATCH 1/7] qqq --- .../engine3d/materials/ShaderProgram.as | 3 +- .../engine3d/materials/StandardMaterial.as | 54 +++++++++++-------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/alternativa/engine3d/materials/ShaderProgram.as b/src/alternativa/engine3d/materials/ShaderProgram.as index 339c2c0..edef8f8 100644 --- a/src/alternativa/engine3d/materials/ShaderProgram.as +++ b/src/alternativa/engine3d/materials/ShaderProgram.as @@ -19,7 +19,8 @@ package alternativa.engine3d.materials { * @private */ public class ShaderProgram { - + + public var key:String; public var program:Program3D; public var vertexShader:Linker; diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 73f462d..c1018cc 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -53,7 +53,7 @@ package alternativa.engine3d.materials { private static var caches:Dictionary = new Dictionary(true); private var cachedContext3D:Context3D; - private var programsCache:Dictionary; + private var programsCache:Vector.; private var groups:Vector.> = new Vector.>(); /** @@ -515,9 +515,16 @@ package alternativa.engine3d.materials { * @param directionalLight * @param lightsLength */ - private function getProgram(object:Object3D, programs:Dictionary, camera:Camera3D, materialKey:String, opacityMap:TextureResource, alphaTest:int, lightsGroup:Vector., lightsLength:int, isFirstGroup:Boolean, shadowedLight:Light3D):StandardMaterialProgram { + private function getProgram(object:Object3D, programs:Vector., camera:Camera3D, materialKey:String, opacityMap:TextureResource, alphaTest:int, lightsGroup:Vector., lightsLength:int, isFirstGroup:Boolean, shadowedLight:Light3D):StandardMaterialProgram { var key:String = materialKey + (opacityMap != null ? "O" : "o") + alphaTest.toString(); - var program:StandardMaterialProgram = programs[key]; + var program:StandardMaterialProgram = null;//programs[key]; + + for (var i:int = 0; i(); caches[cachedContext3D] = programsCache; } } - var optionsPrograms:Dictionary = programsCache[object.transformProcedure]; - if (optionsPrograms == null) { - optionsPrograms = new Dictionary(false); - programsCache[object.transformProcedure] = optionsPrograms; - } +// var optionsPrograms:Dictionary = programsCache[object.transformProcedure]; +// if (optionsPrograms == null) { +// optionsPrograms = new Dictionary(false); +// programsCache[object.transformProcedure] = optionsPrograms; +// } // Form groups of lights var groupsCount:int = 0; @@ -1040,11 +1048,11 @@ package alternativa.engine3d.materials { if (alphaThreshold > 0) { // Alpha test // use opacityMap if it is presented - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 1, null, 0, true, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 1, null, 0, true, null); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, true, null, true, false, objectRenderPriority); } else { // do not use opacityMap at all - program = getProgram(object, optionsPrograms, camera, materialKey, null, 0, null, 0, true, null); + program = getProgram(object, programsCache, camera, materialKey, null, 0, null, 0, true, null); addDrawUnits(program, camera, surface, geometry, null, null, 0, true, null, true, false, objectRenderPriority); } } @@ -1053,11 +1061,11 @@ package alternativa.engine3d.materials { // use opacityMap if it is presented if (alphaThreshold <= alpha && !opaquePass) { // Alpha threshold - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 2, null, 0, true, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 2, null, 0, true, null); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, true, null, false, true, objectRenderPriority); } else { // There is no Alpha threshold or check z-buffer by previous pass - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 0, null, 0, true, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 0, null, 0, true, null); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, true, null, false, true, objectRenderPriority); } } @@ -1086,11 +1094,11 @@ package alternativa.engine3d.materials { if (alphaThreshold > 0) { // Alpha test // use opacityMap if it is presented - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 1, lightGroup, lightGroupLength, isFirstGroup, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 1, lightGroup, lightGroupLength, isFirstGroup, null); addDrawUnits(program, camera, surface, geometry, opacityMap, lightGroup, lightGroupLength, isFirstGroup, null, true, false, objectRenderPriority); } else { // do not use opacityMap at all - program = getProgram(object, optionsPrograms, camera, materialKey, null, 0, lightGroup, lightGroupLength, isFirstGroup, null); + program = getProgram(object, programsCache, camera, materialKey, null, 0, lightGroup, lightGroupLength, isFirstGroup, null); addDrawUnits(program, camera, surface, geometry, null, lightGroup, lightGroupLength, isFirstGroup, null, true, false, objectRenderPriority); } } @@ -1099,11 +1107,11 @@ package alternativa.engine3d.materials { // use opacityMap if it is presented if (alphaThreshold <= alpha && !opaquePass) { // Alpha threshold - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 2, lightGroup, lightGroupLength, isFirstGroup, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 2, lightGroup, lightGroupLength, isFirstGroup, null); addDrawUnits(program, camera, surface, geometry, opacityMap, lightGroup, lightGroupLength, isFirstGroup, null, false, true, objectRenderPriority); } else { // There is no Alpha threshold or check z-buffer by previous pass - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 0, lightGroup, lightGroupLength, isFirstGroup, null); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 0, lightGroup, lightGroupLength, isFirstGroup, null); addDrawUnits(program, camera, surface, geometry, opacityMap, lightGroup, lightGroupLength, isFirstGroup, null, false, true, objectRenderPriority); } } @@ -1132,11 +1140,11 @@ package alternativa.engine3d.materials { if (alphaThreshold > 0) { // Alpha test // use opacityMap if it is presented - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 1, null, 0, isFirstGroup, light); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 1, null, 0, isFirstGroup, light); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, isFirstGroup, light, true, false, objectRenderPriority); } else { // do not use opacityMap at all - program = getProgram(object, optionsPrograms, camera, materialKey, null, 0, null, 0, isFirstGroup, light); + program = getProgram(object, programsCache, camera, materialKey, null, 0, null, 0, isFirstGroup, light); addDrawUnits(program, camera, surface, geometry, null, null, 0, isFirstGroup, light, true, false, objectRenderPriority); } } @@ -1145,11 +1153,11 @@ package alternativa.engine3d.materials { // use opacityMap if it is presented if (alphaThreshold <= alpha && !opaquePass) { // Alpha threshold - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 2, null, 0, isFirstGroup, light); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 2, null, 0, isFirstGroup, light); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, isFirstGroup, light, false, true, objectRenderPriority); } else { // There is no Alpha threshold or check z-buffer by previous pass - program = getProgram(object, optionsPrograms, camera, materialKey, opacityMap, 0, null, 0, isFirstGroup, light); + program = getProgram(object, programsCache, camera, materialKey, opacityMap, 0, null, 0, isFirstGroup, light); addDrawUnits(program, camera, surface, geometry, opacityMap, null, 0, isFirstGroup, light, false, true, objectRenderPriority); } } From efca42c57bae91b1a69e68eeeac28b2a6966a286 Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Wed, 13 Jun 2012 14:24:38 +0600 Subject: [PATCH 2/7] materialKey -> int --- .../engine3d/materials/StandardMaterial.as | 100 +++++++++++++----- 1 file changed, 72 insertions(+), 28 deletions(-) diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index c1018cc..9cf3dcc 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -51,9 +51,21 @@ package alternativa.engine3d.materials { */ public class StandardMaterial extends TextureMaterial { + private static const LIGHT_MAP:int = 1; + private static const GLOSSINESS_MAP:int = 2; + private static const SPECULAR_MAP:int = 4; + private static const OPACITY_MAP:int = 8; + private static const NORMAL_MAP_SPACE_BIT:int = 4; + private static const ALPHA_TEST_BIT:int = 6; + private static const OMNI_LIGHT_BIT:int = 8; + private static const DIRECTIONAL_LIGHT_BIT:int = 11; + private static const SPOT_LIGHT_BIT:int = 14; + private static const OBJECT_TYPE_BIT:int = 17; + + private static var caches:Dictionary = new Dictionary(true); private var cachedContext3D:Context3D; - private var programsCache:Vector.; + private var programsCache:Array; private var groups:Vector.> = new Vector.>(); /** @@ -515,16 +527,17 @@ package alternativa.engine3d.materials { * @param directionalLight * @param lightsLength */ - private function getProgram(object:Object3D, programs:Vector., camera:Camera3D, materialKey:String, opacityMap:TextureResource, alphaTest:int, lightsGroup:Vector., lightsLength:int, isFirstGroup:Boolean, shadowedLight:Light3D):StandardMaterialProgram { - var key:String = materialKey + (opacityMap != null ? "O" : "o") + alphaTest.toString(); - var program:StandardMaterialProgram = null;//programs[key]; - - for (var i:int = 0; i, lightsLength:int, isFirstGroup:Boolean, shadowedLight:Light3D):StandardMaterialProgram { + var key:int = materialKey + (opacityMap != null ? OPACITY_MAP : 0) + alphaTest << ALPHA_TEST_BIT; + var program:StandardMaterialProgram = programs[key]; +// var programsCount:int = programs.length; +// for (var i:int = 0; i(); + programsCache = new Array(); caches[cachedContext3D] = programsCache; } } @@ -1034,15 +1047,18 @@ package alternativa.engine3d.materials { } // Iterate groups - var materialKey:String; + var materialKey:int; var program:StandardMaterialProgram; + var OmniLightCount:int = 0; + var DirectionalLightCount:int = 0; + var SpotLightCount:int = 0; if (groupsCount == 0 && shadowGroupLength == 0) { // There is only Ambient light on the scene // Form key - materialKey = (lightMap != null) ? "L" : "l"+ - ((glossinessMap != null) ? "G" : "g") + - ((specularMap != null) ? "S" : "s"); + materialKey = (lightMap != null) ? LIGHT_MAP : 0 + + (glossinessMap != null) ? GLOSSINESS_MAP : 0 + + (specularMap != null) ? SPECULAR_MAP : 0; if (opaquePass && alphaThreshold <= alpha) { if (alphaThreshold > 0) { @@ -1078,15 +1094,21 @@ package alternativa.engine3d.materials { // Group of lights without shadow // Form key - materialKey = (isFirstGroup)?((lightMap != null) ? "L" : "l"):""; + materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP : 0) : 0; materialKey += - (_normalMapSpace.toString()) + - ((glossinessMap != null) ? "G" : "g") + - ((specularMap != null) ? "S" : "s"); + ((_normalMapSpace==NormalMapSpace.OBJECT) ? 1 : (_normalMapSpace==NormalMapSpace.TANGENT_LEFT_HANDED) ? 2 : 3) << NORMAL_MAP_SPACE_BIT + + (glossinessMap != null) ? GLOSSINESS_MAP : 0 + + (specularMap != null) ? SPECULAR_MAP : 0; for (j = 0; j < lightGroupLength; j++) { light = lightGroup[j]; - materialKey += light.lightID; + if (light is OmniLight) OmniLightCount++; + else if (light is DirectionalLight) DirectionalLightCount++; + else if (light is SpotLight) SpotLightCount++; } + materialKey += OmniLightCount << OMNI_LIGHT_BIT; + materialKey += DirectionalLightCount << DIRECTIONAL_LIGHT_BIT; + materialKey += SpotLightCount << SPOT_LIGHT_BIT; + // Create program and drawUnit for group // Opaque pass @@ -1126,13 +1148,35 @@ package alternativa.engine3d.materials { light = shadowGroup[j]; // Form key - materialKey = (isFirstGroup)?((lightMap != null) ? "L" : "l"):""; + materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP : 0) : 0; materialKey += - (_normalMapSpace.toString()) + - ((glossinessMap != null) ? "G" : "g") + - ((specularMap != null) ? "S" : "s"); - materialKey += light.shadow.type; - materialKey += light.lightID; + ((_normalMapSpace==NormalMapSpace.OBJECT) ? 1 : (_normalMapSpace==NormalMapSpace.TANGENT_LEFT_HANDED) ? 2 : 3) << NORMAL_MAP_SPACE_BIT + + (glossinessMap != null) ? GLOSSINESS_MAP : 0 + + (specularMap != null) ? SPECULAR_MAP : 0; + + // TODO: rewrite + switch (light.shadow.type){ + case "OS": + materialKey += 7 << OMNI_LIGHT_BIT; + break; + case "os": + materialKey += 6 << OMNI_LIGHT_BIT; + break; + case "DS": + materialKey += 7 << DIRECTIONAL_LIGHT_BIT; + break; + case "ds": + materialKey += 6 << DIRECTIONAL_LIGHT_BIT; + break; + } + +// if (light is OmniLight) OmniLightCount++; +// else if (light is DirectionalLight) DirectionalLightCount++; +// else if (light is SpotLight) SpotLightCount++; +// +// materialKey += light.shadow.type; +// materialKey += light.lightID; + // Для группы создаем программу и дроуюнит // Opaque pass From 12a3e5c8e9c9a2d6b474b5217bcc430aaedc3ab7 Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Wed, 13 Jun 2012 17:54:35 +0600 Subject: [PATCH 3/7] shadow type --- .../engine3d/materials/StandardMaterial.as | 25 +++---------------- .../shadows/DirectionalLightShadow.as | 4 +-- .../engine3d/shadows/OmniLightShadow.as | 4 +-- src/alternativa/engine3d/shadows/Shadow.as | 5 +++- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index f0691c8..0f17b98 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -1145,28 +1145,9 @@ package alternativa.engine3d.materials { (glossinessMap != null) ? GLOSSINESS_MAP : 0 + (specularMap != null) ? SPECULAR_MAP : 0; - // TODO: rewrite - switch (light.shadow.type){ - case "OS": - materialKey += 7 << OMNI_LIGHT_BIT; - break; - case "os": - materialKey += 6 << OMNI_LIGHT_BIT; - break; - case "DS": - materialKey += 7 << DIRECTIONAL_LIGHT_BIT; - break; - case "ds": - materialKey += 6 << DIRECTIONAL_LIGHT_BIT; - break; - } - -// if (light is OmniLight) OmniLightCount++; -// else if (light is DirectionalLight) DirectionalLightCount++; -// else if (light is SpotLight) SpotLightCount++; -// -// materialKey += light.shadow.type; -// materialKey += light.lightID; + if (light is OmniLight) materialKey += light.shadow.type << OMNI_LIGHT_BIT; + else if (light is DirectionalLight) materialKey += light.shadow.type << DIRECTIONAL_LIGHT_BIT; + else if (light is SpotLight) materialKey += light.shadow.type << SPOT_LIGHT_BIT; // Для группы создаем программу и дроуюнит diff --git a/src/alternativa/engine3d/shadows/DirectionalLightShadow.as b/src/alternativa/engine3d/shadows/DirectionalLightShadow.as index 6ab2a00..154a6be 100644 --- a/src/alternativa/engine3d/shadows/DirectionalLightShadow.as +++ b/src/alternativa/engine3d/shadows/DirectionalLightShadow.as @@ -214,7 +214,7 @@ package alternativa.engine3d.shadows { this._mapSize = mapSize; this._pcfOffset = pcfOffset; - this.type = _pcfOffset > 0 ? "DS" : "ds"; + this.type = _pcfOffset > 0 ? Shadow.PCF_MODE : Shadow.SIMPLE_MODE; vertexShadowProcedure = getVShader(); fragmentShadowProcedure = _pcfOffset > 0 ? getFShaderPCF() : getFShader(); @@ -866,7 +866,7 @@ package alternativa.engine3d.shadows { */ public function set pcfOffset(value:Number):void { _pcfOffset = value; - type = _pcfOffset > 0 ? "S" : "s"; + type = _pcfOffset > 0 ? Shadow.PCF_MODE : Shadow.SIMPLE_MODE; fragmentShadowProcedure = _pcfOffset > 0 ? getFShaderPCF() : getFShader(); } diff --git a/src/alternativa/engine3d/shadows/OmniLightShadow.as b/src/alternativa/engine3d/shadows/OmniLightShadow.as index 8310ece..7d92b72 100644 --- a/src/alternativa/engine3d/shadows/OmniLightShadow.as +++ b/src/alternativa/engine3d/shadows/OmniLightShadow.as @@ -104,7 +104,7 @@ package alternativa.engine3d.shadows { this.pcfOffset = pcfOffset; vertexShadowProcedure = getVShader(); - type = _pcfOffset > 0 ? "OS" : "os"; + type = _pcfOffset > 0 ? Shadow.PCF_MODE : Shadow.SIMPLE_MODE; fragmentShadowProcedure = _pcfOffset > 0 ? getFShaderPCF() : getFShader(); debugMaterial = new ShadowDebugMaterial(); @@ -939,7 +939,7 @@ package alternativa.engine3d.shadows { */ public function set pcfOffset(value:Number):void { _pcfOffset = value; - type = _pcfOffset > 0 ? "OS" : "os"; + type = _pcfOffset > 0 ? Shadow.PCF_MODE : Shadow.SIMPLE_MODE; fragmentShadowProcedure = _pcfOffset > 0 ? getFShaderPCF() : getFShader(); } diff --git a/src/alternativa/engine3d/shadows/Shadow.as b/src/alternativa/engine3d/shadows/Shadow.as index 8b67f97..03628d0 100644 --- a/src/alternativa/engine3d/shadows/Shadow.as +++ b/src/alternativa/engine3d/shadows/Shadow.as @@ -23,6 +23,9 @@ package alternativa.engine3d.shadows { */ public class Shadow { + alternativa3d static const SIMPLE_MODE:int = 6; + alternativa3d static const PCF_MODE:int = 7; + /** * Debug mode. */ @@ -32,7 +35,7 @@ package alternativa.engine3d.shadows { * @private * Key for processing in materials. */ - alternativa3d var type:String = "s"; + alternativa3d var type:int = 6; /** * @private From 53677cda9b4fb3d6bda33e7a798abb3663f267ed Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Wed, 13 Jun 2012 18:18:47 +0600 Subject: [PATCH 4/7] shadow type --- src/alternativa/engine3d/materials/StandardMaterial.as | 1 - 1 file changed, 1 deletion(-) diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 0f17b98..59e5ba0 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -1149,7 +1149,6 @@ package alternativa.engine3d.materials { else if (light is DirectionalLight) materialKey += light.shadow.type << DIRECTIONAL_LIGHT_BIT; else if (light is SpotLight) materialKey += light.shadow.type << SPOT_LIGHT_BIT; - // Для группы создаем программу и дроуюнит // Opaque pass if (opaquePass && alphaThreshold <= alpha) { From 0da520d22f27c8d333d1690ae6e50061452e211b Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Thu, 14 Jun 2012 18:36:35 +0600 Subject: [PATCH 5/7] Add light sort in camera --- src/alternativa/engine3d/core/Camera3D.as | 36 +++++++++ src/alternativa/engine3d/core/Light3D.as | 11 +++ .../engine3d/lights/AmbientLight.as | 1 + .../engine3d/lights/DirectionalLight.as | 1 + src/alternativa/engine3d/lights/OmniLight.as | 1 + src/alternativa/engine3d/lights/SpotLight.as | 1 + .../engine3d/materials/ShaderProgram.as | 1 - .../engine3d/materials/StandardMaterial.as | 77 +++++++++---------- .../engine3d/materials/TextureMaterial.as | 1 + src/alternativa/engine3d/shadows/Shadow.as | 7 +- 10 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/alternativa/engine3d/core/Camera3D.as b/src/alternativa/engine3d/core/Camera3D.as index 9f792e3..ab1cbc7 100644 --- a/src/alternativa/engine3d/core/Camera3D.as +++ b/src/alternativa/engine3d/core/Camera3D.as @@ -319,6 +319,10 @@ public class Camera3D extends Object3D { } lightsLength = j; lights.length = j; + + // Sort lights by types + if (lightsLength > 0) sortLights(0, lightsLength - 1); + // Check getting in frustum and occluding if (root.culling >= 0 && (root.boundBox == null || occludersLength == 0 || !root.boundBox.checkOcclusion(occluders, occludersLength, root.localToCameraTransform))) { // Check if the ray crossing the bounding box @@ -397,6 +401,38 @@ public class Camera3D extends Object3D { cpuTimer = -1; } + + /** + * @private + */ + private function sortLights(l:int, r:int):void { + var i:int = l; + var j:int = r; + var left:Light3D; + var index:int = (r + l) >> 1; + var m:Light3D = lights[index]; + var mid:int = m.type; + var right:Light3D; + do { + while ((left = lights[i]).type < mid) { + i++; + } + while (mid < (right = lights[j]).type) { + j--; + } + if (i <= j) { + lights[i++] = right; + lights[j--] = left; + } + } while (i <= j); + if (l < j) { + sortLights(l, j); + } + if (i < r) { + sortLights(i, r); + } + } + /** * Transforms point from global space to screen space. The view property should be defined. * @param point Point in global space. diff --git a/src/alternativa/engine3d/core/Light3D.as b/src/alternativa/engine3d/core/Light3D.as index 31fae99..2554144 100644 --- a/src/alternativa/engine3d/core/Light3D.as +++ b/src/alternativa/engine3d/core/Light3D.as @@ -24,6 +24,16 @@ package alternativa.engine3d.core { */ public class Light3D extends Object3D { + /** + * @private + */ + alternativa3d var type:int = 0; + alternativa3d static const AMBIENT:int = 1; + alternativa3d static const DIRECTIONAL:int = 2; + alternativa3d static const OMNI:int = 3; + alternativa3d static const SPOT:int = 4; + alternativa3d static const SHADOW_BIT:int = 0x100; + /** * @private */ @@ -124,6 +134,7 @@ package alternativa.engine3d.core { if (_shadow != null) _shadow._light = null; _shadow = value; if (value != null) value._light = this; + type = (value != null) ? type & ~SHADOW_BIT : type | SHADOW_BIT; } } } diff --git a/src/alternativa/engine3d/lights/AmbientLight.as b/src/alternativa/engine3d/lights/AmbientLight.as index 829462b..10fba53 100644 --- a/src/alternativa/engine3d/lights/AmbientLight.as +++ b/src/alternativa/engine3d/lights/AmbientLight.as @@ -30,6 +30,7 @@ package alternativa.engine3d.lights { * @param color Light color. */ public function AmbientLight(color:uint) { + this.type = AMBIENT; this.color = color; } diff --git a/src/alternativa/engine3d/lights/DirectionalLight.as b/src/alternativa/engine3d/lights/DirectionalLight.as index a5bc48f..a1e2547 100644 --- a/src/alternativa/engine3d/lights/DirectionalLight.as +++ b/src/alternativa/engine3d/lights/DirectionalLight.as @@ -31,6 +31,7 @@ package alternativa.engine3d.lights { * @param color Color of light source. */ public function DirectionalLight(color:uint) { + this.type = DIRECTIONAL; this.color = color; } diff --git a/src/alternativa/engine3d/lights/OmniLight.as b/src/alternativa/engine3d/lights/OmniLight.as index ee23aec..07c55ae 100644 --- a/src/alternativa/engine3d/lights/OmniLight.as +++ b/src/alternativa/engine3d/lights/OmniLight.as @@ -39,6 +39,7 @@ package alternativa.engine3d.lights { * @param attenuationEnd Distance from at which falloff is complete. */ public function OmniLight(color:uint, attenuationBegin:Number, attenuationEnd:Number) { + this.type = OMNI; this.color = color; this.attenuationBegin = attenuationBegin; this.attenuationEnd = attenuationEnd; diff --git a/src/alternativa/engine3d/lights/SpotLight.as b/src/alternativa/engine3d/lights/SpotLight.as index fdd8d9e..4f54935 100644 --- a/src/alternativa/engine3d/lights/SpotLight.as +++ b/src/alternativa/engine3d/lights/SpotLight.as @@ -54,6 +54,7 @@ package alternativa.engine3d.lights { * @param falloff Adjusts the angle of a light's falloff. The Falloff value is measured in radians. */ public function SpotLight(color:uint, attenuationBegin:Number, attenuationEnd:Number, hotspot:Number, falloff:Number) { + this.type = SPOT; this.color = color; this.attenuationBegin = attenuationBegin; this.attenuationEnd = attenuationEnd; diff --git a/src/alternativa/engine3d/materials/ShaderProgram.as b/src/alternativa/engine3d/materials/ShaderProgram.as index edef8f8..6c928ed 100644 --- a/src/alternativa/engine3d/materials/ShaderProgram.as +++ b/src/alternativa/engine3d/materials/ShaderProgram.as @@ -20,7 +20,6 @@ package alternativa.engine3d.materials { */ public class ShaderProgram { - public var key:String; public var program:Program3D; public var vertexShader:Linker; diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 59e5ba0..b22080a 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -51,17 +51,18 @@ package alternativa.engine3d.materials { */ public class StandardMaterial extends TextureMaterial { - private static const LIGHT_MAP:int = 1; - private static const GLOSSINESS_MAP:int = 2; - private static const SPECULAR_MAP:int = 4; - private static const OPACITY_MAP:int = 8; - private static const NORMAL_MAP_SPACE_BIT:int = 4; - private static const ALPHA_TEST_BIT:int = 6; - private static const OMNI_LIGHT_BIT:int = 8; - private static const DIRECTIONAL_LIGHT_BIT:int = 11; - private static const SPOT_LIGHT_BIT:int = 14; - private static const OBJECT_TYPE_BIT:int = 17; - + private static const LIGHT_MAP_BIT:int = 1; + private static const GLOSSINESS_MAP_BIT:int = 2; + private static const SPECULAR_MAP_BIT:int = 4; + private static const OPACITY_MAP_BIT:int = 8; + private static const NORMAL_MAP_SPACE_OFFSET:int = 4; // shift value + private static const ALPHA_TEST_OFFSET:int = 6; + private static const OMNI_LIGHT_OFFSET:int = 8; + private static const DIRECTIONAL_LIGHT_OFFSET:int = 11; + private static const SPOT_LIGHT_OFFSET:int = 14; + private static const SHADOW_OFFSET:int = 17; + // TODO: remove double cash by transform procedure. It increase speed by 1% +// private static const OBJECT_TYPE_BIT:int = 19; private static var caches:Dictionary = new Dictionary(true); private var cachedContext3D:Context3D; @@ -529,16 +530,9 @@ package alternativa.engine3d.materials { * @param lightsLength */ private function getProgram(object:Object3D, programs:Array, camera:Camera3D, materialKey:int, opacityMap:TextureResource, alphaTest:int, lightsGroup:Vector., lightsLength:int, isFirstGroup:Boolean, shadowedLight:Light3D):StandardMaterialProgram { - var key:int = materialKey + (opacityMap != null ? OPACITY_MAP : 0) + alphaTest << ALPHA_TEST_BIT; + var key:int = materialKey | (opacityMap != null ? OPACITY_MAP_BIT : 0) | (alphaTest << ALPHA_TEST_OFFSET); var program:StandardMaterialProgram = programs[key]; -// var programsCount:int = programs.length; -// for (var i:int = 0; i 0) { @@ -1085,20 +1079,20 @@ package alternativa.engine3d.materials { // Group of lights without shadow // Form key - materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP : 0) : 0; - materialKey += - ((_normalMapSpace==NormalMapSpace.OBJECT) ? 1 : (_normalMapSpace==NormalMapSpace.TANGENT_LEFT_HANDED) ? 2 : 3) << NORMAL_MAP_SPACE_BIT + - (glossinessMap != null) ? GLOSSINESS_MAP : 0 + - (specularMap != null) ? SPECULAR_MAP : 0; + materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP_BIT : 0) : 0; + materialKey |= + (_normalMapSpace << NORMAL_MAP_SPACE_OFFSET) | + ((glossinessMap != null) ? GLOSSINESS_MAP_BIT : 0) | + ((specularMap != null) ? SPECULAR_MAP_BIT : 0); for (j = 0; j < lightGroupLength; j++) { light = lightGroup[j]; if (light is OmniLight) OmniLightCount++; else if (light is DirectionalLight) DirectionalLightCount++; else if (light is SpotLight) SpotLightCount++; } - materialKey += OmniLightCount << OMNI_LIGHT_BIT; - materialKey += DirectionalLightCount << DIRECTIONAL_LIGHT_BIT; - materialKey += SpotLightCount << SPOT_LIGHT_BIT; + materialKey |= OmniLightCount << OMNI_LIGHT_OFFSET; + materialKey |= DirectionalLightCount << DIRECTIONAL_LIGHT_OFFSET; + materialKey |= SpotLightCount << SPOT_LIGHT_OFFSET; // Create program and drawUnit for group @@ -1139,15 +1133,14 @@ package alternativa.engine3d.materials { light = shadowGroup[j]; // Form key - materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP : 0) : 0; - materialKey += - ((_normalMapSpace==NormalMapSpace.OBJECT) ? 1 : (_normalMapSpace==NormalMapSpace.TANGENT_LEFT_HANDED) ? 2 : 3) << NORMAL_MAP_SPACE_BIT + - (glossinessMap != null) ? GLOSSINESS_MAP : 0 + - (specularMap != null) ? SPECULAR_MAP : 0; - - if (light is OmniLight) materialKey += light.shadow.type << OMNI_LIGHT_BIT; - else if (light is DirectionalLight) materialKey += light.shadow.type << DIRECTIONAL_LIGHT_BIT; - else if (light is SpotLight) materialKey += light.shadow.type << SPOT_LIGHT_BIT; + materialKey = (isFirstGroup)?((lightMap != null) ? LIGHT_MAP_BIT : 0) : 0; + materialKey |= (_normalMapSpace << NORMAL_MAP_SPACE_OFFSET) | + ((glossinessMap != null) ? GLOSSINESS_MAP_BIT : 0) | + ((specularMap != null) ? SPECULAR_MAP_BIT : 0); + materialKey |= light.shadow.type << SHADOW_OFFSET; + if (light is OmniLight) materialKey |= 1 << OMNI_LIGHT_OFFSET; + else if (light is DirectionalLight) materialKey |= 1 << DIRECTIONAL_LIGHT_OFFSET; + else if (light is SpotLight) materialKey |= 1 << SPOT_LIGHT_OFFSET; // Для группы создаем программу и дроуюнит // Opaque pass diff --git a/src/alternativa/engine3d/materials/TextureMaterial.as b/src/alternativa/engine3d/materials/TextureMaterial.as index 3504555..b98ac30 100644 --- a/src/alternativa/engine3d/materials/TextureMaterial.as +++ b/src/alternativa/engine3d/materials/TextureMaterial.as @@ -172,6 +172,7 @@ package alternativa.engine3d.materials { private function getProgram(object:Object3D, programs:Vector., camera:Camera3D, opacityMap:TextureResource, alphaTest:int):TextureMaterialProgram { var key:int = (opacityMap != null ? 3 : 0) + alphaTest; var program:TextureMaterialProgram = programs[key]; + if (program == null) { // Make program // Vertex shader diff --git a/src/alternativa/engine3d/shadows/Shadow.as b/src/alternativa/engine3d/shadows/Shadow.as index 03628d0..d73526a 100644 --- a/src/alternativa/engine3d/shadows/Shadow.as +++ b/src/alternativa/engine3d/shadows/Shadow.as @@ -23,8 +23,9 @@ package alternativa.engine3d.shadows { */ public class Shadow { - alternativa3d static const SIMPLE_MODE:int = 6; - alternativa3d static const PCF_MODE:int = 7; + alternativa3d static const NONE_MODE:int = 0; + alternativa3d static const SIMPLE_MODE:int = 1; + alternativa3d static const PCF_MODE:int = 2; /** * Debug mode. @@ -35,7 +36,7 @@ package alternativa.engine3d.shadows { * @private * Key for processing in materials. */ - alternativa3d var type:int = 6; + alternativa3d var type:int = 0; /** * @private From 2b4e16b7ff08a4e92ea612f3bb6cdf4645f062f9 Mon Sep 17 00:00:00 2001 From: Leonid Gaev Date: Fri, 15 Jun 2012 19:25:40 +0600 Subject: [PATCH 6/7] fix bug excludeLight --- src/alternativa/engine3d/core/Camera3D.as | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/alternativa/engine3d/core/Camera3D.as b/src/alternativa/engine3d/core/Camera3D.as index ab1cbc7..57b53cf 100644 --- a/src/alternativa/engine3d/core/Camera3D.as +++ b/src/alternativa/engine3d/core/Camera3D.as @@ -341,7 +341,7 @@ public class Camera3D extends Object3D { light = lights[i]; // Checking light source for existing in excludedLights j = 0; - while (j Date: Mon, 18 Jun 2012 15:41:20 +0600 Subject: [PATCH 7/7] OmniLightShadow: add omni radius in debug scale --- src/alternativa/engine3d/shadows/OmniLightShadow.as | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/alternativa/engine3d/shadows/OmniLightShadow.as b/src/alternativa/engine3d/shadows/OmniLightShadow.as index 7d92b72..8e0a166 100644 --- a/src/alternativa/engine3d/shadows/OmniLightShadow.as +++ b/src/alternativa/engine3d/shadows/OmniLightShadow.as @@ -52,7 +52,7 @@ package alternativa.engine3d.shadows { /** * @private */ - alternativa3d static var debugRadiusScale:Number = 0.5; + alternativa3d static var debugRadiusScale:Number = 0.2; private var renderer:Renderer = new Renderer(); @@ -331,7 +331,7 @@ package alternativa.engine3d.shadows { if (debugObject == null) { debugObject = createDebugObject(debugMaterial, camera.context3D); } - debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = debugRadiusScale; + debugObject.scaleX = debugObject.scaleY = debugObject.scaleZ = radius*debugRadiusScale; debugObject.composeTransforms(); // Формируем матрицу трансформации для debugObject