SetUV for OpenGL ?

BlitzMax Forums/BlitzMax Programming/SetUV for OpenGL ?

I've looked around the forum to find a way of scrolling a basic square (2d) texture.

i.e. draw a quad in max2D, scroll the texture in a constant direction.


I found SetUV for directX but do we have a counterpart for openGL ?

I haven't done any OpenGL in ages, but I think the UV coordinates are supplied with the command glTexCoord2f, something like this :

glTexCoord2f(0.0f, 1.0f)

It goes right before your call to glVertex3f to draw the vertex.

I want to still use drawimage (max2D), so the scrolling textures can be placed in front and behind other drawimage images.


If thats possible of course.

This should contain all you need...
'Why scrolling a non ^2 image may give unexpected results

Strict

SetGraphicsDriver GLMax2DDriver()
'SetGraphicsDriver BufferedD3D7Max2DDriver()

Graphics 800, 600, 0'32, -1

Local image:TImage = LoadImage(getenv_("BMXPATH") + "\samples\digesteroids\graphics\digestive.png")
If image = Null Then RuntimeError "Couldn't load image"
 
Local tw# = Pow2Size(image.width), th# = Pow2Size(image.height)
Local scalex# = (tw# - image.width) / image.width
Local scaley# = (th# - image.height) / image.height
Local scrollx#, scrolly#, showtex

SetBlend ALPHABLEND

SetTextureRepeat(image, True)

Repeat	
	If KeyDown(KEY_LEFT) Then scrollx# :+ 0.01
	If KeyDown(KEY_RIGHT) Then scrollx# :- 0.01
	If KeyDown(KEY_UP) Then scrolly# :+ 0.01
	If KeyDown(KEY_DOWN) Then scrolly# :- 0.01
	
	If KeyHit(KEY_SPACE) Then showtex = 1 - showtex
	
	Cls
	
	If showtex
		SetAlpha 0.33
		SetColor 0, 0, 100
		DrawRect 12, 36, tw#, th#
			
		SetColor 255, 255, 255
		SetUV(image, 1 + scrollx#, scrolly#, 1 + scalex# + scrollx#, 1 + scrolly#)
		SetScale scalex#, 1
		DrawImage image, 12 + image.width, 36
		
		SetUV(image, 1 + scrollx#, 1 + scrolly#, 1 + scalex# + scrollx#, 1 + scaley# + scrolly#)
		SetScale scalex#, scaley#
		DrawImage image, 12 + image.width, 36 + image.height
		
		SetUV(image, scrollx#, 1 + scrolly#, 1 + scrollx#, 1 + scaley# + scrolly#)
		SetScale 1, scaley#
		DrawImage image, 12, 36 + image.height
	EndIf
	
	SetAlpha 1
	SetScale 1, 1
	SetColor 0, 0, 100
	DrawRect 12, 36, image.width, image.height
	
	SetColor 255, 255, 255
	SetUV(image, scrollx#, scrolly#, 1 + scrollx#, 1 + scrolly#)
	DrawImage image, 12, 36
	
	DrawText "Show Texture = " + showtex, 12, 12
	DrawText "Hit SPACE to toggle texture, CURSOR keys to scroll image", 200, 576
	
	Flip 1
Until KeyHit(KEY_ESCAPE)

End

Function SetTextureRepeat(image:TImage, rep=True)' Under DX, *ALL* images drawn will repeat
'	Assert (image.width = Pow2Size(image.width)) And (image.height = Pow2Size(image.height)),..
'					"Image width and height must be a power of two"
	Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
	
	If rep
?Win32 
		If D3D7Driver
			'DX
			D3D7Driver.device.SetTextureStageState 0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP
		Else
?
			'GL		
			glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT
?Win32
		EndIf
?
	Else
?Win32
		If D3D7Driver
			'DX
			D3D7Driver.device.SetTextureStageState 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP
		Else
?
			'GL
			glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE
			glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE
?Win32
		EndIf
?
	EndIf
End Function

Function SetUV(image:TImage, u0!, v0!, u1!, v1!, frame=0)
	Local twr! = Double(image.width) / Pow2Size(image.width)
	Local thr! = Double(image.height) / Pow2Size(image.height)
	
	u0! = twr! * u0!
	v0! = thr! * v0! 
	u1! = twr! * u1!
	v1! = thr! * v1!
	
?Win32			
	If TGLMax2DDriver(_max2dDriver)
?
		'GL
		Local GLImageFrame:TGLImageFrame = TGLImageFrame(image.Frame(frame))

		GLImageFrame.u0# = u0!
		GLImageFrame.v0# = v0!
		GLImageFrame.u1# = u1!
		GLImageFrame.v1# = v1!
?Win32
	Else
		'DX
		TD3D7ImageFrame(image.Frame(frame)).SetUV(u0!, v0!, u1!, v1!)
	EndIf
?
End Function

Function Pow2Size(n)
	Local t = 1
	
	While t < n
		t :* 2
	Wend
	
	Return t
End Function


Thats what I was after, many thanks

Does anyone have a version of this that will work with non ^2 images ?

I have a small banner that I want to scroll , but its 78 pixels high :S

Are you just scrolling horizontally with no vertical wrapping?

This seems to work fine, its the code posted by Yan but cut down to only have the openGL part. And with the example title image, which is much wider than its heigh, it seems to work just fine on my computer.

SuperStrict

SetGraphicsDriver GLMax2DDriver()

Graphics 800, 600, 0

Local image:TImage = LoadImage(getenv_("BMXPATH") + "\samples\digesteroids\graphics\title.png")
If image = Null Then RuntimeError "Couldn't load image"

Local scrollx:Float, scrolly:Float

 
SetBlend ALPHABLEND

SetTextureRepeat(image)

Repeat	
	If KeyDown(KEY_LEFT) Then scrollx :+ 0.01
	If KeyDown(KEY_RIGHT) Then scrollx :- 0.01
	If KeyDown(KEY_UP) Then scrolly :+ 0.01
	If KeyDown(KEY_DOWN) Then scrolly :- 0.01
	
	Cls
	
	SetAlpha 1
	SetScale 1, 1
	SetColor 0, 0, 100
	DrawRect 12, 36, image.width, image.height
	
	SetColor 255, 255, 255
	SetUV(image, scrollx, scrolly, 1 + scrollx, 1 + scrolly)
	DrawImage image, 12, 36
	
	DrawText "CURSOR keys to scroll image", 200, 576
	
	Flip 1
Until KeyHit(KEY_ESCAPE)

End

Function SetTextureRepeat(image:TImage)
	glBindTexture GL_TEXTURE_2D, TGLImageFrame(image.Frame(0)).name
	glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT
	glTexParameteri GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT
End Function

Function SetUV(image:TImage, u0:Float, v0:Float, u1:Float, v1:Float, frame:Int=0)
	Local GLImageFrame:TGLImageFrame = TGLImageFrame(image.Frame(frame))
	GLImageFrame.u0 = u0
	GLImageFrame.v0 = v0
	GLImageFrame.u1 = u1
	GLImageFrame.v1 = v1
End Function


I just want to scroll the Y.

> Zawran - that doesn't wrap the none ^ 2 texture - it leaves a border around the outside of the picture when it wraps

Scale the original image (pixmap) up to the nearest ^2 vertically, then scale the image's Y axis down by the relevant amount when you draw it.

78 -> 128 = Y * (78 / 128) = SetScale 1, 0.6094

hmm, there are no border on the outside here, but it might be that I do not know exactly what you are refereing to. Sorry I couldn't help then.

How big is the border? 1 pixel wide?

Scaling works a treat - Many thanks