PDA

View Full Version : TBGL_EntityGetMatrix...TBGL_PushMatrix...?



ReneMiner
04-05-2013, 14:38
Currently I create some Terrain-Editor. Now the following: I want to have a water-layer that shall be translucent - great would be, if I could scroll the texture on 8 layers (so all directions) and add up the colors of all 8 layers, so there's a typical water-effect. But that's just the second step...

Currently I'm still here: Even if I make it just one blue colored rectangle that shall be translucent I would need to draw it seperate but not as an Entity since TBGL_EntitySetColor does not accept Alpha-Values...
If I just draw the rectangle within TBGL_BeginPoly/TBGL_EndPoly the rotation of the camera is missing so the rectangle is not in the right place. Also if I change something about the FOV-angle, the non-Entities, Fonts, Points etc. are not at the right place. So I know I can receive the camera-matrix easy using TBGL_EntityGetMatrix I guess. But how can I push this received values in, so it can just render the waterlayer where it's supposed to appear?

And- I would prefer using some Entity as a waterlayer anyway - even if is just two rectangles- I could just set TBGL_EntitySetUse for example to change the state once instead of checking for the state every frame...

Petr Schreiber
04-05-2013, 15:40
Hi Rene,

water surface can be easily implemented via custom entity. TBGL_EntitySetColor does not support alpha? That is not an obstacle, you can implement your own way. How?

To give you something for a start, here is an example of how I would do the water level entity myself.

Step #1: Start from template
In thinAIR:

click File/New
choose TBGL template folder
choose actor_object.taguit
click on Use
it will generate this code:



'
' Custom <object> actor entity
' , 05-04-2013
'

' -----
Type <object>


End Type

'[!] Constructor and destructor
Function <object>_Create( sScene As Long ) As Long

Dim eEntity As Long = TBGL_EntityGetFreeID(sScene)
Dim data As <object>


TBGL_EntityCreateFuncSlot(sScene, eEntity, 0, "<object>_Render")
TBGL_EntitySetUserData(sScene, eEntity, data)

Return eEntity

End Function

Function <object>_Destroy(sScene As Long, eEntity As Long)
' -- Destructor is not that needed as TBGL has garbage collection...
TBGL_EntityDestroy(sScene, eEntity)
End Function

'[!] Rendering
Function <object>_Render()
Dim element As TBGL_TENTITYIDENTIFIER At TBGL_CallingEntity
Dim data As <object> At TBGL_EntityGetUserDataPointer(element.scene, element.entity)


End Function

'[!] Methods
Function <object>_Method(sScene As Long, eEntity As Long)
Dim data As <object> At TBGL_EntityGetUserDataPointer(sScene, eEntity)

End Function

Step #2: Customize the template
Press Ctrl-R for Find and Replace dialog:

To Find field, enter "<object>"
To Replace with field enter "WaterPlane"
Click Replace All, it is safe in this case :)


Now all the functions for manipulating water plane will be prefixed WaterPlane, cool!

Step #3: Define the data for your entity
You seem to know what you need from the entity, so let's edit this part:


Type WaterPlane


End Type


You want - water texture and ability to specify R, G, B and Alpha channel + plane dimensions. So let's plug it in:

Type WaterPlane
textureID As Long

R As Byte
G As Byte
B As Byte
A As Byte

planeWidth As Single
planeHeight As Single
End Type


Step #4: Adjust the initialization routine
You need to specify the defaults for the data above, right? The best place for it is the WaterPlane_Create, it looks by default like this:


Function WaterPlane_Create( sScene As Long ) As Long

Dim eEntity As Long = TBGL_EntityGetFreeID(sScene)
Dim data As WaterPlane


TBGL_EntityCreateFuncSlot(sScene, eEntity, 0, "WaterPlane_Render")
TBGL_EntitySetUserData(sScene, eEntity, data)

Return eEntity

End Function


After customization, it can look like this:


'[!] Constructor and destructor
Function WaterPlane_Create( sScene As Long, waterTexture As Long ) As Long ' -- Texture for water added as parameter

Dim eEntity As Long = TBGL_EntityGetFreeID(sScene)
Dim data As WaterPlane

' -- Custom initialization
' -- Texture for water from parameter
data.textureID = waterTexture

' -- Some defaults for now
data.R = 255
data.G = 255
data.B = 255
data.A = 128

data.planeWidth = 32
data.planeHeight = 32

TBGL_EntityCreateFuncSlot(sScene, eEntity, 0, "WaterPlane_Render")
TBGL_EntitySetUserData(sScene, eEntity, data)

Return eEntity

End Function


Step #5: Setup the rendering routine
The WaterPlane_Render will be automatically called by TBGL once you add WaterPlane entity to scene. So let's define water plane here:


Function WaterPlane_Render()
Dim element As TBGL_TENTITYIDENTIFIER At TBGL_CallingEntity
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(element.scene, element.entity)

