2015-06-21 2 views
0

Я пытаюсь создать демонстрационное приложение iOS/Android, которое показывает Xamarin OpenTK/OpenGl, отображая некоторые кубы на экране. Все работает в iOS, но один и тот же код в Android просто падает. Это полностью разделенный код, основанный на некоторых их демо-кодах.Xamarin: OpenTK OpenGL Android crash

Я не получаю информацию об аварии.

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); 
     } 
    } 
} 

UPDATE

Я считаю, что это что-то с Android и VBO. Известная проблема? Кто-нибудь знает, как решить это

Update 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]: Invalid родной буфера. Не удалось queueBuffer [Adreno-EGLSUB]: родной буфер NULL

ответ

2
По некоторым причинам, Android падает, когда мы используем (Object Index Buffer) МБО с Xamarin.Forms + OpenGL. Вместо этого передайте индексную информацию в 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); 
} 

EDIT

Я вновь некоторых OpenTK на прошлой неделе или около того, и я понял это!

GL.DrawElements() предназначен для использования для передачи в индексных данных, если вы предпочитаете использовать IBO, связать его, как вы показали, и вместо того, чтобы использовать

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

Я получаю [Adreno-EGLSUB] : native buffer - NULL [Adreno-EGLSUB] : Недействительный собственный бафф э. Ошибка в queueBuffer как ошибка и ничего не отображается. – Burf2000

+1

Попробуйте это в симуляторе, я уверен, что ошибка вашего получения связана с фактическим физическим устройством, и это отдельная проблема. –

+0

Я просто получаю мусор – Burf2000

0

Я знаю, что эта нить немного старый, но я воюю этот вопрос в течение нескольких дней, и, наконец, решил ее изменения последнего параметра DrawElements звоните в IntPtr.Zero:

GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedByte, IntPtr.Zero); 
Смежные вопросы