flat assembler
Message board for the users of flat assembler.

Index > Windows > COFF vs PE vs MZ vs ELF?

Author
Thread Post new topic Reply to topic
wbutterdog



Joined: 01 Oct 2025
Posts: 7
wbutterdog 03 Oct 2025, 09:54
I'm wanting to create a openGL context using GLFW.
What output format should I use? And why?
And also, in general, what output formats should I use when?

Thank you! Very Happy
Post 03 Oct 2025, 09:54
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 13:47
I prefer OBJ files of late, but that is because of the added flexibility - which comes with added complexity.

Yet, DLL use is easier ...
Code:
; .\fasm2.cmd -e 5 glfw0.asm
format PE64 NX GUI 5.0
entry start

include 'win64a.inc'
include 'globstr.inc'
GLOBSTR.reuse := 1
macro fastcall?.inline_string var
        local data
        data GLOBSTR var,0
        redefine var data
end macro


section '.data' data readable writeable
        hWindow dq ? ; GLFWwindow *
        GLOBSTR.here


section '.text' code readable executable

start:
        push rax ; align stack

        invoke glfwInit
        test eax, eax
        jz .quit

        invoke glfwCreateWindow,800,600,'glfw + fasm2',0,0
        test rax, rax
        jz .term
        mov [hWindow], rax

        invoke glfwMakeContextCurrent,[hWindow]
;       invoke glfwSwapInterval,1

.loop:  invoke glClearColor,\
                float dword 0.0,\       ; red
                float dword 0.6,\       ; green
                float dword 0.8,\       ; blue
                float dword 1.0         ; alpha
        invoke glClear,0x00004000 ; GL_COLOR_BUFFER_BIT

        invoke glfwSwapBuffers,[hWindow]
        invoke glfwPollEvents
        invoke glfwWindowShouldClose,[hWindow]
        test eax, eax
        jz .loop

.term:  invoke glfwTerminate
.quit:  invoke ExitProcess,0
        jmp $


section '.idata' import data readable writeable
library glfw3,'glfw3.dll',\
        kernel32,'kernel32.dll',\
        opengl32,'opengl32.dll'

import glfw3,\
        glfwCreateWindow,'glfwCreateWindow',\
        glfwInit,'glfwInit',\
        glfwMakeContextCurrent,'glfwMakeContextCurrent',\
        glfwPollEvents,'glfwPollEvents',\
        glfwSwapBuffers,'glfwSwapBuffers',\
        glfwTerminate,'glfwTerminate',\
        glfwWindowShouldClose,'glfwWindowShouldClose'

import  kernel32,\
        ExitProcess,'ExitProcess'

import opengl32,\
        glClear,'glClear',\
        glClearColor,'glClearColor'    
You'll need fasm2 and glfw download.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.


Last edited by bitRAKE on 03 Oct 2025, 14:32; edited 2 times in total
Post 03 Oct 2025, 13:47
View user's profile Send private message Visit poster's website Reply with quote
wbutterdog



Joined: 01 Oct 2025
Posts: 7
wbutterdog 03 Oct 2025, 13:51
Quote:

You'll need fasm2


Thanks man xD I really appreciate the help. A lot of people on reddit and other forums kinda just told me to figure it out myself.
Will try this out. May I ask tho, why is FASM 2 needed?
Post 03 Oct 2025, 13:51
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 13:59
Because that is what I wrote the code for.
Post 03 Oct 2025, 13:59
View user's profile Send private message Visit poster's website Reply with quote
wbutterdog



Joined: 01 Oct 2025
Posts: 7
wbutterdog 03 Oct 2025, 14:19
Okay cool thanks, also just quick:
what does the '.\fasm2.cmd -e 5 glfw0.asm' comment mean?
Post 03 Oct 2025, 14:19
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 14:34
It's the command to assemble the program - assuming you name it "glfw0.asm". "-e 5" is an option to display five errors (if they exist). My editor is setup to execute commands from the source code - it's handy.
Post 03 Oct 2025, 14:34
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 16:22
Code:
; build with: .\fasm2.cmd -e 5 glfw1.asm
;------------------------------------------------------------------------------
; fasm 64-bit / Windows / GLFW 3.x / OpenGL 3.3 core
; - Creates a window and context
; - Loads GL 3.x entry points via glfwGetProcAddress
; - Compiles minimal shaders
; - Sets up VAO/VBO for a colored triangle
; - Animates rotation using a time uniform
; - Handles resize with a framebuffer size callback (glViewport)
;------------------------------------------------------------------------------
format PE64 NX GUI 5.0
entry start

include 'win64a.inc'
include 'globstr.inc'
GLOBSTR.reuse := 1
macro fastcall?.inline_string var
        local data
        data GLOBSTR var,0
        redefine var data
end macro

;------------------------------ Constants -------------------------------------
GL_COLOR_BUFFER_BIT        = 0x00004000
GL_TRIANGLES               = 0x0004
GL_FLOAT                   = 0x1406
GL_ARRAY_BUFFER            = 0x8892
GL_STATIC_DRAW             = 0x88E4
GL_VERTEX_SHADER           = 0x8B31
GL_FRAGMENT_SHADER         = 0x8B30
GL_COMPILE_STATUS          = 0x8B81
GL_LINK_STATUS             = 0x8B82

; GLFW window hints
GLFW_CONTEXT_VERSION_MAJOR = 0x00022002
GLFW_CONTEXT_VERSION_MINOR = 0x00022003
GLFW_OPENGL_PROFILE        = 0x00022008
GLFW_OPENGL_CORE_PROFILE   = 0x00032001

iterate _,\
        glCreateShader,\
        glShaderSource,\
        glCompileShader,\
        glGetShaderiv,\
        glCreateProgram,\
        glAttachShader,\
        glLinkProgram,\
        glGetProgramiv,\
        glDeleteShader,\
        glGenVertexArrays,\
        glBindVertexArray,\
        glGenBuffers,\
        glBindBuffer,\
        glBufferData,\
        glVertexAttribPointer,\
        glEnableVertexAttribArray,\
        glUseProgram,\
        glGetUniformLocation,\
        glUniform1f,\
        glDrawArrays

        define CONTEXT_AWARE_FUNCTION_ENTRIES _
end iterate

;------------------------------ Data ------------------------------------------
section '.data' data readable writeable

; GLSL sources (null-terminated single string each)
vs_src db \
        '#version 330 core',10,\
        'layout(location=0) in vec2 aPos;',10,\
        'layout(location=1) in vec3 aCol;',10,\
        'out vec3 vCol;',10,\
        'uniform float uTime;',10,\
        'void main(){',10,\
                'float c=cos(uTime), s=sin(uTime);',10,\
                'vec2 p = vec2(c*aPos.x - s*aPos.y, s*aPos.x + c*aPos.y);',10,\
                'gl_Position = vec4(p,0.0,1.0);',10,\
                'vCol = aCol;',10,\
        '}',0

