在Scala中再现Java OpenGL ES 2.0演示时出现奇怪的NullPointerException

时间:2013-11-15 18:24:26

标签: scala opengl-es-2.0 jogl

我正在尝试在Scala中重现this JOGL demo,一个关于如何使用OpenGL ES 2.0的Java演示。编译成功,但尝试执行此操作会产生以下输出:

Main() called
libEGL warning: DRI2: failed to authenticate
Chosen GL capabilities: GLCaps[glx vid 0xae, fbc 0x17a: rgba 8/8/8/8,
trans-rgba 0xff/ff/ff/ff, accum-rgba 16/16/16/16, dp/st/ms 24/0/0, dbl, mono  , hw,    
GLProfile[GL2ES2/GL3.hw], on-scr[.]]
INIT GL IS: jogamp.opengl.gl4.GL4bcImpl
GL_VENDOR: NVIDIA Corporation 
GL_RENDERER: GeForce GTX 260/PCIe/SSE2
GL_VERSION: 3.3.0 NVIDIA 304.88

vertex Shader successfully compiled!
fragment Shader successfully compiled!
Exception in thread "main-Display-.x11_:0.0-1-EDT-1" java.lang.NullPointerException
at jogamp.newt.driver.x11.DisplayDriver.dispatchMessagesNative(DisplayDriver.java:103)
at jogamp.newt.DisplayImpl.dispatchMessages(DisplayImpl.java:540)
at jogamp.newt.DisplayImpl$5.run(DisplayImpl.java:463)
at jogamp.newt.DefaultEDTUtil$NEDT.run(DefaultEDTUtil.java:326)
X11Util.Display: Shutdown (JVM shutdown: true, open (no close attempt): 2/2, reusable 
(open, marked uncloseable): 0, pending (open in creation order): 2)
X11Util: Open X11 Display Connections: 2
X11Util: Open[0]: NamedX11Display[:0.0, 0x7da0cab0, refCount 1, unCloseable false]
X11Util: Open[1]: NamedX11Display[:0.0, 0x7da1bea8, refCount 1, unCloseable false]

在异常上升之前成功渲染1或几帧。当我从jswat调试器运行它时,没有出现预期
我错过了一些非常明显的东西吗有没有其他人遇到类似Scala和OpenGL ES 2.0的问题?

我正在使用Linux Mint 13和Ant来编译和运行代码。我的Scala代码是:

import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLCapabilities;

import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util._;
import com.jogamp.common.nio.Buffers;

import java.nio.FloatBuffer;

// explicitly enabling postifx length operator:
import scala.language.postfixOps;

object RectangleDisplayer extends GLEventListener {
  val vertexShaderCode : Array[String] =
Array("#if __VERSION__ >= 130\n", 
"  #define attribute in\n",
"  #define varying out\n",
"#endif\n",

"#ifdef GL_ES\n",
"precision mediump float; \n", 
"precision mediump int; \n",
"#endif \n",

"uniform mat4    uniform_Projection; \n", 
"attribute vec4  attribute_Position;\n",  
"attribute vec4  attribute_Color;\n", 

"varying vec4    varying_Color;\n", 

"void main(void)\n", 
"{\n", 
"  varying_Color = attribute_Color;\n", 
"  gl_Position = uniform_Projection * attribute_Position;\n", 
"}\n")

  val fragmentShaderCode : Array[String] =
Array("#if __VERSION__ >= 130\n",
"  #define varying in\n",
"  out vec4 mgl_FragColor;\n",
"  #define texture2D texture\n",
"  #define gl_FragColor mgl_FragColor\n",
"#endif\n",

"#ifdef GL_ES\n",
"precision mediump float;\n",
"precision mediump int;\n",
"#endif\n",

"varying vec4 varying_Color; \n",

"void main(void)\n",
"{\n",
"  gl_FragColor = varying_Color;\n",
"}\n")

  var width : Int = 640
  var height : Int = 480

  // Scheinbar müssen in Scala alle Variablen zu Beginn initialisiert sein
  var shaderProgram : Int = 0
  var vertexShader : Int = 0
  var fragmentShader : Int = 0

  var vboHandles : Array[Int] = new Array[Int](2)
  var vboVertices : Int  = 0
  var vboColors : Int = 0

  var ModelViewProjectionMatrix_location : Int = 0


  def compileShaderIntoProgram(gl : GL2ES2, theShader : Int, shaderCode : Array[String]):Unit = {
    /*println("Shader code")
    for (l <- shaderCode) {
      print(l)
    }*/
    val lengths = shaderCode map(_ length)
    gl.glShaderSource(theShader, shaderCode.length, shaderCode, lengths, 0)
    gl.glCompileShader(theShader)
  }

  def checkCompileStatus(gl : GL2ES2, theShader: Int, which : Int):Unit = {
    var compiled : Array[Int] = Array(1)
    gl.glGetShaderiv(theShader, GL2ES2.GL_COMPILE_STATUS, compiled, 0)

    var shaderType : String = "vertex"
    if (which == 1) {
      shaderType = "fragment"
    }

    if (compiled(0) != 0) {
      println(shaderType + " Shader successfully compiled!")
    } else {
      var logLength = new Array[Int](1)
      var returnedLogLength = new Array[Int](1)

      gl.glGetShaderiv(theShader, GL2ES2.GL_INFO_LOG_LENGTH, logLength, 0)

      var log : Array[Byte] = new Array[Byte](logLength(0))
      gl.glGetShaderInfoLog(theShader, logLength(0), returnedLogLength, 0, log, 0)

      println("Error compiling "+shaderType+" shader:")
      println(new String(log))

      System.exit(1)
    }
  }

