OpenGL ES 2.0 Alpha

Я пытаюсь загрузить текстуру PNG (экспортированную из Photoshop) и использовать ее в OpenGL ES 2.0 в Android, но сплошной цвет выглядит прозрачным (черный круг в png полностью черный)

Ошибка PNG

Я читал, что если вы масштабируете png более чем на 50%, эта ошибка появляется (я тестировал с масштабированием больше и то же самое, поэтому я предположил, что это не так)

Я также читал, что BitmapFactory не читает предварительно умноженный альфа PNG, я попробовал другую функцию, которая предполагала, что выполняет работу, но не работает (возможно, это было неправильно)

Есть ли способы добиться правильной альфы?

Это мой фрагментный шейдер:

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));                                       
}

Это мой розыгрыш:

    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);

Это моя функция загрузки;

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];
}

1 ответ

Решение

Не уверен, что может быть проблема и с самой текстурой, но в вашем шейдерном коде определенно есть что-то, что может дать вам неожиданные результаты:

gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));

Поскольку вы умножаете все цветовые компоненты, включая альфа, с diffuseПолученный цвет будет частично прозрачным, как только diffuse имеет значение менее 1,0. Итоговая альфа будет diffuse умножается на альфа, полученную из текстуры.

Если вы хотите использовать альфа, которую вы взяли из текстуры, в качестве альфы вашего фрагмента, вы не должны умножать ее на diffuse, Код только для умножения компонентов RGB на diffuse может выглядеть так:

vec4 texVal = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(diffuse * texVal.rgb, texVal.a);
Другие вопросы по тегам