OpenGL ES 2.0的阿尔法 [英] OpenGL ES 2.0 Alpha

查看:454
本文介绍了OpenGL ES 2.0的阿尔法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在OpenGL ES 2.0的Andr​​oid中加载纹理PNG(由Photoshop中导出),并使用它,但纯色好像透明的(在PNG黑圈完全是黑色)

我已经读,如果你扩展一个PNG超过50%的错误出现(我使用缩放更多相同的测试,因此我认为事实并非如此)

我也读到BitmapFactory不要读premultiplied阿尔法PNG,我trye​​d另一个机能的那个假设做的工作,但没有工作(也许是错误的)

要实现正确的阿尔法任何方式?

这是我的片段着色器:

  precision mediump浮动; //设置默认precision到中等。我们不需要高的
                            //在片段着色器precision。
统一VEC3 u_LightPos; //眼空间光的位置。
统一sampler2D u_Texture; //输入质感。不同VEC3 v_Position; //内插这个片段的位置。
不同VEC3 v_Normal; //这个片段插值正常。
不同VEC2 v_TexCoordinate; //每个片段插值纹理坐标。//入口点我们的片段着色器。
无效的主要()
{
    //将用于衰减。
    浮距离=长度(u_LightPos - v_Position);    //从光到顶点获取的照明方向向量。
    VEC3 lightVector =正常化(u_LightPos - v_Position);    //计算光矢量和顶点法线的点积。如果正常光向量
    //在相同的方向指向然后将得到最大的照明。
    飘漫= MAX(点(v_Normal,lightVector),0.0);    //添加衰减。
    扩散=漫*(1.0 /(1.0 +(0.25 *距离)));    //添加环境照明
    弥漫=弥漫+ 0.7;    //乘以漫反射照明的层次和质感值的颜色来获得最终输出的颜色。
    gl_FragColor =(漫射*的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(mMagiaProgramHandlea_TexCoordinate);
    mTexturePruebaUniformHandle = GLES20.glGetUniformLocation(mMagiaProgramHandleu_TextureVec);
    coordinate.drawMagia(mPositionHandle,mNormalHandle,mMagiaTextureCoordinateHandle);    //这乘以模型矩阵的视图矩阵,并且存储所述
    //导致MVP矩阵
    //(目前包含型号*视图)。    Matrix.multiplyMM(mMVPMatrix,0,mViewMatrix,0,mModelMatrix,0);
    //把在模型视图矩阵。
    GLES20.glUniformMatrix4fv(mMVMatrixHandle,1,假,mMVPMatrix,0);
    //这乘以投影矩阵的模型视图矩阵,并
    //将结果存储在MVP的矩阵
    //(现在包含模型*查看*投影)。
    Matrix.multiplyMM(mMVPMatrix,0,mProjectionMatrix,0,mMVPMatrix,0);    //传入联合矩阵。
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle,1,假,mMVPMatrix,0);    //转至眼睛空间光源位置。
    GLES20.glUniform3f(mLightPosHandle,mLightPosInEyeSpace [0],mLightPosInEyeSpace [1],mLightPosInEyeSpace [2]);    GLES20.glUniform2f(mTexturePruebaUniformHandle,Magia.posTextureX,Magia.posTextureY);
    //绘制正方形。
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,6);
    GLES20.glDisable(GLES20.GL_BLEND);

这是我的加载功能;

 公共静态INT loadTexture(最终上下文的背景下,最终诠释RESOURCEID)
{
    最终诠释[] = textureHandle新INT [1];    GLES20.glGenTextures(1,textureHandle,0);    如果(textureHandle [0]!= 0)
    {
        最后BitmapFactory.Options选项=新BitmapFactory.Options();
        options.inScaled = FALSE; //没有pre-缩放
        //读取的资源
        最后的位图位图= BitmapFactory.de codeResource(context.getResources(),RESOURCEID,期权);        //绑定到在OpenGL纹理
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,textureHandle [0]);        //设置过滤
        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);        //将位图到绑定的质感。
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,位图,0);        //回收该位图中,由于它的数据已被加载到OpenGL的。
        bitmap.recycle();
    }    如果(textureHandle [0] == 0)
    {
        抛出新的RuntimeException(错误加载的质感。);
    }    返回textureHandle [0];
}


解决方案

不知道是否有可能是与本身的质感,以及一个问题,但肯定有东西在你的shader code,可以给你带来意想不到的结果:

  gl_FragColor =(漫*的Texture2D(u_Texture,v_TexCoordinate));

既然你乘以所有颜色分量,包括α,用,所产生的颜色会尽快漫<部分透明/ code>具有小于1.0的值。由此产生的阿尔法将乘以你从质地得到了阿尔法。

如果你想使用你从质地为你片段的alpha采样的α,你不应该乘以漫。在code只乘以 RGB分量漫可能看起来像这样:

  vec4 texVal =的Texture2D(u_Texture,v_TexCoordinate);
gl_FragColor = vec4(漫* texVal.rgb,texVal.a);

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

这篇关于OpenGL ES 2.0的阿尔法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