android ndk调用OpenGL 实现纹理贴图Texture

android ndk调用OpenGL 实现纹理贴图Texture

首先必须说,国内在OpenGL这方面特别是ndk上的分享太太太少

这中间遇到很多问题,而这些问题需要在书上,在网上,在各种资料上找,而且书上是java层调用,网上的缺少各种文件案例,只有在java层研究,在各种案例中找需要的知识点,遇到问题最终只有google搜外国网站才能解决。

顺便说下,虽然现在google被墙,除了FQ还有个很简单的办法上google。

http://www.gfsoso.com/ 

谷粉搜搜

接下来正文

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

学习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;\n"
  "attribute vec2 vTexCoords;\n"
  "varying vec2 colorVarying;\n"
  "void main() {\n"
  "  gl_Position = vPosition;\n"
  "  colorVarying = vTexCoords;\n"
  "}\n";

static const char gFragmentShader[] = 
  "precision mediump float;\n"
  "varying vec2 colorVarying;\n"
  "uniform sampler2D sampler;\n"
  "void main() {\n"
  "  //gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
  "gl_FragColor = texture2D(sampler,colorVarying);\n"
  "}\n";

添加了定点纹理坐标和传递给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(\"vPosition\") = %d\n",
      gvPositionHandle);
  gvTexCoorHandle = glGetAttribLocation(gProgram, "vTexCoords");
  checkGlError("glGetAttribLocation");
  LOGI("glGetAttribLocation(\"vTexCoords\") = %d\n",
      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\n", "m_texture:", v);
//    v = (const char *) mTexture;
//    LOGI("GL %s = %s\n", "mTexture:", v);
}

这里有个问题就是导致后面黑色纹理的主要原因:

接收Java传过来的id时要用GLuint*类型。这样在上面

<pre name="code" class="cpp"> glBindTexture(GL_TEXTURE_2D,mTexture[0]);

传进去才不会错。

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

最后希望大家能多点分享,像我这样刚接触OpenGL特别是在ndk上真的太少资料

posted on 2016-02-24 14:46  qingchen1984  阅读(1669)  评论(0编辑  收藏  举报

导航