无法获取要在 GLSL Xamarin OpenGLView 控件中呈现的颜色

Cannot get colors to render in GLSL Xamarin OpenGLView contol

谁能帮忙解决以下问题?

使用 Visual Studio 2019 Xamarin Forms 项目我试图在 Android 模拟器中显示一个旋转的红色方块。我可以正常工作,但我的方块是黑色的:

这是我的 MainPage.xaml.cs 的代码(我使用 ES20,因为 ES10 没有我需要的 OpenGL 函数):

using OpenTK.Graphics.ES20;
using System;
using Xamarin.Forms;

namespace OGLMobile
{
    public partial class MainPage : ContentPage
    {
        private float red = 1.0f;
        private float green = 0.0f;
        private float blue = 0.0f;

        private const float halfWidth = 0.2f;
        private float[] m_vertex_buffer_data = { 0.5f - halfWidth, 0.5f - halfWidth, 0.0f,
                                                 0.5f + halfWidth, 0.5f - halfWidth, 0.0f,
                                                 0.5f + halfWidth, 0.5f + halfWidth, 0.0f,
                                                 0.5f - halfWidth, 0.5f + halfWidth, 0.0f };

        private string[] m_szVertexShader = null;
        private string[] m_szFragmentShader = null;

        private int m_nProgram = -1;
        private int m_nVertexShaderHandle = -1;
        private int m_nFragmentShaderHandle = -1;

        private uint[] indices = { 0, 1, 2, 0, 2, 3 };

        private int m_nVertexBuffer = -1;

        bool m_bOGLParametersSet = false;

        private void RotateSquare(float radians, float xRotationCentre, float yRotationCentre)
        {
            int[] nBaseIndices = { 0, 3, 6, 9 };

            for (int nVertex = 0; nVertex <= 3 ; nVertex++)
            {
                int nIndex1 = nBaseIndices[nVertex];
                int nIndex2 = nIndex1 + 1;

                float offsetX = m_vertex_buffer_data[nIndex1] - xRotationCentre;
                float offsetY = m_vertex_buffer_data[nIndex2] - yRotationCentre;

                double xRotated = offsetX * Math.Cos(radians) - offsetY * Math.Sin(radians);
                double yRotated = offsetX * Math.Sin(radians) + offsetY * Math.Cos(radians);

                m_vertex_buffer_data[nIndex1] = (float)xRotated + xRotationCentre;
                m_vertex_buffer_data[nIndex2] = (float)yRotated + yRotationCentre;
            }

            GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);
            GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data);
        }

        public MainPage()
        {
            Title = "OpenGL";
            var view = new OpenGLView { HasRenderLoop = true };
            var toggle = new Switch { IsToggled = true };

            m_szVertexShader = new string[1];
            m_szFragmentShader = new string[1];

            view.HeightRequest = 300;
            view.WidthRequest = 300;
            
            GL.Viewport(0, 0, 300, 300);

            view.OnDisplay = r =>
            {
                if(!m_bOGLParametersSet) // Do this only on first rendering
                {
                    CreateShader();

                    m_bOGLParametersSet = true;

                    GL.UseProgram(m_nProgram);

                    GL.GenBuffers(1, out m_nVertexBuffer);

                    GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);

                    GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(m_vertex_buffer_data.Length * sizeof(float)), m_vertex_buffer_data, BufferUsage.StaticDraw);
                }

                GL.ClearColor(0.0f, 0.0f, 1.0f, 1.0f);
                GL.Clear((ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));

                RotateSquare(0.0174533f, 0.5f, 0.5f);

                GL.EnableVertexAttribArray(0);
                GL.BindBuffer(BufferTarget.ArrayBuffer, m_nVertexBuffer);


                GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);

                GL.DrawElements(BeginMode.Triangles, indices.Length, DrawElementsType.UnsignedInt, indices);

                GL.DisableVertexAttribArray(0);

                
            };

            toggle.Toggled += (s, a) =>
            {
                view.HasRenderLoop = toggle.IsToggled;
            };

            var stack = new StackLayout
            {
                Padding = new Size(20, 20),
                Children = { view, toggle}
            };

            Content = stack;
        }

        private void SetShaderSource()
        {
            m_szVertexShader[0] = "void main()" +
                                  "{" +
                                    "gl_Position = ftransform();" +
                                  "}";

            m_szFragmentShader[0] = "void main()" +
                                    "{" +
                                        "gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
                                    "}";
        }


        private void CreateShader()
        {
            SetShaderSource();

            int nVertexShaderSourceLength = m_szVertexShader[0].Length;
            int nFragmentShaderLength = m_szFragmentShader[0].Length;

            m_nVertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
            m_nFragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);

            GL.ShaderSource(m_nVertexShaderHandle, 1, m_szVertexShader, new int[] { nVertexShaderSourceLength });
            GL.ShaderSource(m_nFragmentShaderHandle, 1, m_szFragmentShader, new int[] { nVertexShaderSourceLength });

            GL.CompileShader(m_nVertexShaderHandle);
            GL.CompileShader(m_nFragmentShaderHandle);

            string szVertexShaderLog = GL.GetShaderInfoLog(m_nVertexShaderHandle);
            string szFragmentShaderLog = GL.GetShaderInfoLog(m_nFragmentShaderHandle);

            m_nProgram = GL.CreateProgram();

            GL.AttachShader(m_nProgram, m_nVertexShaderHandle);
            GL.AttachShader(m_nProgram, m_nFragmentShaderHandle);

            GL.LinkProgram(m_nProgram);
        }
    }
}

我的着色器一定是不正确的,如果我用垃圾字符串替换它们,我会得到相同的输出,所以系统一定是默认的东西。

我在调用 GetShaderInfoLog 时确实有编译错误,但我的着色器太简单了,我看不出问题所在:

非常感谢您的帮助,(现在已经坚持了一段时间。之前已经在桌面和 WebGL 上完成了大量的 OpenGL,但在移动设备上还没有任何运气)。

补充:非常感谢您的回复。我已经用兼容的着色器替换了着色器,不幸的是我仍然有一个黑色方块:

(图中写的是mediump,highp和lowp我也试过,结果一样)

我现在在编译顶点着色器时遇到一个不同的错误,而在片段着色器上没有错误 - 尽管我对后者有一个警告:

感谢您提供任何进一步的建议。

这些着色器不符合任何 GLSL ES 规范。参见 OpenGL ES Shading Language 1.00 Specification respectively. OpenGL ES Shading Language 3.00 Specification

查看带有顶点着色器的工作着色器:

attribute vec3 a_position;

void main()
{
    gl_Position = vec4(a_position, 1.0);
}

和片段着色器

precision mediump float;

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

我建议验证着色器编译是否有错误:

GL.CompileShader(m_nVertexShaderHandle);
string infoLogFrag = GL.GetShaderInfoLog(m_nVertexShaderHandle);
if (infoLogFrag != System.String.Empty)
{
    System.Console.WriteLine(infoLogFrag);
}

GL.CompileShader(m_nFragmentShaderHandle);
string infoLogVert = GL.GetShaderInfoLog(m_nFragmentShaderHandle);
if (infoLogVert != System.String.Empty)
{
    System.Console.WriteLine(infoLogVert);
}

并且程序链接没有错误:

GL.LinkProgram(m_nProgram);
string infoLogProg = GL.GetProgramInfoLog(m_nProgram );
if (infoLogProg != System.String.Empty)
{
    System.Console.WriteLine(infoLogProg);
}