[ Java JOGL 프로그래밍 ] 텍스처 렌더링 - 2 - Whitmem
[ Java JOGL 프로그래밍 ] 텍스처 렌더링 - 2
Graphic Development
2024-08-18 01:53 게시 658634cb4cf0a422e2ff

0
0
382
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
GL 측에 Texture 을 넘기기 위해서는 이미지 바이트 배열 버퍼로 넘겨야 한다. 나는 자바에서 제공하는 기본 클래스인 ImageIO를 사용해서 이미지를 BufferedImage로 로드하고, byte[] 로 로드하였다.
BufferedImage img = ImageIO.read(is); byte[] obuffer = ((DataBufferByte) (img.getRaster().getDataBuffer())).getData(); for(int i=0;i<obuffer.length;i+=4) { //ARGB to RGBA byte tempA= obuffer; obuffer = obuffer[i+1]; obuffer[i+1] = obuffer[i+2]; obuffer[i+2] = obuffer[i+3]; obuffer[i+3] = tempA; }
내가 로드하는 건 png 파일이다.
기본적으로 윈도우 11 그림판에서 수정한 png 파일은 알파 채널이 존재하는 그림 이미지 파일이다. 그런데 바이트 배열 순서가 ARGB 순서이다. 즉 Alpha 값을 255 (1바이트)로 저장하고, R, G, B 를 각각 1바이트씩 저장한다. 이를 바이트 배열로 나타낸 obuffer 은 ARGB 순서로 되어있다. 그런데 GL의 텍스처는 RGBA 순서로 버퍼를 로드해야하기 때문에 순서를 역전 시켜줄 필요가 있다. 단순히 뒤집기만 하면 A,R,G,B 가 B,G,R,A 가 되어 빨,초,파 색상 채널이 뒤집힐 수 있으므로 반복문을 사용해서 부분적으로 교체해준다. 이렇게 할당된 버퍼는 ByteBuffer에 할당한다.
ByteBuffer buffer = ByteBuffer.allocate(obuffer.length); buffer.put(obuffer); buffer.position(0);
즉 byte[]로 로드한 이미지 데이터를 ARGB 채널에서 RGBA 채널로 변환을 한 뒤 ByteBuffer에 담아주었다. 이 ByteBuffer은 이제 GL 단의 버퍼로 넘겨줄 수 있다.
GL에서 텍스처 공간을 할당하기 위해서는 아이디를 발급받아야 하는데, 그 아이디는 IntBuffer로 발급받을 수 있다. int 는 4바이트 기준이므로, 4 공간을 할당하고 해당 공간에 발급받는다.
IntBuffer intbf = IntBuffer.allocate(4); gl.glGenTextures(1, intbf); int cha = intbf.get(); gl.glBindTexture(gl.GL_TEXTURE_2D,cha);
그러면 cha 라는 공간에 최종적으로 ID가 할당된다. 이 ID로 텍스처 바인딩을 해주고, 바인딩된 텍스처에 할당할 텍스처 정보와 버퍼를 기입한다.
gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGBA, img.getWidth(),img.getHeight(), 0, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE, buffer);
아까, ARGB 채널에서 RGBA 채널로 변환하엿으므로 GL2.GL_RGBA 로 변환한다. 한편, BufferedImage 로 로드한 이미지의 width와 height를 가져와 기입한다. 이미지의 width 정보와 height 정보는 명확해야한다. 이미지 버퍼 데이터를 1차원으로 펴놓은 상태이기 때문에, 이미지 너비 높이 정보가 확실해야 문제 없이 불러올 수 있다. 1이라도 차이나는 경우 이미지가 깨질 수 있다.
렌더링
이 텍스처 정보를 이제 Vertex를 출력할때 같이 TexCoord를 할당해서 출력할 수 있다. 기본적으로 쉐이더 없이 텍스처를 출력할 것이기 때문에 텍스처 좌표 맵핑 방법을 정의한다. GL_TEXTURE_WRAP_S는 수평방향의 작업 정책, GL_TEXTURE_WRAP_T는 수직 방향의 작업 정책을 의미하고, GL_TEXTURE_MIN_FILTER은 축소시 정책, GL_TEXTURE_MAG_FILTER은 확대시 정책을 나타내는데, 벗어난 텍스처 좌표는 반복되도록 하기 위해서 GL_REPEAT로 지정하고, 축, 확대시 부드러운 표시를 위해 선형 보간 모드인 GL_LINEAR로 지정하였다.
gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR); gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
그리고 Texture 2D 에 특정 텍스처를 바인딩하고 TexCoord와 함께 그려준다.
gl.glEnable(GL2.GL_TEXTURE_2D); gl.glBindTexture(GL2.GL_TEXTURE_2D, textureID); gl.glBegin(GL2.GL_QUADS); gl.glTexCoord2f(0.0f, 0.0f);gl.glVertex2f(-0.5f, 0.5f);//좌상단 gl.glTexCoord2f(3.5f, 0.0f); gl.glVertex2f(0.5f, 0.5f);//우상단 gl.glTexCoord2f(3.5f, 1.0f); gl.glVertex2f(0.5f, -0.5f); //우하단 gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex2f(-0.5f, -0.5f); //좌하단 gl.glEnd(); gl.glDisable(GL2.GL_TEXTURE_2D);
다른 객체를 렌더링할 때는 텍스처가 적용되면 안되므로, 마지막으로는 Disable을 해준다.
댓글 0개
댓글은 일회용 패스워드가 발급되며 사이트 이용 약관에 동의로 간주됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.