1

I've been building a method to colour (I'm Australian) vertices of a digital terrain model in a WPF app using SharpGL. The problem I'm facing is that I can't seem to change the GL_TEXTURE_WRAP_T and S parameters to anything other than GL_REPEAT using the TexParameter method attached to the active OpenGL instance.

If I can't set the texture wrapping to GL_CLAMP_TO_EDGE then I'll get a bleed of the highest colour when accessing the lowest colour unless I offset the texture coordinates by half a pixel (which is clunky but I understand it will work).

The window currently renders like this:

Current wrong result

When it should have the rainbow in the middle third with solid red in the top third and blue in the bottom third.

I know that I'm using the TexParameter method correctly because I can manipulate the GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER parameters for the same texture successfully. The only thing I can think of is that there's something needs enabling in the OpenGL instance to be able to change the texture wrapping parameters.

I've attached the entire C# test code and WPF xaml code to be able to recreate the problem. Line 52 and 53 are where the method is called. Any help I can get would be hugely appreciated.

using SharpGL;
using System.Windows;
using System.Drawing;
using SharpGL.SceneGraph.Assets;

namespace WpfApplication3
{
    public partial class MainWindow : Window
    {
        Bitmap bitmap;
        Texture texture;

        public MainWindow()
        {
            InitializeComponent();

            //Create a 5-pixel wide bitmap to be used as the texture
            bitmap = new Bitmap(5, 1);
            bitmap.SetPixel(0, 0, Color.Red);
            bitmap.SetPixel(1, 0, Color.Yellow);
            bitmap.SetPixel(2, 0, Color.Green);
            bitmap.SetPixel(3, 0, Color.Cyan);
            bitmap.SetPixel(4, 0, Color.Blue);
        }

        private void GLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
        {
            OpenGL gl = args.OpenGL;

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

            //Set an ortho projection to be able to see the entire square
            gl.MatrixMode(OpenGL.GL_PROJECTION);
            gl.LoadIdentity();
            gl.Ortho(-2, 2, -2, 2, -2, 2);

            gl.MatrixMode(OpenGL.GL_MODELVIEW);

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

            texture.Bind(gl);

            gl.Enable(OpenGL.GL_TEXTURE_2D);

            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, OpenGL.GL_CLAMP_TO_EDGE);
            gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, OpenGL.GL_CLAMP_TO_EDGE);
            //gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, OpenGL.GL_NEAREST);
            //gl.TexParameter(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, OpenGL.GL_NEAREST);

            //Draw the square
            gl.Begin(OpenGL.GL_QUADS);

            gl.Color(1.0f, 1.0f, 1.0f, 1.0f);

            //Texture coordinate outside of 0-1 range to test wrapping method
            gl.TexCoord(-1, 0.5);
            gl.Vertex(1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            //Texture coordinate outside of 0-1 range to test wrapping method
            gl.TexCoord(2, 0.5);
            gl.Vertex(-1.0f, -1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);

            gl.End();

            gl.Disable(OpenGL.GL_TEXTURE_2D);

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

        private void GLInitialize(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
        {
            OpenGL gl = args.OpenGL;
            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);

            texture = new Texture();
            texture.Create(gl, bitmap);
        }
    }
}

Here's the xaml code:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication3"
        xmlns:sharpGL="clr-namespace:SharpGL.WPF;assembly=SharpGL.WPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <sharpGL:OpenGLControl OpenGLVersion="OpenGL3_2" OpenGLDraw="GLDraw" OpenGLInitialized="GLInitialize" Cursor="Cross"
                               Background="Transparent"/>
    </Grid>
</Window>
Ross Batten
  • 114
  • 8

1 Answers1

0

I found the answer. I was using a version of OpenGL which didn't support "GL_CLAMP_TO_EDGE" for texture wrapping and the code worked after changing it to simply "GL_CLAMP", the older equivalent.

Edit: I found AN answer but an incomplete one.

Ross Batten
  • 114
  • 8
  • It's not equivalent; that's why there's a different name for it. `GL_CLAMP` clamps to the border texels. `GL_CLAMP_TO_EDGE` clamps to the edge of the texture. – Nicol Bolas Dec 13 '17 at 15:01
  • Using GL_CLAMP_TO_EDGE didn't do anything though, nor did GL_CLAMP_TO_BORDER. I thought clamping to border set the outside 0-1 range texture coordinates to a preset colour? – Ross Batten Dec 14 '17 at 23:42
  • I said "clamps to border *texels*". Back in the GL 1.1 days, textures had this notion of "border texels". You could give textures extra pixels around the edges of them, which would only be sampled from if you were using `GL_CLAMP`. That is, rather than a single border color (what `GL_CLAMP_TO_BORDER` does) or clamp to the edge of the texture (what `GL_CLAMP_TO_EDGE` does), you clamp to the border texels nearest the sampling point. So they're not equivalent. – Nicol Bolas Dec 14 '17 at 23:47
  • Ah I see. So any idea why GL_CLAMP_TO_EDGE doesn't do anything for me? My problem above? I'm using OpenGL version 3.1 so it should be supported – Ross Batten Dec 15 '17 at 01:35