OpenGL или DirectX в VB .NET

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

MAGRAV
Новичок
Новичок
Аватара пользователя
 
Сообщения: 41
Зарегистрирован: 27.01.2011 (Чт) 11:57

OpenGL или DirectX в VB .NET

Сообщение MAGRAV » 07.11.2012 (Ср) 10:42

Доброго времени суток,

Столкнулся с проблемой, что стандартные GDI-графические возможности VB .NET не позволяют качественно и быстро отображать большой объём графических примитивов. Посредством объектов DrawArc и DrawLine рисую чертёж состоящий из нескольких тысяч дуг и линий. Результат заставляет ждать заметное для глаза количество времени, а дуги и вовсе не отображаются. Возможно ли воспользоваться библиотеками OpenGL или DirectX в VB .NET? Каковы преимущества и недостатки этих вариантов? Какой из них рекомендуете мне изучить?

Буду рад любой помощи в этом нелёгком деле.
Уходя с аэродрома прихвати деталь для дома.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: OpenGL или DirectX в VB .NET

Сообщение Хакер » 07.11.2012 (Ср) 10:54

Сколько надо туголегкомысленности иметь, чтобы поместить вопрос по богомерзкому вбнэту в раздел по классическому VB?

Перенесено.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: OpenGL или DirectX в VB .NET

Сообщение Mikle » 07.11.2012 (Ср) 13:01

MAGRAV писал(а):Возможно ли воспользоваться библиотеками OpenGL или DirectX в VB .NET? Каковы преимущества и недостатки этих вариантов? Какой из них рекомендуете мне изучить?

С шарпом или vb.net более естественно использовать DirectX, далее зависит от задачи - если это разовая работа, то достаточно взять ManagedDX, он наиболее прост. А если планируется и дальше программировать на DirectX под .net, то лучше взять более перспективные SlimDX или, особенно, SharpDX.
Единственный недостаток вижу в том, что любой из этих портов DirectX на целевой машине нужно устанавливать, изначально их нет.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 07.11.2012 (Ср) 19:44

WPF, кажется, использует другой принцип работы с графикой по сравнению с WinForms. Может стоит попытаться использовать его?
И ещё, ты рисуешь на форме или в BitMap?

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: OpenGL или DirectX в VB .NET

Сообщение FireFenix » 08.11.2012 (Чт) 1:45

Qwertiy писал(а):WPF, кажется, использует другой принцип работы с графикой по сравнению с WinForms

WPF - DirectX 9
WinForms - GDI+

Mikle писал(а):взять более перспективные SlimDX или, особенно, SharpDX.

Так же кучу всякого под OGL: CsGL, SharpGL и прочие
Главное определиться и начать изучать. И со временем всё придёт =)
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

MAGRAV
Новичок
Новичок
Аватара пользователя
 
Сообщения: 41
Зарегистрирован: 27.01.2011 (Чт) 11:57

Re: OpenGL или DirectX в VB .NET

Сообщение MAGRAV » 08.11.2012 (Чт) 17:13

Qwertiy писал(а):WPF, кажется, использует другой принцип работы с графикой по сравнению с WinForms. Может стоит попытаться использовать его?
И ещё, ты рисуешь на форме или в BitMap?

Я рисую на форме :D

FireFenix писал(а):Главное определиться и начать изучать. И со временем всё придёт =)

Я и рад бы, да времени свободного не вагон, а скоре маленькая тележка. Хотелось бы выбрать лучший вариант применительно к VB .NET.
Уходя с аэродрома прихвати деталь для дома.

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: OpenGL или DirectX в VB .NET

Сообщение Admiralisimys » 08.11.2012 (Чт) 17:23

MAGRAV писал(а):
Qwertiy писал(а):И ещё, ты рисуешь на форме или в BitMap?

Я рисую на форме :D

Вот, тогда по наводящему вопросу Qwertiy рисуй в Bitmap'е, тогда сам непосредственно вывод не будет зависеть от сложности рисунка.
Пример ScribbleWithBitmap.vb

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.11.2012 (Чт) 19:41

MAGRAV писал(а):Я рисую на форме :D

Раз часть элементов пропадает, возникает подозрение, что ты это делаешь не в обрпаботчике события Paint и/или используешь метод CreateGraphics, причём, возможно, для каждого объекта или группы объектов. Ни то, ни другое делать не надо. Надо использовать обработчик Paint и e.Graphics.