fs_src db \
        '#version 330 core',10,\
        'in vec3 vCol;',10,\
        'out vec4 FragColor;',10,\
        'void main(){ FragColor = vec4(vCol,1.0); }',0

GLOBSTR.here
align 4

; Interleaved vertex data: vec2 position + vec3 color
; 3 vertices * (2+3) floats = 15 floats = 60 bytes
vertices:
  dd  0.0,  0.5,        1.0, 0.2, 0.3
  dd -0.5, -0.5,        0.2, 1.0, 0.3
  dd  0.5, -0.5,        0.2, 0.3, 1.0

vs_id           dd ?
fs_id           dd ?
program         dd ?
vao             dd ?
vbo             dd ?
uTimeLoc        dd ?
tmpi            dd ?

align 8
p_vs_src        dq vs_src
p_fs_src        dq fs_src
hWindow         dq ? ; GLFWwindow *

irpv CAFE,CONTEXT_AWARE_FUNCTION_ENTRIES
        CAFE dq ?
end irpv

;------------------------------ Code ------------------------------------------
section '.text' code readable executable

FramebufferSizeCallBack:
; RCX : GLFWwindow*
; EDX : int, width
; R8D : int, height
        enter 32, 0
        mov r9d, r8d
        mov r8d, edx
        invoke glViewport,0,0,r8d,r9d
        leave
        retn


start:  push rax

        invoke glfwInit
        test eax, eax
        jz .quit

        iterate <HINT,VALUE>,\
                GLFW_CONTEXT_VERSION_MAJOR, 3,\
                GLFW_CONTEXT_VERSION_MINOR, 3,\
                GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE

                invoke glfwWindowHint, HINT, VALUE
        end iterate

        invoke glfwCreateWindow, 800,600, 'fasm2 + glfw + gl 3.3', 0,0
        test rax, rax
        jz .term
        mov [hWindow], rax

        invoke  glfwMakeContextCurrent, [hWindow]
        invoke  glfwSwapInterval, 1

        invoke glViewport, 0,0, 800,600
        invoke glfwSetFramebufferSizeCallback, [hWindow],\
                addr FramebufferSizeCallBack

