Browse Source

Improved sorting of transparent surfaces attached to the same model by using bounds center for sorting instead of entity origin.

Mark Sibly 6 years ago
parent
commit
6b56b3e7ab

+ 32 - 5
modules/mojo3d/render/renderqueue.monkey2

@@ -3,6 +3,24 @@ Namespace mojo3d
 
 Internal
 
+'TODO: cache this stuff
+Class RenderInstance
+	Field instance:Entity
+	Field uniforms:UniformBlock
+	Field bones:Mat4f
+End
+
+'TODO: cache this too
+Class RenderGeometry
+	Field material:Material
+	Field vbuffer:VertexBuffer
+	Field ibuffer:IndexBuffer
+	Field bounds:Boxf
+	Field order:Int
+	Field count:Int
+	Field first:Int
+End
+
 Struct SpriteOp
 	Field sprite:Sprite
 
@@ -16,6 +34,7 @@ Class RenderOp
 	Field bones:Mat4f[]			'should be in instance
 	Field vbuffer:VertexBuffer
 	Field ibuffer:IndexBuffer
+	Field bounds:Boxf
 	Field order:Int
 	Field count:Int
 	Field first:Int
@@ -104,7 +123,11 @@ Class RenderQueue
 		Else
 			stack=_transparentOps
 			op.shader=op.material.GetRenderShader()
-			op.distance=op.instance ? op.instance.Position.Distance( _eyePos ) Else _eyeLen
+			If op.instance
+				op.distance=(op.instance.Matrix * op.bounds.Center).Distance( _eyePos )
+			Else
+				op.distance=op.bounds.Center.Distance( _eyePos )
+			Endif
 		Endif
 		
 		stack.Add( op )
@@ -115,48 +138,52 @@ Class RenderQueue
 		_spriteOps.Add( op )
 	End
 	
-	Method AddRenderOp( material:Material,uniforms:UniformBlock,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
+	Method AddRenderOp( material:Material,uniforms:UniformBlock,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,bounds:Boxf,order:Int,count:Int,first:Int )
 		Local op:=New RenderOp
 		op.material=material
 		op.uniforms=uniforms
 		op.instance=instance
 		op.vbuffer=vbuffer
 		op.ibuffer=ibuffer
+		op.bounds=bounds
 		op.order=order
 		op.count=count
 		op.first=first
 		AddRenderOp( op )
 	End
 	
-	Method AddRenderOp( material:Material,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
+	Method AddRenderOp( material:Material,instance:Entity,vbuffer:VertexBuffer,ibuffer:IndexBuffer,bounds:Boxf,order:Int,count:Int,first:Int )
 		Local op:=New RenderOp
 		op.material=material
 		op.instance=instance
 		op.vbuffer=vbuffer
 		op.ibuffer=ibuffer
+		op.bounds=bounds
 		op.order=order
 		op.count=count
 		op.first=first
 		AddRenderOp( op )
 	End
 	
-	Method AddRenderOp( material:Material,bones:Mat4f[],vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
+	Method AddRenderOp( material:Material,bones:Mat4f[],vbuffer:VertexBuffer,ibuffer:IndexBuffer,bounds:Boxf,order:Int,count:Int,first:Int )
 		Local op:=New RenderOp
 		op.material=material
 		op.bones=bones
 		op.vbuffer=vbuffer
 		op.ibuffer=ibuffer
+		op.bounds=bounds
 		op.order=order
 		op.count=count
 		op.first=first
 		AddRenderOp( op )
 	End
 	
-	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,order:Int,count:Int,first:Int )
+	Method AddRenderOp( material:Material,vbuffer:VertexBuffer,ibuffer:IndexBuffer,bounds:Boxf,order:Int,count:Int,first:Int )
 		Local op:=New RenderOp
 		op.material=material
 		op.vbuffer=vbuffer
 		op.ibuffer=ibuffer
+		op.bounds=bounds
 		op.order=order
 		op.count=count
 		op.first=first

+ 4 - 2
modules/mojo3d/scene/entities/model.monkey2

@@ -227,13 +227,15 @@ Class Model Extends Renderable
 		For Local i:=0 Until _mesh.NumMaterials
 
 			Local ibuffer:=_mesh.GetIndexBuffer( i )
+			
+			Local bounds:=_mesh.GetIndexBufferBounds( i )
 
 			Local material:=i<_materials.Length And _materials[i] ? _materials[i] Else _material
 			
 			If _bones
-				rq.AddRenderOp( material,_boneMatrices,vbuffer,ibuffer,3,ibuffer.Length/3,0 )
+				rq.AddRenderOp( material,_boneMatrices,vbuffer,ibuffer,bounds,3,ibuffer.Length/3,0 )
 			Else
-				rq.AddRenderOp( material,Self,vbuffer,ibuffer,3,ibuffer.Length/3,0 )
+				rq.AddRenderOp( material,Self,vbuffer,ibuffer,bounds,3,ibuffer.Length/3,0 )
 			Endif
 			
 		Next

+ 1 - 1
modules/mojo3d/scene/entities/particlebuffer.monkey2

@@ -154,7 +154,7 @@ Class ParticleBuffer
 
 		Endif
 		
-		rq.AddRenderOp( material,_uniforms,instance,_vbuffer,Null,1,_length,0 )
+		rq.AddRenderOp( material,_uniforms,instance,_vbuffer,Null,Boxf.FullBounds,1,_length,0 )
 	End		
 	
 	Private

+ 27 - 2
modules/mojo3d/scene/mesh.monkey2

@@ -590,6 +590,30 @@ Class Mesh Extends Resource
 		Return material.ibuffer
 	End
 	
+	Method GetIndexBufferBounds:Boxf( materialid:Int )
+		
+		Local material:=_materials[materialid]
+		
+		If material.dirty & Dirty.Bounds
+			
+			Local bounds:=Bounds.EmptyBounds
+			
+			Local vertices:=_vertices.Data.Data
+			
+			For Local i:=Eachin material.indices
+				
+				bounds|=vertices[i].position
+			Next
+			
+			material.bounds=bounds
+			
+			material.dirty&=~Dirty.Bounds
+		Endif
+		
+		Return material.bounds
+	End
+		
+	
 	Private
 	
 	Enum Dirty
@@ -600,8 +624,9 @@ Class Mesh Extends Resource
 	
 	class MaterialID
 		Field indices:=New Stack<UInt>
-		Field dirty:Dirty=Dirty.IndexBuffer
+		Field dirty:Dirty=Dirty.IndexBuffer|Dirty.Bounds
 		Field ibuffer:IndexBuffer
+		Field bounds:Boxf
 	End
 	
 	Const IndexPitch:=4
@@ -628,7 +653,7 @@ Class Mesh Extends Resource
 		InvalidateVertices( 0,_vertices.Length )
 	End
 	
-	Method GetMaterial:MaterialID( materialid:Int,dirty:Dirty=Dirty.IndexBuffer )
+	Method GetMaterial:MaterialID( materialid:Int,dirty:Dirty=Dirty.IndexBuffer|Dirty.Bounds )
 		
 		DebugAssert( materialid>=0 And materialid<=_materials.Length,"Materialid out of range" )