I've been trying to get into OpenGL ES world and everything have been fine(following book "OpenGL ES 2.0 Programming Guide" which is great!) until now. I've tried adding textures to primitive I've drawn, which I succeed in using previous versions of OpenGL ES and with WebGL.
I can perfectly draw texture if I place the "texture" inside Java code like this:
pixelBuffer.put(new byte[]{
0, 0, Byte.MAX_VALUE,
0, Byte.MAX_VALUE, 0,
Byte.MAX_VALUE, 0, 0,
0, 0, 0, 0});
but whenever I try to load the texture from external file, it just appears as black. Below is code I am using to load the texture and use it.
My Activity:
glSurface = new GLSurfaceView(this);
glSurface.setEGLContextClientVersion(2);
glSurface.setDebugFlags(GLSurfaceView.DEBUG_LOG_GL_CALLS | GLSurfaceView.DEBUG_CHECK_GL_ERROR);
this.setContentView(glSurface);
glSurface.setRenderer(new TriangleRenderer(this));
ShaderLoader:
public static int loadShader(int shaderType, String shaderSource) {
int shaderHandle = glCreateShader(shaderType);
glShaderSource(shaderHandle, shaderSource);
glCompileShader(shaderHandle);
int[] buffer = new int[1];
glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, buffer, 0);
if(buffer[0] == GLES20.GL_FALSE) {
Log.e("ShaderHelper", glGetShaderInfoLog(shaderHandle));
glDeleteShader(shaderHandle);
return -1;
}
return shaderHandle;
}
public static int loadProgram(String vertexShader, String fragmentShader) {
int programHandle = glCreateProgram();
glAttachShader(programHandle, loadShader(GL_VERTEX_SHADER, vertexShader));
glAttachShader(programHandle, loadShader(GL_FRAGMENT_SHADER, fragmentShader));
glLinkProgram(programHandle);
int[] buffer = new int[1];
glGetProgramiv(programHandle, GL_LINK_STATUS, buffer, 0);
if(buffer[0] == GL_FALSE) {
Log.e("ShaderHelper", glGetProgramInfoLog(programHandle));
glDeleteProgram(programHandle);
return -1;
}
return programHandle;
}
TextReader:
public static String readResource(Resources resources, int id) {
StringBuilder content = new StringBuilder(128);
BufferedReader br = new BufferedReader(new InputStreamReader(resources.openRawResource(id)));
String line = null;
try {
while((line = br.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
Log.v("Readed text:", content.toString());
return content.toString();
}
Renderer:
private int shaderProgram;
private int vertexBufferPointer;
private int colorBufferPointer;
private int textureBufferPointer;
private Context context;
private float[] vertices = {-1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f};
private float[] colors = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f
};
private float[] textureVertices = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
private int aVerPos, aTexPos, aVerCol;
private int uSamp;
private int texture;
private Bitmap textureBitmap;
public TriangleRenderer(Context context) {
this.context = context;
}
@Override
public void onDrawFrame(GL10 gl) {
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(uSamp, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferPointer);
glVertexAttribPointer(aVerPos, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferPointer);
glVertexAttribPointer(aVerCol, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferPointer);
glVertexAttribPointer(aTexPos, 2, GL_FLOAT, false, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
checkGLError("test");
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
glViewport(0, 0, width, height);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
initBuffers();
initShaders();
initTextures();
}
private void initTextures() {
textureBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
Log.v("Bitmap inafo:", textureBitmap.getWidth() + ", " + textureBitmap.getHeight());
int[] buffer = new int[1];
glGenTextures(1, buffer, 0);
texture = buffer[0];
Log.v("Texture", "Texture is at " + texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, GL_TRUE);
GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureBitmap, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
private void initShaders() {
shaderProgram = ShaderLoader.loadProgram(TextReader.readResource(context.getResources(), R.raw.vshader), TextReader.readResource(context.getResources(), R.raw.fshader));
Log.v("Shader program", shaderProgram + " is the id of shader program. :)");
glUseProgram(shaderProgram);
aVerPos = glGetAttribLocation(shaderProgram, "aVerPos");
if(aVerPos == -1) {
Log.e("Shader program", "Cudn't find aVerPos");
} else {
Log.v("Shader program", "Found vPosition @ " + aVerPos);
}
glEnableVertexAttribArray(aVerPos);
aVerCol = glGetAttribLocation(shaderProgram, "aVerCol");
if(aVerCol == -1) {
Log.e("Error", "Couldn't find aVColor");
} else {
Log.v("Success", "aVColor is at " + aVerCol + " :-3");
}
glEnableVertexAttribArray(aVerCol);
aTexPos = glGetAttribLocation(shaderProgram, "aTexPos");
if(aTexPos == -1) {
Log.e("Error", "Failed 2 find aTexPos");
} else {
Log.v("Succeed", "Succesfully located aTexPos @ " + aTexPos);
}
glEnableVertexAttribArray(aTexPos);
uSamp = glGetUniformLocation(shaderProgram, "uSampler");
if(uSamp == -1) {
Log.e("Error", "Couldn't finda uSampler " + uSamp);
} else {
Log.v("Succeed", "uSampler is @ " + uSamp + " :3");
}
}
private void initBuffers() {
vertexBufferPointer = initFloatBuffer(vertices);
colorBufferPointer = initFloatBuffer(colors);
textureBufferPointer = initFloatBuffer(textureVertices);
}
private int initFloatBuffer(float[] data) {
int[] buffer = new int[1];
glGenBuffers(1, buffer, 0);
int pointer = buffer[0];
if(pointer == -1) {
Log.e("Error", "Couldn't create buffer");
} else {
Log.v("Success", "Succesfully created buffer to " + pointer);
}
glBindBuffer(GL_ARRAY_BUFFER, pointer);
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(data.length * 4); //one float size is 4 bytes
byteBuffer.order(ByteOrder.nativeOrder()); //byte order must be native
FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
floatBuffer.put(data);
floatBuffer.flip();
glBufferData(GL_ARRAY_BUFFER, data.length * 4, floatBuffer, GL_STATIC_DRAW);
return pointer;
}
private void checkGLError(String op) {
int error = glGetError();
if(error != GL_NO_ERROR) {
Log.e("Error", op + "'s errorcode:" + Integer.toHexString(error));
}
}
and ofcourse
Vertex Shader:
attribute vec3 aVerPos;
attribute vec3 aVerCol;
attribute vec2 aTexPos;
varying vec3 vVerCol;
varying vec2 vTexPos;
void main(void) {
vTexPos = aTexPos;
vVerCol = aVerCol;
gl_Position = vec4(aVerPos, 1.0);
}
Fragment Shader:
precision mediump float;
varying vec3 vVerCol;
varying vec2 vTexPos;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vTexPos);
}
and result of executing that code is black screen and my custom logs
03-24 18:11:44.933: D/libEGL(4805): loaded /system/lib/egl/libGLES_android.so
03-24 18:11:44.948: D/libEGL(4805): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
03-24 18:11:44.956: D/libEGL(4805): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
03-24 18:11:44.956: D/libEGL(4805): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
03-24 18:11:45.066: D/dalvikvm(4805): Note: class Landroid/opengl/GLWrapperBase; has 250 unimplemented (abstract) methods
03-24 18:11:45.073: V/GLSurfaceView(4805): glGetString(7937) returns PowerVR SGX 540;
03-24 18:11:45.073: V/Success(4805): Succesfully created buffer to 70001
03-24 18:11:45.073: V/Success(4805): Succesfully created buffer to 140002
03-24 18:11:45.073: V/Success(4805): Succesfully created buffer to 210003
03-24 18:11:45.081: V/Readed text:(4805): attribute vec3 aVerPos;attribute vec3 aVerCol;attribute vec2 aTexPos;varying vec3 vVerCol;varying vec2 vTexPos;void main(void) { vTexPos = aTexPos; vVerCol = aVerCol; gl_Position = vec4(aVerPos, 1.0);}
03-24 18:11:45.081: V/Readed text:(4805): precision mediump float;varying vec3 vVerCol;varying vec2 vTexPos;uniform sampler2D uSampler;void main(void) { gl_FragColor = texture2D(uSampler, vTexPos);}
03-24 18:11:45.097: V/Shader program(4805): 70001 is the id of shader program. :)
03-24 18:11:45.097: V/Shader program(4805): Found vPosition @ 2
03-24 18:11:45.105: V/Success(4805): aVColor is at 1 :-3
03-24 18:11:45.105: V/Succeed(4805): Succesfully located aTexPos @ 0
03-24 18:11:45.105: V/Succeed(4805): uSampler is @ 1 :3
03-24 18:11:45.105: V/Bitmap inafo:(4805): 96, 96
03-24 18:11:45.105: V/Texture(4805): Texture is at 70001
I've also tried using legen... wait for it... dary nehe texture but didn't show up either
Okay.. out of stupidity I only added the image into drawable-hdpi.. This happened to me before but I didn't learn from it. Problem was solved by moving the picture to /raw folder