OpenGL ES 2.0 / MonoTouch:渲染GUI纹理不显示任何内容

时间:2011-11-04 18:11:25

标签: iphone opengl-es xamarin.ios opengl-es-2.0

我为MonoTouch构建一个简单的OpenGL UI框架。我设置了所有内容并成功渲染了3D模型,但是一个简单的2D纹理对象失败了。纹理的大小为256x256,所以它不大,功率为2。

这是一些渲染代码(注意:我确实删除了现有的和正在运行的代码):

// Render the gui objects ( flat )
Projection = Matrix4x4.Orthographic(0, WindowProperties.Width, WindowProperties.Height, 0);
View = new Matrix4x4();
GL.Disable(All.CullFace);
GL.Disable(All.DepthTest);
_Stage.RenderGui();

阶段:

public void RenderGui ()
{
    Draw(this);
    // Renders every child control, all of them call "DrawImage" when rendering something
}


public void DrawImage (Control caller, ITexture2D texture, PointF position, SizeF size)
{
    PointF gposition = caller.GlobalPosition; // Resulting position is 0,0 in my tests
    gposition.X += position.X;
    gposition.Y += position.Y;

    // Renders the ui model, this is done by using a existing ( and working vertex buffer )
    // The shader gets some parameters ( this works too in 3d space )   
    _UIModel.Render(new RenderParameters() {
        Model = Matrix4x4.Scale(size.Width, size.Height, 1) * Matrix4x4.Translation(gposition.X, gposition.Y, 0),
       TextureParameters = new TextureParameter[] {
           new TextureParameter("texture", texture)
       }
    });
}

模型使用vector2作为位置,没有为着色器提供其他属性。

下面的着色器应该渲染纹理。

顶点:

attribute vec2 position;        
uniform mat4 modelViewMatrix;           
varying mediump vec2 textureCoordinates;

void main()
{
    gl_Position = modelViewMatrix * vec4(position.xy, -3.0, 1.0);
    textureCoordinates = position;
}

片段:

varying mediump vec2 textureCoordinates;
uniform sampler2D texture;          

void main()
{
    gl_FragColor = texture2D(texture, textureCoordinates) + vec4(0.5, 0.5, 0.5, 0.5);
}

我发现绘图问题是由着色器引起的。此行生成GL_INVALID_OPERATION(它适用于其他着色器):

GL.UniformMatrix4(uni.Location, 1, false, (parameters.Model * _Device.View * _Device.Projection).ToArray());

编辑:

事实证明着色器均匀位置发生了变化(是的,我也想知道这一点,因为初始化发生在着色器完全初始化时。我改变了它,现在一切正常。

如在另一个线程中提到的那样,纹理是错误的,但这是另一个问题(OpenGL ES 2.0 / MonoTouch: Texture is colorized red

使用上面提到的GL.GetUniformLocation问题进行着色器初始化:

[... Compile shaders ...]
// Attach vertex shader to program.
GL.AttachShader (_Program, vertexShader);

// Attach fragment shader to program.
GL.AttachShader (_Program, pixelShader);        

// Bind attribute locations
for (int i = 0; i < _VertexAttributeList.Length; i++) {
    ShaderAttribute attribute = _VertexAttributeList [i];
    GL.BindAttribLocation (_Program, i, attribute.Name);
}

// Link program
if (!LinkProgram (_Program)) {
    GL.DeleteShader (vertexShader);
    GL.DeleteShader (pixelShader);
    GL.DeleteProgram (_Program);

    throw new Exception ("Shader could not be linked");
}

// Get uniform locations
for (int i = 0; i < _UniformList.Length; i++) {
    ShaderUniform uniform = _UniformList [i];
    uniform.Location = GL.GetUniformLocation (_Program, uniform.Name);
    Console.WriteLine ("Uniform: {0} Location: {1}", uniform.Name, uniform.Location);
}

// Detach shaders
GL.DetachShader (_Program, vertexShader);
GL.DetachShader (_Program, pixelShader);

GL.DeleteShader (vertexShader);
GL.DeleteShader (pixelShader);

// Shader is initialized add it to the device
_Device.AddResource (this);

2 个答案:

答案 0 :(得分:3)

我不知道Matrix4x4.Orthographic使用什么作为近远距离,但如果它像[-1,1]那样简单,那么对象可能只是在远近距离之外,因为你在顶点着色器中将其z值显式设置为-3.0(模型矩阵的比例和平移都不会改变它)。尝试使用0.0的z代替。无论如何,它为什么是-3?

编辑:因此,如果GL.UniformMatrix4函数抛出GL_INVALID_OPERATION,则您似乎没有成功检索相应的unfiorm位置。因此,执行此操作的代码也可能有助于找到问题。

或者也可能是在使用相应的着色器程序之前调用GL.UniformMatrix4。请记住,只有在程序处于活动状态时才能设置制服(使用着色器程序调用{​​{1}}或类似的东西)。

顺便说一下,无论如何,你都会以错误的顺序将矩阵相乘(给定着色器和矩阵设置代码)。如果它真的以这种方式用于其他渲染,那么你要么幸运,要么你的矩阵库中存在严重的概念和数学上的不一致。

答案 1 :(得分:0)

事实证明,着色器制服在未知时间发生变化。当我向OpenGL ES询问统一位置时,所有内容都已创建并初始化,因此它必定是OpenGL中的错误。

每次设置着色器时,调用GL.GetUniformLocation(..)都可以解决问题。