Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android ndk調用OpenGL 實現紋理貼圖Texture

android ndk調用OpenGL 實現紋理貼圖Texture

編輯:關於Android編程

首先必須說,國內在OpenGL這方面特別是ndk上的分享太太太少

 

這中間遇到很多問題,而這些問題需要在書上,在網上,在各種資料上找,而且書上是java層調用,網上的缺少各種文件案例,只有在java層研究,在各種案例中找需要的知識點,遇到問題最終只有google搜外國網站才能解決。

 

 

接下來正文

——————————————————————————————

學習ndk應該都是從google配有的案例開始的吧:GL2JNIActivity

這個案例就是一個會變顏色的背景加一個綠色三角形

因為我開始學習紋理貼圖,所以打算將三角形換成貼圖

 

首先需要配置紋理

在GL2JNIView.java中修改Renderer類

 

 private static class Renderer implements GLSurfaceView.Renderer {
        public void onDrawFrame(GL10 gl) {
            GL2JNILib.step();
        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GL2JNILib.init(width, height);
        }
        
        
        private Context mContext;
        int textureId;
        private int[] TextureString = new int[1];
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        	mContext = GL2JNIActivity.getContext();
        	
            //Bitmap bitmap = getBitmap(mContext,R.drawable.bac);
            Bitmap bitmap = getBitmap(mContext,R.drawable.wall);
            if(bitmap != null)
            {
            	Log.e(step, bing the texture succeed!);
            	gl.glEnable(GLES20.GL_TEXTURE_2D);
	            gl.glGenTextures(1, TextureString,0);
	            textureId= TextureString[0];
	            Log.e(textureId, String.valueOf(textureId));
	            gl.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
	            		GLES20.GL_CLAMP_TO_EDGE); 
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
	            		GLES20.GL_CLAMP_TO_EDGE); 
	            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
	            GL2JNILib.setTextures(TextureString);
	           // GL2JNILib.setTextures(textureId);
	            bitmap.recycle();
            }

        }
        
        private Bitmap getBitmap(Context context,int resId)
        {
        	//getBitmap by decodeResources()
//        	BitmapFactory.Options options = new BitmapFactory.Options();
//        	options.inScaled = false;
//        	return BitmapFactory.decodeResource(context.getResources(), resId,options);
        
        	//getBitmap by decodeStream()
        	InputStream bitmapStream = null;
        	bitmapStream = context.getResources().openRawResource(R.drawable.bac);
        	return BitmapFactory.decodeStream(bitmapStream);
        	//經驗證上面兩種方法都可以
        }
    }
因為這部分之前一直有問題,紋理試過一直閃爍,一直黑色,修改了很多地方,也不確定那些才是導致問題的根本原因,但是我盡可能貼出來,大家也多交流交流:

 

1.圖片格式要是2的倍數*2的倍數,而且有的說不超過1024有點不超過512,做測試還是用256*256的好了。

2.

gl.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
要在
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
	            		GLES20.GL_CLAMP_TO_EDGE); 
	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
	            		GLES20.GL_CLAMP_TO_EDGE); 
之前

 

3.

 

	            gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
	            		GLES20.GL_CLAMP_TO_EDGE); 
最後的參數要是
GLES20.GL_CLAMP_TO_EDGE

 

貌似跟mipmap有關

4.

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

 

這個一定要放最後

5.

 

GL2JNILib.setTextures(TextureString);
傳給C++層的參數一定要是int數組

 

 

 

接著是c++層的代碼

首先是腳本修改

 

static const char gVertexShader[] = 
    attribute vec4 vPosition;

	attribute vec2 vTexCoords;

	varying vec2 colorVarying;

    void main() {

      gl_Position = vPosition;

	  colorVarying = vTexCoords;

    }
;

static const char gFragmentShader[] = 
	precision mediump float;

	varying vec2 colorVarying;

	uniform sampler2D sampler;

    void main() {

      //gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);

	gl_FragColor = texture2D(sampler,colorVarying);

    }
