SyntaxBomb - Indie Coders

Languages & Coding => BlitzMax / BlitzMax NG => MiniB3D => Topic started by: Krischan on January 04, 2019, 23:33:07

Title: OpenB3D Questions
Post by: Krischan on January 04, 2019, 23:33:07
Hi there. I've stopped working with Blitzmax and OpenB3D a few months ago due to a great showstopper problem with OpenB3D. Now I started to work on it again and came across new topics. I modified one of my techdemos so that you can play around with it. Maybe Mark or someone else can help here.

Background: OpenB3D should be mostly syntax compatible to MiniB3D. So I wrote the same demo once in the latest MiniB3D version and once parallel in the newest OpenB3D release from Github. Actually these source codes should be almost the same in syntax, but I noticed different results in some parts in OpenB3D and had to code some workarounds. I'm still using BlitzmaxOS, BLIDE and a BMK.exe from October 2017 (because of BLIDE). MinGW is gcc.exe (tdm64-1) 5.1.0 here.

The demo is visually quite simple, but has - as always - a complex sourcecode. I tried to stay below 1000 lines - I've attached both sources and the compiled executables here to this post. The demo shows an endless star field, which consists of 6.250.000 single stars (yes, correctly read). The star texture is generated procedurally by the code so no external media is needed. You can move around with WASD, QE and RF - hold TAB for Turbo. I've added three Debug stages which you can enable by changing the DEBUGLEVEL variable at the top of the source, together with other variables there. Level 1 disables Instancing and calculates a limited starfield using the TQuad rotations only for ALL stars, which is very slow. Level 2 disables textures and shows the 125 clusters colored, visualizing the teleport effect. And Level 3 makes it possible to leave the Cube to see the whole structure.

To make the demo still run with 60FPS I use Instancing with CopyEntity. First, a single star cluster with 50,000 stars is calculated, which is then duplicated in a 5x5x5 matrix in a cube. The camera only moves around in the innermost cube and is teleported to the opposite side of the inner cluster when reaching the edge. Since all clusters are visually identical, this teleporting is nearly not noticeable and the impression of an infinite star field is created.

Now to the problems / questions regarding OpenB3D: ???

1) Line 99: I must add "SetBlend ALPHABLEND" here or the initialization in OpenB3D looks very strange - MiniB3D doesn't have this problem. Generally the blending seems to work differently than in MiniB3D. Comment this line and see yourself :-)

2) Line 111 / 257 / TQuad Type: why are the vertex coordinate changes in CopyEntity not copied to all children meshes live like in MiniB3D? I manipulate the quads only in the source mesh, but the copies are ignored? Is it a bug? Or still not implemented? This is IMHO a very important feature of 3D graphics.

3) Line 102-185: why does the initialization take much longer with OpenB3D than with MiniB3D? MiniB3D: 1250ms vs. OpenB3D: 3000ms

4) Line 739: why do I must calculate the Cameraviewport Y value from the bottom left? In MiniB3D I use "CameraViewport tempcam, 0, 0, size, size" (top left) and in OpenB3D I must use "GraphicsHeight() - size" for the Y-coordinate to get the same result. I know that OpenGL calculates this way, but it is confusing compared to Blitz3D/MiniB3D

5) Line 205-206: in OpenB3D the mouse pointer moves slightly after initialization, this can only be fixed by NOT subtracting -1 in GraphicsHeight() - in MiniB3D it works (and would also be mathematically correct) - is it a rounding bug?

6) Line 279-285: I must use my own Begin2D/End2D functions here instead of the BeginMax2D/EndMax2D, or all vertex colors vanish and the universe is grey (replace my Commands with the default ones and see yourself). But why is this? It could be connected to the first problem noticed here.

7) Line 846: in MiniB3D I could access a Texture's pixmap directly by using the "glBindTexture (GL_TEXTURE_2D, tex.gltex[0])" command. How do I access the Pixmap of a Texture in OpenB3D? Is it only possible with the "BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)" command I've used instead?

8. @Mark: has OpenB3D development stopped four months ago or did you just not have time for it anymore? Am I the only one still using it? :o

Oh, and even if you can't help - have fun with the demo ;D It was a hard piece of work to get BOTH versions running.

MiniB3D Version:
Code (blitzmax) Select
SuperStrict

Import sidesign.minib3d

Graphics3D DesktopWidth() / 1.5, DesktopHeight() / 1.5, 32, 2

ClearTextureFilters()

Global STARS:Int = 50000        ' number of stars per cluster part
Global DIMENSION:Int = 2000     ' cluster dimension
Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
Global SPEED:Float = 1.0        ' overall move speed multiplicator
Global BRAKE:Float = 0.95       ' brake multiplicator
Global VSYNC:Int = False        ' Vertical Sync
Global HOMING:Int = True        ' turn homing on/off
Global COLORED:Int = False      ' colorize clusters
Global TEXTURED:Int = True      ' use star texture
Global Scale:Float = 0.5        ' star scale factor
Global FADE:Int = True          ' fade distant clusters
Global INSTANCING:Int = True    ' duplicate source mesh

Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene

If DEBUGLEVEL > 0 Then

STARS = 1000
Scale = 1.6
DISTRIBUTION = 0.5
INSTANCING = False

If DEBUGLEVEL > 1 Then

COLORED = True
TEXTURED = False

If DEBUGLEVEL > 2 Then

HOMING = False
FADE = False

EndIf

EndIf

EndIf

' ----------------------------------------------------------------------------
' Global variables
' ----------------------------------------------------------------------------
Global localx:Float, localy:Float, localz:Float
Global globalx:Float, globaly:Float, globalz:Float
Global simx:Float, simy:Float, simz:Float
Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float

Global FPS:TFPS = New TFPS
Global MS:Int = MilliSecs()

' ----------------------------------------------------------------------------
' Init scene
' ----------------------------------------------------------------------------
Global masterpivot:TPivot = CreatePivot()

Global cam:TCamera = CreateCamera()
CameraRange cam, 1, DIMENSION * 8
PositionEntity cam, 0, 0, 0

Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
TextureBlend tex, 3

' ----------------------------------------------------------------------------
' Duplicate Quad mesh in a 9x9x9 matrix
' ----------------------------------------------------------------------------
Global meshlist:TList = CreateList()
Global quadlist:TList = CreateList()
Global quadsourcelist:TList = CreateList()
Global lx:Float, ly:Float, lz:Float

Local entities:TEntity[9, 9, 9]
Local meshes:TMesh[9, 9, 9]

Local mesh:TMesh

' star cluster properties
mesh = CreateMesh()
EntityFX mesh, 1 + 2
EntityBlend mesh, 3
If TEXTURED Then EntityTexture mesh, tex
HideEntity mesh

' create blueprint star cluster
For Local i:Int = 1 To STARS

CreateStar(mesh)

Next

' fix for OpenB3D to enable Texture Blending and Alpha?
SetBlend ALPHABLEND

' create 5x5x5 = 125 cluster
For Local x:Int = 0 To 4 Step 1

For Local y:Int = 0 To 4 Step 1

For Local z:Int = 0 To 4 Step 1

' create a mesh and duplicate its properties = FAST
If INSTANCING Then

entities[x, y, z] = CopyEntity(mesh)

PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)

Else

EntityColor entities[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, entities[x, y, z])

' create many unique meshes without instancing = SLOW
Else

' new mesh
meshes[x, y, z] = CreateMesh()
EntityFX meshes[x, y, z], 1
EntityBlend meshes[x, y, z], 3
If TEXTURED Then

EntityTexture meshes[x, y, z], tex
EntityFX meshes[x, y, z], 1 + 2

EndIf

' duplicate blueprint cluster
For Local s:TQuad = EachIn quadsourcelist

Local q:TQuad = New TQuad

q.mesh = meshes[x, y, z]
q.x = s.x
q.y = s.y
q.z = s.z
q.scalex = s.scalex
q.scaley = s.scaley
q.RGB = s.RGB

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)

Next

PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)

Else

EntityColor meshes[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, meshes[x, y, z])

EndIf

RenderWorld

Flip False

Next

Next

Next

' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
MouseX()
MouseY()
MouseXSpeed()
MouseYSpeed()
Flip

MS = MilliSecs() - MS

' ----------------------------------------------------------------------------
' Main Loop
' ----------------------------------------------------------------------------
While Not AppTerminate()

If KeyHit(KEY_ESCAPE) Then End

' axis rotation
Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)

' XYZ movement
Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
Local turbo:Int = KeyDown(KEY_TAB)

If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1

If tadd < 0.01 Then tadd = 0.0

If Abs(xmove) Then xadd:+0.01
If Abs(ymove) Then yadd:+0.01
If Abs(zmove) Then zadd:+0.01
If Abs(roll) Then radd:+0.025
If Abs(turbo) Then tadd:+0.05

xadd:*1.025
yadd:*1.025
zadd:*1.025
radd:*1.025
tadd:*1.025

If xadd > 2.0 Then xadd = 2.0
If yadd > 2.0 Then yadd = 2.0
If zadd > 2.0 Then zadd = 2.0
If radd > 1.5 Then radd = 1.5
If tadd > 25.0 Then tadd = 25.0

' calculate movespeed/rollspeed
If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
If Abs(roll) Then rspeed = radd * Sgn(roll)

' perform rotation and motion
Turn(cam, pitch, yaw, rspeed)
MoveEntity cam, xspeed, yspeed, zspeed

' keep camera at home
If HOMING Then Home(cam, masterpivot, DIMENSION)

' only the master instance quads are facing to the camera
For Local q:TQuad = EachIn quadlist

q.Update(cam)

Next

' fade mesh according to its distance
If FADE Then

For Local e:TEntity = EachIn meshlist

Local d:Float = EntityDistance(cam, e)
Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
EntityAlpha e, a

Next

EndIf

RenderWorld

FPS.Update()

' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
Begin2D()

DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
DrawText("Star Cluster: " + STARS, 0, 15)
DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)

End2D()

Flip VSYNC

' decrease speed
xspeed:*BRAKE
yspeed:*BRAKE
zspeed:*BRAKE
rspeed:*BRAKE

Wend

End

' creates a single star quad
Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)

Local q:TQuad = New TQuad

q.mesh = mesh
q.surf = surf

q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff

' randomized clustering
If Rnd(1) > 1 - DISTRIBUTION Then

Local d:Float = Rnd(0.0001, 0.05)

q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff

EndIf

q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
q.scaley = q.scalex

Local c:Float = (1.0 / q.scalex)
If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)
ListAddLast(quadsourcelist, q)

lx = q.x
ly = q.y
lz = q.z

End Function

' keeps the player in a predefined cubic area
Function Home(target:TEntity, world:TEntity, homesize:Int = 100)

' store Local player Position
Local localx:Double = EntityX(target)
Local localy:Double = EntityY(target)
Local localz:Double = EntityZ(target)

' Check X axis
While localx > homesize

globalx:+homesize
localx:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, -homesize, 0, 0

Wend

While localx < - homesize

globalx:-homesize
localx:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, homesize, 0, 0

Wend

' Check Y axis
While localy > homesize

globaly:+homesize
localy:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, -homesize, 0

Wend

While localy < - homesize

globaly:-homesize
localy:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, homesize, 0

Wend

' Check Z axis
While localz > homesize

globalz:+homesize
localz:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, -homesize

Wend

While localz < - homesize

globalz:-homesize
localz:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, homesize

Wend

' store simulated player Position
simx = localx + globalx
simy = localy + globaly
simz = localz + globalz

End Function

' ----------------------------------------------------------------------------
' Normalizes a value to given range
' ----------------------------------------------------------------------------
Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)

Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin

End Function

' ----------------------------------------------------------------------------
' Turn Entity using Quaternions
' ----------------------------------------------------------------------------
Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)

Local Pitch:Float = 0.0
Local Yaw:Float = 0.0
Local Roll:Float = 0.0

Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)

If Glob = False

Quat = EulerToQuat(EntityPitch(ent, True), EntityYaw(ent, True), EntityRoll(ent, True))
Turn_Quat = EulerToQuat(X, Y, Z)
Quat = MultiplyQuats(Quat, Turn_Quat)
Quat = NormalizeQuat(Quat)
QuatToEuler2(Quat.X, Quat.Y, Quat.Z, Quat.w, Pitch, Yaw, Roll)
RotateEntity Ent, Pitch, Yaw, Roll

Else

RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z

EndIf

End Function

' ----------------------------------------------------------------------------
' Euler to Quaternion
' ----------------------------------------------------------------------------
Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)

Local cr:Float = Cos(-roll / 2.0)
Local cp:Float = Cos(pitch / 2.0)
Local cy:Float = Cos(yaw / 2.0)
Local sr:Float = Sin(-roll / 2.0)
Local sp:Float = Sin(pitch / 2.0)
Local sy:Float = Sin(yaw / 2.0)
Local cpcy:Float = cp * cy
Local spsy:Float = sp * sy
Local spcy:Float = sp * cy
Local cpsy:Float = cp * sy

Local q:TQuaternion = New TQuaternion

q.w = cr * cpcy + sr * spsy
q.x = sr * cpcy - cr * spsy
q.y = cr * spcy + sr * cpsy
q.z = cr * cpsy - sr * spcy

Return q

End Function

' ----------------------------------------------------------------------------
' Quaternion to Euler
' ----------------------------------------------------------------------------
Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)

Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31

Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
Local cost_temp:Float = 1.0 - (sint * sint)
Local cost:Float

If Abs(cost_temp) > QuatToEulerAccuracy

cost = Sqr(cost_temp)

Else

cost = 0.0

EndIf

Local sinv:Float, cosv:Float, sinf:Float, cosf:Float

If Abs(cost) > QuatToEulerAccuracy

sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost

Else

sinv = (2.0 * w * x) - (2.0 * y * z)
cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
sinf = 0.0
cosf = 1.0

EndIf

pitch = ATan2(sint, cost)
yaw = ATan2(sinf, cosf)
roll = -ATan2(sinv, cosv)

End Function

' ----------------------------------------------------------------------------
' Multiply Quaternion
' ----------------------------------------------------------------------------
Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)

Local q:TQuaternion = New TQuaternion

q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z
q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y
q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z
q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x

Return q

End Function

' ----------------------------------------------------------------------------
' Normalize Quaternion
' ----------------------------------------------------------------------------
Function NormalizeQuat:TQuaternion(q:TQuaternion)

Local uv:Float = Sqr(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z)

q.w = q.w / uv
q.x = q.x / uv
q.y = q.y / uv
q.z = q.z / uv

Return q

End Function

' ------------------------------------------------------------------------------------------------
' Quad Type
' ------------------------------------------------------------------------------------------------
Type TQuad

Field x:Float = 0.0 ' position x
Field y:Float = 0.0 ' position y
Field z:Float = 0.0 ' position z

Field row:Int = 0 ' texture row
Field col:Int = 0 ' texture column

Field scalex:Float = 1.0 ' current size X
Field scaley:Float = 1.0 ' current size Y

Field RGB:Int[] = [255, 255, 255] ' Vertex Color
Field Alpha:Float = 1.0 ' Vertex Alpha

Field v:Int = 0 ' vertex counter
Field mesh:TMesh = Null ' mesh pointer
Field surf:TSurface = Null ' surface pointer

