私はMonoTouchのOpenTKを使用してiOSでいくつかのテクスチャをレンダリングしていますが、いくつかのテクスチャが壊れています。これはiPadのスクリーンショットのクローズアップで、正しくレンダリングされた1つのテクスチャ(上のテクスチャ)と下の2つの壊れたテクスチャを示しています。
私は変なことは何もしていません。CGImage
-> CGBitmapContext
->を使用して、半透明のPNGからテクスチャをロードしていGL.TexImage2D
ます。各スプライトを2つの三角形でレンダリングしています。フラグメントシェーダーは、サンプラーからテクセルを読み取り、texture2D()
それをaで乗算してuniform vec4
、テクスチャに色を付けます。
ファイル自体は問題ないようで、Mono for Androidを使用する同じアプリケーションのAndroidポート、およびまったく同じバイナリリソースがファイルを完全にレンダリングします。ご覧のとおり、他の透明なテクスチャは問題なく機能します。
それが役に立ったら、シミュレータでプログラムを実行すると、ほとんどすべてのテクスチャが壊れます。また、プログラムを再構築してもこの問題は解決しません。
この問題の原因を突き止める方法について何かアイデアはありますか?
これが私の頂点シェーダーです:
attribute vec4 spritePosition;
attribute vec2 textureCoords;
uniform mat4 projectionMatrix;
uniform vec4 color;
varying vec4 colorVarying;
varying vec2 textureVarying;
void main()
{
gl_Position = projectionMatrix * spritePosition;
textureVarying = textureCoords;
colorVarying = color;
}
これが私のフラグメントシェーダーです:
varying lowp vec4 colorVarying;
varying lowp vec2 textureVarying;
uniform sampler2D spriteTexture;
void main()
{
gl_FragColor = texture2D(spriteTexture, textureVarying) * colorVarying;
}
私はこのように画像をロードしています:
using (var bitmap = UIImage.FromFile(resourcePath).CGImage)
{
IntPtr pixels = Marshal.AllocHGlobal(bitmap.Width * bitmap.Height * 4);
using (var context = new CGBitmapContext(pixels, bitmap.Width, bitmap.Height, 8, bitmap.Width * 4, bitmap.ColorSpace, CGImageAlphaInfo.PremultipliedLast))
{
context.DrawImage(new RectangleF(0, 0, bitmap.Width, bitmap.Height), bitmap);
int[] textureNames = new int[1];
GL.GenTextures(1, textureNames);
GL.BindTexture(TextureTarget.Texture2D, textureNames[0]);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmap.Width, bitmap.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
CurrentResources.Add(resourceID, new ResourceData(resourcePath, resourceType, 0, new TextureEntry(textureNames[0], bitmap.Width, bitmap.Height)));
}
}
私のonRenderFrameには、次のものがあります。
GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.UseProgram(RenderingProgram);
GL.VertexAttribPointer((int)ShaderAttributes.SpritePosition, 2, VertexAttribPointerType.Float, false, 0, squareVertices);
GL.VertexAttribPointer((int)ShaderAttributes.TextureCoords, 2, VertexAttribPointerType.Float, false, 0, squareTextureCoords);
GL.EnableVertexAttribArray((int)ShaderAttributes.SpritePosition);
GL.EnableVertexAttribArray((int)ShaderAttributes.TextureCoords);
//...
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, textureEntry.TextureID);
GL.Uniform1(Uniforms[(int)ShaderUniforms.Texture], 0);
// ...
GL.DrawArrays(BeginMode.TriangleStrip, 0, 4);
その三角ストリップは、テクスチャを構成する2つの三角形で構成されており、頂点とテクスチャの座標がスプライトを表示する場所に設定されています。projectionMatrix
は単純なオルトグラフィック射影行列です。
ご覧のとおり、私はここで特別なことをしようとはしていません。これはすべてかなり標準的なコードであり、一部のテクスチャでも機能するので、一般的にコードは問題ないと思います。私はMonoforAndroidでもほぼ同じことを行っており、テクスチャが破損することなく非常にうまく機能します。
そのような破損した色は、どこかで初期化されていない変数のようなにおいがします。それが透明な部分でのみ発生するのを見ると、どこかに初期化されていないアルファ値があると思います。ただし、GL.Clear(ClearBufferMask.ColorBufferBit)
アルファ値をクリアする必要があります。それでも、背景テクスチャのアルファ値は1であり、現在のBlendFunc
場合、これらのピクセルのアルファを1に設定する必要があります。その後、透明テクスチャのアルファ値は0から1の範囲になります。 、適切にブレンドする必要があります。初期化されていない変数はどこにも見当たりません。
...または...これはすべてのせいですCGBitmapContext
。たぶん、を実行することDrawImage
で、ソースイメージをブリット化するのではなく、代わりにブレンディングで描画します。ガベージデータは、作成したときのものですAllocGlobal
。これは、なぜこれら2つのテクスチャだけで一貫して発生するのかを説明していません...(私はこれをコアグラフィックとしてタグ付けしているので、クォーツの人の1人が助けることができます)
さらにコードを見たい場合はお知らせください。