Почему я не могу установить параметры Texture Wrap с помощью OpenGL в C#? (библиотека SharpGL)

Я разрабатывал метод раскрашивания (я австралиец) вершин цифровой модели местности в приложении WPF с использованием SharpGL. Проблема, с которой я столкнулся, заключается в том, что я не могу изменить параметры GL_TEXTURE_WRAP_T и S на что-либо, кроме GL_REPEAT, используя метод TexParameter, прикрепленный к активному экземпляру OpenGL.

Если я не могу установить обтекание текстуры на GL_CLAMP_TO_EDGE, то при доступе к самому низкому цвету я получу обтекание самого высокого цвета, если только я не сдвину координаты текстуры на полпикселя (что неуклюже, но я понимаю, что это сработает).

В настоящее время окно отображается следующим образом:

Текущий неверный результат

Когда он должен иметь радугу в средней трети с сплошным красным в верхней трети и синим в нижней трети.

Я знаю, что правильно использую метод TexParameter, потому что могу успешно манипулировать параметрами GL_TEXTURE_MIN_FILTER и GL_TEXTURE_MAG_FILTER для одной и той же текстуры. Единственное, о чем я могу думать, это то, что в экземпляре OpenGL нужно что-то включить, чтобы иметь возможность изменять параметры наложения текстуры.

Я приложил весь тестовый код C# и код WPF xaml, чтобы воссоздать проблему. В строках 52 и 53 вызывается метод. Любая помощь, которую я могу получить, будет очень признательна.

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);
        }
    }
}

Вот xaml-код:

<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>

person Ross Batten    schedule 13.12.2017    source источник


Ответы (1)


Я нашел ответ. Я использовал версию OpenGL, которая не поддерживала «GL_CLAMP_TO_EDGE» для переноса текстур, и код работал после замены на просто «GL_CLAMP», более старый эквивалент.

Изменить: я нашел ответ AN, но неполный.

person Ross Batten    schedule 13.12.2017
comment
Это не эквивалентно; вот почему для него есть другое имя. GL_CLAMP фиксирует тексели границы. GL_CLAMP_TO_EDGE прижимается к краю текстуры. - person Nicol Bolas; 13.12.2017
comment
Однако использование GL_CLAMP_TO_EDGE ничего не дало, равно как и GL_CLAMP_TO_BORDER. Я думал, что прижатие к границе устанавливает внешние координаты текстуры диапазона 0-1 в предустановленный цвет? - person Ross Batten; 15.12.2017
comment
Я сказал зажимы для границы texels. Еще во времена GL 1.1 в текстурах использовалось понятие граничных текселей. Вы можете добавить к текстурам дополнительные пиксели по краям, которые будут сэмплированы, только если вы используете GL_CLAMP. То есть, вместо одного цвета границы (что делает GL_CLAMP_TO_BORDER) или привязки к краю текстуры (что делает GL_CLAMP_TO_EDGE), вы фиксируете тексели границы, ближайшие к точке выборки. Так что они не эквивалентны. - person Nicol Bolas; 15.12.2017
comment
Ах я вижу. Итак, есть идеи, почему GL_CLAMP_TO_EDGE ничего не делает для меня? Моя проблема выше? Я использую OpenGL версии 3.1, поэтому он должен поддерживаться. - person Ross Batten; 15.12.2017