此页面记录开发中遇到的显示编程问题。内容随时可能变更。
一、Skia
Android的二维渲染引擎
http://code.google.com/p/skia/
1. 两类抗锯齿
Skia有两种不同的抗锯齿,用不同的标志表示:
void setAntiAlias(boolean aa)
void setFilterBitmap(boolean filter)
注意不要混淆,前者是边缘的抗锯齿,后者则是位图缩放或旋转的抗锯齿。
see also:
http://developer.android.com/reference/android/graphics/Paint.html
而
void setDither(boolean dither)
则是用于设备与源不同色深时的像素处理方式,和抗锯齿(实际上是抗色带)有关。
see also:
http://www.codeandweb.com/texturepacker/features
二、OpenGL ES
Android的三维渲染引擎
http://www.khronos.org/opengles/
(20130317)
opengles-book-samples
Android GLES 2.0示例代码(跨平台)
https://code.google.com/p/opengles-book-samples/
三、Renderscript
Android的高性能三维渲染语言
http://developer.android.com/guide/topics/renderscript/index.html
四、AndEngine
自由的Android 2D OpenGL游戏引擎
1. Texture disappears问题(纹理消失)
http://www.andengine.org/forums/development/texture-disappears-t4294.html
http://www.andengine.org/forums/bugs/texture-disappears-t3962.html
这个问题出现在渲染一个场景较长时间(?)。
解决办法是关闭VBO:
EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mBoundCamera); engineOptions.getRenderOptions().disableExtensionVertexBufferObjects(); engineOptions.getTouchOptions().setRunOnUpdateThread(true); this.mEngine = new Engine(engineOptions); return this.mEngine;
2. setAlpha的问题
使用setAlpha之前需要设置混合函数:
bg.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
因为默认下的混合函数不符合图层混合的效果(和背景色混合,而非下面的那个图层)。
用于制作透明度动画时要注意这个问题。
五、libGDX
Desktop/Android/HTML5 Java游戏开发框架
http://libgdx.badlogicgames.com/
http://code.google.com/p/libgdx/
(20130314)
lwjgl-basics
https://github.com/mattdesl/lwjgl-basics/wiki
gles和glsl相关教程,示例代码可以移植到libgdx上(lwjgl为后端)
讲解比较详细,推荐。
(20130606)
对于官方的IDE:adt-bundle,通常需要一个Java工程(可运行PC版)和一个Android工程(可运行在Android上)。
注意:Android工程是依赖于Java工程,而且需要在工程属性->Java Build Path->Order and Export中勾选依赖的Java工程(否则,运行时会提示找不到类)
另外,由于相同的原因,如果libgdx的jar文件放在libs目录下,会自动链接到类路径中,不过问题是无法指定源代码jar,也就是说,无法在编辑器中跳转至源代码(例如gdx-sources.jar)。
解决办法是gdx.jar和gdx-backend-android.jar及其源码jar包不要放在libs目录下,而是用Java工程的方式加入编译类路径,然后用上面的方法,在工程属性->Java Build Path->Order and Export中勾选这些jar。这样,既可以指定xxx-sources.jar的源码jar,同时也能保证编译到apk包中。
(20131207)
libgdxメモ(日语)
http://doc.tir.ne.jp/devel/clan/libgdx
(20131208)
官方wiki
https://github.com/libgdx/libgdx/wiki
=================
(20130905)
六、JNI
1. image buffer控制
参考自:
https://vec.io/posts/how-to-render-image-buffer-in-android-ndk-native-code
1.1 Java Surface JNI
private Bitmap mBitmap; private ByteBuffer mByteBuffer; private ByteBuffer surfaceInit() { synchronized (this) { mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565); mByteBuffer = ByteBuffer.allocateDirect(w * h * 2); return mByteBuffer; } } private void surfaceRender() { synchronized (this) { try { Canvas c = mSurface.lockCanvas(null); mBitmap.copyPixelsFromBuffer(mByteBuffer); c.drawBitmap(mBitmap, 0, 0, null); mSurface.unlockCanvasAndPost(c); } catch (Exception e) { } } } private void surfaceRelease() { synchronized (this) { mBitmap.recycle(); mBitmap = null; mByteBuffer = null; } }
static jbyte* g_buffer; bool jni_surface_init(JNIEnv* env) { jobject buf = (*env)->CallObjectMethod(env, javaClass, javaSurfaceInit); if (buf == NULL) return false; g_buffer = (jbyte*)(*env)->GetDirectBufferAddress(env, buf); if (g_buffer == NULL) return false; return JNI_VERSION_1_6; } void jni_surface_release(JNIEnv* env) { (*env)->CallVoidMethod(env, javaClass, javaSurfaceRelease); g_buffer = NULL; } void jni_surface_render(JNIEnv* env, uint8_t* pixels, int w, int h) { if (g_buffer != NULL) { memcpy(g_buffer, pixels, w * h * 2); // RGB565 pixels (*env)->CallVoidMethod(env, javaClass, javaSurfaceRender); } }
1.2 OpenGL ES 2 Texture
1.3 NDK ANativeWindow API
ANativeWindow* window = ANativeWindow_fromSurface(env, javaSurface); ANativeWindow_Buffer buffer; if (ANativeWindow_lock(window, &buffer, NULL) == 0) { memcpy(buffer.bits, pixels, w * h * 2); ANativeWindow_unlockAndPost(window); } ANativeWindow_release(window);
1.4 Private C++ API
#ifdef FROYO #include "surfaceflinger/Surface.h" #else #include "ui/Surface.h" #endif using namespace android; jclass surfaceClass = env->FindClass("android/view/Surface"); if (surfaceClass == NULL) return; jfield fid = env->GetFieldID(surfaceClass, "mSurface", "I"); if (fid == NULL) return; sp<Surface> surface = (Surface*)env->GetIntField(javaSurface, fid); Surface::SurfaceInfo info; if (surface->lock(&info) == 0) { memcpy(info.bits, pixels, w * h * 2); surface->unlockAndPost(); }
The performance in this method is also the same as the ANativeWindow one.
(TODO)