I am newbie in opengl es 2 programming, I was trying to load a texture in png format in my test application. I used PNGDecoder to do this, but just the black rectangle and the line are show in the screen. What is wrong?
Renderer:
@file:Suppress("NAME_SHADOWING") package vga import de.matthiasmann.twl.utils.PNGDecoder import org.lwjgl.opengles.GLES20.* import java.io.File import org.lwjgl.BufferUtils import org.lwjgl.opengl.GLUtil import java.io.BufferedInputStream import java.io.FileInputStream import java.io.InputStream import java.nio.Buffer import java.nio.ByteBuffer import kotlin.math.cos import kotlin.math.sin object RendererGLES { val vertexShader: Int val fragmentShader: Int val program: Int lateinit var vbosSquareIndices: IntArray lateinit var vbosSquareVertices: IntArray lateinit var vbosLine: IntArray val a_Position: Int val square: Square2D val textureId: Int val u_SamplerLocation: Int val a_TextCoordLocation: Int init { val vertexCode = File("C:\Users\cassio\Desktop\tutorial_learnopengles\seila\src\main\resources\vertex_shader.glsl").run{ readText() } val fragmentCode = File("C:\Users\cassio\Desktop\tutorial_learnopengles\seila\src\main\resources\fragment_shader.glsl").run{ readText() } vertexShader = compileShader(vertexCode, GL_VERTEX_SHADER) fragmentShader = compileShader(fragmentCode, GL_FRAGMENT_SHADER) program = createProgram(fragmentShader, vertexShader) a_Position = glGetAttribLocation(program, "a_Position") u_SamplerLocation = glGetUniformLocation(program, "u_Sampler") a_TextCoordLocation = glGetAttribLocation(program, "a_TextureCoord") glEnableVertexAttribArray(a_Position) square = Square2D(0.1f) glClearColor(0.8f, 0.8f, 0.8f, 1f) createVBOS() textureId = loadTexture("C:\Users\cassio\Desktop\tutorial_learnopengles\seila\src\main\resources\sla.png") } fun compileShader(code: String, type: Int): Int { val shader = glCreateShader(type) glShaderSource(shader, code) glCompileShader(shader) println(glGetShaderInfoLog(shader)) return shader } fun createProgram(frag: Int, vert: Int): Int { val prog = glCreateProgram() glAttachShader(prog, vert) glAttachShader(prog, frag) glLinkProgram(prog) println(glGetProgramInfoLog(program)) return prog } fun createVBOS() { vbosSquareVertices = IntArray(1) vbosSquareIndices = IntArray(1) vbosLine = IntArray(1) glGenBuffers(vbosSquareVertices) glBindBuffer(GL_ARRAY_BUFFER, vbosSquareVertices[0]) glBufferData(GL_ARRAY_BUFFER, square.vertexArray, GL_STATIC_DRAW) glGenBuffers(vbosSquareIndices) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbosSquareIndices[0]) glBufferData(GL_ELEMENT_ARRAY_BUFFER, square.vertexIndices, GL_STATIC_DRAW) glGenBuffers(vbosLine) glBindBuffer(GL_ARRAY_BUFFER, vbosLine[0]) glBufferData(GL_ARRAY_BUFFER, square.line, GL_STATIC_DRAW) } fun loadTexture(fileName: String): Int { // Load PNG file val decoder = PNGDecoder( BufferedInputStream(FileInputStream(fileName)) ) // Create a big buffer to store the png data val buffer = ByteBuffer.allocateDirect( 4 * decoder.width * decoder.height) decoder.decode(buffer, decoder.width * 4, PNGDecoder.Format.RGBA) buffer.flip() val id = glGenTextures() glBindTexture(GL_TEXTURE_2D, id) // Say to opengl how unpack bytes glPixelStorei(GL_UNPACK_ALIGNMENT, 1) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.width, decoder.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer) return id } fun renderer() { glClear(GL_COLOR_BUFFER_BIT) glUseProgram(program) glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, textureId) glUniform1i(u_SamplerLocation, 0) square.bufferTexture.position(0) glBindBuffer(GL_ARRAY_BUFFER, 0) glVertexAttribPointer(a_TextCoordLocation, 2, GL_FLOAT, false, 0, square.bufferTexture) glEnableVertexAttribArray(a_TextCoordLocation) glBindBuffer(GL_ARRAY_BUFFER, vbosSquareVertices[0]) glVertexAttribPointer(a_Position, 2, GL_FLOAT, false, 0, 0) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbosSquareIndices[0]) nglDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0) } }
Fragment Shader:
precision mediump float; varying vec2 v_TextureCoord; uniform sampler2D u_Sampler; void main(){ gl_FragColor = texture2D(u_Sampler, v_TextureCoord); }
Vertex Shader:
attribute vec4 a_Position; attribute vec2 a_TextureCoord; uniform mat4 projectionMatrix; uniform mat4 modelMatrix; uniform mat4 viewMatrix; varying vec2 v_TextureCoord; void main() { v_TextureCoord = a_TextureCoord; gl_Position = a_Position; gl_PointSize = 1.0; }
Square2D (is used to store vertex positions):
package vga import java.nio.* import org.lwjgl.opengles.GLES20.* class Square2D(val size: Float) { val vertexArray: FloatArray val vertexIndices: ShortArray val line: FloatArray val textureCoordinate: FloatArray val bufferTexture: FloatBuffer init { line = floatArrayOf( -0.5f, -0.5f, 0.5f, 0.5f ) vertexArray = floatArrayOf( -1f, 1f, -1f, -1f, 1f, -1f, 1f, 1f, ) for (i in vertexArray.indices) { vertexArray[i] *= size } vertexIndices = shortArrayOf( 0, 1, 2, 2, 3, 0 ) textureCoordinate = floatArrayOf( 1f,0f, 0f,0f, 1f,1f, 0f,1f ) for (i in textureCoordinate.indices) { textureCoordinate[i] *= size } bufferTexture = ByteBuffer.allocateDirect(textureCoordinate.size * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer() bufferTexture.put(textureCoordinate) bufferTexture.flip() } }
Advertisement
Answer
glVertexAttribPointer
can be use in 2 ways. If a named buffer object is bound, then the last argument is treated as byte offset in the buffer objects data store. If no buffer is bound (0), then the last argument is a pointer to the array data.
Hence you have to bind no buffer (0), to the GL_ARRAY_BUFFER
target, before you can specify the texture coordinate attribute:
glBindBuffer(GL_ARRAY_BUFFER, 0) glVertexAttribPointer( a_TextCoordLocation, 2, GL_FLOAT, false, 0, square.bufferTexture)