2

我正在尝试使用 GLSurfaceView 和本机 C 代码在 Android 上使用 OpenGL ES 渲染 640x480 RGB565 图像。

最初,glTexImage2D 出现 0x0501 错误,我可以通过更改图像尺寸来解决该错误。

但是现在,在“drawFrame”调用中,当我执行 glDrawTexiOES 来重新渲染纹理时,我在日志上收到以下错误:

drawtex.c:89:DrawTexture:未启用纹理

我已经在做 glEnable(GL_TEXTURE_2D),还有什么我应该做的吗?

是否有完整的示例显示 GLSurfaceView 与使用纹理的本机代码?

提前致谢!

4

4 回答 4

2

我遇到了同样的问题,您可以像这样制作自定义渲染器:或者(通过直接将 SurfaceView 子类化有点复杂)


import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import javax.microedition.khronos.opengles.GL11Ext;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.util.Log;

import com.TIEmulator.JNI.NLib;

class EmulatorRenderer implements GLSurfaceView.Renderer, NLib.EventsInterface {

    public static interface RenderCb {
        public boolean dismissStartupDialog();

        public void updateStartupDialog(String msg);
    }

    private static int mViewHeight;
    private static int mViewWidth;
    private static BitmapFactory.Options sBitmapOptions = new BitmapFactory.Options();

    private static int TEX_BUF_HEIGHT = 128;
    private static int TEX_BUF_WIDTH = 256;

    private final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4
            * EmulatorRenderer.TEX_BUF_HEIGHT * EmulatorRenderer.TEX_BUF_WIDTH);
    private boolean emulation_running = false;

    private Context mContext = null;
    private final int[] mCropWorkspace;
    private final GLSurfaceView mGLView;
    protected int mTex = -1;

    protected int[] mtexBuf = new int[1];
    private final int[] mTextureNameWorkspace;

    public EmulatorRenderer(final Context ctx, final GLSurfaceView v) {
        // Pre-allocate and store these objects so we can use them at runtime
        // without allocating memory mid-frame.
        mTextureNameWorkspace = new int[1];
        mCropWorkspace = new int[4];

        byteBuffer.order(ByteOrder.BIG_ENDIAN);

        // Set our bitmaps to 16-bit, 565 format.
        EmulatorRenderer.sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        mGLView = v;
        mContext = ctx;

        try {
            NLib.setListener(this);
        } catch (final RuntimeException exc) {
            exc.printStackTrace();
            callFinishOnce();
            return;
        }
        if (!NLib.TryLoadLib()) {
            callFinishOnce();
            return;
        }
        Log.v(this.getClass().toString(),">>>>>>>>>>>>>>>>>>>>>>> init successfull! <<<<<<<<<<<<<<<<<<<<<<");
    }

    private void callFinishOnce() {
        if (mContext != null) {
            ((Activity) mContext).finish();
            mContext = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        NLib.stopEmu();
        super.finalize();
    }

    protected int loadBB(final GL10 gl) {
        int textureName = -1;
        if (mContext != null && gl != null) {
            gl.glGenTextures(1, mTextureNameWorkspace, 0);

            textureName = mTextureNameWorkspace[0];
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                    GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                    GL10.GL_NEAREST);// GL10.GL_LINEAR);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                    GL10.GL_CLAMP_TO_EDGE);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                    GL10.GL_CLAMP_TO_EDGE);

            gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
                    GL10.GL_REPLACE);

            mCropWorkspace[0] = 0; // u
            // mCropWorkspace[1] = EMU_HEIGHT; // v
            mCropWorkspace[1] = 0; // v

            mCropWorkspace[2] = NLib.getWidth(); // w
            // mCropWorkspace[3] = -EMU_HEIGHT; // h -EMU_HEIGHT;
            mCropWorkspace[3] = NLib.getHeight(); // h -EMU_HEIGHT;
            byteBuffer.order(ByteOrder.BIG_ENDIAN);

            final int error = gl.glGetError();
            if (error != GL10.GL_NO_ERROR) {
                Log.e("SpriteMethodTest", "Texture Load GLError: " + error);
            }
        }
        return textureName;
    }

    public void onDrawFrame(final GL10 gl) {
        // Log.v(this.toString(),"onDrawFrame called");
        gl.glActiveTexture(mTex);
        gl.glClientActiveTexture(mTex);

        byteBuffer.position(0);

        // this two lines bind and create the texture!
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTex);
        ((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D,
                GL11Ext.GL_TEXTURE_CROP_RECT_OES, mCropWorkspace, 0);

        gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA,
                EmulatorRenderer.TEX_BUF_WIDTH,
                EmulatorRenderer.TEX_BUF_HEIGHT, 0, GL10.GL_RGBA,
                GL10.GL_UNSIGNED_BYTE, byteBuffer);

        ((GL11Ext) gl).glDrawTexiOES(0, 0, 0, EmulatorRenderer.mViewWidth,
                EmulatorRenderer.mViewHeight);

        /** gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL);
         */
    }

    public void OnFatalError(final String text) {
        Log.d(toString(), "FATAL ERROR CALLBACK raised: " + text
                + " ===> Activity calls finish()");
    }

    public void onFinish() {
        onPause();
    }
