Any chance of a GLFW port?

Started by DruggedBunny, March 10, 2020, 02:04:32

Previous topic - Next topic

medi71

#45
DruggedBunny,
I studied the c++ code that you are trying to convert. I think that code is too complex to be a good learning example for beginners. For example, I don't suggest using complex shader class to begin with. That code uses its own shader class. I wish you continue steps in learnopengl.com so that I can leave the book that I am reading and stick to your examples.
What I am doing is to learn how glfw.mod can handle OpenGL's various tasks so that I can confidently spend time on converting a simple space simulator code that I wrote few years ago in C++/GLFW to BlitzMax. I just began to converts code in that book because I realized that the glfw.mod examples are not enough.

DruggedBunny

I'm probably not going to convert much more myself -- my plan was to get just enough working/understood to make my own really basic 3D engine (basically, flat-shading and pixel shaders!), so my own code is admittedly becoming a little too complex as it's been arranged into a load of project files. I've had to cut and paste it down into a single file for this example... obviously being a little too ambitious, ha ha.

I'm glad you've run into the same problem, though, as it suggests I may still be on the right track and that the library is at fault! I'd like to get this basic stuff working and understood before going any further.

I've raised an issue on GitHub so Brucey can try our examples... and hopefully not point out why we're both wrong!

https://github.com/bmx-ng/glfw.mod/issues/1

medi71

#47
My example above (from the book) works, but the cube is not visible. To make it visible, just comment out glEnable(GL_DEPTH_TEST) in the bottom of the code. To see it better, bring down the cube position by 2: cubeLocY:Float = -2.0.

Change shader to see it in color:
Vertex shader:

#version 330
layout (location=0) in vec3 position;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
out vec4 varyingColor;
void main(void)
{
gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
varyingColor = vec4(position,1.0) * .5 + vec4(.5,.5,.5,.5);
}

fragment shader:

#version 330
out vec4 color;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
in vec4 varyingColor;
void main(void)
{
//color = vec4(1.0, 0.0, 1.0, 1.0);
color = varyingColor;
}


Notes:
1 - Uniforms in fragment shader are not necessary for this program.
2 - The depth test shouldn't remove the cube. In C++ version it doesn't. With the mod, it seems front face is removed. This could be my mistake somewhere too. The good thing is that I can go further now.
3 - In the above shader program, simple position vertices are colored as they come in one after the other. Uniforms are used for transforming the spaces.

DruggedBunny

I think your problem may be this:

   glClear (GL_COLOR_BUFFER_BIT)

You also need to clear the depth buffer, I believe, as this is something I read about while trying to figure it out.

I'll have another look at your code, too!

DruggedBunny

Yeah, changing to glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) allows your code to work! So it looks like I'm at fault...

medi71

#50
Thanks DruggedBunny,
Previous examples (from the book) were good enough for me to continue. Now I have a new example.
In this example, cube moves around and rotates. Shaders are the same.
A model matrix is built out of two changing matrices, one from translation and another from rotation. Finally, the model-view matrix is updated based on those two.
I removed perspective and view matrix out of the main loop because they don't change in this example.

SuperStrict

Framework GLFW.GLFWWindow

Import GLFW.GLFW
Import GLFW.GLFWOpenGL
Import GLFW.GLFWSystem

Import BRL.StandardIO

Import BRL.Matrix

'------------------------- gl & window setup --------------
Type TGameWindow Extends TGLFWWindow
Method OnFrameBufferSize (width:Int, height:Int)
glViewport (0, 0, width, height)
EndMethod

EndType

Function ProcessInput (window:TGLFWWindow)

If window.IsKeyDown (GLFW_KEY_ESCAPE)
window.SetShouldClose (True)
EndIf

EndFunction

TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MAJOR, 4)
TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MINOR, 3)
TGLFWWindow.Hint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

?MacOS
TGLFWWindow.Hint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)
?

Local  width:Int = 800, height:Int = 600
Local app_name:String = "Medi Cube"

Local window:TGLFWWindow = New TGameWindow.Create (width, height, app_name)

If Not window
Print "Failed to create GLFW window!"
End
EndIf

window.MakeContextCurrent ()

gladLoadGL (glfwGetProcAddress)

'-----------------------------------------------------
Local numVAOs:Int=1
Local numVBOs:Int=2

Local cameraX:Float= 0, cameraY:Float=0, cameraZ:Float=8
Local cubeLocX:Float = 0.0, cubeLocY:Float = -2.0, cubeLocZ:Float = 0.0
Local renderProgram:Int
Local vbo:UInt[numVBOs]
Local vao:UInt[numVAOs]

Local mvLoc:UInt, projLoc:UInt

Local aspect:Float
Local pMat:SMat4F, vMat:SMat4F, mMat:SMat4F, mvMat:SMat4F, tMat:SMat4F, rMat:SMat4F

'--------------------------- setup vertecies  -------------------
renderProgram = CreateShaderProgram("vshader.glsl", "fshader.glsl")

Local vertexPositions:Float[] = [..
-1.0,  1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, ..
1.0, -1.0, -1.0, 1.0,  1.0, -1.0, -1.0,  1.0, -1.0, ..
1.0, -1.0, -1.0, 1.0, -1.0,  1.0, 1.0,  1.0, -1.0, ..
1.0, -1.0,  1.0, 1.0,  1.0,  1.0, 1.0,  1.0, -1.0, ..
1.0, -1.0,  1.0, -1.0, -1.0,  1.0, 1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0, -1.0,  1.0,  1.0, 1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0, -1.0, -1.0, -1.0, -1.0,  1.0,  1.0, ..
-1.0, -1.0, -1.0, -1.0,  1.0, -1.0, -1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  1.0, -1.0, -1.0, ..
1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,  1.0, ..
-1.0,  1.0, -1.0, 1.0,  1.0, -1.0, 1.0,  1.0,  1.0, ..
1.0,  1.0,  1.0, -1.0,  1.0,  1.0, -1.0,  1.0, -1.0]

glGenVertexArrays (1, Varptr vao)
glBindVertexArray (vao[0])
glGenBuffers (numVBOs, Varptr vbo)

glBindBuffer (GL_ARRAY_BUFFER, vbo[0])
glBufferData (GL_ARRAY_BUFFER, SizeOf (vertexPositions ), vertexPositions, GL_STATIC_DRAW)

' perspective 3d
projLoc = glGetUniformLocation(renderProgram, "proj_matrix")
pMat = SMat4F.Perspective(60, width , height, 0.1, 1000.0)

'cam
mvLoc = glGetUniformLocation(renderProgram, "mv_matrix")
vMat = SMat4F.Translation(New SVec3F(-cameraX, -cameraY, -cameraZ))

' -------------- ------------- main loop -----------------------------------
While Not window.ShouldClose ()

ProcessInput (window)
glClearColor (0.2, 0.3, 0.3, 1.0)
glClear(GL_DEPTH_BUFFER_BIT)
glClear (GL_COLOR_BUFFER_BIT)

glUseProgram (renderProgram)

Local xt:Double = Sin(56*GetTime()) *2.0
Local yt:Double = Cos(23*GetTime())*2.0
Local zt:Double = Sin(76*GetTime())*2.0
Local v:SVec3F = New SVec3F(Float(xt),Float(yt),Float(zt))
tMat=SMat4F.Translation(v)

rMat = SMat4F.Rotation(New SVec3F(0, 1, 0),50*Float(GetTime()))
rMat = SMat4F.Rotation(New SVec3F(1, 0, 1),29*Float(GetTime()))
rMat = SMat4F.Rotation(New SVec3F(0, 0, 1),75*Float(GetTime()))

mMat = tMat*rMat
mvMat = vMat * mMat 'model-view

glUniformMatrix4fv(mvLoc, 1, GL_FALSE,  Varptr mvMat.a)
glUniformMatrix4fv(projLoc, 1, GL_FALSE, Varptr pMat.a)

glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, 0);
glEnableVertexAttribArray(0)

'glEnable(GL_DEPTH_TEST)
'glDepthFunc(GL_LEQUAL)

glDrawArrays(GL_TRIANGLES, 0, 36)

window.SwapBuffers ()
PollSystem ()
Wend

glDeleteVertexArrays (1, Varptr vao)
glDeleteBuffers (1, Varptr vbo)

End

'------------------------- end --------------------------------

