
Newbie qeustion and a potential bug
Posted Friday, 12 December, 2008 - 11:08 by eths inHello,
As a newbie to the world of OpenGL, I have started to teach myself a bit about OpenGL using OpenTK on a Windows XP Professional system with a NVidia GeForce 6600 graphic card. I am including one of my experiments as a bit VB.Net code written with VisualStudio 2005 (Microsoft .Net 2.0).
1) Potentialbug: When I move windows from other applications around, the GlControls appear to loose or shift their internal GL coordinate systems. I've attached screen shots of this.
2) They also do not redraw correctly if they have been hidden by another widow, but this may well be a GL problem, meaning I would need to do my own redraw.
3) There must be a kinder, gentler way of scrolling a "waterfall" display, than using GL.CopyPixels especially if (some) redraws (see above) must be be done by myself. Is there an easy way of drawing to my own buffers and then moving them screen buffers? I haven't been able to figure out how to do this (yet).
4) GL.CopyPixels can be very slow at times, which I why I ended up doing the copy in chunks. Is this a good or a poor method for doing these kinds of stuff in GL.
Thank you!
Option Strict On Option Explicit On Imports OpenTK Imports OpenTK.Graphics Imports OpenTK.Math Imports System Imports System.Collections.Generic Imports System.Text Imports System.IO Imports System.Drawing Public Class Form1 Private hasLoaded As Boolean = False Public Shared Event Idle As EventHandler Private handler As New EventHandler(AddressOf Application_Idle) Private spectrum(1999) As Integer Private noise As Integer = 12 Private zufall As New Random Private sw As Stopwatch = New Stopwatch() Private accumulator As Double = 0 Private idleCounter As Integer = 0 'Private serif As TextureFont = New TextureFont(New Font(FontFamily.GenericSerif, 24.0F)) Private sans As TextureFont = New TextureFont(New Font(FontFamily.GenericSansSerif, 8.0F)) Private txt_handle As TextHandle Private txt As ITextPrinter = New TextPrinter() Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load hasLoaded = True Me.GlControl1.MakeCurrent() GL.ClearColor(Color.FromArgb(10, 10, 10)) Me.GlControl2.MakeCurrent() GL.ClearColor(Color.FromArgb(100, 100, 100)) SetupViewport() Me.GlControl2.MakeCurrent() GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) GlControl2.SwapBuffers() GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) GlControl2.SwapBuffers() sw.Start() AddHandler Application.Idle, handler End Sub Private Sub Application_Idle(ByVal sender As Object, ByVal e As System.EventArgs) Dim ms As Double = ComputeTimeSlice() Accumulate(ms) Animate(ms) End Sub Private Sub Accumulate(ByVal milliseconds As Double) idleCounter += 1 accumulator += milliseconds If (accumulator > 1000) Then Label1.Text = idleCounter.ToString() accumulator -= 1000 idleCounter = 0 End If End Sub Private Function ComputeTimeSlice() As Double sw.Stop() Dim timeslice As Double = sw.Elapsed.TotalMilliseconds sw.Reset() sw.Start() Return timeslice End Function Private Sub Animate(ByVal ms As Double) spectrum(500) = 270 spectrum(250) = 30 For i As Integer = 600 To 880 Step 20 spectrum(i) = i - 590 Next For j As Integer = 0 To spectrum.Length - 1 If j = 0 Then spectrum(j) = (spectrum(j) * 2 + spectrum(j + 1)) \ 3 + zufall.Next(-noise, noise) ElseIf j = spectrum.Length - 1 Then spectrum(j) = (spectrum(j) * 2 + spectrum(j - 1)) \ 3 + zufall.Next(-noise, noise) Else spectrum(j) = (spectrum(j) * 4 + spectrum(j + 1) + spectrum(j - 1)) \ 6 + zufall.Next(-noise, noise) End If Select Case spectrum(j) Case Is < 0 spectrum(j) = 0 Case Is >= Me.GlControl1.Height spectrum(j) = Me.GlControl1.Height - 1 End Select Next GlControl1.Invalidate() End Sub Private Sub SetupViewport() Dim w As Integer = GlControl1.Width Dim h As Integer = GlControl1.Height Me.GlControl1.MakeCurrent() GL.MatrixMode(MatrixMode.Projection) GL.LoadIdentity() GL.Ortho(0, w, 0, h, -1, 1) ' Bottom-left corner pixel has coordinate (0, 0) GL.Viewport(0, 0, w, h) ' Use all of the glControl painting area w = GlControl2.Width h = GlControl2.Height Me.GlControl2.MakeCurrent() GL.MatrixMode(MatrixMode.Projection) GL.LoadIdentity() GL.Ortho(0, w, 0, h, -1, 1) ' Bottom-left corner pixel has coordinate (0, 0) GL.Viewport(0, 0, w, h) ' Use all of the glControl painting area End Sub Private Sub GlControl1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles GlControl1.Paint If hasLoaded Then Me.GlControl1.MakeCurrent() GL.Clear(ClearBufferMask.ColorBufferBit Or ClearBufferMask.DepthBufferBit) GL.MatrixMode(MatrixMode.Modelview) GL.LoadIdentity() GL.Color3(Color.DarkGray) GL.Begin(BeginMode.Lines) For j As Integer = 20 To GlControl1.Height - 1 Step 20 GL.Vertex2(25, j) GL.Vertex2(GlControl1.Width, j) Next GL.End() For j As Integer = 11 To GlControl1.Height - 11 Step 20 txt.Prepare((-154 + (j - GlControl1.Height) \ -2).ToString, sans, txt_handle) txt.Begin() GL.Translate(0.0F, j + 2, 0.0F) txt.Draw(txt_handle) txt.End() Next GL.Color3(Color.YellowGreen) GL.Begin(BeginMode.LineStrip) For j As Integer = 0 To spectrum.Length - 1 GL.Vertex2(j, spectrum(j)) Next GL.End() Me.GlControl2.MakeCurrent() GL.ReadBuffer(ReadBufferMode.Front) For j As Integer = GlControl2.Height To 0 Step -255 GL.RasterPos2(0, j - 1) GL.CopyPixels(0, j, GlControl2.Width, 255, PixelCopyType.Color) Next GL.Begin(BeginMode.Points) 'For i As Integer = 0 To GlControl2.Height - 1 For j As Integer = 0 To spectrum.Length - 1 Dim r As Integer = spectrum(j) * 1 Dim g As Integer = spectrum(j) * 3 Dim b As Integer = spectrum(j) * 6 If r > 255 Then r = 255 If g > 255 Then g = 255 - (g - 255) If b > 255 Then b = 255 - (b - 255) If g < 0 Then g = 0 If b < 0 Then b = 0 GL.Color3(Color.FromArgb(r, g, b)) GL.Vertex2(j, GlControl2.Height - 1) Next 'Next GL.End() GlControl1.SwapBuffers() GlControl2.SwapBuffers() Else 'do nuthin' End If End Sub End Class
| Attachment | Size |
|---|---|
| ScreenShot_1.JPG | 237 KB |
| ScreenShot_2.JPG | 251.37 KB |
| ScreenShot_3.JPG | 216.02 KB |


