bas
bas

Reputation: 1678

Bad Performance of sharpGL inside WPF

I have followed a SharpGL tutorial that can display a rotating block. Initially this only had default colors drawn on it with gl.Color(r, g, b). After this succeeded I tried to texture the cube with an uv map.

When I run the application fullscreen while only coloring the cube (with the sharpGL component covering the entire inside of the application) I get 70~80 fps only for displaying a colored cube. When I enable OpenGL.GL_TEXTURE_2D and draw the textures on a singular cube I get 8~9 fps.

Whenever a bitmap is loaded for use as a texture, it is stored in the memory. This drop in framerates only occurs after I enable OpenGL.GL_TEXTURE_2D and call gl.TexCoord(c1, c2) for all coordinates. Actually moving the object with gl.Rotate(angle, x, y, z) does not noticably affect performance.

The provided data for the method including GetBlockUv and CubeCoordinates are static float-arrays.

Is SharpGL supposed to perform this poorly (i.e. on displaying a singular cube) or is there another reason? Am I doing something wrong that is affecting performance? Is applying textures supposed to affect the performance like that?

The main draw Event happens in a Block:

public void DrawBlock(object sender, OpenGLEventArgs args)
    {
        //  Get the OpenGL instance that's been passed to us.
        OpenGL gl = args.OpenGL;

        //  Reset the modelview.
        gl.LoadIdentity();

        //  Move the block to its location
        gl.Translate(Coord.X, Coord.Y, Coord.Z);

        gl.Rotate(angle, 1.0f, 1.0f, 0.5f);
        angle += 3;

        // retrieve the right texture for this block and bind it. 
        Texture blockTex = BlockTexture.GetBlockTexture(gl, _type);
        blockTex.Bind(gl);

        // retrieve the uv map for this block
        float[] uv = BlockTexture.GetBlockUv(_type);

        // retrieve the coordinates for a cube
        float[] cube = CubeCoordinates();


        gl.Enable(OpenGL.GL_TEXTURE_2D);

        //  Draw the cube with the bound texture. 
        gl.Begin(OpenGL.GL_QUADS);
        //
        //
        // Begin by allowing all colors. 
        gl.Color(1.0f, 1.0f, 1.0f);

        // since the uv index increments with 2 each time, we will be keeping track of this separately. 
        int uvInd = 0;

        // i denotes the current coordinate. Each coordinate consists of 3 
        // values (x, y, z), thus letting us skip 3. 
        //
        // Seeing as we are creating quads, it is expected that cube.Length 
        // is 3 * 4 * N (where n is a whole number)
        for (int i = 0; i < cube.Length; i += 3)
        {
            // color experiment
            //if (i < cube.Length / 3)
            //{
            //    gl.Color(1.0f, 0.00f, 0.00f);
            //}
            //else if (i < 2 * (cube.Length / 3))
            //{
            //    gl.Color(0.0f, 1.0f, 0.0f);
            //}
            //else
            //{
            //    gl.Color(0.0f, 0.0f, 1.0f);
            //}

            try
            {
                // set the coordinate for the texture
                gl.TexCoord(uv[uvInd], uv[uvInd + 1]);

                // set the vertex
                gl.Vertex(cube[i], cube[i + 1], cube[i + 2]);
            }
            catch (IndexOutOfRangeException e)
            {
                throw new IndexOutOfRangeException(
                    "This exception is thrown because the cube map and uv map do not match size");
            }

            // increment the uv index
            uvInd += 2;
        }

        gl.End();
        gl.Disable(OpenGL.GL_TEXTURE_2D);
    }

OpenGL is initialized elsewhere

 private void OpenGLControl_OpenGLDraw(object sender, OpenGLEventArgs args)
    {
        //  Get the OpenGL instance that's been passed to us.
        OpenGL gl = args.OpenGL;

        //  Clear the color and depth buffers.
        gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);


        // call the draw method of the GameRunner if the 
        // GameRunner has already been created. 
        game?.DrawOpenGL(sender, args);


        //  Flush OpenGL.
        gl.Flush();
    }

    private void OpenGLControl_OpenGLInitialized(object sender, OpenGLEventArgs args)
    {
        //  Enable the OpenGL depth testing functionality.
        args.OpenGL.Enable(OpenGL.GL_DEPTH_TEST);
    }

All the intermediate GameRunner does right now is call the DrawBlock routine.

What I mainly would want to know is some insight into the performance I can expect of openGL / sharpGL and whether there are better alternatives. I would like to keep using the WPF architecture surrounding the game, but if openGL inside WPF is more meant as a gimmick, that might not be the best course of action.

Upvotes: 0

Views: 2326

Answers (1)

Adsolution
Adsolution

Reputation: 31

I've been having the exact same issue, and it seems to be the case that either SharpGL or the WPF control itself are using software rendering. I tested this by disabling my main display adapter in Device Manager and got the exact same performance as I did with it enabled.

I don't know how to enable hardware acceleration though, so I don't actually know how to fix the issue.

Upvotes: 1

Related Questions