'------------ function read shader file  ----------------------
Function readShaderFile:String(file:String)
Local shaderSource:String
Local lineFromFile:String
Local in:TStream = OpenStream(file)
While Not Eof(in)
lineFromFile = ReadLine(in)
shaderSource :+ lineFromFile + "~n"
Wend
CloseStream(in)
Return shaderSource
End Function
'------------- function create shader program ------------------
Function CreateShaderProgram:Int(vsFile:String, frFile:String)

' read and compile vertex shader
Local infoLog:String
Local success:Int
Local vertexShaderSource:String
vertexShaderSource = readShaderFile(vsFile)
Local vertexShader:Int = glCreateShader (GL_VERTEX_SHADER)
glShaderSource (vertexShader, 1, vertexShaderSource)
glCompileShader (vertexShader)
glGetShaderiv (vertexShader, GL_COMPILE_STATUS, Varptr success)
If Not success
infoLog = glGetShaderInfoLog (vertexShader )
Print "Vertex shader compilation failed: " + String.FromCString (infoLog)
EndIf

' read and compile fragment shader
Local fragmentShaderSource:String
fragmentShaderSource = readShaderFile("fshader.glsl")
Local fragmentShader:Int = glCreateShader (GL_FRAGMENT_SHADER)
glShaderSource (fragmentShader, 1, fragmentShaderSource)
glCompileShader (fragmentShader)
glGetShaderiv (fragmentShader, GL_COMPILE_STATUS, Varptr success)
If Not success
infoLog = glGetShaderInfoLog (fragmentShader)
Print "Fragment shader compilation failed: " + String.FromCString (infoLog)
EndIf

' link, attach and check
Local shaderProgram:Int = glCreateProgram ()
glAttachShader (shaderProgram, vertexShader)
glAttachShader (shaderProgram, fragmentShader)
glLinkProgram (shaderProgram)
glGetProgramiv (shaderProgram, GL_LINK_STATUS, Varptr success)
If Not success
infoLog = glGetProgramInfoLog (shaderProgram)
Print "Shader program linking failed: " + String.FromCString (infoLog)
EndIf

' have the program, don't need anymore
glDeleteShader (vertexShader)
glDeleteShader (fragmentShader)

Return shaderProgram
End Function


medi71

Ok, the cube will be drawn correctly, if we add these three depth test stuff:

glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glFrontFace(GL_CW)

So, all the previous code must be modified.

The second one is not necessary for now.

medi71

DruggedBunny, you were right, I was just confused. Now, I can work on many more examples.  ;D

DruggedBunny

Hmm, I'm still confused -- I notice you're not using SMat4F.LookAt, and if I replace your line:

vMat = SMat4F.Translation(New SVec3F(-cameraX, -cameraY, -cameraZ))

... with what I think is the same offset:

vMat = SMat4F.LookAt (New SVec3f (cameraX, cameraY, cameraZ), New SVec3f (0.0, 0.0, 0.0), New SVec3f (0.0, 1.0, 0.0))

... it still doesn't work. Is LookAt broken after all?

DruggedBunny

Hmm, trying to use the original tutorials' camera position of 3, 3, 3 in your code also fails, in that the cube doesn't appear in the scene unless I use your camera's z=8 position... something seems to be wrong still.

DruggedBunny

#55
OK, not convinced I'm right, but I tried adapting SMat4F.LookAt to be somewhat similar to GLM's, and with a bit of trial and error it gives close results using the 3, 3, 3 position. Not sure why it doesn't quite match the OS X version, but the viewpoint looks the same.

Also, it seems SMat4F.Perspective does use degrees for the first parameter, as I see you've done!

Here's my experimental SMat4F.LookAt, with references:


' https://github.com/g-truc/glm/blob/master/glm/ext/matrix_transform.inl
' Adapted from lookAtRH
' https://github.com/g-truc/glm/blob/master/copying.txt
' "GLM is licensed under The Happy Bunny License or MIT License"

Function LookAt:SMat4F(eye:SVec3F, center:SVec3F, up:SVec3F)

Local f:SVec3F = (center - eye).Normal ()
Local s:SVec3F = f.Cross (up).Normal ()
Local u:SVec3F = s.Cross (f)

Return New SMat4F (s.x, u.x, -f.x, 0, s.y, u.y, -f.y, 0, s.z, u.z, -f.z, 0, -s.Dot (eye), -u.Dot (eye), f.Dot (eye), 1)
End Function


