I am trying to load a texture PNG ( exported by photoshop) and use it in OpenGL ES 2.0 in Android, but the solid color seems like transparent ( black circle in the png is totally black)
I has been read that if you scale a png more than 50% that bug appear( I tested with scaling more and same so I supposed that is not the case)
I also read that BitmapFactory dont read premultiplied alpha PNG ,I tryed another fuction that supposed that do the work but didnt work( maybe it was wrong)
Any ways to achieve the correct alpha?
This is my fragment shader:
precision mediump float; // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
uniform vec3 u_LightPos; // The position of the light in eye space.
uniform sampler2D u_Texture; // The input texture.
varying vec3 v_Position; // Interpolated position for this fragment.
varying vec3 v_Normal; // Interpolated normal for this fragment.
varying vec2 v_TexCoordinate; // Interpolated texture coordinate per fragment.
// The entry point for our fragment shader.
void main()
{
// Will be used for attenuation.
float distance = length(u_LightPos - v_Position);
// Get a lighting direction vector from the light to the vertex.
vec3 lightVector = normalize(u_LightPos - v_Position);
// Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
// pointing in the same direction then it will get max illumination.
float diffuse = max(dot(v_Normal, lightVector), 0.0);
// Add attenuation.
diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance)));
// Add ambient lighting
diffuse = diffuse + 0.7;
// Multiply the color by the diffuse illumination level and texture value to get final output color.
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
}
This is my draw call:
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glUseProgram(mMagiaProgramHandle);
mMagiaTextureCoordinateHandle = GLES20.glGetAttribLocation(mMagiaProgramHandle, "a_TexCoordinate");
mTexturePruebaUniformHandle = GLES20.glGetUniformLocation(mMagiaProgramHandle, "u_TextureVec");
coordinate.drawMagia(mPositionHandle, mNormalHandle, mMagiaTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the
// result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and
// stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Pass in the light position in eye space.
GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);
GLES20.glUniform2f(mTexturePruebaUniformHandle, Magia.posTextureX, Magia.posTextureY);
// Draw the square.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
GLES20.glDisable(GLES20.GL_BLEND);
This is my load function;
public static int loadTexture(final Context context, final int resourceId)
{
final int[] textureHandle = new int[1];
GLES20.glGenTextures(1, textureHandle, 0);
if (textureHandle[0] != 0)
{
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Read in the resource
final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
// Bind to the texture in OpenGL
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
// Set filtering
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Recycle the bitmap, since its data has been loaded into OpenGL.
bitmap.recycle();
}
if (textureHandle[0] == 0)
{
throw new RuntimeException("Error loading texture.");
}
return textureHandle[0];
}
Not sure if there could be a problem with the texture itself as well, but there's definitely something in your shader code that could give you unexpected results:
gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));
Since you're multiplying all color components, including the alpha, with diffuse
, the resulting color will be partially transparent as soon as diffuse
has a value less than 1.0. The resulting alpha will be diffuse
multiplied by the alpha you got from the texture.
If you want to use the alpha that you sampled from the texture as the alpha of your fragment, you should not multiply it with diffuse
. The code to only multiply the RGB components with diffuse
could look like this:
vec4 texVal = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(diffuse * texVal.rgb, texVal.a);