Quantcast
Channel: SharpGL
Viewing all articles
Browse latest Browse all 104

New Post: SharpGL FBO and High Res Texture Question

$
0
0
First and foremost I would like to thank Dave Kerr for all his work on the SharpGL project. I would also like to thank him for posting his source code so that novices such as myself can learn. My initial question was why can't I use a texture where the initial image was 8000x4000 pixels. I've been dancing around the solution for a few days now and finally pinned it down to code in the "Texture" class of the SharpGL.SceneGraph project. More specifically in "Create" method of the SharpGL.SceneGraph.Assets.Texture code.
        /// <summary>
        /// This function creates the texture from an image.
        /// </summary>
        /// <param name="gl">The OpenGL object.</param>
        /// <param name="image">The image.</param>
        /// <returns>True if the texture was successfully loaded.</returns>
        public virtual bool Create(OpenGL gl, Bitmap image)
        {
            //  Create the underlying OpenGL object.
            Create(gl);

            //  Get the maximum texture size supported by OpenGL.
            int[] textureMaxSize = { 0 };
            gl.GetInteger(OpenGL.GL_MAX_TEXTURE_SIZE, textureMaxSize);

            //  Find the target width and height sizes, which is just the highest
            //  posible power of two that'll fit into the image.

            int targetWidth = textureMaxSize[0];
            int targetHeight = textureMaxSize[0];

            for (int size = 1; size <= textureMaxSize[0]; size *= 2)
            {
                if (image.Width < size)
                {
                    targetWidth = size / 2;
                    break;
                }
                if (image.Width == size)
                    targetWidth = size;

            }

            for (int size = 1; size <= textureMaxSize[0]; size *= 2)
            {
                if (image.Height < size)
                {
                    targetHeight = size / 2;
                    break;
                }
                if (image.Height == size)
                    targetHeight = size;
            }

            //  If need to scale, do so now.
            if (image.Width != targetWidth || image.Height != targetHeight)
            {
                System.Windows.Forms.MessageBox.Show("IWidth: " + image.Width.ToString() + "  IHeight: " + image.Height.ToString() + " TWidth: " + targetWidth.ToString() + " THeight: " + targetHeight.ToString());

                //  Resize the image.
                Image newImage = image.GetThumbnailImage(targetWidth, targetHeight, null, IntPtr.Zero);

                //  Destory the old image, and reset.
                image.Dispose();
                image = (Bitmap)newImage;
            }

            //  Lock the image bits (so that we can pass them to OGL).
            BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            //  Set the width and height.
            width = image.Width;
            height = image.Height;

            //  Bind our texture object (make it the current texture).
            gl.BindTexture(OpenGL.GL_TEXTURE_2D, TextureName);

            //  Set the image data.
            gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGBA,
                width, height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE,
                bitmapData.Scan0);

            //  Unlock the image.
            image.UnlockBits(bitmapData);

            //  Dispose of the image file.
            image.Dispose();

            //  Set linear filtering mode.
            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_LINEAR);
            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_LINEAR);

            //  We're done!
            return true;
        }
The first thing this code does is to get the Max Texture Size form the current OpenGL context. In my case that is 16384. Then it runs through two loops calculating powers of 2 (stored in the "size" variable) from 1 to the Max Texture Size (1, 2, 4, 8, 16, ... 1024, 2048, 4096, 8192, ...) till the power of 2 was greater than the image height or width (depending on the loop). When the power of 2 jumps beyond the image size, it divides the power of 2 or "size" by 2 to get the largest power of 2 not greater than the image size. Where this hoses me for my width is the loop counts up to 8192 which is greater than my width of 8000 and then divides that by 2 which ends up being 4096. The same thing happens for my height of 4000. The code loops through to 4096 which is greater than 4000, so it divides by two and returns 2048. 4096x2048 is just over half the resolution of my image.

The code then goes on to compare the "targetWidth" and "targetHeight" to the image width and height. If they don't match, the code then re-samples the image to the "targetWidth" and "targetHeight" which ends giving me a texture at a little over 1/2 my initial resolution. My work around is to let it do its thing and then just set the "targetWidth" and "targetHeight" to my image's width and height prior to the code that ordinarily would re-scale the image / texture.

I have learned a lot from Mr. Kerr's code. However the most important thing I've learned is that I still have a lot to learn.

Respectfully;


Windknot

Viewing all articles
Browse latest Browse all 104

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>