Not saying it's right (notice slightly more zoomed/filling window), but it looks more like it's meant to! The faces are in the right positions too.

Code and screenshot showing my 3, 3, 3-positioned cube, versus tutorial version, attached... remember to change matrix.mod -> LookAt:SMat4F !

medi71

3,3,3 moves the camera space out of where the cube is. Try .7, .2, 5. You will see that part of the cube is visible.
About the LookAt, it works.
Here I have modified my example to draw the cube using LookAt. Shaders are as before.

SuperStrict

Framework GLFW.GLFWWindow

Import GLFW.GLFW
Import GLFW.GLFWOpenGL
Import GLFW.GLFWSystem

Import BRL.StandardIO

Import BRL.Matrix

'------------------------- gl & window setup --------------
Type TGameWindow Extends TGLFWWindow
Method OnFrameBufferSize (width:Int, height:Int)
glViewport (0, 0, width, height)
EndMethod

EndType

Function ProcessInput (window:TGLFWWindow)

If window.IsKeyDown (GLFW_KEY_ESCAPE)
window.SetShouldClose (True)
EndIf

EndFunction

TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MAJOR, 4)
TGLFWWindow.Hint (GLFW_CONTEXT_VERSION_MINOR, 3)
TGLFWWindow.Hint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

?MacOS
TGLFWWindow.Hint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE)
?

Local  width:Int = 800, height:Int = 600
Local app_name:String = "Medi Cube"

Local window:TGLFWWindow = New TGameWindow.Create (width, height, app_name)

If Not window
Print "Failed to create GLFW window!"
End
EndIf

window.MakeContextCurrent ()

gladLoadGL (glfwGetProcAddress)

'-----------------------------------------------------
Local numVAOs:Int=1
Local numVBOs:Int=2

Local cameraX:Float= 1.5, cameraY:Float=1.5, cameraZ:Float=1.5
Local cubeLocX:Float = 0.0, cubeLocY:Float = 0.0, cubeLocZ:Float = 0.0
Local renderProgram:Int
Local vbo:UInt[numVBOs]
Local vao:UInt[numVAOs]

Local mvLoc:UInt, projLoc:UInt

Local aspect:Float
Local pMat:SMat4F, vMat:SMat4F, mMat:SMat4F, mvMat:SMat4F, rMat:SMat4F, tMat:SMat4F

'--------------------------- setup vertecies  -------------------
renderProgram = CreateShaderProgram("vshader.glsl", "fshader.glsl")

Local vertexPositions:Float[] = [..
-1.0,  1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, ..
1.0, -1.0, -1.0, 1.0,  1.0, -1.0, -1.0,  1.0, -1.0, ..
1.0, -1.0, -1.0, 1.0, -1.0,  1.0, 1.0,  1.0, -1.0, ..
1.0, -1.0,  1.0, 1.0,  1.0,  1.0, 1.0,  1.0, -1.0, ..
1.0, -1.0,  1.0, -1.0, -1.0,  1.0, 1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0, -1.0,  1.0,  1.0, 1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0, -1.0, -1.0, -1.0, -1.0,  1.0,  1.0, ..
-1.0, -1.0, -1.0, -1.0,  1.0, -1.0, -1.0,  1.0,  1.0, ..
-1.0, -1.0,  1.0,  1.0, -1.0,  1.0,  1.0, -1.0, -1.0, ..
1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0,  1.0, ..
-1.0,  1.0, -1.0, 1.0,  1.0, -1.0, 1.0,  1.0,  1.0, ..
1.0,  1.0,  1.0, -1.0,  1.0,  1.0, -1.0,  1.0, -1.0]

glGenVertexArrays (1, Varptr vao)
glBindVertexArray (vao[0])
glGenBuffers (numVBOs, Varptr vbo)

glBindBuffer (GL_ARRAY_BUFFER, vbo[0])
glBufferData (GL_ARRAY_BUFFER, SizeOf (vertexPositions ), vertexPositions, GL_STATIC_DRAW)

mvLoc = glGetUniformLocation(renderProgram, "mv_matrix")
projLoc = glGetUniformLocation(renderProgram, "proj_matrix")

' projection
pMat = SMat4F.Perspective(45, width , height, 0.1, 1000.0)

