无法获得要在GLSL Xamarin OpenGLView控制中渲染的颜色

问题描述

任何人都可以提供以下帮助吗?

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

enter image description here

这是我的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.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,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,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,m_vertex_buffer_data,BufferUsage.StaticDraw);
                }

                GL.ClearColor(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,VertexAttribPointerType.Float,false,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,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,m_szVertexShader,new int[] { nVertexShaderSourceLength });
            GL.ShaderSource(m_nFragmentShaderHandle,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时确实存在编译错误,但是我的着色器太琐碎,以至于我看不到这个问题:

enter image description here

非常感谢您的帮助(暂时停滞了一段时间。之前已经在台式机和WebGL上完成了很多OpenGL,但在移动方面还没有运气)。

添加:非常感谢您的答复。我已经用兼容的着色器替换了着色器,不幸的是我仍然有一个黑色正方形:

(在图中显示为mediump的图像中,我也尝试过highp和lowp,但仍然得到相同的结果)。

enter image description here

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

enter image description here

感谢您可能提供的其他建议。

解决方法

这些着色器不符合任何GLSL ES规范。分别参见OpenGL ES Shading Language 1.00 SpecificationOpenGL 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,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);
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...