; --- load gl entry points via glfwGetProcAddress ---

        irpv CAFE,CONTEXT_AWARE_FUNCTION_ENTRIES
                invoke glfwGetProcAddress, `CAFE
                mov [CAFE], rax
        end irpv

; --- build pipeline: shaders -> program ---

        invoke glCreateShader,GL_VERTEX_SHADER
        mov [vs_id], eax
        invoke glShaderSource,[vs_id],1,addr p_vs_src,0
        invoke glCompileShader,[vs_id]

        invoke glCreateShader,GL_FRAGMENT_SHADER
        mov [fs_id], eax
        invoke glShaderSource,[fs_id],1,addr p_fs_src,0
        invoke glCompileShader,[fs_id]

        invoke glCreateProgram
        mov [program], eax

        ; attach + link

        invoke glAttachShader,[program],[vs_id]
        invoke glAttachShader,[program],[fs_id]

        invoke glLinkProgram,[program]

        invoke glDeleteShader,[vs_id]
        invoke glDeleteShader,[fs_id]

        invoke glUseProgram,[program]

        invoke glGetUniformLocation,[program],'uTime'
        mov [uTimeLoc], eax

; --- VAO/VBO and vertex format ---

        invoke glGenVertexArrays,1,addr vao
        invoke glBindVertexArray,[vao]

        invoke glGenBuffers,1,addr vbo
        invoke glBindBuffer,GL_ARRAY_BUFFER,[vbo]

        invoke glBufferData,GL_ARRAY_BUFFER,60,addr vertices,GL_STATIC_DRAW

        invoke glVertexAttribPointer,\; position
                0,\             ; index, layout(location=0)
                2,\             ; size(vec2)
                GL_FLOAT,\      ; type
                0,\             ; normalized
                20,\            ; stride(bytes)
                0               ; offset(bytes)
        invoke glEnableVertexAttribArray,0

        invoke glVertexAttribPointer,\; color
                1,\             ; index, layout(location=1)
                3,\             ; size(vec3)
                GL_FLOAT,\      ; type
                0,\             ; normalized
                20,\            ; stride(bytes)
                8               ; offset(bytes), skip vec2
        invoke glEnableVertexAttribArray,1
.loop:
        invoke glfwGetTime      ; returns double in xmm0
        cvtsd2ss xmm1, xmm0     ; -> float in xmm1
        invoke glUniform1f,[uTimeLoc],float xmm1

        invoke glClearColor,float dword 0.02,float dword 0.02,float dword 0.04,float dword 1.0
        invoke glClear,GL_COLOR_BUFFER_BIT

        invoke glDrawArrays,GL_TRIANGLES,0,3

        invoke  glfwSwapBuffers, [hWindow]
        invoke  glfwPollEvents
        invoke  glfwWindowShouldClose, [hWindow]
        test eax, eax
        jz .loop

.term:  invoke glfwTerminate
.quit:  invoke ExitProcess, 0
        jmp $

;------------------------------ Imports ----------------------------------------
section '.idata' import data readable writeable
library glfw3,'glfw3.dll',\
        kernel32,'kernel32.dll',\
        opengl32,'opengl32.dll'

import kernel32,\
        ExitProcess,'ExitProcess'

import glfw3,\
        glfwInit,'glfwInit',\
        glfwWindowHint,'glfwWindowHint',\
        glfwCreateWindow,'glfwCreateWindow',\
        glfwMakeContextCurrent,'glfwMakeContextCurrent',\
        glfwSwapInterval,'glfwSwapInterval',\
        glfwPollEvents,'glfwPollEvents',\
        glfwSwapBuffers,'glfwSwapBuffers',\
        glfwWindowShouldClose,'glfwWindowShouldClose',\
        glfwTerminate,'glfwTerminate',\
        glfwGetProcAddress,'glfwGetProcAddress',\
        glfwGetTime,'glfwGetTime',\
        glfwSetFramebufferSizeCallback,'glfwSetFramebufferSizeCallback'

import opengl32,\
        glClear,'glClear',\
        glClearColor,'glClearColor',\
        glViewport,'glViewport'    

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 03 Oct 2025, 16:22
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8454
Location: Kraków, Poland
Tomasz Grysztar 03 Oct 2025, 17:35
That's a nice example, perhaps we should move to the Examples forum?
Post 03 Oct 2025, 17:35
View user's profile Send private message Visit poster's website Reply with quote
wbutterdog



Joined: 01 Oct 2025
Posts: 7
wbutterdog 03 Oct 2025, 20:22
Dude Idk how to thank you enough. You literally just solved all my problems. Bless you m8
Post 03 Oct 2025, 20:22
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 21:37
Tomasz Grysztar wrote:
That's a nice example, perhaps we should move to the Examples forum?
I don't have that kind of power. (Just noticed: invoke parameters: float dword xmm2 doesn't work, float xmm2 isn't ignored when xmm2 is target.)

Here is the next natural progression, 3D box - keeping most calculations in the shader,
Code:
; build with: ..\..\fasm2\fasm2.cmd -e 5 glfw_box.asm
;------------------------------------------------------------------------------
; fasm 64-bit / Windows / GLFW 3.x / OpenGL 3.3 core
; - Creates a window and context
; - Loads GL 3.x entry points via glfwGetProcAddress
; - Compiles shaders that do 3D rotation + perspective
; - Sets up VAO/VBO/EBO for an indexed cube
; - Enables depth test
; - Per-frame uTime and uAspect uniforms
;------------------------------------------------------------------------------

format PE64 NX GUI 5.0
entry start

include 'win64a.inc'
include 'globstr.inc'
GLOBSTR.reuse := 1
macro fastcall?.inline_string var
        local data
        data GLOBSTR var,0
        redefine var data
end macro

;------------------------------ GL/GLFW consts --------------------------------
GL_COLOR_BUFFER_BIT     = 0x00004000
GL_DEPTH_BUFFER_BIT     = 0x00000100
GL_TRIANGLES            = 0x0004
GL_FLOAT                = 0x1406
GL_UNSIGNED_SHORT       = 0x1403
GL_ARRAY_BUFFER         = 0x8892
GL_ELEMENT_ARRAY_BUFFER = 0x8893
GL_STATIC_DRAW          = 0x88E4
GL_VERTEX_SHADER        = 0x8B31
GL_FRAGMENT_SHADER      = 0x8B30
GL_COMPILE_STATUS       = 0x8B81
GL_LINK_STATUS          = 0x8B82
GL_DEPTH_TEST           = 0x0B71
GL_CULL_FACE            = 0x0B44
GL_BACK                 = 0x0405
GL_CCW                  = 0x0901

GLFW_CONTEXT_VERSION_MAJOR = 0x00022002
GLFW_CONTEXT_VERSION_MINOR = 0x00022003
GLFW_OPENGL_PROFILE        = 0x00022008
GLFW_OPENGL_CORE_PROFILE   = 0x00032001

iterate _,\
        glCreateShader,\
        glShaderSource,\
        glCompileShader,\
        glGetShaderiv,\
        glCreateProgram,\
        glAttachShader,\
        glLinkProgram,\
        glGetProgramiv,\
        glDeleteShader,\
        glGenVertexArrays,\
        glBindVertexArray,\
        glGenBuffers,\
        glBindBuffer,\
        glBufferData,\
        glVertexAttribPointer,\
        glEnableVertexAttribArray,\
        glUseProgram,\
        glGetUniformLocation,\
        glUniform1f,\
        glDrawArrays,\
        glDrawElements

        define CONTEXT_AWARE_FUNCTION_ENTRIES _
end iterate

;------------------------------ Data ------------------------------------------
section '.data' data readable writeable

vs_src db \
'#version 330 core',10,\
'layout(location=0) in vec3 aPos;',10,\
'layout(location=1) in vec3 aCol;',10,\
'out vec3 vCol;',10,\
'uniform float uTime;',10,\
'uniform float uAspect;',10,\
'mat4 persp(float fov, float a, float zn, float zf){',10,\
'       float f = 1.0/tan(fov*0.5);',10,\
'       return mat4(',10,\
'               vec4(f/a,0,0,0),',10,\
'               vec4(0,f,0,0),',10,\
'               vec4(0,0,(zf+zn)/(zn-zf),-1),',10,\
'               vec4(0,0,(2.0*zf*zn)/(zn-zf),0));',10,\
'}',10,\
'void main(){',10,\
'       float c=cos(uTime), s=sin(uTime);',10,\
'       mat3 Rx = mat3(1,0,0, 0,c,-s, 0,s,c);',10,\
'       mat3 Ry = mat3(c,0,s, 0,1,0, -s,0,c);',10,\
'       vec3 p = Ry*(Rx*aPos);',10,\
'       vec4 pos = vec4(p,1.0);',10,\
'       pos.z -= 3.0;',10,\
'       mat4 P = persp(radians(60.0), uAspect, 0.1, 10.0);',10,\
'       gl_Position = P * pos;',10,\
'       vCol = aCol;',10,\
'}',0

fs_src db \
'#version 330 core',10,\
'in vec3 vCol;',10,\
'out vec4 FragColor;',10,\
'void main(){ FragColor = vec4(vCol,1.0); }',0

GLOBSTR.here
align 4

; Cube vertices: 8 * (pos.xyz + col.rgb) = 8 * 6 floats
; side = 1 centered at origin
vertices:
        ;     x     y     z     r    g    b
        dd  -0.5, -0.5,  0.5,  1.0, 0.2, 0.2    ; 0
        dd   0.5, -0.5,  0.5,  0.2, 1.0, 0.2    ; 1
        dd   0.5,  0.5,  0.5,  0.2, 0.2, 1.0    ; 2
        dd  -0.5,  0.5,  0.5,  1.0, 1.0, 0.2    ; 3
        dd  -0.5, -0.5, -0.5,  1.0, 0.2, 1.0    ; 4
        dd   0.5, -0.5, -0.5,  0.2, 1.0, 1.0    ; 5
        dd   0.5,  0.5, -0.5,  1.0, 0.6, 0.2    ; 6
        dd  -0.5,  0.5, -0.5,  0.2, 0.6, 1.0    ; 7

; Indices: 12 triangles -> 36 uint16
indices dw \
        0,1,2,  2,3,0,\ ; front
        1,5,6,  6,2,1,\ ; right
        7,6,5,  5,4,7,\ ; back
        4,0,3,  3,7,4,\ ; left
        4,5,1,  1,0,4,\ ; bottom
        3,2,6,  6,7,3   ; top

vs_id           dd ?
fs_id           dd ?
program         dd ?
vao             dd ?
vbo             dd ?
ebo             dd ?
uTimeLoc        dd ?
uAspectLoc      dd ?
fb_w            dd ?
fb_h            dd ?
tmpi            dd ?

align 8
p_vs_src        dq vs_src
p_fs_src        dq fs_src
hWindow         dq ? ; GLFWwindow*

irpv CAFE,CONTEXT_AWARE_FUNCTION_ENTRIES
        CAFE dq ?
end irpv

;------------------------------ Code ------------------------------------------
section '.text' code readable executable

FramebufferSizeCallback:
; RCX : GLFWwindow*
; EDX : width
; R8D : height
        enter 32, 0
        mov r9d, r8d
        mov r8d, edx
        invoke glViewport,0,0,r8d,r9d
        leave
        retn

start:  push rax

        invoke glfwInit
        test eax, eax
        jz .quit

        iterate <HINT,VALUE>,\
                GLFW_CONTEXT_VERSION_MAJOR, 3,\
                GLFW_CONTEXT_VERSION_MINOR, 3,\
                GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE

                invoke glfwWindowHint, HINT, VALUE
        end iterate

        invoke glfwCreateWindow, 512,512, 'fasm2 + glfw + cube', 0,0
        test rax, rax
        jz .term
        mov [hWindow], rax

        invoke glfwMakeContextCurrent, [hWindow]
        invoke glfwSwapInterval, 1

        invoke glViewport, 0,0, 512,512
        invoke glfwSetFramebufferSizeCallback, [hWindow],\
                addr FramebufferSizeCallback

; --- load GL entry points via glfwGetProcAddress ---

        irpv CAFE,CONTEXT_AWARE_FUNCTION_ENTRIES
                invoke glfwGetProcAddress, `CAFE
                mov [CAFE], rax
        end irpv

; --- pipeline: shaders -> program ---

        invoke glCreateShader,GL_VERTEX_SHADER
        mov [vs_id], eax
        invoke glShaderSource,[vs_id],1,addr p_vs_src,0
        invoke glCompileShader,[vs_id]

        invoke glCreateShader,GL_FRAGMENT_SHADER
        mov [fs_id], eax
        invoke glShaderSource,[fs_id],1,addr p_fs_src,0
        invoke glCompileShader,[fs_id]

        invoke glCreateProgram
        mov [program], eax
        invoke glAttachShader,[program],[vs_id]
        invoke glAttachShader,[program],[fs_id]
        invoke glLinkProgram,[program]
        invoke glDeleteShader,[vs_id]
        invoke glDeleteShader,[fs_id]
        invoke glUseProgram,[program]

        invoke glGetUniformLocation,[program],'uTime'
        mov [uTimeLoc], eax
        invoke glGetUniformLocation,[program],'uAspect'
        mov [uAspectLoc], eax

; --- VAO / VBO / EBO ---

        invoke glGenVertexArrays,1,addr vao
        invoke glBindVertexArray,[vao]

        invoke glGenBuffers,1,addr vbo
        invoke glBindBuffer,GL_ARRAY_BUFFER,[vbo]
        ; 8 verts * 6 floats * 4 = 192 bytes
        invoke glBufferData,GL_ARRAY_BUFFER,192,addr vertices,GL_STATIC_DRAW

        invoke glGenBuffers,1,addr ebo
        invoke glBindBuffer,GL_ELEMENT_ARRAY_BUFFER,[ebo]
        ; 36 indices * 2 bytes = 72 bytes
        invoke glBufferData,GL_ELEMENT_ARRAY_BUFFER,72,addr indices,GL_STATIC_DRAW

        ; layout(location=0) vec3 aPos
        invoke glVertexAttribPointer,0,3,GL_FLOAT,0,24,0
        invoke glEnableVertexAttribArray,0

        ; layout(location=1) vec3 aCol
        invoke glVertexAttribPointer,1,3,GL_FLOAT,0,24,12
        invoke glEnableVertexAttribArray,1

        ; depth test
        invoke glEnable,GL_DEPTH_TEST

        ; back-face culling (performance optimization)
        invoke glEnable,GL_CULL_FACE
        invoke glCullFace,GL_BACK
        invoke glFrontFace,GL_CCW

.loop:  invoke glfwGetTime
        cvtsd2ss xmm1, xmm0
        invoke glUniform1f,[uTimeLoc],float xmm1

        ; get fb size, update uAspect - keep the box looking boxy
        invoke glfwGetFramebufferSize,[hWindow],addr fb_w,addr fb_h
        mov eax, [fb_w]
        cvtsi2ss xmm1, eax
        mov eax, [fb_h]
        cvtsi2ss xmm0, eax
        divss xmm1, xmm0
        invoke glUniform1f,[uAspectLoc],float xmm1

        ; clear color + depth
        invoke glClearColor,float dword 0.02,float dword 0.02,float dword 0.04,float dword 1.0
        invoke glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT

        ; draw indexed cube
        invoke glDrawElements, GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0

        invoke glfwSwapBuffers,[hWindow]
        invoke glfwPollEvents
        invoke glfwWindowShouldClose,[hWindow]
        test eax, eax
        jz .loop

.term:  invoke glfwTerminate
.quit:  invoke ExitProcess,0
        jmp $

;------------------------------ Imports ----------------------------------------
section '.idata' import data readable writeable
library glfw3,'glfw3.dll',\
        kernel32,'kernel32.dll',\
        opengl32,'opengl32.dll'

import kernel32,\
        ExitProcess,'ExitProcess'

import glfw3,\
        glfwInit,'glfwInit',\
        glfwWindowHint,'glfwWindowHint',\
        glfwCreateWindow,'glfwCreateWindow',\
        glfwMakeContextCurrent,'glfwMakeContextCurrent',\
        glfwSwapInterval,'glfwSwapInterval',\
        glfwPollEvents,'glfwPollEvents',\
        glfwSwapBuffers,'glfwSwapBuffers',\
        glfwWindowShouldClose,'glfwWindowShouldClose',\
        glfwTerminate,'glfwTerminate',\
        glfwGetProcAddress,'glfwGetProcAddress',\
        glfwGetTime,'glfwGetTime',\
        glfwSetFramebufferSizeCallback,'glfwSetFramebufferSizeCallback',\
        glfwGetFramebufferSize,'glfwGetFramebufferSize'

import opengl32,\
        glClear,'glClear',\
        glClearColor,'glClearColor',\
        glViewport,'glViewport',\
        glEnable,'glEnable',\
        glCullFace,'glCullFace',\
        glFrontFace,'glFrontFace'    
Edit: uAspect backward fix, add back-face culling.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.


Last edited by bitRAKE on 03 Oct 2025, 22:16; edited 2 times in total
Post 03 Oct 2025, 21:37
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8454
Location: Kraków, Poland
Tomasz Grysztar 03 Oct 2025, 21:55
I tried to combine your code with my ancient OpenGL example (the one shipped with fasm) and got a variant that works without GLFW:
Code:
format PE64 NX GUI 5.0
entry start

include 'win64a.inc'

WGL_CONTEXT_MAJOR_VERSION_ARB := 0x2091
WGL_CONTEXT_MINOR_VERSION_ARB := 0x2092

GL_COLOR_BUFFER_BIT        = 0x00004000
GL_TRIANGLES               = 0x0004
GL_FLOAT                   = 0x1406
GL_ARRAY_BUFFER            = 0x8892
GL_STATIC_DRAW             = 0x88E4
GL_VERTEX_SHADER           = 0x8B31
GL_FRAGMENT_SHADER         = 0x8B30
GL_COMPILE_STATUS          = 0x8B81
GL_LINK_STATUS             = 0x8B82

iterate name,\
        glCreateShader,\
        glShaderSource,\
        glCompileShader,\
        glGetShaderiv,\
        glCreateProgram,\
        glAttachShader,\
        glLinkProgram,\
        glGetProgramiv,\
        glDeleteShader,\
        glGenVertexArrays,\
        glBindVertexArray,\
        glGenBuffers,\
        glBindBuffer,\
        glBufferData,\
        glVertexAttribPointer,\
        glEnableVertexAttribArray,\
        glUseProgram,\
        glGetUniformLocation,\
        glUniform1f,\
        glDrawArrays

        define CONTEXT_AWARE_FUNCTION name

end iterate

section '.rdata' data readable

  _title db 'OpenGL 3.3',0
  _class db 'FASM2OPENGL33',0

  _wglCreateContextAttribsARB db 'wglCreateContextAttribsARB',0

  irpv name, CONTEXT_AWARE_FUNCTION
        _#name db `name,0
  end irpv

  attribList    dd WGL_CONTEXT_MAJOR_VERSION_ARB, 3
                dd WGL_CONTEXT_MINOR_VERSION_ARB, 3
                dd 0

  vs_src db \
        '#version 330 core',10,\
        'layout(location=0) in vec2 aPos;',10,\
        'layout(location=1) in vec3 aCol;',10,\
        'out vec3 vCol;',10,\
        'uniform float uTime;',10,\
        'void main(){',10,\
                'float c=cos(uTime), s=sin(uTime);',10,\
                'vec2 p = vec2(c*aPos.x - s*aPos.y, s*aPos.x + c*aPos.y);',10,\
                'gl_Position = vec4(p,0.0,1.0);',10,\
                'vCol = aCol;',10,\
        '}',0

  fs_src db \
        '#version 330 core',10,\
        'in vec3 vCol;',10,\
        'out vec4 FragColor;',10,\
        'void main(){ FragColor = vec4(vCol,1.0); }',0


section '.data' data readable writeable

  vertices:
        dd  0.0,  0.5,        1.0, 0.2, 0.3
        dd -0.5, -0.5,        0.2, 1.0, 0.3
        dd  0.5, -0.5,        0.2, 0.3, 1.0

  thousand dd 1000.0

  p_vs_src dq vs_src
  p_fs_src dq fs_src

  wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,NULL,NULL,_class

  hdc dq ?
  hrc dq ?

  msg MSG
  rc RECT
  pfd PIXELFORMATDESCRIPTOR

  wglCreateContextAttribsARB dq ?

  irpv name, CONTEXT_AWARE_FUNCTION
        name dq ?
  end irpv

  vs_id           dd ?
  fs_id           dd ?
  program         dd ?
  vao             dd ?
  vbo             dd ?
  uTimeLoc        dd ?

section '.text' code readable executable

  start:
        sub     rsp,8

        invoke  GetModuleHandle,0
        mov     [wc.hInstance],rax
        invoke  LoadIcon,0,IDI_APPLICATION
        mov     [wc.hIcon],rax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],rax
        invoke  RegisterClass,wc
        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS,16,16,432,432,NULL,NULL,[wc.hInstance],NULL

  msg_loop:
        invoke  GetMessage,addr msg,NULL,0,0
        cmp     eax,1
        jb      end_loop
        jne     msg_loop
        invoke  TranslateMessage,addr msg
        invoke  DispatchMessage,addr msg
        jmp     msg_loop

  end_loop:
        invoke  ExitProcess,[msg.wParam]

proc WindowProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam
        mov     [hwnd],rcx
        frame
        cmp     edx,WM_CREATE
        je      wmcreate
        cmp     edx,WM_SIZE
        je      wmsize
        cmp     edx,WM_PAINT
        je      wmpaint
        cmp     edx,WM_KEYDOWN
        je      wmkeydown
        cmp     edx,WM_DESTROY
        je      wmdestroy
  defwndproc:
        invoke  DefWindowProc,rcx,rdx,r8,r9
        jmp     finish
  wmcreate:
        invoke  GetDC,rcx
        mov     [hdc],rax
        lea     rdi,[pfd]
        mov     rcx,sizeof.PIXELFORMATDESCRIPTOR shr 3
        xor     eax,eax
        rep     stosq
        mov     [pfd.nSize],sizeof.PIXELFORMATDESCRIPTOR
        mov     [pfd.nVersion],1
        mov     [pfd.dwFlags],PFD_SUPPORT_OPENGL+PFD_DOUBLEBUFFER+PFD_DRAW_TO_WINDOW
        mov     [pfd.iLayerType],PFD_MAIN_PLANE
        mov     [pfd.iPixelType],PFD_TYPE_RGBA
        mov     [pfd.cColorBits],32
        mov     [pfd.cAlphaBits],8
        mov     [pfd.cDepthBits],24
        mov     [pfd.cStencilBits],8
        invoke  ChoosePixelFormat,[hdc],addr pfd
        invoke  SetPixelFormat,[hdc],eax,addr pfd

        invoke  wglCreateContext,[hdc]
        mov     [hrc],rax
        invoke  wglMakeCurrent,[hdc],[hrc]

        invoke  wglGetProcAddress,_wglCreateContextAttribsARB
        mov     [wglCreateContextAttribsARB],rax

        invoke  wglDeleteContext,[hrc]
        invoke  wglCreateContextAttribsARB,[hdc],0,attribList
        test    eax,eax
        jz      failed
        mov     [hrc],rax
        invoke  wglMakeCurrent,[hdc],[hrc]

  irpv name, CONTEXT_AWARE_FUNCTION
        invoke  wglGetProcAddress,_#name
        mov     [name],rax
  end irpv

        invoke  GetClientRect,[hwnd],addr rc
        invoke  glViewport,0,0,[rc.right],[rc.bottom]

