flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
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' _________________ ¯\(°_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 |
|||
![]() |
|
wbutterdog 03 Oct 2025, 13:51
Quote:
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? |
|||
![]() |
|
bitRAKE 03 Oct 2025, 13:59
Because that is what I wrote the code for.
|
|||
![]() |
|
wbutterdog 03 Oct 2025, 14:19
Okay cool thanks, also just quick:
what does the '.\fasm2.cmd -e 5 glfw0.asm' comment mean? |
|||
![]() |
|
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.
|
|||
![]() |
|
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. |
|||
![]() |
|
Tomasz Grysztar 03 Oct 2025, 17:35
That's a nice example, perhaps we should move to the Examples forum?
|
|||
![]() |
|
wbutterdog 03 Oct 2025, 20:22
Dude Idk how to thank you enough. You literally just solved all my problems. Bless you m8
|
|||
![]() |
|
bitRAKE 03 Oct 2025, 21:37
Tomasz Grysztar wrote: That's a nice example, perhaps we should move to the Examples forum? 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' _________________ ¯\(°_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 |
|||
![]() |
|
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' |
|||
![]() |
|
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 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 Vulkan has an error reporting layer - which is nice once configured. _________________ ¯\(°_o)/¯ AI may [not] have aided with the above reply. |
|||
![]() |
|
bitRAKE 04 Oct 2025, 00:12
Instancing is mostly handled in the shader as well - another abstraction where each is given a gl_InstanceID.
_________________ ¯\(°_o)/¯ AI may [not] have aided with the above reply. |
|||||||||||
![]() |
|
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. |
|||
![]() |
|
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? |
|||
![]() |
|
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. |
|||
![]() |
|
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. 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 |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.