当 运行 异步但它同步工作时,我的代码会产生错误
My code is producing an error when run asynchronously but it works synchronously
我正在使用 OpenGL 和 Nim 制作 3d 视频游戏。
最初,我的代码在我的显示函数中绘制了一些立方体,但它使用了 {.cdecl.} pragma,这意味着我无法访问像相机位置这样的外部变量。我切换到一个空的显示函数,取而代之的是异步 while 循环。但是,当我编译 运行 程序时,它产生了一个 GLError,消息为“错误:未处理的异常:OpenGl 错误:操作无效 [GLError]”。有谁知道为什么会这样?
我的代码:
import opengl, opengl/[glut, glu]
import os, strutils, threadpool
# import camera, controller, dataprotocol, inventory
proc display() {.cdecl.} =
discard
proc reshape(width: GLsizei, height: GLsizei) {.cdecl.} =
if height == 0:
return
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, width / height, 0.1, 100.0)
proc drawAll(xpos: float, ypos: float, zpos: float): void =
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(1.55+xpos, -1.75+ypos, -7.0+zpos)
glBegin(GL_TRIANGLES)
# Top face
glColor3f(0.0, 1.0, 0.0) # Green
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
# Bottom face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Front face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
# Back face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
# Left face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Right face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(1.0, -1.0, 1.0)
glVertex3f(1.0, -1.0, -1.0)
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, -1.0, 1.0)
glEnd()
glutSwapBuffers()
# var blocks = string(open("blocks.bmc").readAll).split(";")
# Commented out because not used yet
# glutInit()
glutInitDisplayMode(GLUT_DOUBLE)
glutInitWindowSize(640, 480)
glutInitWindowPosition(50, 50)
discard glutCreateWindow("BlueMC")
if paramCount() == 1 and paramStr(1) == "-fullscreen":
glutFullScreen()
glutSetCursor(GLUT_CURSOR_CROSSHAIR)
glutDisplayFunc(display)
glutReshapeFunc(reshape)
loadExtensions()
glClearColor(GLFloat(172.0/255.0), GLFloat(246.0/255.0), GLFloat(246.0/255.0), GLFloat(1.0))
glClearDepth(1.0)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glShadeModel(GL_SMOOTH)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
proc eventloop(): void {.gcsafe.} =
while true:
drawAll(0.0, 0.0, 0.0)
spawn eventloop()
glutMainLoop()
Nim 的 spawn
语句将在不同的线程中执行您的过程。在 OpenGL 中,当前上下文是 per-thread 属性,并且 OpenGL conetxt 只能成为 a single thread 的当前上下文在每一次。您的构造不能 与 OpenGL 一起工作。但是,问题的根本原因是您使用了非常过时的 GLUT 框架,它迫使您使用一些反向控制流来执行渲染循环。如果您使用更现代的框架,如 GLFW、SDL 或许多其他框架,您可以实现您的事件和渲染循环,而无需任何这些麻烦。
我正在使用 OpenGL 和 Nim 制作 3d 视频游戏。 最初,我的代码在我的显示函数中绘制了一些立方体,但它使用了 {.cdecl.} pragma,这意味着我无法访问像相机位置这样的外部变量。我切换到一个空的显示函数,取而代之的是异步 while 循环。但是,当我编译 运行 程序时,它产生了一个 GLError,消息为“错误:未处理的异常:OpenGl 错误:操作无效 [GLError]”。有谁知道为什么会这样?
我的代码:
import opengl, opengl/[glut, glu]
import os, strutils, threadpool
# import camera, controller, dataprotocol, inventory
proc display() {.cdecl.} =
discard
proc reshape(width: GLsizei, height: GLsizei) {.cdecl.} =
if height == 0:
return
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, width / height, 0.1, 100.0)
proc drawAll(xpos: float, ypos: float, zpos: float): void =
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(1.55+xpos, -1.75+ypos, -7.0+zpos)
glBegin(GL_TRIANGLES)
# Top face
glColor3f(0.0, 1.0, 0.0) # Green
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
# Bottom face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Front face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
# Back face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
# Left face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Right face
glColor3f(139.0/256.0, 69.0/256.0, 19.0/256.0) # Brown
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(1.0, -1.0, 1.0)
glVertex3f(1.0, -1.0, -1.0)
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, -1.0, 1.0)
glEnd()
glutSwapBuffers()
# var blocks = string(open("blocks.bmc").readAll).split(";")
# Commented out because not used yet
# glutInit()
glutInitDisplayMode(GLUT_DOUBLE)
glutInitWindowSize(640, 480)
glutInitWindowPosition(50, 50)
discard glutCreateWindow("BlueMC")
if paramCount() == 1 and paramStr(1) == "-fullscreen":
glutFullScreen()
glutSetCursor(GLUT_CURSOR_CROSSHAIR)
glutDisplayFunc(display)
glutReshapeFunc(reshape)
loadExtensions()
glClearColor(GLFloat(172.0/255.0), GLFloat(246.0/255.0), GLFloat(246.0/255.0), GLFloat(1.0))
glClearDepth(1.0)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glShadeModel(GL_SMOOTH)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
proc eventloop(): void {.gcsafe.} =
while true:
drawAll(0.0, 0.0, 0.0)
spawn eventloop()
glutMainLoop()
Nim 的 spawn
语句将在不同的线程中执行您的过程。在 OpenGL 中,当前上下文是 per-thread 属性,并且 OpenGL conetxt 只能成为 a single thread 的当前上下文在每一次。您的构造不能 与 OpenGL 一起工作。但是,问题的根本原因是您使用了非常过时的 GLUT 框架,它迫使您使用一些反向控制流来执行渲染循环。如果您使用更现代的框架,如 GLFW、SDL 或许多其他框架,您可以实现您的事件和渲染循环,而无需任何这些麻烦。