' -- Our custom coloring, with alpha support
TBGL_PushColor data.R, data.G, data.B, data.A

' -- Enable texturing
TBGL_PushState %TBGL_TEXTURING
TBGL_PushTexture data.textureID

' -- Enable alpha blending
TBGL_PushState %TBGL_BLEND
TBGL_PushBlendFunc %GL_SRC_ALPHA, %GL_ONE_MINUS_SRC_ALPHA

' -- Draw the quad, centered
TBGL_BeginPoly %GL_QUADS
TBGL_Normal 0, -1, 0
TBGL_TexCoord2D 0 , 0
TBGL_Vertex -data.planeWidth/2, 0, -data.planeHeight/2

TBGL_TexCoord2D data.planeWidth, 0
TBGL_Vertex data.planeWidth/2, 0, -data.planeHeight/2

TBGL_TexCoord2D data.planeWidth, data.planeHeight
TBGL_Vertex data.planeWidth/2, 0, data.planeHeight/2

TBGL_TexCoord2D 0 , data.planeHeight
TBGL_Vertex -data.planeWidth/2, 0, data.planeHeight/2
TBGL_EndPoly
' -- Feel free to add more layers, water animation...

' -- Restore blending state
TBGL_PopBlendFunc
TBGL_PopState

' -- Restore texuring state
TBGL_PopTexture
TBGL_PopState

' -- Restore coloring
TBGL_PopColor

End Function


Step #6: Add custom routines to modify plane size, color...
The template contains a recipe for custom method, it looks like this:


Function WaterPlane_Method(sScene As Long, eEntity As Long)
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(sScene, eEntity)

End Function


By trivial modification, we can transform it to methods defining what we need:


Function WaterPlane_SetSize(sScene As Long, eEntity As Long, planeWidth As Single, planeHeight As Single)
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(sScene, eEntity)

data.planeWidth = planeWidth
data.planeHeight = planeHeight
End Function

Function WaterPlane_SetColorAlpha(sScene As Long, eEntity As Long, r As Byte, g As Byte, b As Byte, a As Byte)
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(sScene, eEntity)

data.r = r
data.g = g
data.b = b
data.a = a
End Function


Step #7: Final touch
To make the code reusable in multiple projects, just save it as code unit. What about entity_WaterPlane.tBasicU?

Step #8: Using in code
Just include the unit and call the function from it. Its intuitive...


#include "entity_WaterPlane.tBasicU"

...

%eWaterPlane = WaterPlane_Create(%sScene, 1) ' -- We want it to texture with texture no.1
WaterPlane_SetColorAlpha(%sScene, %eWaterPlane, 255, 255, 255, 192) ' -- We want it to be less transparent
WaterPlane_SetSize(%sScene, %eWaterPlane, 64, 64) ' -- Make it bigger


That is all! Using entities from template is easy, systematic way to add powerful elements to your scenes... I attach the code here, feel free to tune.


Petr

ReneMiner
04-05-2013, 16:55
I tried. But somehow the Textures don't add up- I only can see the top-layer- I used Test_of as in your example and changed a little in the Entity-Unit, now looks like this:


'
' Custom WaterPlane actor entity
' Petr Schreiber, 05-04-2013
'

' -----

Type t_Texel
U As Double
V As Double
End Type

Type WaterPlane
textureID As Long

R As Byte
G As Byte
B As Byte
A As Byte

planeWidth As Single
planeHeight As Single

T(8, 4) As t_Texel
Move(8) As t_Texel
End Type


'[!] Constructor and destructor
Function WaterPlane_Create( sScene As Long, waterTexture As Long ) As Long ' -- Texture for water added as parameter

Dim eEntity As Long = TBGL_EntityGetFreeID(sScene)
Dim data As WaterPlane
Dim i As Long

' -- Custom initialization
' -- Texture for water from parameter
data.textureID = waterTexture

' -- Some defaults for now
data.R = 255
data.G = 255
data.B = 255
data.A = 128

data.planeWidth = 32
data.planeHeight = 32

For i = 1 To 8
data.T(i, 2).U = 1.0
data.T(i, 3).V = 1.0
data.T(i, 4).U = 1.0 : data.T(i, 4).V = 1.0
Next
data.Move(1).U = -0.0015 : data.Move(1).V = -0.0015
data.Move(2).U = 0 : data.Move(2).V = -0.0015
data.Move(3).U = 0.0015 : data.Move(3).V = -0.0015
data.Move(4).U = -0.0015 ': data.Move(4).V = 0
data.Move(5).U = 0.0015 ': data.Move(5).V = 0
data.Move(6).U = -0.0015 : data.Move(6).V = 0.0015
data.Move(7).U = 0 : data.Move(7).V = 0.0015
data.Move(8).U = 0.0015 : data.Move(8).V = 0.0015

TBGL_EntityCreateFuncSlot(sScene, eEntity, 0, "WaterPlane_Render")
TBGL_EntitySetUserData(sScene, eEntity, data)

Return eEntity

