본문 바로가기

구글과인터넷/안드로이드

안드로이드 openglES 2.0 효과, api 등등

출처: http://gogorchg.tistory.com/entry/Android-ColorMask-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

[ Android ] ColorMask 사용하기

 | 


글로우 효과를 내거나 이미지에 발광 효과를 줄려고 할 때
사용하면 괜찮을 것 같아서 이렇게 글을 남깁니다.

Opengl es 같은 경우 자체적으로 diffuse(범위) 빛 효과 값을 이용하여 
글로우 효과를 표현하기도 하는 것 같은데요..

만약 랜더링 되지 않은 그냥 bitmap 파일을 글로우 효과를 낼려면..
어쩔수 없이 bitmap 자체를 변경 시켜줘야 한다는 게
몇일 간 조사한 저의 결과 였습니다.

bitmap변경은 다음과 같이 이용하였습니다.

// bitmap 소스를 받아온다.

Bitmap tmpbitmap = 

BitmapFactory.decodeStream(mContext.getResources().openRawResource(R.raw.lightmap));

tmpbitmap = Bitmap.createScaledBitmap(tmpbitmap, 256, 256, true);


Paint paint = new Paint();

int textureIndex = 0;

// 50개의 텍스처를 초기화 했습니다. 

for(float contrast = 0.0f ; textureIndex < 50 ; contrast += 0.1f,textureIndex++){
      // 컬러 매트릭스 생성 

      ColorMatrix cm = new ColorMatrix();

        
        // 컬러 캐트릭스를 적용 시킨 비트맵을 그릴 팔레트Bitmap 

        Bitmap paletBmp = Bitmap.createBitmap(tmpbitmap.getWidth(), tmpbitmap.getHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(paletBmp);
 

        // contrast값이 높아 질수록 밝아진다. ( 글로우 효과일 경우 보이는 부분이 줄어드는 효과를 볼 수 있죠.)

      setContrastScaleOnly(cm, contrast);
 
      // 컬러 필터로 적용

        paint.setColorFilter(new ColorMatrixColorFilter(cm));

        canvas.save();

        canvas.drawBitmap(tmpbitmap, 0,0, paint);

        canvas.restore();

        

        mLightMapTexId[textureIndex] = loadTexture(paletBmp);

}

tmpbitmap.recycle();

tmpbitmap = null;

 

아마 글로우 효과를 내는데 제가 잘못 생각할 수도 있을 것 같네요..

혹시 다른 의견이나~~

괜찮은 생각 있으신 분~~~ 특히 Opengl es 2.0을 이용하는 방법이면

더욱 환영입니다.^^

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://gogorchg.tistory.com/entry/Android-Opengl-es-Blur%ED%9A%A8%EA%B3%BC

[ Android Opengl es ] Blur효과

 

아직 실험해보지는 않았다.

이것도 역시 Bitmap의 컬러값을 이용하여,변경하는 함수이다.

function BlurHorizontal (source, dest, radius) {
        for (y = 0; y < height; ++y) {
            for (x = 0; x < width; ++x) {
                total = 0
                for (kx = -radius; kx <= radius; ++kx)
                    total += source(x + kx, y)
                dest(x, y) = total / (radius * 2 + 1)
            }
        }
    }
    
    function BlurVertical (source, dest, radius) {
        for (x = 0; x < width; ++x) {
            for (y = 0; y < height; ++y) {
                total = 0
                for (ky = -radius; ky <= radius; ++ky)
                    total += source(x, y + ky)
                dest(x, y) = total / (radius * 2 + 1)
            }
        }
    }

    function Blur (source, dest, radius) {
        BlurHorizontal(source, temp, radius)
        BlurVertical(temp, dest, radius)
    }

 출처 : http://www.blackpawn.com/texts/blur/default.html


 중요한 건 , 모든 연산이 CPU에서 하기 때문에.
매번 블러를 적용시킬려고 하면, 속도가 현저하게 저하되는 것을 느낄 수 있을 것 같다.


먼가 Opengl es 내적으로 GPU를 이용하는 방법을 빨리 찾아야 할 것 같다.

어렵다 정말...^^;;; 


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://gogorchg.tistory.com/entry/Android-Opengl-es-20-Blur-%ED%9A%A8%EA%B3%BC

드뎌!!!! Blur효과를 냈습니다. 
아마 이런 것 가지고 하시는 분들 계시겠지만, 저한테는 너무 기분 좋은 일이네요.^^

이 효과를 내고 싶어도... 낼 수가 없었던  지금까지의 고생이 오늘 해결 되었네요.

Opengl es 2.0으로 했구요. 
FrameShader 소스 부분의 컬러 값을 변경하면 됩니다.

 

String fShaderStr =

            "precision mediump float;                            \n" +

            "varying vec2 v_texCoord;                            \n" +         // 이건 texture index 배열이죠. DrawElement에서 사용

            "uniform sampler2D s_lightMap;                       \n" +     //  이미지 텍스쳐 입니다.

            "uniform float u_blurAmount;                       \n" +          // Blur을 먹이기 위해 Object간의 간격을 조절

            "uniform int u_blurFlag;                       \n" +                 // 테스트를 위해 Blur 먹인 것과 아닌 것을 구분하는 Flag

            "void main()                                         \n" +

            "{                                                   \n" +

            "                                                   \n" +

            "  vec4 lightColor;                                  \n" +

            "                                                    \n" +

"   highp vec4 color = vec4(0,0,0,1); \n" +              // 색깔을 받을 변수

// Blur를 가우스 공식에 의해 변경을 시켜주는 거지요. 

            "  if ( u_blurFlag == "+ENABLE_BLUR+"){  \n " +

            "       highp vec2 gaussFilter[7];   \n" +

            "       gaussFilter[0] = vec2(-3.0, 0.015625); \n" +

            "       gaussFilter[1] = vec2(-2.0, 0.09375); \n" +

            "       gaussFilter[2] = vec2(-1.0, 0.234375); \n" +

            "       gaussFilter[3] = vec2(0.0, 0.3125); \n" +

            "       gaussFilter[4] = vec2(1.0, 0.234375); \n" +

            "       gaussFilter[5] = vec2(2.0, 0.09375); \n" +

            "      gaussFilter[6] = vec2(3.0, 0.015625); \n" +

            "                                                   \n" +

            "       highp float blurSize = u_blurAmount * 1.0; \n" +

            "                                                   \n" +

            "    for( int i = 0; i < 7; i++ ) \n" +

            "         color += texture2D( s_lightMap, vec2( v_texCoord.x+gaussFilter[i].x*blurSize, v_texCoord.y+gaussFilter[i].x*blurSize ) )*gaussFilter[i].y; \n" +

            "  }else{   \n " +

            "   color = texture2D( s_lightMap, v_texCoord );  \n" +

            "   }  \n" +

            "  gl_FragColor = color ;   \n" +

            "}                                                    \n";


결과 화면:












위 쪽은 기본 이미지.
밑 쪽은 Blur 값을 넣은 이미지 입니다.

blurAmount를 0.01f로 줬을 때 나오는 결과구요.

더 주게 되면 Blur Object가 더욱 벌어져서 이상하게 보여버립니다.






이렇게요^^

왠지 오늘 너무 행복한 하루 네요~~^^

더 궁금한 거 있으시면 댓글 달아주세요 ㅎ

모두 추운 날씨 몸 조심하시고
즐코딩하세요~ ㅎ

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://gogorchg.tistory.com/entry/Android-Opengl-es-20-glDrawArrays-%EC%99%80-glDrawElements-%EC%82%AC%EC%9A%A9%EB%B2%95

[ Android Opengl es 2.0 ] glDrawArrays 와 glDrawElements 사용법

 

여러 소스를 보다 보면,
glDrawArrays를 사용하거나, glDrawElements를 사용하기도 합니다.

그래서, 저 같은 경우는 이해하기 쉬운 glDrawArrays를 많이 사용했는데요.

// Vertex 배열을 만듬.
private final float[] mVerticesData =

    { 

     0.0f, 0.0f, 0.0f, 

     -0.5f, 0.5f, 0.0f, 

     0.5f, 0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     1.0f, 0.0f, 0.0f, 

     0.5f, 0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     0.5f, -0.5f, 0.0f, 

     1.0f, 0.0f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     -0.5f, -0.5f, 0.0f, 

     0.5f, -0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f, 

     -1.0f, 0.0f, 0.0f, 

     -0.5f, -0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f, 

     -1.0f, 0.0f, 0.0f, 

     -0.5f, 0.5f, 0.0f,

    

 };



// Vertex Buffer에 포인터를 설정한다.

GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
// Vertex 속성을 허용한다. 

GLES20.glEnableVertexAttribArray(0);


// Vertex의 포인터 갯수 만큼만 그린다. ( 0부터 18 )

GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVerticesData.length/3); 



