二维坐标系变换为原点在左上角(测试用)
* GLES
* JOGL
* LWJGL
* libgdx(使用g2d与pixmap)
package com.iteye.weimingtom.testgl; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.Window; import android.view.WindowManager; public class Testgl3Activity extends Activity implements GLSurfaceView.Renderer { private boolean USE_ORIGIN_TOPLEFT = true; private IntBuffer vertices; private int vertexBytes; private int vertexNum; private float[] arrVertices; private int[] tmpBuffer; private GLSurfaceView contentView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); contentView = new GLSurfaceView(this); contentView.setRenderer(this); setContentView(contentView); } @Override protected void onPause() { super.onPause(); contentView.onPause(); } @Override protected void onResume() { super.onResume(); contentView.onResume(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { loadData(); gl.glDisable(GL10.GL_DITHER); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glClearColor(1, 1, 1, 1); gl.glDisable(GL10.GL_CULL_FACE); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_DEPTH_TEST); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glViewport(0, 0, width, height); //gl.glViewport(0, height, width, height); if (USE_ORIGIN_TOPLEFT) { gl.glOrthof(0, width, -height, 0, 0, 1); } else { gl.glOrthof(0, width, 0, height, 0, 1); } updateData(width, height); } @Override public void onDrawFrame(GL10 gl) { gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); if (USE_ORIGIN_TOPLEFT) { gl.glScalef(1f, -1f, 1f); } gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); vertices.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, vertexBytes, vertices); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); vertices.position(3); gl.glColorPointer(4, GL10.GL_FLOAT, vertexBytes, vertices); gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, vertexNum); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); } private void loadData() { final float factor = 200f / 320f * 100; this.arrVertices = new float[] { 0f * factor, 0f * factor, 0, 0, 0, 1, 1, 1f * factor, 0f * factor, 0, 0, 0, 1, 1, 1f * factor, 1f * factor, 0, 0, 0, 1, 1, 0f * factor, 1f * factor, 0, 0, 0, 1, 1, }; this.vertexBytes = (3 + 4) * (Integer.SIZE / 8); this.vertexNum = arrVertices.length / (this.vertexBytes / (Integer.SIZE / 8)); this.tmpBuffer = new int[vertexNum * vertexBytes / (Integer.SIZE / 8)]; ByteBuffer buffer = ByteBuffer.allocateDirect(vertexNum * vertexBytes); buffer.order(ByteOrder.nativeOrder()); vertices = buffer.asIntBuffer(); this.vertices.clear(); for (int i = 0, j = 0; i < arrVertices.length; i++, j++) { tmpBuffer[j] = Float.floatToRawIntBits(arrVertices[i]); } this.vertices.put(tmpBuffer, 0, tmpBuffer.length); this.vertices.flip(); } private void updateData(int width, int height) { arrVertices[0] = 100f; arrVertices[1] = 100f; arrVertices[0 + 7] = width - 10; arrVertices[1 + 7] = 0; arrVertices[0 + 14] = width - 10; arrVertices[1 + 14] = height - 10; arrVertices[0 + 21] = 0; arrVertices[1 + 21] = height - 10; this.vertices.clear(); for (int i = 0, j = 0; i < arrVertices.length; i++, j++) { tmpBuffer[j] = Float.floatToRawIntBits(arrVertices[i]); } this.vertices.put(tmpBuffer, 0, tmpBuffer.length); this.vertices.flip(); } }
JOGL:
import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import javax.media.opengl.GL2ES1; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import javax.media.opengl.awt.GLCanvas; import com.jogamp.opengl.util.FPSAnimator; /** * gluegen-rt-natives-windows-i586.jar * gluegen-rt.jar * gluegen.jar * jogl-all-natives-windows-i586.jar * jogl.all.jar * * @see sites.google.com/site/justinscsstuff/jogl-tutorial-3 * @author Administrator * */ public class TestGLES1 implements GLEventListener { private boolean USE_ORIGIN_TOPLEFT = true; private IntBuffer vertices; private int vertexBytes; private int vertexNum; private float[] arrVertices; private int[] tmpBuffer; @Override public void init(GLAutoDrawable drawable) { GL2ES1 gl = drawable.getGL().getGL2ES1(); loadData(); gl.glDisable(GL2ES1.GL_DITHER); gl.glHint(GL2ES1.GL_PERSPECTIVE_CORRECTION_HINT, GL2ES1.GL_FASTEST); gl.glClearColor(1, 1, 1, 1); gl.glDisable(GL2ES1.GL_CULL_FACE); gl.glShadeModel(GL2ES1.GL_SMOOTH); gl.glEnable(GL2ES1.GL_DEPTH_TEST); } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) { GL2ES1 gl = drawable.getGL().getGL2ES1(); gl.glMatrixMode(GL2ES1.GL_PROJECTION); gl.glLoadIdentity(); gl.glViewport(0, 0, w, h); //gl.glViewport(0, height, width, height); if (USE_ORIGIN_TOPLEFT) { gl.glOrthof(0, w, -h, 0, 0, 1); } else { gl.glOrthof(0, w, 0, h, 0, 1); } updateData(w, h); } @Override public void display(GLAutoDrawable drawable) { GL2ES1 gl = drawable.getGL().getGL2ES1(); gl.glClear(GL2ES1.GL_COLOR_BUFFER_BIT | GL2ES1.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL2ES1.GL_MODELVIEW); gl.glLoadIdentity(); if (USE_ORIGIN_TOPLEFT) { gl.glScalef(1f, -1f, 1f); } gl.glEnableClientState(GL2ES1.GL_VERTEX_ARRAY); vertices.position(0); gl.glVertexPointer(3, GL2ES1.GL_FLOAT, vertexBytes, vertices); gl.glEnableClientState(GL2ES1.GL_COLOR_ARRAY); vertices.position(3); gl.glColorPointer(4, GL2ES1.GL_FLOAT, vertexBytes, vertices); gl.glDrawArrays(GL2ES1.GL_TRIANGLE_FAN, 0, vertexNum); gl.glDisableClientState(GL2ES1.GL_COLOR_ARRAY); gl.glDisableClientState(GL2ES1.GL_VERTEX_ARRAY); } @Override public void dispose(GLAutoDrawable drawable) { } private void loadData() { final float factor = 200f / 320f * 100; this.arrVertices = new float[] { 0f * factor, 0f * factor, 0, 0, 0, 1, 1, 1f * factor, 0f * factor, 0, 0, 0, 1, 1, 1f * factor, 1f * factor, 0, 0, 0, 1, 1, 0f * factor, 1f * factor, 0, 0, 0, 1, 1, }; this.vertexBytes = (3 + 4) * (Integer.SIZE / 8); this.vertexNum = arrVertices.length / (this.vertexBytes / (Integer.SIZE / 8)); this.tmpBuffer = new int[vertexNum * vertexBytes / (Integer.SIZE / 8)]; ByteBuffer buffer = ByteBuffer.allocateDirect(vertexNum * vertexBytes); buffer.order(ByteOrder.nativeOrder()); vertices = buffer.asIntBuffer(); this.vertices.clear(); for (int i = 0, j = 0; i < arrVertices.length; i++, j++) { tmpBuffer[j] = Float.floatToRawIntBits(arrVertices[i]); } this.vertices.put(tmpBuffer, 0, tmpBuffer.length); this.vertices.flip(); } private void updateData(int width, int height) { arrVertices[0] = 100f; arrVertices[1] = 100f; arrVertices[0 + 7] = width - 10; arrVertices[1 + 7] = 0; arrVertices[0 + 14] = width - 10; arrVertices[1 + 14] = height - 10; arrVertices[0 + 21] = 0; arrVertices[1 + 21] = height - 10; this.vertices.clear(); for (int i = 0, j = 0; i < arrVertices.length; i++, j++) { tmpBuffer[j] = Float.floatToRawIntBits(arrVertices[i]); } this.vertices.put(tmpBuffer, 0, tmpBuffer.length); this.vertices.flip(); } public static void main(String[] args) { GLProfile glp = GLProfile.getDefault(); GLCapabilities caps = new GLCapabilities(glp); GLCanvas canvas = new GLCanvas(caps); Frame frame = new Frame("AWT Window Test"); frame.setSize(240, 320); frame.setResizable(false); frame.setLocationRelativeTo(null); frame.add(canvas); frame.setVisible(true); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); canvas.addGLEventListener(new TestGLES1()); FPSAnimator animator = new FPSAnimator(canvas, 60); animator.add(canvas); animator.start(); } }
LWJGL:
import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.GL11; /** * lwjgl.jar : native library location -> testlwjgl/native/windows * * @see http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_1_(The_Display) * @see http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_3_(The_Quad) * @author Administrator * */ public class Testlwjgl1 { private boolean USE_ORIGIN_TOPLEFT = true; private final static int SCREEN_WIDTH = 240; private final static int SCREEN_HEIGHT = 320; public void start() { try { Display.setDisplayMode(new DisplayMode( SCREEN_WIDTH, SCREEN_HEIGHT)); Display.create(); } catch (LWJGLException e) { e.printStackTrace(); System.exit(0); } init(); while (!Display.isCloseRequested()) { render(); Display.update(); } Display.destroy(); } private void init() { GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); if (USE_ORIGIN_TOPLEFT) { GL11.glOrtho(0, SCREEN_WIDTH, -SCREEN_HEIGHT, 0, 1, -1); } else { GL11.glOrtho(0, SCREEN_WIDTH, 0, SCREEN_HEIGHT, 1, -1); } } private void render() { GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glLoadIdentity(); if (USE_ORIGIN_TOPLEFT) { GL11.glScalef(1f, -1f, 1f); } GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); GL11.glClearColor(1, 1, 1, 1); GL11.glColor3f(0.0f, 0.0f, 1.0f); GL11.glBegin(GL11.GL_TRIANGLE_FAN); { GL11.glVertex2f(100, 100); GL11.glVertex2f(SCREEN_WIDTH - 10, 0); GL11.glVertex2f(SCREEN_WIDTH - 10, SCREEN_HEIGHT - 10); GL11.glVertex2f(0, SCREEN_HEIGHT - 10); } GL11.glEnd(); } public static void main(String[] args) { new Testlwjgl1().start(); } }
libgdx (使用g2d与pixmap,而非使用GLES绘画)
package com.iteye.weimingtom.libgdxtest; import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.FPSLogger; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; public class Test001Screen implements Screen { private final static boolean DIRECTION_DOWN = true; private final static int BOX_W = 50; private final static int BOX_H = 50; private int LOG_LEVEL = Application.LOG_DEBUG; private final static String TAG = "Test001Screen"; private FPSLogger logger; private SpriteBatch sb; private Pixmap pixmap; private Texture texture; private TextureRegion textureRegion; private Vector2 pos; private Vector2 dir; public Test001Screen() { Gdx.app.setLogLevel(LOG_LEVEL); logger = new FPSLogger(); init(); } private void init() { log("init"); sb = new SpriteBatch(); int w = Gdx.graphics.getWidth(); int h = Gdx.graphics.getHeight(); pixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888); final int potW = MathUtils.nextPowerOfTwo(w); final int potH = MathUtils.nextPowerOfTwo(h); texture = new Texture(potW, potH, Pixmap.Format.RGBA8888); if (DIRECTION_DOWN) { textureRegion = new TextureRegion(texture, 0, 0, w, h); } else { textureRegion = new TextureRegion(texture, 0, h, w, -h); } pos = new Vector2(w / 2, h / 2); dir = new Vector2(1, 1); } @Override public void dispose() { log("dispose"); texture.dispose(); pixmap.dispose(); sb.dispose(); } @Override public void render(float delta) { onUpdate(delta); GL10 gl = Gdx.gl10; gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glClearColor(0, 0, 0, 0); //gl.glClearColor(1, 1, 1, 1); onRender(); sb.begin(); texture.draw(pixmap, 0, 0); sb.draw(textureRegion, 0, 0); sb.end(); logger.log(); } @Override public void resize(int width, int height) { sb.getProjectionMatrix().setToOrtho2D(0, 0, width, height); } @Override public void show() { } @Override public void hide() { } @Override public void pause() { } @Override public void resume() { } private void onUpdate(float delta) { int w = pixmap.getWidth(); int h = pixmap.getHeight(); pos.x += dir.x * delta * 60; pos.y += dir.y * delta * 60; if (pos.x < 0) { dir.x = -dir.x; pos.x = 0; } if (pos.x > w) { dir.x = -dir.x; pos.x = w; } if (pos.y < 0) { dir.y = -dir.y; pos.y = 0; } if (pos.y > h) { dir.y = -dir.y; pos.y = h; } } private void onRender() { pixmap.setColor(0, 0, 0, 0); pixmap.fill(); pixmap.setColor(Color.BLUE); pixmap.fillRectangle( (int)pos.x - BOX_W / 2, (int)pos.y - BOX_H / 2, BOX_W, BOX_H); } private void log(String message) { Gdx.app.log(TAG, message); } }
X. 参考资料:
1. Beginning Android 4 Games Development
随书代码Source Code/Downloads
http://www.apress.com/9781430239871
(TODO)