' --------------------------------------------------------------------------------------------
' METHOD: Add new Quad
' --------------------------------------------------------------------------------------------
Method Add(col:Int = 0, row:Int = 0)

Local s:Int = CountSurfaces(mesh)
If s = 0 Then

surf = CreateSurface(mesh)

Else

surf = GetSurface(mesh, s)

EndIf

Local i:Int = CountVertices(surf)
If i + 4 > 32768 Then

surf = CreateSurface(mesh)
v = 0

EndIf

' add Vertices
Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)

' color vertices
VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha

' connect triangles
AddTriangle surf, V0, V1, V2
AddTriangle surf, V0, V2, V3

VertexTexCoords surf, V0, col + 1, row
VertexTexCoords surf, V1, col + 1, row + 1
VertexTexCoords surf, V2, col, row + 1
VertexTexCoords surf, V3, col, row

' increase vertex counter
If v >= 4 Then v = V0 + 4 Else v = V0

End Method

' --------------------------------------------------------------------------------------------
' METHOD: Update a Quad
' --------------------------------------------------------------------------------------------
Method Update(target:TEntity)

TFormVector scalex, 0, 0, target, Null
Local X1:Float = TFormedX()
Local Y1:Float = TFormedY()
Local Z1:Float = TFormedZ()

TFormVector 0, scaley, 0, target, Null
Local X2:Float = TFormedX()
Local Y2:Float = TFormedY()
Local Z2:Float = TFormedZ()

' set vertices
VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2

End Method

End Type

' ------------------------------------------------------------------------------------------------
' Exact FPS counter
' ------------------------------------------------------------------------------------------------

Type TFPS

Global renders:Int = 0

Field FPS:Int = 60 ' current FPS value
Field interval:Int = 999
Field averagefps:Int = 60 ' average FPS value
Field framedrops:Int = 0 ' dropped frames
Field oldlooptime:Int = 0
Field looptime:Int = 0
Field multi:Float ' main loop multiplicator

Field old:Int = MilliSecs()
Field totalfps:Int = 30
Field Ticks:Int

' --------------------------------------------------------------------------------------------
' METHOD: Update FPS counter
' --------------------------------------------------------------------------------------------
Method Update()

renders:+1

looptime = MilliSecs() - oldlooptime
oldlooptime = MilliSecs()

If MilliSecs() - old >= interval Then

old = MilliSecs()

FPS = renders * (1000 / interval)
renders = 0
totalfps:+FPS
Ticks:+1

averagefps = totalfps / Ticks

EndIf

End Method

End Type

' Create a stunning star texture
Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)

Local i:Float, j:Int, col:Int, rgb:Int
Local x:Int, y:Int

Local w:Int = GraphicsWidth()

Local tempcam:TCamera, tempsun:TPivot
Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
Local tex:TTexture = CreateTexture(size, size, 1 + 8)

For j = 0 To (size / 2) - 1

col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
If col > 255 Then col = 255
rgb = col * $1000000 + col * $10000 + col * $100 + col

For i = 0 To 360 Step 0.1

WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)

Next

Next

PixmapToTexture(pixmap, tex)
'SavePixmapPNG(pixmap, "proceduralstar1.png", 0)

' temp camera
tempcam = CreateCamera()
CameraRange tempcam, 1, w * 2

' no fix needed compared to OpenB3D
CameraViewport tempcam, 0, 0, size, size

' temp pivot
tempsun = CreatePivot()

' Create 4 body quads
CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)

' create 4 ray quads
Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)

' rescale and rotate rays
ScaleEntity ray1, size * 2, size / 32, size
ScaleEntity ray2, size / 32, size * 2, size
ScaleEntity ray3, size, size / 32, size
ScaleEntity ray4, size, size / 32, size
RotateEntity ray3, 0, 0, 45
RotateEntity ray4, 0, 0, 135

PositionEntity tempsun, 0, 0, w

' render star
RenderWorld
RenderWorld

' grab image
pixmap = GrabPixmap(0, 0, size, size)
For x = 0 To size - 1

For y = 0 To size - 1

rgb = ReadPixel(pixmap, x, y)

r = (rgb & $ff0000) / $10000
g = (rgb & $ff00) / $100
b = (rgb & $ff)

' rgb
rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b

WritePixel(pixmap, x, y, rgb)

Next

Next

PixmapToTexture(pixmap, tex)
'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)

' Delete pixmap, pivot and temp cam
pixmap = Null
FreeEntity tempsun
FreeEntity tempcam

Return tex

End Function

' custom quad creation
Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)

Local mesh:TMesh = CreateMesh()
Local surf:TSurface = CreateSurface(mesh)
Local v0:Int, v1:Int, v2:Int, v3:Int

v0 = AddVertex(surf, 1, 1, 0, 0, 0)
v1 = AddVertex(surf, -1, 1, 0, 1, 0)
v2 = AddVertex(surf, -1, -1, 0, 1, 1)
v3 = AddVertex(surf, 1, -1, 0, 0, 1)

AddTriangle surf, v0, v1, v2
AddTriangle surf, v0, v2, v3

If parent Then EntityParent Mesh, parent
If fx Then EntityFX Mesh, fx
If tex Then EntityTexture Mesh, tex
If blend Then EntityBlend Mesh, blend

EntityColor Mesh, r, g, b
EntityAlpha Mesh, a

VertexColor surf, v0, r, g, b, a
VertexColor surf, v1, r, g, b, a
VertexColor surf, v2, r, g, b, a
VertexColor surf, v3, r, g, b, a

ScaleEntity Mesh, Scale, Scale, Scale

Return Mesh

End Function

' creates a texture from a pixmap
Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)

If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)

' OpenB3D only function to copy pixmap to texture
'BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)

' MiniB3D workaround to copy pixmap to texture
glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, pixmap.width, pixmap.Height, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))

End Function

' --------------------------------------------------------------------------------
' Fixed BeginMax2D()
' --------------------------------------------------------------------------------
Function Begin2D()

Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)

'glPopClientAttrib()
'glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_TEXTURE)
glPopMatrix()
glMatrixMode(GL_COLOR)
glPopMatrix()

glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)

glMatrixMode GL_TEXTURE
glLoadIdentity

glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1

glMatrixMode GL_MODELVIEW
glLoadIdentity

SetViewport x, y, w, h

Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))

For Local Layer:Int = 0 Until MaxTex

glActiveTexture(GL_TEXTURE0+Layer)

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)

Next

glActiveTexture(GL_TEXTURE0)

glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
glScissor(0, 0, GraphicsWidth(), GraphicsHeight())

glEnable GL_BLEND
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)

End Function

' --------------------------------------------------------------------------------
' Fixed EndMax2D()
' --------------------------------------------------------------------------------
Function End2D()

' save the Max2D settings for later
'glPushAttrib(GL_ALL_ATTRIB_BITS)
'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_TEXTURE)
glPushMatrix()
glMatrixMode(GL_COLOR)
glPushMatrix()

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)

TGlobal.EnableStates()
'glDisable(GL_TEXTURE_2D)

' ' only needed for OpenB3D
'TGlobal.alpha_enable[0] = 0 ' alpha blending was disabled by Max2d (GL_BLEND)
'TGlobal.blend_mode[0] = 1 ' force alpha blending
'TGlobal.fx1[0] = 0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
'TGlobal.fx2[0] = 1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)

glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

glAlphaFunc(GL_GEQUAL, 0.5)

' ' only needed for OpenB3D
'For Local cam:TCamera=EachIn TCamera.cam_list

' active camera - was if cam.hide[0]=0
'If cam = TGlobal.camera_in_use

' fog with Max2d fix
' cam.UpdateFog()
' Exit

'EndIf

'Next

End Function


OpenB3D Version:
Code (blitzmax) Select
SuperStrict

Import openb3dmax.B3dglgraphics

Graphics3D DesktopWidth() / 1.5, DesktopHeight() / 1.5, 32, 2

ClearTextureFilters()

Global STARS:Int = 50000        ' number of stars per cluster part
Global DIMENSION:Int = 2000     ' cluster dimension
Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
Global SPEED:Float = 1.0        ' overall move speed multiplicator
Global BRAKE:Float = 0.95       ' brake multiplicator
Global VSYNC:Int = False        ' Vertical Sync
Global HOMING:Int = True        ' turn homing on/off
Global COLORED:Int = False      ' colorize clusters
Global TEXTURED:Int = True      ' use star texture
Global Scale:Float = 0.5        ' star scale factor
Global FADE:Int = True          ' fade distant clusters
Global INSTANCING:Int = True    ' duplicate source mesh

Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene

If DEBUGLEVEL > 0 Then

STARS = 1000
Scale = 1.6
DISTRIBUTION = 0.5
INSTANCING = False

If DEBUGLEVEL > 1 Then

COLORED = True
TEXTURED = False

If DEBUGLEVEL > 2 Then

HOMING = False
FADE = False

EndIf

EndIf

EndIf

' ----------------------------------------------------------------------------
' Global variables
' ----------------------------------------------------------------------------
Global localx:Float, localy:Float, localz:Float
Global globalx:Float, globaly:Float, globalz:Float
Global simx:Float, simy:Float, simz:Float
Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float

Global FPS:TFPS = New TFPS
Global MS:Int = MilliSecs()

' ----------------------------------------------------------------------------
' Init scene
' ----------------------------------------------------------------------------
Global masterpivot:TPivot = CreatePivot()

Global cam:TCamera = CreateCamera()
CameraRange cam, 1, DIMENSION * 8
PositionEntity cam, 0, 0, 0

Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
TextureBlend tex, 3

' ----------------------------------------------------------------------------
' Duplicate Quad mesh in a 9x9x9 matrix
' ----------------------------------------------------------------------------
Global meshlist:TList = CreateList()
Global quadlist:TList = CreateList()
Global quadsourcelist:TList = CreateList()
Global lx:Float, ly:Float, lz:Float

Local entities:TEntity[9, 9, 9]
Local meshes:TMesh[9, 9, 9]

Local mesh:TMesh

' star cluster properties
mesh = CreateMesh()
EntityFX mesh, 1 + 2
EntityBlend mesh, 3
If TEXTURED Then EntityTexture mesh, tex
HideEntity mesh

' create blueprint star cluster
For Local i:Int = 1 To STARS

CreateStar(mesh)

Next

' fix for OpenB3D to enable Texture Blending and Alpha?
SetBlend ALPHABLEND

' create 5x5x5 = 125 cluster
For Local x:Int = 0 To 4 Step 1

For Local y:Int = 0 To 4 Step 1

For Local z:Int = 0 To 4 Step 1

' create a mesh and duplicate its properties = FAST
If INSTANCING Then

entities[x, y, z] = CopyEntity(mesh)

PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)

Else

EntityColor entities[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, entities[x, y, z])

' create many unique meshes without instancing = SLOW
Else

' new mesh
meshes[x, y, z] = CreateMesh()
EntityFX meshes[x, y, z], 1
EntityBlend meshes[x, y, z], 3
If TEXTURED Then

EntityTexture meshes[x, y, z], tex
EntityFX meshes[x, y, z], 1 + 2

EndIf

' duplicate blueprint cluster
For Local s:TQuad = EachIn quadsourcelist

Local q:TQuad = New TQuad

q.mesh = meshes[x, y, z]
q.x = s.x
q.y = s.y
q.z = s.z
q.scalex = s.scalex
q.scaley = s.scaley
q.RGB = s.RGB

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)

Next

PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)

Else

EntityColor meshes[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, meshes[x, y, z])

EndIf

RenderWorld

Flip False

Next

Next

Next

' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
MouseX()
MouseY()
MouseXSpeed()
MouseYSpeed()
Flip

MS = MilliSecs() - MS

' ----------------------------------------------------------------------------
' Main Loop
' ----------------------------------------------------------------------------
While Not AppTerminate()

If KeyHit(KEY_ESCAPE) Then End

' axis rotation
Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)

' XYZ movement
Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
Local turbo:Int = KeyDown(KEY_TAB)

If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1

If tadd < 0.01 Then tadd = 0.0

If Abs(xmove) Then xadd:+0.01
If Abs(ymove) Then yadd:+0.01
If Abs(zmove) Then zadd:+0.01
If Abs(roll) Then radd:+0.025
If Abs(turbo) Then tadd:+0.05

xadd:*1.025
yadd:*1.025
zadd:*1.025
radd:*1.025
tadd:*1.025

If xadd > 2.0 Then xadd = 2.0
If yadd > 2.0 Then yadd = 2.0
If zadd > 2.0 Then zadd = 2.0
If radd > 1.5 Then radd = 1.5
If tadd > 25.0 Then tadd = 25.0

' calculate movespeed/rollspeed
If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
If Abs(roll) Then rspeed = radd * Sgn(roll)

' perform rotation and motion
Turn(cam, pitch, yaw, rspeed)
MoveEntity cam, xspeed, yspeed, zspeed

' keep camera at home
If HOMING Then Home(cam, masterpivot, DIMENSION)

' only the master instance quads are facing to the camera
For Local q:TQuad = EachIn quadlist

q.Update(cam)

Next

' fade mesh according to its distance
If FADE Then

For Local e:TEntity = EachIn meshlist

Local d:Float = EntityDistance(cam, e)
Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
EntityAlpha e, a

Next

EndIf

RenderWorld

FPS.Update()

' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
Begin2D()

DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
DrawText("Star Cluster: " + STARS, 0, 15)
DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)

End2D()

Flip VSYNC

' decrease speed
xspeed:*BRAKE
yspeed:*BRAKE
zspeed:*BRAKE
rspeed:*BRAKE

Wend

End

' creates a single star quad
Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)

Local q:TQuad = New TQuad

q.mesh = mesh
q.surf = surf

q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff

' randomized clustering
If Rnd(1) > 1 - DISTRIBUTION Then

Local d:Float = Rnd(0.0001, 0.05)

q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff

EndIf

q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
q.scaley = q.scalex

Local c:Float = (1.0 / q.scalex)
If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)
ListAddLast(quadsourcelist, q)

lx = q.x
ly = q.y
lz = q.z

End Function

' keeps the player in a predefined cubic area
Function Home(target:TEntity, world:TEntity, homesize:Int = 100)

' store Local player Position
Local localx:Double = EntityX(target)
Local localy:Double = EntityY(target)
Local localz:Double = EntityZ(target)

' Check X axis
While localx > homesize

globalx:+homesize
localx:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, -homesize, 0, 0

Wend

While localx < - homesize

globalx:-homesize
localx:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, homesize, 0, 0

Wend

' Check Y axis
While localy > homesize

globaly:+homesize
localy:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, -homesize, 0

Wend

While localy < - homesize

globaly:-homesize
localy:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, homesize, 0

Wend

' Check Z axis
While localz > homesize

globalz:+homesize
localz:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, -homesize

Wend

While localz < - homesize

globalz:-homesize
localz:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, homesize

Wend

' store simulated player Position
simx = localx + globalx
simy = localy + globaly
simz = localz + globalz

End Function

' ----------------------------------------------------------------------------
' Normalizes a value to given range
' ----------------------------------------------------------------------------
Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)

Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin

End Function

' ----------------------------------------------------------------------------
' Turn Entity using Quaternions
' ----------------------------------------------------------------------------
Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)

Local Pitch:Float = 0.0
Local Yaw:Float = 0.0
Local Roll:Float = 0.0

Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)

If Glob = False

Quat = EulerToQuat(EntityPitch(Ent, True), EntityYaw(Ent, True), EntityRoll(Ent, True))
Turn_Quat = EulerToQuat(X, Y, Z)
Quat = MultiplyQuats(Quat, Turn_Quat)
Quat = NormalizeQuat(Quat)
QuatToEuler2(Quat.x[0], Quat.y[0], Quat.z[0], Quat.w[0], pitch, yaw, roll)
RotateEntity Ent, pitch, yaw, roll

Else

RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z

EndIf

End Function

' ----------------------------------------------------------------------------
' Euler to Quaternion
' ----------------------------------------------------------------------------
Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)

Local cr:Float = Cos(-roll / 2.0)
Local cp:Float = Cos(pitch / 2.0)
Local cy:Float = Cos(yaw / 2.0)
Local sr:Float = Sin(-roll / 2.0)
Local sp:Float = Sin(pitch / 2.0)
Local sy:Float = Sin(yaw / 2.0)
Local cpcy:Float = cp * cy
Local spsy:Float = sp * sy
Local spcy:Float = sp * cy
Local cpsy:Float = cp * sy

Local q:TQuaternion = NewQuaternion()

q.w[0] = cr * cpcy + sr * spsy
q.x[0] = sr * cpcy - cr * spsy
q.y[0] = cr * spcy + sr * cpsy
q.z[0] = cr * cpsy - sr * spcy

Return q

End Function

' ----------------------------------------------------------------------------
' Quaternion to Euler
' ----------------------------------------------------------------------------
Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)

Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31

Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
Local cost_temp:Float = 1.0 - (sint * sint)
Local cost:Float

If Abs(cost_temp) > QuatToEulerAccuracy

cost = Sqr(cost_temp)

Else

cost = 0.0

EndIf

Local sinv:Float, cosv:Float, sinf:Float, cosf:Float

If Abs(cost) > QuatToEulerAccuracy

sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost

Else

sinv = (2.0 * w * x) - (2.0 * y * z)
cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
sinf = 0.0
cosf = 1.0

EndIf

pitch = ATan2(sint, cost)
yaw = ATan2(sinf, cosf)
roll = -ATan2(sinv, cosv)

End Function

' ----------------------------------------------------------------------------
' Multiply Quaternion
' ----------------------------------------------------------------------------
Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)

Local q:TQuaternion = NewQuaternion()

q.w[0] = q1.w[0] * q2.w[0] - q1.x[0] * q2.x[0] - q1.y[0] * q2.y[0] - q1.z[0] * q2.z[0]
q.x[0] = q1.w[0] * q2.x[0] + q1.x[0] * q2.w[0] + q1.y[0] * q2.z[0] - q1.z[0] * q2.y[0]
q.y[0] = q1.w[0] * q2.y[0] + q1.y[0] * q2.w[0] + q1.z[0] * q2.x[0] - q1.x[0] * q2.z[0]
q.z[0] = q1.w[0] * q2.z[0] + q1.z[0] * q2.w[0] + q1.x[0] * q2.y[0] - q1.y[0] * q2.x[0]

Return q

End Function

' ----------------------------------------------------------------------------
' Normalize Quaternion
' ----------------------------------------------------------------------------
Function NormalizeQuat:TQuaternion(q:TQuaternion)

Local uv:Float = Sqr(q.w[0] * q.w[0] + q.x[0] * q.x[0] + q.y[0] * q.y[0] + q.z[0] * q.z[0])

q.w[0] = q.w[0] / uv
q.x[0] = q.x[0] / uv
q.y[0] = q.y[0] / uv
q.z[0] = q.z[0] / uv

Return q

End Function

' ------------------------------------------------------------------------------------------------
' Quad Type
' ------------------------------------------------------------------------------------------------
Type TQuad

Field x:Float = 0.0 ' position x
Field y:Float = 0.0 ' position y
Field z:Float = 0.0 ' position z

Field row:Int = 0 ' texture row
Field col:Int = 0 ' texture column

Field scalex:Float = 1.0 ' current size X
Field scaley:Float = 1.0 ' current size Y

Field RGB:Int[] = [255, 255, 255] ' Vertex Color
Field Alpha:Float = 1.0 ' Vertex Alpha

Field v:Int = 0 ' vertex counter
Field mesh:TMesh = Null ' mesh pointer
Field surf:TSurface = Null ' surface pointer

' --------------------------------------------------------------------------------------------
' METHOD: Add new Quad
' --------------------------------------------------------------------------------------------
Method Add(col:Int = 0, row:Int = 0)

Local s:Int = CountSurfaces(mesh)
If s = 0 Then

surf = CreateSurface(mesh)

Else

surf = GetSurface(mesh, s)

EndIf

Local i:Int = CountVertices(surf)
If i + 4 > 32768 Then

surf = CreateSurface(mesh)
v = 0

EndIf

' add Vertices
Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)

' color vertices
VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha

' connect triangles
AddTriangle surf, V0, V1, V2
AddTriangle surf, V0, V2, V3

VertexTexCoords surf, V0, col + 1, row
VertexTexCoords surf, V1, col + 1, row + 1
VertexTexCoords surf, V2, col, row + 1
VertexTexCoords surf, V3, col, row

' increase vertex counter
If v >= 4 Then v = V0 + 4 Else v = V0

End Method

' --------------------------------------------------------------------------------------------
' METHOD: Update a Quad
' --------------------------------------------------------------------------------------------
Method Update(target:TEntity)

TFormVector scalex, 0, 0, target, Null
Local X1:Float = TFormedX()
Local Y1:Float = TFormedY()
Local Z1:Float = TFormedZ()

TFormVector 0, scaley, 0, target, Null
Local X2:Float = TFormedX()
Local Y2:Float = TFormedY()
Local Z2:Float = TFormedZ()

' set vertices
VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2

End Method

End Type

' ------------------------------------------------------------------------------------------------
' Exact FPS counter
' ------------------------------------------------------------------------------------------------

Type TFPS

Global renders:Int = 0

Field FPS:Int = 60 ' current FPS value
Field interval:Int = 999
Field averagefps:Int = 60 ' average FPS value
Field framedrops:Int = 0 ' dropped frames
Field oldlooptime:Int = 0
Field looptime:Int = 0
Field multi:Float ' main loop multiplicator

Field old:Int = MilliSecs()
Field totalfps:Int = 30
Field Ticks:Int

' --------------------------------------------------------------------------------------------
' METHOD: Update FPS counter
' --------------------------------------------------------------------------------------------
Method Update()

renders:+1

looptime = MilliSecs() - oldlooptime
oldlooptime = MilliSecs()

If MilliSecs() - old >= interval Then

old = MilliSecs()

FPS = renders * (1000 / interval)
renders = 0
totalfps:+FPS
Ticks:+1

averagefps = totalfps / Ticks

EndIf

End Method

End Type

' Create a stunning star texture
Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)

Local i:Float, j:Int, col:Int, rgb:Int
Local x:Int, y:Int

Local w:Int = GraphicsWidth()

Local tempcam:TCamera, tempsun:TPivot
Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
Local tex:TTexture = CreateTexture(size, size, 1 + 8)

For j = 0 To (size / 2) - 1

col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
If col > 255 Then col = 255
rgb = col * $1000000 + col * $10000 + col * $100 + col

For i = 0 To 360 Step 0.1

WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)

Next

Next

PixmapToTexture(pixmap, tex)
'SavePixmapPNG(pixmap, "proceduralstar1.png", 0)

' temp camera
tempcam = CreateCamera()
CameraRange tempcam, 1, w * 2

' fix for OpenB3D to simulate MiniB3D's Cameraviewport handling
CameraViewport tempcam, 0, GraphicsHeight() - size, size, size

' temp pivot
tempsun = CreatePivot()

' Create 4 body quads
CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)

' create 4 ray quads
Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)

' rescale and rotate rays
ScaleEntity ray1, size * 2, size / 32, size
ScaleEntity ray2, size / 32, size * 2, size
ScaleEntity ray3, size, size / 32, size
ScaleEntity ray4, size, size / 32, size
RotateEntity ray3, 0, 0, 45
RotateEntity ray4, 0, 0, 135

PositionEntity tempsun, 0, 0, w

' render star
RenderWorld
RenderWorld

' grab image
pixmap = GrabPixmap(0, 0, size, size)
For x = 0 To size - 1

For y = 0 To size - 1

rgb = ReadPixel(pixmap, x, y)

r = (rgb & $ff0000) / $10000
g = (rgb & $ff00) / $100
b = (rgb & $ff)

' rgb
rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b

WritePixel(pixmap, x, y, rgb)

Next

Next

PixmapToTexture(pixmap, tex)
'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)

' Delete pixmap, pivot and temp cam
pixmap = Null
FreeEntity tempsun
FreeEntity tempcam

Return tex

End Function

' custom quad creation
Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)

Local mesh:TMesh = CreateMesh()
Local surf:TSurface = CreateSurface(mesh)
Local v0:Int, v1:Int, v2:Int, v3:Int

v0 = AddVertex(surf, 1, 1, 0, 0, 0)
v1 = AddVertex(surf, -1, 1, 0, 1, 0)
v2 = AddVertex(surf, -1, -1, 0, 1, 1)
v3 = AddVertex(surf, 1, -1, 0, 0, 1)

AddTriangle surf, v0, v1, v2
AddTriangle surf, v0, v2, v3

If parent Then EntityParent Mesh, parent
If fx Then EntityFX Mesh, fx
If tex Then EntityTexture Mesh, tex
If blend Then EntityBlend Mesh, blend

EntityColor Mesh, r, g, b
EntityAlpha Mesh, a

VertexColor surf, v0, r, g, b, a
VertexColor surf, v1, r, g, b, a
VertexColor surf, v2, r, g, b, a
VertexColor surf, v3, r, g, b, a

ScaleEntity Mesh, Scale, Scale, Scale

Return Mesh

End Function

' creates a texture from a pixmap
Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)

If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)

' OpenB3D only function to copy pixmap to texture
BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)

' MiniB3D workaround to copy pixmap to texture
'glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
'gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))

End Function

' --------------------------------------------------------------------------------
' Fixed BeginMax2D()
' --------------------------------------------------------------------------------
Function Begin2D()

Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)

'glPopClientAttrib()
'glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_TEXTURE)
glPopMatrix()
glMatrixMode(GL_COLOR)
glPopMatrix()

glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)

glMatrixMode GL_TEXTURE
glLoadIdentity

glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1

glMatrixMode GL_MODELVIEW
glLoadIdentity

SetViewport x, y, w, h

Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))

For Local Layer:Int = 0 Until MaxTex

glActiveTexture(GL_TEXTURE0+Layer)

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)

Next

glActiveTexture(GL_TEXTURE0)

glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
glScissor(0, 0, GraphicsWidth(), GraphicsHeight())

glEnable GL_BLEND
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)

End Function

' --------------------------------------------------------------------------------
' Fixed EndMax2D()
' --------------------------------------------------------------------------------
Function End2D()

' save the Max2D settings for later
'glPushAttrib(GL_ALL_ATTRIB_BITS)
'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_TEXTURE)
glPushMatrix()
glMatrixMode(GL_COLOR)
glPushMatrix()

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)

TGlobal.EnableStates()
'glDisable(GL_TEXTURE_2D)

' only needed for OpenB3D
TGlobal.alpha_enable[0] = 0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0] = 1 ' force alpha blending
TGlobal.fx1[0] = 0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0] = 1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)

glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

glAlphaFunc(GL_GEQUAL, 0.5)

' only needed for OpenB3D
For Local cam:TCamera=EachIn TCamera.cam_list

' active camera - was if cam.hide[0]=0
If cam = TGlobal.camera_in_use

' fog with Max2d fix
cam.UpdateFog()
Exit

EndIf

Next

End Function
Title: Re: OpenB3D Questions
Post by: Flanker on January 05, 2019, 02:17:03
Nice demo here, instancing is very powerful. You're not the only one using OpenB3D, I've totally abandon Blitz3D for OpenB3D because I prefer Blitzmax coding and because GLSL (or shaders in general) are amazing.

1) The only problem if I comment "SetBlend ALPHABLEND" is that there is no alpha when building the mesh at startup but after that it works well. However I also noticed a problem with alpha textures on my side a few weeks ago when I tried to code a 3D snow fall effect with OpenB3D. I had to use EntityAlpha to be able to activate texture alpha, wich is strange.

2) I remember using instancing with CopyEntity() in Blitz3D to make an "ocean" from one single animated mesh, and as you mentioned, in Blitz3D when you modify the source mesh, all instancies are also affected (useful to animate a lot of vertices). Maybe it's just not implemented here.

5) Funny to see that you also have a fix before the main loop to prevent the camera from spinning at the start. I think there is also a problem with MouseXSpeed()/MouseYSpeed() and MoveMouse(), or at least it works differently than Blitz3D.
Title: Re: OpenB3D Questions
Post by: Krischan on January 05, 2019, 11:21:54
The mouse fix is needed both in MiniB3D and OpenB3D, but I don't know why this happens. And the two Flips before and after the Mouse Commands are important or it won't work. I had blending problems with OpenB3D since I first saw it - I created a few workarounds but this should be fixed in general IMHO. And yes, GLSL shaders are amazing with OpenB3D but a big problem with GLSL is that I hate to code without the possibility to debug values onscreen - you need tricks or hints to see what's wrong. But this is not a problem of OpenB3D ;D

Another problem I had already pointed out to mark is a strange bug in my game with reloaded Textures on B3D Models. In my game, when a new level is loaded, a BSP file is parsed and created as a mesh, gets textured and then I load a B3D model like a chest or a torch template and use CopyEntity to spread it across the level. After entering another level, all loaded assets are deleted and recreated. This worked until May 18 2017.

Now with the latest versions, either the models are completely untextured, I see only the normalmap or the normalmap+diffusemap in a random manner, but only on the B3D models - the level geometry is still fine. I've checked the OpenB3D source changes since the May 18 2017 version which is the last one where it worked (and it was the last one I could compile with my old BMK until he fixed this in the more current versions). I've sent my whole game project to Mark a few months ago and hope he will find some time to find the error as I failed with it.

But beside all these annoyances Blitzmax+OpenB3D is still a great combo and my first choice. On the other hand I spend more time to create workarounds in OpenB3D than creating progress in the game engine and game logic, which is not good.
Title: Re: OpenB3D Questions
Post by: markcwm on January 06, 2019, 01:48:05
Hi Krischan,

I'll just reply to point 8 for now, yes I'll be continuing development on Openb3dmax in my spare time, in fact I have been working on it these last few days and have an update to the 1.25 source coming, but I've a few nasty bugs to fix first, shaders and b3d files are crashing!

Well I'll more fully explain why development stopped, about the start of September I got sciatica in my lower back lifting about 20kg, so yes about 4 months ago, this is a recurring injury and I just lifted something too heavy. So I was in too much pain to concentrate for coding, now I still have sciatica quite bad but I've found ibuprofen gel which makes the pain manageable so I can do a bit of coding now.

I sorry you've had so many problems with Openb3d, it's always been a WIP but it is starting to mature into something like Blitz3d. It has great potential as Angros has done an awesome job on the OpenGL, all it needs is a bit more work, well quite a bit really!

Also sorry I never got back to you on LOF, I ran the exe but it just crashed when I launched a level. I'll have another look at it soon.
Title: Re: OpenB3D Questions
Post by: Krischan on January 07, 2019, 20:06:57
Mark, your health is more important than our projects - don't worry, take the time you need and get well soon! I'll continue developing the game with the old April 30 version which seemed stable enough for me. I know that OpenB3D is not finished but it already creates stunning results. I/we really appreciate your work and if you get LOF running you can see what can be done with it by a single enthusiast (but I don't think I can already tap the full potential yet and my shaders are a mess). For the LOF crash: I've re-uploaded my complete Blitzmax+LOF environment and sent you a PM with some instructions how to setup. I think it makes sense to have the same basis here to hunt the bugs.

Beside that I found an interesting issue today:

9) I tried MSI Afterburner on LOF today - works fine until I switch with "Escape" into the game menu (which uses 2D) - the MSI overlay turns into filled quads and stays filled until I end+restart the game (see attached screenshots). This happens too when I replace my custom Begin2D()+End2D() functions with BeginMax2D()+EndMax2D(). Can somebody confirm this with another demo or could it be a bug in my game?
Title: Re: OpenB3D Questions
Post by: markcwm on January 11, 2019, 03:44:20
Hi Krischan,

thanks for your consideration of my health, I am really not too bad so work will continue, albeit at a slow pace.

I have a fix up for the B3D textures not reloaded bug in LOF, it appears to have been the texture ref not getting returned from LoadTexture in TB3D, it's strange though as the ref *should* be the same and not need to be returned, anyway I'm pretty sure that was the problem.

Note that the latest version is now updated to Openb3d 1.25 so it will need LinkShader(s) called after AttachVertShader and AttachFragShader. The most interesting new feature is the PostFX functions which I'll need to make an example for. Also the GLES2 stuff, so it might build for Android now but I haven't tested.

Also I noticed your LOF shaders are written for GL3 which is what was crashing the game, so I just edited a few things to get it to compile on GL2.1:
//#version 130
//precision mediump float;
replace "in" with "varying"
replace "out" with "varying"


@Point 7: yes gltex[] was removed by Angros but I can add that back in to the streamed texture functions.
Title: Re: OpenB3D Questions
Post by: Krischan on January 11, 2019, 10:02:59
Hi Mark,

great that you found time to add these fixes. It compiles and runs here, I've changed my shaders and added the LinkShader to the AssembleMap() Method in TBSP.bmx.

But when I switch the level it crashes at the ParseTextures() method - it seems to load the first texture but the next one crashes (in Renderworld() - inside the texture load function are some calls to UpdateLoader() which updates the Loading Screen with the spinning compass which needs a render pass in the loop there). This worked before and happens before the shaders are re-applied again.

I've added the patched Source, just overwrite the Dev project I've sent you.
Title: Re: OpenB3D Questions
Post by: markcwm on January 11, 2019, 21:12:49
Hi Krischan,

