I'm attempting to get a texture to show up on on a square made from a triangle fan, the texture is made from a Canvas. The main color is just yellow and a smaller box is drawn inside of it, but the final texture is just solid yellow.
Yellow square with no texture (picture)
Fragment shadder:
public static final String fragmentShaderCode_TEXTURED =
"precision mediump float;" +
"varying vec2 v_texCoord;" +
"uniform sampler2D s_texture;" +
"void main() {" +
//"gl_FragColor = vColor;"+
" gl_FragColor = texture2D( s_texture, v_texCoord );" +
"}";
Texture generation:
public static int loadGLTexture(String s){
Rect r = new Rect();
ThreadDat.get().paint.getTextBounds(s, 0, 1, r); //get string dimensions, yeilds 8x9 pxls
Bitmap bitmap = Bitmap.createBitmap(bestSize(r.width()),bestSize(r.height()), Bitmap.Config.ARGB_8888);
//example size is 16x16pxls
Log.i("TextureSize", r.width() + " " + r.height());
Canvas c = new Canvas(bitmap);
//some temporary test code setting the background yellow
//Paint colors are stored per thread, only one right now
ThreadDat.get().paint.setARGB(255, 255, 255, 0);
c.drawRect(0, 0, c.getWidth(), c.getHeight(), ThreadDat.get().paint);
//type the letter, in this case "A" in blue
ThreadDat.get().paint.setARGB(255, 0, 0, 255);
ThreadDat.get().paint.setTypeface(Typeface.create("Consolas", Typeface.NORMAL));
c.drawText(s.charAt(0) + "", 0, 0, ThreadDat.get().paint);
//draw another square that is half width and height, should be Blue
c.drawRect(0, 0, c.getWidth() / 2, c.getHeight() / 2, ThreadDat.get().paint);
return loadTexture(bitmap);
}
Draw code:
@Override
public void draw() {
//clearing any error to check if program has an error
GLES20.glGetError();
//get the compiled shader for textured shapes
int prgm = MyGLRenderer.getSTRD_TXTR_SHDR();
GLES20.glUseProgram(prgm);
//check for new errors and log to logcat (nothing)
MyGLRenderer.logError();
//setup projection view matrix
float[] scratch = new float[16];
Matrix.setIdentityM(scratch, 0);
Matrix.multiplyMM(scratch, 0, MyGLRenderer.getmMVPMatrix(), 0, scratch, 0);
//apply translations to matrix
Matrix.translateM(scratch, 0, xOffset, yOffset, zOffset);
Matrix.setRotateEulerM(scratch, 0, yaw, pitch, roll);
//get vPosition variable handle from chosen shader
mPosHandle = GLES20.glGetAttribLocation(prgm, "vPosition");
GLES20.glEnableVertexAttribArray(mPosHandle);
GLES20.glVertexAttribPointer(mPosHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, VERTEX_STRIDE, vertexBuffer);
////pass color data (set to white)
//mColorHandle = GLES20.glGetUniformLocation(prgm, "vColor");
//GLES20.glUniform4fv(mColorHandle, 1, color, 0);
//use texture0
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//use texture from -> int textureID = MyGLRenderer.loadGLTexture("A");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
//get handel for "uniform sampler2D s_texture;" to set value
int txtureHandle = GLES20.glGetUniformLocation(prgm, "s_texture");
GLES20.glUniform1i(txtureHandle, 0); //set s_texture to use binded texture 0
//pass in texture coords (u,v / s,t)
int textureCoordHndl = GLES20.glGetAttribLocation(prgm, "a_texCoord");
GLES20.glVertexAttribPointer(textureCoordHndl, 2/*size, 2 points per vector*/,
GLES20.GL_FLOAT, false, 0, textureBuffer);
//pass in the model view projection matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(prgm, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, scratch, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertex_count);
GLES20.glDisableVertexAttribArray(mPosHandle);
MyGLRenderer.logError();
}
I tried using the same coordinate set as used in this example:
Vertices for square:
{ 0, 0, 0, //bottom left
0, height, 0, //topLeft
width, 0, 0, // bottom Right
width, height, 0)}; //topRight
Texture coords:
0.0f, 1.0f, // top left (V2)
0.0f, 0.0f, // bottom left (V1)
1.0f, 1.0f, // top right (V4)
1.0f, 0.0f // bottom right (V3)
This does sound like there is an issue with texture coordinates. Since the whole thing is yellow I would suspect that the v_texCoord
is always (0,0)
in your fragment shader so the first texture pixel is being repeated.
The texture itself seems to be ok since the color is being drawn. Without the texture you would most likely see a black rectangle.
Anyway to handle such issues you need to be a bit inventive in debugging, testing. For testing the coordinates use gl_FragColor = vec4( v_texCoord.x, v_texCoord.y, .0, 1.0 );
. This should output a gradient rectangle where top left is black, top right is red, bottom left is green. If you do not see this result then your texture coordinates are incorrect. In this case first check if the varying
is correctly connected from the vertex shader. You may use v_texCoord = vec2(1.0, 0.0)
in the vertex shader and the result should be a red rectangle (assuming you still have the previous test in the fragment shader). If the rectangle is red then the issue is most likely in your handles and not in the shaders (otherwise the varying is incorrectly set. Maybe a mismatch in naming). Check what is the value of the handle textureCoordHndl
. If this is a negative value then the handle was not connected. This is most likely due to a mismatch in the naming.
From further inspection:
You are missing the enabling of the attribute for texture coordinates GLES20.glEnableVertexAttribArray(textureCoordHndl);
. Remember that each of the attributes must be enabled before you use them.