И да, попробуй рисовать в BitMap, а потом его отображать. Если рисунок не делается один раз и меняется редко, то проблем с производительностью вообще не должно быть.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 08.11.2012 (Чт) 19:46

Admiralisimys писал(а):Пример ScribbleWithBitmap.vb

Извращение, по-моему...

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: OpenGL или DirectX в VB .NET

Сообщение Admiralisimys » 11.11.2012 (Вс) 23:04

Qwertiy технологию с этого примера я было решил попробовать аж один раз
Код: Выделить всё
Imports System
Imports System.Drawing
Imports System.Windows.Forms

Class Satelite
    Private orbCent As PointF = PointF.Empty
    Private orbRadius As Single = 0.0F
    Private satRadius As Single = 0.0F
    Private clr As Color = Color.Black
    Private br As Brush = Nothing
    Private vel As Single = 0.0F
    Private angelFi As Single = 0.0F
    Private pos As PointF = PointF.Empty

    Public Property OrbitCenter() As PointF
        Get
            Return orbCent
        End Get
        Set(value As PointF)
            orbCent = value
        End Set
    End Property

    Public Property OrbitRadius() As Single
        Get
            Return orbRadius
        End Get
        Set(value As Single)
            orbRadius = value
        End Set
    End Property

    Public Property Radius() As Single
        Get
            Return satRadius
        End Get
        Set(value As Single)
            satRadius = value
        End Set
    End Property

    Public Property Color() As Color
        Get
            Return clr
        End Get
        Set(value As Color)
            clr = value
            If br IsNot Nothing Then
                br.Dispose()
                br = Nothing
            End If
            br = New SolidBrush(clr)
        End Set
    End Property

    Public Property Velocity() As Single
        Get
            Return vel
        End Get
        Set(value As Single)
            vel = value
        End Set
    End Property

    Public Property Position As PointF
        Get
            Return pos
        End Get
        Set(value As PointF)
            pos = value
        End Set
    End Property

    Public Sub update(ByRef parentCtr As Control)
        'parentCtr.Invalidate(New Rectangle(Position.X - 2 * Radius, Position.Y - 2 * Radius, _
        '                                Position.X + 2 * Radius, Position.Y + 2 * Radius))
        angelFi += Velocity
        If (angelFi >= 2 * Math.PI) Then
            angelFi = 0.0F
        ElseIf (angelFi < 0) Then
            angelFi = 2 * Math.PI
        End If
        Position = New PointF(OrbitCenter.X + OrbitRadius * Math.Cos(angelFi), _
                              OrbitCenter.Y + OrbitRadius * Math.Sin(angelFi))
    End Sub

    Public Sub draw(ByRef grfx As Graphics)
        If br IsNot Nothing Then
            grfx.FillEllipse(br, Position.X - satRadius, _
                                 Position.Y - satRadius, _
                                 2 * satRadius, 2 * satRadius)
        End If
    End Sub

End Class

Class CircleAroundAnother
    Inherits Form
    Private tmr As New Timer
    Private sat(10) As Satelite
    Private bm As Bitmap
    Private grfxBm As Graphics

    <STAThread()> Public Shared Sub Main()
        Application.Run(New CircleAroundAnother())
    End Sub

    Public Sub New()
        Me.WindowState = FormWindowState.Maximized
    End Sub

    Protected Overrides Sub OnLoad(ByVal ea As EventArgs)
        MyBase.OnLoad(ea)

        bm = New Bitmap(ClientSize.Width, ClientSize.Height)
        grfxBm = Graphics.FromImage(bm)

        Dim rand As New Random(DateTime.Now.Millisecond)
        Dim center As New PointF(Me.ClientSize.Width / 2, Me.ClientSize.Height / 2)
        For i As Integer = 0 To sat.Length() - 1
            sat(i) = New Satelite()
            sat(i).Color = Color.FromArgb(255, rand.Next(255), rand.Next(255), rand.Next(255))
            sat(i).OrbitCenter = center
            sat(i).OrbitRadius = rand.Next(5, 500)
            sat(i).Radius = rand.Next(5, 50)
            sat(i).Velocity = 0.025 * rand.NextDouble()
        Next i

        tmr.Interval = 25
        tmr.Enabled = True
        AddHandler tmr.Tick, AddressOf TimerOnTick
    End Sub

    Private Sub TimerOnTick(ByVal obj As Object, ByVal ea As EventArgs)
        For Each st In sat
            If st IsNot Nothing Then st.update(Me)
        Next st
        'Invalidate()

        grfxBm.Clear(BackColor)
        For Each st In sat
            If st IsNot Nothing Then st.draw(grfxBm)
        Next st
        Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal pea As PaintEventArgs)
        'Dim grfx As Graphics = pea.Graphics
        'For Each st In sat
        '    If st IsNot Nothing Then st.draw(grfx)
        'Next st

        Me.BackgroundImage = bm
    End Sub

