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


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

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

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

    顺便说下,虽然现在google被墙,除了翻墙还有个很简单的办法上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;
    "
      "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("vPosition") = %d
    ",
          gvPositionHandle);
      gvTexCoorHandle = glGetAttribLocation(gProgram, "vTexCoords");
      checkGlError("glGetAttribLocation");
      LOGI("glGetAttribLocation("vTexCoords") = %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*类型。这样在上面

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

    传进去才不会错。

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

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

  • 相关阅读:
    Spring读书笔记
    window.open参数详解
    在spring security3上实现验证码
    Struts2.1 标签详细说明
    总结一下log4j
    【转】hibernate映射oracle自增长
    Java中四舍五入保留七位小数
    求三个整数的最小公倍数
    boxshadow 曲线阴影和翘边阴影
    <div> <p> <span>的用法和区别
  • 原文地址:https://www.cnblogs.com/qingchen1984/p/5212951.html
Copyright © 2020-2023  润新知