mirror of
https://github.com/MapMakersAndProgrammers/Alternativa3D.git
synced 2025-10-26 01:49:07 -07:00
Add light sort in camera
This commit is contained in:
@@ -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 <code>view</code> property should be defined.
|
||||
* @param point Point in global space.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ package alternativa.engine3d.lights {
|
||||
* @param color Light color.
|
||||
*/
|
||||
public function AmbientLight(color:uint) {
|
||||
this.type = AMBIENT;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -20,7 +20,6 @@ package alternativa.engine3d.materials {
|
||||
*/
|
||||
public class ShaderProgram {
|
||||
|
||||
public var key:String;
|
||||
public var program:Program3D;
|
||||
|
||||
public var vertexShader:Linker;
|
||||
|
||||
@@ -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.<Light3D>, 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<programsCount; i++){
|
||||
// if (programs[i].key == key){
|
||||
// program = StandardMaterialProgram(programs[i]);
|
||||
// }
|
||||
// }
|
||||
// trace(programsCount);
|
||||
if (program == null) {
|
||||
var vertexLinker:Linker = new Linker(Context3DProgramType.VERTEX);
|
||||
var fragmentLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
|
||||
@@ -1005,12 +999,12 @@ package alternativa.engine3d.materials {
|
||||
cachedContext3D = camera.context3D;
|
||||
programsCache = caches[cachedContext3D];
|
||||
if (programsCache == null) {
|
||||
programsCache = new Dictionary(true);
|
||||
programsCache = new Dictionary(false);
|
||||
caches[cachedContext3D] = programsCache;
|
||||
}
|
||||
}
|
||||
|
||||
var optionsPrograms:Array = programsCache[object.transformProcedure];
|
||||
var optionsPrograms:Array;
|
||||
optionsPrograms = programsCache[object.transformProcedure];
|
||||
if (optionsPrograms == null) {
|
||||
optionsPrograms = new Array();
|
||||
programsCache[object.transformProcedure] = optionsPrograms;
|
||||
@@ -1047,9 +1041,9 @@ package alternativa.engine3d.materials {
|
||||
if (groupsCount == 0 && shadowGroupLength == 0) {
|
||||
// There is only Ambient light on the scene
|
||||
// Form key
|
||||
materialKey = (lightMap != null) ? LIGHT_MAP : 0 +
|
||||
(glossinessMap != null) ? GLOSSINESS_MAP : 0 +
|
||||
(specularMap != null) ? SPECULAR_MAP : 0;
|
||||
materialKey = ((lightMap != null) ? LIGHT_MAP_BIT : 0) |
|
||||
((glossinessMap != null) ? GLOSSINESS_MAP_BIT : 0) |
|
||||
((specularMap != null) ? SPECULAR_MAP_BIT : 0);
|
||||
|
||||
if (opaquePass && alphaThreshold <= alpha) {
|
||||
if (alphaThreshold > 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
|
||||
|
||||
@@ -172,6 +172,7 @@ package alternativa.engine3d.materials {
|
||||
private function getProgram(object:Object3D, programs:Vector.<TextureMaterialProgram>, 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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user