출처: http://apecoder.net/2010/11/17/using-2d-opengl-on-android-part-2/
The earlier OpenGL on Android tutorial was about setting up the GLSurfaceView. Obviously this is important as what will you be drawing to if you don’t have a surface! So I recommend you read it before you continue. Remember I am only aiming to produce 2D!
draw_texture
In this tutorial we will render our first texture. You may be thinking “wait a minute, don’t you need to explain polygons, vertices and indices?”. Nope! Thankfully OpenGL has a useful function ‘draw_texture’ which to you and me (OpenGL ES) isglDrawTexfOES. This function will draw our texture straight to the surface. We need to make sure draw_texture is supported, to do this just add the following to your renderer class’ onSurfaceCreated function.
1 2 3 4 5 6 7 | ... // Test for device specific extensions String extensions = gl10.glGetString(GL10.GL_EXTENSIONS); // Test for draw texture boolean drawTexture = extensions.contains("draw_texture"); Log.i( "OpenGL Support - ver.:" + gl10.glGetString(GL10.GL_VERSION) + "renderer:" + gl10.glGetString(GL10.GL_RENDERER) + " : " + (drawTexture ? "good to go!" : "forget it!!" )); |
You should probably show an error dialog or something here, but for now we’ll just write to the log that there is a problem.
Setting up a texture
Ok so that worked fine, right? Now we can load our .png file and setup the texture. The following code needs to be added to the onSurfaceCreadted method of our Renderer. Looking at this code you can see that the first thing we do is get a texture name, which is essentially a number that OpenGL uses to index all the different textures. Now that we have a texture name, we switch to this texture with the function glBindTexture.
Whenever we need to swap to a different texture, this is the function we’ll need. There are two types of texture target (the first parameter to this funciton): GL_TEXTURE_2D and GL_TEXTURE_1D. 2D textures are your common image file, and 1D textures are a flat array of pixels. Maybe I’ll explain these in another tutorial. Or if you need to know now checkout the tutorials over at nehe.gamedev.net for info on this.
The crop array basically defines a square, which we can ignore for now (this will be explained in a future tutorial). I have put this in the setup code to simplify the example. Now for what is usually the most tricky bit! Luckily for us the nice Android developers have given us a handy OpenGL utility function that takes our bitmap stream and sets up the internal 2D texture. Thanks guys.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ... mTextureName = new int [ 1 ]; // Generate Texture ID gl10.glGenTextures( 1 , mTextureName, 0 ); // Did generate work? assert gl10.glGetError() == GL10.GL_NO_ERROR; // Bind texture id texturing target (we want 2D of course) gl10.glBindTexture(GL10.GL_TEXTURE_2D, mTextureName[ 0 ]); // Open and input stream and read the image. InputStream is = mContext.getResources().openRawResource(R.drawable.asteroid); Bitmap bitmap; try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } // Build our crop texture to be the size of the bitmap (ie full texture) mCrop = new int [ 4 ]; mCrop[ 0 ] = 0 ; mCrop[ 1 ] = imageHeight = bitmap.getHeight(); mCrop[ 2 ] = imageWidth = bitmap.getWidth(); mCrop[ 3 ] = -bitmap.getHeight(); // Magic Android function that setups up the internal formatting // of the bitmap for OpenGL ES GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , bitmap, 0 ); // Did texImage work? assert gl10.glGetError() == GL10.GL_NO_ERROR; bitmap.recycle(); |
Draw the texture
Ok, now the fun part, drawing our texture. The following needs to be added to our onDrawFrame function. I’m not going to explain the functions below, this is where you need to experiment and find out what this does. Enjoy!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ... // Begin drawing //-------------- // These function calls can be experimented with for various effects such // as transparency although certain functionality maybe device specific. gl.glShadeModel(GL10.GL_FLAT); gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); gl.glColor4x( 0x10000 , 0x10000 , 0x10000 , 0x10000 ); // Setup correct projection matrix gl.glMatrixMode(GL10.GL_PROJECTION); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glOrthof( 0 .0f, mWidth, 0 .0f, mHeight, 0 .0f, 1 .0f); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glPushMatrix(); gl.glLoadIdentity(); gl.glEnable(GL10.GL_TEXTURE_2D); // Draw Textures //---------------- gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureName[ 0 ]); ((GL11)gl).glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, mCrop, 0 ); ((GL11Ext)gl).glDrawTexfOES( 0 , 0 , 0 , imageWidth, imageHeight); // Draw the texture a few more times ((GL11Ext)gl).glDrawTexfOES( 100 , 100 , 0 , imageWidth, imageHeight); ((GL11Ext)gl).glDrawTexfOES( 250 , 200 , 0 , imageWidth, imageHeight); // Finish drawing (reset projection matrix) //------------------ gl.glDisable(GL10.GL_BLEND); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glPopMatrix(); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glPopMatrix(); |
The next OpenGL tutorial will be about using buffers for extra speedy drawing!
Download source
/////////////////////////////////////////////////////////////////////////////////////
그럴 때는 당연히 x, y, z 좌표중 z 좌표를 0으로 세팅하고 사용을 하겠죠.
하지만, 좌표만 바꾼다고 단말기 스크린(Screen)의 픽셀 좌표 1개가 OpenGL 상의 원하는 좌표가
되지 않을 경우가 많습니다.
이 때는 ViewPort를 적절하게 잘 조절을 해줘야 합니다.
그러기 위해서는 다음과 같이 세팅하면 됩니다.
gl.glOrthof(0, 480, 0, 800, 1, -1);
이 때 값들은 480x800 해상도를 가진 단말기 기준입니다.
그런데, 이 경우는 y좌표가 단말기 위쪽으로 갈수록 커지고 단말기 아래쪽이 0이 됩니다.
우리가 흔히 사용하는 GUI 좌표에서는 y좌표가 위쪽이 0이고, 아래로 갈수록 커지죠.
즉, 이 때는 이렇게 할 수 있습니다.
gl.glOrthof(0, 480, 800, 0, 1, -1);
자, 그러면 이 픽셀 좌표에 맞게 삼각형을 그리는 전체 소스를 한 번 보겠습니다.
SnowOpenGLESActivity.java
01.
package
snowdeer.opengles.test;
02.
03.
import
android.app.Activity;
04.
import
android.opengl.GLSurfaceView;
05.
import
android.os.Bundle;
06.
import
android.view.Window;
07.
import
android.view.WindowManager;
08.
09.
public
class
SnowOpenGLESActivity
extends
Activity
10.
{
11.
private
GLSurfaceView m_gsView =
null
;
12.
13.
@Override
14.
public
void
onCreate(Bundle savedInstanceState)
15.
{
16.
super
.onCreate(savedInstanceState);
17.
requestWindowFeature(Window.FEATURE_NO_TITLE);
18.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
19.
20.
m_gsView =
new
GLSurfaceView(
this
);
21.
m_gsView.setRenderer(
new
SnowRenderer());
22.
setContentView(m_gsView);
23.
24.
}
25.
26.
@Override
27.
protected
void
onPause()
28.
{
29.
super
.onPause();
30.
m_gsView.onPause();
31.
}
32.
33.
@Override
34.
protected
void
onResume()
35.
{
36.
super
.onResume();
37.
m_gsView.onResume();
38.
}
39.
}
SnowRenderer.java
01.
package
snowdeer.opengles.test;
02.
03.
import
javax.microedition.khronos.egl.EGLConfig;
04.
import
javax.microedition.khronos.opengles.GL10;
05.
06.
import
android.opengl.GLSurfaceView.Renderer;
07.
08.
public
class
SnowRenderer
implements
Renderer
09.
{
10.
private
SnowTriangle m_SnowTriangle =
null
;
11.
12.
public
SnowRenderer()
13.
{
14.
m_SnowTriangle =
new
SnowTriangle();
15.
}
16.
17.
public
void
onDrawFrame(GL10 gl)
18.
{
19.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
20.
gl.glLoadIdentity();
// Matrix 리셋
21.
22.
gl.glTranslatef(0.0f, 0.0f, 0.0f);
23.
24.
m_SnowTriangle.draw(gl);
25.
}
26.
27.
public
void
onSurfaceChanged(GL10 gl,
int
width,
int
height)
28.
{
29.
if
(height == 0)
30.
{
31.
height = 1;
// 0으로 나누는 것을 방지하기 위해서
32.
}
33.
34.
gl.glViewport(0, 0, width, height);
// ViewPort 리셋
35.
gl.glMatrixMode(GL10.GL_PROJECTION);
// MatrixMode를 Project Mode로
36.
gl.glLoadIdentity();
// Matrix 리셋
37.
38.
// 윈도우의 Aspect Ratio 설정
39.
gl.glOrthof(0, 480, 800, 0, 1, -1);
40.
41.
gl.glMatrixMode(GL10.GL_MODELVIEW);
// Matrix를 ModelView Mode로 변환
42.
gl.glLoadIdentity();
// Matrix 리셋
43.
}
44.
45.
public
void
onSurfaceCreated(GL10 gl, EGLConfig config)
46.
{
47.
gl.glShadeModel(GL10.GL_SMOOTH);
// Smooth Shading이 가능하도록 설정
48.
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// 하얀 바탕 그리기
49.
gl.glClearDepthf(1.0f);
// Depth Buffer 세팅
50.
gl.glEnable(GL10.GL_DEPTH_TEST);
// Depth Test 가능하도록 설정
51.
gl.glDepthFunc(GL10.GL_LEQUAL);
// The Type Of Depth Testing
52.
53.
// glHint 설정
54.
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
55.
}
56.
}
SnowTriangle.java
01.
package
snowdeer.opengles.test;
02.
03.
import
java.nio.ByteBuffer;
04.
import
java.nio.ByteOrder;
05.
import
java.nio.FloatBuffer;
06.
07.
import
javax.microedition.khronos.opengles.GL10;
08.
09.
public
class
SnowTriangle
10.
{
11.
private
FloatBuffer m_vertexBuffer;
12.
13.
// 삼각형 좌표 입력
14.
private
float
vertices[] = { 0.0f, 0.0f, 0.0f,
15.
240.0f, 800.0f, 0.0f,
16.
480.0f, 0.0f, 0.0f, };
17.
18.
public
SnowTriangle()
19.
{
20.
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
21.
byteBuf.order(ByteOrder.nativeOrder());
22.
m_vertexBuffer = byteBuf.asFloatBuffer();
23.
m_vertexBuffer.put(vertices);
24.
m_vertexBuffer.position(0);
25.
}
26.
27.
public
void
draw(GL10 gl)
28.
{
29.
gl.glFrontFace(GL10.GL_CW);
// 시계방향 그리기 설정
30.
// VertexPointer 설정
31.
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_vertexBuffer);
32.
// Vertex Array 사용 가능하도록 설정
33.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
34.
// 삼각형 Strip 그리기
35.
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
36.
// Vertex Array 사용 상태를 다시 불가능하도록 설정
37.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
38.
}
39.
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
출처: http://pros2.tistory.com/85