From 094bbcd5b74ab76f34b3965d2ad97392a05b5e92 Mon Sep 17 00:00:00 2001 From: Yaski Date: Tue, 31 Jul 2012 00:28:22 +0600 Subject: [PATCH 1/2] Fallback materials to simpler --- src/alternativa/engine3d/core/Renderer.as | 9 +++-- .../engine3d/materials/EnvironmentMaterial.as | 34 +++++++++++++++++++ .../engine3d/materials/StandardMaterial.as | 33 ++++++++++++++++++ .../materials/VertexLightTextureMaterial.as | 17 ++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/alternativa/engine3d/core/Renderer.as b/src/alternativa/engine3d/core/Renderer.as index ad51b11..211bad2 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; @@ -46,7 +46,9 @@ package alternativa.engine3d.core { alternativa3d var camera:Camera3D; alternativa3d var drawUnits:Vector. = new Vector.(); - + + alternativa3d var isConstrainedMode:Boolean = false; + protected var _context3D:Context3D; protected var _contextProperties:RendererContext3DProperties; @@ -187,6 +189,7 @@ package alternativa.engine3d.core { properties[value] = _contextProperties; } _context3D = value; + isConstrainedMode = _context3D.driverInfo.lastIndexOf("(Baseline Constrained)") >= 0; } } diff --git a/src/alternativa/engine3d/materials/EnvironmentMaterial.as b/src/alternativa/engine3d/materials/EnvironmentMaterial.as index d1e8478..276044d 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.renderer.isConstrainedMode) { + // 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..3cb1022 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.renderer.isConstrainedMode) { + // 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..57efd3f 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.renderer.isConstrainedMode) { + // 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 From d08989b9b1362555f6333e2ed691e7920711513a Mon Sep 17 00:00:00 2001 From: Yaski Date: Tue, 31 Jul 2012 21:53:03 +0600 Subject: [PATCH 2/2] Get context properties in Camera3D --- src/alternativa/engine3d/core/Camera3D.as | 30 +++++++++++++++-- src/alternativa/engine3d/core/Renderer.as | 32 ++++++------------- .../core/RendererContext3DProperties.as | 2 ++ .../engine3d/materials/EnvironmentMaterial.as | 2 +- .../engine3d/materials/StandardMaterial.as | 2 +- .../materials/VertexLightTextureMaterial.as | 2 +- src/alternativa/engine3d/objects/LOD.as | 1 + 7 files changed, 42 insertions(+), 29 deletions(-) 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 211bad2..77fae35 100644 --- a/src/alternativa/engine3d/core/Renderer.as +++ b/src/alternativa/engine3d/core/Renderer.as @@ -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,9 +36,6 @@ 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; @@ -47,9 +43,6 @@ package alternativa.engine3d.core { alternativa3d var drawUnits:Vector. = new Vector.(); - alternativa3d var isConstrainedMode:Boolean = false; - - protected var _context3D:Context3D; protected var _contextProperties:RendererContext3DProperties; alternativa3d function render(context3D:Context3D):void { @@ -61,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; @@ -92,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; @@ -182,15 +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; - isConstrainedMode = _context3D.driverInfo.lastIndexOf("(Baseline Constrained)") >= 0; - } + _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 276044d..24dcb83 100644 --- a/src/alternativa/engine3d/materials/EnvironmentMaterial.as +++ b/src/alternativa/engine3d/materials/EnvironmentMaterial.as @@ -825,7 +825,7 @@ package alternativa.engine3d.materials { if (_reflectionMap != null && _reflectionMap._texture == null) return; if (_lightMap != null && _lightMap._texture == null) return; - if (camera.renderer.isConstrainedMode) { + if (camera.context3DProperties.isConstrained) { // fallback to simpler material if (lightMap == null) { fallbackTextureMaterial.diffuseMap = diffuseMap; diff --git a/src/alternativa/engine3d/materials/StandardMaterial.as b/src/alternativa/engine3d/materials/StandardMaterial.as index 3cb1022..f451c23 100644 --- a/src/alternativa/engine3d/materials/StandardMaterial.as +++ b/src/alternativa/engine3d/materials/StandardMaterial.as @@ -995,7 +995,7 @@ 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.renderer.isConstrainedMode) { + if (camera.context3DProperties.isConstrained) { // fallback to simpler material if (lightMap == null) { fallbackTextureMaterial.diffuseMap = diffuseMap; diff --git a/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as b/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as index 57efd3f..ceb0664 100644 --- a/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as +++ b/src/alternativa/engine3d/materials/VertexLightTextureMaterial.as @@ -287,7 +287,7 @@ 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.renderer.isConstrainedMode) { + if (camera.context3DProperties.isConstrained) { // fallback to texture material fallbackMaterial.diffuseMap = diffuseMap; fallbackMaterial.opacityMap = opacityMap; 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) {