이렇게 Vertex만 잡아주면 쉽게 그릴 수 있는게 glDrawArrays이구요.

만약, 한 구역 내에서 여러 모양의 형태로 그리고 싶을 경우가 있을 때 , glDrawElements를 사용하는데요.
이 때 필요한 것이 Indices 배열입니다.

// Vertex 배열을 만듬.
private final float[] mVerticesData =

    { 

     0.0f, 0.0f, 0.0f,  // Vertex 0

     -0.5f, 0.5f, 0.0f,// Vertex 1 

     0.5f, 0.5f, 0.0f, // Vertex 2

     1.0f, 0.0f, 0.0f, // Vertex 3

     0.5f, -0.5f, 0.0f,// Vertex 4

     -0.5f, -0.5f, 0.0f,// Vertex 5

     -1.0f, 0.0f, 0.0f,// Vertex 6

     };

// Indice 배열을 만듬. 

    private final short[] mIndicesData = {

     0,2,1, // 삼각형 1

     0,3,2,// 삼각형 2

     0,4,3,// 삼각형 3

         0,5,4,// 삼각형 4

         0,6,5,// 삼각형 5

         0,1,6,// 삼각형 6

    };


// Vertex Buffer에 포인터를 설정한다.

GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
// Vertex 속성을 허용한다. 

GLES20.glEnableVertexAttribArray(0);


// Indices 갯수만큼 설정.

GLES20.glDrawElements(GLES20.GL_TRIANGLE_FAN, mIndicesData.length, GLES20.GL_UNSIGNED_SHORT, mIndices); 

 
 

.





Vertex의 위치 를 보여드린 그림입니다.
 
각각 안에 삼각형이 6개가 그려지죠.
3각형을 그릴 포인트를 Indices 배열에 지정한 것입니다.

이 그림의 주소따라 
mIndicesData 안에 값들 대로 그려보십시요.

아~~~ 하실 껍니다.^^ 

참고> 
glDrawElements를 할 경우, 여러 Object를 연결 시키고자 할때,
Vertex는 많아도 indices로 연결을 시켜주면 되니 사용하기 편하다고 하네요..^^
 


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


출처: http://gogorchg.tistory.com/entry/Android-Opengl-es-20-VBOVertexArray-Buffer-Object-%EA%B4%80%EB%A0%A8%ED%95%B4%EC%84%9C


[Android Opengl es 2.0 ] VBO(VertexArray Buffer Object ) 관련해서



이번에 이해하게된 함수는

glGenBuffers, glBindBuffer,glBufferData 이 세 함수입니다.

이 함수에는 다음과 같은 코드로 Vertex 배열을 Opengl Buffer에 저장을 시켜서
Handle Number를 이용하여 사용을 하는데요.

// Buffer 생성 공간을 2군데 만든다.
GLES20.glGenBuffers(2, vObjId);


// Buffer 공간에서 첫번째와 연결
       

GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vObjId.get(0));
// 연결된 첫번째 공간에 Static형태로 Vertex데이터를 저장 한다. 

GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mVerticesData.length * 4, mVertices, GLES20.GL_STATIC_DRAW);
// 한 번 읽을 때마다 , float 4바이트를 3개씩 읽게 된다. ( ex> 0.0f,0.0f,0.0f ) 

GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices);
// 속성 적용을 허용한다. 

GLES20.glEnableVertexAttribArray(0);

 

전 코드를 만들면서 생각에 큰 오류가 있었습니다.

바로 위  glGenBuffers라는 함수는 
여러 Object에 대한 형태를 지정해 놓으면,
Handle Number를 통하여 Object 모양을 바꿀 수 있을 줄 알았습니다.


하지만!!!!!
glGenBuffers는 한 Object에 대한 여러 Attribute을 지정하는 것이었습니다.


즉, 한 Object에 한해서 밖에 생성이 안된다는 이야기입니다.

구글링을 해본 결과 얻은 결론은 Opengl es 버전이 아닌,
또는 안드로이드가 아니고 iOS내에 Opengl es 버전에는

 glGenVertexArrays       ( Opengl )
 glGenVertexArraysOES ( iOS Opengl )

위 함수를 통하여 여러 Object를 Buffer에 지정할 수가 있는 것 같습니다.

우선, 제가 테스트해 본 결과로는 안드로이드에서 Buffer 여러 Object를 지정해 놓는 것은
힘들어 보이네요...

혹시 이 의견에 반발이 있으신 분은 주저 말고 댓글 달아주세요!!!

이게 100% 맞다고 할 수 없지 않습니까??^^ 


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://gogorchg.tistory.com/entry/Android-Opengl-es-20-Vertex%EB%B0%B0%EC%97%B4%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EA%B0%84%EB%8B%A8%ED%95%9C-%EB%8F%84%ED%98%95-%EB%A7%8C%EB%93%A4%EA%B8%B0


[ Android Opengl es 2.0 ] Vertex배열을 이용하여 간단한 도형 만들기

 


안녕하세요.

이번엔 Vertex배열을 이용하여 제가 그린 그림을 보여드릴려고 합니다.

private final float[] mVerticesData =

    { 

     0.0f, 0.0f, 0.0f, 

     -0.5f, 0.5f, 0.0f, 

     0.5f, 0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     1.0f, 0.0f, 0.0f, 

     0.5f, 0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     0.5f, -0.5f, 0.0f, 

     1.0f, 0.0f, 0.0f,

    

     0.0f, 0.0f, 0.0f,

     -0.5f, -0.5f, 0.0f, 

     0.5f, -0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f, 

     -1.0f, 0.0f, 0.0f, 

     -0.5f, -0.5f, 0.0f,

    

     0.0f, 0.0f, 0.0f, 

     -1.0f, 0.0f, 0.0f, 

     -0.5f, 0.5f, 0.0f,

    

     };

 위와 같이 하게 되면 정육각형이 구해집니다.

먼저 결과 화면을 보여드리겠습니다.













Vertex로직은 다음과 같습니다.






 

public void onTouchEvent(MotionEvent event){

     switch(event.getAction()){

     case MotionEvent.ACTION_UP:

     if(drawType == GLES20.GL_TRIANGLES){

     drawType = GLES20.GL_LINE_LOOP;

     }else{

     drawType = GLES20.GL_TRIANGLES;

     }

     break;

     }

    } 


그릴 때 마다 drawType을 변형 시켜서, Touch를 할 경우에
선일 경우에는 꽉 채우는 형태로,
꽉 채워져 있으면 선으로 그려보았습니다.

중요한 부분이 vertex의 순서를 잘못 하면 다음과 같은 결과가 날 수 있다는 것이지요.







GL_LINE_LOOP일 경우는 저희가 예전 놀이로 많이 했던,
연필을 때지 않고 선 그리기 형태로 선을 계속 그린다고 
생각하시면 됩니다.


이렇게 Vertex를 공책이나 연습장에 생각해서 그려보신 후,
이제 VertexShader에 적용을 시켜야하는데요.

[ mVerticesBuffer가 사용되기 전에 적용]
mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)

                .order(ByteOrder.nativeOrder()).asFloatBuffer();

mVertices.put(mVerticesData).position(0);

[ Drawing 하는 함수에서]

// Vertex 값은 시작이 0이요, 3단위씩 끊어져 있소, 값은 Float형태요.
// Float일 경우 false로 하지만, 만약 다른 데이터 형식일 때 true로 하면 normalize가 된다고 책있네요.
// 3단위로 읽고, 0만큼 건너 뛰겠소. (나중에 Vertex배열에 여러가지를 겸해서 설정할 수도 있습니다.)
// mVertices라는 ByteBuffer를 가지고 그리시요. 

GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices); 

GLES20.glEnableVertexAttribArray(0);

// 배열형태를 그립니다.
// 총 배열의 Column 수는 18개 입니다.
// 3단위씩 18개로 되어있죠. 

GLES20.glDrawArrays(drawType, 0, 18);


이렇게 간단하게 육각형을 그리는 연습을 해보았습니다.
이제 먼가 움직여도 보고 이것 저것 해볼려고 합니다.

Opengl es 1.0은 해봤는데.

먼가 2.0에서는 개발자에게 대한 자유도가 더 올라간 듯한 느낌도 들고,
이해하기가 더 복잡해 진것 같기도 하고..

아무튼!!!
공부해서 이해가 될 때 마다 글을 남겨둘까 합니다.

이 글이 많은 사람들에게 도움이 되면 좋겠습니다.


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

출처: http://gogorchg.tistory.com/entry/Android-Opengl%EC%97%90%EC%84%9C-glDrawElements%ED%95%A8%EC%88%98%EB%A1%9C-%EA%B7%B8%EB%A6%B4-%EB%96%84-%EC%A3%BC%EC%9D%98%EC%A0%90


[ Android ] Opengl에서 glDrawElements함수로 그릴 떄 주의점

 

전 glDrawArray함수를 많이 사용하는데요.

폴라곤을 이용하여 텍스처를 입힐 때에는 glDrawElements함수를 사용하는 게 훨 편하고

속도면에서도 낫더라구요.

그런데 기존에 사용했던 glDrawArray함수와 glDrawElements함수를 사용할 때 

준비해야할 점들이 다릅니다. 

glDrawArray함수는 vertex 좌표만 있어도 표현이 가능하죠. ( 다른 Normal등 부수적인 것을 제외 )

하지만, glDrawElements함수에서는 vertex만큼 중요한 좌표가 두가지가 있죠.

바로!!! vertex포인터를 하게 될 좌표와 텍스처 포인터를 할 좌표!!

이 두가지를 확실하게 해주지 않으면 죽을 때까지 원하는 모양을 보실수 없으십니다.

먼저 , 텍스처 포인터를 할 때






 
위와 같이 두 포인터가 합쳐서 1을 표현해야만 합니다.

저 윗 그림을 배열로 표시하면

{

0.0 , 0.0

0.5 , 0.0

1.0 , 0.0

0.0 , 0.5

0.5 , 0.5

1.0 , 0.5

0.0 , 1.0

0.5 , 1.0

1.0 , 1.0


함수는 다음과 같습니다. 참고하세요.^^ : Java에서 테스트 한 거라 ㅎㅎ

private static void texturePoint(){

 int i = 0;

   float delta_x = 1.0f / (float)(3-1);

   float delta_y = 1.0f / (float)(3-1);

   for (int y = 0; y < 3; y++)

        for (int x = 0; x < 3; x++)

      {

         System.out.println((float)x * delta_x + " , " + (float)y * delta_y);

           i += 2;

       }

 } 



그 다음은 Vertex포인트 입니다.

똑같은 위 그림을 표현하면 배열이 다음과 같구요.

0 , 1 , 4 ,         0 , 3 , 4

1 , 2 , 5 ,         1 , 4 , 5

3 , 4 , 7,          3 , 6 , 7

4 , 5 , 8,          4 , 7 , 8 

소스는 다음과  같습니다.

 private static void vertexPoint(){

 int i=0;

    

     for(int y=0;y<(3-1);y++){

    

     for(int x=0;x< (3-1) ; x++){

    

     int n = (y*3)+x;

    

     System.out.println((byte)n + " , " + (byte)(n+1) + " , " + (byte)(n+1+3));

     System.out.println((byte)n + " , " + (byte)(n+1+3-1) + " , " + (byte)(n+1+3));

    

     i+=6;

    

     }

    

     }

 } 


 
저두 이걸로 조금 씩 텍스처의 개념이 이해가 되어 가고, DrawElements를 사용하는데 자신감이 생겼네요^^

어려움을 직면했을 때 포기말고 끝까지 해봅시다.!!!

도움이 되었으면 좋겠네요.. 화이팅!!

아!!! 지금 숫자 3은 가로 세로의 포인트 갯수가 각각 3개인 것입니다.^^