繁体   English   中英

如何在Opengl ES中获得一个像素的透明颜色?

[英]How I can get the transparent color of one pixel in Opengl ES?

在OpenGL的渲染器中,我尝试以下代码:

ByteBuffer buf = ByteBuffer.allocate(1 * 1 * 4);

GLES20.glReadPixels(60, 100, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);


float red = buf.get()/255.0f;

float green = buf.get()/255.0f;

float blue = buf.get()/255.0f;

float alpha = buf.get();

EngineX.show("red: " + red + " green: " + green + " blue: " + blue + " alpha: " + alpha);

alpha值始终返回-1.0

//类SurfaceView的实现//对此实现,我没有做任何特别的事情

public class GLSurfaceViewX extends GLSurfaceView
{
    BaseActivity activity;

    public GLSurfaceViewX(Context context)
    {
        super(context);
        activity = (BaseActivity) context;
            getHolder().setFormat(PixelFormat.RGBA_8888);
    }
}

//这是活动//在此处创建工程图的视图

public abstract class BaseActivity extends Activity
{
    private EngineX engine;
     GLSurfaceViewX view;

    @Override
    protected void onCreate(final Bundle pSavedInstanceState)
    {
        super.onCreate(pSavedInstanceState);

        if (!isOGLES20Compatible())
        {
            view = null;
            showErrorDialogBox();
            return;
        }
        engine = new EngineX(this);

        view = new GLSurfaceViewX(this);

        view.setEGLContextClientVersion(2);

        view.setRenderer(engine);

        // Render the view only when there is a change in the drawing data
        view.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

        setContentView(view);

    }

    @Override
    protected void onResume()
    {
        EngineX.show("BaseActivity: onResume");
        super.onResume();
        if (view != null)
        {
            view.onResume();
        }

    }

    @Override
    protected void onPause()
    {
        EngineX.show("BaseActivity: onPause");

        super.onPause();
        if (view != null)
        {
            view.onPause();
        }
    }

    @Override
    protected void onDestroy()
    {
        if (engine != null)
        {
            engine.closeGame();
        }

        super.onDestroy();
    }

    /* This method verify that your Phone is compatible with OGLES 2.x */
    private boolean isOGLES20Compatible()
    {
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo info = am.getDeviceConfigurationInfo();
        return (info.reqGlEsVersion >= 0x20000);
    }

    /* show an error message */
    private void showErrorDialogBox()
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Sorry! OpenGL ES 2.0 not supported on device.").setCancelable(false)
                .setPositiveButton("OK", new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dialog, int id)
                    {
                        dialog.cancel();
                        finish();
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();
    }

}

好吧,首先您必须意识到Java无法使用byte表示数字255 它没有无符号字节类型。 全亮的颜色分量将返回0xFF ,在Java中(二进制补码)为-1

那么,您如何解决呢? 我会考虑以下几点:

float red   = (buf.get () & 0xFF) / 255.0f;
float green = (buf.get () & 0xFF) / 255.0f;
float blue  = (buf.get () & 0xFF) / 255.0f;
float alpha = (buf.get () & 0xFF);

这是有效的,因为带符号的字节被提升为整数以执行按位与。 生成的整数仍然是带符号的,但是这里发生的是符号位不包含在您AND的值中( 0x000000FF ),因此该数字丢失了其符号,因此可以正确表示> 127的值。

  • 注意 :我不确定为什么不像其余值一样将alpha除以255.0f 它们都是8位的。

还请记住,并非所有像素格式实际上都在帧缓冲区中有一个位置来存储alpha值。 很多情况下不需要目标Alpha,您可以仅使用当前绘制的Alpha值(源Alpha)生成Alpha混合。 如果您使用的是RGB_565RGB_888OPAQUE之类的格式,那么向后读取alpha通道将始终为您提供恒定值。


更新:

为了使您的帧缓冲区存储一个Alpha通道,您应该修改以下函数:

@Override
protected void onCreate(final Bundle pSavedInstanceState)
{
    super.onCreate(pSavedInstanceState);

    if (!isOGLES20Compatible())
    {
        view = null;
        showErrorDialogBox();
        return;
    }
    engine = new EngineX(this);

    view = new GLSurfaceViewX(this);

    view.setEGLContextClientVersion(2);


    //
    // Default is usually RGB565 or RGB8 (no Alpha) -- you need RGBA8
    //
    view.setEGLConfigChooser (8, 8, 8, 8, 16, 0);

    //
    // If you want the actual SURFACE to be translucent, then you also need this
    //
    view.setZOrderOnTop         (true);
    view.getHolder ().setFormat (PixelFormat.RGBA_8888);


    view.setRenderer(engine);

    // Render the view only when there is a change in the drawing data
    view.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

    setContentView(view);

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM