我在 MonoTouch 中使用 OpenTK 在 iOS 中渲染一些纹理,并且一些纹理出现损坏。这是 iPad 屏幕截图的特写,显示了一个正确渲染的纹理(顶部)和下面的两个损坏的纹理:
我没有做任何奇怪的事情。我正在使用CGImage
-> CGBitmapContext
->从半透明 PNG 加载纹理GL.TexImage2D
。我用两个三角形渲染每个精灵,我的片段着色器只是从采样器中读取纹素,texture2D()
并将其乘以 auniform 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);
该三角形条由构成纹理的两个三角形组成,顶点和纹理坐标设置为我想要显示我的精灵的位置。projectionMatrix
是一个简单的正射投影矩阵。
正如你所看到的,我不想在这里做任何花哨的事情。这都是非常标准的代码,它适用于某些纹理,所以我认为总的来说代码是可以的。我也在 Mono for Android 中做几乎相同的事情,它运行良好,没有任何纹理损坏。
像这样的损坏颜色在某处闻起来像未初始化的变量,并且只在透明部分发生这种情况让我相信我在某处有未初始化的 alpha 值。但是,GL.Clear(ClearBufferMask.ColorBufferBit)
应该清除我的 alpha 值,即使这样,背景纹理的 alpha 值也是 1,并且使用 current BlendFunc
,应该将这些像素的 alpha 设置为 1。之后,透明纹理的 alpha 值范围为 0 到 1 ,所以它们应该正确混合。我在任何地方都看不到未初始化的变量。
……或者……这都是 的错CGBitmapContext
。也许通过这样做DrawImage
,我不是在对源图像进行 blitting,而是通过混合来绘制它,而垃圾数据来自我这样做的时候AllocGlobal
。这并不能解释为什么它始终只发生在这两种纹理上......(我将其标记为核心图形,所以也许石英人之一可以提供帮助)
如果您想查看更多代码,请告诉我。