2010-01-05 2 views
2

OpenGL 게임을 만들고 있는데, 지금까지 RGBA8888 형식의 .png를 텍스처 시트로 사용했지만, 너무 많은 배가 고프다 고해서 앱이 자주 중단됩니다. 나는 Apple 사이트에서 너무 많은 화질이 필요할 때만 그런 형식을 사용하고 대신 RGBA4444 및 RGBA5551을 사용하도록 권장합니다 (이미 PVR로 텍스처를 변환했으나 대부분의 스프라이트 시트에서 품질 손실이 너무 큽니다).RGBA4444의 .png 생성 및로드 OpenGL을위한 RGBA5551

내 텍스처를로드하기 위해 내 텍스처 로더 클래스 안에 내 glTexImage2D 통화에서 GL_UNSIGNED_SHORT_5_5_5_1 또는 GL_UNSIGNED_SHORT_4_4_4_4를 사용해야합니다,하지만 난 RGBA4444와 RGBA5551 내 텍스처 시트를 변환해야합니다, 나는에 대한 우둔 해요

난 단지 내가 어떻게 할 수 이것을 달성하십시오.

+0

거기에 도구가 있습니다. 나는 아이폰 개발에 관심이 없다. 그러나 Nintendo DS homebrew 커뮤니티는 이미지를 그 포맷으로 변환 할 수있는 도구를 가지고있다. – LiraNuna

+0

나에게 그 도구의 이름을 알려주시겠습니까?!, thanks. –

+0

이미지를 다른 형식으로 변환 할 수있는 문자는 거의 무한합니다. 일부는 Windows 전용 일 수 있지만 일부는 iOS 전용입니다. 간단한 구글은 PNG를 RGBA4444로 변환 할 수있는 많은 프로그램을 만들어 낼 것입니다. –

답변

3

심각하게? 이러한 종류의 변환을 수행 할 라이브러리가 있습니다. 그러나 솔직히 말해서, 이것은 조금 비틀 거림이다. asm을 사용하는 라이브러리 나 SSE 명령을 사용하여 빠른 속도로 실행할 수 있지만 C/C++에서 자체 형식 변환기를 쉽게 사용할 수 있습니다. 귀하의 기본 프로세스는 다음과 같습니다

  • 는 RGBA4444 또는 RGBA5551 값을 저장하기에 충분히 큰 버퍼를 작성 RGBA8888 인코딩 값
  • 의 버퍼를 감안할 때. 이 경우, 그것의 간단한 - 크기의 절반.
  • 소스 버퍼를 반복하고 각 구성 요소의 압축을 풀고 대상 형식으로 다시 패킹 한 후 대상 버퍼에 씁니다.

    void* rgba8888_to_rgba4444(
        void* src, // IN, pointer to source buffer 
        int cb) // IN size of source buffer, in bytes 
    { 
        // this code assumes that a long is 4 bytes and short is 2. 
        //on some compilers this isnt true 
        int i; 
        // compute the actual number of pixel elements in the buffer. 
        int cpel = cb/4; 
        unsigned long* psrc = (unsigned long*)src; 
        // create the RGBA4444 buffer 
        unsigned short* pdst = (unsigned short*)malloc(cpel*2); 
        // convert every pixel 
        for(i=0;i<cpel; i++) 
        { 
        // read a source pixel 
        unsigned pel = psrc[i]; 
        // unpack the source data as 8 bit values 
        unsigned r = p & 0xff; 
        unsigned g = (pel >> 8) & 0xff; 
        unsigned b = (pel >> 16) & 0xff; 
        unsigned a = (pel >> 24) & 0xff; 
        //convert to 4 bit vales 
        r >>= 4; 
        g >>= 4; 
        b >>= 4; 
        a >>= 4; 
        // and store 
        pdst[i] = r | g << 4 | b << 8 | a << 12; 
        } 
        return pdst; 
    } 
    

