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;\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传过来的参数
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上真的太少资料
项目下载链接:
http://download.csdn.net/detail/chrisfxs/7547637
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。