; --- build pipeline: shaders -> program ---

        invoke glCreateShader,GL_VERTEX_SHADER
        mov [vs_id], eax
        invoke glShaderSource,[vs_id],1,addr p_vs_src,0
        invoke glCompileShader,[vs_id]

        invoke glCreateShader,GL_FRAGMENT_SHADER
        mov [fs_id], eax
        invoke glShaderSource,[fs_id],1,addr p_fs_src,0
        invoke glCompileShader,[fs_id]

        invoke glCreateProgram
        mov [program], eax

        ; attach + link

        invoke glAttachShader,[program],[vs_id]
        invoke glAttachShader,[program],[fs_id]

        invoke glLinkProgram,[program]

        invoke glDeleteShader,[vs_id]
        invoke glDeleteShader,[fs_id]

        invoke glUseProgram,[program]

        invoke glGetUniformLocation,[program],'uTime'
        mov [uTimeLoc], eax

; --- VAO/VBO and vertex format ---

        invoke glGenVertexArrays,1,addr vao
        invoke glBindVertexArray,[vao]

        invoke glGenBuffers,1,addr vbo
        invoke glBindBuffer,GL_ARRAY_BUFFER,[vbo]

        invoke glBufferData,GL_ARRAY_BUFFER,60,addr vertices,GL_STATIC_DRAW

        invoke glVertexAttribPointer,\; position
                0,\             ; index, layout(location=0)
                2,\             ; size(vec2)
                GL_FLOAT,\      ; type
                0,\             ; normalized
                20,\            ; stride(bytes)
                0               ; offset(bytes)
        invoke glEnableVertexAttribArray,0

        invoke glVertexAttribPointer,\; color
                1,\             ; index, layout(location=1)
                3,\             ; size(vec3)
                GL_FLOAT,\      ; type
                0,\             ; normalized
                20,\            ; stride(bytes)
                8               ; offset(bytes), skip vec2
        invoke glEnableVertexAttribArray,1

        xor     eax,eax
        jmp     finish
  wmsize:
        invoke  GetClientRect,[hwnd],addr rc
        invoke  glViewport,0,0,[rc.right],[rc.bottom]
        xor     eax,eax
        jmp     finish
  wmpaint:
        invoke  GetTickCount
        cvtsi2ss xmm1,rax
        divss   xmm1,[thousand]
        invoke  glUniform1f,[uTimeLoc],float xmm1

        invoke  glClearColor,float dword 0.02,float dword 0.02,float dword 0.04,float dword 1.0
        invoke  glClear,GL_COLOR_BUFFER_BIT

        invoke  glDrawArrays,GL_TRIANGLES,0,3

        invoke  SwapBuffers,[hdc]
        xor     eax,eax
        jmp     finish
  wmkeydown:
        cmp     r8d,VK_ESCAPE
        jne     defwndproc
  wmdestroy:
        invoke  wglMakeCurrent,0,0
        invoke  wglDeleteContext,[hrc]
  failed:
        invoke  ReleaseDC,[hwnd],[hdc]
        invoke  PostQuitMessage,0
        xor     eax,eax
  finish:
        endf
        ret
endp

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          gdi,'GDI32.DLL',\
          opengl,'OPENGL32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         GetTickCount,'GetTickCount',\
         ExitProcess,'ExitProcess'

  import user,\
         RegisterClass,'RegisterClassA',\
         CreateWindowEx,'CreateWindowExA',\
         DefWindowProc,'DefWindowProcA',\
         GetMessage,'GetMessageA',\
         TranslateMessage,'TranslateMessage',\
         DispatchMessage,'DispatchMessageA',\
         LoadCursor,'LoadCursorA',\
         LoadIcon,'LoadIconA',\
         GetClientRect,'GetClientRect',\
         GetDC,'GetDC',\
         ReleaseDC,'ReleaseDC',\
         PostQuitMessage,'PostQuitMessage'

  import gdi,\
         ChoosePixelFormat,'ChoosePixelFormat',\
         SetPixelFormat,'SetPixelFormat',\
         SwapBuffers,'SwapBuffers'

  import opengl,\
         glClear,'glClear',\
         glClearColor,'glClearColor',\
         glViewport,'glViewport',\
         wglGetProcAddress,'wglGetProcAddress',\
         wglCreateContext,'wglCreateContext',\
         wglDeleteContext,'wglDeleteContext',\
         wglMakeCurrent,'wglMakeCurrent'    
I'm thinking about making a nice example for fasm2 package this way. Needs better error handling, though.
Post 03 Oct 2025, 21:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 03 Oct 2025, 22:41
Tomasz Grysztar wrote:
I'm thinking about making a nice example for fasm2 package this way. Needs better error handling, though.
I hadn't really used glfw before - it doesn't feel like it's doing much in these examples, but renaming Windows API conventions. Perhaps it's easier for someone coming from another environment?

I should have noted that the only error checking is glfwInit/glfwCreateWindow - so much missing! In the past I've created macros for a common error reporting.
Code:
calminstruction ✓ line& ; very simple HRESULT error debug helper
        assemble line
        arrange line,=mov =r8d,=__LINE__
        assemble line
        arrange line,=test =eax,=eax
        assemble line
        arrange line,=js .=HR_FAILURE
        assemble line
end calminstruction    
... something that doesn't really make the code harder to follow, imho.

Vulkan has an error reporting layer - which is nice once configured.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 03 Oct 2025, 22:41
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 04 Oct 2025, 00:12
Instancing is mostly handled in the shader as well - another abstraction where each is given a gl_InstanceID.


Description: rotating around 8000 rotating cubes
Download
Filename: 3_glfw_instanced.zip
Filesize: 4 KB
Downloaded: 13 Time(s)


_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 04 Oct 2025, 00:12
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8454
Location: Kraków, Poland
Tomasz Grysztar 04 Oct 2025, 09:05
I used this as an inspiration to remake the old example for fasm2 and this is now another of the basic examples coming packaged with fasm2: https://github.com/tgrysztar/fasm2/tree/master/examples/opengl

I believe it can serve as a nice minimalistic tool to start playing with shaders. I may update the example with something fun.
Post 04 Oct 2025, 09:05
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8454
Location: Kraków, Poland
Tomasz Grysztar 04 Oct 2025, 11:52
The updated version is there, I modified it to provide some minimal compatibility with Shadertoy and even included one of their small eye-candy shaders. Their default license is "Attribution-NonCommercial-ShareAlike", so I believe linking to the original author should be enough, with fasm2 being non-commercial project.

You can replace the "mainImage" function in "fragment.glsl" with one of the simple Shadertoy examples and it might work. The visuals are not exactly the same, as I've put the image into a rotating square, inherited from the original example distributed with fasm 1. It's all a bit of a fun remix.

To make it not rotate and fill the entire viewport with image, you can modify "vertex.glsl" like this:
Code:
#version 330 core
layout(location=0) in vec2 aPos;
layout(location=1) in vec3 aCol;
out vec3 vCol;
uniform float iTime;
void main(){
        gl_Position = vec4(aPos/0.6,0.0,1.0);
        vCol = aCol;
}    