End Class

Однако неприятный эффект, который наблюдался как при Invalidate() для всей клиентской области, так и при выделенной области под объект parentCtr.Invalidate(...) (хоть в цикле OnPaint там все объекты пройдут сквозь, однако нарисуются лишь те, с координатами попадающими в заданный Rectangle) остаётся.
Мне не подошло, но ведь автору может и подойдёт.

Примером ScribbleWithBitmap.vb хотел показать технологию переключения "back" буфера.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 12.11.2012 (Пн) 14:53

Код отвратительный. И при переопределении метолдов надо вызывать соотвуетствующие методы ролдителя. Потом покажу, как сделать без мигания.

MAGRAV
Новичок
Новичок
Аватара пользователя
 
Сообщения: 41
Зарегистрирован: 27.01.2011 (Чт) 11:57

Re: OpenGL или DirectX в VB .NET

Сообщение MAGRAV » 12.11.2012 (Пн) 16:25

Вот часть кода как я пытаюсь работать:
Код: Выделить всё
    Public Sub PainPicture(ByVal X_min, ByVal X_max, ByVal Y_min, ByVal Y_max)
        Dim a1, b1, a2, b2, X1, X2, Y1, Y2 As Double
        Dim Alfa, DeltaAlfa, Angle, Angle1, Angle2, AnglePointOnArc1, AnglePointOnArc2 As Double

        'Dim e As Graphics = PictureBox1.CreateGraphics
        Dim Pen As New System.Drawing.Pen(System.Drawing.Color.White, Width:=1) 'Задаём цвет и толщину пера


        Pen.DashStyle = Drawing2D.DashStyle.Solid 'Тип пера

        For i = 1 To ChisloGeomPrimitive
            If TypeGeomPrimitive(i) = 110 Then 'ОТРИСОВКА ЛИНИИ
                X1 = FormatX(AAA, X1_GeomPrimitive(i), X_min, X_max)
                Y1 = FormatY(AAA, Y1_GeomPrimitive(i), Y_min, Y_max)
                X2 = FormatX(AAA, X2_GeomPrimitive(i), X_min, X_max)
                Y2 = FormatY(AAA, Y2_GeomPrimitive(i), Y_min, Y_max)
                PictureBox1.CreateGraphics.DrawLine(Pen, Convert.ToSingle(X1), Convert.ToSingle(Y1), Convert.ToSingle(X2), Convert.ToSingle(Y2))
            End If
            If TypeGeomPrimitive(i) = 150 Then 'ОТРИСОВКА ДУГИ

                AnglePointOnArc(AnglePointOnArc1, Angle1, X0_GeomPrimitive(i), Y0_GeomPrimitive(i), X1_GeomPrimitive(i), Y1_GeomPrimitive(i)) 'угол образуемый при участии точки №1
                AnglePointOnArc(AnglePointOnArc2, Angle2, X0_GeomPrimitive(i), Y0_GeomPrimitive(i), X2_GeomPrimitive(i), Y2_GeomPrimitive(i)) 'угол образуемый при участии точки №2

                If (Y0_GeomPrimitive(i) = Y1_GeomPrimitive(i) And Y0_GeomPrimitive(i) = Y2_GeomPrimitive(i)) Or _
                   (X0_GeomPrimitive(i) = X1_GeomPrimitive(i) And X0_GeomPrimitive(i) = X2_GeomPrimitive(i)) Then 'проверка на совпадение точек образующих дугу.
                    Angle = AnglePointOnArc1 : AnglePointOnArc2 = Angle + 2 * Pi()
                    b1 = lengthLine(Y0_GeomPrimitive(i), Y1_GeomPrimitive(i))
                    a1 = lengthLine(X0_GeomPrimitive(i), X1_GeomPrimitive(i))
                    If i = 1 Then
                        i = 2
                    End If
                    GoTo next_i
                    'ElseIf (Angle1 = 0 Or Pi() / 2 Or Pi() Or 3 * Pi() / 2 Or 2 * Pi()) And _
                    '      (Angle2 = 0 Or Pi() / 2 Or Pi() Or 3 * Pi() / 2 Or 2 * Pi()) Then
                ElseIf (AnglePointOnArc1 = 0 Or AnglePointOnArc1 = Pi() / 2 Or AnglePointOnArc1 = Pi() Or AnglePointOnArc1 = 3 * Pi() / 2 Or AnglePointOnArc1 = 2 * Pi()) And _
                   (AnglePointOnArc2 = 0 Or AnglePointOnArc2 = Pi() / 2 Or AnglePointOnArc2 = Pi() Or AnglePointOnArc2 = 3 * Pi() / 2 Or AnglePointOnArc2 = 2 * Pi()) Then
                    'If Angle2 = 0 Or Pi() Or 2 * Pi() Then
                    If AnglePointOnArc2 = 0 Or AnglePointOnArc2 = Pi() Or AnglePointOnArc2 = 2 * Pi() Then
                        a1 = WidthCircle(X0_GeomPrimitive(i), X1_GeomPrimitive(i), AnglePointOnArc1) 'lengthLine(X0_GeomPrimitive(i), X1_GeomPrimitive(i))
                        b1 = HeightCircle(Y0_GeomPrimitive(i), Y2_GeomPrimitive(i), AnglePointOnArc2) 'lengthLine(Y0_GeomPrimitive(i), Y2_GeomPrimitive(i))
                        'ElseIf Angle2 = Pi() / 2 Or 3 * Pi() / 2 Then
                    ElseIf AnglePointOnArc2 = Pi() / 2 Or AnglePointOnArc2 = 3 * Pi() / 2 Then
                        a1 = WidthCircle(X0_GeomPrimitive(i), X2_GeomPrimitive(i), AnglePointOnArc2) 'lengthLine(X0_GeomPrimitive(i), X2_GeomPrimitive(i))
                        b1 = HeightCircle(Y0_GeomPrimitive(i), Y1_GeomPrimitive(i), AnglePointOnArc1) 'lengthLine(Y0_GeomPrimitive(i), Y1_GeomPrimitive(i))
                    End If
                    If i = 1 Then
                        i = 2
                    End If
                    GoTo next_i
                    'ElseIf Angle1 = 0 Or Pi() / 2 Or Pi() Or 3 * Pi() / 2 Or 2 * Pi() Then 'проверка на равность Angle1 ={0;90;180;270;360}grad
                ElseIf AnglePointOnArc1 = 0 Or AnglePointOnArc1 = Pi() / 2 Or AnglePointOnArc1 = Pi() Or AnglePointOnArc1 = 3 * Pi() / 2 Or AnglePointOnArc1 = 2 * Pi() Then
                    Angle = AnglePointOnArc2
                    b1 = HeightCircle(Y0_GeomPrimitive(i), Y2_GeomPrimitive(i), Angle) 'высота элепса которому пренадлежит дуга
                    a1 = WidthCircle(X0_GeomPrimitive(i), X2_GeomPrimitive(i), Angle) 'ширина элепса которому пренадлежит дуга
                    If i = 1 Then
                        i = 2
                    End If
                    GoTo next_i
                    'ElseIf Angle2 = 0 Or Pi() / 2 Or Pi() Or 3 * Pi() / 2 Or 2 * Pi() Then 'проверка на равность Angle2 ={0;90;180;270;360}grad
                ElseIf AnglePointOnArc2 = 0 Or AnglePointOnArc2 = Pi() / 2 Or AnglePointOnArc2 = Pi() Or AnglePointOnArc2 = 3 * Pi() / 2 Or AnglePointOnArc2 = 2 * Pi() Then
                    Angle = AnglePointOnArc1
                    b1 = HeightCircle(Y0_GeomPrimitive(i), Y1_GeomPrimitive(i), Angle)
                    a1 = WidthCircle(X0_GeomPrimitive(i), X1_GeomPrimitive(i), Angle)
                    If i = 1 Then
                        i = 2
                    End If
                    GoTo next_i
                Else 'общий случай
                    Angle = AnglePointOnArc1
                    b1 = HeightCircle(Y0_GeomPrimitive(i), Y1_GeomPrimitive(i), Angle)
                    a1 = WidthCircle(X0_GeomPrimitive(i), X1_GeomPrimitive(i), Angle)
                    If i = 1 Then
                        i = 2
                    End If
                End If
                'Format(Angle2, "0.00000000") = Format(2 * Pi(), "0.00000000")