/*
* JNI interface
*
*/
    @Override
    public void OnBufferUpdate() {
        mGLView.requestRender();
    }
    // TODO Auto-generated method stub

    @Override
    public void OnWarning(String msg) {
        // TODO Auto-generated method stub

    }
    public void onPause() {
        mGLView.onPause();
        // Log.v("onPause", "NILib.stopEmulate()");
        emulation_running = false;
        //startupDialogDismiss = false;
        NLib.stopEmu();
    }

    public void onResume() {
        // Log.v(this.toString(),"EmulatorRenderer:onResume called");
        NLib.startEmu(byteBuffer);

        mGLView.onResume();
        //callFinishOnce();
        emulation_running = true;
    }

    public void onSurfaceChanged(final GL10 gl, final int w, final int h) {
        EmulatorRenderer.mViewWidth = w;
        EmulatorRenderer.mViewHeight = h;
        Log.v(toString(), "onSurfaceChanged: ==> New View Size: [" + w + ","
                + h + "]");
    }

    public void onSurfaceCreated(final GL10 gl, final EGLConfig config) {

        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
        gl.glShadeModel(GL10.GL_FLAT);
        gl.glDisable(GL10.GL_DEPTH_TEST);
        gl.glEnable(GL10.GL_TEXTURE_2D);

        /*
         * By default, OpenGL enables features that improve quality but reduce
         * performance. One might want to tweak that especially on software
         * renderer.
         */
        gl.glDisable(GL10.GL_DITHER);
        gl.glDisable(GL10.GL_LIGHTING);
        gl.glDisable(GL10.GL_BLEND);
        gl.glDisable(GL10.GL_DEPTH_TEST);
        gl.glHint(GL10.GL_LINE_SMOOTH_HINT, GL10.GL_NICEST); // Set Line
        // Antialiasing
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        // create the one and only texture here...
        mTex = loadBB(gl);
    }

    public void OnTIEmuStopped() {
        System.out.println("OnTIEmuStopped callback called! ");
        callFinishOnce();
    }

    /* Called when the size of the window changes. */
    public void sizeChanged(final GL10 gl, final int w, final int h) {
        // Log.v(this.toString(),"sizeChanged: ==> new Viewport: ["+w+","+h+"]");

        gl.glViewport(0, 0, w, h);
        /*
         * Set our projection matrix. This doesn't have to be done each time we
         * draw, but usually a new projection needs to be set when the viewport
         * is resized.
         */
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();

        // Set up the orthographic projection
        // gl.glOrthof(0.0f, w, 0.0f, h, 0.0f, 1.0f);
        gl.glOrthof(0.0f, w, 0.0f, 0.0f, h, 1.0f);

        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
        gl.glEnable(GL10.GL_TEXTURE_2D);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
    }
}
于 2010-11-11T16:51:51.577 回答
1

是的,我做到了...

gl.glGenTextures(1, mTextureNameWorkspace, 0);

            textureName = mTextureNameWorkspace[0];
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                    GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                    GL10.GL_NEAREST);// GL10.GL_LINEAR);

            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                    GL10.GL_CLAMP_TO_EDGE);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                    GL10.GL_CLAMP_TO_EDGE);

            gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
                    GL10.GL_REPLACE);

            mCropWorkspace[0] = 0; // u
            // mCropWorkspace[1] = EMU_HEIGHT; // v
            mCropWorkspace[1] = 0; // v

            mCropWorkspace[2] = NLib.getWidth(); // w
            // mCropWorkspace[3] = -EMU_HEIGHT; // h -EMU_HEIGHT;
            mCropWorkspace[3] = NLib.getHeight(); // h -EMU_HEIGHT;

            static_test_debug_if_gl_error( gl , "loadBB time 1");

            gl.glActiveTexture(mTex);
            gl.glClientActiveTexture(mTex);

            static_test_debug_if_gl_error( gl , "loadBB time 2");
于 2010-11-11T20:49:24.257 回答
0

以下将设置纹理并准备好在 GL_TEXTURE0 上使用:

加载纹理时:

// in your native onSurfaceCreated function:

glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
// setup texture parameters if you want:
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // etc.
glTexImage2D(GL_TEXTURE_2D, ... );

请参阅此处了解如何填写 TexImage2D 参数。

不幸的是,我无法让 glDrawTex_OES 函数正常工作,但是如果将纹理渲染到四边形上,纹理确实可以工作:

// in your native onRender function:

glBindTexture(GL_TEXTURE_2D, sGlTexture.texID);
// quad drawing:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, quadVerts[i]);
glTexCoordPointer(2, GL_FLOAT, 0, quadTexCoords[i]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
于 2010-07-06T06:03:27.980 回答
0

您是否先生成纹理 ID 并绑定纹理?

glGenTexture()/glBindTexture()

于 2010-05-20T05:56:31.350 回答