single surface - not quite pixel perfect?

Blitz3D Forums/Blitz3D Programming/single surface - not quite pixel perfect?

Fry Crayola(Posted 2004) [#1]
In my single surface system, I can't seem to get it pixel perfect. To all intents and purposes it is the correct size but the left hand side of a quad tends to fade to black.

When two identical quads are placed side by side, this results in a visible gap between them, which I don't want.

At the minute I've used a get-around by making the quads slightly longer on the horizontal - one pixel each side. This removes the fade but means a slightly elongated texture on the quad. For the most part this is invisible, yet the perfectionist in me isn't happy.

Is there anything I can do?

Function E2_drawSprite(this.sprite, xpos#, ypos#, xscale#, yscale#, angle#, alpha#)
	
	;get x and y distances from centre
	angle = 360-angle
	xdist# = (((this\width))/2.0)*xscale
	ydist# = (((this\height))/2.0)*yscale
	
	;rotate each vertex in turn
	x1# = (xdist*-1) * Cos(angle) - ydist * Sin(angle) - 1
	y1# = (xdist*-1) * Sin(angle) + ydist * Cos(angle)
	
	x2# = xdist * Cos(angle) - ydist * Sin(angle) + 1
	y2# = xdist * Sin(angle) + ydist * Cos(angle)
	
	x3# = xdist * Cos(angle) + ydist * Sin(angle) + 1
	y3# = xdist * Sin(angle) - ydist * Cos(angle)
	
	x4# = (xdist*-1) * Cos(angle) + ydist * Sin(angle) - 1
	y4# = (xdist*-1) * Sin(angle) - ydist * Cos(angle)

	;create the four vertices as part of the quad.
	v1 = AddVertex(mainSurface, xpos+x1, ypos+y1, 0, this\u1, this\v1)
	v2 = AddVertex(mainSurface, xpos+x2, ypos+y2, 0, this\u2, this\v1)
	v3 = AddVertex(mainSurface, xpos+x3, ypos+y3, 0, this\u2, this\v2)
	v4 = AddVertex(mainSurface, xpos+x4, ypos+y4, 0, this\u1, this\v2)
	
	VertexColor mainSurface, v1, 255, 255, 255, alpha
	VertexColor mainSurface, v2, 255, 255, 255, alpha
	VertexColor mainSurface, v3, 255, 255, 255, alpha
	VertexColor mainSurface, v4, 255, 255, 255, alpha
	
	;add two triangles
	t1 = AddTriangle(mainSurface, v1, v2, v4)
	t2 = AddTriangle(mainSurface, v2, v3, v4)

End Function



Fry Crayola(Posted 2004) [#2]
I think I may have solved my own problem. Well, worked out the problem anyhow, I'm not sure about the solution.

It appears that the edges of the quad are being affected by the colours of the texture outside the u,v coordinates. By making sure the direct edges are the same colour as the area of the texture to be drawn, I eliminate this problem.

It seems no amount of repositioning u,v coordinates is helping, though I might be doing it wrong. I've tried calculating the coordinates and offsetting them 0.5 from their original position before getting u,v values, but this doesn't have any affect.


Difference(Posted 2004) [#3]
I think the solution is here: http://www.blitzbasic.com/codearcs/codearcs.php?code=456


Fry Crayola(Posted 2004) [#4]
That's concerned with sprites, though, while I'm going for a system more akin to Anthony Flack's system for Cletus.

Can the principles apply across the board?


Gabriel(Posted 2004) [#5]
It appears that the edges of the quad are being affected by the colours of the texture outside the u,v coordinates. By making sure the direct edges are the same colour as the area of the texture to be drawn, I eliminate this problem.

It seems no amount of repositioning u,v coordinates is helping, though I might be doing it wrong. I've tried calculating the coordinates and offsetting them 0.5 from their original position before getting u,v values, but this doesn't have any affect.



Yeah, textures will do that, because we can't turn bloody texture filtering off ( sorry.. I've hit this wall a few times ) . Normally, setting the ClampX and ClampY texture flags when loading the texture will suffice.


poopla(Posted 2004) [#6]
Lemme post my pixel perfect single surface code in a few minutes. Expect a few bugs(I stopped working on it a while ago... I think there was a bug with creating pivots for every surface/spritesource.)

Anywho, you'll need to look it over for errors.


poopla(Posted 2004) [#7]
Have fun, and do what ya can to fix any bugs/memory leaks I might have left in when I dropped working on this. I've been a bit too busy with work to keep it up!

(On first glance, 'SpriteSource_Create()' is the erea I neglected to finalize.)

Global Cam
	
Type SpriteSource
	
	Field Mesh%, Surf%
	Field Texture%
	Field Frames%, FramesPerRow%
	Field Animated%
	
	Field RefImage%
	
End Type

Function SpriteSource_Create%(Camera%, File$, FramesPerRow% = -1)

	viewwidth=GraphicsWidth()
	viewheight=GraphicsHeight()
	
	S.SpriteSource = New SpriteSource
	
	magic=CreatePivot(Camera) 
	NameEntity(magic,"pixiespace")
	aspect#=Float(viewheight)/viewwidth
	PositionEntity magic,-1,aspect,1 
	scale#=2.0/viewwidth 
	ScaleEntity magic,scale,-scale,-scale 
	magic=CreatePivot(magic)
	
	S\Mesh = CreateMesh(Magic)
	EntityFX(S\Mesh, 2)
	S\Surf = CreateSurface(S\Mesh)
	PositionEntity S\Mesh, -.5, .5, 0
	
	S\Texture = LoadTexture(File, 4)
	S\RefImage = LoadImage(File)
	
	If S\Texture <> 0 Then
		EntityTexture S\Mesh, S\Texture
		If FramesPerRow <> -1 And FramesPerRow > 0 Then
			S\FramesPerRow = FramesPerRow
			S\Animated = True	
		EndIf
	EndIf
	
	Return Handle(S)
	
End Function

Function SpriteSource_SetAnimation%(Source%, FramesPerRow%)

	S.SpriteSource = Object.SpriteSource(Source)
	S\FramesPerRow = FramesPerRow
	S\Animated = True

End Function

Function SpriteSource_CacheSprites(Source%, W%, H%, Count%)
	
	S.SpriteSource = Object.SpriteSource(Source)
	If S = Null Then Return 
		
	For CS = 1 To Count
		
		Sprite_Create%(Source, W, H)
		
	Next
	
End Function

Function SpriteSource_AvailSprite(Source%)

	For S.Sprite = Each Sprite
		If S\Source = Object.SpriteSource(Source) And S\Draw = False Then
			Return Handle(S)
		EndIf
	Next

End Function

Type Sprite

	Field Source.SpriteSource
	Field VertRef%
	Field TriRef%
	
	Field Draw%
	
	Field DrawX%, DrawY%
	Field Width%, Height%
	
	Field HandleX%, HandleY%
	
	Field RotAngle%, OffsetAngle%
	
	Field CurFrameColumn#, CurFrame#, AnimTime%, AnimTimeMax%
	Field Animated%
	
	Field Active%
	
End Type

Function Sprite_Create%(Source%, W%, H%)
	
	S.Sprite = New Sprite
	S\Source = Object.SpriteSource(Source)
	
	If W = 0 Or H = 0 Then
		S\Width = ImageWidth(S\Source\RefImage)
		S\Height = ImageWidth(S\Source\RefImage)
	Else
		S\Width = W
		S\Height = H	
	EndIf
	
	Sprite_CreateQuad(S)

	Return Handle(S)
	
End Function

Function Sprite_Animate(Sprite%, Time%)
	
	S.Sprite = Object.Sprite(Sprite)
	If S\Source\Animated = True
		S\AnimTimeMax = Time%
		S\AnimTime = Time
		S\Animated = True
	EndIf
	
End Function

Function Sprite_Draw(Sprite, X, Y)
	
	S.Sprite = Object.Sprite(Sprite)
	
	S\Draw = True
	S\DrawX = X
	S\DrawY = Y
	
End Function

Function Sprite_Update(Delta# = 1.0)
	
	For S.Sprite = Each Sprite
		If S\Draw = True Then
			If S\Source\Animated = True
				S\AnimTime = S\AnimTime - 1
				If S\AnimTime = 0 Then
					S\AnimTime = S\AnimTimeMax
					
					S\CurFrame = S\CurFrame + 1
					If S\CurFrame = S\Source\FramesPerRow
						S\CurFrame = 0
						
						S\CurFrameColumn = S\CurFrameColumn + 1
						If S\CurFrameColumn = S\Source\FramesPerRow
							S\CurFrameColumn = 0
						EndIf
					EndIf
	
					Dims# = .5;1.0 / (S\Source\FramesPerRow)					
					SU# = Dims * S\CurFrame
					SV# = Dims * S\CurFrameColumn
								
					VertexTexCoords(S\Source\Surf, S\VertRef, SU, SV)
					VertexTexCoords(S\Source\Surf, S\VertRef+1, SU+Dims, SV)
					VertexTexCoords(S\Source\Surf, S\VertRef+2, SU, SV+Dims)
					VertexTexCoords(S\Source\Surf, S\VertRef+3, SU+Dims, SV+Dims)
				EndIf
			EndIf			
			
			S\Draw = False
		EndIf
	Next
	
End Function

Function Sprite_RenderAll()

	For S.Sprite = Each Sprite
		If S\Draw = True Then

			;Top or "rear" vertices
			Mag# = Sqr(S\Width*S\Width + S\Height*S\Height)*.5 

			CosVal# = Cos(S\RotAngle+S\OffsetAngle)
			SinVal# = Sin(S\RotAngle+S\OffsetAngle)
			
			Atan2Val# = ATan2(S\Height, S\Width)
			
			VX# = (Cos((S\RotAngle+S\OffsetAngle) - Atan2Val)*Mag) + S\DrawX
			VY# = (Sin((S\RotAngle+S\OffsetAngle) - Atan2Val)*Mag) + S\DrawY			
			VertexCoords(S\Source\Surf, S\VertRef+1, VX , VY, 0)

			VX# = (Cos((S\RotAngle+S\OffsetAngle) + Atan2Val)*Mag) + S\DrawX
			VY# = (Sin((S\RotAngle+S\OffsetAngle) + Atan2Val)*Mag) + S\DrawY			
			VertexCoords(S\Source\Surf, S\VertRef+3, VX , VY, 0)


			VX# = (Cos((S\RotAngle+S\OffsetAngle+180) - Atan2Val)*Mag) + S\DrawX
			VY# = (Sin((S\RotAngle+S\OffsetAngle+180) - Atan2Val)*Mag) + S\DrawY			
			VertexCoords(S\Source\Surf, S\VertRef+2, VX , VY, 0)


			VX# = (Cos((S\RotAngle+S\OffsetAngle+180) + Atan2Val)*Mag) + S\DrawX
			VY# = (Sin((S\RotAngle+S\OffsetAngle+180) + Atan2Val)*Mag) + S\DrawY			
			VertexCoords(S\Source\Surf, S\VertRef, VX , VY, 0)
		
		ElseIf S\Draw = False Then
			VX# = -100
			
			VertexCoords(S\Source\Surf, S\VertRef+1, VX , VY, 0)	
			VertexCoords(S\Source\Surf, S\VertRef+3, VX , VY, 0)	
			VertexCoords(S\Source\Surf, S\VertRef+2, VX , VY, 0)	
			VertexCoords(S\Source\Surf, S\VertRef, VX , VY, 0)			 
								
		EndIf
	Next

End Function

Function Sprite_CreateQuad(S.Sprite)

	V1 = AddVertex(S\Source\Surf, 0, 0, 0, 0, 0)
	V2 = AddVertex(S\Source\Surf, 0, 0, 0, 1, 0)
	V3 = AddVertex(S\Source\Surf, 0, 0, 0, 0, 1)
	V4 = AddVertex(S\Source\Surf, 0, 0, 0, 1, 1)
	
;	VertexColor S\Source\Surf, V1, 255, 0, 0
;	VertexColor S\Source\Surf, V2, 0, 255, 0
;	VertexColor S\Source\Surf, V3, 0, 0, 255
;	VertexColor S\Source\Surf, V4, 255, 255, 255	
	S\VertRef = V1
	
	T1 = AddTriangle(S\Source\Surf, V1, V2, V3)
	AddTriangle(S\Source\Surf, V3, V2, V4)
	
End Function



BlitzSupport(Posted 2004) [#8]

because we can't turn bloody texture filtering off


ClearTextureFilters somwhere after Graphics3D should do it.


Gabriel(Posted 2004) [#9]
ClearTextureFilters somwhere after Graphics3D should do it.


No, that just turns mipmapping off. Linear ( is it linear or bilinear with Blitz? ) filtering remains on.


Stevie G(Posted 2004) [#10]
Look for the pixies code in the archives - might have been by Skidracer - but it works perfectly - even on textures which are not ^2 etc..


Fry Crayola(Posted 2004) [#11]
I've looked at that pixies code a thousand times and can't work it out.

At the minute my stopgap is working fine, there's no degradation on performace. I'm sure I'll solve it eventually but unless you zoom in (which I won't be doing much) there's nothing to worry about.


poopla(Posted 2004) [#12]
I'm sure it's linear filtering with blitz.