bitRAKE, it seems we went in different directions, and I would love to see more of your work. Are you going to publish examples in one of your repositiories?
Post 04 Oct 2025, 11:52
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4288
Location: vpcmpistri
bitRAKE 04 Oct 2025, 19:30
When it comes to shaders, aligning with ShaderToy is certainly a good choice - so much talent there.

These examples might find a place somewhere, but the "invoke"/PE style is away from the direction I'm going. I'm more interested in building language layers in the style of fasmg - less difference between functions and macros. Supporting various features at the interface during assemble-time. And this style aligns better with object file creation, imho. My published work will be along those lines.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 04 Oct 2025, 19:30
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8454
Location: Kraków, Poland
Tomasz Grysztar 05 Oct 2025, 11:50
bitRAKE wrote:
These examples might find a place somewhere, but the "invoke"/PE style is away from the direction I'm going. I'm more interested in building language layers in the style of fasmg - less difference between functions and macros. Supporting various features at the interface during assemble-time. And this style aligns better with object file creation, imho. My published work will be along those lines.
Then you are likely making much better use of fasmg engine than I am. My example does not really need fasm2, it can be easily adapted to assemble with fasm 1, with only minor changes:
Code:
; Backported to fasm 1 syntax

format PE64 NX GUI 5.0
entry start

include 'win64a.inc'

WGL_CONTEXT_MAJOR_VERSION_ARB   = 0x2091
WGL_CONTEXT_MINOR_VERSION_ARB   = 0x2092

GL_COLOR_BUFFER_BIT     = 0x00004000
GL_TRIANGLES            = 0x0004
GL_TRIANGLE_STRIP       = 0x0005
GL_FLOAT                = 0x1406
GL_ARRAY_BUFFER         = 0x8892
GL_STATIC_DRAW          = 0x88E4
GL_VERTEX_SHADER        = 0x8B31
GL_FRAGMENT_SHADER      = 0x8B30
GL_COMPILE_STATUS       = 0x8B81
GL_LINK_STATUS          = 0x8B82

irp name,\
        glCreateShader,\
        glShaderSource,\
        glCompileShader,\
        glGetShaderiv,\
        glCreateProgram,\
        glAttachShader,\
        glLinkProgram,\
        glGetProgramiv,\
        glDeleteShader,\
        glGenVertexArrays,\
        glBindVertexArray,\
        glGenBuffers,\
        glBindBuffer,\
        glBufferData,\
        glVertexAttribPointer,\
        glEnableVertexAttribArray,\
        glUseProgram,\
        glGetUniformLocation,\
        glUniform1f,\
        glUniform3f     { define CONTEXT_AWARE_FUNCTION name }

section '.data' data readable writeable

  wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,NULL,NULL,_class

  attribs:
        dd WGL_CONTEXT_MAJOR_VERSION_ARB, 3
        dd WGL_CONTEXT_MINOR_VERSION_ARB, 3
        dd 0

  vertices:
        dd  0.6, 0.6,           0.1, 0.1, 1.0
        dd  -0.6, 0.6,          1.0, 0.1, 1.0
        dd  0.6, -0.6,          0.1, 0.1, 0.1
        dd  -0.6, -0.6,         1.0, 0.1, 0.1

  thousand dd 1000.0

  align 8

  p_vs_src dq vs_src
  p_fs_src dq fs_src

  hdc dq ?
  hrc dq ?

  clock dq ?

  msg MSG
  rc RECT
  pfd PIXELFORMATDESCRIPTOR

  wglCreateContextAttribsARB dq ?

  irpv name, CONTEXT_AWARE_FUNCTION { name dq ? }

  vs_id dd ?
  fs_id dd ?
  program dd ?
  vao dd ?
  vbo dd ?

  uTimeLoc dd ?
  uResolutionLoc dd ?

section '.text' code readable executable

  start:
        sub     rsp,8
        invoke  GetModuleHandle,0
        mov     [wc.hInstance],rax
        invoke  LoadIcon,0,IDI_APPLICATION
        mov     [wc.hIcon],rax
        invoke  LoadCursor,0,IDC_ARROW
        mov     [wc.hCursor],rax
        invoke  RegisterClass,wc
        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_OVERLAPPEDWINDOW+WS_CLIPCHILDREN+WS_CLIPSIBLINGS,16,16,432,432,NULL,NULL,[wc.hInstance],NULL

  msg_loop:
        invoke  GetMessage,addr msg,NULL,0,0
        cmp     eax,1
        jb      end_loop
        jne     msg_loop
        invoke  TranslateMessage,addr msg
        invoke  DispatchMessage,addr msg
        jmp     msg_loop

  end_loop:
        invoke  ExitProcess,[msg.wParam]

