瀏覽代碼

Removed old mojo2 module.

Mark Sibly 9 年之前
父節點
當前提交
541bd3a82d

+ 0 - 43
modules/mojo2/data/mojo2_bumpshader.glsl

@@ -1,43 +0,0 @@
-
-//shader for full lighting.
-
-uniform sampler2D ColorTexture;
-uniform sampler2D SpecularTexture;
-uniform sampler2D NormalTexture;
-
-uniform vec4 AmbientColor;
-uniform float Roughness;
-
-void shader(){
-
-	vec4 color=texture2D( ColorTexture,b3d_Texcoord0 );
-	
-#if GAMMA_CORRECTION
-	color.rgb=pow( color.rgb,vec3( 2.2 ) );
-#endif
-
-	color*=b3d_Color;
-
-	b3d_Alpha=color.a;
-
-	b3d_Ambient=color * AmbientColor;
-
-	b3d_Diffuse=color * (1.0-AmbientColor);
-	
-	b3d_Specular=texture2D( SpecularTexture,b3d_Texcoord0 );
-
-#if GAMMA_CORRECTION
-	b3d_Specular.rgb=pow( b3d_Specular.rgb * b3d_Alpha,vec3( 2.2 ) );
-#else
-	b3d_Specular.rgb*=b3d_Alpha;
-#endif
-	
-#if OPT_FAST
-	b3d_Normal=texture2D( NormalTexture,b3d_Texcoord0 ).xyz*2.0-1.0;
-#else	
-	b3d_Normal=normalize( texture2D( NormalTexture,b3d_Texcoord0 ).xyz*2.0-1.0 );
-#endif
-	b3d_Normal.yz=-b3d_Normal.yz;
-
-	b3d_Roughness=Roughness;
-}

+ 0 - 17
modules/mojo2/data/mojo2_fastshader.glsl

@@ -1,17 +0,0 @@
-
-//shader for simple unlit sprites.
-
-uniform sampler2D ColorTexture;
-
-void shader(){
-
-	b3d_Ambient=texture2D( ColorTexture,b3d_Texcoord0 );
-	
-#if GAMMA_CORRECTION
-	b3d_Ambient.rgb=pow( b3d_Ambient.rgb,vec3( 2.2 ) );
-#endif
-
-	b3d_Ambient*=b3d_Color;	//apply vertex coloring
-
-	b3d_Alpha=b3d_Ambient.a;	//extract alpha
-}

二進制
modules/mojo2/data/mojo2_font.png


+ 0 - 9
modules/mojo2/data/mojo2_lightmapshader.glsl

@@ -1,9 +0,0 @@
-
-//shader for drawing lightmaps, ie: light images or layer light masks.
-
-uniform sampler2D ColorTexture;
-
-void shader(){
-
-	b3d_FragColor=vec4( texture2D( ColorTexture,b3d_Texcoord0 ).r );
-}

+ 0 - 32
modules/mojo2/data/mojo2_matteshader.glsl

@@ -1,32 +0,0 @@
-
-//shader for simple matte lighting.
-
-uniform sampler2D ColorTexture;
-uniform sampler2D SpecularTexture;
-uniform sampler2D NormalTexture;
-
-uniform vec4 AmbientColor;
-uniform float Roughness;
-
-void shader(){
-
-	vec4 color=texture2D( ColorTexture,b3d_Texcoord0 );
-	
-#if GAMMA_CORRECTION
-	color.rgb=pow( color.rgb,vec3( 2.2 ) );
-#endif
-
-	color*=b3d_Color;
-
-	b3d_Alpha=color.a;
-
-	b3d_Ambient=color * AmbientColor;
-
-	b3d_Diffuse=color * (1.0-AmbientColor);
-	
-	b3d_Specular=vec4( 0.0 );
-	
-	b3d_Normal=vec3( 0.0,0.0,-1.0 );
-
-	b3d_Roughness=Roughness;
-}

+ 0 - 260
modules/mojo2/data/mojo2_program.glsl

@@ -1,260 +0,0 @@
-
-//***** Mojo2 Mega Shader *****
-
-//***** USER OPTIONS ******
-
-//enable less accurate but faster rendering - make sure yer normals are right when enabling this!
-#define OPT_FAST 0
-
-//Apply cheesy_hdr to lighting - slower, but nice for colored lights as they saturate to white
-#define CHEESY_HDR 1
-
-//enable bump tangents, for correct bump mapping of rotating drawops - can only really handle uniform scaling/rotation, but will probably look OK otherwise...
-#define BUMP_TANGENTS 1
-
-//make sure shadows are working!
-#define DEBUG_SHADOWS 0
-
-//enable ortho lighting - faster + makes lights easier to position
-#define ORTHO_LIGHTING 1
-
-//enable fresnel effect - slower
-#define FRESNEL_EFFECT 1
-
-//enable gamma correction - slower. Don't use yet! Messes up with >4 lights...
-#define GAMMA_CORRECTION 0
-
-
-//***** ENABLED VARS *****
-
-#if NUM_LIGHTS && !defined(B3D_CLIPPOSITION)
-#define B3D_CLIPPOSITION 1
-#endif
-
-#if NUM_LIGHTS && !defined(B3D_VIEWPOSITION)
-#define B3D_VIEWPOSITION 1
-#endif
-
-#if NUM_LIGHTS && BUMP_TANGENTS && !defined(B3D_VIEWTANGENT)
-#define B3D_VIEWTANGENT 1
-#endif
-
-#ifdef B3D_TEXCOORD0
-varying vec2 b3d_Texcoord0;
-#endif
-
-#ifdef B3D_COLOR
-varying vec4 b3d_Color;
-#endif
-
-#ifdef B3D_VIEWPOSITION
-varying vec3 b3d_ViewPosition;
-#endif
-
-#ifdef B3D_VIEWNORMAL
-varying vec3 b3d_ViewNormal;
-#endif
-
-#ifdef B3D_VIEWTANGENT
-varying vec3 b3d_ViewTangent;
-#endif
-
-#ifdef B3D_CLIPPOSITION
-varying vec4 b3d_ClipPosition;
-#endif
-
-//@vertex
-
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform vec4 ClipPosScale;	//hack to handle inverted y when rendering to display
-uniform vec4 GlobalColor;
-
-attribute vec4 Position;
-attribute vec2 Texcoord0;
-attribute vec3 Tangent;
-attribute vec4 Color;
-
-void main(){
-
-	gl_Position=ModelViewProjectionMatrix * Position;
-	
-	gl_PointSize=1.0;
-	
-#ifdef B3D_CLIPPOSITION
-	b3d_ClipPosition=gl_Position * ClipPosScale;
-#endif
-
-#ifdef B3D_VIEWPOSITION
-	b3d_ViewPosition=(ModelViewMatrix * Position).xyz;
-#endif
-	
-#ifdef B3D_VIEWNORMAL
-	b3d_ViewNormal=(ModelViewMatrix * vec4( 0.0,0.0,-1.0 )).xyz;
-#endif
-
-#ifdef B3D_VIEWTANGENT
-#if OPT_FAST
-	b3d_ViewTangent=normalize( (ModelViewMatrix * vec4( Tangent,0.0 )).xyz );
-#else
-	b3d_ViewTangent=(ModelViewMatrix * vec4( Tangent,0.0 )).xyz;
-#endif
-#endif
-
-#ifdef B3D_TEXCOORD0
-	b3d_Texcoord0=Texcoord0;
-#endif
-
-#ifdef B3D_COLOR
-	b3d_Color=Color * GlobalColor;
-#endif
-		
-}
-
-//@fragment
-
-uniform vec4 FogColor;
-uniform vec4 AmbientLight;
-
-#if NUM_LIGHTS
-uniform sampler2D ShadowTexture;
-uniform vec4 LightColors[NUM_LIGHTS];
-uniform vec4 LightVectors[NUM_LIGHTS];
-#endif
-
-#define b3d_FragColor gl_FragColor
-float b3d_Alpha;
-float b3d_Roughness;
-vec4 b3d_Ambient;
-vec4 b3d_Diffuse;
-vec4 b3d_Specular;
-vec3 b3d_Normal;
-
-${SHADER}
-
-#if NUM_LIGHTS
-
-float gloss;
-float spow;
-float fnorm;
-float ndotv;
-#if ORTHO_LIGHTING
-const vec3 eyevec=vec3( 0.0,0.0,-1.0 );
-#else
-vec3 eyevec;
-#endif
-vec4 diffuse;
-vec4 specular;
-mat3 tanMatrix;
-
-void light( in vec4 lightVector,in vec4 lightColor,float shadow ){
-
-#if DEBUG_SHADOWS
-	diffuse+=1.0-shadow;
-	return;
-#endif
-
-	vec3 v=lightVector.xyz-b3d_ViewPosition;
-#if BUMP_TANGENTS
-	v=tanMatrix * v;
-#endif
-	
-	float falloff=max( 1.0-length( v )/lightVector.w,0.0 );
-	
-	vec3 lvec=normalize( v );
-	vec3 hvec=normalize( lvec + eyevec );
-	
-	float ndotl=max( dot( b3d_Normal,lvec ),0.0 );
-	float ndoth=max( dot( b3d_Normal,hvec ),0.0 );
-	
-	vec4 icolor=lightColor * ndotl * falloff * shadow;
-	
-	diffuse+=icolor;
-	specular+=icolor * pow( ndoth,spow ) * fnorm;
-}
-
-#if CHEESY_HDR
-vec4 cheesy_hdr( in vec4 color ){
-	vec4 ov=max( color-1.0,0.0 );
-	return color+( (ov.r+ov.g+ov.b)/3.0 );
-}
-#endif
-
-#endif
-
-void main(){
-
-	shader();
-	
-#ifndef B3D_FRAGCOLOR
-	
-#if NUM_LIGHTS
-
-#if !ORTHO_LIGHTING
-	eyevec=normalize( -b3d_ViewPosition );
-#endif
-
-	//specular power	
-	gloss=1.0-Roughness;
-	spow=pow( 2.0,gloss*12.0 );	//specular power
-	fnorm=spow*2.0/8.0;			//energy conservation - sharper highlights are brighter coz they're smaller.
-	
-#if FRESNEL_EFFECT				//fresnel effect - reflectivity approaches 1 as surface grazing angle approaches 0 for glossy surfaces.
-	ndotv=max( dot( b3d_Normal,eyevec ),0.0 );
-	b3d_Specular+=(1.0-b3d_Specular) * pow( 1.0-ndotv,5.0 ) * gloss;
-#endif
-
-	diffuse=AmbientLight;
-	specular=vec4( 0.0 );
-
-#if BUMP_TANGENTS
-#if OPT_FAST
-	vec3 vtan=b3d_ViewTangent;
-#else
-	vec3 vtan=normalize( b3d_ViewTangent );
-#endif
-	tanMatrix=mat3( vec3( vtan.x,-vtan.y,0.0 ),vec3( vtan.y,vtan.x,0.0 ),vec3( 0.0,0.0,1.0 ) );
-#endif
-	
-	vec4 clip=b3d_ClipPosition/b3d_ClipPosition.w;
-	vec4 shadow=texture2D( ShadowTexture,clip.xy*0.5+0.5 );
-	
-	light( LightVectors[0],LightColors[0],shadow.r );
-#if NUM_LIGHTS>1
-	light( LightVectors[1],LightColors[1],shadow.g );
-#if NUM_LIGHTS>2
-	light( LightVectors[2],LightColors[2],shadow.b );
-#if NUM_LIGHTS>3
-	light( LightVectors[3],LightColors[3],shadow.a );
-#endif
-#endif
-#endif
-
-#if CHEESY_HDR
-	diffuse=cheesy_hdr( diffuse );
-	specular=cheesy_hdr( specular );
-#endif
-
-	vec4 color=(b3d_Diffuse * diffuse) + (b3d_Specular * specular) + (b3d_Ambient * AmbientLight.a);
-
-#else
-
-#ifdef B3D_DIFFUSE
-	vec4 color=(b3d_Diffuse * AmbientLight) + (b3d_Ambient * AmbientLight.a);
-#else
-	vec4 color=b3d_Ambient * AmbientLight.a;
-#endif	
-	
-#endif
-
-	color.rgb=mix( color.rgb,FogColor.rgb,FogColor.a * b3d_Alpha );
-
-#if GAMMA_CORRECTION
-	gl_FragColor=vec4( pow( color.rgb,vec3( 1.0/2.2 ) ),b3d_Alpha );
-#else
-	gl_FragColor=vec4( color.rgb,b3d_Alpha );
-#endif
-
-#endif	//B3D_FRAGCOLOR
-
-}

+ 0 - 7
modules/mojo2/data/mojo2_shadowshader.glsl

@@ -1,7 +0,0 @@
-
-//shader for drawing shadows
-
-void shader(){
-
-	b3d_FragColor=vec4( 0.0 );
-}

+ 0 - 190
modules/mojo2/glslparser.monkey2

@@ -1,190 +0,0 @@
-
-Namespace mojo2.glslparser
-
-Using mojo2
-
-Const TOKE_EOF:=0
-Const TOKE_IDENT:=1
-Const TOKE_INTLIT:=2
-Const TOKE_FLOATLIT:=3
-Const TOKE_STRINGLIT:=4
-Const TOKE_SYMBOL:=5
-	
-Const CHAR_QUOTE:=34
-Const CHAR_PLUS:=43
-Const CHAR_MINUS:=45
-Const CHAR_PERIOD:=46
-Const CHAR_UNDERSCORE:=95
-Const CHAR_APOSTROPHE:=39
-
-Function IsDigit:Bool( ch:Int )
-	Return (ch>=48 And ch<58)
-End
-
-Function IsAlpha:Bool( ch:Int )
-	Return (ch>=65 And ch<65+26) Or (ch>=97 And ch<97+26)
-End
-
-Function IsIdent:Bool( ch:Int )
-	Return (ch>=65 And ch<65+26) Or (ch>=97 And ch<97+26) Or (ch>=48 And ch<58) Or ch=CHAR_UNDERSCORE
-End
-
-Class Parser
-
-	Method New( text:String )
-		SetText( text )
-	End
-
-	Method SetText:Void( text:String )
-		_text=text
-		_pos=0
-		_len=_text.Length
-		Bump()
-	End
-	
-	Method Bump:String()
-
-		While _pos<_len
-			Local ch:=_text[_pos]
-			If ch<=32
-				_pos+=1
-				Continue
-			Endif
-			If ch<>CHAR_APOSTROPHE Exit
-			_pos+=1
-			While _pos<_len And _text[_pos]<>10
-				_pos+=1
-			Wend
-		Wend
-		
-		If _pos=_len
-			_toke=""
-			_tokeType=TOKE_EOF
-			Return _toke
-		Endif
-		
-		Local pos:=_pos
-		Local ch:=_text[_pos]
-		_pos+=1
-		
-		If IsAlpha( ch ) Or ch=CHAR_UNDERSCORE
-		
-			While _pos<_len
-				Local ch:=_text[_pos]
-				If Not IsIdent( ch ) Exit
-				_pos+=1
-			Wend
-			_tokeType=TOKE_IDENT
-			
-		Else If IsDigit( ch ) 
-		
-			While _pos<_len
-				If Not IsDigit( _text[_pos] ) Exit
-				_pos+=1
-			Wend
-			_tokeType=TOKE_INTLIT
-			
-		Else If ch=CHAR_QUOTE
-		
-			While _pos<_len
-				Local ch:=_text[_pos]
-				If ch=CHAR_QUOTE Exit
-				_pos+=1
-			Wend
-			If _pos=_len Mojo2Error( "String literal missing closing quote" )
-			_tokeType=TOKE_STRINGLIT
-			_pos+=1
-			
-		Else
-			#rem
-			Local digraphs:=[":="]
-			If _pos<_len
-				Local ch:=_text[_pos]
-				For Local t:=Eachin digraphs
-					If ch=t[1]
-						_pos+=1
-						Exit
-					Endif
-				Next
-			Endif
-			#end
-			_tokeType=TOKE_SYMBOL
-		Endif
-		
-		_toke=_text.Slice( pos,_pos )
-		
-		Return _toke
-	End
-	
-	Property Toke:String()
-		Return _toke
-	End
-	
-	property TokeType:Int()
-		Return _tokeType
-	End
-	
-	Method CParse:Bool( toke:String )
-		If _toke<>toke Return False
-		Bump()
-		Return True
-	End
-	
-	Method CParseIdent:String()
-		If _tokeType<>TOKE_IDENT Return ""
-		Local id:=_toke
-		Bump()
-		Return id
-	End
-	
-	Method CParseLiteral:String()
-		If _tokeType<>TOKE_INTLIT And _tokeType<>TOKE_FLOATLIT And _tokeType<>TOKE_STRINGLIT Return ""
-		Local id:=_toke
-		Bump()
-		Return id
-	End
-	
-	Method Parse:String()
-		Local toke:=_toke
-		Bump()
-		Return toke
-	End
-	
-	Method Parse:Void( toke:String )
-		If Not CParse( toke ) Mojo2Error( "Expecting '"+toke+"'" )
-	End
-	
-	Method ParseIdent:String()
-		Local id:=CParseIdent()
-		If Not id Mojo2Error( "Expecting identifier" )
-		Return id
-	End
-	
-	Method ParseLiteral:String()
-		Local id:=CParseLiteral()
-		If Not id Mojo2Error( "Expecting literal" )
-		Return id
-	End
-	
-	Private
-
-	Field _text:String
-	Field _pos:Int
-	Field _len:Int
-	Field _toke:String
-	Field _tokeType:Int
-	
-End
-
-Class GlslParser Extends Parser
-
-	Method New( text:String )
-		Super.New( text )
-	End
-
-	Method ParseType:String()
-		Local id:=ParseIdent()
-		Return id
-	End
-	
-End

+ 0 - 63
modules/mojo2/glutil.monkey2

@@ -1,63 +0,0 @@
-
-Namespace mojo2.glutil
-
-Private
-
-Using lib.gles20
-
-Global tmpi:Int
-
-Public
-
-Function glCheck()
-	Local err:=glGetError()
-	If err=GL_NO_ERROR Return
-	Mojo2Error( "GL ERROR! err="+err )
-End
-
-Function glPushTexture2d:Void( tex:Int )
-	glGetIntegerv( GL_TEXTURE_BINDING_2D,Varptr tmpi )
-	glBindTexture( GL_TEXTURE_2D,tex )
-End
-
-Function glPopTexture2d:Void()
-	glBindTexture( GL_TEXTURE_2D,tmpi )
-End
-
-Function glPushFramebuffer:Void( framebuf:Int )
-	glGetIntegerv( GL_FRAMEBUFFER_BINDING,Varptr tmpi )
-	glBindFramebuffer( GL_FRAMEBUFFER,framebuf )
-End
-
-Function glPopFramebuffer:Void()
-	glBindFramebuffer( GL_FRAMEBUFFER,tmpi )
-End
-
-Function glCompile:Int( type:Int,source:String )
-
-	#If __TARGET__="emscripten"	Or (__TARGET__="desktop" And __HOSTOS__="windows")
-'	#If TARGET<>"glfw" Or GLFW_USE_ANGLE_GLES20
-		source="precision mediump float;~n"+source
-	#Endif
-	
-	Local shader:=glCreateShader( type )
-	glShaderSourceEx( shader,source )
-	glCompileShader( shader )
-	glGetShaderiv( shader,GL_COMPILE_STATUS,Varptr tmpi )
-	If Not tmpi
-		Print "Failed to compile fragment shader:"+glGetShaderInfoLogEx( shader )
-		Print source
-'		Local lines:=source.Split( "~n" )
-'		For Local i:=0 Until lines.Length
-'			Print (i+1)+":~t"+lines[i]
-'		Next
-		Mojo2Error( "Compile fragment shader failed" )
-	Endif
-	Return shader
-End
-
-Function glLink:Void( program:Int )
-	glLinkProgram( program )
-	glGetProgramiv( program,GL_LINK_STATUS,Varptr tmpi )
-	If Not tmpi Mojo2Error( "Failed to link program:"+glGetProgramInfoLogEx( program ) )
-End

+ 0 - 2683
modules/mojo2/graphics.monkey2