  override def init(drawable : GLAutoDrawable):Unit = {
    val gl : GL2ES2 = drawable.getGL().getGL2ES2()

    println("Chosen GL capabilities: " + drawable.getChosenGLCapabilities())
    println("INIT GL IS: " + gl.getClass().getName())
    println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR))
    println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER))
    println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION))

    // create, compile and attach shaders
    vertexShader = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER)
    fragmentShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER)

    compileShaderIntoProgram(gl, vertexShader, vertexShaderCode)
    checkCompileStatus(gl, vertexShader, 0)

    compileShaderIntoProgram(gl, fragmentShader, fragmentShaderCode)
    checkCompileStatus(gl, fragmentShader, 1)

    shaderProgram = gl.glCreateProgram()
    gl.glAttachShader(shaderProgram, vertexShader)
    gl.glAttachShader(shaderProgram, fragmentShader)

    // Associate attribute ids with the attribute names inside the (vertex) shader
    gl.glBindAttribLocation(shaderProgram, 0, "attribute_Position")
    gl.glBindAttribLocation(shaderProgram, 1, "attribute_Color")

    gl.glLinkProgram(shaderProgram)

    ModelViewProjectionMatrix_location = gl.glGetUniformLocation(shaderProgram, "uniform_Projection")

    // forward compatibility with ES 3 by creating and binding a "Vertex Buffer Object"
    gl.glGenBuffers(2, vboHandles, 0)
    vboColors = vboHandles(0)
    vboVertices = vboHandles(1)
  }

  override def display(drawable : GLAutoDrawable):Unit = {
    val gl : GL2ES2 = drawable.getGL().getGL2ES2()

    gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f)
    gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

    gl.glUseProgram(shaderProgram)

    // Define projection matrix
    val model_view_projection : Array[Float] = 
      Array(1.0f, 0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f, -1.0f,
            0.0f, 0.0f, 0.0f, 1.0f)

    gl.glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, false, model_view_projection, 0)

    // Define Vertex buffer
    val vertices : Array[Float] = Array(0.0f, 1.0f, 0.0f,
                                        -1.0f, -1.0f, 0.0f,
                                        1.0f, -1.0f, 0.0f)

    var fbVertices : FloatBuffer = Buffers.newDirectFloatBuffer(vertices)
    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboVertices)

    var numBytes : Int = vertices.length*4
    gl.glBufferData(GL.GL_ARRAY_BUFFER, numBytes, fbVertices, GL.GL_STATIC_DRAW)
    fbVertices = null

    // Associate vertex attribute 0 with the last bound VBO
    gl.glVertexAttribPointer(0, // the vertex attribute
                              3, GL.GL_FLOAT,
                              false, // normalized?
                              0, // stride
                              0 // The bound VBO data offset
                              )
    gl.glEnableVertexAttribArray(0)


    // Define color buffer
    val colors : Array[Float] = Array(1.0f, 0.0f, 0.0f, 1.0f,
                                      0.0f, 0.0f, 0.0f, 1.0f,
                                      1.0f, 1.0f, 0.0f, 0.9f)
    var fbColors : FloatBuffer = Buffers.newDirectFloatBuffer(colors)
    gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboColors)
    numBytes = colors.length*4
    gl.glBufferData(GL.GL_ARRAY_BUFFER, numBytes, fbColors, GL.GL_STATIC_DRAW)
    fbColors = null

    // Associate vertex attribute 1 with the last bound VBO
    gl.glVertexAttribPointer(1, 4, // four positions used for each vertex
                            GL.GL_FLOAT, false, // normalized?
                            0, // stride
                            0 // the bound VBO data offset
                            )
    gl.glEnableVertexAttribArray(1)

    gl.glDrawArrays(GL.GL_TRIANGLES, 0, 3)

    gl.glDisableVertexAttribArray(0)
    gl.glDisableVertexAttribArray(1)

    gl.glDeleteBuffers(2, vboHandles, 0)
  }

  override def reshape(drawable : GLAutoDrawable, 
    x: Int, y: Int, z: Int, h: Int):Unit = {
      width = z
      height = h

      val gl : GL2ES2 = drawable.getGL().getGL2ES2()

      gl.glViewport(0, 0, width, height)
  }

  override def dispose(drawable : GLAutoDrawable):Unit = {
    println("cleanup operations, disposing and detaching shaders")
    val gl : GL2ES2 = drawable.getGL().getGL2ES2()

    gl.glUseProgram(0)
    gl.glDetachShader(shaderProgram, vertexShader)
    gl.glDeleteShader(vertexShader)
    gl.glDetachShader(shaderProgram, fragmentShader)
    gl.glDeleteShader(fragmentShader)

    gl.glDeleteProgram(shaderProgram)
    System.exit(0)
  }

  def main(args: Array[String]): Unit = {
    println("Main() called")

    val caps : GLCapabilities = new GLCapabilities(GLProfile.get(GLProfile.GL2ES2))
    caps.setBackgroundOpaque(false)
    var glWindow : GLWindow = GLWindow.create(caps)

    // setup window parameters
    glWindow.setTitle("Scala GL ES test")
    glWindow.setSize(width, height)
    glWindow.setUndecorated(false)
    glWindow.setPointerVisible(true)
    glWindow.setVisible(true)

    // add this class as event listener to the window
    glWindow.addGLEventListener(this)
    var animator: Animator = new Animator()
    animator.add(glWindow)
    animator.start()
  }
}

1 个答案:

答案 0 :(得分:3)

我认为你需要先进行调试。 在gl.glcreateprogram之后使用'println',准确调试它来自你的bug。

'NULL指针异常'可以比任何其他奇怪的bug更容易找到。 (只为我!)

使用这种方式并找到首先出现异常的地方。