multithreadingJOGL问题

我正在用Java编写一个简单的OpenGL应用程序,它实现了用于估计PI值的Monte Carlo方法。 这个方法很简单。 简单地说,你在一个单位正方形内绘制一个圆圈,然后在场景上绘制随机点。 现在,对于圆圈内的每个点,您都将点数递增。 在确定了所有的随机点之后,他们在圆圈内或者不在圆圈内,将所有绘制的点的总数乘以4得到PI的估计值。 它是这样的PI =(inPoints / totalPoints)* 4。这是因为在math上一个圆的面积与一个正方形的面积比是PI / 4,所以当我们乘以4我们得到PI。

我的问题不在于algorithm本身; 然而,我正在试图绘制点,因为他们正在生成的问题,而不是在程序完成执行时一次绘制一切。 我想给应用程序一个实时显示的感觉,用户可以看到他们被绘制的点。 我是OpenGL的初学者,我很确定内置了multithreadingfunction。 不less,我试图手动创建自己的线程。 每个工作线程一次绘制一个点。 以下是psudo代码:

/* this part of the code exists in display() method in MyCanvas.java which extends GLCanvas and implements GLEventListener */ // main loop for(int i = 0; i < number_of_points; i++){ RandomGenerator random = new RandomGenerator(); float x = random.nextFloat(); float y = random.nextFloat(); Thread pointThread = new Thread(new PointThread(x, y)); } gl.glFlush(); /* this part of the code exists in run() method in PointThread.java which implements Runnable */ void run(){ try{ gl.glPushMatrix(); gl.glBegin(GL2.GL_POINTS); if(pointIsIn) gl.glColor3f(1.0f, 0.0f, 0.0f); // red point else gl.glColor3f(0.0f, 0.0f, 1.0f); // blue point gl.glVertex3f(x, y, 0.0f); // coordinates gl.glEnd(); gl.glPopMatrix(); }catch(Exception e){ } } 

我不确定我的解决方法是否正确。 我希望你们能帮助我。 谢谢。

编辑:

好! 所以我遵循了Sven的建议,而不是使用AWT组件来限制multithreading,于是我继续使用了GLONOWOW,它是一个NEWT上下文组件,不会限制我这样做。 不过,在调度线程时我仍然面临同样的问题。 该程序似乎要等到所有点都确定后,才能一下子把所有的东西都画出来。 请看下面我真正的代码,这是一个叫做“MonteCarlo”的类,这个问题在display()方法中是特别的。 请记住,我现在并没有真正地密切关注这些问题,只是为了testing程序而打印出标准输出的问候。

 import javax.media.opengl.GL2; import javax.media.opengl.glu.gl2.GLUgl2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import com.jogamp.newt.event.WindowAdapter; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.FPSAnimator; import java.util.Random; public class MonteCarlo implements GLEventListener{ private static final String TITLE = "Monte Carlo Method"; private static final int WINDOW_WIDTH = 400; private static final int WINDOW_HEIGHT = 400; private static final int FPS = 60; private static final float RADIUS = 0.5f; public MonteCarlo(){ } @Override public void init(GLAutoDrawable drawable){ GL2 gl = drawable.getGL().getGL2(); gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); gl.glClearDepth(1.0f); } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height){ GL2 gl = drawable.getGL().getGL2(); GLUgl2 glu = new GLUgl2(); gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL2.GL_PROJECTION); gl.glLoadIdentity(); glu.gluPerspective(53.14f, 1.0f, 1.0f, 100.0f); gl.glMatrixMode(GL2.GL_MODELVIEW); } @Override public void display(GLAutoDrawable drawable){ GL2 gl = drawable.getGL().getGL2(); GLUgl2 glu = new GLUgl2(); gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT); gl.glLoadIdentity(); glu.gluLookAt(0.5f, 0.5f, 1.0f, 0.5f, 0.5f, -1.0f, 0.0f, 1.0f, 0.0f); gl.glPushMatrix(); gl.glBegin(GL2.GL_LINES); gl.glColor3f(0.0f, 0.0f, 0.0f); gl.glVertex3f(0.0f, 0.5f, 0.0f); gl.glVertex3f(1.0f, 0.5f, 0.0f); gl.glVertex3f(0.5f, 0.0f, 0.0f); gl.glVertex3f(0.5f, 1.0f, 0.0f); gl.glEnd(); gl.glPopMatrix(); int in = 0; int total = 1000000; Random floatRandomGenerator = new Random(); for(int i = 0; i < total; i++){ float x = floatRandomGenerator.nextFloat(); float y = floatRandomGenerator.nextFloat(); if((Math.pow(x - 0.5, 2) + Math.pow(y - 0.5, 2)) <= Math.pow(RADIUS, 2)){ in++; new Thread(){ @Override public void run(){ System.out.println("hello"); } }.start(); } } gl.glPushMatrix(); gl.glPointSize(10.0f); gl.glBegin(GL2.GL_POINTS); gl.glColor3f(1.0f, 0.0f, 0.0f); gl.glVertex3f(0.5f, 0.5f, 0.0f); gl.glVertex3f(0.75f, 0.5f, 0.0f); gl.glVertex3f(1.0f, 0.5f, 0.0f); gl.glEnd(); gl.glPopMatrix(); gl.glFlush(); } @Override public void dispose(GLAutoDrawable drawable){ } public static void main(String[] args){ GLProfile glProfile = GLProfile.getDefault(); GLCapabilities glCapabilities = new GLCapabilities(glProfile); GLWindow glWindow = GLWindow.create(glCapabilities); final FPSAnimator fpsAnimator = new FPSAnimator(glWindow, FPS, true); glWindow.addWindowListener(new WindowAdapter(){ @Override public void windowDestroyNotify(WindowEvent e){ new Thread(){ @Override public void run(){ fpsAnimator.stop(); System.exit(0); } }.start(); }; }); glWindow.addGLEventListener(new MonteCarlo()); glWindow.setTitle(TITLE); glWindow.setSize(WINDOW_WIDTH, WINDOW_HEIGHT); glWindow.setVisible(true); fpsAnimator.start(); } } 

谢谢 :)

规范支持multithreading使用一个 OpenGL上下文,但是一个OpenGL上下文一次只能由一个线程创建。

要使用您的伪码W /多个线程和一个可绘制的目标,你想使用共享上下文,请参阅我的答案相关的OpenGLmultithreading问题 。

共享的上下文需要绑定到一个通用的drawable,这是一个完全不同于我们迄今为止所介绍的用例的场景。

韦德是在这里,这是完全有可能这样做的规范,至less不禁止:)

然而,OpenGL驱动程序实现通常将上下文绑定到一个可绘制的(因为它是真正的w / Mesa DRI),并且将执行locking。

这也是正确的JOG,也就是说,当使上下文成为当前的时候,我们要求可绘制的locking,以确保没有其他线程同时使用它。

同时使用drawable通常会产生未定义的结果,如OpenGL规范中关于FBO(帧缓冲区对象)所述。

另一个OpenGL实现的副作用是固定函数管道的仿真,即构造如 – glBegin(..).. glVertex(..).. glEnd()

将只会 – 创建一个VBO – 将其发送到着色器,并在需要完成时在某个时间点渲染(swapBuffer()是最新的点)。

上述的影响意味着你的multithreading将至less为GPU的着色引擎而战,但是impl。 也为可拉锁。

即使您使用专为这种原因而devise的OpenCL(即HPC),您的工作stream程也不适合,因为在启动内核之前,要处理的数据应该是可用的。 因此,OpenGL或OpenCL在这里没有任何区别。

尽管在隧道尽头有一点点光线:)如果你要使用一个使用噪声函数(随机)的片段着色器,并单独渲染圆圈 – 你可能会得到你正在做的,GPU加速的估计”。

你说得对,OpenGL(理论上)是multithreading的,你可以从JOGL中这样使用它。 但实际上,如果你select了任意的平台和驱动程序版本,在multithreading支持中有时会出现一些错误。 所以如果你希望你的程序对于其他用户来说是健壮的,那么从多个线程访问OpenGL可能比它的价值更麻烦。

我建议创建一个拥有GLContext的渲染线程,并执行所有的OpenGL操作。 然后让工作者的PointThreads将完成的点推送到由渲染线程维护的线程安全集合(例如java.util.concurrent.ConcurrentLinkedQueue)。 渲染线程可以在队列中显示点时绘制点,也可以将点传递到顶点缓冲区以进行更高性能的渲染。