End Function

Function WaterPlane_Destroy(sScene As Long, eEntity As Long)
' -- Destructor is not that needed as TBGL has garbage collection...
TBGL_EntityDestroy(sScene, eEntity)
End Function

'[!] Rendering
Function WaterPlane_Render()
Dim element As TBGL_TENTITYIDENTIFIER At TBGL_CallingEntity
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(element.scene, element.entity)

Static i, j As Long

' -- Our custom coloring, with alpha support
TBGL_PushColor data.R, data.G, data.B, data.A

' -- Enable texturing
TBGL_PushState %TBGL_TEXTURING
TBGL_PushTexture data.textureID

' -- Enable alpha blending
TBGL_PushState %TBGL_BLEND
TBGL_PushBlendFunc %GL_SRC_ALPHA, %GL_ONE_MINUS_SRC_ALPHA

' -- Draw the quad, centered
TBGL_BeginPoly %GL_QUADS
TBGL_Normal 0, -1, 0
For i = 1 To 8

For j = 1 To 4
data.t(i,j).U += data.Move(i).U
data.t(i,j).V += data.Move(i).V
' of course has to multiply with Framerate later
' but omit here since it's not global in this script
Next

If data.t(i,1).U > 10 Then
data.t(i,1).U -= 10
data.t(i,1).V -= 10
data.t(i,2).U -= 10
data.t(i,2).V -= 10
data.t(i,3).U -= 10
data.t(i,3).V -= 10
data.t(i,4).U -= 10
data.t(i,4).V -= 10
ElseIf data.t(i,1).U < -10 Then
data.t(i,1).U += 10
data.t(i,1).V += 10
data.t(i,2).U += 10
data.t(i,2).V += 10
data.t(i,3).U += 10
data.t(i,3).V += 10
data.t(i,4).U += 10
data.t(i,4).V += 10
EndIf

TBGL_TexCoord2D data.t(i,1).U , data.t(i,1).V
TBGL_Vertex -data.planeWidth/2, 0, -data.planeHeight/2

TBGL_TexCoord2D data.t(i,2).U , data.t(i,2).V
TBGL_Vertex data.planeWidth/2, 0, -data.planeHeight/2


TBGL_TexCoord2D data.t(i,3).U , data.t(i,3).V
TBGL_Vertex data.planeWidth/2, 0, data.planeHeight/2

TBGL_TexCoord2D data.t(i,4).U , data.t(i,4).V
TBGL_Vertex -data.planeWidth/2, 0, data.planeHeight/2
Next
TBGL_EndPoly
' -- Feel free to add more layers, water animation...

' -- Restore blending state
TBGL_PopBlendFunc
TBGL_PopState

' -- Restore texuring state
TBGL_PopTexture
TBGL_PopState

' -- Restore coloring
TBGL_PopColor

End Function

'[!] Methods
Function WaterPlane_SetSize(sScene As Long, eEntity As Long, planeWidth As Single, planeHeight As Single)
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(sScene, eEntity)

data.planeWidth = planeWidth
data.planeHeight = planeHeight
End Function

Function WaterPlane_SetColorAlpha(sScene As Long, eEntity As Long, r As Byte, g As Byte, b As Byte, a As Byte)
Dim data As WaterPlane At TBGL_EntityGetUserDataPointer(sScene, eEntity)

data.r = r
data.g = g
data.b = b
data.a = a
End Function



OK, I also added something in the other unit but that was just lower alpha at line 47. And I wonder why just half of texture is visible... but that might be the overlapping 8 of faces since the textures have no own layers to scroll.

The stuff about "If data.t(i,1).U > 10 Then...Else If data.t(i,1).U < -10 Then..." is just to set back to some lower number - intention is to scroll texture into 8 directions translucent in a way that the colors add up so it looks like real water-reflections. To influence as having a river or stream you would only lower the Move-speed in the opposing direction.

Petr Schreiber
04-05-2013, 21:17
Hi Rene,

the most probable reason will be the fragments being discarded in depth test. Try to add this to your render function:


TBGL_PushDepthFunc %TBGL_LEQUAL

... render geometry here ...

TBGL_PopDepthFunc



Petr

ReneMiner
05-05-2013, 08:30
I also tried- it works not satisfying: The orange cube - or call it the rest of the world - get's invisible then. And the textures don't add up but just cover each other so the animation does not look right. I attach my changed version including a seamless texture especially made for this purpose - then you can imagine what it's supposed to look like a little bit - but it's far from perfect because it does not show the correct mixing-effect on top nor the rest of the scene.

Edit: Currently for terrain-ed I just use some translucent colored quad without any texture. That serves the needs for editor.

Petr Schreiber
05-05-2013, 11:21
Hi Rene,

I attach modified version for you, it seems to work okay to me now.
I removed your alpha func - it would just discard fragments with 0..127 alpha values here.


Petr

Petr Schreiber
05-05-2013, 11:42
Alternative using color blending.


Petr