next_i:
                If i = 2 Then
                    i = i
                End If
                X1 = FormatX(AAA, X0_GeomPrimitive(i), X_min, X_max) 'центр дуги по X
                Y1 = FormatY(AAA, Y0_GeomPrimitive(i), Y_min, Y_max) 'центр дуги по Y
                X2 = FormatX(AAA, Math.Abs(2 * a1), X_min, X_max) 'ширина дуги по X
                X2 = Math.Abs(X2)
                Y2 = FormatY(AAA, Math.Abs(2 * b1), Y_min, Y_max) 'ширина дуги по Y
                Y2 = Math.Abs(Y2)
                Alfa = AnglePointOnArc1 * 180 / Pi() 'угол начала отсчёта дуги
                DeltaAlfa = Delta(AnglePointOnArc1, AnglePointOnArc2) * 180 / Pi() 'угол прохода линии от начала отсчёта дуги
                On Error Resume Next
                If i = 2 Then
                    i = i
                End If
                PictureBox1.CreateGraphics.DrawArc(New Pen(Color.White, Width:=1), Convert.ToSingle(X1), Convert.ToSingle(Y1), _
                                                          Convert.ToSingle(X2), Convert.ToSingle(Y2), _
                                                          Convert.ToSingle(-Alfa), Convert.ToSingle(-DeltaAlfa))
                If i = 1 Then
                    i = i
                End If
            End If
            If i = 2 Then
                i = i
            End If
        Next i

        Beep() 'Звуковой сигнал
    End Sub


