user10913773
user10913773

Reputation:

OPENGLES 20 ```GlUniform4fv``` method for coloring an object throwing an exception in C# Android

I am trying to draw a triangle shape in Android Xamarin with C#. The triangle is a class with the method draw. In this draw method, there is an openGL20 method for coloring the triangle object we just created. Whenever the execution in the draw method reaches this color object method, this exception is thrown Java.Lang.IllegalArgumentException Message=length - offset < count*4 < needed. I really can't understand what that error means but here is the code am using so far

 public class MyGLRenderer : Java.Lang.Object, GLSurfaceView.IRenderer
    {
     //Renderer method to draw the triangle object
       public void OnDrawFrame(IGL10 gl)
        {
            GLES20.GlClear(GLES20.GlColorBufferBit);
            Triangle triangle = new Triangle();
            triangle.draw();
        }
       //Method to set the view and the height of the painting window
          public void OnSurfaceChanged(IGL10 gl, int width, int height)
        {
            GLES20.GlViewport(0, 0, width, height);
        }
         public void OnSurfaceCreated(IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config)
        {
            //Set the background frame color
            GLES20.GlClearColor(0.0f, 0.0f, 1.0f, 0.0f);
            GLES20.GlDrawArrays(GLES20.GlColorBufferBit, 2, 10);
         }
    }

Code below defines the Triangle class and the OPENGL20 color method thats throwing an exception commented upon

 public class Triangle
    {
        private FloatBuffer vertexBuffer;

        //Number of co-ordinates per vertex in this context
        private static readonly int Coords_per_vert = 3;

        private static float[] triangleCoords = new float[] {
            0.0f,0.622008459f,0.0f, //top
            -0.5f,-0.311004243f,0f  , //bottom left
            0.5f, -0.311004243f,0.0f   //bottom right
        };

        //Set color with red, green, blue and alpha values
        private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f };

        private readonly int mProgram;

        public Triangle()
        {
            //Initialize vertex byte buffer for shape co-ordinates
            ByteBuffer bb = ByteBuffer.AllocateDirect(triangleCoords.Length * 4);
            //Use the device native byte order
            bb.Order(ByteOrder.NativeOrder());
            FloatBuffer myfloat = bb.AsFloatBuffer();
            //Create floating point buffer from ByteBuffer
            vertexBuffer = bb.AsFloatBuffer();
            vertexBuffer.Put(triangleCoords);
            vertexBuffer.Position(0);

            int vertexShader = MyGLRenderer.loadShader(GLES20.GlVertexShader, vertexShaderCode);
            int fragmentShader = MyGLRenderer.loadShader(GLES20.GlFragmentShader, fragmentShaderCode);
            //Create empty opengles program
            mProgram = GLES20.GlCreateProgram();
            //Add vertex shader to program
            GLES20.GlAttachShader(mProgram, vertexShader);
            //Add Fragment to shader
            GLES20.GlAttachShader(mProgram, fragmentShader);
            //Create openGL program executables
            GLES20.GlLinkProgram(mProgram);
        }

        private readonly string vertexShaderCode = "attribute vec4 vPosition;" +
                                                                                            "void main(){" +
                                                                                            "  gl_Position=vPosition;" +
                                                                                             "}";

        private readonly string fragmentShaderCode = "precision mediump float;" +
                                                                                                 "uniform vec4 vColor;" +
                                                                                                  "void main(){" +
                                                                                                    "gl_FragColor=vColor;" +
                                                                                                       "}";

        private int positionHandle, colorHandle;
        private readonly int vertexCount = triangleCoords.Length / Coords_per_vert;
        private readonly int vertexStride = Coords_per_vert * 4;

        //Create a method for drawing the triangle
        public void draw()
        {
            //Add Program to open GLES Environment
            GLES20.GlUseProgram(mProgram);
            //Get handle to vertex shader's vPosition member
            positionHandle = GLES20.GlGetAttribLocation(mProgram, "vPosition");
            //Enable a handle to the triangle's vertices
            GLES20.GlEnableVertexAttribArray(positionHandle);
            //Prepare the triangle co ordinate data
            GLES20.GlVertexAttribPointer(positionHandle, Coords_per_vert, GLES20.GlFloat, false, vertexStride, vertexBuffer);
            //Get handle to fragment shader's vColor Member
            colorHandle = GLES20.GlGetUniformLocation(mProgram, "vColor");
            //Set color for drawing the triangle
            GLES20.GlUniform4fv(colorHandle, 1, color, 3);
            
            //Draw the triangle, this method causes an exception
            GLES20.GlDrawArrays(GLES20.GlTriangles, 0, vertexCount);
            //Disable vertex array
            GLES20.GlDisableVertexAttribArray(positionHandle);
        }
    }

Please help me color the triangle object with success, what am i doing wrong

Upvotes: 2

Views: 142

Answers (1)

user14187680
user14187680

Reputation:

You are using a 3 sized float array for a vec4 uniform. Add the alpha array to your color array like this Replace

  private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f };

with

  private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f,1.0f};

with the last member of the second array representing the alpha or opacity of the color being drawn

Upvotes: 2

Related Questions