'view
vMat = SMat4F.LookAt(New SVec3F(cameraX, cameraY, cameraZ), ..
New SVec3F(0, 0, 0), ..
New SVec3F(0, 1, 0))
' -------------- ------------- main loop -----------------------------------
While Not window.ShouldClose ()
ProcessInput (window)
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)
glClearColor (0.2, 0.4, 0.6, 1.0)

glUseProgram (renderProgram)

'model
Global rot:Float
rot:+1.5
If rot>360 Then rot = 0
tMat = SMat4F.Translation(New SVec3F(cubeLocX, cubeLocY, cubeLocZ)) 'no move, all zero
rMat = SMat4F.Rotation(New SVec3F(0, 1, 0),rot)

mMat = tMat*rMat
mvMat = vMat * mMat 'model-view

glUniformMatrix4fv(mvLoc, 1, GL_FALSE,  Varptr mvMat.a)
glUniformMatrix4fv(projLoc, 1, GL_FALSE, Varptr pMat.a)

glBindBuffer(GL_ARRAY_BUFFER, vbo[0])
glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, 0);
glEnableVertexAttribArray(0)

glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glFrontFace(GL_CW)

glDrawArrays(GL_TRIANGLES, 0, 36)

window.SwapBuffers ()
PollSystem ()
Wend

glDeleteVertexArrays (1, Varptr vao)
glDeleteBuffers (1, Varptr vbo)

End

'------------------------- end --------------------------------

'------------ function read shader file  ----------------------
Function readShaderFile:String(file:String)
Local shaderSource:String
Local lineFromFile:String
Local in:TStream = OpenStream(file)
While Not Eof(in)
lineFromFile = ReadLine(in)
shaderSource :+ lineFromFile + "~n"
Wend
CloseStream(in)
Return shaderSource
End Function
'------------- function create shader program ------------------
Function CreateShaderProgram:Int(vsFile:String, frFile:String)

' read and compile vertex shader
Local infoLog:String
Local success:Int
Local vertexShaderSource:String
vertexShaderSource = readShaderFile(vsFile)
Local vertexShader:Int = glCreateShader (GL_VERTEX_SHADER)
glShaderSource (vertexShader, 1, vertexShaderSource)
glCompileShader (vertexShader)
glGetShaderiv (vertexShader, GL_COMPILE_STATUS, Varptr success)
If Not success
infoLog = glGetShaderInfoLog (vertexShader )
Print "Vertex shader compilation failed: " + String.FromCString (infoLog)
EndIf

' read and compile fragment shader
Local fragmentShaderSource:String
fragmentShaderSource = readShaderFile("fshader.glsl")
Local fragmentShader:Int = glCreateShader (GL_FRAGMENT_SHADER)
glShaderSource (fragmentShader, 1, fragmentShaderSource)
glCompileShader (fragmentShader)
glGetShaderiv (fragmentShader, GL_COMPILE_STATUS, Varptr success)
If Not success
infoLog = glGetShaderInfoLog (fragmentShader)
Print "Fragment shader compilation failed: " + String.FromCString (infoLog)
EndIf

' link, attach and check
Local shaderProgram:Int = glCreateProgram ()
glAttachShader (shaderProgram, vertexShader)
glAttachShader (shaderProgram, fragmentShader)
glLinkProgram (shaderProgram)
glGetProgramiv (shaderProgram, GL_LINK_STATUS, Varptr success)
If Not success
infoLog = glGetProgramInfoLog (shaderProgram)
Print "Shader program linking failed: " + String.FromCString (infoLog)
EndIf

' have the program, don't need anymore
glDeleteShader (vertexShader)
glDeleteShader (fragmentShader)

Return shaderProgram
End Function


DruggedBunny

OK, that's cool (and thanks for all your code!)... but what I don't get is why 3, 3, 3 actually works in the original C versions, yet not here.

DruggedBunny

Ha ha, now I'm even more confused! I was still using my LookAt when I ran yours. When I change back to the original, I get this, using:

Local cameraX:Float= .7, cameraY:Float=.2, cameraZ:Float=5

DruggedBunny

I notice you're using a large far value too, where the original near=0.1, far=10 doesn't seem to work here.

It surely ought to be possible to get the same/similar results using the values from the tutorials' C code.