0

私のシーンは、2 つのテクスチャでシェーディングしている平面で構成されています。一番下の最初のテクスチャは、iPhone のカメラからのソリッド イメージです。2 番目のイメージは、カメラ入力 (透過性あり) の上に重ねる必要がある一種のビューファインダーです。透明なテクスチャのソリッドの境界にこれらの黒い暗い線が表示されます。

ソリッドの周りの黒い枠

私はこれについていくつかの調査を行っており、このアーティファクトは事前に乗算されたアルファと組み合わせた補間の結果であるという理解に達しました. XCodeはすべてのPNG画像を自動的に事前乗算されたpngに変換し、画像をロードするために書いたコードも事前乗算されたアルファコンテキストを尊重しているため、正確な問題がどこにあるかにちょっとこだわっています。

私は次の解決策を試しました:

  • アルファ値が 0 のピクセルの RGB 値も 0 に設定されていることを確認しました
  • xcodeの自動png圧縮をオフにして、テクスチャを私が提供したままにします
  • mix() 呼び出しを避けるためにフラグメントシェーダーをいじりました
  • ビットマップ コンテキストを作成するときの AlphaInfo 値を変更しました

重要: 私は glBlendFunc() を使用していません。2 つのテクスチャを 1 つのフラグメント シェーダーに一緒に供給し、そこでそれらを混ぜようとしています。したがって、この gl-call による解決策では、それ以上は得られません。

透明なテクスチャをロードするために使用しているコードは次のとおりです。

shared_ptr<ImageData> IOSFileSystem::loadImageFile(string path, bool flip) const
{
    cout << path << endl;
    // Result
    shared_ptr<ImageData> result = shared_ptr<ImageData>();

    // Convert cpp string to nsstring
    NSString *convertedPathString = [NSString stringWithCString:path.c_str() encoding:[NSString defaultCStringEncoding]];
    NSString *fullPath = [NSString stringWithFormat:@"%@%@", [[NSBundle mainBundle] resourcePath], convertedPathString];

    // Check if file exists
    if([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:NO])
    {
        // Load image
        UIImage *image = [[[UIImage alloc] initWithContentsOfFile:fullPath] autorelease];
        CGImageRef imageRef = image.CGImage;

        // Allocate memory for the image
        size_t width = CGImageGetWidth(imageRef);
        size_t height = CGImageGetHeight(imageRef);
        GLubyte *spriteData = (GLubyte*) calloc(width * height * 4, sizeof(GLubyte));

        // Create drawing context
        CGContextRef context = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(imageRef), kCGImageAlphaPremultipliedLast);

        // Flip for OpenGL coord system
        if(flip)
        {
            CGContextTranslateCTM(context, 0, image.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
        }

        // Draw & release
        CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), imageRef);
        CGContextRelease(context);

        // Put result in shared ptr
        // Don't free() the spritedata because our shared pointer will take care of that
        // Since the shared pointer doesn't know how to free "calloc" data, we have to teach it how: &std::free
        shared_ptr<GLubyte> spriteDataPtr = shared_ptr<GLubyte>(spriteData, &std::free);
        result = shared_ptr<ImageData>(new ImageData(path, width, height, spriteDataPtr));
    }
    else
    {
        cout << "IOSFileSystem::loadImageFile -> File does not exist at path.\nPath: " + path;
        exit(1);
    }

    return result;
}

テクスチャにピクセルを設定する方法は次のとおりです。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 
    GL_RGBA, GL_UNSIGNED_BYTE, pixels);

フラグメント シェーダーの簡略化されたバージョンを次に示します。

void main(void)
{
    lowp vec4 camera = texture2D(texture0, destinationTexCoord);
    lowp vec4 viewfinder = texture2D(texture1, destinationTexCoord);

    lowp vec4 result = mix(camera, viewfinder, viewfinder.a);

    gl_FragColor = result;
}
4

2 に答える 2

2

これはpremultiplied alpha、PNG 画像が原因である可能性があります。ブレンドモードを変更してみてください:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // instead of (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
于 2012-08-28T15:52:43.507 に答える
0

呼び出しがどのように機能するかを調査することで、問題の解決策を見つけましたglBlendFuncこのエディターを使用して、GL_ONEとをブレンドするために使用される式を確認しましたGL_ONE_MINUS_SRC_ALPHA

これにより、次のフラグメント シェーダー コードが作成されました。

lowp vec4 camera = texture2D(texture0, destinationTexCoord);
lowp vec4 viewfinder = texture2D(texture1, destinationTexCoord);

lowp vec4 result = viewfinder + camera * vec4(1.0 - viewfinder.a);
于 2012-08-29T16:52:09.963 に答える