Dot 3?

Blitz3D Forums/Blitz3D Beginners Area/Dot 3?

killertomato(Posted 2007) [#1]
I know this is a dumb question but what exactly is the dot 3 texture blend mode? I assume it has to do with bumpmapping, but all it seems to do is make the model appear black and white.


puki(Posted 2007) [#2]
Are you also using a normal map (ie a bump map)?

For this mode you need more than one texture - the normal map and the actual texture.

EDIT:
Make sure your Blitz3D is up-to-date.


puki(Posted 2007) [#3]
I've not tried the following, but take a look anyway:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1145


I always found this one effective:
Type Dot3Light
	Field ent
	Field mul#
	Field typ
End Type

Graphics3D 800,600,32,2

cube=CreateCube()
ScaleEntity cube,5,.1,5
PositionEntity cube,0,-1,0
EntityColor cube,255,0,0

decl=LoadTexture( "tex.png",1+8)
bump=LoadTexture( "norm.png",1+8)
MeshEntity=LoadMesh("Floor16.x")

;MeshEntity=CreateSphere(16)
;ScaleEntity Meshentity,.7,.7,.7
;ScaleTexture decl,.1,.1
;ScaleTexture bump,.1,.1

PositionEntity MeshEntity,0,0,1

EntityFX MeshEntity,1+2
TextureBlend bump,4
EntityTexture MeshEntity,bump,0,0
EntityTexture MeshEntity,decl,0,1
Global piv=CreatePivot()

pivvy=CreatePivot()
light = Dot3_CreateLight(2,piv,1.0,1)
lighticon = CreateSphere(8,light)
EntityFX lighticon,1
ScaleEntity lighticon,0.01,0.01,0.01
Dot3_LightRange light,10

camera=CreateCamera()
CameraClsColor camera,100,120,130
PositionEntity camera,0,.2,-1.0

EntityParent camera,piv,1
EntityParent MeshEntity,piv,1

CameraRange camera,0.1,100

AmbientLight 100,100,100

declon = True
bumpon = True
doAnim=1
wire=1

While Not KeyHit(1)
	For d3l.dot3light = Each dot3light
		PositionEntity d3l\ent,Float((MouseX()-400))/200,-Float((MouseY()-300))/200,0,0
	Next
	
	If KeyHit(17)
		wire=Not wire
		WireFrame wire
	End If
	
	If KeyHit(57) doAnim=Not doAnim
	If KeyHit(2)
		If declon
			TextureBlend decl,0
		Else
			TextureBlend decl,2
		End If
		declon = Not declon
	End If
	If KeyHit(3)
		If bumpon
			TextureBlend bump,0
			EntityFX MeshEntity,0
		Else
			TextureBlend bump,4
			EntityFX MeshEntity,1+2
		End If
		bumpon = Not bumpon
	End If

	If KeyDown(4) TurnEntity MeshEntity,0,-1,0
	If KeyDown(5) TurnEntity MeshEntity,0,1,0
		
	If KeyDown(200) TurnEntity piv, 1,0,0
	If KeyDown(208) TurnEntity piv,-1,0,0
	
	If KeyDown(205) TurnEntity piv,0,-5,0
	If KeyDown(203) TurnEntity piv,0, 5,0
	
	If KeyDown(30) MoveEntity camera,0,0,0.05
	If KeyDown(44) MoveEntity camera,0,0,-0.05
	
	processtime=MilliSecs()
	If bumpon
		UpdateBumpNormals(MeshEntity,light,1)
	End If
	processtime=MilliSecs() - processtime
	
	UpdateWorld
	RenderWorld
	declstr$="OFF"
	If declon declstr$="ON "
	
	bumpstr$="OFF"
	If bumpon bumpstr$="ON "
		
	Text 10,20,"Process Time: "+processtime+"ms"
	Text GraphicsWidth()/2,0,"1 - Toggle Texture: "+declstr$+"   2 - Toggle Bumpmap: "+bumpstr$,True,False
	Text GraphicsWidth()/2,14,"A & Z to zoom in/out",True
	Text GraphicsWidth()/2,28,"3,4 Spins Sphere localy, cursors turns entire world except Cube ground",True
	
	Flip
Wend

Function UpdateBumpNormals(mesh,light,lighttype=0)
	EP=GetParent(mesh)
	n_surf = CountSurfaces(mesh)
	For s = 1 To n_surf
		surf = GetSurface(mesh,s)
		n_vert = CountVertices(surf)-1
		For v = 0 To n_vert
			red2# = 0
			grn2# = 0
			blu2# = 0
			For d3l.Dot3Light = Each Dot3Light
				lx#=EntityX(d3l\ent,True)
				ly#=EntityY(d3l\ent,True)
				lz#=EntityZ(d3l\ent,True)
	
				If d3l\typ = 1 ; Directional light
					TFormVector 0,0,1,d3l\ent,0
					nx# = TFormedX()
					ny# = TFormedY()
					nz# = TFormedZ()
					TFormNormal VertexNX(surf,v),VertexNY(surf,v),VertexNZ(surf,v),mesh,0
					red# = TFormedX()
					grn# = TFormedY()
					blu# = TFormedZ()
					
					
				ElseIf d3l\typ = 2 ; Point light		
					; Vertex Normal in World coordinates
					TFormNormal VertexNX(surf,v),VertexNY(surf,v),VertexNZ(surf,v),mesh,0
					Vnx# = TFormedX()
					Vny# = TFormedY()
					Vnz# = TFormedZ()
					
					; Vertex > Light Vector in World coordinates
					TFormPoint VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v),mesh,0
					Lvx# = lx - TFormedX()
					Lvy# = ly - TFormedY()
					Lvz# = lz - TFormedZ()

					
					; Normalize Vertex > Light Vector
					d# = Sqr(Lvx*Lvx + Lvy*Lvy + Lvz*Lvz)
					Lvx	=	Lvx / d
					Lvy = Lvy / d
					Lvz = Lvz / d
				End If

				; Theta Angle between Vertex Normal & Vertex>Light Normal
				dot# = (Lvx*Vnx + Lvy*Vny + Lvz*Vnz)

				; Clamp Colors to 0
				If dot<0.0 Then dot# = 0
				
				; If the Mesh had a Parent, Convert Light Vector into that Parents Local coordinates
				; unsure if this'll work with multiple hierarchy
				If EP
					TFormNormal Lvx,Lvy,Lvz,0,EP
					Lvx# = TFormedX()
					Lvy# = TFormedY()
					Lvz# = TFormedZ()
				End If
				
				red# = ( (1.0+(  Lvx * dot)) * 127) * d3l\mul
				grn# = ( (1.0+(  Lvy * dot)) * 127) * d3l\mul
				blu# = ( (1.0+( -Lvz * dot)) * 127) * d3l\mul
				
				red2# = red2+red
				grn2# = grn2+grn
				blu2# = blu2+blu
			Next
			VertexColor surf,v,red2,grn2,blu2
		Next
	Next
End Function



puki(Posted 2007) [#4]
Sub-division variant:
Type Dot3Light
	Field ent
	Field mul#
	Field typ
End Type

Graphics3D 800,600,32,2

cube=CreateCube()
ScaleEntity cube,5,.1,5
PositionEntity cube,0,-2,0
EntityColor cube,255,0,0

decl=LoadTexture( "tex.png",1+8)
bump=LoadTexture( "norm.png",1+8)
MeshEntity=LoadMesh("Floor.x")
MeshEntity2=LoadMesh("Floor4.x")
MeshEntity3=LoadMesh("Floor16.x")

PositionEntity MeshEntity,-4,0,4
PositionEntity MeshEntity2,0,0,4
PositionEntity MeshEntity3,4,0,4

EntityFX MeshEntity,1+2
TextureBlend bump,4
EntityTexture MeshEntity,bump,0,0
EntityTexture MeshEntity,decl,0,1

EntityFX MeshEntity2,1+2
;TextureBlend bump,4
EntityTexture MeshEntity2,bump,0,0
EntityTexture MeshEntity2,decl,0,1

EntityFX MeshEntity3,1+2
;TextureBlend bump,4
EntityTexture MeshEntity3,bump,0,0
EntityTexture MeshEntity3,decl,0,1


Global piv=CreatePivot()


pivvy=CreatePivot()
light = Dot3_CreateLight(2,piv,1.4,0)
lighticon = CreateSphere(8,light)
EntityFX lighticon,1
ScaleEntity lighticon,0.1,0.1,0.1
Dot3_LightRange light,10

camera=CreateCamera()
CameraClsColor camera,100,120,130
PositionEntity camera,0,.2,-1.0


EntityParent camera,piv,1
EntityParent MeshEntity,piv,1


CameraRange camera,0.1,100


declon = True
bumpon = True
doAnim=1
wire=0

While Not KeyHit(1)
	For d3l.dot3light = Each dot3light
		PositionEntity d3l\ent,EntityX(camera) + Float((MouseX()-400))/100,EntityY(camera) -Float((MouseY()-300))/100,3,1
	Next
	
	If KeyHit(17)
		wire=Not wire
		WireFrame wire
	End If
	
	If KeyHit(57) doAnim=Not doAnim
	If KeyHit(2)
		If declon
			TextureBlend decl,0
		Else
			TextureBlend decl,2
		End If
		declon = Not declon
	End If
	If KeyHit(3)
		If bumpon
			TextureBlend bump,0
			EntityFX MeshEntity,0
		Else
			TextureBlend bump,4
			EntityFX MeshEntity,1+2
		End If
		bumpon = Not bumpon
	End If

	If KeyDown(205) MoveEntity camera, .1,0,0
	If KeyDown(203) MoveEntity camera,-.1,0,0
	

	If KeyDown(200) MoveEntity camera,0,0,0.05
	If KeyDown(208) MoveEntity camera,0,0,-0.05
	
	processtime=MilliSecs()
	If bumpon
		UpdateBumpNormals(MeshEntity,light,1)
		UpdateBumpNormals(MeshEntity2,light,1)
		UpdateBumpNormals(MeshEntity3,light,1)
	End If
	processtime=MilliSecs() - processtime
	
	UpdateWorld
	RenderWorld
	declstr$="OFF"
	If declon declstr$="ON "
	
	bumpstr$="OFF"
	If bumpon bumpstr$="ON "
		
	Text 10,20,"Process Time: "+processtime+"ms"
	Text GraphicsWidth()/2,0,"1 - Toggle Texture: "+declstr$+"   2 - Toggle Bumpmap: "+bumpstr$,True,False

	Text GraphicsWidth()/2,30,"Cursors to move & zoom, 'w' toggle wireframe",True
	
	Flip
Wend

Function UpdateBumpNormals(mesh,light,lighttype=0)
	EP=GetParent(mesh)
	If EP	EntityParent mesh,0,1

	n_surf = CountSurfaces(mesh)
	For s = 1 To n_surf
		surf = GetSurface(mesh,s)
		n_vert = CountVertices(surf)-1
		For v = 0 To n_vert
			red2# = 0
			grn2# = 0
			blu2# = 0
			For d3l.Dot3Light = Each Dot3Light
				lx#=EntityX(d3l\ent,True)
				ly#=EntityY(d3l\ent,True)
				lz#=EntityZ(d3l\ent,True)
	
				If d3l\typ = 1 ; Directional light
					TFormVector 0,0,1,d3l\ent,0
					nx# = TFormedX()
					ny# = TFormedY()
					nz# = TFormedZ()
					TFormNormal VertexNX(surf,v),VertexNY(surf,v),VertexNZ(surf,v),mesh,0
					red# = TFormedX()
					grn# = TFormedY()
					blu# = TFormedZ()
					
					
				ElseIf d3l\typ = 2 ; Point light		
					; Vertex Normal in World coordinates
					TFormNormal VertexNX(surf,v),VertexNY(surf,v),VertexNZ(surf,v),mesh,0
					Vnx# = TFormedX()
					Vny# = TFormedY()
					Vnz# = TFormedZ()
					
					; Vertex > Light Vector in World coordinates
					TFormPoint VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v),mesh,0
					Lvx# = lx - TFormedX()
					Lvy# = ly - TFormedY()
					Lvz# = lz - TFormedZ()

					; Normalize Vertex > Light Vector
					d# = Sqr(Lvx*Lvx + Lvy*Lvy + Lvz*Lvz)
					Lvx	=	Lvx / d
					Lvy = Lvy / d
					Lvz = Lvz / d
				End If

				; Theta Angle between Vertex Normal & Vertex>Light Normal
				dot# = (Lvx*Vnx + Lvy*Vny + Lvz*Vnz)

				; Clamp Colors to 0
				If dot<0.0 Then dot# = 0
				
				; If the Mesh had a Parent, Convert Light Vector into that Parents Local coordinates
				; unsure if this'll work with multiple hierarchy
				If EP
					TFormNormal Lvx,Lvy,Lvz,0,EP
					Lvx# = TFormedX()
					Lvy# = TFormedY()
					Lvz# = TFormedZ()
				End If
				
				red# = ( (1.0+( Lvx * dot)) * 127) * d3l\mul
				grn# = ( (1.0+( Lvy * dot)) * 127) * d3l\mul
				blu# = ( (1.0+( -Lvz * dot)) * 127) * d3l\mul
				
				red2# = red2+red
				grn2# = grn2+grn
				blu2# = blu2+blu
			Next
			VertexColor surf,v,red2,grn2,blu2
		Next
	Next
	If EP EntityParent mesh,EP,1
End Function





Function Dot3_CreateLight(typ=1,parent=0,mul#=1.0,real=True)
	
	d3l.Dot3Light = New Dot3Light
	
	If real
		d3l\ent = CreateLight(typ,parent)
		LightRange d3l\ent,50
	Else
		d3l\ent = CreatePivot(parent)
	End If

	d3l\typ = typ
	d3l\mul = mul
	
	Return d3l\ent

End Function

Function Dot3_LightRange(ent,range#)
	For d3l.dot3light = Each dot3light
		If d3l\ent = ent
			If Lower$(EntityClass(d3l\ent))="light"
				LightRange d3l\ent,range
				Return
			End If
		End If
	Next
	
End Function

Function Dot3_LightIntensity(ent,intens#)
	For d3l.dot3light = Each dot3light
		If d3l\ent = ent
			d3l\mul = intens
			If Lower$(EntityClass(d3l\ent))="light"
				LightColor d3l\ent,d3l\mul*255.0,d3l\mul*255.0,d3l\mul*255.0
			End If			
			Return
		End If
	Next
End Function


End



killertomato(Posted 2007) [#5]
Wow, thanks


Pinete(Posted 2007) [#6]
what's or does the "subdivision variant" code??
what's de difference?
:)

regards!


sswift(Posted 2007) [#7]
The Dot3 mode in Blitz is useless because to properly utilize it you need access to pixel shaders, which Blitz does not have. There are a few demos that show DOT3 in action, but don't be fooled, these either "cheat" and use directional lights and a static model, or the lighting displayed isn't actually correct. You could light a normal mapped car with something like a directional light, but that's about it. Can't do animated characters with bones, and can't use omni lights. Making normal maps is a pain anyway, and totally unnneccessary for indie games.


JA2(Posted 2007) [#8]
I thought somebody was developing a game in Blitz 3D using normal mapped characters? I can't remember who tho, maybe Puki knows?

I don't see why it's unnecessary for indie games to use normal mapped models. Normals maps, if done correctly, can add a lot of detail to a low poly model.

Normals maps are easy to make if you know how. You just need two versions of the same model, or you can make the normal map by hand.


jfk EO-11110(Posted 2007) [#9]
They look nice in doom 2, but I'm pretty sure you won't get them in blitz. The Blitz dot3 is using some kind of Non-world space light mode (or so) wich makes it kind of static. Many people tried to hack this limit away, with questionable success. Even the most bril minds around here were not able to get an acceptable solution, AFAIR.

One solution for example was dealing with VertexColors to realtime-mod the missing world dimension of the bumpmaping.

I'd suggest to use the search function in the forum and you'll find lots of topics about dot3 and bumpmapping.


sswift(Posted 2007) [#10]
"I don't see why it's unnecessary for indie games to use normal mapped models. Normals maps, if done correctly, can add a lot of detail to a low poly model."


It's unnecessary because what an indie game looks like doesn't matter as much as you might think. It hardly matters at all in fact. Casual gamers have no taste when it comes to a game's graphics. (Within reason.) It's really only important that the game be fun.

Also, you can make a game look great without normal maps. 99% of what makes one game look great and another look crap is the skill of the artist, not the number of polygons he has to work with. Unless you have an artist that can really utilize all that extra detail, it will just go to waste. There are plenty of XBOX 360 games which look worse than games produced for the GameCube.


JA2(Posted 2007) [#11]
Personally I don't think it's unnecessary to add normal maps or any other visual effect for indie games. If it's suitable for the game you're working on then why not?

The thread was started by somebody wanting to know more about normal/bump/dot3 mapping and I don't think it's very constructive to tell them it's "totally unnneccessary for indie games".


Mustang(Posted 2007) [#12]

The Blitz dot3 is using some kind of Non-world space light mode (or so) wich makes it kind of static.



--> Object space... if you move vertices like you do with animated characters you need Tangent space normal maps. Tangent space ones are perfectly good for static stuff too but are harder to light (more math etc) obviously. If only Mark would have gone the extra mile... *sigh*

http://en.wikipedia.org/wiki/Normal_mapping