【问题标题】:Xamarin : OpenTK OpenGL Android crashXamarin:OpenTK OpenGL Android 崩溃
【发布时间】:2015-09-06 22:08:29
【问题描述】:

我正在尝试创建一个 iOS/Android 演示应用程序,该应用程序显示 Xamarin OpenTK / OpenGl 在屏幕上呈现一些立方体。在 iOS 中一切正常,但在 Android 中相同的代码会崩溃。这是基于他们的一些演示代码的完全共享代码。

我没有得到有关崩溃的信息。

using OpenTK.Graphics.ES20;
using Xamarin.Forms;
using OpenTK.Graphics;
using OpenTK;
using System.Reflection;
using System.IO;
using System.Diagnostics;
using System;

namespace GLDemo
{
    public class App
    {
        public static Page GetMainPage ()
        {   
            return new OpenGLPage ();
        }
    }

    public class OpenGLPage : ContentPage
    {

        uint positionSlot;
        uint colorSlot;
        uint projectionSlot;
        uint modelViewSlot;

        uint colorRenderBuffer;
        uint depthBuffer;

        // cube verticies 
        Vector3[] Verticies = new Vector3[] { 
            new Vector3 (1.0f, -1.0f, 1.0f),
            new Vector3 (1.0f, 1.0f, 1.0f),
            new Vector3 (-1.0f, 1.0f, 1.0f),
            new Vector3(-1.0f, -1.0f, 1.0f),
            new Vector3(1.0f, -1.0f, -1.0f),
            new Vector3(1.0f, 1.0f, -1.0f),
            new Vector3(-1.0f, 1.0f, -1.0f),
            new Vector3(-1.0f, -1.0f, -1.0f)};

        Vector4[] Colors = new Vector4[]{
            new Vector4(0.0f, 0.0f, 0.0f, 1.0f),
            new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
            new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
            new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
            new Vector4(1.0f, 1.0f, 1.0f, 1.0f)};

        byte[] Indices = new byte [] 
        { 0, 1, 2,
            2, 3, 0,
            4, 6, 5,
            4, 7, 6,
            2, 7, 3,
            7, 6, 2,
            0, 4, 1,
            4, 1, 5,
            6, 2, 1,
            1, 6, 5,
            0, 3, 7,
            0, 7, 4};

        public OpenGLPage ()
        {
            Title = "OpenGL";
            var view = new OpenGLView { HasRenderLoop = true };
            var toggle = new Xamarin.Forms.Switch { IsToggled = true };
            var button = new Button { Text = "Display" };

            view.HeightRequest = 300;
            view.WidthRequest = 300;

            bool initialize = false;

            float rotation = 0.0f;
            float translation = 0.0f;
            bool goingRight = true;

            view.OnDisplay = r => {

                if(!initialize){
                    SetupDepthBuffer ();
                    SetupRenderBuffers ();
                    SetupFrameBuffer ();
                    CompileShaders ();
                    SetupVBOs ();
                    initialize = true;
                }

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

                rotation += 0.02f;
                if(goingRight){
                    translation += 0.01f;
                    if(translation > 1.0f){
                        goingRight = false;
                    }
                } else{
                    translation -= 0.01f;
                    if(translation < -1.0f){
                        goingRight = true;
                    }
                }

                for(int i = 0; i < 3; i++){
                    float h = 4.0f * (float)view.Height / (float)view.Width;
                    Matrix4[] projection = new Matrix4[]{ Matrix4.CreatePerspectiveOffCenter(-2, 2, -h/2, h/2, 4, 10) };
                    GL.UniformMatrix4 ((int)projectionSlot, false, ref projection[0]);

                    Matrix4[] modelView = new Matrix4[]{ Matrix4.CreateRotationX(rotation) * Matrix4.CreateRotationY(rotation) * Matrix4.CreateRotationZ(rotation) * Matrix4.CreateTranslation (translation - i * 3.5f + 4.0f, (float)(-1^i) * translation, -7 + translation) };
                    GL.UniformMatrix4 ((int)modelViewSlot, false, ref modelView [0]);

                    GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedByte, 0);
                }
            };

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

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

            Content = stack;


        }

        void SetupRenderBuffers(){
            GL.GenRenderbuffers (1, out colorRenderBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, colorRenderBuffer);
            GL.RenderbufferStorage (RenderbufferTarget.Renderbuffer, RenderbufferInternalFormat.Rgba4, 300, 300);
        }

        void SetupFrameBuffer(){
            uint frameBuffer;
            GL.GenFramebuffers (1, out frameBuffer);
            GL.BindFramebuffer (FramebufferTarget.Framebuffer, frameBuffer);
            GL.FramebufferRenderbuffer (FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0,
                RenderbufferTarget.Renderbuffer, colorRenderBuffer);
            GL.FramebufferRenderbuffer (FramebufferTarget.Framebuffer, FramebufferSlot.DepthAttachment,
                RenderbufferTarget.Renderbuffer, depthBuffer);
        }

        void SetupDepthBuffer(){
            GL.GenRenderbuffers (1, out depthBuffer);
            GL.BindRenderbuffer (RenderbufferTarget.Renderbuffer, depthBuffer);
            GL.RenderbufferStorage (RenderbufferTarget.Renderbuffer, RenderbufferInternalFormat.DepthComponent16, 300, 300);
        }