나는 매우 낭비했던 실제 변환 루프는 구성 요소를 추출 변환 훨씬 더 빠른 코드를 만들고, 단일 패스에서 재 포장 할 수있다. 전환을 명확하고 쉽게 변경하려면이 방법을 사용했습니다. 또한, 내가 올바른 순서로 구성 요소를 주문했는지 확신 할 수 없습니다. 따라서 b, r, g, a 일 수 있지만 dest 버퍼에 동일한 순서로 다시 팩할 때 함수의 결과에 영향을 주어서는 안됩니다.

+1

훌륭한 코드 샘플. BTW, 나는 당신의 pdst 가치가 있어야한다고 생각합니다 .... pdst [i] = r << 12 | g << 8 | b << 4 | 에이; – tyshock

+0

아참. 나는 방향을 잘못 잡았다!. 그게 끔찍한 일이야. OpenGL.org 어디서나 실제로 모든 다른 형식의 레이아웃을 지정하는 문서를 찾을 수 없습니다. / –

5

ImageMagick를 사용하여 다음을 실행하여 RGBA4444 PNG 파일을 만들 수 있습니다

convert source.png -depth 4 destination.png 

을 당신은 MacPorts에서 ImageMagick를 얻을 수 있습니다.

+0

이것은 픽셀 값의 최하위 비트를 잘라 버릴 것이지만 libpng (또는 사용중인 모든 로더)의 출력은 여전히 ​​8 비트 구성 요소입니다. 문제는 픽셀 구성 요소 값을 OpenGL 형식으로 비트 팩하는 방법에 관한 것입니다. 이를 수행 할 웹상의 샘플 코드가 많이 있습니다. 단지 비트 뭉치 일뿐입니다. –

+0

@Andy : 하나 이상의 예제를 가르쳐 주시겠습니까? –

5

Windows 용 상상력의 PVRTexTool을 사용해보십시오. 특히 지원되는 모든 색상 형식으로 PVR 텍스처를 만드는 데 적합합니다. 이것은 PVRTC 압축 텍스처 ("PVR"이라고 부르는 것)와 8888, 5551, 4444 등의 비 압축 텍스처를 모두 생성 할 수 있습니다.

그러나 PNG (PVR 만)를 출력하지 않으므로로드 코드가 변화가있다. 또한 PNG의 픽셀이 수축 압축으로 압축되기 때문에 때로는 PVR이 PNG보다 훨씬 큽니다. 당신은 대부분의 OS X를 실행하기 때문에

, 당신은 당신이 PVRTexTool을 다운로드 할 수 있습니다 전에 register as an Imagination developer해야합니다 OS X의

에 (그리고 다른 윈도우 프로그램)을 실행하는 데 Darwine (now WineBottler)를 사용할 수 있습니다. 등록과 도구는 모두 무료입니다.

일단 설정을 마치면 꽤 고통스럽고 PVR 작업에 알맞은 GUI를 제공합니다.

0

가 2 배 빠른 속도로 실행해야합니다 크리스 '코드의 현재 위치에서 변환에 최적화되어 있지만, 해협처럼 앞으로가 아니다. 내부 변환은 메모리 스파이크를 낮추어 충돌을 피하는 데 도움이됩니다. 누구든지이 코드를 사용할 계획이라면 나눌 생각이었습니다. 나는 그것을 테스트했으며 훌륭하게 작동합니다 :

void* rgba8888_to_rgba4444(void* src, // IN, pointer to source buffer 
          int cb) // IN size of source buffer, in bytes 
{ 
    int i; 
    // compute the actual number of pixel elements in the buffer. 
    int cpel = cb/4; 
    unsigned long* psrc = (unsigned long*)src; 
    unsigned short* pdst = (unsigned short*)src; 

    // convert every pixel 

    for(i=0;i<cpel; i++) 
    { 
     // read a source pixel 
     unsigned pel = psrc[i]; 
     // unpack the source data as 8 bit values 
     unsigned r = (pel << 8) & 0xf000; 
     unsigned g = (pel >> 4) & 0x0f00; 
     unsigned b = (pel >> 16) & 0x00f0; 
     unsigned a = (pel >> 28) & 0x000f; 

     // and store 
     pdst[i] = r | g | b | a; 
    } 
    return pdst; 
}