Comments
Re: Newbie qeustion and a potential bug
1. Which operating system? I can't seem to reproduce this on my PC (either XP or linux).
2. In what way do they fail to redraw? Note that you should handle both GLControl1.Paint and GLControl2.Paint, puting the relevant code to each handler. The same should be done for the Resize event (keep GLControl1 as separate from GLControl2 as possible).
3. There are several methods to achieve this. For example, you can create a large texture and use TexSubImage and CopyTexSubImage to update and scroll it respectively. The texture is then displayed on a simple screen-sized quad.
This method minimizes system -> video memory transfers, which should give a nice speed boost. The downside is that it can get complicated if your window is larger than the max texture size of your system (you'll have to separate the display in many smaller textures). Fortunately, all recent cards support at least 2048x2048 textures, so it will only be a problem if you want to support old systems (Geforce 2 era and older).
4. As far as I know, CopyPixels involves a video -> system -> video memory transfer, which should be avoided at all costs. CopyTexSubImage on the other hand means a blazing-fast video -> video memory copy.
As a rule of thumb, pixel-level manipulations are slow in OpenGL (and DirectX). You'll get better performance by assembling whole rows of data and uploading them at once, compared to sending each pixel one-by-one.
Re: Newbie qeustion and a potential bug
1. > Which operating system?
Microsoft Windows XP Professional
5.1.2600 Service Pack 3 Build 2600
Microsoft Corporation
NVIDIA GeForce 6600
PCI\VEN_10DE&DEV_0141&SUBSYS_31261458&REV_A2\4&123D6358&0&0010
GeForce 6600, NVIDIA-kompatibel
NVIDIA GeForce 6600
256.00 MB (268,435,456 Bytes)
nv4_disp.dll
6.14.10.7801
Try opening the task manager and moving its form while the GL program is running. I could send you my project, if you wish.
2. > In what way do they fail to redraw?
When you move a window from another application across the GlControls, this can cause the error in 1) and also you can see remnants of the foreign window in the area which scrolls (see screen shot #3).
3. > use TexSubImage and CopyTexSubImag
Need to figure out how to do this - good fun - always nice to learn something new.
4. > CopyPixels involves a video -> system -> video
AFAIK and according to the book I've got here, CopyPixels does not use system memory.
For the waterfall, sooner or later I'll end having to set the color of each pixel in the top line individually, after that then I only want to move the line but not redraw it pixel for pixel.
Thanks!
Re: Newbie qeustion and a potential bug
Looks interesting, haven't seen spectrum analyzers for a while ^^
3. You can fake the scrolling by setting MatrixMode to Texture and translate it repeatedly. This will give the illusion that your texture is scrolling and avoids any copy, but you have to fine-tune the translation and your updates to the texture carefully, so that the illusion does not break.