;

 

添加了定點紋理坐標和傳遞給pixelShader變量

pixelShader添加了接收vertexShader傳過來的參數

 

bool setupGraphics(int w, int h)的修改

 

GLuint gProgram;
GLuint gvPositionHandle;
GLuint gvTexCoorHandle;

bool setupGraphics(int w, int h) {
    printGLString(Version, GL_VERSION);
    printGLString(Vendor, GL_VENDOR);
    printGLString(Renderer, GL_RENDERER);
    printGLString(Extensions, GL_EXTENSIONS);

    LOGI(setupGraphics(%d, %d), w, h);
    gProgram = createProgram(gVertexShader, gFragmentShader);
    if (!gProgram) {
        LOGE(Could not create program.);
        return false;
    }
    gvPositionHandle = glGetAttribLocation(gProgram, vPosition);
    checkGlError(glGetAttribLocation);
    LOGI(glGetAttribLocation(Position) = %d
,
            gvPositionHandle);
    gvTexCoorHandle = glGetAttribLocation(gProgram, vTexCoords);
    checkGlError(glGetAttribLocation);
    LOGI(glGetAttribLocation(TexCoords) = %d
,
    		gvTexCoorHandle);

    glViewport(0, 0, w, h);
    checkGlError(glViewport);
    return true;
}
添加了
gvTexCoorHandle = glGetAttribLocation(gProgram, vTexCoords);
獲取紋理坐標屬性引用id

 


void renderFrame() 的修改

 

const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
        0.5f, -0.5f };
const GLfloat gTexCoor[] = { 0.5f,0, 0,1,
		1,1 };
void renderFrame() {
    static float grey;
    grey += 0.01f;
    if (grey > 1.0f) {
        grey = 0.0f;
    }
    glClearColor(grey, grey, grey, 1.0f);
    checkGlError(glClearColor);
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    //glClear( GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    checkGlError(glClear);

    glUseProgram(gProgram);
    checkGlError(glUseProgram);

    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
    checkGlError(glVertexAttribPointer);
    glVertexAttribPointer(gvTexCoorHandle, 2, GL_FLOAT, GL_FALSE, 0, gTexCoor);
    checkGlError(glVertexAttribPointer);
    glEnableVertexAttribArray(gvPositionHandle);
    checkGlError(glEnableVertexAttribArray);
    glEnableVertexAttribArray(gvTexCoorHandle);
    checkGlError(glEnableVertexAttribArray);
    glActiveTexture(GL_TEXTURE0);
    checkGlError(glActiveTexture);
    glBindTexture(GL_TEXTURE_2D,mTexture[0]);
    checkGlError(glBindTexture);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    checkGlError(glDrawArrays);
}

添加了紋理坐標的數據,綁定紋理,最後畫帶有紋理的三角形

 

添加接收Java層傳遞過來的紋理id

 

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_setTextures(JNIEnv * env, jobject obj,jintArray texture)
{
	mTexture = (GLuint *)env->GetIntArrayElements(texture,0);
//	m_texture = (unsigned int)env->GetIntArrayElements(texture,0);//it doesnt work!!!!what the fuck dont try this anymore!!!
//    const char *v = (const char *) m_texture;
//    LOGI(GL %s = %s
, m_texture:, v);
//    v = (const char *) mTexture;
//    LOGI(GL %s = %s
, mTexture:, v);
}
這裡有個問題就是導致後面黑色紋理的主要原因:

 

接收Java傳過來的id時要用GLuint*類型。這樣在上面


glBindTexture(GL_TEXTURE_2D,mTexture[0]);

 


 

傳進去才不會錯。

都怪我c++基礎不好...

最後希望大家能多點分享,像我這樣剛接觸OpenGL特別是在ndk上真的太少資料

 

項目下載鏈接:

http://download.csdn.net/detail/chrisfxs/7547637

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved