我为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);
答案 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(..)都可以解决问题。