diff --git a/src/alternativa/engine3d/core/Camera3D.as b/src/alternativa/engine3d/core/Camera3D.as
index 9f0a18e..50de4ca 100644
--- a/src/alternativa/engine3d/core/Camera3D.as
+++ b/src/alternativa/engine3d/core/Camera3D.as
@@ -46,6 +46,12 @@ package alternativa.engine3d.core {
*/
public class Camera3D extends Object3D {
+ /**
+ * @private
+ * Key - context, value - properties.
+ */
+ alternativa3d static var context3DPropertiesPool:Dictionary = new Dictionary(true);
+
/**
* The viewport defines part of screen to which renders image seen by the camera.
* If viewport is not defined, the camera would not draws anything.
@@ -156,6 +162,11 @@ public class Camera3D extends Object3D {
*/
alternativa3d var context3D:Context3D;
+ /**
+ * @private
+ */
+ alternativa3d var context3DProperties:RendererContext3DProperties;
+
/**
* @private
* Camera's renderer. If is not defined, the camera will no draw anything.
@@ -195,7 +206,6 @@ public class Camera3D extends Object3D {
* @param stage3D Stage3D to which image will be rendered.
*/
public function render(stage3D:Stage3D):void {
- // TODO: don't check mouse events if no listeners
var i:int;
var j:int;
var light:Light3D;
@@ -214,11 +224,26 @@ public class Camera3D extends Object3D {
ambient[2] = 0;
ambient[3] = 1;
// Receiving the context
- context3D = stage3D.context3D;
+ var currentContext3D:Context3D = stage3D.context3D;
+ if (currentContext3D != context3D) {
+ if (currentContext3D != null) {
+ context3DProperties = context3DPropertiesPool[currentContext3D];
+ if (context3DProperties == null) {
+ context3DProperties = new RendererContext3DProperties();
+ context3DProperties.isConstrained = currentContext3D.driverInfo.lastIndexOf("(Baseline Constrained)") >= 0;
+ context3DPropertiesPool[currentContext3D] = context3DProperties;
+ }
+ context3D = currentContext3D;
+ } else {
+ context3D = null;
+ context3DProperties = null;
+ }
+ }
if (context3D != null && view != null && renderer != null && (view.stage != null || view._canvas != null)) {
renderer.camera = this;
// Projection argument calculating
calculateProjection(view._width, view._height);
+ // TODO: clear after shadows rendering
// Preparing to rendering
view.prepareToRender(stage3D, context3D);
// Transformations calculating
@@ -403,7 +428,6 @@ public class Camera3D extends Object3D {
lights.length = 0;
childLights.length = 0;
occluders.length = 0;
- context3D = null;
}
/**
diff --git a/src/alternativa/engine3d/core/Renderer.as b/src/alternativa/engine3d/core/Renderer.as
index ad51b11..77fae35 100644
--- a/src/alternativa/engine3d/core/Renderer.as
+++ b/src/alternativa/engine3d/core/Renderer.as
@@ -4,8 +4,8 @@
* You may add additional accurate notices of copyright ownership.
*
* It is desirable to notify that Covered Software was "Powered by AlternativaPlatform" with link to http://www.alternativaplatform.com/
- * */
-
+ *
+ */
package alternativa.engine3d.core {
import alternativa.engine3d.alternativa3d;
@@ -16,7 +16,6 @@ package alternativa.engine3d.core {
import flash.display3D.Context3DProgramType;
import flash.display3D.IndexBuffer3D;
import flash.display3D.Program3D;
- import flash.utils.Dictionary;
use namespace alternativa3d;
@@ -37,17 +36,13 @@ package alternativa.engine3d.core {
public static const NEXT_LAYER:int = 50;
- // Key - context, value - properties.
- protected static var properties:Dictionary = new Dictionary(true);
-
// Collector
protected var collector:DrawUnit;
alternativa3d var camera:Camera3D;
alternativa3d var drawUnits:Vector. = new Vector.();
-
- protected var _context3D:Context3D;
+
protected var _contextProperties:RendererContext3DProperties;
alternativa3d function render(context3D:Context3D):void {
@@ -59,29 +54,29 @@ package alternativa.engine3d.core {
if (list != null) {
switch (i) {
case SKY:
- _context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
+ context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
break;
case OPAQUE:
- _context3D.setDepthTest(true, Context3DCompareMode.LESS);
+ context3D.setDepthTest(true, Context3DCompareMode.LESS);
break;
case OPAQUE_OVERHEAD:
- _context3D.setDepthTest(false, Context3DCompareMode.EQUAL);
+ context3D.setDepthTest(false, Context3DCompareMode.EQUAL);
break;
case DECALS:
- _context3D.setDepthTest(false, Context3DCompareMode.LESS_EQUAL);
+ context3D.setDepthTest(false, Context3DCompareMode.LESS_EQUAL);
break;
case TRANSPARENT_SORT:
if (list.next != null) list = sortByAverageZ(list);
- _context3D.setDepthTest(false, Context3DCompareMode.LESS);
+ context3D.setDepthTest(false, Context3DCompareMode.LESS);
break;
case NEXT_LAYER:
- _context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
+ context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
break;
}
// Rendering
while (list != null) {
var next:DrawUnit = list.next;
- renderDrawUnit(list, _context3D, camera);
+ renderDrawUnit(list, context3D, camera);
// Send to collector
list.clear();
list.next = collector;
@@ -90,6 +85,7 @@ package alternativa.engine3d.core {
}
}
}
+ // TODO: not free buffers and textures in each renderer, only when full camera cycle finishes.
freeContext3DProperties(context3D);
// Clear
drawUnits.length = 0;
@@ -180,14 +176,7 @@ package alternativa.engine3d.core {
}
protected function updateContext3D(value:Context3D):void {
- if (_context3D != value) {
- _contextProperties = properties[value];
- if (_contextProperties == null) {
- _contextProperties = new RendererContext3DProperties();
- properties[value] = _contextProperties;
- }
- _context3D = value;
- }
+ _contextProperties = camera.context3DProperties;
}
/**
diff --git a/src/alternativa/engine3d/core/RendererContext3DProperties.as b/src/alternativa/engine3d/core/RendererContext3DProperties.as
index a92aad0..4c2fabe 100644
--- a/src/alternativa/engine3d/core/RendererContext3DProperties.as
+++ b/src/alternativa/engine3d/core/RendererContext3DProperties.as
@@ -16,6 +16,8 @@ package alternativa.engine3d.core {
*/
public class RendererContext3DProperties {
+ public var isConstrained:Boolean = false;
+
public var usedBuffers:uint = 0;
public var usedTextures:uint = 0;
diff --git a/src/alternativa/engine3d/materials/EnvironmentMaterial.as b/src/alternativa/engine3d/materials/EnvironmentMaterial.as
index d1e8478..24dcb83 100644
--- a/src/alternativa/engine3d/materials/EnvironmentMaterial.as
+++ b/src/alternativa/engine3d/materials/EnvironmentMaterial.as
@@ -310,6 +310,15 @@ package alternativa.engine3d.materials {
"mov v0, a0"
], "passLightMapUVProcedure");
+ /**
+ * @private
+ */
+ alternativa3d static var fallbackTextureMaterial:TextureMaterial = new TextureMaterial();
+ /**
+ * @private
+ */
+ alternativa3d static var fallbackLightMapMaterial:LightMapMaterial = new LightMapMaterial();
+
private var _normalMapSpace:int = NormalMapSpace.TANGENT_RIGHT_HANDED;
/**
@@ -815,6 +824,31 @@ package alternativa.engine3d.materials {
if (_normalMap != null && _normalMap._texture == null) return;
if (_reflectionMap != null && _reflectionMap._texture == null) return;
if (_lightMap != null && _lightMap._texture == null) return;
+
+ if (camera.context3DProperties.isConstrained) {
+ // fallback to simpler material
+ if (lightMap == null) {
+ fallbackTextureMaterial.diffuseMap = diffuseMap;
+ fallbackTextureMaterial.opacityMap = opacityMap;
+ fallbackTextureMaterial.alphaThreshold = alphaThreshold;
+ fallbackTextureMaterial.alpha = alpha;
+ fallbackTextureMaterial.opaquePass = opaquePass;
+ fallbackTextureMaterial.transparentPass = transparentPass;
+ fallbackTextureMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
+ } else {
+ fallbackLightMapMaterial.diffuseMap = diffuseMap;
+ fallbackLightMapMaterial.lightMap = lightMap;
+ fallbackLightMapMaterial.lightMapChannel = lightMapChannel;
+ fallbackLightMapMaterial.opacityMap = opacityMap;
+ fallbackLightMapMaterial.alphaThreshold = alphaThreshold;
+ fallbackLightMapMaterial.alpha = alpha;
+ fallbackLightMapMaterial.opaquePass = opaquePass;
+ fallbackLightMapMaterial.transparentPass = transparentPass;
+ fallbackLightMapMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
+ }
+ return;
+ }
+
var object:Object3D = surface.object;
// Program
diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as
index 7ce0217..f451c23 100644
--- a/src/alternativa/engine3d/materials/StandardMaterial.as
+++ b/src/alternativa/engine3d/materials/StandardMaterial.as
@@ -307,6 +307,15 @@ package alternativa.engine3d.materials {
"mov v0, a0"
], "passLightMapUVProcedure");
+ /**
+ * @private
+ */
+ alternativa3d static var fallbackTextureMaterial:TextureMaterial = new TextureMaterial();
+ /**
+ * @private
+ */
+ alternativa3d static var fallbackLightMapMaterial:LightMapMaterial = new LightMapMaterial();
+
/**
* Normal map.
*/
@@ -986,6 +995,30 @@ package alternativa.engine3d.materials {
// Check if textures uploaded in to the context.
if (opacityMap != null && opacityMap._texture == null || glossinessMap != null && glossinessMap._texture == null || specularMap != null && specularMap._texture == null || lightMap != null && lightMap._texture == null) return;
+ if (camera.context3DProperties.isConstrained) {
+ // fallback to simpler material
+ if (lightMap == null) {
+ fallbackTextureMaterial.diffuseMap = diffuseMap;
+ fallbackTextureMaterial.opacityMap = opacityMap;
+ fallbackTextureMaterial.alphaThreshold = alphaThreshold;
+ fallbackTextureMaterial.alpha = alpha;
+ fallbackTextureMaterial.opaquePass = opaquePass;
+ fallbackTextureMaterial.transparentPass = transparentPass;
+ fallbackTextureMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
+ } else {
+ fallbackLightMapMaterial.diffuseMap = diffuseMap;
+ fallbackLightMapMaterial.lightMap = lightMap;
+ fallbackLightMapMaterial.lightMapChannel = lightMapChannel;
+ fallbackLightMapMaterial.opacityMap = opacityMap;
+ fallbackLightMapMaterial.alphaThreshold = alphaThreshold;
+ fallbackLightMapMaterial.alpha = alpha;
+ fallbackLightMapMaterial.opaquePass = opaquePass;
+ fallbackLightMapMaterial.transparentPass = transparentPass;
+ fallbackLightMapMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
+ }
+ return;
+ }
+
var object:Object3D = surface.object;
// Buffers
diff --git a/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as b/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as
index 009f231..ceb0664 100644
--- a/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as
+++ b/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as
@@ -98,6 +98,11 @@ package alternativa.engine3d.materials {
private static const _lightsProcedures:Dictionary = new Dictionary(true);
+ /**
+ * @private
+ */
+ alternativa3d static var fallbackMaterial:TextureMaterial = new TextureMaterial();
+
/**
* Creates a new VertexLightTextureMaterial instance.
*
@@ -282,6 +287,18 @@ package alternativa.engine3d.materials {
override alternativa3d function collectDraws(camera:Camera3D, surface:Surface, geometry:Geometry, lights:Vector., lightsLength:int, useShadow:Boolean, objectRenderPriority:int = -1):void {
if (diffuseMap == null || diffuseMap._texture == null || opacityMap != null && opacityMap._texture == null) return;
+ if (camera.context3DProperties.isConstrained) {
+ // fallback to texture material
+ fallbackMaterial.diffuseMap = diffuseMap;
+ fallbackMaterial.opacityMap = opacityMap;
+ fallbackMaterial.alphaThreshold = alphaThreshold;
+ fallbackMaterial.alpha = alpha;
+ fallbackMaterial.opaquePass = opaquePass;
+ fallbackMaterial.transparentPass = transparentPass;
+ fallbackMaterial.collectDraws(camera, surface, geometry, lights, lightsLength, useShadow, objectRenderPriority);
+ return;
+ }
+
var object:Object3D = surface.object;
// Buffers
diff --git a/src/alternativa/engine3d/objects/LOD.as b/src/alternativa/engine3d/objects/LOD.as
index 487da9c..04d38a0 100644
--- a/src/alternativa/engine3d/objects/LOD.as
+++ b/src/alternativa/engine3d/objects/LOD.as
@@ -176,6 +176,7 @@ package alternativa.engine3d.objects {
* @private
*/
override alternativa3d function calculateVisibility(camera:Camera3D):void {
+ // TODO: optimize - use square of distance
var distance:Number = Math.sqrt(localToCameraTransform.d*localToCameraTransform.d + localToCameraTransform.h*localToCameraTransform.h + localToCameraTransform.l*localToCameraTransform.l);
for (level = levelList; level != null; level = level.next) {
if (distance <= level.distance) {