Page 1 of 1

OpenGL ->Rotate / Scale in GLSL vertex shader question

Posted: Mon Feb 08, 2021 7:38 pm
by sq4
Why, oh why is the aspect ratio of the image not kept after rotate / scale?
I must be misunderstanding something...
If I change the screen resolution to a square (#W=#H) then it's ok, but I do not understand why since the vertexes are in world coords.

Code: Select all

#W=1200
#H=800

#GL_COLOR_BUFFER_BIT                = $00004000
#GL_DEPTH_BUFFER_BIT                = $00000100
#GL_ARRAY_BUFFER                    = $8892
#GL_ELEMENT_ARRAY_BUFFER            = $8893
#GL_MODELVIEW                       = $1700
#GL_PROJECTION                      = $1701
#GL_SMOOTH                          = $1D01
#GL_DEPTH_TEST                      = $0B71
#GL_CULL_FACE                       = $0B44
#GL_STATIC_DRAW                     = $88E4
#GL_VERTEX_ARRAY                    = $8074
#GL_FLOAT                           = $1406
#GL_TRIANGLES                       = $0004
#GL_UNSIGNED_BYTE                   = $1401
#GL_UNSIGNED_SHORT                  = $1403
#GL_UNSIGNED_INT                    = $1405

#GL_ARRAY_BUFFER = $8892
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30
#GL_TEXTURE0 = $84C0
#GL_TEXTURE1 = $84C1

#GL_BGR = $80E0
#GL_BGRA = $80E1
#GL_RGB= $1907
#GL_RGBA= $1908

Prototype glGenBuffers( n.i, *buffers)
Prototype glBindBuffer( target.l, buffer.i)
Prototype glBufferData ( target.l, size.i, *Data_, usage.l)
Prototype glBufferSubData ( target.l, offset.i, size.i, *Data_)
Prototype glGenVertexArrays (n.i, *arrays)
Prototype glBindVertexArray(n.i)
Prototype glEnableVertexAttribArray ( index.i )
Prototype glVertexAttribPointer ( index.i, size.i, type.l, normalized.b, stride.i, *pointer )
Prototype glDrawArrays ( mode.l, first.i, count.i )
Prototype glIndexPointer ( enum.i, stride.i, *length )
Prototype glDeleteBuffers ( n.i, *buffers)
Prototype glDeleteVertexArrays ( n.i, *buffers)
Prototype glDisableVertexAttribArray(index.i)
Prototype glMapBuffer(Target.i, Access.i)
Prototype glUnmapBuffer(Target.i)
Prototype glActiveTexture(Texture.l)
Prototype glUniformMatrix4fv(location.i, count.i, transpose.b, *value)

Prototype glCreateShader(type.l)
Prototype glCreateProgram()
Prototype glCompileShader(shader.l)
Prototype glDeleteShader(ShaderObj.i)
Prototype glLinkProgram(shader.l)
Prototype glUseProgram(shader.l)
Prototype glAttachShader(Program.l, shader.l)
Prototype glShaderSource(shader.l, numOfStrings.l, *strings, *lenOfStrings) :
Prototype glGetUniformLocation(Program.i, name.p-ascii)
Prototype glUniform1i(location.i, v0.i)
Prototype glUniform2i(location.i, v0.i, v1.i)
Prototype glUniform1f(location.i, v0.f)
Prototype glUniform2f(location.i, v0.f, v1.f)
Prototype glGetShaderInfoLog(shader.i, bufSize.l, *length_l, *infoLog)

Structure GLSL
  glGenBuffers.glGenBuffers
  glBindBuffer.glBindBuffer
  glBufferData.glBufferData
  glBufferSubData.glBufferSubData
  glGenVertexArrays.glGenVertexArrays
  glBindVertexArray.glBindVertexArray
  glEnableVertexAttribArray.glEnableVertexAttribArray
  glVertexAttribPointer.glVertexAttribPointer
  glDrawArrays.glDrawArrays
  glIndexPointer.glIndexPointer
  glDeleteBuffers.glDeleteBuffers
  glDeleteVertexArrays.glDeleteVertexArrays
  glDisableVertexAttribArray.glDisableVertexAttribArray
  glMapBuffer.glMapBuffer
  glUnmapBuffer.glUnmapBuffer
  glActiveTexture.glActiveTexture
  glUniformMatrix4fv.glUniformMatrix4fv
  glCreateShader.glCreateShader
  glCreateProgram.glCreateProgram
  glCompileShader.glCompileShader
  glDeleteShader.glDeleteShader
  glLinkProgram.glLinkProgram
  glUseProgram.glUseProgram
  glAttachShader.glAttachShader
  glShaderSource.glShaderSource
  glGetUniformLocation.glGetUniformLocation
  glUniform1i.glUniform1i
  glUniform2i.glUniform2i
  glUniform1f.glUniform1f
  glUniform2f.glUniform2f
  glGetShaderInfoLog.glGetShaderInfoLog
EndStructure

Procedure GLGetFunctions(*GLSL.GLSL)
  *GLSL\glGenBuffers = wglGetProcAddress_("glGenBuffers")
  *GLSL\glBindBuffer = wglGetProcAddress_("glBindBuffer")
  *GLSL\glBufferData = wglGetProcAddress_("glBufferData")
  *GLSL\glBufferSubData = wglGetProcAddress_("glBufferSubData")
  *GLSL\glGenVertexArrays = wglGetProcAddress_("glGenVertexArrays")
  *GLSL\glBindVertexArray = wglGetProcAddress_("glBindVertexArray")
  *GLSL\glEnableVertexAttribArray = wglGetProcAddress_("glEnableVertexAttribArray")
  *GLSL\glVertexAttribPointer = wglGetProcAddress_("glVertexAttribPointer")
  *GLSL\glDrawArrays = wglGetProcAddress_("glDrawArrays")
  *GLSL\glIndexPointer = wglGetProcAddress_("glIndexPointer")
  *GLSL\glDeleteBuffers = wglGetProcAddress_("glDeleteBuffers")
  *GLSL\glDeleteVertexArrays = wglGetProcAddress_("glDeleteVertexArrays")
  *GLSL\glDisableVertexAttribArray = wglGetProcAddress_("glDisableVertexAttribArray")
  *GLSL\glMapBuffer = wglGetProcAddress_("glMapBuffer")
  *GLSL\glUnmapBuffer = wglGetProcAddress_("glUnmapBuffer")
  *GLSL\glActiveTexture = wglGetProcAddress_("glActiveTexture")
  *GLSL\glUniformMatrix4fv=wglGetProcAddress_("glUniformMatrix4fv")
  *GLSL\glCreateShader = wglGetProcAddress_("glCreateShader")
  *GLSL\glCreateProgram = wglGetProcAddress_("glCreateProgram")
  *GLSL\glCompileShader = wglGetProcAddress_("glCompileShader")
  *GLSL\glDeleteShader = wglGetProcAddress_("glDeleteShader")
  *GLSL\glLinkProgram = wglGetProcAddress_("glLinkProgram")
  *GLSL\glUseProgram = wglGetProcAddress_("glUseProgram")
  *GLSL\glAttachShader = wglGetProcAddress_("glAttachShader")
  *GLSL\glShaderSource = wglGetProcAddress_("glShaderSource")
  *GLSL\glGetUniformLocation = wglGetProcAddress_("glGetUniformLocation")
  *GLSL\glUniform1i = wglGetProcAddress_("glUniform1i")
  *GLSL\glUniform2i = wglGetProcAddress_("glUniform2i")
  *GLSL\glUniform1f = wglGetProcAddress_("glUniform1f")
  *GLSL\glUniform2f = wglGetProcAddress_("glUniform2f")
  *GLSL\glGetShaderInfoLog = wglGetProcAddress_("glGetShaderInfoLog")    
EndProcedure

Global points_vbo.i, colors_vbo.i, vao.i, ebo.i, texture.i, transparenz.f

Structure _2DPoint
  x.f
  y.f
EndStructure

Structure _2DTex
  x.f
  y.f
EndStructure

Structure myTexVertex
  Pos._2DPoint
  Tex._2DTex
EndStructure

Structure Tindex
  a.l
  b.l
  c.l
  d.l
EndStructure

UseJPEGImageDecoder()
UsePNGImageDecoder()

#ImagePath = #PB_Compiler_Home + "examples/3d/Data/Textures/"
LoadImage(1, #ImagePath + "ValetCoeur.jpg")
ImgDepth=ImageDepth(1)
If ImgDepth<>32
  CreateImage(2,ImageWidth(1), ImageHeight(1),32)
  StartDrawing(ImageOutput(2))
  DrawImage(ImageID(1),0,0)
  StopDrawing()
  FreeImage(1)
  CopyImage(2,1)
  FreeImage(2)
EndIf
  
Sprite_W=ImageWidth(1)
Sprite_H=ImageHeight(1)

StartDrawing(ImageOutput(1))
  Debug DrawingBufferPixelFormat()
  mem=DrawingBuffer()
  size=DrawingBufferPitch()* ImageHeight(1)
  *Buffer1=AllocateMemory(size)
  CopyMemory(mem, *Buffer1, size)
StopDrawing()

Dim Vertex.myTexVertex(3)

Sprite_X=0
Sprite_Y=0

; Vertexes in WorldSpace
; // top left
Vertex(0)\Pos\x = -1  : Vertex(0)\Pos\y = 1 
Vertex(0)\Tex\x = 0.0   : Vertex(0)\Tex\y = 1.0

;// top right
Vertex(1)\Pos\x = 1   : Vertex(1)\Pos\y = 1
Vertex(1)\Tex\x = 1.0   : Vertex(1)\Tex\y = 1.0

; // bottom left
Vertex(2)\Pos\x = -1  : Vertex(2)\Pos\y = -1
Vertex(2)\Tex\x = 0.0   : Vertex(2)\Tex\y = 0.0

; // bottom right
Vertex(3)\Pos\x = 1   : Vertex(3)\Pos\y = -1
Vertex(3)\Tex\x = 1.0   : Vertex(3)\Tex\y = 0.0

;Another way to transform, but that's not the question...
;fLeft.f=((Sprite_X/#W)-0.5)*2
;fTop.f=(0.5-(Sprite_Y/#H))*2
;fRight.f=(((Sprite_X+Sprite_W)/#W)-0.5)*2
;fBottom.f=(0.5-((Sprite_Y+Sprite_H)/#H))*2

Dim uRotate.f(3,3)
Dim uScale.f(3,3)
Dim uTranslate.f(3,3)
Dim Index.Tindex(0)
Index(0)\a = 2  : Index(0)\b = 3  : Index(0)\c = 1  : Index(0)\d = 0

Global GLSL.GLSL

;**************************************************************************************

OpenWindow(0, 0, 0, #W, #H, "GLSL sprites in WindowedScreen")
InitSprite()
OpenWindowedScreen(WindowID(0),0,0,#W,#H)

;**************************************************************************************
GLGetFunctions(GLSL.GLSL)
;**************************************************************************************

glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
glEnable_(#GL_DEPTH_TEST); // enable depth-testing
glEnable_(#GL_BLEND)
glBlendFunc_(#GL_SRC_ALPHA, #GL_ONE_MINUS_SRC_ALPHA) 

GLSL\glGenVertexArrays(1, @vao) 
GLSL\glGenBuffers(1, @points_vbo )
GLSL\glGenBuffers(1, @ebo)       

GLSL\glBindVertexArray(vao)
GLSL\glBindBuffer(#GL_ARRAY_BUFFER, points_vbo)
GLSL\glBufferData(#GL_ARRAY_BUFFER,SizeOf(myTexVertex) * (ArraySize(Vertex())+1),@Vertex(0), #GL_STATIC_DRAW) 

GLSL\glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, ebo)
GLSL\glBufferData(#GL_ELEMENT_ARRAY_BUFFER, 16*(ArraySize(Index())+1), @Index(0), #GL_STATIC_DRAW)

GLSL\glVertexAttribPointer(0, SizeOf(_2DPoint)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), 0)
GLSL\glEnableVertexAttribArray(0)     

GLSL\glVertexAttribPointer(1, SizeOf(_2DTex)/SizeOf(float), #GL_FLOAT, #GL_FALSE, SizeOf(myTexVertex), OffsetOf(myTexVertex\Tex))
GLSL\glEnableVertexAttribArray(1);

glGenTextures_(1, @texture1)
glBindTexture_(#GL_TEXTURE_2D, texture1)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_S, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_WRAP_T, #GL_CLAMP_TO_EDGE)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
glTexImage2D_(#GL_TEXTURE_2D, 0, 4, ImageWidth(1), ImageHeight(1), 0, #GL_BGRA_EXT, #GL_UNSIGNED_BYTE, *Buffer1)
 ;glGenerateMipmap_(#GL_TEXTURE_2D)
FreeMemory(*Buffer1)

Define vertex_shader.s
Define fragment_shader.s
Define *fbuff
Define *vbuff

vertex_shader = "#version 330 core"+#CRLF$
vertex_shader + "layout(location = 0) in vec2 aPos;"+#CRLF$             ; the position variable has attribute position 0
vertex_shader + "layout(location = 1) in vec2 aTexCoord;"+#CRLF$        ; the color variable has attribute position 1
vertex_shader + "out vec2 TexCoord;"+#CRLF$
vertex_shader + "uniform mat4 uScale;"+#CRLF$
vertex_shader + "uniform mat4 uRotate;"+#CRLF$
vertex_shader + "uniform mat4 uTranslate;"+#CRLF$
vertex_shader + "void main() {"+#CRLF$
vertex_shader + "vec4 Position = vec4(aPos, 1.0, 1.0);"+#CRLF$

;I DO NOT UNDERSTAND WHY ROTATE/SCALE acts like this
vertex_shader + "Position = uRotate*Position;"+#CRLF$
vertex_shader + "Position = uScale*Position;"+#CRLF$
vertex_shader + "Position = uTranslate*Position;"+#CRLF$

vertex_shader + "gl_Position = Position;"+#CRLF$
vertex_shader + "TexCoord = aTexCoord;"+#CRLF$
vertex_shader + "}"

fragment_shader = "#version 330 core"+#CRLF$
fragment_shader + "out vec4 FragColor;"+#CRLF$
fragment_shader + "in vec2 TexCoord;"+#CRLF$
fragment_shader + "uniform sampler2D texture1;"+#CRLF$

fragment_shader + "void main()"+#CRLF$
fragment_shader + "{"+#CRLF$
fragment_shader + "   FragColor = texture(texture1, TexCoord)*vec4(1.,1.,1.,1);"+#CRLF$
fragment_shader + "}"+#CRLF$

*vbuff = Ascii(vertex_shader)
*fbuff = Ascii(fragment_shader)


Global vs = GLSL\glCreateShader(#GL_VERTEX_SHADER);
GLSL\glShaderSource(vs, 1, @*vbuff, #Null) ;
GLSL\glCompileShader(vs)

  buffer = AllocateMemory(512)
  GLSL\glGetShaderInfoLog(vs,512,#Null,buffer)
  Log$=PeekS(buffer,512,#PB_Ascii)
  If Log$:Debug Log$:EndIf
  FreeMemory(buffer)


Global fs = GLSL\glCreateShader(#GL_FRAGMENT_SHADER);
GLSL\glShaderSource(fs, 1, @*fbuff, #Null);
GLSL\glCompileShader(fs) 


Global Shader = GLSL\glCreateProgram();
GLSL\glAttachShader(Shader, vs)
GLSL\glAttachShader(Shader, fs)
GLSL\glLinkProgram(Shader)     

GLSL\glDeleteShader(vs)
GLSL\glDeleteShader(fs)


GLSL\glUseProgram(Shader)  ; // don't forget to activate/use the shader before setting uniforms!
GLSL\glUniform1i(GLSL\glGetUniformLocation(Shader, "texture1"), 0)  ; muss nur einmal festgelegt werden

GLSL\glActiveTexture(#GL_TEXTURE0);
glBindTexture_(#GL_TEXTURE_2D, texture1)

Repeat
 Event = WindowEvent()
          
  ;glClearColor_(0.2, 0.5, 0.3, 1)
  ;glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
  ;glViewport_(0, 0, #W, #H) 
    
  GLSL\glUseProgram(Shader) 
    
  GLSL\glBindVertexArray(vao)
  Scale_X.f=(Sprite_W/#W)
  Scale_Y.f=Sprite_H/#H
  
  Sprite_X=0
  Sprite_Y=0

  fLeft.f=Sprite_X/(#W/2)
  fTop.f=Sprite_Y/#H
  myCos.f=Cos(Radian(Angle))
  mySin.f=Sin(Radian(Angle))
  
  Angle+1
  Angle%360

  ;Trying to understand matrices.....???
  ;Why is the aspect ratio of the image not correct after rotate / scale ?????
  uScale(0,0)=Scale_X : uScale(1,0)=0 : uScale(2,0)=0 : uScale(3,0)=0
  uScale(0,1)=0 : uScale(1,1)=Scale_Y : uScale(2,1)=0 : uScale(3,1)=0
  uScale(0,2)=0 : uScale(1,2)=0 : uScale(2,2)=1 : uScale(3,2)=0
  uScale(0,3)=0 : uScale(1,3)=0 : uScale(2,3)=0 : uScale(3,3)=1

  uRotate(0,0)=myCos : uRotate(1,0)=-mySin : uRotate(2,0)=0 : uRotate(3,0)=0
  uRotate(0,1)=mySin : uRotate(1,1)=myCos : uRotate(2,1)=0 : uRotate(3,1)=0
  uRotate(0,2)=0 : uRotate(1,2)=0 : uRotate(2,2)=1 : uRotate(3,2)=0
  uRotate(0,3)=0 : uRotate(1,3)=0 : uRotate(2,3)=0 : uRotate(3,3)=1

  uTranslate(0,0)=1 : uTranslate(1,0)=0 : uTranslate(2,0)=0 : uTranslate(3,0)=fLeft
  uTranslate(0,1)=0 : uTranslate(1,1)=1 : uTranslate(2,1)=0 : uTranslate(3,1)=fTop
  uTranslate(0,2)=0 : uTranslate(1,2)=0 : uTranslate(2,2)=1 : uTranslate(3,2)=0
  uTranslate(0,3)=0 : uTranslate(1,3)=0 : uTranslate(2,3)=0 : uTranslate(3,3)=1

  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uScale"), 1, #GL_FALSE, @uScale(0,0));
  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uRotate"), 1, #GL_FALSE, @uRotate(0,0));
  GLSL\glUniformMatrix4fv(GLSL\glGetUniformLocation(Shader, "uTranslate"), 1, #GL_FALSE, @uTranslate(0,0));

  glDrawElements_(#GL_QUADS, 4, #GL_UNSIGNED_INT, 0 )  

  GLSL\glBindVertexArray(0)
  GLSL\glUseProgram(0)   

  FlipBuffers()  
Until Event = #PB_Event_CloseWindow Or quit = 1

Re: OpenGL ->Rotate / Scale in GLSL vertex shader question

Posted: Mon Feb 08, 2021 10:01 pm
by Olli
If you swap these two lines and you paste them like this:

Code: Select all

vertex_shader + "Position = uScale*Position;"+#CRLF$
vertex_shader + "Position = uRotate*Position;"+#CRLF$
... does it change anything?

Good the Ascii(ShaderSourceCode$) : I forgot this formatting subtility.

Re: OpenGL ->Rotate / Scale in GLSL vertex shader question

Posted: Mon Feb 08, 2021 10:15 pm
by sq4
Olli wrote:If you swap these two lines and you paste them like this:

Code: Select all

vertex_shader + "Position = uScale*Position;"+#CRLF$
vertex_shader + "Position = uRotate*Position;"+#CRLF$
... does it change anything?

Good the Ascii(ShaderSourceCode$) : I forgot this formatting subtility.
Yes, it works reverse. That is why I splitted the transformations.

I think I need to set the aspect ratio of the object to square, then do the rotation, and then reverse that first transformation.
I might also need to compensate the view matrix.
The reason I want the vertex shader to take care of it is purely a question of performance.

Re: OpenGL ->Rotate / Scale in GLSL vertex shader question

Posted: Tue Feb 09, 2021 9:02 am
by sq4
Solved it!

I needed to apply a screen transformation after rotation.
What a fresh mind can do :D

Re: OpenGL ->Rotate / Scale in GLSL vertex shader question

Posted: Tue Feb 09, 2021 3:38 pm
by Olli
Good thing you solve it successfully.

This could be helpful to get perspective projection matrix 4*4.