i am following NEHE's turtorial here http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=03
and combined with hitchhiker's example OPENGL.ASM
the app is working except for the color of triangle isn't shown(should be different color at different vertex).
can someone tell me what is wrong with this ASM?
( light properties are in .DATA paragraph. triangle drawing function is at the bottom ,in drawscene proc )
=============================================================
.586
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\opengl32.inc
include \masm32\include\glu32.inc
include \masm32\macros\macros.asm
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\opengl32.lib
includelib \masm32\lib\glu32.lib
wininit proto :dword,:dword,:dword,:dword
setlight proto :dword,:dword,:dword,:dword,:dword,:dword,\
:dword,:dword,:dword,:dword,:dword
.data
classname db "GLVIEWPORT0",0
appname db "GLTEST",0
quitmsg db "Are you sure?",0
hInstance dd 0
hwnd dd 0
mainhdc dd 0
opendc dd 0
winwidth dd 0
winheight dd 0
viewaspect dq 0
fov dq 45.0
nearclip dq 0.1
farclip dq 1000.0
key db 256 dup(0)
even
active db 1
value1dbl dq 1.0
pixfrm PIXELFORMATDESCRIPTOR <>
light1pos dd 0.0,0.0,4.0,0.0
light1color dd 0.8,0.8,0.8,1.0
light1diffuse dd 0.5,0.5,0.5,1.0
light1specular dd 0.5,0.5,0.5,1.0
spotcut1 dd -1.0
spotexp1 dd 0.0
spotdir1 dd -1.0,-1.0,-1.0
light1const dd 0.5
light1lin dd 0.5
light1quad dd 0.5
.code
start:
invoke GetModuleHandle,0
mov hInstance,eax
invoke GetSystemMetrics,SM_CXSCREEN
mov winwidth,eax
invoke GetSystemMetrics,SM_CYSCREEN
mov winheight,eax
fild word ptr winwidth
fidiv word ptr winheight
fstp qword ptr viewaspect
invoke wininit,hInstance,0,0,SW_SHOWDEFAULT
invoke ExitProcess,eax
wininit proc hInst:dword,hprevinst:dword,cmdline:dword,cmdshow:dword
local wc:WNDCLASSEX
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.lpfnWndProc,offset mainloop
mov wc.lpszClassName,offset classname
mrm wc.hInstance,hInst
mov wc.style,0
mov wc.cbClsExtra,0
mov wc.cbWndExtra,0
mov wc.lpszMenuName,0
mov wc.hIcon,0
mov wc.hIconSm,0
mov wc.hCursor,0
invoke RegisterClassEx,addr wc
invoke CreateWindowEx,WS_EX_APPWINDOW,addr classname,addr appname,WS_POPUP,\
0,0,winwidth,winheight,0,0,hInst,0
mov hwnd,eax
invoke ShowCursor,0
invoke ShowWindow,hwnd,SW_SHOWNORMAL
invoke SetForegroundWindow,hwnd
invoke UpdateWindow,hwnd
call doevent
ret
wininit endp
mainloop proc hwnd1:dword,umsg:dword,wparam:dword,lparam:dword
local winrect:RECT
local pixformat:dword
.if umsg == WM_SIZE
call setcamera
ret
.elseif umsg == WM_DESTROY
invoke PostQuitMessage,0
ret
.elseif umsg == WM_CLOSE
invoke MessageBox,hwnd1,addr quitmsg,addr appname,MB_YESNO+MB_ICONQUESTION
.if eax == IDYES
invoke DestroyWindow,hwnd1
.endif
ret
.elseif umsg == WM_ACTIVATE
mov al,byte ptr wparam
mov active,al
ret
.elseif umsg == WM_KEYDOWN
mov eax,wparam
mov key[eax],1
ret
.elseif umsg == WM_KEYUP
mov eax,wparam
mov key[eax],0
ret
.elseif umsg == WM_CREATE
invoke GetDC,hwnd1
mov mainhdc,eax
mov ax,sizeof pixfrm
mov pixfrm.nSize,ax
mov pixfrm.nVersion,1
mov pixfrm.dwFlags,PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER
mov pixfrm.dwLayerMask,PFD_MAIN_PLANE
mov pixfrm.iPixelType,PFD_TYPE_RGBA
mov pixfrm.cColorBits,16
mov pixfrm.cDepthBits,24
mov pixfrm.cStencilBits,8
invoke ChoosePixelFormat,mainhdc,addr pixfrm
mov pixformat,eax
invoke SetPixelFormat,mainhdc,pixformat,addr pixfrm
invoke wglCreateContext,mainhdc
mov opendc,eax
invoke wglMakeCurrent,mainhdc,opendc
invoke GetClientRect,hwnd1,addr winrect
call glinit
ret
.endif
invoke DefWindowProc,hwnd1,umsg,wparam,lparam
ret
mainloop endp
doevent proc
local msg:MSG
startloop:
invoke PeekMessage,addr msg,0,0,0,PM_NOREMOVE
or eax,eax
jz noevent
invoke GetMessage,addr msg,0,0,0
or eax,eax
jz exitloop
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
jmp startloop
noevent:
call drawscene
jmp startloop
exitloop:
mov eax,msg.wParam
ret
doevent endp
glinit proc
invoke glEnable,GL_DEPTH_TEST
invoke glEnable,GL_LIGHTING
invoke glEnable,GL_CULL_FACE
invoke glShadeModel,GL_SMOOTH
invoke glEnable,GL_NORMALIZE
invoke glClearColor,0,3f000000h,3f000000h,0
invoke glClearDepth,dword ptr value1dbl,dword ptr value1dbl+4
invoke glDepthFunc,GL_LEQUAL
invoke glHint,GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST
invoke setlight,GL_LIGHT0,addr light1pos,addr light1color,addr light1diffuse,\
addr light1specular,addr spotcut1,addr spotexp1,addr spotdir1,\
addr light1const,addr light1lin,addr light1quad
ret
glinit endp
setlight proc lightnum:dword,lightpos:dword,lightcolor:dword,lightdiffuse:dword,\
lightspecular:dword,spotcut:dword,spotexp:dword,spotdir:dword,\
lightconst:dword,lightlin:dword,lightquad:dword
invoke glLightfv,lightnum,GL_POSITION,lightpos
invoke glLightfv,lightnum,GL_AMBIENT,lightcolor
invoke glLightfv,lightnum,GL_DIFFUSE,addr lightdiffuse
invoke glLightfv,lightnum,GL_SPECULAR,addr lightspecular
invoke glLightfv,lightnum,GL_SPOT_CUTOFF,addr spotcut
invoke glLightfv,lightnum,GL_SPOT_EXPONENT,addr spotexp
invoke glLightfv,lightnum,GL_SPOT_DIRECTION,addr spotdir
invoke glLightfv,lightnum,GL_CONSTANT_ATTENUATION,addr lightconst
invoke glLightfv,lightnum,GL_LINEAR_ATTENUATION,addr lightlin
invoke glLightfv,lightnum,GL_QUADRATIC_ATTENUATION,addr lightquad
invoke glEnable,lightnum
ret
setlight endp
setcamera proc
invoke glViewport,0,0,winwidth,winheight
invoke glMatrixMode,GL_PROJECTION
invoke glLoadIdentity
invoke gluPerspective, dword ptr fov,dword ptr fov+4,\
dword ptr viewaspect,dword ptr viewaspect+4,\
dword ptr nearclip,dword ptr nearclip+4,\
dword ptr farclip,dword ptr farclip+4
invoke glMatrixMode,GL_MODELVIEW
invoke glLoadIdentity
ret
setcamera endp
drawscene proc
invoke glClear,GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
invoke glLoadIdentity
invoke glBegin,GL_POLYGON
invoke glColor3b,127,0,0
invoke glVertex3f,0,3f800000h,0c0800000h
invoke glColor3b,0,127,0
invoke glVertex3f,0bf800000h,0,0c0800000h
invoke glColor3b,0,0,127
invoke glVertex3f,3f800000h,0,0c0800000h
invoke glEnd
invoke SwapBuffers,mainhdc
ret
drawscene endp
end start
Added code tags.
Quote from: supercoollee on May 07, 2010, 09:54:45 AMthe app is working except for the color of triangle isn't shown
Your program fails on RegisterClassEx() because you are passing invalid handles: clear all unused structure elements. Also the message loop cause an CPU usage of 100% - use a timer for drawing or simply place drawscene() after GetMessage().
i will add timer later on. but i don't understand the former part. i modified the code like this, but still get the same result.
============================================
...
local hwnd:HWND
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.lpfnWndProc,offset mainloop
mov wc.lpszClassName,offset classname
mrm wc.hInstance,hInst
mov wc.style,0
mov wc.cbClsExtra,0
mov wc.cbWndExtra,0
mov wc.hbrBackground,0
mov wc.lpszMenuName,0
mov wc.hIcon,0
mov wc.hIconSm,0
mov wc.hCursor,0
invoke RegisterClassEx,addr wc
...
=============================================
can't i just input 0 to the unnecessary elements? since i don't need menu or icon or cursor in my app.
Iczelion's tutorials also write in similar way except they invoke LoadIcon etc.
Zeroing the structure with a call to RtlZeroMemory would allow you to avoid having to zero the individual members.
Quote from: qWord on May 07, 2010, 02:54:09 PM
Also the message loop cause an CPU usage of 100% - use a timer for drawing or simply place drawscene() after GetMessage().
Placing the call to drawscene in the message loop after the GetMessage call will not work very well because GetMessage waits for a message to be posted before returning.
now i modified the code like this, but it's not important, it only runs once anyway.
=========================
xor eax,eax
mov wc.style,eax
mov wc.cbClsExtra,eax
mov wc.cbWndExtra,eax
mov wc.hbrBackground,eax
mov wc.lpszMenuName,eax
mov wc.hIcon,eax
mov wc.hIconSm,eax
mov wc.hCursor,eax
=========================
the structure of this ASM is almost the same as the example file OPENGL.ASM, only that there are rotating lights and spheres in OPENGL.ASM while there is only a triangle in this ASM.
problem still unsolved. :(
Add code to check the return values for the API functions that you are calling. In the code you posted the call to CreateWindowEx was failing, and adding:
invoke RtlZeroMemory, ADDR wc, SIZEOF wc
Above the code that initializes the structure members eliminated that problem, although there appears to be other problems further down.
i don't understand, if register or create functions fails, how can a window be shown on screen?
in my PC, when i run the program, the screen is filled with light blue color, and there is a gray triangle in the middle of screen. the problem is that the triangle has pure color, while it was meant to be multi-colored.
do these show on your PC ?
i tried RtlZeroMemory too, i got the same result.
Have you tried this?
invoke glColor3f,CFLT(128.0),0,0
Under Windows 2000 your code as posted hangs without showing a window. If I zero the WNDCLASSEX structure with RtlZeroMemory then I get a full-screen window, with a dark cyan background and a black triangle.
Farabi,
invoke glColor3f,CFLT(128.0),0,0 can't be recognized in my MASM, what file should i include?
MichaelW
i am running WinXP SP2 with ATI 9600 graphic card. that code can run on my PC except the color of triangle is wrong. with or without RtlZeroMemory, i get the same thing.
include \masm32\include\opengl32.inc
includelib \masm32\lib\opengl32.lib
You seem to have these included so maybe it's the CFLT macro:
literal_float macro lit_float
local local_float
.data
local_float real4 lit_float
.code
exitm <local_float>
endm
CFLT macro lit_float
exitm <literal_float(lit_float)>
endm
i already have those in my ASM , still not working.
Sorry EDIT: :lol
You seem to have these included so maybe it's the CFLT macro:
literal_float macro lit_float
local local_float
.data
local_float real4 lit_float
.code
exitm <local_float>
endm
CFLT macro lit_float
exitm <literal_float(lit_float)>
endm
may this simple macro helps:
finvoke macro fnName:req,args:VARARG
_iargs TEXTEQU <>
FOR _arg,<&args>
_iargs TEXTEQU <&_arg,>,_iargs
ENDM
% FOR _arg,<_iargs>
IFNB <&_arg>
IF @InStr(1,<&_arg>,<.0>) OR @InStr(1,<&_arg>,<.1>) OR @InStr(1,<&_arg>,<.2>) OR @InStr(1,<&_arg>,<.3>) OR @InStr(1,<&_arg>,<.4>)
ELSEIF @InStr(1,<&_arg>,<.5>) OR @InStr(1,<&_arg>,<.6>) OR @InStr(1,<&_arg>,<.7>) OR @InStr(1,<&_arg>,<.8>) OR @InStr(1,<&_arg>,<.9>)
ELSEIF @InStr(1,<&_arg>,<ADDR>)
lea eax,@SubStr(<&_arg>,@InStr(1,<&_arg>,<ADDR>)+4)
push eax
GOTO Z
ELSE
push _arg
GOTO Z
ENDIF
push 123456789
org $-4
REAL4 _arg
ENDIF
:Z
ENDM
call fnName
endm
example:
finvoke glColor3f,1.0,0.0,0.0
Children, why make this so complex? :P
Add invoke glEnable, GL_COLOR_MATERIAL into "glinit"
The colours are a little dark, but I think you can fix that :wink
finally! i can go on with GL tutorial now! :clap:
thanks a lot!
what i don't understand is that ,why in OPENGL.ASM and NEHE's tutorial there is not such a line, but they can show color?
what's more, in NEHE's tutorial , there is not even a lightsource!
isn't it strange?
It depends on the combinations of modes you set.
You have GL_LIGHTING enabled, which means light sources are taken into account. If it's not enabled then everything is assumed to be in full light (white ambient light of full intensity.) This also affects how vertices are shaded.
Comment out glEnable(GL_LIGHTING) to see the difference.
i got it , thanks.
i have found new problems:
1) could someone tell me what's the relationship between "wininit" and "mainloop" in this ASM? i found that both proc are looping, not just "mainloop". can i have only one of them looping?
2) i added a timeGetTime function in "doevent", my current way is like this:
=====================
.data
active db 0
systemtime dd 0
keyptimer dd 0
...
...
doevent proc
local msg:MSG
startloop:
call timeGetTime
cmp eax,systemtime
jle startloop
mov systemtime,eax
cmp key[VK_P],0
mov al,active
mov ah,keyptimer
je keyptimecount
test ah,ah
jne key_p_up
test al,al
sete al
mov active,al
mov ah,50
mov keyptimer,ah
jmp key_p_up
keyptimecount:
test ah,ah
je key_p_up
dec keyptimer
key_p_up:
test al,al
je pausegame
(rendering and movement)
pausegame:
invoke PeekMessage,addr msg,0,0,0,PM_NOREMOVE
or eax,eax
jz startloop
invoke GetMessage,addr msg,0,0,0
or eax,eax
jz exitloop
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
jmp startloop
exitloop:
mov eax,msg.wParam
ret
doevent endp
=====================
in theory, this makes the rendering procedures run 100 times per second. but i read in MSDN that timeGetTime is not accurate, how can i improve the accuarcy? and how can i make the program run 60 or 50 or 30 times per second?
3) and, even if i added delay in "doevent", the program uses up 100% of CPU time, how can i free the CPU when this app is paused? the other winapps don't use CPU when i don't touch them, why?
currently i have an "active" flag in "mainloop".
======================
.elseif umsg == WM_ACTIVATE
mov al,byte ptr wparam
test al,al
jne gamepaused
mov active,al
ret
gamepaused:
call drawscene
ret
======================
P key can activate/deactivate the app, but it only functions in the way of skipping some lines in "doevent", the app is in fact running (timeGetTime never stops). how can i free my CPU?
1. a normal GUI program first creates the window and then enter the message loop ('mainloop'). This loop get messages from the system an distributed them to the corresponding windows procedure.
In your program the window is created in wininit. the message loop is also entered from here through a call to doevent, which contains the message loop.
2. look for SetTimer() (http://msdn.microsoft.com/en-us/library/ms644906(VS.85).aspx). As long as you don't need more than 50-60fps this a fine way. (This timer has resolution of ~15 ms)
This will also sink the CPU usage.