thanks, I can't reproduce this so I'm guessing it's a shader crash, you should try reverting to your original GLSL 130 syntax. I haven't tried your patch yet so I'll do that now.
Title: Re: OpenB3D Questions
Post by: Krischan on January 11, 2019, 22:55:42
It didn't work with the original shader, too. It only "works" (=no crash) if I uncomment my ApplyShaderCache() Method - but then I don't have any level textures anymore. My current level loader is quite complex, but as far as I remember it works like that (it's all in the source but I try to describe it with my own words):

Global Shader Variables in the Type:

Code (Blitzmax) Select
Field VERTEXSHADER_SOURCE:String
Field FRAGMENTSHADER_SOURCE:String
Field MAINSHADER:TShader
Field VERTEXSHADER_COMPILED:TShaderObject
Field FRAGMENTSHADER_COMPILED:TShaderObject
Field SHADERLIST:TList
Field SHADERCACHED:TList


The BSP level geometry consists of several meshes and these can have different diffuse textures while the doors share the same texture but doors must be additional single meshes (not part of the level geometry mesh) to make alpha / Z-Index work on them (you can actually see through some of them). As I have many doors but only some level geometry meshes, I try to reuse the door shader using a cache to load the level faster. But I use only ONE shader source for both use cases (geometry and doors).

I first load the fragment+vertex shader source once (VERTEXSHADER_SOURCE+FRAGMENTSHADER_SOURCE), create a shader material (MAINSHADER), compile both sources once and attach the compiled shaders (VERTEXSHADER_COMPILED+FRAGMENTSHADER_COMPILED) to the MAINSHADER material. With your additions I then use the new LinkShader command on the MAINSHADER material? Is this correct?

Code (Blitzmax) Select
s = ReadFile(PATH_SHADER + filename + ".vert")
VERTEXSHADER_SOURCE = ReadString(s, FileSize(PATH_SHADER + filename + ".vert"))
s = ReadFile(PATH_SHADER + filename + ".vert")
FRAGMENTSHADER_SOURCE = ReadString(s, FileSize(PATH_SHADER + filename + ".frag"))
MAINSHADER = CreateShaderMaterial("")
FRAGMENTSHADER_COMPILED = CreateFragShaderString(MAINSHADER, FRAGMENTSHADER_SOURCE)
VERTEXSHADER_COMPILED = CreateVertShaderString(MAINSHADER, VERTEXSHADER_SOURCE)
AttachFragShader(MAINSHADER, FRAGMENTSHADER_COMPILED)
AttachVertShader(MAINSHADER, VERTEXSHADER_COMPILED)
LinkShader(MAINSHADER)


The Shader cache works like this:
When a mesh gets assembled (geometry or door), on every new surface with different textures I create a new TShaderCache TMap Object and add all detail information about this surface to it (diffuse map, normal map, light map, surface id, mesh num and so on). I use a MD5 string of the diffuse filename plus the surface ID as a GUID key to distinguish between the same texture combinations and add new combinations to the SHADERLIST TList. This is because I don't want to create a new surface if it already exists. For example Walls should share the same shader while carpets or painting have their own shader. I think this is the best way to speed things up. And I've saved a lot of new surfaces with this algorithm.

After creating all meshes I use the ApplyShaderCache() Method. It iterates through all SHADERLIST objects and creates new shaders from the shader sources only for these surfaces. It adds the textures and variables to the shader and uses the ShadeSurface command to apply it to the cached surface. If it is a door, the MAINSHADER is applied instead.

I don't know why I don't compile this new created shader at this point (it is only created from the source) but I think I've had a big problem here I can't remember and needed to bypass it somehow (compiling here leads to a instant crash loading the initial level). I don't know if this is part of the problem:

Code (Blitzmax) Select
s.shader = CreateShader("", VERTEXSHADER_SOURCE, FRAGMENTSHADER_SOURCE)
ShaderTexture(s.shader, s.dm, "diffuseMap", 0)
ShaderTexture(s.shader, s.nm, "normalMap", 1)
ShaderTexture(s.shader, s.lm, "lightMap", 2)
...
ShadeSurface(s.surf, s.shader)


This new s.shader is then added to the SHADERCACHED TList for the next cache loop. The doors all use the precompiled global MAINSHADER instead of the newly created shaders. I don't know why but I had to create it this way but it really worked fast and flawless. When entering a new level, everything I created on the Load() Method is unloaded, cleared, nullified and destroyed. It is a large function but I think I didn't missed something and this worked before, too.

Currently I don't know what to change in my source to make it work again. So a very simple example would be nice: how to properly create, load, apply and unload/recreate a Vert+Frag Shader on a mesh with the same or a different texture without leaving shader, mesh or texture garbage behind before loading a new level - ideally with some kind of caching like I tried. A simple level loader/unloader with shaded meshes. I'm really confused how to use the shaders in such a complex but common scenario. But with such an example, I might be able to understand the problem better.
Title: Re: OpenB3D Questions
Post by: markcwm on January 12, 2019, 00:20:48
Hi Krischan,

well it's probably a bug in the Openb3d 1.25 code as the usematrix example is crashing, so  somethings wrong somewhere and I haven't figured it out yet, however your patch works perfectly here in win32 GL2.1. I suggest you test this by reverting to before the 1.25 update which is 12 sep 18 (https://github.com/markcwm/openb3dmax.mod/tree/275310e439f275480a136581345d5d8af3000706).
Title: Re: OpenB3D Questions
Post by: markcwm on January 18, 2019, 03:50:11
Hi Krischan,

here's an update on my progress, still lots to do...

I added the missing tex.gltex[0], Angros renamed it to frames so you can use that too, gltex just points to frames. Edit: actually only working with anim textures but fixed in latest commit.

Also added is tex.no_mipmaps[0] but it's calculated rather than counted at generation like Minib3d.

BeginMax2D now has a version parameter 0 for old one, 1 for your latest code, which I've credited you for in the source. So thanks. Your version definitely works better with 2d text so it should really be the default.

Other changes are error messages if mesh or texture urls are bad, this is essential functionality, of course Blitz3d does this.

And the 3DS loader is fixed (edit: well nearly) it's a port from Openb3d but with a few changes, texture v's are flipped so words read from left-right, mesh transforms are enabled with MeshLoader "trans" and there's a second 3DS loader from Warner which is improved and basically should now work the same as the default one, it's enabled by MeshLoader "3ds2".

Then there's MeshDebug 1 to enable extra mesh debug info (edit: changed to MeshLoader "debug").

And then LightMesh ported from Blitz3d. And a fix for FreeSurface crashing.
Title: Re: OpenB3D Questions
Post by: Krischan on January 18, 2019, 08:59:01
Thanks for the update - it builds but I can't compile my game anymore:

C:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.release.win32.x86.a(openb3dmax.bmx.release.win32.x86.o):(code+0x1ca5b): undefined reference to `Log2_'
Build Error: Failed to link C:/LOF/Legend of Faerghail.exe

I compiled it like I did with all previous versions, cross-tested it with the 30 apr 18 version (everything is fine) and the 12 sep 18 version works, too (still with the texture/model bug).
bmk makemods -a -r openb3dmax
bmk makemods -a -d openb3dmax

By the way, does LOF work for you now? Another suggestion for future versions: sometimes OpenB3D shows error messages, sometimes they are commented in the CPP sources. For example in texture.cpp all errors are commented while in file.cpp there are some outputs.

It would be nice if this would be uniform across all sources and that you could switch it on/off with a global command, like let's say ShowDebugErrors() / HideDebugErrors(). But this is only a nice-to-have feature.
Title: Re: OpenB3D Questions
Post by: markcwm on January 19, 2019, 06:22:04
Yes sorry, I forgot a file yesterday and didn't double-check.

The latest version replaces Log2 to Mipmaps. Also BeginMax2D now defaults to 1 which is your version. And another update to the 3DS loader, LoadMesh loads one mesh with many surfaces, LoadAnimMesh loads many meshes with one surface, CollapseAnimMesh was used before but wasn't working in bmx, it's a wierd function though so I'm not sure what it does. And shaders now debug errors when the filename is wrong.

Yes, LOF works with this latest commit so I'm not sure what's up but it may be a GL3 issue as I'm in GL2. You could try commenting out all ShadeSurface but I've just tested and that was working. Is it crashing exactly at the ShadeSurface function? It also might be the shader matrix code, so try running shader/bumpmap as it has some mat3 code.
Title: Re: OpenB3D Questions
Post by: Krischan on January 20, 2019, 11:53:05
First - the model texture bug has vanished now - so the model textures are applied correct again after loading another level. Great.

But it still crashes after loading the next level. It only "works" when I comment the two ShadeSurface() commands in the ApplyShaderCache() Method in include\types\TBSP.bmx. The level geometry is untextured then, well at least I have some distance fog ;-) So Shadesurface crashes the texture loader in the second run. But why? I've tested it on an old nVidia GTX 780M with a very outdated driver (398.82) and a brandnew GTX 2080 with the newest driver (417.71) which still has the same problem. So is it a bug in LOF or in OpenB3D? I don't know.

And I think my custom Begin/End commands are not complete yet as I'm still having the MSI Afterburner OSD bug after entering the menu. The bug vanishes when I uncomment the glActiveTexture(GL_TEXTURE0) in BeginMax2D(), but then all menu textures vanish, too. Does anybody know why or how to fix it? And it is risky to use my own functions in OpenB3D as I really didn't knew what excactly to do there - it is the result of try and error only.

So it would make sense if someone who knows more about OpenGL than I do would take a look at it.

Code (Blitzmax) Select

Rem
bbdoc: Blitz2D
EndRem
Type TBlitz2D

Function BeginMax2D( version:Int=1 )

Select version

Case 0 ' Old begin function (by Oddball)

glPopClientAttrib()
glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_TEXTURE)
glPopMatrix()
glMatrixMode(GL_COLOR)
glPopMatrix()

Case 1 ' New begin function, allows instant resolution switch (by Krischan)

Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)

'glPopClientAttrib()
'glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_TEXTURE)
glPopMatrix()
glMatrixMode(GL_COLOR)
glPopMatrix()

glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)

glMatrixMode GL_TEXTURE
glLoadIdentity

glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho(0, TGlobal.width[0], TGlobal.height[0], 0, -1, 1) ' TGlobal.w/h instead of GraphicsW/H for MaxGUI

glMatrixMode GL_MODELVIEW
glLoadIdentity

SetViewport x, y, w, h

Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))

For Local Layer:Int = 0 Until MaxTex
glActiveTexture(GL_TEXTURE0+Layer)

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)
Next

glActiveTexture(GL_TEXTURE0)

glViewport(0, 0, TGlobal.width[0], TGlobal.height[0])
glScissor(0, 0, TGlobal.width[0], TGlobal.height[0])

glEnable GL_BLEND
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)

End Select

End Function

' Old end Max2d function
Function EndMax2D( version:Int=1 )

Select version

Case 0 ' Old end function (by Oddball)

' save the Max2D settings for later
glPushAttrib(GL_ALL_ATTRIB_BITS)
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_TEXTURE)
glPushMatrix()
glMatrixMode(GL_COLOR)
glPushMatrix()

TGlobal.EnableStates() ' enables normals and vertex colors
glDisable(GL_TEXTURE_2D) ' needed as Draw in Max2d enables it, but doesn't disable after use

' set render state flags (crash if fx2 is not set)
TGlobal.alpha_enable[0]=0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0]=1 ' force alpha blending
TGlobal.fx1[0]=0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0]=1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)

glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

glAlphaFunc(GL_GEQUAL,0.5)

For Local cam:TCamera=EachIn TCamera.cam_list
If cam=TGlobal.camera_in_use ' active camera - was if cam.hide[0]=0
cam.UpdateFog() ' fog with Max2d fix
Exit
EndIf
Next

Case 1 ' New end function, allows instant resolution switch (by Krischan)

' save the Max2D settings for later
'glPushAttrib(GL_ALL_ATTRIB_BITS)
'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_TEXTURE)
glPushMatrix()
glMatrixMode(GL_COLOR)
glPushMatrix()
 
glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)

TGlobal.EnableStates()

' set render state flags (crash if fx2 is not set)
TGlobal.alpha_enable[0]=0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0]=1 ' force alpha blending
TGlobal.fx1[0]=0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0]=1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)

glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

glAlphaFunc(GL_GEQUAL, 0.5)

For Local cam:TCamera=EachIn TCamera.cam_list ' active camera - was if cam.hide[0]=0
If cam = TGlobal.camera_in_use ' fog with Max2d fix
cam.UpdateFog()
Exit
EndIf
Next

End Select

End Function

End Type
Title: Re: OpenB3D Questions
Post by: markcwm on January 22, 2019, 04:34:00
Hi Krischan,

I think I have a fix for the ShadeSurface crash now, I was able to reproduce it, as it turns out the shader/usematrix crash is the same bug, which is a crash if a b3d model had no texture, it happened in shader render TurnOn. The fix skips rendering if there's no texture for shader, brush and surface brush.

Then there's a fix for the vertex color breaking with Max2D, it happens if the mesh is the last in the list, some state is not being set/reset but I couldn't figure out what so I settled for just rendering a dummy mesh after everything.

Also BeginMax2d has the glPopAttrib/glPushAttrib code back in because this may fix your MSI Afterburner issue, if you don't do this the blend state isn't saved and can be affected by other code, Text doesn't do this and it changes depending on the last blend used, see standard/alphamap. I wasn't able to test with Afterburner as I don't know what that is, so please let me know how that goes. Thanks!

I also noticed in LOF when you reload a level sometimes a letter is blocked out in the menu text, like it was a C today but an S last time, I think it must be a LOF bug as it happens randomly.
Title: Re: OpenB3D Questions
Post by: Krischan on January 22, 2019, 07:34:50
Thanks Mark - I'll give it a try this evening. Looks like OpenB3D gets better every day :-) The MSI Afterburner is a free tool for overclocking but has the nice feature of this overlay for DX/OGL, too. You can display a lot of data like FPS, CPU/GPU usage, Core temp/clock and so on which is very useful for developing. You can download it here:

http://download.msi.com/uti_exe//vga/MSIAfterburnerSetup.zip (http://download.msi.com/uti_exe//vga/MSIAfterburnerSetup.zip)

Here is a short video how to set it up:
https://www.youtube.com/watch?v=uIlMRRlKQGg

For the letter bug in LOF, do you have a screenshot? I haven't noticed this. There is a hidden debug mode for the menu screen - press the ^ circumflex key to see the menu text layout borders and change the resolution with 1,2,3 or 4 to see if it works (see attachment).
Title: Re: OpenB3D Questions
Post by: Krischan on January 22, 2019, 23:38:46
I've tested the current version, the OSD works fine now, but it is still crashing here at Renderworld when loading a new level. Again, commenting the two ShadeSurface commands in the ApplyShaderCache Method "fix" the crash. I've used the LOFDEV_2019_01_07.zip with the LOF_DevPatch001.zip applied to make sure we have the same version for testing.
Title: Re: OpenB3D Questions
Post by: markcwm on January 23, 2019, 01:46:05
Bummer. Okay since i can't reproduce try this please. Goto openb3dlib.mod/openb3d/src/material.cpp line 458
if (brush->tex[ix]==0 && surf->brush->tex[ix]==0 && Shader_Tex[ix]==0) return; // fixes crash if no textures
and comment that and replace with just "return;" and rebuild (without -a for quick build). Then uncomment your ShadeSurface and test, it shouldn't crash then.

If that works then try debugging so go to the top of material.cpp and add #include <stdio.h> then before the same return add printf("%p %p %p \n",brush->tex[ix],surf->brush->tex[ix],Shader_Tex[ix]); and replace the return with the commented line above, build that and run until it crashes, then post the bottom 30 lines of the output window, hopefully there will be some (Nil) pointers. Thanks.
Title: Re: OpenB3D Questions
Post by: Krischan on January 23, 2019, 07:45:41
Mark, I hope I followed your instructions correctly (it's early in the morning here ;D ). Commenting line 458 leads to the same result like commenting the two shadesurface commands - the models stay while all other textures vanish. Reloading is possible then.

Sometimes it loads the first level, sometimes it crashes without a warning, perhaps because there is too much output to the console window (the whole system hangs then for a while).

I've added some Screenshots including the complete log of a successful debug run trying to load the next level. I hope you can see the problem, I see only a bunch of digits ???
Title: Re: OpenB3D Questions
Post by: markcwm on January 24, 2019, 03:30:10
Hi Krischan,

thanks for the output window text, I've a new fix up for this ShadeSurface no tex bug. Your debug shows first if there's a shadertex, then brushtex, then surfacetex, it suggests you're not applying a ShaderTexture at all, so that may be a bug in your BSP code but it still shouldn't crash. I didn't notice until now but TurnOn was changed in Openb3d 1.25 and a small mistake made which should now be 100% fixed, but if it still crashes goto material.cpp line 459 and edit it to be just: if(Shader_Tex[ix]==0) break;

here's a screenie of the text bug, it appears after reloading a level but not at first load, it seems to keep to the same letter all the time but the color of the block often changes to black/purple or white.
(https://www.syntaxbomb.com/gallery/39_24_01_19_3_10_08.jpeg)

Title: Re: OpenB3D Questions
Post by: Krischan on January 26, 2019, 00:47:53
Mark, I hate to say it but it still crashes here - there must be another problem. The question is why the April 30 version works. On the other hand, I've never seen the bug in your screenshot and I can't explain what could be wrong there. So why is only the "T" missing here? This makes no sense. It's a simple TTF font converted to OTF and using LoadImageFont, nothing special.
Title: Re: OpenB3D Questions
Post by: markcwm on January 26, 2019, 04:44:26
Hi Krischan,

okay, I just noticed a bug in Surface constructor where vbo_id[] is set out of bounds, that may be crashing things for you. I also added new code to shader TurnOn which should be correct in theory and works here.

The text bug happens with other letters too, it just seems to be random, it may be something wierd in my Blitzmax install, I'll rebuild modules and see if it goes away.
Title: Re: OpenB3D Questions
Post by: Krischan on January 27, 2019, 22:33:19
Crash ;D Is there any way that I can help you debugging this? All other OpenGL games work perfect, even the very old RTCW or ET. Do you test on nVidia or Ati? And you're using my Blitzmax setup?
Title: Re: OpenB3D Questions
Post by: markcwm on January 28, 2019, 02:28:20
Hi Krischan,

yes that's disappointing! Well simplifying problems is always best, so can you confirm this crash is with the latest commit which is now fix 5 for this issue. To help you could run all shader examples in openb3dmax.docs to see if any crash, also you could test the texture loader in standard/lightmap, etc. Then you could go to material.cpp and at line 458 add a newline and paste:
if(Shader_Tex[ix]==0) break;
What happened was Angros added code for brush and surface.brush properties to Shader::TurnOn which is still there but I've tried to make it safe. I don't really understand why he did this as a normal texture shouldn't really be used as a shader texture if not specified. The next step is to just revert to the old version.
Title: Re: OpenB3D Questions
Post by: Krischan on January 28, 2019, 07:26:16
Hi Mark,

yes, I always use the latest commit. I've run all shader samples now in Debug mode, they work perfect except this one:

pixellight2.bmx crashes in line 54 (BrushFX) and according to debuglog in the function Shadesurface. Uncommenting Line 53-55 shows the tree, pressing P two times = crash. Hmm, sounds common? ;-)

The textureloader seems to work. Adding the line to material.cpp has no effect at all.
Title: Re: OpenB3D Questions
Post by: markcwm on January 30, 2019, 03:14:43
Hi Krischan,

Hah, yes too common really! :P Well in this case the example is just referencing the wrong surface, so that's fixed now.

Thanks for testing, strange that the edit to material.cpp doesn't work when a return in the same place did, I have reverted Shader::TurnOn to the earlier (Apr 30) version, I also fixed a bug in LoadTexture, ApplyAlpha was accessing pixels outside bounds. There was also some bones code commented out in TB3D and I never noticed, animations I tested worked though.

I added a new CollapseAnimMesh for LoadMesh because it seemed to not be working properly, at least on 3ds files, the new function is working much better. It also transforms mesh vertices in case they have entity positions. T3DS has had it's multi-surface code removed now that CollapseAnimMesh works.
Title: Re: OpenB3D Questions
Post by: Krischan on January 30, 2019, 18:17:55
There is an error compiling the current version in TSurface.bmx;151;3. Unable to convert from 'Byte Ptr' to 'String'

As it is only a debug function and I didn't know how to fix it I've REMarked the whole function to test the reverted shader functions - and guess what? It WORKS reloading the level, including the models and MSI Afterburner. Great. :o And the pixellight2.bmx example works too.
Title: Re: OpenB3D Questions
Post by: markcwm on February 01, 2019, 00:12:27
Hi Krischan,

well that's a relief as I was beginning to wonder if I was ever going to fix that! :o

The string error is a BRL Bmax issue where you have to cast byte ptr to int, NG Bmax doesn't need that, I think it might auto-cast pointers. I added a StringPtr function for the fix.

Well I've a new commit fixing a few more things, first the previous ApplyAlpha fix was bad, it was a for..until loop and I thought it was a for..to loop so I added -1 which left alpha textures with 2 black edges.

Then I added alpha to LightMesh, it takes the value from EntityAlpha or BrushAlpha.

The other fix is for vertex colors and normals render states, I've let the library completely manage vertex colors, this was the only way I could find to fix your Starfield demo where it lost vertex colors after loading and also the samples/fakelight example. So there should be no need for SetBlend ALPHABLEND at init now.

For normals, I disabled them in the library and manage them from Bmax in BeginMax2d, the problem was that the metal torches with reflection maps in Romanbath.b3d were blank if managed by the library.
Title: Re: OpenB3D Questions
Post by: markcwm on February 02, 2019, 05:07:20
Hi Krischan,

I've another small update, but nothing for the CopyEntity issue as I don't understand the problem yet.

CameraViewport is like in Minib3d now, I'm not sure if this fixes your problem as it seems to work the same for me. CameraPick and BackBufferToTex were also changed, all in the library instead of the wrapper.

DebugObject for Texture and Brush were added.

A fix for tex.gltex which wasn't working for normal single-frame textures.

A slight change to Graphics3D, GraphicsInit is now after the library function, as it should store the render states but it didn't seem to make any difference.
Title: Re: OpenB3D Questions
Post by: Krischan on February 03, 2019, 13:08:15
There is still no crash, but a new bug in LOF: switching the resolution with keys 1-4 creates a "black bar" on the screen and the camera positioning goes wrong. This worked before.

Engine workflow: Key Press > call SetResolution(x,y) in main file > function SetResolution in include/system.bmx > calls SetGadgetShape, CameraViewport, CameraZoom

Title: Re: OpenB3D Questions
Post by: markcwm on February 04, 2019, 05:30:18
Hi Krischan,

QuoteThere is still no crash, but a new bug in LOF: switching the resolution with keys 1-4 creates a "black bar" on the screen and the camera positioning goes wrong. This worked before.

Engine workflow: Key Press > call SetResolution(x,y) in main file > function SetResolution in include/system.bmx > calls SetGadgetShape, CameraViewport, CameraZoom

well this isn't actually a bug in Openb3dmax, it's because you're not updating TGlobal.height[0]=height before CameraViewport, so either do that in TCam Update() or System SetResolution().

It worked before because CameraViewport was bottom-up OpenGL coords, I tested with minib3d/tex_render and it's now top-down screen coords like Minib3d. To invert we need to use "vy=TGlobal.height-h-vy" which is why it has to be updated when switching graphics resolution.

I've pushed a commit with some convenience functions to help make this clearer, they are GlobalResolution(w,h) to set, and GlobalWidth, GlobalHeight to get. I also moved GraphicsInit back to where it was, before states are set in Global::Graphics.
Title: Re: OpenB3D Questions
Post by: Krischan on February 04, 2019, 07:53:05
That's why I wrote "a bug in LOF" ;D Adding TGlobal.Height[0] = Height or GlobalResolution(width, Height) to the TCam Update() function fixed the problem, thanks.

But there is another issue I can't fix without your help. Switch to higher resolutions (keys 3,4) and the second magic sphere camera and the hand light vanish. Going back to lower resolutions (1,2) and they are there again. Hmm... They are stored in the MINIMAP_CAMERA and MINIMAP_HANDLIGHT variables, init at GUI.bmx, function InitMinimap(), update occurs in TPlayer.bmx UpdateMinimap() function using the BackBufferToTex() function. Z-Order is off for the hand pivot children to make the hand visible over the rest of the 3D stuff. The compass (switch with key M) works. Could be a problem grabbing the texture in a higher resolution with wrong camera settings.
Title: Re: OpenB3D Questions
Post by: markcwm on February 06, 2019, 00:14:00
Hi Krischan,

well I get the spheremap on keys 1,2 and 4 but not on 3 where it's also not even shown on screen, I had to drop the camera zoom to see it. I found out the resolution you're setting wasn't right, when I changed 1920,1200 to 1920,1080 then the spheremap worked.
Title: Re: OpenB3D Questions
Post by: Krischan on February 06, 2019, 19:32:34
I think I must rethink my second camera concept. Strange enough it worked before but it fails now in higher resolutions. The texture grabbing seems to work, it looks like the camera position goes totally wrong but I dunno why. When I start the game from the beginning in the higher resolutions (the ones which fail later) - everything is fine, until I switch to a lower and back.

EDIT: I think I've found a workaround. I must call CameraViewport(MINIMAP_CAMERA, 0, 0, MINIMAP_RESOLUTION, MINIMAP_RESOLUTION) in the PositionMinimap() function which is called in the SetResolution() function. It only repositions the hand according to the current/new aspect ratio. But the MINIMAP_RESOLUTION value never changes even after switching the resolution (it is always 512) so it shouldn't be necessary there.
Title: Re: OpenB3D Questions
Post by: markcwm on February 12, 2019, 03:52:07
Quote2) Line 111 / 257 / TQuad Type: why are the vertex coordinate changes in CopyEntity not copied to all children meshes live like in MiniB3D? I manipulate the quads only in the source mesh, but the copies are ignored? Is it a bug? Or still not implemented? This is IMHO a very important feature of 3D graphics.

Hi Krischan,

I've fixed CopyEntity in the latest commit, Angros had it working with RepeatMesh but he made a mistake with CopyEntity thinking it was CopyMesh that did instancing in Blitz3d but it's not, well that or the docs are wrong.

So I made CopyMesh what CopyEntity was and made CopyEntity instance surfaces, this causes issues when using FreeEntity, I tried managing it with a list of surfaces but it was too complex so I decided the rule is you can't free a mesh before the copies or it will crash (unless you free them all at the same time).

CopyMesh in Minib3d doesn't copy entity data so I replaced it. Then RepeatMesh instances both surfaces and anim surfaces, I'm not sure what Angros was doing there as animation appears to not be smooth, but it works with FreeEntity now.
Title: Re: OpenB3D Questions
Post by: Krischan on February 12, 2019, 21:00:32
That's good news Mark - instancing is very important. A quick miniB3D/OpenB3D comparison shows 108FPS vs. 133FPS @ 3840x1600 here - so OpenB3D is about 25% faster. Great. I only had to fix the code in Line 739 in the initial post to make it work again to CameraViewport tempcam, 0, 0, size, size.

What's not so great: LOF crashes again loading the next level (last Log entry is "Shaders deleted") :-((( Debug Error is "EXCEPTION BREAKPOINT" in the TEntity -> FreeEntity Method.

Another thing which is not a bug in OpenB3D but perhaps you or somebody else knows the answer - the OpenB3D starfield demo is not running smoothly, it has some kind of microstuttering when moving. I've played around with many of the nVidia settings but nothing helped. Flip true or false makes no difference, Fast/Quality settings neither. The MiniB3D demo has the same problem. But: starting a game like Everspace (D3D) or the old Wolfenstein Enemy Territory (OpenGL) with the same settings always run incredible smooth. The stuttering is best visible when moving the mouse around while moving. What could be the problem here?

Here's the modifed code to run with the latest OpenB3D commit:

Code (Blitzmax) Select
SuperStrict

Import openb3dmax.B3dglgraphics

Graphics3D DesktopWidth() / 1.0, DesktopHeight() / 1.0, 32, 2

ClearTextureFilters()

Global STARS:Int = 50000        ' number of stars per cluster part
Global DIMENSION:Int = 2000     ' cluster dimension
Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
Global SPEED:Float = 1.0        ' overall move speed multiplicator
Global BRAKE:Float = 0.95       ' brake multiplicator
Global VSYNC:Int = True        ' Vertical Sync
Global HOMING:Int = True        ' turn homing on/off
Global COLORED:Int = False      ' colorize clusters
Global TEXTURED:Int = True      ' use star texture
Global Scale:Float = 0.5        ' star scale factor
Global FADE:Int = True          ' fade distant clusters
Global INSTANCING:Int = True    ' duplicate source mesh

Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene

If DEBUGLEVEL > 0 Then

STARS = 1000
Scale = 1.6
DISTRIBUTION = 0.5
INSTANCING = False

If DEBUGLEVEL > 1 Then

COLORED = True
TEXTURED = False

If DEBUGLEVEL > 2 Then

HOMING = False
FADE = False

EndIf

EndIf

EndIf

' ----------------------------------------------------------------------------
' Global variables
' ----------------------------------------------------------------------------
Global localx:Float, localy:Float, localz:Float
Global globalx:Float, globaly:Float, globalz:Float
Global simx:Float, simy:Float, simz:Float
Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float

Global FPS:TFPS = New TFPS
Global MS:Int = MilliSecs()

' ----------------------------------------------------------------------------
' Init scene
' ----------------------------------------------------------------------------
Global masterpivot:TPivot = CreatePivot()

Global cam:TCamera = CreateCamera()
CameraRange cam, 1, DIMENSION * 8
PositionEntity cam, 0, 0, 0

Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
TextureBlend tex, 3

' ----------------------------------------------------------------------------
' Duplicate Quad mesh in a 9x9x9 matrix
' ----------------------------------------------------------------------------
Global meshlist:TList = CreateList()
Global quadlist:TList = CreateList()
Global quadsourcelist:TList = CreateList()
Global lx:Float, ly:Float, lz:Float

Local entities:TEntity[9, 9, 9]
Local meshes:TMesh[9, 9, 9]

Local mesh:TMesh

' star cluster properties
mesh = CreateMesh()
EntityFX mesh, 1 + 2
EntityBlend mesh, 3
If TEXTURED Then EntityTexture mesh, tex
HideEntity mesh

' create blueprint star cluster
For Local i:Int = 1 To STARS

CreateStar(mesh)

Next

' fix for OpenB3D to enable Texture Blending and Alpha?
SetBlend ALPHABLEND

' create 5x5x5 = 125 cluster
For Local x:Int = 0 To 4 Step 1

For Local y:Int = 0 To 4 Step 1

For Local z:Int = 0 To 4 Step 1

' create a mesh and duplicate its properties = FAST
If INSTANCING Then

entities[x, y, z] = CopyEntity(mesh)

PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)

Else

EntityColor entities[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, entities[x, y, z])

' create many unique meshes without instancing = SLOW
Else

' new mesh
meshes[x, y, z] = CreateMesh()
EntityFX meshes[x, y, z], 1
EntityBlend meshes[x, y, z], 3
If TEXTURED Then

EntityTexture meshes[x, y, z], tex
EntityFX meshes[x, y, z], 1 + 2

EndIf

' duplicate blueprint cluster
For Local s:TQuad = EachIn quadsourcelist

Local q:TQuad = New TQuad

q.mesh = meshes[x, y, z]
q.x = s.x
q.y = s.y
q.z = s.z
q.scalex = s.scalex
q.scaley = s.scaley
q.RGB = s.RGB

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)

Next

PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION

If COLORED Then

EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)

Else

EntityColor meshes[x, y, z], 255, 255, 255

EndIf

ListAddLast(meshlist, meshes[x, y, z])

EndIf

RenderWorld

Flip False

Next

Next

Next

' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
MouseX()
MouseY()
MouseXSpeed()
MouseYSpeed()
Flip

Global timer:TTimer = CreateTimer(60)

MS = MilliSecs() - MS

' ----------------------------------------------------------------------------
' Main Loop
' ----------------------------------------------------------------------------
While Not AppTerminate()

If KeyHit(KEY_ESCAPE) Then End

' axis rotation
Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)

' XYZ movement
Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
Local turbo:Int = KeyDown(KEY_TAB)

If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1

If tadd < 0.01 Then tadd = 0.0

If Abs(xmove) Then xadd:+0.01
If Abs(ymove) Then yadd:+0.01
If Abs(zmove) Then zadd:+0.01
If Abs(roll) Then radd:+0.025
If Abs(turbo) Then tadd:+0.05

xadd:*1.025
yadd:*1.025
zadd:*1.025
radd:*1.025
tadd:*1.025

If xadd > 2.0 Then xadd = 2.0
If yadd > 2.0 Then yadd = 2.0
If zadd > 2.0 Then zadd = 2.0
If radd > 1.5 Then radd = 1.5
If tadd > 25.0 Then tadd = 25.0

' calculate movespeed/rollspeed
If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
If Abs(roll) Then rspeed = radd * Sgn(roll)

' perform rotation and motion
Turn(cam, pitch, yaw, rspeed)
MoveEntity cam, xspeed, yspeed, zspeed

' keep camera at home
If HOMING Then Home(cam, masterpivot, DIMENSION)

' only the master instance quads are facing to the camera
For Local q:TQuad = EachIn quadlist

q.Update(cam)

Next

' fade mesh according to its distance
If FADE Then

For Local e:TEntity = EachIn meshlist

Local d:Float = EntityDistance(cam, e)
Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
EntityAlpha e, a

Next

EndIf

RenderWorld

FPS.Update()

' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
Begin2D()

DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
DrawText("Star Cluster: " + STARS, 0, 15)
DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)

End2D()

Flip VSYNC

' decrease speed
xspeed:*BRAKE
yspeed:*BRAKE
zspeed:*BRAKE
rspeed:*BRAKE

Wend

End

' creates a single star quad
Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)

Local q:TQuad = New TQuad

q.mesh = mesh
q.surf = surf

q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff

' randomized clustering
If Rnd(1) > 1 - DISTRIBUTION Then

Local d:Float = Rnd(0.0001, 0.05)

q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff

EndIf

q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
q.scaley = q.scalex

Local c:Float = (1.0 / q.scalex)
If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O

q.Add()
q.Update(cam)

ListAddLast(quadlist, q)
ListAddLast(quadsourcelist, q)

lx = q.x
ly = q.y
lz = q.z

End Function

' keeps the player in a predefined cubic area
Function Home(target:TEntity, world:TEntity, homesize:Int = 100)

' store Local player Position
Local localx:Double = EntityX(target)
Local localy:Double = EntityY(target)
Local localz:Double = EntityZ(target)

' Check X axis
While localx > homesize

globalx:+homesize
localx:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, -homesize, 0, 0

Wend

While localx < - homesize

globalx:-homesize
localx:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, homesize, 0, 0

Wend

' Check Y axis
While localy > homesize

globaly:+homesize
localy:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, -homesize, 0

Wend

While localy < - homesize

globaly:-homesize
localy:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, homesize, 0

Wend

' Check Z axis
While localz > homesize

globalz:+homesize
localz:-homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, -homesize

Wend

While localz < - homesize

globalz:-homesize
localz:+homesize
PositionEntity target, localx, localy, localz
MoveEntity world, 0, 0, homesize

Wend

' store simulated player Position
simx = localx + globalx
simy = localy + globaly
simz = localz + globalz

End Function

' ----------------------------------------------------------------------------
' Normalizes a value to given range
' ----------------------------------------------------------------------------
Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)

Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin

End Function

' ----------------------------------------------------------------------------
' Turn Entity using Quaternions
' ----------------------------------------------------------------------------
Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)

Local Pitch:Float = 0.0
Local Yaw:Float = 0.0
Local Roll:Float = 0.0

Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)

If Glob = False

Quat = EulerToQuat(EntityPitch(Ent, True), EntityYaw(Ent, True), EntityRoll(Ent, True))
Turn_Quat = EulerToQuat(X, Y, Z)
Quat = MultiplyQuats(Quat, Turn_Quat)
Quat = NormalizeQuat(Quat)
QuatToEuler2(Quat.x[0], Quat.y[0], Quat.z[0], Quat.w[0], pitch, yaw, roll)
RotateEntity Ent, pitch, yaw, roll

Else

RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z

EndIf

End Function

' ----------------------------------------------------------------------------
' Euler to Quaternion
' ----------------------------------------------------------------------------
Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)

Local cr:Float = Cos(-roll / 2.0)
Local cp:Float = Cos(pitch / 2.0)
Local cy:Float = Cos(yaw / 2.0)
Local sr:Float = Sin(-roll / 2.0)
Local sp:Float = Sin(pitch / 2.0)
Local sy:Float = Sin(yaw / 2.0)
Local cpcy:Float = cp * cy
Local spsy:Float = sp * sy
Local spcy:Float = sp * cy
Local cpsy:Float = cp * sy

Local q:TQuaternion = NewQuaternion()

q.w[0] = cr * cpcy + sr * spsy
q.x[0] = sr * cpcy - cr * spsy
q.y[0] = cr * spcy + sr * cpsy
q.z[0] = cr * cpsy - sr * spcy

Return q

End Function

' ----------------------------------------------------------------------------
' Quaternion to Euler
' ----------------------------------------------------------------------------
Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)

Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31

Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
Local cost_temp:Float = 1.0 - (sint * sint)
Local cost:Float

If Abs(cost_temp) > QuatToEulerAccuracy

cost = Sqr(cost_temp)

Else

cost = 0.0

EndIf

Local sinv:Float, cosv:Float, sinf:Float, cosf:Float

If Abs(cost) > QuatToEulerAccuracy

sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost

Else

sinv = (2.0 * w * x) - (2.0 * y * z)
cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
sinf = 0.0
cosf = 1.0

EndIf

pitch = ATan2(sint, cost)
yaw = ATan2(sinf, cosf)
roll = -ATan2(sinv, cosv)

End Function

' ----------------------------------------------------------------------------
' Multiply Quaternion
' ----------------------------------------------------------------------------
Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)

Local q:TQuaternion = NewQuaternion()

q.w[0] = q1.w[0] * q2.w[0] - q1.x[0] * q2.x[0] - q1.y[0] * q2.y[0] - q1.z[0] * q2.z[0]
q.x[0] = q1.w[0] * q2.x[0] + q1.x[0] * q2.w[0] + q1.y[0] * q2.z[0] - q1.z[0] * q2.y[0]
q.y[0] = q1.w[0] * q2.y[0] + q1.y[0] * q2.w[0] + q1.z[0] * q2.x[0] - q1.x[0] * q2.z[0]
q.z[0] = q1.w[0] * q2.z[0] + q1.z[0] * q2.w[0] + q1.x[0] * q2.y[0] - q1.y[0] * q2.x[0]

Return q

End Function

' ----------------------------------------------------------------------------
' Normalize Quaternion
' ----------------------------------------------------------------------------
Function NormalizeQuat:TQuaternion(q:TQuaternion)

Local uv:Float = Sqr(q.w[0] * q.w[0] + q.x[0] * q.x[0] + q.y[0] * q.y[0] + q.z[0] * q.z[0])

q.w[0] = q.w[0] / uv
q.x[0] = q.x[0] / uv
q.y[0] = q.y[0] / uv
q.z[0] = q.z[0] / uv

Return q

End Function

' ------------------------------------------------------------------------------------------------
' Quad Type
' ------------------------------------------------------------------------------------------------
Type TQuad

Field x:Float = 0.0 ' position x
Field y:Float = 0.0 ' position y
Field z:Float = 0.0 ' position z

Field row:Int = 0 ' texture row
Field col:Int = 0 ' texture column

Field scalex:Float = 1.0 ' current size X
Field scaley:Float = 1.0 ' current size Y

Field RGB:Int[] = [255, 255, 255] ' Vertex Color
Field Alpha:Float = 1.0 ' Vertex Alpha

Field v:Int = 0 ' vertex counter
Field mesh:TMesh = Null ' mesh pointer
Field surf:TSurface = Null ' surface pointer

' --------------------------------------------------------------------------------------------
' METHOD: Add new Quad
' --------------------------------------------------------------------------------------------
Method Add(col:Int = 0, row:Int = 0)

Local s:Int = CountSurfaces(mesh)
If s = 0 Then

surf = CreateSurface(mesh)

Else

surf = GetSurface(mesh, s)

EndIf

Local i:Int = CountVertices(surf)
If i + 4 > 32768 Then

surf = CreateSurface(mesh)
v = 0

EndIf

' add Vertices
Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)

' color vertices
VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha

' connect triangles
AddTriangle surf, V0, V1, V2
AddTriangle surf, V0, V2, V3

VertexTexCoords surf, V0, col + 1, row
VertexTexCoords surf, V1, col + 1, row + 1
VertexTexCoords surf, V2, col, row + 1
VertexTexCoords surf, V3, col, row

' increase vertex counter
If v >= 4 Then v = V0 + 4 Else v = V0

End Method

' --------------------------------------------------------------------------------------------
' METHOD: Update a Quad
' --------------------------------------------------------------------------------------------
Method Update(target:TEntity)

TFormVector scalex, 0, 0, target, Null
Local X1:Float = TFormedX()
Local Y1:Float = TFormedY()
Local Z1:Float = TFormedZ()

TFormVector 0, scaley, 0, target, Null
Local X2:Float = TFormedX()
Local Y2:Float = TFormedY()
Local Z2:Float = TFormedZ()

' set vertices
VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2

End Method

End Type

' ------------------------------------------------------------------------------------------------
' Exact FPS counter
' ------------------------------------------------------------------------------------------------

Type TFPS

Global renders:Int = 0

Field FPS:Int = 60 ' current FPS value
Field interval:Int = 999
Field averagefps:Int = 60 ' average FPS value
Field framedrops:Int = 0 ' dropped frames
Field oldlooptime:Int = 0
Field looptime:Int = 0
Field multi:Float ' main loop multiplicator

Field old:Int = MilliSecs()
Field totalfps:Int = 30
Field Ticks:Int

' --------------------------------------------------------------------------------------------
' METHOD: Update FPS counter
' --------------------------------------------------------------------------------------------
Method Update()

renders:+1

looptime = MilliSecs() - oldlooptime
oldlooptime = MilliSecs()

If MilliSecs() - old >= interval Then

old = MilliSecs()

FPS = renders * (1000 / interval)
renders = 0
totalfps:+FPS
Ticks:+1

averagefps = totalfps / Ticks

EndIf

End Method

End Type

' Create a stunning star texture
Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)

Local i:Float, j:Int, col:Int, rgb:Int
Local x:Int, y:Int

Local w:Int = GraphicsWidth()

Local tempcam:TCamera, tempsun:TPivot
Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
Local tex:TTexture = CreateTexture(size, size, 1 + 8)

For j = 0 To (size / 2) - 1

col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
If col > 255 Then col = 255
rgb = col * $1000000 + col * $10000 + col * $100 + col

For i = 0 To 360 Step 0.1

WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)

Next

Next

PixmapToTexture(pixmap, tex)
SavePixmapPNG(pixmap, "proceduralstar1.png", 0)

' temp camera
tempcam = CreateCamera()
CameraRange tempcam, 1, w * 2

' fix for OpenB3D to simulate MiniB3D's Cameraviewport handling
CameraViewport tempcam, 0, 0, size, size

' temp pivot
tempsun = CreatePivot()

' Create 4 body quads
CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)

' create 4 ray quads
Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)

' rescale and rotate rays
ScaleEntity ray1, size * 2, size / 32, size
ScaleEntity ray2, size / 32, size * 2, size
ScaleEntity ray3, size, size / 32, size
ScaleEntity ray4, size, size / 32, size
RotateEntity ray3, 0, 0, 45
RotateEntity ray4, 0, 0, 135

PositionEntity tempsun, 0, 0, w

' render star
RenderWorld
RenderWorld

' grab image
pixmap = GrabPixmap(0, 0, size, size)
For x = 0 To size - 1

For y = 0 To size - 1

rgb = ReadPixel(pixmap, x, y)

r = (rgb & $ff0000) / $10000
g = (rgb & $ff00) / $100
b = (rgb & $ff)

' rgb
rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b

WritePixel(pixmap, x, y, rgb)

Next

Next

PixmapToTexture(pixmap, tex)
'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)

' Delete pixmap, pivot and temp cam
pixmap = Null
FreeEntity tempsun
FreeEntity tempcam

Return tex

End Function

' custom quad creation
Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)

Local mesh:TMesh = CreateMesh()
Local surf:TSurface = CreateSurface(mesh)
Local v0:Int, v1:Int, v2:Int, v3:Int

v0 = AddVertex(surf, 1, 1, 0, 0, 0)
v1 = AddVertex(surf, -1, 1, 0, 1, 0)
v2 = AddVertex(surf, -1, -1, 0, 1, 1)
v3 = AddVertex(surf, 1, -1, 0, 0, 1)

AddTriangle surf, v0, v1, v2
AddTriangle surf, v0, v2, v3

If parent Then EntityParent Mesh, parent
If fx Then EntityFX Mesh, fx
If tex Then EntityTexture Mesh, tex
If blend Then EntityBlend Mesh, blend

EntityColor Mesh, r, g, b
EntityAlpha Mesh, a

VertexColor surf, v0, r, g, b, a
VertexColor surf, v1, r, g, b, a
VertexColor surf, v2, r, g, b, a
VertexColor surf, v3, r, g, b, a

ScaleEntity Mesh, Scale, Scale, Scale

Return Mesh

End Function

' creates a texture from a pixmap
Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)

If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)

' OpenB3D only function to copy pixmap to texture
BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)

' MiniB3D workaround to copy pixmap to texture
'glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
'gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))

End Function

' --------------------------------------------------------------------------------
' Fixed BeginMax2D()
' --------------------------------------------------------------------------------
Function Begin2D()

Local x:Int, y:Int, w:Int, h:Int
GetViewport(x, y, w, h)

'glPopClientAttrib()
'glPopAttrib()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_TEXTURE)
glPopMatrix()
glMatrixMode(GL_COLOR)
glPopMatrix()

glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glDisable(GL_SCISSOR_TEST)
glDisable(GL_FOG)
glDisable(GL_CULL_FACE)

glMatrixMode GL_TEXTURE
glLoadIdentity

glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1

glMatrixMode GL_MODELVIEW
glLoadIdentity

SetViewport x, y, w, h

Local MaxTex:Int
glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))

For Local Layer:Int = 0 Until MaxTex

glActiveTexture(GL_TEXTURE0+Layer)

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)

Next

glActiveTexture(GL_TEXTURE0)

glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
glScissor(0, 0, GraphicsWidth(), GraphicsHeight())

glEnable GL_BLEND
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glEnable(GL_TEXTURE_2D)

End Function

' --------------------------------------------------------------------------------
' Fixed EndMax2D()
' --------------------------------------------------------------------------------
Function End2D()

' save the Max2D settings for later
'glPushAttrib(GL_ALL_ATTRIB_BITS)
'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glMatrixMode(GL_TEXTURE)
glPushMatrix()
glMatrixMode(GL_COLOR)
glPushMatrix()

glDisable(GL_TEXTURE_CUBE_MAP)
glDisable(GL_TEXTURE_GEN_S)
glDisable(GL_TEXTURE_GEN_T)
glDisable(GL_TEXTURE_GEN_R)

glDisable(GL_TEXTURE_2D)
glDisable(GL_BLEND)

TGlobal.EnableStates()
'glDisable(GL_TEXTURE_2D)

' only needed for OpenB3D
TGlobal.alpha_enable[0] = 0 ' alpha blending was disabled by Max2d (GL_BLEND)
TGlobal.blend_mode[0] = 1 ' force alpha blending
TGlobal.fx1[0] = 0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
TGlobal.fx2[0] = 1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)

glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)

glClearDepth(1.0)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)

glAlphaFunc(GL_GEQUAL, 0.5)

' only needed for OpenB3D
For Local cam:TCamera=EachIn TCamera.cam_list

' active camera - was if cam.hide[0]=0
If cam = TGlobal.camera_in_use

' fog with Max2d fix
cam.UpdateFog()
Exit

EndIf

Next

End Function


Title: Re: OpenB3D Questions
Post by: markcwm on February 13, 2019, 03:52:47
QuoteWhat's not so great: LOF crashes again loading the next level (last Log entry is "Shaders deleted") :-((( Debug Error is "EXCEPTION BREAKPOINT" in the TEntity -> FreeEntity Method.

Hi Krischan,

well I thought this was due to deleting surfaces but it seems not, I uncommented the code to delete bones, now I see why it was commented. :) So a quick fix, is goto mesh.cpp line 331 in FreeEntity and comment out "delete bone". This should be in though so I'll have to have a go at fixing it properly.

Re: microstuttering, I don't really follow you, are you sure it's not just low FPS?
Title: Re: OpenB3D Questions
Post by: Krischan on February 13, 2019, 07:47:00
Uncommenting didn't help. The Feb 9, 2019 commit (Added DebugFields/Globals, TVector wrapped, Terrain vertices) and the second Feb 10, 2019 commit (Fix CopyEntity causing FreeEntity crash) work, the latest one and the first Feb 10, 2019 commit (Fixed CopyEntity not instancing, CopyMesh now full copy) crash.

And do you think that 133FPS @ 3840x1600 is too low? :o

EDIT: Anyway, we shouldn't pay too much attention to the microstutters as it could be related to my GPU/Display combination. Such a large display can have unwanted side effects unless it has 144Hz (I have "only" 75Hz)
Title: Re: OpenB3D Questions
Post by: markcwm on February 14, 2019, 05:07:04
I'm sure the latest crashes are due to me un-commenting the delete bones code in Mesh::Freeentity, as I've been able to reproduce it with LOF and fix it by removing that code, the bones are stored in the entity child_list and also in the mesh bones list, which is what I didn't realize, so yeah it was double freeing. That was a bit stupid of me, oh well I learned some new stuff.
Title: Re: OpenB3D Questions
Post by: Krischan on February 15, 2019, 10:17:28
Your latest commit fixed it again. So what problems are left, I've lost track of things ??? I think it is only point 5) with the barely noticeable moving of the mouse pointer after centering (Line 187 ff.)

Change the lines like this and the mouse is moving:

Code (Blitzmax) Select
' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2)' ; Flip
'MouseX()
'MouseY()
'MouseXSpeed()
'MouseYSpeed()
'Flip
Title: Re: OpenB3D Questions
Post by: markcwm on February 15, 2019, 14:03:55
Phew, that's great, thanks Krischan! :)

Re: MouseMove, I don't think this is a bug at all, when you use the mouse to move the camera you have to do that sort of thing to take control, there are demos in Blitz3d that do the same thing.

Edit: also I notice DrawText doesn't work with the current BeginMax2d, this is because it needs GL_TEXTURE_2D enabled, GLDrawText doesn't so I'll push that fix with the next feature, which will be Minib3d's AntiAlias code.
Title: Re: OpenB3D Questions
Post by: Krischan on February 15, 2019, 14:36:45
Well, the code worked in miniB3D without a workaround like Flip/Reset/Flip :P The problem is when the program starts and the user takes no action there is movement where it shouldn't.
Title: Re: OpenB3D Questions
Post by: markcwm on February 17, 2019, 00:25:16
Quote5) Line 205-206: in OpenB3D the mouse pointer moves slightly after initialization, this can only be fixed by NOT subtracting -1 in GraphicsHeight() - in MiniB3D it works (and would also be mathematically correct) - is it a rounding bug?

Hmm, well I had another look at this. I can't really follow your GraphicsHeight-1 fix but I think you mean for the pitch/yaw variables. I found no difference subtracting -1 and I found no difference at all between Minib3d and Openb3d, also there's not really anything I can do about this as they are Brl.System commands, but if you place MoveMouse before the first Renderworld then you don't see the jump, although you do see the mouse pointer move.
Title: Re: OpenB3D Questions
Post by: Krischan on February 17, 2019, 01:29:59
Hmm looks you're right - I can't reproduce it here now. I swear I had this problem on my old rig and checked it many times. Anyway, I've fixed it now in my code by checking too small numbers:

If Abs(pitch) < 0.005 Then pitch = 0
If Abs(yaw) < 0.005 Then yaw = 0

Well I think afaik all known bugs are fixed now. Time for new bugs, we're running out of bugs ;D
Title: Re: OpenB3D Questions
Post by: markcwm on February 17, 2019, 04:29:09
I tried the pitch/yaw fix but it still moved at render init, it might have been an issue on a previous version but it's good to know it's now working like Minib3d.

I'm really happy I could fix all these bugs and thanks to you Krischan for your assistance and persistence which I'm sure was not easy. I don't really thank people enough for their help fixing these bugs some people have been amazingly helpful in the past, I think good feedback can be as valuable as the fix.

I'm glad you can now carry on with your project which I think looks great, although maybe we should look at fixing that bumpmap issue, what shader are you using, is it test.frag?

Also, Minib3d's AntiAlias is now in with the latest commit and example, it's the same speed as in Minib3d but quite slow compared to the shader fxaa example by RonTek.
Title: Re: OpenB3D Questions
Post by: Krischan on February 17, 2019, 12:00:52
No Mark, I have to thank you. With OpenB3D, my project looks much better than all MiniB3D tests before. Optimizing the shader is a good idea, yes it is test.frag. I'm still not very good writing shaders and this one became complex. I'd like to have a shader style like in "Legend of Grimrock" (it looks very similar but the name is a coincidence and my game will work different than LOG), with nice lighting and shadows but I never achieved it, not even close. So more help is welcome and appreaciated.

As you can see in the test.frag I'm using Distance Fog, Tone Mapping, some kind of flashlight illumination/attenuation and a fake bumpmap to create depth. It looks somehow nice but is far away from a really good looking shader. And I had problems to make the shadows work with my level geometry.

I think another important point are very good normal textures, I'm using my own "Legend of Faerghail Normalmap Generator.bmx" to save time by converting a diffuse map into a normalmap, but all normalmap textures should be drawn by hand according to the diffuse map to have better detail (though my tool already creates nice results in a single mouseclick). To make it work again you must comment the "Import brl.d3d9max2d" and uncomment the "Import brl.glmax2d" line, I don't know what happened there (I'm getting a _d3dDev.Reset failed)

https://www.youtube.com/watch?v=_HnTeQFBIq0
Title: Re: OpenB3D Questions
Post by: markcwm on February 23, 2019, 23:12:20
Hi Krischan,

yes that does look awesome, much better than LOF. I have been kind of distracted getting multisample antialiasing (for Windows) running and fixing several bugs with ClearWorld, which is still not finished.

I think the soft shadows there are shader based, I was talking to RonTek about this and he posted some code which I'll try to convert to Openb3dmax, here's the link (https://www.blitzcoder.org/forum/topic.php?id=156).
Title: Re: OpenB3D Questions
Post by: Qube on February 23, 2019, 23:20:01
@Krischan - That looks really impressive and highly professional, nice work indeed :)
Title: Re: OpenB3D Questions
Post by: Derron on February 23, 2019, 23:31:49
Quote from: Qube on February 23, 2019, 23:20:01
@Krischan - That looks really impressive and highly professional, nice work indeed :)

Are you talking about the screenshots (Krischan's work) or the gameplay video (of another game) ?


bye
Ron
Title: Re: OpenB3D Questions
Post by: Qube on February 23, 2019, 23:43:22
QuoteAre you talking about the screenshots (Krischan's work) or the gameplay video (of another game) ?
Krischan's work of course. I do know that LOG is not his :P. I kinda missed this thread and only just read through it.
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 00:58:38
Thanks Qube, you should see it in action (if it runs, see PM). But I didn't make any progress in the last months as Mark and I had to find out and fix some nasty OpenB3D bugs first, which is this topic about.

And without Mark, it would not exist in this form. So thanks again to Mark for OpenB3D at this point ;D
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 01:15:42
Quote from: markcwm on February 23, 2019, 23:12:20yes that does look awesome, much better than LOF.
Very true, but it hurts :P. To distinguish the two games better I've switched the name to "Faerghail" only. Faerghail already looks nice but it could look even nicer. Perhaps you have an idea how to pimp it.

Quote from: markcwm on February 23, 2019, 23:12:20I think the soft shadows there are shader based, I was talking to RonTek about this and he posted some code which I'll try to convert to Openb3dmax, here's the link (https://www.blitzcoder.org/forum/topic.php?id=156).
Yes, Grimrock is using shaders for everything - and they have very nice and clean normalmaps (see attachment). For OpenB3D I would prefer a simple shadow solution that I could add to the game without having to rewrite much of it.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 01:39:33
QuoteThanks Qube, you should see it in action (if it runs, see PM).
Thanks for the PM :) - I wasn't aware of the original but was that an Amiga emulator in an exe? lol, so cool. Where are such magics from? ( so behind the times )

I tried your other zip file in both VM and native boot but each one failed unfortunately. They both got as far as showing the screen res options > loading splash screen with compass and then an "EXPECTION_ACCESS_VIOLATION" error.

I only have Windows 7 via VM and Windows 10 as a native boot so if you want me to install any bits and pieces or debug stuff then feel free to send as much as you want :)

*edit* - The other exe's in the zip file for the maps and stuff appeared to run fine though.
Title: Re: OpenB3D Questions
Post by: markcwm on February 24, 2019, 02:09:13
Qube, it could be the shader code, it only runs in GL 2.1.

Krischan, yeah don't get me wrong I think the art in Faergail is fine but it needs nicer bumpmapping code, which would be correct angle calculations and less glossy, maybe the lighting is a bit better too.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 02:24:31
QuoteQube, it could be the shader code, it only runs in GL 2.1.
Does that not work on Window 10?
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 11:19:11
Qube, it should work on a native system but not in a VM, perhaps VMware but I don't own it. Which graphics card do you have: ATI/nVidia/Model? GPU RAM size? Here it is working on Windows 10 x64 Pro 1809 with a nVidia RTX 2080/8GB, Driver version 417.71 which is not the newest but still new enough.

And yes, the Amiga emulator is WinUAE (here the old version 3.4) which comes in a single exe today, I've only renamed it. The harddrive setup was complex but it runs very good and fast. You can restore an old savegame like "Aktuell" or "Schloss" which is inside the castle to see the difference between the original and Faerghail. But don't expect too much, this game is 30 years old now, this is "gaming stone age".

Mark, I know the bumpmapping is not correct, there is much room for improvements or we should use a complete new shader. I was starting with the bumpmap2.frag example, wasn't happy with it and rewrote everything to meet my needs. But writing shaders, I'm still a newbie. They are hard to debug and there are a lot of mathemetics and procedures inside I don't understand yet.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 14:02:20
Windows 10 is native and not VM. I tried native first and then a VM but both failed. I have a few games installed on Windows 10 so all needed bits should be present.

GPU is a Radeon RX580 8GB which should be up to the task :)
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 15:15:30
Then it must be the shader itself as I can't check the game on a ATI card here (I can only debug the shader source using the included glslangvalidator.exe which says it has some errors inside but works so far, at least on my rig). I decided to keep Intel+nVidia for my new rig as this combination never made any problems (even if it is much more expensive than AMD) and got rid of all AMD stuff years ago. Perhaps I'll buy a smaller rig with AMD/ATI only for my wife in the future to test the games there, but not yet.

However, you can change the EXE with the attached one, which is a recompile with the basic.frag shader which has no compilation errors, perhaps it works. But it looks not so good like the test shader. Or fix the shader bug to make it run with ATI and recompile it with BlitzmaxOS and the latest OpenB3D by yourself, the full source is included. ;D
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 22:14:48
That one worked fine, thanks. Still looks really good without a fancy shader :)

QuoteI decided to keep Intel+nVidia for my new rig as this combination never made any problems (even if it is much more expensive than AMD)
Mine is a special Apple version in an iMac so it's super expensive for what it is :P
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 23:12:41
Good to hear that it works now. Looks like I have to put more effort into the shader QA. Ok, new release date for Faerghail is set to Fall 2059, after my funeral :o

I abandoned iMac after they decided to go for Intel+AMD, a bad combination IMHO - either one should use the overexpensive Intel+nVidia combo or go for the cheaper rebels from AMD instead. But don't mix it. And I still remember the problems I had back in 2001 with my Radeon 8500, never again, they've lost me as a customer forever.

My previous iMac was the Late 2013 (i7-4770+nVidia 780M) which is still a really good machine but after 5 years it became "too slow" for me (I know, first world problems :D) so I sold it and got my new rig which is really up to date now. And now as they'll go for ARM in the Macs, Apple is history to me. Good luck without Steve Jobs, I'm off.

If I want to take a look into Mojave I now start Virtualbox and there is my old system again (thanks to Disk2VHD) which is now encapsulated as a slave of Win10 :-D Was not that easy but it's working. But I'm working 99% on Windows, so it is merely a waste of SSD space, I've been just curious if it works.
Title: Re: OpenB3D Questions
Post by: Qube on February 25, 2019, 00:10:02
QuoteGood to hear that it works now. Looks like I have to put more effort into the shader QA. Ok, new release date for Faerghail is set to Fall 2059, after my funeral :o
Don't forget to post about it here :P

QuoteI abandoned iMac after they decided to go for Intel+AMD, a bad combination IMHO - either one should use the overexpensive Intel+nVidia combo
I'd of preferred Intel + nVidia too but I am impressed how well the RX580 preforms compared to my earlier iMac which had a pretty naff nVidia GPU ( 740M I think it was ). This is the first iMac that's actually decent at running modern games to any decent frame rate.

QuoteAnd now as they'll go for ARM in the Macs, Apple is history to me.
I'm not sure about that move as it'll mean the end to dual booting Windows and MacOS which many people do. Also for those who use Windows via Parallels will get screwed too as there is no way you're going to get perfect X86 emulation under ARM at anywhere near native speeds. It'll be a really dumb move if they do replace Intel CPU's with ARM ones.
Title: Re: OpenB3D Questions
Post by: Krischan on February 25, 2019, 06:00:30
Quote from: Qube on February 25, 2019, 00:10:02I am impressed how well the RX580 preforms compared to my earlier iMac which had a pretty naff nVidia GPU ( 740M I think it was ). This is the first iMac that's actually decent at running modern games to any decent frame rate.

Yes, even the Late 2013 was a gaming machine, too (with at least High Details in modern games). But the RTX 2080 is a beast and wants Ultra only, so I don't really miss it - like the 16:9 screen (21:9 is more immersive but hard to configure in older games) :P The ARM decision reminds me of Hitchhiker's Guide to the Galaxy:

"The story so far: In the beginning Apple switched to ARM. This has made a lot of people very angry and been widely regarded as a bad move." :P
Title: Re: OpenB3D Questions
Post by: Steve Elliott on February 25, 2019, 09:18:31
Quote
And now as they'll go for ARM in the Macs, Apple is history to me.

I'm not sure about that move as it'll mean the end to dual booting Windows and MacOS which many people do. Also for those who use Windows via Parallels will get screwed too as there is no way you're going to get perfect X86 emulation under ARM at anywhere near native speeds. It'll be a really dumb move if they do replace Intel CPU's with ARM ones.

"The story so far: In the beginning Apple switched to ARM. This has made a lot of people very angry and been widely regarded as a bad move." :P

That would be a very bad move IMO too.



Title: Re: OpenB3D Questions
Post by: Naughty Alien on February 25, 2019, 14:01:03
@Krischan

..those dungeons looks fantastic..very nice..
Title: Re: OpenB3D Questions
Post by: Krischan on March 01, 2019, 15:12:25
Thanks Naughty Alien, I hope you mean my project, not the LOG video (which looks even more fantastic). :))

Mark, I have another suggestion about an issue which is bugging me since MiniB3D, perhaps you have an elegant solution for this. In TTexture.bmx line 573-589 (https://github.com/markcwm/openb3dmax.mod/blob/master/openb3dmax.mod/inc/TTexture.bmx) a check is performed if a texture has been already loaded before and uses the loaded one if yes, like an instance. This is a nice feature to save VRAM but can bring the coder (me!) in trouble when you need to treat the same texture with two different blend modes. So when I'm loading a texture file and set its blend mode to 2 and load the same file again but with a different handle and set its blend mode to 3, the blend mode of the first texture handle becomes 3, too. That is bad.

I've avoided this by just eliminating the whole check in Line 574 with

Code (Blitzmax) Select
Local old_tex:TTexture'=tex.TexInList()

which makes every loaded texture unique, but I'm not happy with this solution as in other cases the check could be useful. Perhaps we can add a flag to the LoadTexture function or create a global function so switch it on/off before loading such a multi-role texture. You know what I mean?

EDIT: or a new function "CopyTexture" to copy an already loaded texture to a different, unique handle which is independant from the original texture.
Title: Re: OpenB3D Questions
Post by: markcwm on March 02, 2019, 04:21:16
Hi Krischan,

yes that's not something that occurred to me before, the simplest way round this is to save the same image with different filenames, but I have a fix uploaded now which uses your ideas, which is a good solution. So you use CopyTexture() and there's an internal global to disable TexInList() when copying, it works in the library as well as BMax.
Title: Re: OpenB3D Questions
Post by: Krischan on March 02, 2019, 11:00:42
Thanks Mark. But there is a new compile error:

Compile Error: Identifier 'glClearDepthf' not found
[c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/inc/TGlobal.bmx;268;3]
Build Error: failed to compile c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.bmx

As it fails on a single OpenGL command - do I need to update another module or is it O3D related?

Commenting this line shows a second error (and perhaps there can be more):

Compile Error: Unable to convert from 'Byte Ptr' to 'String'
[c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/inc/TTexture.bmx;1006;5]
Build Error: failed to compile c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.bmx

So I can't test it right now.
Title: Re: OpenB3D Questions
Post by: markcwm on March 02, 2019, 17:21:22
Hi Krischan,

sorry, I should have tested it in BRL BMax. It should be fixed now.

glClearDepthf isn't declared in BRL pub.glew (nor in Maxmods glew) but it is declared in NG pub.glew. I copied code from the library where it is declared from GLee.
Title: Re: OpenB3D Questions
Post by: Krischan on March 02, 2019, 21:29:20
Ok, works now - thanks! A question: I wondered if it is possible to have load flags like in LoadTexture in this function, like tex=CopyTexture(tex,1+2+8). If there are no new flags given, the flags of the original texture are used. This makes the function more flexible. Here's my attempt, if you think it is ok you can add it:

functions.bmx
Code (blitzmax) Select
Rem
bbdoc: Returns a copy of the new texture
End Rem
Function CopyTexture:TTexture( tex:TTexture, flags:Int )
Return tex.Copy(flags)
End Function


TTexture.bmx
Code (blitzmax) Select
Method Copy:TTexture(copyflags:Int=Null)

Select TGlobal.Texture_Loader

Case 2 ' library
Local inst:Byte Ptr=TextureCopy_( GetInstance(Self) )
Return CreateObject(inst)

Default ' wrapper
Local tex:TTexture=NewTexture()

tex.SetString(tex.file,GetString(file))
tex.SetString(tex.file_abs,FileAbs(GetString(file))) ' returns absolute path of file if relative
tex.blend[0]=blend[0]
tex.coords[0]=coords[0]
tex.u_scale[0]=u_scale[0]
tex.v_scale[0]=v_scale[0]
tex.u_pos[0]=u_pos[0]
tex.v_pos[0]=v_pos[0]
tex.angle[0]=angle[0]

' added by Krischan to use new flags instead of the original ones
If copyflags then flags[0]=copyflags

TTexture.is_unique=True
If no_frames[0]<2
LoadAnimTextureStream(GetString(file),flags[0],0,0,0,1,tex)
Else
LoadAnimTextureStream(GetString(file),flags[0],width[0],height[0],0,no_frames[0],tex)
EndIf
TTexture.is_unique=False
Return tex

EndSelect

End Method
Title: Re: OpenB3D Questions
Post by: markcwm on March 03, 2019, 02:10:37
Hi Krischan,

Great! Okay I can add flags if you think this is needed, there is no command to set flags as such so other than adding a TextureFlags function there is no way to alter flags other than with tex.flags[0].
Title: Re: OpenB3D Questions
Post by: Krischan on March 04, 2019, 07:46:46
Yes, I'd appreciate if you add this in the next update if there's nothing else against it. Sometimes I reuse a texture, for example a texture is loaded with alpha flag (1+2+8) and again without (1+8) and this would save diskspace or I'd need to save the same texture twice with different filenames like you described it to keep the "texture instance" feature.

In Faerghail, I'm using this feature for my loading screen - the loader pic in the middle is the version without alpha and I use the same picture with an alpha flag zoomed in a larger size, blended with another texture as a background filler because a simple wall texture or just a black screen is too boring ;D
Title: Re: OpenB3D Questions
Post by: markcwm on March 06, 2019, 03:57:07
Hi Krischan,

sure I'll add your fix in to the next commit, I just realized there is a TextureFlags function already in there but certainly no reason not to add it to CopyTexture.

I'm currently struggling a bit with Adam Redwoods awesome batch sprites. I can get it working in Minib3d but Openb3d works a bit different, especially with sprites so I'm just trying to fix that so we can have better single-surface options.
Title: Re: OpenB3D Questions
Post by: markcwm on March 10, 2019, 00:16:49
Hi Krischan,

CopyTexture(flags) is now in along with batch sprites from minib3d-monkey, this exposed a fix for AddVertex/Triangle which over-resizes arrays to prevent crashes, which is what Minib3d does.

The batch sprite port is in Blitzmax but there's a few issues, first it's not as fast as Minib3d and second there's a render bug which changes the orientation of sprites/meshes at a certain angle, but this is a general bug and nothing to do with batch sprite code. See docs example samples/mak/firepaint3d. There's also an unfinished port to c++ which I may fix later.

Re: your screenies, I can't really follow what you mean but I do think your loading screens are awesome.
Title: Re: OpenB3D Questions
Post by: markcwm on March 13, 2019, 01:16:17
Hi Krischan,

I've another update which fixes the batch sprites bugs, it seems the "render bug which changes the orientation of sprites/meshes at a certain angle" was actually a bug with the Blitzmax port but that code is replaced with the C++ port which works perfectly and is actually faster than Minib3d, roughly twice as fast, so that's the icing on the cake for me! I didn't expect that, interesting for anyone wondering if C++ is faster than Blitzmax.
Title: Re: OpenB3D Questions
Post by: Krischan on March 13, 2019, 22:12:52
Great, though I haven't used the Batchsprites yet. Oh, and Faerghail still works but I hadn't much time to work on it :-D So what comes next? I'm still unsure how to create a better looking RPG style torchlight shader with shadows to illuminate my levels properly. Perhaps like in this demo video with multiple lights and shadows. The bumpmap.bmx example in OpenB3D is nice to learn the basics but could be better in this point.

https://www.youtube.com/watch?v=7iyvv4mXg6k
Title: Re: OpenB3D Questions
Post by: markcwm on March 16, 2019, 02:04:59
Hi Krischan,

thanks nice video. Yes I'm going to have a go at soft shadows soon, first I'm tidying up some shader examples by RonTek and then I think we really need an example of the new Postfx functions.
Title: Re: OpenB3D Questions
Post by: markcwm on June 03, 2019, 23:18:06
Hello Krischan,

I don't think I'll be able to work on soft shadows and bump maps for a while yet, but let me know if you get anything done.
Title: Re: OpenB3D Questions
Post by: Krischan on June 28, 2019, 09:56:43
Thanks for the notice. I'll continue programming it without the shaders for now, but at the moment I've stopped the development, I've had enough other problems and no nerves at the moment. But I'd love to hear if/when you continue working on the shaders.
Title: Re: OpenB3D Questions
Post by: angros47 on July 03, 2019, 19:29:00
Bump map and soft shadows are features (experimental) in OpenB3D Plus 0.1