在Android上使用OpenGL显示FloatBuffer或顶点数组

时间:2019-05-10 14:54:51

标签: java android kotlin opengl-es

我想在我的Android应用程序中显示3D点数组,即带有OpenGL的顶点。我正在从.obj文件中读取顶点,现在我只想显示这些顶点,即没有面元素等。我将顶点的3D坐标加载到FloatBuffer中,当我调用glDrawElements方法时,它什么都不显示。有帮助吗?

代码如下:

class PreviewActivity : AppCompatActivity() {

    private lateinit var surfaceView : GLSurfaceView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_opengl_preview)
        surfaceView = findViewById(R.id.my_surface_view)
        surfaceView.setEGLContextClientVersion(3)
        surfaceView.setRenderer(renderer)
    }


    private var model : Model? = null

    private val renderer = object : GLSurfaceView.Renderer {
        override fun onDrawFrame(gl: GL10?) {
            GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT)
            model?.draw()
        }

        override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
            GLES31.glViewport(0, 0, width, height)
        }

        override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
            surfaceView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
            model = Model(applicationContext)
        }

    }

}



class Model(context : Context) {

    private val verticesList : List<String>
    private val verticesBuffer : FloatBuffer
    private val program : Int

    init {
        verticesList = ArrayList()

        val filePath = "storage/emulated/0/Pictures/DiplRaw/torus.obj"
        val file = File(filePath)
        val scanner = Scanner(file)
        while (scanner.hasNextLine()) {
            val line = scanner.nextLine()
            if(line.startsWith("v ")) {
                verticesList.add(line)
            }
        }
        scanner.close()

        val buffer = ByteBuffer.allocateDirect(verticesList.size * 3 * 4) //3 koordinate po 8 byteova (Double je!)
        buffer.order(ByteOrder.nativeOrder())
        verticesBuffer = buffer.asFloatBuffer()

        for(vertex in verticesList) {
            val coords = vertex.split(" ")
            val x = coords[1].toFloat()
            val y = coords[2].toFloat()
            val z = coords[3].toFloat()
            verticesBuffer.put(x)
            verticesBuffer.put(y)
            verticesBuffer.put(z)
        }
        verticesBuffer.position(0)

        val vertexSharedStream = context.resources.openRawResource(R.raw.vertex_shader)
        val vertexSharedCode = IOUtils.toString(vertexSharedStream, Charset.defaultCharset())
        vertexSharedStream.close()

        val fragmentSharedStream = context.resources.openRawResource(R.raw.fragment_shader)
        val fragmentSharedCode = IOUtils.toString(fragmentSharedStream, Charset.defaultCharset())
        fragmentSharedStream.close()

        val vertexShader = GLES31.glCreateShader(GLES31.GL_VERTEX_SHADER)
        GLES31.glShaderSource(vertexShader, vertexSharedCode)

        val fragmentShader = GLES31.glCreateShader(GLES31.GL_FRAGMENT_SHADER)
        GLES31.glShaderSource(fragmentShader, fragmentSharedCode)

        GLES31.glCompileShader(vertexShader)
        GLES31.glCompileShader(fragmentShader)


        program = GLES31.glCreateProgram()
        GLES31.glAttachShader(program, vertexShader)
        GLES31.glAttachShader(program, fragmentShader)

        GLES31.glLinkProgram(program)
        GLES31.glUseProgram(program)
    }


    fun draw() {
        val position = GLES31.glGetAttribLocation(program, "position")
        GLES31.glEnableVertexAttribArray(position)

        GLES31.glVertexAttribPointer(position, 3, GLES31.GL_FLOAT, false, 3*4, verticesBuffer)

        val projectionMatrix = FloatArray(16)
        val viewMatrix = FloatArray(16)
        val productMatrix = FloatArray(16)

        Matrix.frustumM(projectionMatrix, 0, -1f, 1f, -1f, 1f, 2f, 9f) //TODO
        Matrix.setLookAtM(viewMatrix, 0, 0f, 3f, -4f, 0f, 0f, 0f, 0f, 1f, 0f)
        Matrix.multiplyMM(productMatrix, 0, projectionMatrix,0, viewMatrix,0)

        val matrix = GLES31.glGetUniformLocation(program, "matrix")
        GLES31.glUniformMatrix4fv(matrix, 1, false, productMatrix, 0)

        GLES31.glDrawElements(GLES31.GL_POINTS, verticesList.size, GLES31.GL_FLOAT, verticesBuffer)

        GLES31.glDisableVertexAttribArray(position)
    }

}

这是我的vertex_shader.txt文件:

attribute vec4 position;
uniform mat4 matrix;

void main() {
    gl_Position = matrix * position;
    gl_PointSize = 10.0;
}

和我的fragment_shader.txt文件:

precision mediump float;

void main() {
    gl_FragColor = vec4(1, 0.5, 0, 1.0);
}

0 个答案:

没有答案