        uint CompileShader(string shaderName, ShaderType shaderType){
            string prefix;

            #if __IOS__ 
            prefix = "GLDemo.iOS.";
            #endif
            #if __ANDROID__
            prefix = "GLDemo.Android.";
            #endif

            var assembly = typeof(App).GetTypeInfo ().Assembly;


            foreach (var res in assembly.GetManifestResourceNames())
                System.Diagnostics.Debug.WriteLine("found resource: " + res);

            Stream stream = assembly.GetManifestResourceStream (prefix + shaderName + ".glsl");

            string shaderString;

            using (var reader = new StreamReader (stream)) {
                shaderString = reader.ReadToEnd ();
            }
            Debug.WriteLine (shaderString);
            uint shaderHandle = (uint)GL.CreateShader (shaderType);
            GL.ShaderSource ((int)shaderHandle, shaderString);
            GL.CompileShader (shaderHandle);

            return shaderHandle;
        }

        void CompileShaders(){
            uint vertexShader = CompileShader ("SimpleVertex", ShaderType.VertexShader);
            uint fragmentShader = CompileShader ("SimpleFragment", ShaderType.FragmentShader);
            uint programHandle = (uint)GL.CreateProgram ();
            GL.AttachShader (programHandle, vertexShader);
            GL.AttachShader (programHandle, fragmentShader);
            GL.LinkProgram (programHandle);
            GL.UseProgram (programHandle);

            positionSlot = (uint)GL.GetAttribLocation (programHandle, "Position");
            colorSlot = (uint)GL.GetAttribLocation (programHandle, "SourceColor");
            projectionSlot = (uint)GL.GetUniformLocation (programHandle, "Projection");
            modelViewSlot = (uint)GL.GetUniformLocation (programHandle, "Modelview");

            GL.EnableVertexAttribArray (positionSlot);
            GL.EnableVertexAttribArray (colorSlot);
            GL.EnableVertexAttribArray (projectionSlot);
            GL.EnableVertexAttribArray (modelViewSlot);

        }

        void SetupVBOs(){
            uint vertexBuffer;
            GL.GenBuffers (1, out vertexBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, vertexBuffer);
            GL.BufferData (BufferTarget.ArrayBuffer,(IntPtr)(Vector3.SizeInBytes * Verticies.Length), Verticies, BufferUsage.StaticDraw);
            GL.VertexAttribPointer (positionSlot, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

            uint colorBuffer;
            GL.GenBuffers (1, out colorBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, colorBuffer);
            GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(Vector4.SizeInBytes * Colors.Length), Colors, BufferUsage.StaticDraw);
            GL.VertexAttribPointer (colorSlot, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);

            uint indexBuffer;
            GL.GenBuffers (1, out indexBuffer);
            GL.BindBuffer (BufferTarget.ElementArrayBuffer, indexBuffer);
            GL.BufferData (BufferTarget.ElementArrayBuffer,(IntPtr)(sizeof(byte) * Indices.Length), Indices, BufferUsage.StaticDraw);
        }
    }
}

更新

我相信这与 Android 和 VBO 有关。已知问题?谁知道怎么解决

更新 2

更新到

void SetupVBOs(){
            uint vertexBuffer;
            GL.GenBuffers (1, out vertexBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, vertexBuffer);
            GL.BufferData (BufferTarget.ArrayBuffer,(IntPtr)(Vector3.SizeInBytes * Verticies.Length), Verticies, BufferUsage.StaticDraw);
            GL.VertexAttribPointer (positionSlot, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

            uint colorBuffer;
            GL.GenBuffers (1, out colorBuffer);
            GL.BindBuffer (BufferTarget.ArrayBuffer, colorBuffer);
            GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(Vector4.SizeInBytes * Colors.Length), Colors, BufferUsage.StaticDraw);
            GL.VertexAttribPointer (colorSlot, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);
        }

我试试

GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedByte, Indices);

它在设备上崩溃

我试试

            unsafe
            {
                fixed (byte* ptr = Indices)
                {
                    GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedByte, new IntPtr(ptr));

                }
            }

并且没有任何错误呈现

[Adreno-EGLSUB] : 本机缓冲区无效。排队缓冲区失败 [Adreno-EGLSUB] : 本机缓冲区为 NULL

【问题讨论】:

    标签: android opengl-es xamarin xamarin.android opentk


    【解决方案1】:

    我知道这个线程有点老了,但我已经解决了这个问题几天,最后通过将 DrawElements 调用的最后一个参数更改为 IntPtr.Zero 来解决它:

    GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedByte, IntPtr.Zero);
    

    【讨论】:

      【解决方案2】:
      出于某种原因,当我们将 IBO(索引缓冲区对象)与 Xamarin.Forms + OpenGL 一起使用时,Android 会崩溃。而是将索引信息传递给 DrawElements。
      void SetupVBOs(){
          uint vertexBuffer;
          GL.GenBuffers (1, out vertexBuffer);
          GL.BindBuffer (BufferTarget.ArrayBuffer, vertexBuffer);
          GL.BufferData (BufferTarget.ArrayBuffer,(IntPtr)(Vector3.SizeInBytes * Verticies.Length), Verticies, BufferUsage.StaticDraw);
          GL.VertexAttribPointer (positionSlot, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
      
          uint colorBuffer;
          GL.GenBuffers (1, out colorBuffer);
          GL.BindBuffer (BufferTarget.ArrayBuffer, colorBuffer);
          GL.BufferData (BufferTarget.ArrayBuffer, (IntPtr)(Vector4.SizeInBytes * Colors.Length), Colors, BufferUsage.StaticDraw);
          GL.VertexAttribPointer (colorSlot, 4, VertexAttribPointerType.Float, false, Vector4.SizeInBytes, 0);
      }
      

      编辑

      我在过去一周左右重新访问了一些 OpenTK,我想通了!

      GL.DrawElements() 用于传递索引数据,如果您更喜欢使用 IBO,请按照所示绑定它,而不是使用

      GL.DrawArrays(BeginMode.Triangles, 0, Indices.Length);
      

      【讨论】:

      • 我得到 [Adreno-EGLSUB] <436><1348>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多