proc WindowProc uses rbx rsi rdi, hwnd,wmsg,wparam,lparam
        frame
        mov     [hwnd],rcx
        cmp     edx,WM_CREATE
        je      wmcreate
        cmp     edx,WM_SIZE
        je      wmsize
        cmp     edx,WM_PAINT
        je      wmpaint
        cmp     edx,WM_KEYDOWN
        je      wmkeydown
        cmp     edx,WM_DESTROY
        je      wmdestroy
  defwndproc:
        invoke  DefWindowProc,rcx,rdx,r8,r9
        jmp     finish
  wmcreate:
        invoke  GetDC,rcx
        mov     [hdc],rax
        lea     rdi,[pfd]
        mov     rcx,sizeof.PIXELFORMATDESCRIPTOR shr 3
        xor     eax,eax
        rep     stosq
        mov     [pfd.nSize],sizeof.PIXELFORMATDESCRIPTOR
        mov     [pfd.nVersion],1
        mov     [pfd.dwFlags],PFD_SUPPORT_OPENGL+PFD_DOUBLEBUFFER+PFD_DRAW_TO_WINDOW
        mov     [pfd.iLayerType],PFD_MAIN_PLANE
        mov     [pfd.iPixelType],PFD_TYPE_RGBA
        mov     [pfd.cColorBits],32
        mov     [pfd.cAlphaBits],8
        mov     [pfd.cDepthBits],24
        mov     [pfd.cStencilBits],8
        invoke  ChoosePixelFormat,[hdc],addr pfd
        invoke  SetPixelFormat,[hdc],eax,addr pfd

        invoke  wglCreateContext,[hdc]
        test    rax,rax
        jz      context_not_created
        mov     [hrc],rax
        invoke  wglMakeCurrent,[hdc],[hrc]

        lea     rbx,[_wglCreateContextAttribsARB]       ; name pointer in rbx for error handler
        invoke  wglGetProcAddress,rbx
        test    rax,rax
        jz      function_not_supported
        mov     [wglCreateContextAttribsARB],rax

        invoke  wglDeleteContext,[hrc]
        invoke  wglCreateContextAttribsARB,[hdc],0,attribs
        test    rax,rax
        jz      context_not_created
        mov     [hrc],rax
        invoke  wglMakeCurrent,[hdc],[hrc]

  irpv name, CONTEXT_AWARE_FUNCTION {
        lea     rbx,[_#name]                            ; name pointer in rbx for error handler
        invoke  wglGetProcAddress,rbx
        test    rax,rax
        jz      function_not_supported
        mov     [name],rax
  }

        invoke  glCreateShader,GL_VERTEX_SHADER
        mov     [vs_id],eax
        invoke  glShaderSource,[vs_id],1,addr p_vs_src,0
        invoke  glCompileShader,[vs_id]

        invoke  glCreateShader,GL_FRAGMENT_SHADER
        mov     [fs_id],eax
        invoke  glShaderSource,[fs_id],1,addr p_fs_src,0
        invoke  glCompileShader,[fs_id]

        invoke  glCreateProgram
        mov     [program],eax

        invoke  glAttachShader,[program],[vs_id]
        invoke  glAttachShader,[program],[fs_id]

        invoke  glLinkProgram,[program]

        invoke  glDeleteShader,[vs_id]
        invoke  glDeleteShader,[fs_id]

        invoke  glUseProgram,[program]

        invoke  glGetUniformLocation,[program],uTime
        mov     [uTimeLoc],eax
        invoke  glGetUniformLocation,[program],uResolution
        mov     [uResolutionLoc],eax

        invoke  glGenVertexArrays,1,addr vao
        invoke  glBindVertexArray,[vao]

        invoke  glGenBuffers,1,addr vbo
        invoke  glBindBuffer,GL_ARRAY_BUFFER,[vbo]

        invoke  glBufferData,GL_ARRAY_BUFFER,4*5*4,addr vertices,GL_STATIC_DRAW

        invoke  glVertexAttribPointer,\ ; position
                        0,\             ; index, layout(location=0)
                        2,\             ; size(vec2)
                        GL_FLOAT,\      ; type
                        0,\             ; normalized
                        20,\            ; stride(bytes)
                        0               ; offset(bytes)
        invoke  glEnableVertexAttribArray,0

        invoke  glVertexAttribPointer,\ ; color
                        1,\             ; index, layout(location=1)
                        3,\             ; size(vec3)
                        GL_FLOAT,\      ; type
                        0,\             ; normalized
                        20,\            ; stride(bytes)
                        8               ; offset(bytes), skip vec2
        invoke  glEnableVertexAttribArray,1


  wmsize:
        invoke  GetClientRect,[hwnd],addr rc
        invoke  glViewport,0,0,[rc.right],[rc.bottom]
        cvtsi2ss xmm1,[rc.right]
        cvtsi2ss xmm2,[rc.bottom]
        invoke  glUniform3f,[uResolutionLoc],float xmm1,float xmm2,float 1f
        xor     eax,eax
        jmp     finish
  wmpaint:
        invoke  GetTickCount
        mov     rcx,rax
        sub     rcx,[clock]
        cmp     rcx,10          ; wait at least 10ms before drawing again
        jb      finish
        mov     [clock],rax

        cvtsi2ss xmm1,rax
        divss   xmm1,[thousand]
        invoke  glUniform1f,[uTimeLoc],float xmm1

        invoke  glClearColor,float dword 0.02,float dword 0.02,float dword 0.04,float dword 1.0
        invoke  glClear,GL_COLOR_BUFFER_BIT

        invoke  glDrawArrays,GL_TRIANGLE_STRIP,0,4

        invoke  SwapBuffers,[hdc]
        xor     eax,eax
        jmp     finish
  wmkeydown:
        cmp     r8d,VK_ESCAPE
        jne     defwndproc
  wmdestroy:
        invoke  wglMakeCurrent,0,0
        invoke  wglDeleteContext,[hrc]
  exit:
        invoke  ReleaseDC,[hwnd],[hdc]
        invoke  PostQuitMessage,0
        xor     eax,eax
  finish:
        ret
  function_not_supported:
        invoke  MessageBox,[hwnd],_function_not_supported,rbx,MB_ICONERROR+MB_OK
        jmp     exit
  context_not_created:
        invoke  MessageBox,[hwnd],_context_not_created,NULL,MB_ICONERROR+MB_OK
        jmp     exit
        endf
endp

section '.rdata' data readable

  _title db 'OpenGL 3.3',0
  _class db 'OPENGL3FASM2',0

  _function_not_supported db 'Function not supported.',0
  _context_not_created db 'Failed to create OpenGL context.',0

  _wglCreateContextAttribsARB db 'wglCreateContextAttribsARB',0

  irpv name, CONTEXT_AWARE_FUNCTION { _#name db `name,0 }

  vs_src file 'vertex.glsl'
         db 0

  fs_src file 'fragment.glsl'
         db 0

  uTime db 'iTime',0
  uResolution db 'iResolution',0

  align 8

  data import

  library kernel,'KERNEL32.DLL',\
          user,'USER32.DLL',\
          gdi,'GDI32.DLL',\
          opengl,'OPENGL32.DLL'

  import kernel,\
         GetModuleHandle,'GetModuleHandleA',\
         GetTickCount,'GetTickCount',\
         ExitProcess,'ExitProcess'

  import user,\
         MessageBox,'MessageBoxA',\
         RegisterClass,'RegisterClassA',\
         CreateWindowEx,'CreateWindowExA',\
         DefWindowProc,'DefWindowProcA',\
         GetMessage,'GetMessageA',\
         TranslateMessage,'TranslateMessage',\
         DispatchMessage,'DispatchMessageA',\
         LoadCursor,'LoadCursorA',\
         LoadIcon,'LoadIconA',\
         GetClientRect,'GetClientRect',\
         GetDC,'GetDC',\
         ReleaseDC,'ReleaseDC',\
         PostQuitMessage,'PostQuitMessage'

  import gdi,\
         ChoosePixelFormat,'ChoosePixelFormat',\
         SetPixelFormat,'SetPixelFormat',\
         SwapBuffers,'SwapBuffers'

  import opengl,\
         glClear,'glClear',\
         glClearColor,'glClearColor',\
         glViewport,'glViewport',\
         glDrawArrays,'glDrawArrays',\
         wglGetProcAddress,'wglGetProcAddress',\
         wglCreateContext,'wglCreateContext',\
         wglDeleteContext,'wglDeleteContext',\
         wglMakeCurrent,'wglMakeCurrent'

  end data    
Post 05 Oct 2025, 11:50
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.