2015-06-21 50 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);