@@ -1,2683 +0,0 @@
-
-Namespace mojo2
-
-Private
-
-#Import "<sdl2.monkey2>"
-
-Using mojo2.glutil
-Using mojo2.math3d
-Using mojo2.glslparser
-
-Using lib.c
-Using lib.stb
-Using lib.gles20
-
-Using std
-Using std.stringio
-Using std.filesystem
-
-#Import "data/mojo2_font.png@/mojo2"
-#Import "data/mojo2_program.glsl@/mojo2"
-#Import "data/mojo2_fastshader.glsl@/mojo2"
-#Import "data/mojo2_bumpshader.glsl@/mojo2"
-#Import "data/mojo2_matteshader.glsl@/mojo2"
-#Import "data/mojo2_shadowshader.glsl@/mojo2"
-#Import "data/mojo2_lightmapshader.glsl@/mojo2"
-
-Const VBO_USAGE:=GL_STREAM_DRAW
-Const VBO_ORPHANING_ENABLED:=False'True
-
-Global graphicsSeq:=1
-
-Const MAX_LIGHTS:=4
-Const BYTES_PER_VERTEX:=28
-
-'can really be anything <64K (due to 16bit indices) but this keeps total VBO size<64K, and making it bigger doesn't seem to improve performance much.
-Const MAX_VERTICES:=65536/BYTES_PER_VERTEX	
-
-Const MAX_QUADS:=MAX_VERTICES/4
-Const MAX_QUAD_INDICES:=MAX_QUADS*6
-Const PRIM_VBO_SIZE:=MAX_VERTICES*BYTES_PER_VERTEX
-
-Global tmpi:=New Int[16]
-Global tmpf:=New Float[16]
-
-Global tmpMat2d:=New Float[6]
-Global tmpMat3d:=New Float[16]
-Global tmpMat3d2:=New Float[16]
-
-Global defaultFbo:Int
-
-Global mainShader:String
-
-Global fastShader:Shader
-Global bumpShader:Shader
-Global matteShader:Shader
-Global shadowShader:Shader
-Global lightMapShader:Shader
-
-Global defaultFont:Font
-Global defaultShader:Shader
-
-Global freeOps:=New Stack<DrawOp>
-Global nullOp:=New DrawOp
-
-'shader params
-Global rs_projMatrix:=Mat4New()
-Global rs_modelViewMatrix:=Mat4New()
-Global rs_modelViewProjMatrix:=Mat4New()
-Global rs_clipPosScale:=New Float[]( 1.0,1.0,1.0,1.0 )
-Global rs_globalColor:=New Float[]( 1.0,1.0,1.0,1.0 )
-Global rs_numLights:Int
-Global rs_fogColor:=New Float[]( 0.0,0.0,0.0,0.0 )
-Global rs_ambientLight:=New Float[]( 0.0,0.0,0.0,1.0 )
-Global rs_lightColors:=New Float[MAX_LIGHTS*4]
-Global rs_lightVectors:=New Float[MAX_LIGHTS*4]
-Global rs_shadowTexture:Texture
-Global rs_program:GLProgram
-Global rs_material:Material
-Global rs_blend:Int=-1
-Global rs_vbo:GLuint
-Global rs_ibo:GLuint
-
-Function IsPow2:Bool( sz:Int )
-	Return (sz & (sz-1))=0
-End
-
-Class LightData
-	Field type:Int=0
-	Field color:=New Float[]( 1.0,1.0,1.0,1.0 )
-	Field position:=New Float[]( 0.0,0.0,-10.0 )
-	Field range:Float=10
-	'
-	Field vector:=New Float[]( 0.0,0.0,-10.0,1.0 )
-	Field tvector:=New Float[4]
-End
-
-Global flipYMatrix:=Mat4New()
-
-Global vbosSeq:Int
-
-Function Error:Void( err:String )
-	Print "Error:"+err
-	exit_( -1 )
-End
-
-Function InitVbos:Void()
-	If vbosSeq=graphicsSeq 
-		BindVbos()
-		Return
-	Endif
-	vbosSeq=graphicsSeq
-
-'	Print "InitVbos()"
-
-	glGenBuffers( 1,Varptr rs_vbo )
-	glBindBuffer( GL_ARRAY_BUFFER,rs_vbo )
-	glBufferData( GL_ARRAY_BUFFER,PRIM_VBO_SIZE,Null,VBO_USAGE )
-	glEnableVertexAttribArray( 0 ) ; glVertexAttribPointer( 0,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 0 ) )
-	glEnableVertexAttribArray( 1 ) ; glVertexAttribPointer( 1,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 8 ) )
-	glEnableVertexAttribArray( 2 ) ; glVertexAttribPointer( 2,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 16 ) )
-	glEnableVertexAttribArray( 3 ) ; glVertexAttribPointer( 3,4,GL_UNSIGNED_BYTE,True,BYTES_PER_VERTEX,Byte Ptr( 24 ) )
-
-	glGenBuffers( 1,Varptr rs_ibo )
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER,rs_ibo )
-	Local idxs:=New UShort[ MAX_QUAD_INDICES*4 ]
-	For Local j:=0 Until 4
-		Local k:=j*MAX_QUAD_INDICES
-		For Local i:=0 Until MAX_QUADS
-			idxs[i*6+k+0]=i*4+j+0
-			idxs[i*6+k+1]=i*4+j+1
-			idxs[i*6+k+2]=i*4+j+2
-			idxs[i*6+k+3]=i*4+j+0
-			idxs[i*6+k+4]=i*4+j+2
-			idxs[i*6+k+5]=i*4+j+3
-		Next
-	Next
-	glBufferData( GL_ELEMENT_ARRAY_BUFFER,idxs.Length*2,Varptr idxs[0],GL_STATIC_DRAW )
-End
-
-Function BindVbos:Void()
-
-	glBindBuffer( GL_ARRAY_BUFFER,rs_vbo )
-	glEnableVertexAttribArray( 0 ) ; glVertexAttribPointer( 0,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 0 ) )
-	glEnableVertexAttribArray( 1 ) ; glVertexAttribPointer( 1,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 8 ) )
-	glEnableVertexAttribArray( 2 ) ; glVertexAttribPointer( 2,2,GL_FLOAT,False,BYTES_PER_VERTEX,Byte Ptr( 16 ) )
-	glEnableVertexAttribArray( 3 ) ; glVertexAttribPointer( 3,4,GL_UNSIGNED_BYTE,True,BYTES_PER_VERTEX,Byte Ptr( 24 ) )
-
-	glBindBuffer( GL_ELEMENT_ARRAY_BUFFER,rs_ibo )
-End
-
-Global inited:Bool
-
-Function InitMojo2:Void()
-	If inited Return
-	inited=True
-	
-	InitVbos()
-	
-	glGetIntegerv( GL_FRAMEBUFFER_BINDING,Varptr defaultFbo )
-	
-	mainShader=LoadString( "asset::mojo2/mojo2_program.glsl" )
-	
-	fastShader=New Shader( LoadString( "asset::mojo2/mojo2_fastshader.glsl" ) )
-	bumpShader=New BumpShader( LoadString( "asset::mojo2/mojo2_bumpshader.glsl" ) )
-	matteShader=New MatteShader( LoadString( "asset::mojo2/mojo2_matteshader.glsl" ) )
-	shadowShader=New Shader( LoadString( "asset::mojo2/mojo2_shadowshader.glsl" ) )
-	lightMapShader=New Shader( LoadString( "asset::mojo2/mojo2_lightmapshader.glsl" ) )
-	defaultShader=bumpShader
-	
-	defaultFont=Font.Load( "asset::mojo2/mojo2_font.png",32,96,True )'9,13,1,0,7,13,32,96 )
-	If Not defaultFont Mojo2Error( "Can't load default font" )
-	
-	flipYMatrix[5]=-1
-
-End
-
-Class RefCounted
-
-	Method Retain:Void()
-		If _refs<=0 Mojo2Error( "Internal error" )
-		_refs+=1
-	End
-	
-	Method Release:Void()
-		If _refs<=0 Mojo2Error( "Internal error" )
-		
-		_refs-=1
-		If _refs Return
-		_refs=-1
-		Destroy()
-	End
-	
-	Method Destroy:Void() Abstract
-	
-Private
-
-	Field _refs:=1
-End
-
-Function KludgePath:String( path:String )
-'	If path.StartsWith( "." ) Or path.StartsWith( "/" ) Return path
-'	Local i:=path.Find( ":/" )
-'	If i<>-1 And path.Find("/")=i+1 Return path
-	Return "asset::"+path
-End
-
-Public
-
-Function CrashGraphics:Void()
-	graphicsSeq+=1
-End
-
-'***** Texture *****
-
-Class Texture Extends RefCounted
-
-	'flags
-	Const Filter:=1
-	Const Mipmap:=2
-	Const ClampS:=4
-	Const ClampT:=8
-	Const ClampST:=12
-	Const RenderTarget:=16
-	Const Managed:=256
-	
-	Method New( width:Int,height:Int,format:Int,flags:Int,data:Pixmap=Null )
-	
-		If format<>4 Mojo2Error( "Invalid texture format: "+format )
-
-		'can't mipmap NPOT textures on gles20
-		If Not IsPow2( width ) Or Not IsPow2( height ) flags&=~Mipmap
-		
-		_width=width
-		_height=height
-		_format=format
-		_flags=flags
-		_data=data
-		
-		If _flags & Managed
-			_managed=New Pixmap( width,height,PixelFormat.RGBA32 )
-			If _data
-				_managed.Paste( _data,0,0 )
-				_data=Null
-			Else
-				_managed.ClearARGB( $ffff00ff )
-			Endif
-		Endif
-		
-		Validate()
-	End
-	
-	Method Destroy:Void() Override
-		If _seq=graphicsSeq	
-			If _glTexture glDeleteTextures( 1,Varptr _glTexture )
-			If _glFramebuffer glDeleteFramebuffers( 1,Varptr _glFramebuffer )
-		Endif
-		_glTexture=0
-		_glFramebuffer=0
-	End
-	
-	Property Width:Int()
-		Return _width
-	End
-	
-	Property Height:Int()
-		Return _height
-	End
-	
-	Property Format:Int()
-		Return _format
-	End
-	
-	Property Flags:Int()
-		Return _flags
-	End
-	
-	Method SetData( x:Int,y:Int,pixmap:Pixmap )
-	
-		If _managed
-			If pixmap<>_managed _managed.Paste( pixmap,x,y )
-		Else If _data
-			If pixmap<>_data Mojo2Error( "Texture is read only" )
-		Endif
-		
-		glPushTexture2d( GLTexture )
-		
-		Local width:=pixmap.Width,height:=pixmap.Height
-		
-		If pixmap.Pitch=_width*4
-		
-			glTexSubImage2D( GL_TEXTURE_2D,0,x,y,width,height,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.Data )
-			
-		Else
-		
-			For Local iy:=0 Until height
-				glTexSubImage2D( GL_TEXTURE_2D,0,x,y+iy,width,1,GL_RGBA,GL_UNSIGNED_BYTE,pixmap.PixelPtr( 0,iy ) )
-			Next
-			
-		Endif
-		
-		glFlush()
-		
-		glPopTexture2d()
-		
-	End
-	
-	Method UpdateMipmaps:Void()
-		If Not (_flags & Mipmap) Return
-		
-		If _seq<>graphicsSeq
-			Validate()
-			Return
-		Endif
-
-		glPushTexture2d( GLTexture )
-
-		glGenerateMipmap( GL_TEXTURE_2D )
-		
-		glPopTexture2d()
-	End
-	
-	Property Loading:Bool()
-		Return False
-	End
-	
-	Property GLTexture:Int()
-		Validate()
-		Return _glTexture
-	End
-	
-	Property GLFramebuffer:Int()
-		Validate()
-		Return _glFramebuffer
-	End		
-	
-	Function TexturesLoading:Int()
-		Return 0
-	End
-	
-	Function Load:Texture( path:String,format:Int=4,flags:Int=Filter|Mipmap|ClampST )
-
-		Local data:=Pixmap.Load( path,PixelFormat.RGBA32 )
-		If Not data Return Null
-		
-		data.PremultiplyAlpha()
-		
-		Local tex:=New Texture( data.Width,data.Height,format,flags,data )
-		
-		Return tex
-	End
-	
-	Function Color:Texture( color:Int )
-		Local tex:=_colors[color]
-		If tex Return tex
-		Local pixmap:=New Pixmap( 1,1,PixelFormat.RGBA32 )
-		pixmap.ClearARGB( color )
-		tex=New Texture( 1,1,4,ClampST,pixmap )
-		_colors[color]=tex
-		Return tex
-	End
-	
-	Function Black:Texture()
-		If Not _black _black=Color( $ff000000 )
-		Return _black
-	End
-	
-	Function White:Texture()
-		If Not _white _white=Color( $ffffffff )
-		Return _white
-	End
-	
-	Function Magenta:Texture()
-		If Not _magenta _magenta=Color( $ffff00ff )
-		Return _magenta
-	End
-	
-	Function Flat:Texture()
-		If Not _flat _flat=Color( $ff888888 )
-		Return _flat
-	End
-	
-	Private
-	
-	Field _seq:Int
-	Field _width:Int
-	Field _height:Int
-	Field _format:Int
-	Field _flags:Int
-	Field _data:Pixmap
-	Field _managed:Pixmap
-	
-	Field _glTexture:GLuint
-	Field _glFramebuffer:GLuint
-	
-	Global _colors:=New IntMap<Texture>
-	Global _black:Texture
-	Global _white:Texture
-	Global _magenta:Texture
-	Global _flat:Texture
-	
-	Method Validate()
-
-		If _seq=graphicsSeq Return
-		
-		InitMojo2()
-		
-		_seq=graphicsSeq
-	
-		glGenTextures( 1,Varptr _glTexture )
-		
-		glPushTexture2d( _glTexture )
-		
-		If _flags & Filter
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR )
-		Else
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST )
-		Endif
-		
-		If (_flags & Mipmap) And (_flags & Filter)
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR )
-		Else If _flags & Mipmap
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST )
-		Else If _flags & Filter
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR )
-		Else
-			glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST )
-		Endif
-
-		If _flags & ClampS glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE )
-		If _flags & ClampT glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE )
-
-		glTexImage2D( GL_TEXTURE_2D,0,GL_RGBA,_width,_height,0,GL_RGBA,GL_UNSIGNED_BYTE,Null )
-
-		glPopTexture2d()
-		
-		If _flags & RenderTarget
-		
-			glGenFramebuffers( 1,Varptr _glFramebuffer )
-			
-			glPushFramebuffer( _glFramebuffer )
-			
-			glBindFramebuffer( GL_FRAMEBUFFER,_glFramebuffer )
-			glFramebufferTexture2D( GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,_glTexture,0 )
-			
-			If glCheckFramebufferStatus( GL_FRAMEBUFFER )<>GL_FRAMEBUFFER_COMPLETE Mojo2Error( "Incomplete framebuffer" )
-			
-			glPopFramebuffer()
-			
-		Endif
-		
-		If _managed
-		
-			SetData( 0,0,_managed )
-			UpdateMipmaps()
-			
-		Else If _data
-		
-			SetData( 0,0,_data )
-			UpdateMipmaps()
-		
-		Endif
-		
-	End
-	
-End
-
-'***** Shader ****
-
-Private
-
-Class GLUniform
-	Field name:String
-	Field location:Int
-	Field size:Int
-	Field type:Int
-	
-	Method New( name:String,location:Int,size:Int,type:Int )
-		Self.name=name
-		Self.location=location
-		Self.size=size
-		Self.type=type
-	End
-	
-End
-
-Class GLProgram
-	Field program:Int
-	'material uniforms
-	Field matuniforms:GLUniform[]
-	'hard coded uniform locations
-	Field mvpMatrix:Int
-	Field mvMatrix:Int
-	Field clipPosScale:Int
-	Field globalColor:Int
-	Field ambientLight:Int
-	Field fogColor:Int
-	Field lightColors:Int
-	Field lightVectors:Int
-	Field shadowTexture:Int
-	
-	Method New( program:Int,matuniforms:GLUniform[] )
-		Self.program=program
-		Self.matuniforms=matuniforms
-		mvpMatrix=glGetUniformLocation( program,"ModelViewProjectionMatrix" )
-		mvMatrix=glGetUniformLocation( program,"ModelViewMatrix" )
-		clipPosScale=glGetUniformLocation( program,"ClipPosScale" )
-		globalColor=glGetUniformLocation( program,"GlobalColor" )
-		fogColor=glGetUniformLocation( program,"FogColor" )
-		ambientLight=glGetUniformLocation( program,"AmbientLight" )
-		lightColors=glGetUniformLocation( program,"LightColors" )
-		lightVectors=glGetUniformLocation( program,"LightVectors" )
-		shadowTexture=glGetUniformLocation( program,"ShadowTexture" )
-	End
-	
-	Method Bind:Void()
-	
-		glUseProgram( program )
-		
-		If mvpMatrix<>-1 glUniformMatrix4fv( mvpMatrix,1,False,Varptr rs_modelViewProjMatrix[0] )
-		If mvMatrix<>-1 glUniformMatrix4fv( mvMatrix,1,False,Varptr rs_modelViewMatrix[0] )
-		If clipPosScale<>-1 glUniform4fv( clipPosScale,1,Varptr rs_clipPosScale[0] )
-		If globalColor<>-1 glUniform4fv( globalColor,1,Varptr rs_globalColor[0] )
-		If fogColor<>-1 glUniform4fv( fogColor,1,Varptr rs_fogColor[0] )
-		If ambientLight<>-1 glUniform4fv( ambientLight,1,Varptr rs_ambientLight[0] )
-		If lightColors<>-1 glUniform4fv( lightColors,rs_numLights,Varptr rs_lightColors[0] )
-		If lightVectors<>-1 glUniform4fv( lightVectors,rs_numLights,Varptr rs_lightVectors[0] )
-		If shadowTexture<>-1 
-			Local tex:=rs_shadowTexture
-			If Not tex tex=Texture.White()
-			glActiveTexture( GL_TEXTURE0+7 )
-			glBindTexture( GL_TEXTURE_2D,tex.GLTexture )
-			glActiveTexture( GL_TEXTURE0 )
-			glUniform1i( shadowTexture,7 )
-		End
-	End
-	
-End
-
-Public
-
-Class Shader
-
-	Method New( source:String )
-		Build( source )
-	End
-	
-	Property DefaultMaterial:Material()
-		If Not _defaultMaterial _defaultMaterial=New Material( Self )
-		Return _defaultMaterial
-	End
-	
-	Function FastShader:Shader()
-		Return fastShader
-	End
-	
-	Function BumpShader:Shader()
-		Return bumpShader
-	End
-	
-	Function MatteShader:Shader()
-		Return matteShader
-	End
-	
-	Function ShadowShader:Shader()
-		Return shadowShader
-	End
-	
-	Function LightMapShader:Shader()
-		Return lightMapShader
-	End
-	
-	Function DefaultShader:Shader()
-		Return defaultShader
-	End
-	
-	Function SetDefaultShader:Void( shader:Shader )
-		If Not shader shader=bumpShader
-		defaultShader=shader
-	End
-	
-	Protected
-	
-	Method Build:Void( source:String )
-		_source=source
-		Build()
-	End
-	
-	Method OnInitMaterial:Void( material:Material ) Virtual
-		material.SetTexture( "ColorTexture",Texture.White() )
-	End
-	
-	Method OnLoadMaterial:Material( material:Material,path:String,texFlags:Int ) Virtual
-		Local texture:=Texture.Load( path,4,texFlags )
-		If Not texture Return Null
-		material.SetTexture( "ColorTexture",texture )
-		If texture texture.Release()
-		Return material
-	End
-	
-	Private
-	
-	Const MAX_FLAGS:=8
-	
-	Field _seq:Int
-	Field _source:String
-	
-	Field _vsource:String
-	Field _fsource:String
-	Field _uniforms:=New StringMap<Bool>
-	
-	Field _glPrograms:=New GLProgram[MAX_LIGHTS+1]
-	
-	Field _defaultMaterial:Material
-	
-	Method Bind:Void()
-			
-		Local program:=GLProgram
-		
-		If program=rs_program Return
-
-		rs_program=program
-		rs_material=Null
-		
-		program.Bind()
-	End
-	
-	Property GLProgram:GLProgram()
-	
-		If _seq<>graphicsSeq 
-			_seq=graphicsSeq
-			rs_program=Null
-			Build()
-		Endif
-		
-		Return _glPrograms[rs_numLights]
-	End
-	
-	Method Build:GLProgram( numLights:Int )
-	
-		Local defs:=""
-		defs+="#define NUM_LIGHTS "+numLights+"~n"
-		
-		Local vshader:=glCompile( GL_VERTEX_SHADER,defs+_vsource )
-		Local fshader:=glCompile( GL_FRAGMENT_SHADER,defs+_fsource )
-		
-		Local program:=glCreateProgram()
-		glAttachShader( program,vshader )
-		glAttachShader( program,fshader )
-		glDeleteShader( vshader )
-		glDeleteShader( fshader )
-		
-		glBindAttribLocation( program,0,"Position" )
-		glBindAttribLocation( program,1,"Texcoord0" )
-		glBindAttribLocation( program,2,"Tangent" )
-		glBindAttribLocation( program,3,"Color" )
-		
-		glLink( program )
-		
-		'enumerate program uniforms	
-		Local matuniforms:=New Stack<GLUniform>
-		
-		Local n:Int
-		glGetProgramiv( program,GL_ACTIVE_UNIFORMS,Varptr n )
-
-		Local size:Int,type:UInt,length:Int,nameBuf:=New Byte[256]
-		
-		For Local i:=0 Until n
-			glGetActiveUniform( program,i,nameBuf.Length,Varptr length,Varptr size,Varptr type,Cast<GLchar Ptr>( Varptr nameBuf[0] ) )
-			Local name:=String.FromCString( nameBuf.Data )
-			If _uniforms.Contains( name )
-				Local location:=glGetUniformLocation( program,name )
-				If location=-1 Continue  'IE fix...
-				matuniforms.Push( New GLUniform( name,location,size,type ) )
-			Endif
-		Next
-		
-		Return New GLProgram( program,matuniforms.ToArray() )
-	
-	End
-	
-	Method Build:Void()
-
-		InitMojo2()
-		
-		Local p:=New GlslParser( _source )
-		
-		Local vars:=New StringMap<Bool>
-		
-		While p.Toke
-		
-			If p.CParse( "uniform" )
-				'uniform decl
-				Local ty:=p.ParseType()
-				Local id:=p.ParseIdent()
-				p.Parse( ";" )
-				_uniforms.Set( id,True )
-'				Print "uniform "+ty+" "+id+";"
-				Continue
-			Endif
-			
-			Local id:=p.CParseIdent()
-			If id
-				If id.StartsWith( "gl_" )
-					vars.Set( "B3D_"+id.ToUpper(),True )
-				Else If id.StartsWith( "b3d_" ) 
-					vars.Set( id.ToUpper(),True )
-				Endif
-				Continue
-			Endif
-			
-			p.Bump()
-		Wend
-		
-		Local vardefs:=""
-		For Local tvar:=Eachin vars.Keys
-			vardefs+="#define "+tvar+" 1~n"
-		Next
-		
-'		Print "Vardefs:";Print vardefs
-		
-		Local source:=mainShader
-		Local i0:=source.Find( "//@vertex" )
-		If i0=-1 Mojo2Error( "Can't find //@vertex chunk" )
-		Local i1:=source.Find( "//@fragment" )
-		If i1=-1 Mojo2Error( "Can't find //@fragment chunk" )
-		
-		Local header:=vardefs+source.Slice( 0,i0 )
-		_vsource=header+source.Slice( i0,i1 )
-		_fsource=header+source.Slice( i1 ).Replace( "${SHADER}",_source )
-		
-		For Local numLights:=0 To MAX_LIGHTS
-		
-			_glPrograms[numLights]=Build( numLights )
-
-			If numLights Or vars.Contains( "B3D_DIFFUSE" ) Or vars.Contains( "B3D_SPECULAR" ) Continue
-			
-			For Local i:=1 To MAX_LIGHTS
-				_glPrograms[i]=_glPrograms[0]
-			Next
-			
-			Exit
-			
-		Next
-		
-	End
-	
-End
-
-Class BumpShader Extends Shader
-
-	Method New( source:String )
-		Super.New( source )
-	End
-
-	Protected
-	
-	Method OnInitMaterial:Void( material:Material ) Override
-		material.SetTexture( "ColorTexture",Texture.White() )
-		material.SetTexture( "SpecularTexture",Texture.Black() )
-		material.SetTexture( "NormalTexture",Texture.Flat() )
-		material.SetVector( "AmbientColor",New Float[]( 1.0,1.0,1.0,1.0 ) )
-		material.SetScalar( "Roughness",1.0 )
-	End
-	
-	Method OnLoadMaterial:Material( material:Material,path:String,texFlags:Int ) Override
-	
-		Local format:=4
-	
-		Local ext:=ExtractExt( path )
-		If ext path=StripExt( path ) Else ext=".png"
-
-		Local colorTex:=Texture.Load( path+ext,format,texFlags )
-		If Not colorTex colorTex=Texture.Load( path+"_d"+ext,format,texFlags )
-		If Not colorTex colorTex=Texture.Load( path+"_diff"+ext,format,texFlags )
-		If Not colorTex colorTex=Texture.Load( path+"_diffuse"+ext,format,texFlags )
-		
-		Local specularTex:=Texture.Load( path+"_s"+ext,format,texFlags )
-		If Not specularTex specularTex=Texture.Load( path+"_spec"+ext,format,texFlags )
-		If Not specularTex specularTex=Texture.Load( path+"_specular"+ext,format,texFlags )
-		If Not specularTex specularTex=Texture.Load( path+"_SPECULAR"+ext,format,texFlags )
-		
-		Local normalTex:=Texture.Load( path+"_n"+ext,format,texFlags )
-		If Not normalTex normalTex=Texture.Load( path+"_norm"+ext,format,texFlags )
-		If Not normalTex normalTex=Texture.Load( path+"_normal"+ext,format,texFlags )
-		If Not normalTex normalTex=Texture.Load( path+"_NORMALS"+ext,format,texFlags )
-
-		If Not colorTex And Not specularTex And Not normalTex Return Null
-
-		material.SetTexture( "ColorTexture",colorTex )
-		material.SetTexture( "SpecularTexture",specularTex )
-		material.SetTexture( "NormalTexture",normalTex )
-		
-		If specularTex Or normalTex
-			material.SetVector( "AmbientColor",New Float[]( 0.0,0.0,0.0,1.0 ) )
-			material.SetScalar( "Roughness",.5 )
-		Endif
-		
-		If colorTex colorTex.Release()
-		If specularTex specularTex.Release()
-		If normalTex normalTex.Release()
-		
-		Return material
-	End
-	
-End	
-
-Class MatteShader Extends Shader
-
-	Method New( source:String )
-		Super.New( source )
-	End
-	
-	Protected
-	
-	Method OnInitMaterial:Void( material:Material ) Override
-		material.SetTexture( "ColorTexture",Texture.White() )
-		material.SetVector( "AmbientColor",New Float[]( 0.0,0.0,0.0,1.0 ) )
-		material.SetScalar( "Roughness",1.0 )
-	End
-	
-End
-
-'***** Material *****
-
-Class Material Extends RefCounted
-
-	Method New( shader:Shader=Null )
-		InitMojo2()
-		
-		If Not shader shader=defaultShader
-		_shader=shader
-		_shader.OnInitMaterial( Self )
-		_inited=True
-	End
-	
-	Method Discard:Void()
-		Super.Release()
-	End
-	
-	Method Destroy:Void() Override
-		For Local tex:=Eachin _textures
-			tex.Value.Release()
-		Next
-	End
-	
-	Property Shader:Shader()
-		Return _shader
-	End
-	
-	Property ColorTexture:Texture()
-		Return _colorTexture
-	End
-	
-	Property Width:Int()
-		If _colorTexture Return _colorTexture._width
-		Return 0
-	End
-	
-	property Height:Int()
-		If _colorTexture Return _colorTexture._height
-		Return 0
-	End
-	
-	Method SetScalar:Void( param:String,scalar:Float )
-		If _inited And Not _scalars.Contains( param ) Return
-		_scalars.Set( param,scalar )
-	End
-	
-	Method GetScalar:Float( param:String,defValue:Float=1.0 )
-		If Not _scalars.Contains( param ) Return defValue
-		Return _scalars.Get( param )
-	End
-	
-	Method SetVector:Void( param:String,vector:Float[] )
-		If _inited And Not _vectors.Contains( param ) Return
-		_vectors.Set( param,vector )
-	End
-	
-	Method GetVector:Float[]( param:String,defValue:Float[]=New Float[]( 1.0,1.0,1.0,1.0 ) )
-		If Not _vectors.Contains( param ) Return defValue
-		Return _vectors.Get( param )
-	End
-	
-	Method SetTexture:Void( param:String,texture:Texture )
-		If Not texture Return
-		If _inited And Not _textures.Contains( param ) Return
-		
-		Local old:=_textures.Get( param )
-		texture.Retain()
-		_textures.Set( param,texture )
-		If old old.Release()
-		
-		If param="ColorTexture" _colorTexture=texture
-	End
-	
-	Method GetTexture:Texture( param:String,defValue:Texture=Null )
-		If Not _textures.Contains( param ) Return defValue
-		Return _textures.Get( param )
-	End
-	
-	Method Loading:Bool()
-		Return False
-	End
-	
-	Function Load:Material( path:String,texFlags:Int,shader:Shader )
-	
-		Local material:=New Material( shader )
-		
-		material=material.Shader.OnLoadMaterial( material,path,texFlags )
-		
-		Return material
-	End
-	
-	Private
-	
-	Field _shader:Shader
-	Field _colorTexture:Texture
-	Field _scalars:=New StringMap<Float>
-	Field _vectors:=New StringMap<Float[]>
-	Field _textures:=New StringMap<Texture>
-	Field _inited:Bool
-	
-	Method Bind:Bool()
-	
-		_shader.Bind()
-		
-		If rs_material=Self Return True
-		
-		rs_material=Self
-	
-		Local texid:=0
-		
-		For Local u:=Eachin rs_program.matuniforms
-			Select u.type
-			Case GL_FLOAT
-				glUniform1f( u.location,GetScalar( u.name ) )
-			Case GL_FLOAT_VEC4
-				glUniform4fv( u.location,1,Varptr GetVector( u.name )[0] )
-			Case GL_SAMPLER_2D
-				Local tex:=GetTexture( u.name )
-				If Not tex
-					Print "No texture! "+u.name
-				Endif
-				If tex.Loading
-					rs_material=Null 
-					Exit
-				Endif
-				glActiveTexture( GL_TEXTURE0+texid )
-				glBindTexture( GL_TEXTURE_2D,tex.GLTexture )
-				glUniform1i( u.location,texid )
-				texid+=1
-			Default
-				Mojo2Error( "Unsupported uniform type:"+u.type )
-			End
-		Next
-
-		If texid glActiveTexture( GL_TEXTURE0 )
-		
-		Return rs_material=Self
-	End
-	
-End
-
-'***** ShaderCaster *****
-
-Class ShadowCaster
-
-	Method New()
-	End
-
-	Method New( verts:Float[],type:Int )
-		_verts=verts
-		_type=type
-	End
-	
-	Method SetVertices:Void( vertices:Float[] )
-		_verts=vertices
-	End
-	
-	Property Vertices:Float[]()
-		Return _verts
-	End
-	
-	Method SetType:Void( type:Int )
-		_type=type
-	End
-	
-	Property Type:Int()
-		Return _type
-	End
-	
-	Private
-	
-	Field _verts:Float[]
-	Field _type:Int
-	
-End
-
-'***** Image *****
-
-Class Image
-
-	Const Filter:=Texture.Filter
-	Const Mipmap:=Texture.Mipmap
-	Const Managed:=Texture.Managed
-	
-	Method New( pixmap:Pixmap,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter )
-		Local texture:=New Texture( pixmap.Width,pixmap.Height,4,flags|Texture.ClampST,pixmap )
-		_material=New Material( fastShader )
-		_material.SetTexture( "ColorTexture",texture )
-		texture.Release()
-		_width=pixmap.Width
-		_height=pixmap.Height
-		SetHandle( xhandle,yhandle )
-	End
-	
-	Method New( width:Int,height:Int,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter )
-		Local texture:=New Texture( width,height,4,flags|Texture.ClampST|Texture.RenderTarget )
-		_material=New Material( fastShader )
-		_material.SetTexture( "ColorTexture",texture )
-		texture.Release()
-		_width=width
-		_height=height
-		SetHandle( xhandle,yhandle )
-	End
-	
-	Method New( image:Image,x:Int,y:Int,width:Int,height:Int,xhandle:Float=.5,yhandle:Float=.5 )
-		_material=image._material
-		_material.Retain()
-		_x=image._x+x
-		_y=image._y+y
-		_width=width
-		_height=height
-		SetHandle( xhandle,yhandle )
-	End
-	
-	Method New( material:Material,xhandle:Float=.5,yhandle:Float=.5 )
-		Local texture:=material.ColorTexture
-		If Not texture Mojo2Error( "Material has no ColorTexture" )
-		_material=material
-		_material.Retain()
-		_width=_material.Width
-		_height=_material.Height
-		SetHandle( xhandle,yhandle )
-	End
-
-	Method New( material:Material,x:Int,y:Int,width:Int,height:Int,xhandle:Float=.5,yhandle:Float=.5 )
-		Local texture:=material.ColorTexture
-		If Not texture Mojo2Error( "Material has no ColorTexture" )
-		_material=material
-		_material.Retain()
-		_x=x
-		_y=y
-		_width=width
-		_height=height
-		SetHandle( xhandle,yhandle )
-	End
-
-	Method Discard:Void()
-		If _material _material.Release()
-		_material=Null
-	End
-	
-	Property Material:Material()
-		Return _material
-	End
-	
-	Property X0:Float()
-		Return _x0
-	End
-	
-	Property Y0:Float()
-		Return _y0
-	End
-	
-	Property X1:Float()
-		Return _x1
-	End
-	
-	Property Y1:Float()
-		Return _y1
-	End
-	
-	Property Width:Int()
-		Return _width
-	End
-	
-	Property Height:Int()
-		Return _height
-	End
-	
-	Property HandleX:Float()
-		Return -_x0/(_x1-_x0)
-	End
-	
-	Property HandleY:Float()
-		Return -_y0/(_y1-_y0)
-	End
-	
-'	Method WritePixels:Void( x:Int,y:Int,width:Int,height:Int,data:DataBuffer,dataOffset:Int=0,dataPitch:Int=0 )
-'		_material.ColorTexture.WritePixels( x+_x,y+_y,width,height,data,dataOffset,dataPitch )
-'	End
-	
-	Method SetHandle:Void( xhandle:Float,yhandle:Float )
-		_x0=Float(_width)*-xhandle
-		_x1=Float(_width)*(1-xhandle)
-		_y0=Float(_height)*-yhandle
-		_y1=Float(_height)*(1-yhandle)
-		_s0=Float(_x)/Float(_material.Width)
-		_t0=Float(_y)/Float(_material.Height)
-		_s1=Float(_x+_width)/Float(_material.Width)
-		_t1=Float(_y+_height)/Float(_material.Height)
-	End
-	
-	Method SetShadowCaster:Void( shadowCaster:ShadowCaster )
-		_caster=shadowCaster
-	End
-	
-	Property ShadowCaster:ShadowCaster()
-		Return _caster
-	End
-	
-	Method Loading:Bool()
-		Return _material.Loading()
-	End
-	
-	Function ImagesLoading:Bool()
-		Return Texture.TexturesLoading()>0
-	End
-	
-	Function Load:Image( path:String,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter|Image.Mipmap,shader:Shader=Null )
-	
-		Local material:=mojo2.Material.Load( path,flags|Texture.ClampST,shader )
-		If Not material Return Null
-		
-		Return New Image( material,xhandle,yhandle )
-	End
-	
-	Function LoadFrames:Image[]( path:String,numFrames:Int,padded:Bool=False,xhandle:Float=.5,yhandle:Float=.5,flags:Int=Image.Filter|Image.Mipmap,shader:Shader=Null )
-	
-		Local material:=mojo2.Material.Load( path,flags|Texture.ClampST,shader )
-		If Not material Return Null
-		
-		Local cellWidth:=material.Width/numFrames,cellHeight:=material.Height
-		
-		Local x:=0,width:=cellWidth
-		If padded x+=1;width-=2
-		
-		Local frames:=New Image[numFrames]
-		
-		For Local i:=0 Until numFrames
-			frames[i]=New Image( material,i*cellWidth+x,0,width,cellHeight,xhandle,yhandle )
-		Next
-		
-		Return frames
-	End
-	
-	Private
-	
-	Field _material:Material
-	Field _x:Int,_y:Int,_width:Int,_height:Int
-	Field _x0:Float=-1,_y0:Float=-1,_x1:Float=1,_y1:Float=1
-	Field _s0:Float=0 ,_t0:Float=0 ,_s1:Float=1,_t1:Float=1
-
-	Field _caster:ShadowCaster
-	
-'	Method SetFrame:Void( x0:Float,y0:Float,x1:Float,y1:Float,s0:Float,t0:Float,s1:Float,t1:Float )
-'		_x0=x0;_y0=y0;_x1=x1;_y1=y1
-'		_s0=s0;_t0=t0;_s1=s1;_t1=t1
-'	End
-	
-End
-
-'***** Font *****
-
-Class Glyph
-	Field image:Image
-	Field gchar:Int
-	Field x:Int
-	Field y:Int
-	Field width:Int
-	Field height:Int
-	Field xoffset:Float
-	Field yoffset:Float
-	Field advance:Float
-	
-	Method New( image:Image,gchar:Int,x:Int,y:Int,width:Int,height:Int,xoffset:Float,yoffset:Float,advance:Float )
-		Self.image=image
-		Self.gchar=gchar
-		Self.x=x
-		Self.y=y
-		Self.width=width
-		Self.height=height
-		Self.xoffset=xoffset
-		Self.yoffset=yoffset
-		Self.advance=advance
-	End
-End
-
-Class Font
-
-	Method New( glyphs:Glyph[],firstChar:Int,height:Float )
-		_glyphs=glyphs
-		_firstChar=firstChar
-		_height=height
-	End
-
-	Method GetGlyph:Glyph( gchar:Int )
-		Local i:=gchar-_firstChar
-		If i>=0 And i<_glyphs.Length Return _glyphs[i]
-		Return Null
-	End
-	
-	Method TextWidth:Float( text:String )
-		Local w:=0.0
-		For Local gchar:=Eachin text
-			Local glyph:=GetGlyph( gchar )
-			If Not glyph Continue
-			w+=Ceil( glyph.advance )
-		Next
-		Return w
-	End
-
-	Method TextHeight:Float( text:String )
-		Return _height
-	End
-	
-	Property Height:Int()
-		Return _height
-	End
-	
-	Function LoadTTF:Font( path:String,height:Int,firstChar:Int,numChars:Int )
-	
-		#rem
-		'scale height DPI...
-		Local ddpi:Float,hdpi:Float,vdpi:Float
-		If sdl2.SDL_GetDisplayDPI( 0,Varptr ddpi,Varptr hdpi,Varptr vdpi )=0
-'			Print "vdpi="+vdpi
-
-'			Local height0:=height
-	
-'			height=Ceil( height*Clamp( vdpi/96.0,1.0,4.0 )+.5 )
-			height=Floor( height*Clamp( vdpi/72.0,1.0,4.0 )+.5 )
-			
-'			Print "height0="+height0+", height="+height
-		Endif
-		#end
-		
-		Local data:=DataBuffer.Load( path )
-		If Not data Return Null
-		
-		'Get font info
-		Local f:stbtt_fontinfo,fp:=Varptr f
-		If Not stbtt_InitFont( fp,data.Data,0 ) Return Null
-	
-		Local ascenti:Int,descenti:Int,linegapi:Int
-		stbtt_GetFontVMetrics( fp,Varptr ascenti,Varptr descenti,Varptr linegapi )
-		
-		Local scale:=stbtt_ScaleForPixelHeight( fp,height )
-		Local ascent:=ascenti*scale,descent:=descenti*scale,linegap:=linegapi*scale
-		
-		Local fheight:=(ascenti-descenti+linegapi)*scale
-		
-		'Bake the chars		
-		Local bakedChars:=New stbtt_bakedchar[numChars]
-		Local pixmap:=New Pixmap( 512,512,PixelFormat.I8 )
-		stbtt_BakeFontBitmap( data.Data,0,height,pixmap.Data,512,512,firstChar,numChars,Varptr( bakedChars[0] ) )
-
-		pixmap=pixmap.Convert( PixelFormat.RGBA32 )
-		For Local y:=0 Until 512
-			For Local x:=0 Until 512
-				Local p:=pixmap.GetPixelARGB( x,y )
-				pixmap.SetPixelARGB( x,y,(p & $ff0000) Shl 8 | (p & $ffffff) )
-			Next
-		Next
-		
-		Local texture:=New Texture( 512,512,4,Texture.ClampST,pixmap )
-		
-		Local material:=New Material( fastShader )
-		material.SetTexture( "ColorTexture",texture )
-		
-		Local image:=New Image( material )
-		
-		Local glyphs:=New Glyph[numChars]
-		
-		For Local i:=0 Until numChars
-		
-			Local x:=bakedChars[i].x0
-			Local y:=bakedChars[i].y0
-			Local w:=bakedChars[i].x1-x
-			Local h:=bakedChars[i].y1-y
-			Local xoffset:=bakedChars[i].xoff
-			Local yoffset:=bakedChars[i].yoff+ascent
-			Local advance:=bakedChars[i].xadvance
-			
-			glyphs[i]=New Glyph( image,firstChar+i,x,y,w,h,xoffset,yoffset,advance )
-		Next
-		
-		Return New Font( glyphs,firstChar,fheight )
-	End
-	
-	Function Load:Font( path:String,firstChar:Int,numChars:Int,padded:Bool )
-	
-		Local image:=Image.Load( path )
-		If Not image Return Null
-		
-		Local cellWidth:=image.Width/numChars
-		Local cellHeight:=image.Height
-		
-		Local glyphX:=0,glyphY:=0,glyphWidth:=cellWidth,glyphHeight:=cellHeight
-		If padded glyphX+=1;glyphY+=1;glyphWidth-=2;glyphHeight-=2
-
-		Local w:=image.Width/cellWidth
-		Local h:=image.Height/cellHeight
-
-		Local glyphs:=New Glyph[numChars]
-		
-		For Local i:=0 Until numChars
-			Local y:=i/w
-			Local x:=i-y*w
-			Local glyph:=New Glyph( image,firstChar+i,x*cellWidth+glyphX,y*cellHeight+glyphY,glyphWidth,glyphHeight,0,0,glyphWidth )
-			glyphs[i]=glyph
-		Next
-		
-		Return New Font( glyphs,firstChar,glyphHeight )
-	
-	End
-	
-	Function Load:Font( path:String,cellWidth:Int,cellHeight:Int,firstChar:Int,numChars:Int,padded:Bool )
-	
-		Local image:=Image.Load( path )
-		If Not image Return Null
-		
-		Local glyphX:=0,glyphY:=0,glyphWidth:=cellWidth,glyphHeight:=cellHeight
-		If padded glyphX+=1;glyphY+=1;glyphWidth-=2;glyphHeight-=2
-
-		Local w:=image.Width/cellWidth
-		Local h:=image.Height/cellHeight
-
-		Local glyphs:=New Glyph[numChars]
-		
-		For Local i:=0 Until numChars
-			Local y:=i/w
-			Local x:=i-y*w
-			Local glyph:=New Glyph( image,firstChar+i,x*cellWidth+glyphX,y*cellHeight+glyphY,glyphWidth,glyphHeight,0,0,glyphWidth )
-			glyphs[i]=glyph
-		Next
-		
-		Return New Font( glyphs,firstChar,glyphHeight )
-	
-	End
-	
-	Function Load:Font( path:String,cellWidth:Int,cellHeight:Int,glyphX:Int,glyphY:Int,glyphWidth:Int,glyphHeight:Int,firstChar:Int,numChars:Int )
-
-		Local image:=Image.Load( path )
-		If Not image Return Null
-
-		Local w:=image.Width/cellWidth
-		Local h:=image.Height/cellHeight
-
-		Local glyphs:=New Glyph[numChars]
-		
-		For Local i:=0 Until numChars
-			Local y:=i/w
-			Local x:=i-y*w
-			Local glyph:=New Glyph( image,firstChar+i,x*cellWidth+glyphX,y*cellHeight+glyphY,glyphWidth,glyphHeight,0,0,glyphWidth )
-			glyphs[i]=glyph
-		Next
-		
-		Return New Font( glyphs,firstChar,glyphHeight )
-	End
-	
-	Function Open:Font( path:String,height:Int )
-	
-		Local tag:=path+"@"+String( height )
-		
-		Local font:=_fontCache[tag]
-		If Not font
-			If _fontCache.Contains( tag ) Return Null
-			font=LoadTTF( path,height,32,96 )
-			_fontCache[tag]=font
-			
-		Endif
-		
-		Return font
-	End
-	
-	Private
-	
-	Field _glyphs:Glyph[]
-	Field _firstChar:Int
-	Field _height:Float
-	
-	Global _fontCache:=New StringMap<Font>
-End
-
-'***** DrawList *****
-
-Class DrawOp
-	Field material:Material
-	Field blend:Int
-	Field order:Int
-	Field count:Int
-End
-
-Class BlendMode
-	Const Opaque:=0
-	Const Alpha:=1
-	Const Additive:=2
-	Const Multiply:=3
-	Const Multiply2:=4
-End
-
-Class DrawList
-
-	Method New()
-		InitMojo2()
-		
-		SetFont( Null )
-		SetDefaultMaterial( fastShader.DefaultMaterial )
-	End
-	
-	Method SetBlendMode:Void( blend:Int )
-		_blend=blend
-	End
-	
-	property BlendMode:Int()
-		Return _blend
-	End
-	
-	Method SetColor:Void( r:Float,g:Float,b:Float )
-		_color[0]=r
-		_color[1]=g
-		_color[2]=b
-		_pmcolor=Int(_alpha) Shl 24 | Int(_color[2]*_alpha) Shl 16 | Int(_color[1]*_alpha) Shl 8 | Int(_color[0]*_alpha)
-	End
-	
-	Method SetColor:Void( r:Float,g:Float,b:Float,a:Float )
-		_color[0]=r
-		_color[1]=g
-		_color[2]=b
-		_color[3]=a
-		_alpha=a*255
-		_pmcolor=Int(_alpha) Shl 24 | Int(_color[2]*_alpha) Shl 16 | Int(_color[1]*_alpha) Shl 8 | Int(_color[0]*_alpha)
-	End
-	
-	Method SetAlpha:Void( a:Float )
-		_color[3]=a
-		_alpha=a*255
-		_pmcolor=Int(_alpha) Shl 24 | Int(_color[2]*_alpha) Shl 16 | Int(_color[1]*_alpha) Shl 8 | Int(_color[0]*_alpha)
-	End
-	
-	Property Color:Float[]()
-		Return New Float[]( _color[0],_color[1],_color[2],_color[3] )
-	End
-	
-	Method GetColor:Void( color:Float[] )
-		color[0]=_color[0]
-		color[1]=_color[1]
-		color[2]=_color[2]
-		If color.Length>3 color[3]=_color[3]
-	End
-	
-	Property Alpha:Float()
-		Return _color[3]
-	End
-	
-	Method ResetMatrix:Void()
-		_ix=1;_iy=0
-		_jx=0;_jy=1
-		_tx=0;_ty=0
-	End
-	
-	Method SetMatrix:Void( ix:Float,iy:Float,jx:Float,jy:Float,tx:Float,ty:Float )
-		_ix=ix;_iy=iy
-		_jx=jx;_jy=jy
-		_tx=tx;_ty=ty
-	End
-	
-	Method GetMatrix:Void( matrix:Float[] )
-		matrix[0]=_ix
-		matrix[1]=_iy
-		matrix[2]=_jx
-		matrix[3]=_jy
-		matrix[4]=_tx
-		matrix[5]=_ty
-	End
-	
-	Method Transform:Void( ix:Float,iy:Float,jx:Float,jy:Float,tx:Float,ty:Float )
-		Local ix2:=ix*_ix+iy*_jx,iy2:=ix*_iy+iy*_jy
-		Local jx2:=jx*_ix+jy*_jx,jy2:=jx*_iy+jy*_jy
-		Local tx2:=tx*_ix+ty*_jx+_tx,ty2:=tx*_iy+ty*_jy+_ty
-		SetMatrix( ix2,iy2,jx2,jy2,tx2,ty2 )
-	End
-
-	Method Translate:Void( tx:Float,ty:Float )
-		Transform( 1,0,0,1,tx,ty )
-	End
-	
-	Method Rotate( rz:Float )
-		Transform( Cos( rz ),-Sin( rz ),Sin( rz ),Cos( rz ),0,0 )
-	End
-	
-	Method Scale:Void( sx:Float,sy:Float )
-		Transform( sx,0,0,sy,0,0 )
-	End
-	
-	Method TranslateRotate:Void( tx:Float,ty:Float,rz:Float )
-		Translate( tx,ty )
-		Rotate( rz )
-	End
-	
-	Method RotateScale:Void( rz:Float,sx:Float,sy:Float )
-		Rotate( rz )
-		Scale( sx,sy )
-	End
-	
-	Method TranslateScale:Void( tx:Float,ty:Float,sx:Float,sy:Float )
-		Translate( tx,ty )
-		Scale( sx,sy )
-	End
-	
-	Method TranslateRotateScale:Void( tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
-		Translate( tx,ty )
-		Rotate( rz )
-		Scale( sx,sy )
-	End
-	
-	Method SetMatrixStackCapacity:Void( capacity:Int )
-		_matStack=New Float[ capacity*6 ]
-		_matSp=0
-	End
-	
-	Method MatrixStackCapacity:Int()
-		Return _matStack.Length/6
-	End
-	
-	Method PushMatrix:Void()
-		_matStack[_matSp+0]=_ix;_matStack[_matSp+1]=_iy
-		_matStack[_matSp+2]=_jx;_matStack[_matSp+3]=_jy
-		_matStack[_matSp+4]=_tx;_matStack[_matSp+5]=_ty
-		_matSp+=6
-		If _matSp>=_matStack.Length _matSp-=_matStack.Length
-	End
-	
-	Method PopMatrix:Void()
-		_matSp-=6
-		If _matSp<0 _matSp+=_matStack.Length
-		_ix=_matStack[_matSp+0];_iy=_matStack[_matSp+1]
-		_jx=_matStack[_matSp+2];_jy=_matStack[_matSp+3]
-		_tx=_matStack[_matSp+4];_ty=_matStack[_matSp+5]
-	End
-	
-	Method SetFont:Void( font:Font )
-		If Not font font=defaultFont
-		_font=font
-	End
-	
-	Property Font:Font()
-		Return _font
-	End
-	
-	Method SetDefaultMaterial:Void( material:Material )
-		_defaultMaterial=material
-	End
-	
-	Property DefaultMaterial:Material()
-		Return _defaultMaterial
-	End
-	
-	Method DrawPoint:Void( x0:Float,y0:Float,material:Material=Null,s0:Float=0,t0:Float=0 )
-		BeginPrim( material,1 )
-		PrimVert( x0+.5,y0+.5,s0,t0 )
-	End
-	
-	Method DrawLine:Void( x0:Float,y0:Float,x1:Float,y1:Float,material:Material=Null,s0:Float=0,t0:Float=0,s1:Float=1,t1:Float=0 )
-		BeginPrim( material,2 )
-		PrimVert( x0+.5,y0+.5,s0,t0 )
-		PrimVert( x1+.5,y1+.5,s1,t1 )
-	End
-	
-	Method DrawTriangle:Void( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,material:Material=Null,s0:Float=.5,t0:Float=0,s1:Float=1,t1:Float=1,s2:Float=0,t2:Float=1 )
-		BeginPrim( material,3 )
-		PrimVert( x0,y0,s0,t0 )
-		PrimVert( x1,y1,s1,t1 )
-		PrimVert( x2,y2,s2,t2 )
-	End
-	
-	Method DrawQuad:Void( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,x3:Float,y3:Float,material:Material=Null,s0:Float=.5,t0:Float=0,s1:Float=1,t1:Float=1,s2:Float=0,t2:Float=1 )
-		BeginPrim( material,4 )
-		PrimVert( x0,y0,s0,t0 )
-		PrimVert( x1,y1,s1,t1 )
-		PrimVert( x2,y2,s2,t2 )
-		PrimVert( x3,y3,s2,t2 )
-	End
-	
-	Method DrawOval:Void( x:Float,y:Float,width:Float,height:Float,material:Material=Null )
-		Local xr:=width/2.0,yr:=height/2.0
-		
-		Local dx_x:=xr*_ix,dx_y:=xr*_iy,dy_x:=yr*_jx,dy_y:=yr*_jy
-		Local dx:=Sqrt( dx_x*dx_x+dx_y*dx_y ),dy:=Sqrt( dy_x*dy_x+dy_y*dy_y )
-
-		Local n:=Int( dx+dy )
-		If n<12 
-			n=12 
-		Else If n>MAX_VERTICES
-			n=MAX_VERTICES
-		Else
-			n&=~3
-		Endif
-		
-		Local x0:=x+xr,y0:=y+yr
-		
-		BeginPrim( material,n )
-		
-		For Local i:=0 Until n
-			Local th:=i*360.0/n
-			Local px:=x0+Cos( th ) * xr
-			Local py:=y0+Sin( th ) * yr
-			PrimVert( px,py,0,0 )
-		Next
-	End
-	
-	Method DrawEllipse:Void( x:Float,y:Float,xr:Float,yr:Float,material:Material=Null )
-		DrawOval( x-xr,y-yr,xr*2,yr*2,material )
-	End
-	
-	Method DrawCircle:Void( x:Float,y:Float,r:Float,material:Material=Null )
-		DrawOval( x-r,y-r,r*2,r*2,material )
-	End
-	
-	Method DrawPoly:Void( vertices:Float[],material:Material=Null )
-	
-		Local n:=vertices.Length/2
-		If n<3 Or n>MAX_VERTICES Return
-	
-		BeginPrim( material,n )
-
-		For Local i:=0 Until n
-			PrimVert( vertices[i*2],vertices[i*2+1],0,0 )
-		Next
-	End
-	
-	Method DrawPrimitives:Void( order:Int,count:Int,vertices:Float[],material:Material=Null )
-	
-		BeginPrims( material,order,count )
-		Local p:=0
-		For Local i:=0 Until count
-			For Local j:=0 Until order
-				PrimVert( vertices[p],vertices[p+1],0,0 )
-				p+=2
-			Next
-		Next
-	End
-	
-	Method DrawPrimitives:Void( order:Int,count:Int,vertices:Float[],texcoords:Float[],material:Material=Null )
-	
-		BeginPrims( material,order,count )
-		Local p:=0
-		For Local i:=0 Until count
-			For Local j:=0 Until order
-				PrimVert( vertices[p],vertices[p+1],texcoords[p],texcoords[p+1] )
-				p+=2
-			Next
-		Next
-	End
-	
-	Method DrawIndexedPrimitives:Void( order:Int,count:Int,vertices:Float[],indices:Int[],material:Material=Null )
-	
-		BeginPrims( material,order,count )
-		Local p:=0
-		For Local i:=0 Until count
-			For Local j:=0 Until order
-				Local k:=indices[p+j]*2
-				PrimVert( vertices[k],vertices[k+1],0,0 )
-			Next
-			p+=order
-		Next
-	
-	End
-	
-	Method DrawIndexedPrimitives:Void( order:Int,count:Int,vertices:Float[],texcoords:Float[],indices:Int[],material:Material=Null )
-	
-		BeginPrims( material,order,count )
-		Local p:=0
-		For Local i:=0 Until count
-			For Local j:=0 Until order
-				Local k:=indices[p+j]*2
-				PrimVert( vertices[k],vertices[k+1],texcoords[k],texcoords[k+1] )
-			Next
-			p+=order
-		Next
-	
-	End
-	
-	Method DrawRect:Void( x0:Float,y0:Float,width:Float,height:Float,material:Material=Null,s0:Float=0,t0:Float=0,s1:Float=1,t1:Float=1 )
-		Local x1:=x0+width,y1:=y0+height
-		BeginPrim( material,4 )
-		PrimVert( x0,y0,s0,t0 )
-		PrimVert( x1,y0,s1,t0 )
-		PrimVert( x1,y1,s1,t1 )
-		PrimVert( x0,y1,s0,t1 )
-	End
-	
-	Method DrawRect:Void( x0:Float,y0:Float,width:Float,height:Float,image:Image )
-		DrawRect( x0,y0,width,height,image._material,image._s0,image._t0,image._s1,image._t1 )
-	End
-	
-	Method DrawRect:Void( x:Float,y:Float,image:Image,sourceX:Int,sourceY:Int,sourceWidth:Int,sourceHeight:Int )
-		DrawRect( x,y,sourceWidth,sourceHeight,image,sourceX,sourceY,sourceWidth,sourceHeight )
-	End
-	
-	Method DrawRect:Void( x0:Float,y0:Float,width:Float,height:Float,image:Image,sourceX:Int,sourceY:Int,sourceWidth:Int,sourceHeight:Int )
-		Local material:=image._material
-		Local s0:=Float(image._x+sourceX)/Float(material.Width)
-		Local t0:=Float(image._y+sourceY)/Float(material.Height)
-		Local s1:=Float(image._x+sourceX+sourceWidth)/Float(material.Width)
-		Local t1:=Float(image._y+sourceY+sourceHeight)/Float(material.Height)
-		DrawRect( x0,y0,width,height,material,s0,t0,s1,t1 )
-	End
-	
-	'gradient rect - kinda hacky, but doesn't slow anything else down
-	Method DrawGradientRect:Void( x0:Float,y0:Float,width:Float,height:Float,r0:Float,g0:Float,b0:Float,a0:Float,r1:Float,g1:Float,b1:Float,a1:Float,axis:Int )
-	
-		r0*=_color[0];g0*=_color[1];b0*=_color[2];a0*=_alpha
-		r1*=_color[0];g1*=_color[1];b1*=_color[2];a1*=_alpha
-		
-		Local pm0:=Int( a0 ) Shl 24 | Int( b0*a0 ) Shl 16 | Int( g0*a0 ) Shl 8 | Int( r0*a0 )
-		Local pm1:=Int( a1 ) Shl 24 | Int( b1*a0 ) Shl 16 | Int( g1*a0 ) Shl 8 | Int( r1*a0 )
-		
-		Local x1:=x0+width,y1:=y0+height,s0:=0.0,t0:=0.0,s1:=1.0,t1:=1.0
-		
-		BeginPrim( Null,4 )
-
-		Local pmcolor:=_pmcolor
-		
-		Select axis
-		Case 0	'left->right
-			_pmcolor=pm0
-			PrimVert( x0,y0,s0,t0 )
-			_pmcolor=pm1
-			PrimVert( x1,y0,s1,t0 )
-			PrimVert( x1,y1,s1,t1 )
-			_pmcolor=pm0
-			PrimVert( x0,y1,s0,t1 )
-		Default	'top->bottom
-			_pmcolor=pm0
-			PrimVert( x0,y0,s0,t0 )
-			PrimVert( x1,y0,s1,t0 )
-			_pmcolor=pm1
-			PrimVert( x1,y1,s1,t1 )
-			PrimVert( x0,y1,s0,t1 )
-		End
-		
-		_pmcolor=pmcolor
-	End
-	
-	Method DrawImage:Void( image:Image )
-		BeginPrim( image._material,4 )
-		PrimVert( image._x0,image._y0,image._s0,image._t0 )
-		PrimVert( image._x1,image._y0,image._s1,image._t0 )
-		PrimVert( image._x1,image._y1,image._s1,image._t1 )
-		PrimVert( image._x0,image._y1,image._s0,image._t1 )
-		If image._caster AddShadowCaster( image._caster )
-	End
-	
-	Method DrawImage:Void( image:Image,tx:Float,ty:Float )
-		PushMatrix()
-		Translate( tx,ty )
-		DrawImage( image )
-		PopMatrix()
-	End
-
-	Method DrawImage:Void( image:Image,tx:Float,ty:Float,rz:Float )
-		PushMatrix()
-		TranslateRotate( tx,ty,rz )
-		DrawImage( image )
-		PopMatrix()
-	End
-	
-	Method DrawImage:Void( image:Image,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
-		PushMatrix()
-		TranslateRotateScale( tx,ty,rz,sx,sy )
-		DrawImage( image )
-		PopMatrix()
-	End
-	
-	Method DrawText:Void( text:String,x:Float,y:Float,xhandle:Float=0,yhandle:Float=0 )
-		x-=_font.TextWidth( text )*xhandle
-		y-=_font.TextHeight( text )*yhandle
-		x=Floor( x+.5 )
-		y=Floor( y+.5 )
-		For Local gchar:=Eachin text
-			Local glyph:=_font.GetGlyph( gchar )
-			If Not glyph Continue
-			DrawRect( x+glyph.xoffset,y+glyph.yoffset,glyph.image,glyph.x,glyph.y,glyph.width,glyph.height )
-			x+=Ceil( glyph.advance )
-		Next
-	End
-	
-	Method DrawShadow:Bool( lx:Float,ly:Float,x0:Float,y0:Float,x1:Float,y1:Float )
-	
-		Local ext:=1024
-	
-		Local dx:=x1-x0,dy:=y1-y0
-		Local d0:=Sqrt( dx*dx+dy*dy )
-		Local nx:=-dy/d0,ny:=dx/d0
-		Local pd:=-(x0*nx+y0*ny)
-		
-		Local d:=lx*nx+ly*ny+pd
-		If d<0 Return False
-
-		Local x2:=x1-lx,y2:=y1-ly
-		Local d2:=ext/Sqrt( x2*x2+y2*y2 )
-		x2=lx+x2*ext;y2=ly+y2*ext
-		
-		Local x3:=x0-lx,y3:=y0-ly
-		Local d3:=ext/Sqrt( x3*x3+y3*y3 )
-		x3=lx+x3*ext;y3=ly+y3*ext
-		
-		Local x4:=(x2+x3)/2-lx,y4:=(y2+y3)/2-ly
-		Local d4:=ext/Sqrt( x4*x4+y4*y4 )
-		x4=lx+x4*ext;y4=ly+y4*ext
-		
-		DrawTriangle( x0,y0,x4,y4,x3,y3 )
-		DrawTriangle( x0,y0,x1,y1,x4,y4 )
-		DrawTriangle( x1,y1,x2,y2,x4,y4 )
-		
-		Return True
-	End
-	
-	Method DrawShadows:Void( x0:Float,y0:Float,drawList:DrawList )
-	
-		Local lx:= x0 * _ix + y0 * _jx + _tx
-		Local ly:= x0 * _iy + y0 * _jy + _ty
-
-		Local verts:=drawList._casterVerts.Data,v0:=0
-		
-		For Local i:=0 Until drawList._casters.Length
-		
-			Local caster:=drawList._casters.Get( i )
-			Local n:=caster._verts.Length
-			
-			Select caster._type
-			Case 0	'closed loop
-				Local x0:=verts[v0+n-2]
-				Local y0:=verts[v0+n-1]
-				For Local i:=0 Until n-1 Step 2
-					Local x1:=verts[v0+i]
-					Local y1:=verts[v0+i+1]
-					DrawShadow( lx,ly,x0,y0,x1,y1 )
-					x0=x1
-					y0=y1
-				Next
-			Case 1	'open loop
-			Case 2	'edge soup
-			End
-			
-			v0+=n
-		Next
-		
-	End
-	
-	Method AddShadowCaster:Void( caster:ShadowCaster )
-		_casters.Push( caster )
-		Local verts:=caster._verts
-		For 	Local i:=0 Until verts.Length-1 Step 2
-			Local x0:=verts[i]
-			Local y0:=verts[i+1]
-			_casterVerts.Push( x0*_ix+y0*_jx+_tx )
-			_casterVerts.Push( x0*_iy+y0*_jy+_ty )
-		Next
-	End
-	
-	Method AddShadowCaster:Void( caster:ShadowCaster,tx:Float,ty:Float )
-		PushMatrix()
-		Translate( tx,ty )
-		AddShadowCaster( caster )
-		PopMatrix()
-	End
-	
-	Method AddShadowCaster:Void( caster:ShadowCaster,tx:Float,ty:Float,rz:Float )
-		PushMatrix()
-		TranslateRotate( tx,ty,rz )
-		AddShadowCaster( caster )
-		PopMatrix()
-	End
-	
-	Method AddShadowCaster:Void( caster:ShadowCaster,tx:Float,ty:Float,rz:Float,sx:Float,sy:Float )
-		PushMatrix()
-		TranslateRotateScale( tx,ty,rz,sx,sy )
-		AddShadowCaster( caster )
-		PopMatrix()
-	End
-	
-	Property IsEmpty:Bool()
-		Return _next=0
-	End
-	
-	Method Compact:Void()
-		If _data.Length=_next Return
-		Local data:=New DataBuffer( _next )
-		_data.CopyTo( data,0,0,_next )
-		_data.Discard()
-		_data=data
-	End
-	
-	Method Render:Void( op:DrawOp,index:Int,count:Int )
-	
-		If Not op.material.Bind() Return
-		
-		If op.blend<>rs_blend
-			rs_blend=op.blend
-			Select rs_blend
-			Case mojo2.BlendMode.Opaque
-				glDisable( GL_BLEND )
-			Case mojo2.BlendMode.Alpha
-				glEnable( GL_BLEND )
-				glBlendFunc( GL_ONE,GL_ONE_MINUS_SRC_ALPHA )
-			Case mojo2.BlendMode.Additive
-				glEnable( GL_BLEND )
-				glBlendFunc( GL_ONE,GL_ONE )
-			Case mojo2.BlendMode.Multiply
-				glEnable( GL_BLEND )
-				glBlendFunc( GL_DST_COLOR,GL_ONE_MINUS_SRC_ALPHA )
-			Case mojo2.BlendMode.Multiply2
-				glEnable( GL_BLEND )
-				glBlendFunc( GL_DST_COLOR,GL_ZERO )
-			End
-		End
-		
-		Select op.order
-		Case 1
-			glDrawArrays( GL_POINTS,index,count )
-		Case 2
-			glDrawArrays( GL_LINES,index,count )
-		Case 3
-			glDrawArrays( GL_TRIANGLES,index,count )
-		Case 4
-			glDrawElements( GL_TRIANGLES,count/4*6,GL_UNSIGNED_SHORT,Void Ptr( (index/4*6 + (index&3)*MAX_QUAD_INDICES)*2 ) )
-		Default
-			Local j:=0
-			While j<count
-				glDrawArrays( GL_TRIANGLE_FAN,index+j,op.order )
-				j+=op.order
-			Wend
-		End
-
-	End
-	
-	Method Render:Void()
-
-		If Not _next Return
-		
-		Local offset:=0,opid:=0,ops:=_ops.Data
-		Local length:=_ops.Length
-		
-		While offset<_next
-		
-			Local size:=_next-offset,lastop:=length
-			
-			If size>PRIM_VBO_SIZE
-			
-				size=0
-				lastop=opid
-				While lastop<length
-					Local op:=ops[lastop]
-					Local n:=op.count*BYTES_PER_VERTEX
-					If size+n>PRIM_VBO_SIZE Exit
-					size+=n
-					lastop+=1
-				Wend
-				
-				If Not size
-					Local op:=ops[opid]
-					Local count:=op.count
-					While count
-						Local n:=count
-						If n>MAX_VERTICES n=MAX_VERTICES/op.order*op.order
-						Local size:=n*BYTES_PER_VERTEX
-						
-						If VBO_ORPHANING_ENABLED glBufferData( GL_ARRAY_BUFFER,PRIM_VBO_SIZE,Null,VBO_USAGE )
-						glBufferSubData( GL_ARRAY_BUFFER,0,size,_data.Data+offset )
-						
-						Render( op,0,n )
-						
-						offset+=size
-						count-=n
-					Wend
-					opid+=1
-					Continue
-				Endif
-				
-			Endif
-			
-			If VBO_ORPHANING_ENABLED glBufferData( GL_ARRAY_BUFFER,PRIM_VBO_SIZE,Null,VBO_USAGE )
-			glBufferSubData( GL_ARRAY_BUFFER,0,size,_data.Data+offset )
-			
-			Local index:=0
-			While opid<lastop
-				Local op:=ops[opid]
-				Render( op,index,op.count )
-				index+=op.count
-				opid+=1
-			Wend
-			offset+=size
-			
-		Wend
-		
-		glGetError()
-		
-	End
-	
-	Method Reset:Void()
-		_next=0
-		
-		Local data:=_ops.Data
-		For Local i:=0 Until _ops.Length
-			data[i].material=Null
-			freeOps.Push( data[i] )
-		Next
-		_ops.Clear()
-		_op=nullOp
-		
-		_casters.Clear()
-		_casterVerts.Clear()
-	End
-	
-	Method Flush:Void() Virtual
-		Render()
-		Reset()
-	End
-	
-	Protected
-
-	Field _blend:=1
-	Field _alpha:=255.0
-	Field _color:=New Float[]( 1.0,1.0,1.0,1.0 )
-	Field _pmcolor:Int=$ffffffff
-	Field _ix:Float=1,_iy:Float
-	Field _jx:Float,_jy:Float=1
-	Field _tx:Float,_ty:Float
-	Field _matStack:=New Float[64*6]
-	Field _matSp:Int
-	Field _font:Font
-	Field _defaultMaterial:Material
-	
-	Private
-	
-	Field _data:DataBuffer=New DataBuffer( 4096 )
-	Field _next:=0
-	Field _op:=nullOp
-	Field _ops:=New Stack<DrawOp>
-	Field _casters:=New Stack<ShadowCaster>
-	Field _casterVerts:=New FloatStack
-
-	Method BeginPrim:Void( material:Material,order:Int ) Final
-	
-		If Not material material=_defaultMaterial
-		
-		If _next+order*BYTES_PER_VERTEX>_data.Length
-'			Print "Resizing data"
-			Local newsize:=Max( _data.Length+_data.Length/2,_next+order*BYTES_PER_VERTEX )
-			Local data:=New DataBuffer( newsize )
-			_data.CopyTo( data,0,0,_next )
-			_data.Discard()
-			_data=data
-		Endif
-	
-		If material=_op.material And _blend=_op.blend And order=_op.order
-			_op.count+=order
-			Return
-		Endif
-		
-		If freeOps.Length _op=freeOps.Pop() Else _op=New DrawOp
-		
-		_ops.Push( _op )
-		_op.material=material
-		_op.blend=_blend
-		_op.order=order
-		_op.count=order
-	End
-	
-	Method BeginPrims:Void( material:Material,order:Int,count:Int ) Final
-	
-		If Not material material=_defaultMaterial
-		
-		count*=order
-		
-		If _next+count*BYTES_PER_VERTEX>_data.Length
-'			Print "Resizing data"
-			Local newsize:=Max( _data.Length+_data.Length/2,_next+count*BYTES_PER_VERTEX )
-			Local data:=New DataBuffer( newsize )
-			_data.CopyTo( data,0,0,_next )
-			_data.Discard()
-			_data=data
-		Endif
-	
-		If material=_op.material And _blend=_op.blend And order=_op.order
-			_op.count+=count
-			Return
-		Endif
-		
-		If freeOps.Length _op=freeOps.Pop() Else _op=New DrawOp
-		
-		_ops.Push( _op )
-		_op.material=material
-		_op.blend=_blend
-		_op.order=order
-		_op.count=count
-	End
-	
-	Method PrimVert:Void( x0:Float,y0:Float,s0:Float,t0:Float ) Final
-		_data.PokeFloat( _next+0, x0 * _ix + y0 * _jx + _tx )
-		_data.PokeFloat( _next+4, x0 * _iy + y0 * _jy + _ty )
-		_data.PokeFloat( _next+8, s0 )
-		_data.PokeFloat( _next+12,t0 )
-		_data.PokeFloat( _next+16,_ix )
-		_data.PokeFloat( _next+20,_iy )
-		_data.PokeInt  ( _next+24,_pmcolor )
-		_next+=BYTES_PER_VERTEX
-	End
-	
-End
-
-'***** Canvas *****
-
-Class Canvas Extends DrawList
-
-	Const MaxLights:=MAX_LIGHTS
-	
-	Method New( target:Object )
-		Init()
-		SetRenderTarget( target )
-		SetViewport( 0,0,_width,_height )
-		SetProjection2d( 0,_width,0,_height )
-	End
-	
-	Method New( width:Int,height:Int )
-		Init()
-		Resize( width,height )
-		SetViewport( 0,0,_width,_height )
-		SetProjection2d( 0,_width,0,_height )
-	End
-	
-	Method Resize( width:Int,height:Int )
-		_image=Null
-		_texture=Null
-		_width=width
-		_height=height
-		_twidth=_width
-		_theight=_height
-		_dirty=-1
-	End
-
-	Method SetRenderTarget:Void( target:Object )
-
-		FlushPrims()
-		
-		If Cast<Image>( target )
-		
-			_image=Cast<Image>( target )
-			_texture=_image.Material.ColorTexture
-			If Not (_texture.Flags & Texture.RenderTarget) Mojo2Error( "Texture is not a render target texture" )
-			_width=_image.Width
-			_height=_image.Height
-			_twidth=_texture.Width
-			_theight=_texture.Height
-			
-		Else If Cast<Texture>( target )
-		
-			_image=Null
-			_texture=Cast<Texture>( target )
-			If Not (_texture.Flags & Texture.RenderTarget) Mojo2Error( "Texture is not a render target texture" )
-			_width=_texture.Width
-			_height=_texture.Height
-			_twidth=_texture.Width
-			_theight=_texture.Height
-			
-		Else
-		
-			Mojo2Error( "RenderTarget object must an Image, a Texture or Null" )
-			
-		Endif
-		
-		_dirty=-1
-		
-	End
-	
-	Property RenderTarget:Object()
-		If _image Return _image
-		Return _texture
-	End
-	
-	Property Width:Int()
-		Return _width
-	End
-	
-	Property Height:Int()
-		Return _height
-	End
-	
-	Method SetColorMask:Void( r:Bool,g:Bool,b:Bool,a:Bool )
-		FlushPrims()
-		_colorMask[0]=r
-		_colorMask[1]=g
-		_colorMask[2]=b
-		_colorMask[3]=a
-		_dirty|=DIRTY_COLORMASK
-	End
-	
-	Property ColorMask:Bool[]()
-		Return _colorMask
-	End
-	
-	Method SetViewport:Void( x:Int,y:Int,w:Int,h:Int )
-		FlushPrims()
-		_viewport[0]=x
-		_viewport[1]=y
-		_viewport[2]=w
-		_viewport[3]=h
-		_dirty|=DIRTY_VIEWPORT
-	End
-	
-	Property Viewport:Int[]()
-		Return _viewport
-	End
-	
-	Method SetScissor:Void( x:Int,y:Int,w:Int,h:Int )
-		FlushPrims()
-		_scissor[0]=x
-		_scissor[1]=y
-		_scissor[2]=w
-		_scissor[3]=h
-		_dirty|=DIRTY_VIEWPORT
-	End
-	
-	Property Scissor:Int[]()
-		Return _scissor
-	End
-	
-	Method SetProjectionMatrix:Void( projMatrix:Float[] )
-		FlushPrims()
-		If projMatrix
-			Mat4Copy( projMatrix,_projMatrix )
-		Else
-			Mat4Init( _projMatrix )
-		Endif
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method SetProjection2d:Void( left:Float,right:Float,top:Float,bottom:Float,znear:Float=-1,zfar:Float=1 )
-		FlushPrims()
-		Mat4Ortho( left,right,top,bottom,znear,zfar,_projMatrix )
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property ProjectionMatrix:Float[]()
-		Return _projMatrix
-	End
-	
-	Method SetViewMatrix:Void( viewMatrix:Float[] )
-		FlushPrims()
-		If viewMatrix
-			Mat4Copy( viewMatrix,_viewMatrix )
-		Else
-			Mat4Init( _viewMatrix )
-		End
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property ViewMatrix:Float[]()
-		Return _viewMatrix
-	End
-	
-	Method SetModelMatrix:Void( modelMatrix:Float[] )
-		FlushPrims()
-		If modelMatrix
-			Mat4Copy( modelMatrix,_modelMatrix )
-		Else
-			Mat4Init( _modelMatrix )
-		Endif
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property ModelMatrix:Float[]()
-		Return _modelMatrix
-	End
-
-	Method SetAmbientLight:Void( r:Float,g:Float,b:Float,a:Float=1 )
-		FlushPrims()
-		_ambientLight[0]=r
-		_ambientLight[1]=g
-		_ambientLight[2]=b
-		_ambientLight[3]=a
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property AmbientLight:Float[]()
-		Return _ambientLight
-	End
-	
-	Method SetFogColor:Void( r:Float,g:Float,b:Float,a:Float )
-		FlushPrims()
-		_fogColor[0]=r
-		_fogColor[1]=g
-		_fogColor[2]=b
-		_fogColor[3]=a
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property FogColor:Float[]()
-		Return _fogColor
-	End
-	
-	Method SetLightType:Void( index:Int,type:Int )
-		FlushPrims()
-		Local light:=_lights[index]
-		light.type=type
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method GetLightType:Int( index:Int )
-		Return _lights[index].type
-	End
-	
-	Method SetLightColor:Void( index:Int,r:Float,g:Float,b:Float,a:Float=1 )
-		FlushPrims()
-		Local light:=_lights[index]
-		light.color[0]=r
-		light.color[1]=g
-		light.color[2]=b
-		light.color[3]=a
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method GetLightColor:Float[]( index:Int )
-		Return _lights[index].color
-	End
-	
-	Method SetLightPosition:Void( index:Int,x:Float,y:Float,z:Float )
-		FlushPrims()
-		Local light:=_lights[index]
-		light.position[0]=x
-		light.position[1]=y
-		light.position[2]=z
-		light.vector[0]=x
-		light.vector[1]=y
-		light.vector[2]=z
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method GetLightPosition:Float[]( index:Int )
-		Return _lights[index].position
-	End
-	
-	Method SetLightRange:Void( index:Int,range:Float )
-		FlushPrims()
-		Local light:=_lights[index]
-		light.range=range
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method GetLightRange:Float( index:Int )
-		Return _lights[index].range
-	End
-	
-	Method SetShadowMap:Void( image:Image )
-		FlushPrims()
-		_shadowMap=image
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Property ShadowMap:Image()
-		Return _shadowMap
-	End
-	
-	Method SetLineWidth:Void( lineWidth:Float )
-		FlushPrims()
-		_lineWidth=lineWidth
-		_dirty|=DIRTY_LINEWIDTH
-	End
-	
-	Property LineWidth:Float()
-		Return _lineWidth
-	End
-	
-	Method Clear:Void( r:Float=0,g:Float=0,b:Float=0,a:Float=1 )
-		FlushPrims()
-		Validate()
-		If _clsScissor
-			glEnable( GL_SCISSOR_TEST )
-			glScissor( _vpx,_vpy,_vpw,_vph )
-		Endif
-		glClearColor( r,g,b,a )
-		glClear( GL_COLOR_BUFFER_BIT )
-		If _clsScissor glDisable( GL_SCISSOR_TEST )
-	End
-	
-	Method ReadPixels:Void( x:Int,y:Int,width:Int,height:Int,data:DataBuffer,dataOffset:Int=0,dataPitch:Int=0 )
-	
-		FlushPrims()
-		
-		If Not dataPitch Or dataPitch=width*4
-			glReadPixels( x,y,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data.Data+dataOffset )
-		Else
-			For Local iy:=0 Until height
-				glReadPixels( x,y+iy,width,1,GL_RGBA,GL_UNSIGNED_BYTE,data.Data+dataOffset+dataPitch*iy )
-			Next
-		Endif
-
-	End
-
-	Method RenderDrawList:Void( drawbuf:DrawList )
-	
-		Local fast:=_ix=1 And _iy=0 And _jx=0 And _jy=1 And _tx=0 And _ty=0 And _color[0]=1 And _color[1]=1 And _color[2]=1 And _color[3]=1
-		
-		If fast
-			FlushPrims()
-			Validate()
-			drawbuf.Render()
-			Return
-		Endif
-		
-		tmpMat3d[0]=_ix
-		tmpMat3d[1]=_iy
-		tmpMat3d[4]=_jx
-		tmpMat3d[5]=_jy
-		tmpMat3d[12]=_tx
-		tmpMat3d[13]=_ty
-		tmpMat3d[10]=1
-		tmpMat3d[15]=1
-		
-		Mat4Multiply( _modelMatrix,tmpMat3d,tmpMat3d2 )
-		
-		FlushPrims()
-		
-		Local tmp:=_modelMatrix
-		_modelMatrix=tmpMat3d2
-		rs_globalColor[0]=_color[0]*_color[3]
-		rs_globalColor[1]=_color[1]*_color[3]
-		rs_globalColor[2]=_color[2]*_color[3]
-		rs_globalColor[3]=_color[3]
-		_dirty|=DIRTY_SHADER
-		
-		Validate()
-		drawbuf.Render()
-		
-		_modelMatrix=tmp
-		rs_globalColor[0]=1
-		rs_globalColor[1]=1
-		rs_globalColor[2]=1
-		rs_globalColor[3]=1
-		_dirty|=DIRTY_SHADER
-	End
-	
-	Method RenderDrawList:Void( drawList:DrawList,tx:Float,ty:Float,rz:Float=0,sx:Float=1,sy:Float=1 )
-		Super.PushMatrix()
-		Super.TranslateRotateScale( tx,ty,rz,sx,sy )
-		RenderDrawList( drawList )
-		Super.PopMatrix()
-	End
-
-	Method Flush:Void() Override
-		FlushPrims()
-
-		If Not _texture Return
-#rem		
-		
-		If _texture._flags & Texture.Managed
-			Validate()
-
-			glDisable( GL_SCISSOR_TEST )
-			glViewport( 0,0,_twidth,_theight )
-			
-			If _width=_twidth And _height=_theight
-				glReadPixels 0,0,_twidth,_theight,GL_RGBA,GL_UNSIGNED_BYTE,DataBuffer( _texture._data )
-			Else
-				For Local y:=0 Until _height
-					glReadPixels _image._x,_image._y+y,_width,1,GL_RGBA,GL_UNSIGNED_BYTE,DataBuffer( _texture._data ),(_image._y+y) * (_twidth*4) + (_image._x*4)
-				Next
-			Endif
-
-			_dirty|=DIRTY_VIEWPORT
-		Endif
-#end
-
-		_texture.UpdateMipmaps()
-	End
-	
-	Global _tformInvProj:=New Float[16]
-	Global _tformT:=New Float[]( 0.0,0.0,-1.0,1.0 )
-	Global _tformP:=New Float[4]
-	
-	Method TransformCoords:Void( coords_in:Float[],coords_out:Float[],mode:Int=0 )
-	
-		Mat4Inverse( _projMatrix,_tformInvProj )
-
-		Select mode
-		Case 0
-			_tformT[0]=(coords_in[0]-_viewport[0])/_viewport[2]*2-1
-			_tformT[1]=(coords_in[1]-_viewport[1])/_viewport[3]*2-1
-			Mat4Transform( _tformInvProj,_tformT,_tformP )
-			_tformP[0]/=_tformP[3];_tformP[1]/=_tformP[3];_tformP[2]/=_tformP[3];_tformP[3]=1
-			coords_out[0]=_tformP[0]
-			coords_out[1]=_tformP[1]
-			If coords_out.Length>2 coords_out[2]=_tformP[2]
-		Default
-			Mojo2Error( "Invalid TransformCoords mode" )
-		End
-	End
-	
-	Private
-
-	Const DIRTY_RENDERTARGET:=1
-	Const DIRTY_VIEWPORT:=2
-	Const DIRTY_SHADER:=4
-	Const DIRTY_LINEWIDTH:=8
-	Const DIRTY_COLORMASK:=16
-		
-	Field _seq:Int
-	Field _dirty:Int=-1
-	Field _image:Image
-	Field _texture:Texture	
-	Field _width:Int
-	Field _height:Int
-	Field _twidth:Int
-	Field _theight:Int
-	Field _shadowMap:Image
-	Field _colorMask:=New Bool[]( True,True,True,True )
-	Field _viewport:=New Int[]( 0,0,640,480 )
-	Field _scissor:=New Int[]( 0,0,100000,100000 )
-	Field _vpx:Int,_vpy:Int,_vpw:Int,_vph:Int
-	Field _scx:Int,_scy:Int,_scw:Int,_sch:Int
-	Field _clsScissor:Bool
-	Field _projMatrix:=Mat4New()
-	Field _invProjMatrix:=Mat4New()
-	Field _viewMatrix:=Mat4New()
-	Field _modelMatrix:=Mat4New()
-	Field _ambientLight:=New Float[]( 0.0,0.0,0.0,1.0 )
-	Field _fogColor:=New Float[]( 0.0,0.0,0.0,0.0 )
-	Field _lights:=New LightData[4]
-	Field _lineWidth:Float=1
-
-	Global _active:Canvas
-	
-	Method Init:Void()
-		For Local i:=0 Until 4
-			_lights[i]=New LightData
-		Next
-		_dirty=-1
-	End
-
-	Method FlushPrims:Void()
-		If Super.IsEmpty Return
-		Validate()
-		Super.Flush()
-	End
-	
-	Method Validate:Void()
-
-		If _seq<>graphicsSeq
-			_seq=graphicsSeq
-			InitVbos()
-			_dirty=-1
-		Endif
-	
-		If _active=Self
-			If Not _dirty Return
-		Else
-			If _active _active.Flush()
-			_active=Self
-			_dirty=-1
-		Endif
-
-'		_dirty=-1
-		
-		If _dirty & DIRTY_RENDERTARGET
-
-			If _texture
-				glBindFramebuffer( GL_FRAMEBUFFER,_texture.GLFramebuffer )
-			Else
-				glBindFramebuffer( GL_FRAMEBUFFER,defaultFbo )
-			Endif
-		End
-		
-		If _dirty & DIRTY_VIEWPORT
-		
-			_vpx=_viewport[0];_vpy=_viewport[1];_vpw=_viewport[2];_vph=_viewport[3]
-			If _image
-				_vpx+=_image._x
-				_vpy+=_image._y
-			Endif
-			
-			_scx=_scissor[0];_scy=_scissor[1];_scw=_scissor[2];_sch=_scissor[3]
-			
-			If _scx<0 _scx=0 Else If _scx>_vpw _scx=_vpw
-			If _scw<0 _scw=0 Else If _scx+_scw>_vpw _scw=_vpw-_scx
-			
-			If _scy<0 _scy=0 Else If _scy>_vph _scy=_vph
-			If _sch<0 _sch=0 Else If _scy+_sch>_vph _sch=_vph-_scy
-			
-			_scx+=_vpx;_scy+=_vpy
-		
-			If Not _texture
-				_vpy=_theight-_vpy-_vph
-				_scy=_theight-_scy-_sch
-			Endif
-			
-			glViewport( _vpx,_vpy,_vpw,_vph )
-			
-			If _scx<>_vpx Or _scy<>_vpy Or _scw<>_vpw Or _sch<>_vph
-				glEnable( GL_SCISSOR_TEST )
-				glScissor( _scx,_scy,_scw,_sch )
-				_clsScissor=False
-			Else
-				glDisable( GL_SCISSOR_TEST )
-				_clsScissor=(_scx<>0 Or _scy<>0 Or _vpw<>_twidth Or _vph<>_theight)
-			Endif
-			
-		Endif
-		
-		If _dirty & DIRTY_SHADER
-		
-			rs_program=Null
-			
-			If _texture
-				rs_clipPosScale[1]=1
-				Mat4Copy( _projMatrix,rs_projMatrix )
-			Else
-				rs_clipPosScale[1]=-1
-				Mat4Multiply( flipYMatrix,_projMatrix,rs_projMatrix )
-			Endif
-			
-			Mat4Multiply( _viewMatrix,_modelMatrix,rs_modelViewMatrix )
-			Mat4Multiply( rs_projMatrix,rs_modelViewMatrix,rs_modelViewProjMatrix )
-			Vec4Copy( _ambientLight,rs_ambientLight )
-			Vec4Copy( _fogColor,rs_fogColor )
-			
-			rs_numLights=0
-			For Local i:=0 Until MAX_LIGHTS
-
-				Local light:=_lights[i]
-				If Not light.type Continue
-				
-				Mat4Transform( _viewMatrix,light.vector,light.tvector )
-				
-				rs_lightColors[rs_numLights*4+0]=light.color[0]
-				rs_lightColors[rs_numLights*4+1]=light.color[1]
-				rs_lightColors[rs_numLights*4+2]=light.color[2]
-				rs_lightColors[rs_numLights*4+3]=light.color[3]
-				
-				rs_lightVectors[rs_numLights*4+0]=light.tvector[0]
-				rs_lightVectors[rs_numLights*4+1]=light.tvector[1]
-				rs_lightVectors[rs_numLights*4+2]=light.tvector[2]
-				rs_lightVectors[rs_numLights*4+3]=light.range
-
-				rs_numLights+=1
-			Next
-			
-			If _shadowMap
-				rs_shadowTexture=_shadowMap._material._colorTexture
-			Else 
-				rs_shadowTexture=Null
-			Endif
-			
-			rs_blend=-1
-
-		End
-		
-		If _dirty & DIRTY_LINEWIDTH
-			glLineWidth( _lineWidth )
-		Endif
-		
-		If _dirty & DIRTY_COLORMASK
-			glColorMask( _colorMask[0],_colorMask[1],_colorMask[2],_colorMask[3] )
-		End
-		
-		_dirty=0
-	End
-	
-End

+ 0 - 30
modules/mojo2/makefont.bmx

@@ -1,30 +0,0 @@
-
-Strict
-
-Graphics 1024,64
-
-SetImageFont LoadImageFont( "Monoid",13,SMOOTHFONT )
-
-Local w=TextWidth( " " )+2
-Local h=TextHeight( " " )
-
-For Local i=32 Until 128
-	Local c$=Chr(i)
-	Local x=(i-32)*w
-	SetColor 255,255,255
-	DrawText c,x,0
-	DrawText c,x+2,0
-	SetColor 0,0,0
-	DrawRect x+1,0,w-2,h
-	SetColor 255,255,255
-	DrawText c,x+1,0
-Next
-
-Local pixmap:TPixmap=GrabPixmap( 0,0,w*96,h )
-'pixmap=MaskPixmap( pixmap,0,0,0 )
-
-'SavePixmapPNG pixmap,"data/mojo_font.png"
-
-Flip
-
-WaitKey

+ 0 - 116
modules/mojo2/math3d.monkey2

@@ -1,116 +0,0 @@
-
-Namespace mojo2.math3d
-
-Global Mat4Identity:=Mat4New()
-
-Function Vec4Init:Void( x:Float,y:Float,z:Float,w:Float,r:Float[] )
-	r[0]=x;r[1]=y;r[2]=z;r[3]=w
-End
-
-Function Vec4Copy:Void( v:Float[],r:Float[] )
-	r[0]=v[0];r[1]=v[1];r[2]=v[2];r[3]=v[3]
-End
-
-Function Vec4Copy:Void( v:Float[],r:Float[],src:Int,dst:Int )
-	r[0+dst]=v[0+src];r[1+dst]=v[1+src];r[2+dst]=v[2+src];r[3+dst]=v[3+src]
-End
-
-Function Mat4New:Float[]()
-	Local r:=New Float[16]
-	Mat4Init( 1,1,1,1,r )
-	Return r
-End
-
-Function Mat4Init:Void( ix:Float,jy:Float,kz:Float,tw:Float,r:Float[] )
-	r[0]= ix; r[1]=  0; r[2]=  0; r[3]=  0
-	r[4]=  0; r[5]= jy; r[6]=  0; r[7]=  0
-	r[8]=  0; r[9]=  0; r[10]=kz; r[11]= 0
-	r[12]= 0; r[13]= 0; r[14]= 0; r[15]=tw
-End
-
-Function Mat4Init:Void( ix:Float,iy:Float,iz:Float,iw:Float,jx:Float,jy:Float,jz:Float,jw:Float,kx:Float,ky:Float,kz:Float,kw:Float,tx:Float,ty:Float,tz:Float,tw:Float,r:Float[] )
-	r[0]= ix;r[1]= iy;r[2]= iz;r[3]= iw
-	r[4]= jx;r[5]= jy;r[6]= jz;r[7]= jw
-	r[8]= kx;r[9]= ky;r[10]=kz;r[11]=kw
-	r[12]=tx;r[13]=ty;r[14]=tz;r[15]=tw
-End
-
-Function Mat4Init:Void( r:Float[] )
-	Mat4Init( 1,1,1,1,r )
-End
-
-Function Mat4Copy:Void( m:Float[],r:Float[] )
-	r[0]=m[0];r[1]=m[1];r[2]=m[2];r[3]=m[3]
-	r[4]=m[4];r[5]=m[5];r[6]=m[6];r[7]=m[7]
-	r[8]=m[8];r[9]=m[9];r[10]=m[10];r[11]=m[11]
-	r[12]=m[12];r[13]=m[13];r[14]=m[14];r[15]=m[15]
-End
-
-Function Mat4Ortho:Void( left:Float,right:Float,bottom:Float,top:Float,znear:Float,zfar:Float,r:Float[] )
-	Local w:=right-left,h:=top-bottom,d:=zfar-znear
-	Mat4Init( 2.0/w,0,0,0, 0,2.0/h,0,0, 0,0,2.0/d,0, -(right+left)/w,-(top+bottom)/h,-(zfar+znear)/d,1,r )
-End
-
-Function Mat4Frustum:Void( left:Float,right:Float,bottom:Float,top:Float,znear:Float,zfar:Float,r:Float[] )	
-	Local w:=right-left,h:=top-bottom,d:=zfar-znear,znear2:=znear*2
-	Mat4Init( znear2/w,0,0,0, 0,znear2/h,0,0, (right+left)/w,(top+bottom)/h,(zfar+znear)/d,1, 0,0,-(zfar*znear2)/d,0, r )
-End
-
-Function Mat4Transpose:Void( m:Float[],r:Float[] )
-	Mat4Init( m[0],m[4],m[8],m[12], m[1],m[5],m[9],m[13], m[2],m[6],m[10],m[14], m[3],m[7],m[11],m[15],r )
-End
-
-Function Mat4Inverse:Void( m:Float[],r:Float[] )
-	r[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
-	r[4] =-m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
-	r[8] = m[4] * m[9]  * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
-	r[12]=-m[4] * m[9]  * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
-	r[1] =-m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
-	r[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
-	r[9] =-m[0] * m[9]  * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
-	r[13]= m[0] * m[9]  * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
-	r[2] = m[1] * m[6]  * m[15] - m[1] * m[7]  * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7]  - m[13] * m[3] * m[6]
-	r[6] =-m[0] * m[6]  * m[15] + m[0] * m[7]  * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7]  + m[12] * m[3] * m[6]
-	r[10]= m[0] * m[5]  * m[15] - m[0] * m[7]  * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7]  - m[12] * m[3] * m[5]
-	r[14]=-m[0] * m[5]  * m[14] + m[0] * m[6]  * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6]  + m[12] * m[2] * m[5]
-	r[3] =-m[1] * m[6]  * m[11] + m[1] * m[7]  * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9]  * m[2] * m[7]  + m[9]  * m[3] * m[6]
-	r[7] = m[0] * m[6]  * m[11] - m[0] * m[7]  * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8]  * m[2] * m[7]  - m[8]  * m[3] * m[6]
-	r[11]=-m[0] * m[5]  * m[11] + m[0] * m[7]  * m[9]  + m[4] * m[1] * m[11] - m[4] * m[3] * m[9]  - m[8]  * m[1] * m[7]  + m[8]  * m[3] * m[5]
-	r[15]= m[0] * m[5]  * m[10] - m[0] * m[6]  * m[9]  - m[4] * m[1] * m[10] + m[4] * m[2] * m[9]  + m[8]  * m[1] * m[6]  - m[8]  * m[2] * m[5]
-	Local c:=1.0 / (m[0] * r[0] + m[1] * r[4] + m[2] * r[8] + m[3] * r[12])
-	For Local i:=0 Until 16
-		r[i]*=c
-	Next
-End
-
-Function Mat4Multiply:Void( m:Float[],n:Float[],r:Float[] )
-	Mat4Init(
-	m[0]*n[0]  + m[4]*n[1]  + m[8]*n[2]  + m[12]*n[3],  m[1]*n[0]  + m[5]*n[1]  + m[9]*n[2]  + m[13]*n[3],  m[2]*n[0]  + m[6]*n[1]  + m[10]*n[2]  + m[14]*n[3],  m[3]*n[0]  + m[7]*n[1]  + m[11]*n[2]  + m[15]*n[3],
-	m[0]*n[4]  + m[4]*n[5]  + m[8]*n[6]  + m[12]*n[7],  m[1]*n[4]  + m[5]*n[5]  + m[9]*n[6]  + m[13]*n[7],  m[2]*n[4]  + m[6]*n[5]  + m[10]*n[6]  + m[14]*n[7],  m[3]*n[4]  + m[7]*n[5]  + m[11]*n[6]  + m[15]*n[7],
-	m[0]*n[8]  + m[4]*n[9]  + m[8]*n[10] + m[12]*n[11], m[1]*n[8]  + m[5]*n[9]  + m[9]*n[10] + m[13]*n[11], m[2]*n[8]  + m[6]*n[9]  + m[10]*n[10] + m[14]*n[11], m[3]*n[8]  + m[7]*n[9]  + m[11]*n[10] + m[15]*n[11],
-	m[0]*n[12] + m[4]*n[13] + m[8]*n[14] + m[12]*n[15], m[1]*n[12] + m[5]*n[13] + m[9]*n[14] + m[13]*n[15], m[2]*n[12] + m[6]*n[13] + m[10]*n[14] + m[14]*n[15], m[3]*n[12] + m[7]*n[13] + m[11]*n[14] + m[15]*n[15],r )
-End
-
-Function Mat4Transform:Void( m:Float[],v:Float[],r:Float[] )
-	Vec4Init( 
-	m[0]*v[0] + m[4]*v[1] + m[8] *v[2] + m[12]*v[3],
-	m[1]*v[0] + m[5]*v[1] + m[9] *v[2] + m[13]*v[3],
-	m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3],
-	m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3],r )
-End
-
-Function Mat4Project:Void( m:Float[],v:Float[],r:Float[] )
-	Vec4Init( 
-	m[0]*v[0] + m[4]*v[1] + m[8] *v[2] + m[12]*v[3],
-	m[1]*v[0] + m[5]*v[1] + m[9] *v[2] + m[13]*v[3],
-	m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3],
-	m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3],r )
-	r[0]/=r[3];r[1]/=r[3];r[2]/=r[3];r[3]=1
-End
-
-Function Mat4Scale:Void( x:Float,y:Float,z:Float,m:Float[] )
-	m[0]=x;m[1]=0;m[2]=0;m[3]=0
-	m[4]=0;m[5]=y;m[6]=0;m[7]=0
-	m[8]=0;m[9]=0;m[10]=1;m[11]=0
-	m[12]=0;m[13]=0;m[14]=0;m[15]=1
-End

+ 0 - 30
modules/mojo2/mojo2.monkey2

@@ -1,30 +0,0 @@
-
-Namespace mojo2
-
-#Import "<libc>"
-#Import "<gles20>"
-#Import "<std>"
-#Import "<stb-truetype>"
-
-#Import "math3d.monkey2"
-#Import "glutil.monkey2"
-#Import "graphics.monkey2"
-#Import "glslparser.monkey2"
-#Import "renderer.monkey2"
-
-Using libc
-Using gles20
-
-Using std.memory
-Using std.graphics
-Using std.collections
-
-Using stb.truetype
-
-Global DeviceWidth:=640
-Global DeviceHeight:=480
-
-Function Mojo2Error( msg:String )
-	Print( "Mojo2 error:"+msg )
-	exit_( -1 )
-End

+ 0 - 367
modules/mojo2/renderer.monkey2

@@ -1,367 +0,0 @@
-
-Namespace mojo2
-
-Using std
-
-Using mojo2.math3d
-
-Private
-
-Class LayerData
-	Field matrix:=Mat4New()
-	Field invMatrix:=Mat4New()
-	Field drawList:DrawList
-End
-
-Global lvector:=New Float[4]
-Global tvector:=New Float[4]
-
-Public
-
-Interface ILight
-
-	Method LightMatrix:Float[]()
-	Method LightType:Int()
-	Method LightColor:Float[]()
-	Method LightRange:Float()
-	Method LightImage:Image()
-	
-End
-
-Interface ILayer
-
-	Method LayerMatrix:Float[]()
-	Method LayerFogColor:Float[]()
-	Method LayerLightMaskImage:Image()
-	Method EnumLayerLights:Void( lights:Stack<ILight> )
-	Method OnRenderLayer:Void( drawLists:Stack<DrawList> )
-	
-End
-
-Class Renderer
-
-	Method SetClearMode:Void( clearMode:Int )
-		_clearMode=clearMode
-	End
-	
-	Method SetClearColor:Void( clearColor:Float[] )
-		_clearColor=clearColor
-	End
-	
-	Method SetAmbientLight:Void( ambientLight:Float[] )
-		_ambientLight=ambientLight
-	End
-	
-	Method SetCameraMatrix:Void( cameraMatrix:Float[] )
-		_cameraMatrix=cameraMatrix
-	End
-	
-	Property Layers:Stack<ILayer>()
-		Return _layers
-	End
-	
-	Method Render:Void( dcanvas:Canvas )
-	
-		Local canvas:=dcanvas
-		
-		_canvas=canvas
-		
-		_viewport=canvas.Viewport
-		
-		_projectionMatrix=canvas.ProjectionMatrix
-	
-		Local vwidth:=_viewport[2],vheight:=_viewport[3]
-		
-		If vwidth<=0 Or vheight<=0 Return
-		
-'		Print vwidth+","+vheight
-		
-		Mat4Inverse( _projectionMatrix,_invProjMatrix )
-
-		lvector[0]=-1;lvector[1]=-1;lvector[2]=-1;lvector[3]=1
-		Mat4Project( _invProjMatrix,lvector,tvector )
-		Local px0:=tvector[0],py0:=tvector[1]
-
-		lvector[0]=1;lvector[1]=1;lvector[2]=-1;lvector[3]=1
-		Mat4Project( _invProjMatrix,lvector,tvector )
-		Local px1:=tvector[0],py1:=tvector[1]
-		
-		Local twidth:=Int( px1-px0 ),theight:=Int( py1-py0 )
-		
-		If _timage=Null Or _timage.Width<>twidth Or _timage.Height<>theight
-			If _timage _timage.Discard()
-			_timage=New Image( twidth,theight,0,0 )
-		End
-		
-		If _timage2=Null Or _timage2.Width<>twidth Or _timage2.Height<>theight
-			If _timage2 _timage2.Discard()
-			_timage2=New Image( twidth,theight,0,0 )
-		End
-		
-		If Not _tcanvas
-			_tcanvas=New Canvas( _timage )
-		Endif
-		
-		_tcanvas.SetProjectionMatrix( _projectionMatrix )
-		_tcanvas.SetViewport( 0,0,twidth,theight )
-		_tcanvas.SetScissor( 0,0,twidth,theight )
-
-		Mat4Inverse( _cameraMatrix,_viewMatrix )
-		
-		Local invProj:=False
-		
-		'Clear!
-		Select _clearMode
-		Case 1
-			_canvas.Clear( _clearColor[0],_clearColor[1],_clearColor[2],_clearColor[3] )
-		End
-		
-		For Local layerId:=0 Until _layers.Length
-		
-			Local layer:=_layers.Get( layerId )
-			Local fog:=layer.LayerFogColor()
-			
-			Local layerMatrix:=layer.LayerMatrix()
-			Mat4Inverse( layerMatrix,_invLayerMatrix )
-			
-			_drawLists.Clear()
-			layer.OnRenderLayer( _drawLists )
-			
-			Local lights:=New Stack<ILight>
-			layer.EnumLayerLights( lights )
-			
-			If Not lights.Length
-			
-				For Local i:=0 Until 4
-					canvas.SetLightType( i,0 )
-				Next
-			
-				canvas.SetShadowMap( Null )'_timage )
-				canvas.SetViewMatrix( _viewMatrix )
-				canvas.SetModelMatrix( layerMatrix )
-				canvas.SetAmbientLight( _ambientLight[0],_ambientLight[1],_ambientLight[2],1 )
-				canvas.SetFogColor( fog[0],fog[1],fog[2],fog[3] )
-				
-				canvas.SetColor( 1,1,1,1 )
-				For Local i:=0 Until _drawLists.Length
-					canvas.RenderDrawList( _drawLists.Get( i ) )
-				End
-				canvas.Flush()
-				
-				Continue
-				
-			Endif
-			
-			Local light0:=0
-			
-			Repeat
-			
-				Local numLights:=Min(lights.Length-light0,4)
-				
-				'Shadows
-				'		
-				canvas=_tcanvas
-				canvas.SetRenderTarget( _timage )
-				canvas.SetShadowMap( Null )
-				canvas.SetViewMatrix( _viewMatrix )
-				canvas.SetModelMatrix( layerMatrix )
-				canvas.SetAmbientLight( 0,0,0,0 )
-				canvas.SetFogColor( 0,0,0,0 )
-				
-				canvas.Clear( 1,1,1,1 )
-				canvas.SetBlendMode( 0 )
-				canvas.SetColor( 0,0,0,0 )
-
-				canvas.SetDefaultMaterial( Shader.ShadowShader().DefaultMaterial )
-				
-				For Local i:=0 Until numLights
-				
-					Local light:=lights.Get(light0+i)
-					
-					Local matrix:=light.LightMatrix()
-					
-					Vec4Copy( matrix,lvector,12,0 )
-					Mat4Transform( _invLayerMatrix,lvector,tvector )
-					Local lightx:=tvector[0],lighty:=tvector[1]
-					
-					canvas.SetColorMask( i=0,i=1,i=2,i=3 )
-					
-					Local image:=light.LightImage()
-					If image
-						canvas.Clear( 0,0,0,0 )
-						canvas.PushMatrix()
-						canvas.SetMatrix( matrix[0],matrix[1],matrix[4],matrix[5],lightx,lighty )
-						canvas.DrawImage( image )
-						canvas.PopMatrix()
-					Endif
-		
-					For Local j:=0 Until _drawLists.Length
-						canvas.DrawShadows( lightx,lighty,_drawLists.Get( j ) )
-					Next
-				
-				Next
-				
-				canvas.SetDefaultMaterial( Shader.FastShader().DefaultMaterial )
-				canvas.SetColorMask( True,True,True,True )
-				canvas.Flush()
-				
-				#rem
-				'LightMask
-				'
-				Local lightMask:=layer.LayerLightMaskImage()
-				If lightMask
-				
-					If Not invProj
-						Mat4Inverse( _projectionMatrix,_invProjMatrix )
-						Mat4Project( _invProjMatrix,[-1.0,-1.0,-1.0,1.0],_ptl )
-						Mat4Project( _invProjMatrix,[ 1.0, 1.0,-1.0,1.0],_pbr )
-					Endif
-					
-					Local fwidth:=(_pbr[0]-_ptl[0])
-					Local fheight:=(_pbr[1]-_ptl[1])
-					
-					If _projectionMatrix[15]=0
-						Local scz:=(layerMatrix[14]-_cameraMatrix[14])/_ptl[2]
-						fwidth*=scz
-						fheight*=scz
-					Endif
-				
-					canvas.SetProjection2d( 0,fwidth,0,fheight )
-					canvas.SetViewMatrix( Mat4Identity )
-					canvas.SetModelMatrix( Mat4Identity )
-					
-					'test...
-					'canvas.SetBlendMode 0
-					'canvas.SetColor 1,1,1,1
-					'canvas.DrawRect 0,0,fwidth,fheight
-					
-					canvas.SetBlendMode( 4 )
-					
-					Local w:Float=lightMask.Width
-					Local h:Float=lightMask.Height
-					Local x:=-w
-					While x<fwidth+w
-						Local y:=-h
-						While y<fheight+h
-							canvas.DrawImage( lightMask,x,y )
-							y+=h
-						Wend
-						x+=w
-					Wend
-					
-					canvas.Flush()
-					
-					canvas.SetProjectionMatrix( _projectionMatrix )
-					
-				Endif
-				#end
-				
-				'Enable lights
-				'
-				canvas=_canvas
-				If light0 canvas=_tcanvas
-				
-				For Local i:=0 Until numLights
-				
-					Local light:=lights.Get(light0+i)
-					
-					Local c:=light.LightColor()
-					Local m:=light.LightMatrix()
-					
-					canvas.SetLightType( i,1 )
-					canvas.SetLightColor( i,c[0],c[1],c[2],c[3] )
-					canvas.SetLightPosition( i,m[12],m[13],m[14] )
-					canvas.SetLightRange( i,light.LightRange() )
-				Next
-				For Local i:=numLights Until 4
-					canvas.SetLightType( i,0 )
-				Next
-				
-				If light0=0	'first pass?
-				
-					'render lights+ambient to output
-					'
-					canvas=_canvas
-					canvas.SetShadowMap( _timage )
-					canvas.SetViewMatrix( _viewMatrix )
-					canvas.SetModelMatrix( layerMatrix )
-					canvas.SetAmbientLight( _ambientLight[0],_ambientLight[1],_ambientLight[2],1 )
-					canvas.SetFogColor( fog[0],fog[1],fog[2],fog[3] )
-					
-					canvas.SetColor( 1,1,1,1 )
-					For Local i:=0 Until _drawLists.Length
-						canvas.RenderDrawList( _drawLists.Get( i ) )
-					End
-					
-					canvas.Flush()
-					
-				Else
-				
-					'render lights only
-					'
-					canvas=_tcanvas
-					canvas.SetRenderTarget( _timage2 )
-					canvas.SetShadowMap( _timage )
-					canvas.SetViewMatrix( _viewMatrix )
-					canvas.SetModelMatrix( layerMatrix )
-					canvas.SetAmbientLight( 0,0,0,0 )
-					canvas.SetFogColor( 0,0,0,fog[3] )
-					
-					canvas.Clear( 0,0,0,1 )
-					canvas.SetColor( 1,1,1,1 )
-					For Local i:=0 Until _drawLists.Length
-						canvas.RenderDrawList( _drawLists.Get( i ) )
-					End
-					canvas.Flush()
-					
-					'add light to output
-					'
-					canvas=_canvas
-					canvas.SetShadowMap( Null )
-					canvas.SetViewMatrix( Mat4Identity )
-					canvas.SetModelMatrix( Mat4Identity )
-					canvas.SetAmbientLight( 0,0,0,1 )
-					canvas.SetFogColor( 0,0,0,0 )
-					
-					canvas.SetBlendMode( 2 )
-					canvas.SetColor( 1,1,1,1 )
-					canvas.DrawImage( _timage2 )
-'					canvas.DrawRect( 0,0,twidth,theight,_timage2,0,0,twidth,theight )
-
-					canvas.Flush()
-					
-				Endif
-				
-				light0+=4
-			
-			Until light0>=lights.Length
-			
-		Next
-	End
-	
-	Protected
-	
-	Field _canvas:Canvas
-	Field _tcanvas:Canvas
-	
-	Field _timage:Image		'tmp lighting texture
-	Field _timage2:Image	'another tmp lighting image for >4 lights
-
-	Field _viewport:=New Int[]( 0,0,640,480 )
-	Field _clearMode:Int=1
-	Field _clearColor:=New Float[]( 0.0,0.0,0.0,1.0 )
-	Field _ambientLight:=New Float[]( 1.0,1.0,1.0,1.0 )
-	Field _projectionMatrix:=Mat4New()
-	Field _cameraMatrix:=Mat4New()
-	Field _viewMatrix:=Mat4New()
-	
-	Field _layers:=New Stack<ILayer>
-	
-	Field _invLayerMatrix:=New Float[16]
-	Field _drawLists:=New Stack<DrawList>
-	
-	Field _invProjMatrix:=New Float[16]
-	Field _ptl:=New Float[4]
-	Field _pbr:=New Float[4]
-		
-End

+ 0 - 0
modules/mojo2/renderstate.monkey2