2015-06-21 127 views
0

我想創建一個iOS/Android演示應用程序,顯示Xamarin OpenTK/OpenGl在屏幕上呈現一些多維數據集。一切工作在iOS,但在Android相同的代碼只是崩潰。這是完全基於他們的一些演示代碼的共享代碼。Xamarin:OpenTK OpenGL 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); 
     } 
    } 
} 

UPDATE

我認爲這是一件與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)); 

       } 
      } 

並沒有什麼渲染錯誤

[腎上腺EGLSUB]:無效的本地緩存。未能queueBuffer [腎上腺EGLSUB]:本地緩衝區爲NULL

回答

2
出於某種原因,Android的崩潰,當我們使用IBO(索引緩衝區對象)與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); 
} 

編輯

我已經重新審視了一些OpenTK過去一週左右,我想它了!

GL.DrawElements()意味着要使用索引數據傳遞,如果你喜歡使用IBO,結合起來,你所顯示的,而是使用

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

我得到[腎上腺EGLSUB] :本機緩衝區爲NULL [Adreno-EGLSUB] :無效的本機緩衝區呃。無法將緩衝隊列爲錯誤並且沒有渲染 – Burf2000

+1

在模擬器中嘗試它,即時通訊很確定您獲取的錯誤與實際的物理設備有關,並且是單獨的問題 –

+0

我剛剛得到垃圾 – Burf2000

0

我知道這個線程是有點老了,但我一直在爭取這個問題了幾天,最後通過改變DrawElements的最後一個參數解決它調用IntPtr.Zero:

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