我用C编程了我的游戏.我已经设法使用ndk编译所有内容,但我注意到了一些障碍.
如何将纹理加载到NDK OpenGL中(因为代码已经存在)?我确实使用了BitmapFactory来加载图像,然后将像素复制到ByteBuffer中,我以宽度*高度* 4的大小分配.然后我将ByteBuffer的数组发送到我的本机代码并使用Get /拉出指针ReleasePrimiativeArrayCritical.我认为它不起作用,因为它渲染时崩溃.另外,我不禁注意到,当图像只有16 KB时,垃圾编译器正在呻吟着大约5.37 MB的空间.
另一件事是缓冲区,比如framebuffers和renderbuffers.我注意到它没有使用framebuffers和renderbuffers. GLSurfaceView是否以此方式执行此操作?是否可以使用我自己的缓冲区?
最佳答案 好吧,我已经弄清楚了.事实证明,BitmapFactory将我的图像缩放到2大小的非幂,所以它不起作用. GLSurfaceView支持OpenGL ES 1.0的处理方式,你只需在屏幕上绘图.我可以使用framebuffers,但是我必须将它们链接到纹理然后将纹理绘制到屏幕上.我使用这个
example并将其移植到本机,不包括深度缓冲区.
这是代码:
Java的:
public class NativeRenderer implements Renderer {
static {
System.loadLibrary("Test");
}
private static native void init();
private static native void setTexture(byte[] data, int width, int height);
private static native void resize(int width, int height);
private static native void render();
private Context mContext;
public NativeRenderer(Context context)
{
mContext = context;
}
public void onDrawFrame(GL10 gl) {
render();
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
resize(width, height);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
init();
ByteBuffer data;
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888; //ARGB_888 is the default
opts.inDensity = 240; // this needed so my images are 512x512 (power of 2)
opts.inScaled = false; // someone suggested to add this
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.image, opts);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
data = ByteBuffer.allocate(width * height * 4);
Log.i(TAG, "allocate:" + (width * height * 4));
data.order(ByteOrder.nativeOrder());
bitmap.copyPixelsToBuffer(data);
data.position(0);
bitmap.recycle();
Log.i(TAG, "data.hasArray():" + data.hasArray());
setTexture(data.array(), width, height);
}
}
C :
#include "your_company_NativeRenderer.h"
#include <android/log.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <string.h>
#include "Functions.h"
static GLuint texture[2];
static GLuint framebuffer;
static GLuint renderbuffer;
static GLuint texturebuffer;
static int textureWidth;
static int textureHeight;
static int sWidth;
static int sHeight;
static float hheight;
void viewportFramebuffer()
{
glViewport(0, 0, textureWidth, textureHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
static float viewportFramebufferRight = 160.0f + (320.0 / (float)sWidth) * (textureWidth - sWidth);
static float viewportFramebufferTop = hheight + ((2 * hheight) / (float)sHeight) * (textureHeight - sHeight);
glOrthof(-160.0f, viewportFramebufferRight, -hheight, viewportFramebufferTop, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void viewportSurface()
{
glViewport(0, 0, sWidth, sHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-160.0f, 160.0f, -hheight, hheight, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
JNIEXPORT void JNICALL Java_your_company_NativeRenderer_init
(JNIEnv *env, jclass obj)
{
__android_log_print(ANDROID_LOG_INFO, TAG, "init()");
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glEnable(GL_TEXTURE_2D);
//glEnable(GL_BLEND);
glGenTextures(2, texture);
texturebuffer = texture[0];
}
JNIEXPORT void JNICALL Java_your_company_NativeRenderer_setTexture
(JNIEnv *env, jclass obj, jbyteArray array, jint width, jint height)
{
__android_log_print(ANDROID_LOG_INFO, TAG, "setTexture()");
void *image = env->GetPrimitiveArrayCritical(array, 0);
unsigned int *imageData = static_cast<unsigned int *>(image);
flipImageVertically(imageData, width, height); // flips the bytes vertically
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
env->ReleasePrimitiveArrayCritical(array, image, 0);
}
JNIEXPORT void JNICALL Java_your_company_NativeRenderer_resize
(JNIEnv *env, jclass obj, jint width, jint height)
{
__android_log_print(ANDROID_LOG_INFO, TAG, "resize(width:%d, height:%d)", width, height);
sWidth = width;
sHeight = height;
hheight = 240.0f + additionToScalePlane(width, height); // used to adjust the spect ratio
// iPhone is 2 : 3, my Galaxy S is 5 : 3
__android_log_print(ANDROID_LOG_INFO, TAG, "hheight:%g", hheight);
textureWidth = powerOf2Bigger(width);
textureHeight = powerOf2Bigger(height);
__android_log_print(ANDROID_LOG_INFO, TAG, "texture:{w:%d, h:%d}", textureWidth, textureHeight);
glBindTexture(GL_TEXTURE_2D, texturebuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glColor4ub(0, 0, 0, 255);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
int area[] = {0.0, 0.0, sWidth, sHeight}; // using draw_texture extension
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, area);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texturebuffer, 0);
int status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if(status != GL_FRAMEBUFFER_COMPLETE_OES)
__android_log_print(ANDROID_LOG_ERROR, TAG, "Framebuffer is not complete: %x", status);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
}
JNIEXPORT void JNICALL Java_your_company_NativeRenderer_render
(JNIEnv *env, jclass obj)
{
static float texCoord[] = {
0.0, 0.0,
0.0, 480.0/512.0,
320.0/512.0, 0.0,
320.0/512.0, 480.0/512.0,
};
static float vertex[] = {
-160.0, -240.0,
-160.0, 240.0,
160.0, -240.0,
160.0, 240.0,
};
//off-screen
viewportFramebuffer();
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glVertexPointer(2, GL_FLOAT, 0, vertex);
glTexCoordPointer(2, GL_FLOAT, 0, texCoord);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
//on-screen
viewportSurface();
glClearColor(0.0, 0.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
/*static float textureCoord[] = {
0.0, 0.0,
0.0, sHeight/(float)textureHeight,
sWidth/(float)textureWidth, 0.0,
sWidth/(float)textureWidth, sHeight/(float)textureHeight,
};
static float textureVertex[] = {
-160.0, -hheight,
-160.0, hheight,
160.0, -hheight,
160.0, hheight,
};*/ //if there isn't draw_texture extension
glBindTexture(GL_TEXTURE_2D, texturebuffer);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture(GL_TEXTURE0);
glDrawTexiOES(0, 0, 0, sWidth, sHeight);
//glVertexPointer(2, GL_FLOAT, 0, textureVertex);
//glTexCoordPointer(2, GL_FLOAT, 0, textureCoord);
//glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//glDisableClientState(GL_VERTEX_ARRAY);
//glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, 0);
}