Code archives/3D Graphics - Misc/LoadMaskedSprite

This code has been declared by its author to be Public Domain code.

Download source code

LoadMaskedSprite by BlitzSupport2002
Since 3D sprites and textures can only use 0, 0, 0 (black) as their mask colour, you can't easily use black within them. These two functions allow you to load a sprite or texture with whatever mask colour you choose, so that you can now give your sprites BIG THICK BLACK OUTLINES, which is what we all want, right? Right? Hello...?

Seems to work in both 16- and 32-bit here, but let me know if it fails for you...

UPDATE: It did fail on some cards' 16-bit modes. This version should now work on those too...

UPDATE AGAIN: Added LoadMaskedAnimTexture, for multiple frames...
; -----------------------------------------------------------------------------
; LoadMaskedSprite () and LoadMaskedTexture ()...
; -----------------------------------------------------------------------------

; [THANKS: Skully, for the mind-boggling bit-shift thing!]

; Sprites and textures can only use a mask of 0, 0, 0, which means that you can't
; easily have sprites (or textures) with black in them -- ouch!

; These functions let you load a sprite or texture using whatever mask colour
; suits you, meaning you can now have nice black outlines on your cartoony
; sprites... :D

; LoadMaskedSprite is the same as LoadMaskedTexture, but returns a sprite
; automatically for convenience...

Graphics3D 640, 480
AppTitle "LoadMaskedSprite"

cam = CreateCamera ()
CameraClsColor cam, 64, 128, 180
CameraRange cam, 0.1, 100
PositionEntity cam, 0, 2, -5

plane = CreatePlane ()
EntityColor plane, 128, 180, 128

; -----------------------------------------------------------------------------
; Example usage: just include the LoadMaskedSprite function in your code, and
; call it like this (the 255, 0, 255 isn't actually needed in this example, as
; that's the default, but I've left it in so you can alter it to suit an image
; of your own)...
; -----------------------------------------------------------------------------
	sheep = LoadMaskedSprite ("sheep256.png", 255, 0, 255)
; -----------------------------------------------------------------------------

PositionEntity sheep, 0, 2, 0

Repeat
	MoveEntity sheep, ((-KeyDown (203)) Or (KeyDown (205))) / 10.0, ((-KeyDown (208)) Or (KeyDown (200))) / 10.0, ((-KeyDown (44)) Or (KeyDown (30))) / 10.0
	RenderWorld
	Text 20, 20, "Cursors plus A and Z..."
	Flip
Until KeyHit (1)
End

; -----------------------------------------------------------------------------
; LoadMaskedSprite (image$, r, g, b, flags)
; -----------------------------------------------------------------------------

; -----------------------------------------------------------------------------
; REQUIRED PARAMETERS:
; -----------------------------------------------------------------------------
; image$  = image file to be used for sprite
; -----------------------------------------------------------------------------

; -----------------------------------------------------------------------------
; OPTIONAL PARAMETERS:
; -----------------------------------------------------------------------------
; r, g, b = background colour to mask out (defaults to 255, 0, 255)
; flags   = defaults to 1 + 2 + 8 + 16 + 32 (best not to touch these!)
; -----------------------------------------------------------------------------

; -----------------------------------------------------------------------------
; EXAMPLE
; -----------------------------------------------------------------------------
; LoadMaskedSprite ("ship.bmp", 0, 255, 0)
; ... would use a green background mask...
; -----------------------------------------------------------------------------

Function LoadMaskedSprite (f$, r = 255, g = 0, b = 255, flags = 1 + 2 + 8 + 16 + 32)

	temp = CreateTexture (1, 1, flags)
	WritePixel 0, 0, ((r Shl 16) + (g Shl 8) + b) And $00FFFFFF, TextureBuffer (temp)
	trgb = ReadPixel (0, 0, TextureBuffer (temp))
	r = trgb Shr 16 And %11111111
	g = trgb Shr 8 And %11111111
	b = trgb And %11111111
	FreeTexture temp

	texture = LoadTexture (f$, flags)						; Load texture
	tBuffer = GraphicsBuffer ()								; Store current buffer
		
	SetBuffer TextureBuffer (texture)						; Use texture's buffer
	LockBuffer GraphicsBuffer ()							; Lock it for 'fast' pixel access
	
	; Read each pixel of texture...
	
	For x = 0 To TextureWidth (texture) - 1
		For y = 0 To TextureHeight (texture) - 1

			rgb = ReadPixelFast (x, y) And $00FFFFFF		; Read pixel, strip alpha value			
			If rgb = ((r Shl 16) + (g Shl 8) + b)			; If pixel = rgb mask...
				WritePixelFast x, y, $00000000				; ... make transparent, else...
			Else											; Not rgb mask pixel, so...
				WritePixelFast x, y, rgb Or $FF000000		; ... make 'solid'
			EndIf

		Next
	Next

	UnlockBuffer GraphicsBuffer ()							; Unlock texture buffer

	sprite = CreateSprite ()								; Create blank sprite
	EntityTexture sprite, texture							; Apply masked texture
	
	SetBuffer tBuffer										; Reset graphics buffer as at start
	Return sprite											; Return masked sprite
	
End Function

; -----------------------------------------------------------------------------
; LoadMaskedTexture () -- usage as per LoadMaskedSprite () -- see above...
; -----------------------------------------------------------------------------

Function LoadMaskedTexture (f$, r = 255, g = 0, b = 255, flags = 1 + 2 + 8 + 16 + 32)

	texture = LoadTexture (f$, flags)						; Load texture
	tBuffer = GraphicsBuffer ()								; Store current buffer
		
	SetBuffer TextureBuffer (texture)						; Use texture's buffer
	LockBuffer GraphicsBuffer ()							; Lock it for 'fast' pixel access
	
	; Read each pixel of texture...
	
	For x = 0 To TextureWidth (texture) - 1
		For y = 0 To TextureHeight (texture) - 1

			rgb = ReadPixelFast (x, y) And $00FFFFFF		; Read pixel, strip alpha value
			If rgb = ((r Shl 16) + (g Shl 8) + b)			; If pixel = rgb mask...
				WritePixelFast x, y, $00000000				; ... make transparent, else...
			Else											; Not rgb mask pixel, so...
				WritePixelFast x, y, rgb Or $FF000000		; ... make 'solid'
			EndIf

		Next
	Next

	UnlockBuffer GraphicsBuffer ()							; Unlock texture buffer

	SetBuffer tBuffer										; Reset graphics buffer as at start
	Return texture											; Return masked texture
	
End Function


Function LoadMaskedAnimTexture (f$, width, height, frames, r = 255, g = 0, b = 255, startframe = 0, flags = 1 + 2 + 8 + 16 + 32)

	; Get correct RGB value for 16-bit modes by writing to,
	; and reading from, a temporary texture...
	
	temp = CreateTexture (1, 1, flags)
	WritePixel 0, 0, ((r Shl 16) + (g Shl 8) + b) And $00FFFFFF, TextureBuffer (temp)
	trgb = ReadPixel (0, 0, TextureBuffer (temp))
	r = trgb Shr 16 And %11111111
	g = trgb Shr 8 And %11111111
	b = trgb And %11111111
	FreeTexture temp

	; Load the animated texture...
	
	texture = LoadAnimTexture (f$, flags, width, height, startframe, frames)
	
	If texture
	
		tBuffer = GraphicsBuffer ()									; Store current graphics buffer
	
		For loop = 0 To frames - 1									; Do each frame in turn
		
			SetBuffer TextureBuffer (texture, loop)					; Use texture frame's buffer
			LockBuffer GraphicsBuffer ()							; Lock it for 'fast' pixel access
			
			; Read each pixel of texture frame...
			
			For x = 0 To width - 1
				For y = 0 To height - 1
		
					rgb = ReadPixelFast (x, y) And $00FFFFFF		; Read pixel, strip alpha value			
					If rgb = ((r Shl 16) + (g Shl 8) + b)			; If pixel = rgb mask...
						WritePixelFast x, y, $00000000				; ... make transparent, else...
					Else											; Not rgb mask pixel, so...
						WritePixelFast x, y, rgb Or $FF000000		; ... make 'solid'
					EndIf
		
				Next
			Next
		
			UnlockBuffer GraphicsBuffer ()							; Unlock texture buffer
	
		Next
			
		SetBuffer tBuffer											; Restore graphics buffer
		Return texture												; Hand back the AnimTexture...
	
	EndIf
	
End Function

; EXAMPLE: Loading a 10-frame animation sequence. (This one consists
; of the numbers 0-9, with a frame size of 64 x 64 and
; an RGB mask of 0, 0, 0.)

; tex = LoadMaskedAnimTexture (f$, 64, 64, 10, 0, 0, 0)

Comments

None.

Code Archives Forum