有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在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();
    }

}

共 (1) 个答案

  1. # 1 楼答案

    首先,你必须意识到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);
    

    这是因为有符号字节提升为整数以执行按位和运算。结果的整数仍然是有符号的,但这里发生的是符号位不包括在值you和d中(0x000000FF),因此数字失去了符号,因此能够正确地表示值>127

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

    还请记住,并非所有像素格式都在帧缓冲区中有存储alpha值的位置。很多事情都不需要目标alpha,可以只使用当前绘制的alpha值(源alpha)进行alpha混合。如果您使用的格式是RGB_565RGB_888不透明,则回读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);
    
    }