Все ваши замечания важны для меня!
Уходя с аэродрома прихвати деталь для дома.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: OpenGL или DirectX в VB .NET

Сообщение FireFenix » 12.11.2012 (Пн) 19:47

Код: Выделить всё
GoTo next_i

Изображение
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 12.11.2012 (Пн) 22:37

Плохо создавать перья в цикле. Создай один раз и используй.

MAGRAV
Новичок
Новичок
Аватара пользователя
 
Сообщения: 41
Зарегистрирован: 27.01.2011 (Чт) 11:57

Re: OpenGL или DirectX в VB .NET

Сообщение MAGRAV » 13.11.2012 (Вт) 20:27

Qwertiy писал(а):покажу, как сделать без мигания.

Буду ждать с нетерпением!
Уходя с аэродрома прихвати деталь для дома.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 13.11.2012 (Вт) 23:25

MAGRAV писал(а):
Qwertiy писал(а):покажу, как сделать без мигания.

Буду ждать с нетерпением!

По-моему, гораздо лучше :)

Test - Circles.7z
VS2010 Solution
(30.7 Кб) Скачиваний: 345

Admiralisimys
Постоялец
Постоялец
 
Сообщения: 318
Зарегистрирован: 01.06.2009 (Пн) 10:26

Re: OpenGL или DirectX в VB .NET

Сообщение Admiralisimys » 14.11.2012 (Ср) 2:03

Qwertiy да, спасибо, действительно неприятное "подмигивание" исчезло.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.08.2013 (Пт) 11:39

Qwertiy писал(а):Test - Circles.7z

Кажется, я понял, почему остаётся шевеление краёв у быстродвижущихся кругов. Перерисовка происходит по двум bounding-box'ам, поэтому круг меняется дважды. Скорее всего, если эти bounding-box'ы объединить в один, оно исчезнет. Если будет время, проверю и выложу поправленный вариант.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: OpenGL или DirectX в VB .NET

Сообщение FireFenix » 23.08.2013 (Пт) 22:23

Воу воу, паринь палехче. Уже год прошёл :D
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.08.2013 (Пт) 22:51

FireFenix писал(а):Воу воу, паринь палехче. Уже год прошёл :D

Во-первых, ещё не прошёл, а во-вторых, если ты не заметил, то пример был мой ;)


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList