Programowanie w systemie UNIX/c grafika/OpenGL

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania

Definicja[edytuj]

Ścisła[edytuj]

OpenGL w ścisłym znaczeniu oznacza:

  • standard sposobu dostępu do karty graficznej w celu:
    • tworzenia grafiki (2D i 3D) - główny cel [1]
    • GPGPU - używając renderowania poza ekranem (ang. offscreen rendering): nie wysyła danych do bufora ramki[2] (ang. the frame buffer) ale do innej części pamięci karty graficznej (ang. the offscreen buffer)[3]
  • nie jest biblioteką lecz specyfikacją (API). Nie jest związane ze sprzętem i dzięki temu jest wieloplatformowe, uniwersalne i abstrakcyjne. Nie posiada kodu źródłowego
  • działa w architekturze klient-serwer
  • zajmuje się tylko rysowaniem. Nie ma okien, menu, procedur obsługi wejścia, czy inneych rodzajów interakcji
  • system graficzny czasu rzeczywistego = zapewnia przyspieszenie sprzętowe (ang. hardware acceleration) renderowania grafiki dzięki:
    • programowaniu równoległemu (procesor i program)
    • bezpośredniemu dostępowi do karty graficznej (z pominięciem systemu operacyjnego)[4]

Praktyczna[edytuj]

W potocznym i praktycznym znaczeniu OpenGL obejmuje następujące całe środowisko/platformę/kontekst:[5]

  • sprzęt ( hardware): karta graficzna z procesorem GPU[6]
  • oprogramowanie ( software):
    • system operacyjny
    • sterownik karty graficznej
    • biblioteki pomocnicze
    • program

Typy kodu OpenGL[edytuj]

grafika w linuksie

Typy kodu OpenGL, podział wg:

  • OS (lokalizacja bibliotek)
  • język programowania: C, C++, C#, Ada, Java, JavaScript, Python, Ruby, PHP, Lua, R, Perl, OCaml, Common Lisp, Clojure, Fortran, D i wiele innych
  • środowiska (konsola / IDE)
  • platforma (OpenGL / OpenGL ES)
  • wersja OpenGL:
    • legacy = 1 lub 2
    • modern = czyli 3 lub 4 (GLSL). Do rysowania i wyświetlania grafiki trzeba używać shaderów [7]
  • biblioteki podstawowe i ich wersje (Gl, Glu , GLew, ...)
  • GUI lub konsola
  • sprzętu (karta graficzna / GPU)
  • sterownika karty graficznej (program i jego wersja) i moduł jądra (ang. kernel module)


Ponieważ prawie dowolnie można łączyć powyższe cechy (9) liczba możliwych kombinacji jest bardzo duża, dlatego prawie każdy poradnik, program musimy zmodyfikować do naszych warunków.

Dostęp do GPU:

  • z poziomu X-window: DRI -> GPU (np. Mesa 3D)
  • z poziomu konsoli bez X-window: DRI -> GPU (np. DirectFB[8])

Potok[edytuj]

Schemat blokowy protokołu programowalnego OpenGL 3.3
Kolejność przekształceń punktów w Open GL3.3

Test[edytuj]

Konsolowe[edytuj]

Sprawdzamy instalację za pomocą konsolowego programu glxinfo (Mesa) [9][10]

glxinfo

lub

glxinfo | more

lub

glxinfo > gl.txt   

otrzymujemy:


name of display: :0
display: :0  screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
server glx extensions:
    GLX_ARB_create_context, GLX_ARB_create_context_profile, 
    GLX_ARB_create_context_robustness, GLX_ARB_fbconfig_float, 
    GLX_ARB_multisample, GLX_EXT_buffer_age, 
    GLX_EXT_create_context_es2_profile, GLX_EXT_create_context_es_profile, 
    GLX_EXT_framebuffer_sRGB, GLX_EXT_swap_control, GLX_EXT_swap_control_tear, 
    GLX_EXT_texture_from_pixmap, GLX_EXT_visual_info, GLX_EXT_visual_rating, 
    GLX_NV_float_buffer, GLX_NV_multisample_coverage, GLX_SGIX_fbconfig, 
    GLX_SGIX_pbuffer, GLX_SGI_swap_control, GLX_SGI_video_sync
client glx vendor string: NVIDIA Corporation
client glx version string: 1.4
client glx extensions:
...


 glxinfo | grep "OpenGL version"

przykładowy wynik:

OpenGL version string: 3.0 Mesa 10.3.2

lub:

sudo /usr/lib/nux/unity_support_test -p -f

Przykładowy wynik:

OpenGL vendor string:   NVIDIA Corporation
OpenGL renderer string: GeForce GTX 770/PCIe/SSE2
OpenGL version string:  4.3.0 NVIDIA 319.32

Not software rendered:    yes
Not blacklisted:          yes
GLX fbconfig:             yes
GLX texture from pixmap:  yes
GL npot or rect textures: yes
GL vertex program:        yes
GL fragment program:      yes
GL vertex buffer object:  yes
GL framebuffer object:    yes
GL version is 1.4+:       yes

Unity 3D supported:       yes

Karta graficzna[edytuj]

Sprawdzamy kartę i jej sterownik używając lspci:

lspci | grep VGA


przykładowy wynik:

01:00.0 VGA compatible controller: NVIDIA Corporation GK104 [GeForce GTX 770] (rev a1)

lub nvidia-smi:

nvidia-smi[11]
Sat Jan 18 09:18:20 2014       
+------------------------------------------------------+                       
| NVIDIA-SMI 5.319.60   Driver Version: 319.60         |                       
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 770     Off  | 0000:01:00.0     N/A |                  N/A |
| 17%   29C  N/A     N/A /  N/A |      222MB /  2047MB |     N/A      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Compute processes:                                               GPU Memory |
|  GPU       PID  Process name                                     Usage      |
|=============================================================================|
|    0            Not Supported                                               |
+-----------------------------------------------------------------------------+

Za pomocą cat otrzymujemy informacje o aktualnie załadowanym module jądra (ang. the version of the currently loaded NVIDIA kernel module):

 cat /proc/driver/nvidia/version

otrzymujemy:

NVRM version: NVIDIA UNIX x86_64 Kernel Module  319.60  Wed Sep 25 14:28:26 PDT 2013
GCC version:  gcc version 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)


Za pomocą dkms:

 dkms status

otrzymujemy:

 nvidia-304-updates, 304.108, 3.11.0-15-generic, x86_64: installed


Program: nvidia-detect[12][13]

Przyspieszanie sprzętowe[edytuj]

Sprawdzamy czy mamy przyśpieszanie sprzętowe: [14]

glxinfo | grep renderer

otrzymujemy:

OpenGL renderer string: GeForce GTX 770/PCIe/SSE2

to znaczy, że mamy przyspieszanie sprzętowe. Jeśli otrzymamy:

Mesa GLX Indirect

to powinniśmy zainstalować odpowiednie do posiadanej karty graficznej sterowniki.


Inny :

 glxgear

Graficzne[edytuj]

  • /usr/bin/nvidia-setting
  • hardinfo
  • strona Nvidia: Smart Scan [15]
  • Gpu Test [16]
  • LuxRender [17]
  • w przeglądarce chrome wpisz: chrome://gpu[18]

Błędy[edytuj]

undefined reference to[edytuj]

Spróbujmy skompilować przeglądarkę dla programistów w Ubuntu używając komendy:

gcc v.c -lm -lGLU -lglut -Wall

Otrzymamy:

v.c: In function ‘readPPM’:
v.c:67:13: warning: variable ‘j’ set but not used [-Wunused-but-set-variable]
         int j ;
             ^
/usr/bin/ld: /tmp/cc2PsYvI.o: undefined reference to symbol 'glDrawPixels'
/usr/lib/nvidia-319/libGL.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

Błąd. Kompilator nie widzi definicji procedury glDrawPixels. W Ubuntu problem rozwiązuje dodanie biblioteki GL:

gcc v.c -lm -lGL -lGLU -lglut -Wall
v.c: In function ‘readPPM’:
v.c:67:13: warning: variable ‘j’ set but not used [-Wunused-but-set-variable]
        int j ;
            ^


Czasem kolejność też ma znaczenie[19]

Różne wersje sterownika karty graficznej i modułu jądra[edytuj]

Elementy OpenGL[edytuj]

Low-level -> High-level
Graphic card OpenGL  WGL (for Windows) EGL GLEW  GLUT  SFML Graphics, ClanLib... (2D)
OpenGL ES GLX (for X11) EAGL (iOS) Glee GLFW  Irrlicht, OGRE, Unity, (3D)
WebGL CGL/AGL (for OS X)  SDL, SFML OpenSG, OpenScenegraph...

Sterownik[edytuj]

Sprawdzamy sterownik ( ang. driver)/ moduł jądra ( ang. kernel module)[20]:

 lspci -k

przykładowy wynik ( fragment):

...
01:00.0 VGA compatible controller: NVIDIA Corporation GK104 [GeForce GTX 770] (rev a1)
	Subsystem: Gigabyte Technology Co., Ltd GK104 [GeForce GTX 770]
	Kernel driver in use: nvidia
	Kernel modules: nvidiafb, nouveau, nvidia_375_drm, nvidia_375
...

Wyjaśnienie:

  • the "kernel driver" line : refers to which driver is currently bound to the card ( = in use)
  • The "kernel modules" line : lists all of the drivers known to be capable of binding to this card

wersje[edytuj]

Wersje:[21][22]

  • własnościowe sterowniki (ang.: the proprietary drivers, GPU vendor's driver, binary driver, closed source unified NVIDIA drivers)[23]
  • otwarte sterowniki (ang.: the open source drivers)
    • Nouveau: Accelerated Open Source driver for nVidia cards. [25]
    • MESA (sterowniki zawarte w bibliotece programistycznej)
    • Intel
    • ATI/AMD (radeon, radeonhd)


Sterowniki własnościowe Nvidii powoduję konflikt ze sterownikami Nouvoux. [26]

Etapy instalacji[edytuj]

  • dodanie kodu do drzewa (ang. add)
  • kompilacja (build)
  • instalacja (ang. install)
  • ładowanie modułu do jądra

Elementy[edytuj]

kod źródłowy[edytuj]

  • jądra: /lib/module/kernel - version/build directory
  • modułu: /usr/src/module - module-version

Moduł jądra[edytuj]

Dynamic Kernel Module Support (DKMS)[27]


Moduł jądra:

/lib/modules/wersja_jadra/kernel/drivers/video/nvidia.ko

Sprawdźmy czy mamy załadowany moduł nvidia za pomocą lsmod:

lsmod | grep nvidia

przykładowy wynik:

nvidia               9430379  50 
drm                   297056  2 nvidia

Mamy więc próbujemy otrzymać więcej informacji o nim za pomocą modinfo:[28]

 modinfo nvidia

wynik:

ERROR: Module nvidia not found.

Przyczyną tego jest alias[29]. Znajdujemy właściwą nazwę:

 modprobe --resolve-alias nvidia

wynik:

nvidia_319

i:

modinfo nvidia_319

Wynik:

filename:       /lib/modules/3.11.0-19-generic/updates/dkms/nvidia_319.ko
alias:          char-major-195-*
version:        319.32
supported:      external
license:        NVIDIA
alias:          pci:v000010DEd00000E00sv*sd*bc04sc80i00*
alias:          pci:v000010DEd00000AA3sv*sd*bc0Bsc40i00*
alias:          pci:v000010DEd*sv*sd*bc03sc02i00*
alias:          pci:v000010DEd*sv*sd*bc03sc00i00*
depends:        drm
vermagic:       3.11.0-19-generic SMP mod_unload modversions 
parm:           NVreg_Mobile:int
parm:           NVreg_ResmanDebugLevel:int
parm:           NVreg_RmLogonRC:int
parm:           NVreg_ModifyDeviceFiles:int
parm:           NVreg_DeviceFileUID:int
parm:           NVreg_DeviceFileGID:int
parm:           NVreg_DeviceFileMode:int
parm:           NVreg_RemapLimit:int
parm:           NVreg_UpdateMemoryTypes:int
parm:           NVreg_InitializeSystemMemoryAllocations:int
parm:           NVreg_RMEdgeIntrCheck:int
parm:           NVreg_UsePageAttributeTable:int
parm:           NVreg_MapRegistersEarly:int
parm:           NVreg_RegisterForACPIEvents:int
parm:           NVreg_CheckPCIConfigSpace:int
parm:           NVreg_EnablePCIeGen3:int
parm:           NVreg_EnableMSI:int
parm:           NVreg_MemoryPoolSize:int
parm:           NVreg_RegistryDwords:charp
parm:           NVreg_RmMsg:charp

Biblioteki[edytuj]

Schemat stosu grafiki jądra Linuxa; Aktualna infrastruktura Direct Rendering, dostęp do GPU odbywa się za pośrednictwem Direct Rendering Manager.


Pakiety: [30]

  • freeglut3 freeglut3-dev
  • libglew1.5 libglew1.5-dev
  • libglu1-mesa, libglu1-mesa-dev, libgl1-mesa-glx , libgl1-mesa-dev

kompilacja:

 gcc -lglut -lGL -lGLU -lGLEW example.c 

W kodzie:

#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>

Pliki nagłówkowe bibliotek:

  • gl.h
  • glu.h
  • glut.h
  • glew.h
Includes Static Libs Dynamic Libs
/usr/X11R6/include/GL /usr/X11R6/lib/ /usr/X11R6/lib/
GL gl.h libGL.la libGL.so
GLU glu.h libGLU.la libGLU.so
GLUT glut.h libglut.la libglut.so



Kontekst/platforma[edytuj]

  • windows: WGL
  • linux/unix ( X-window): GLX
  • OS X : CGL i AGL
  • urządzenia przenośne :
    • OpenGL ES
    • EGL
  • www : WebGL
  • Vulkan API


Podstawowe[edytuj]

GL[edytuj]

GL = Graphic Library (ang.) = OpenGl core library

Jest to niskopoziomowa biblioteka zawierająca procedury do rysowania linii, koloru tła itp. Otrzymujemy dostęp do OpenGL-1.1. Na więcej potrzebujemy rozszerzeń, np. za pomocą biblioteki GLEW[31]

GLU[edytuj]

GLU = Graphics Library Utility (ang.) jest to średniopoziomowa biblioteka pozwalająca na dostęp do macierzy, renderowania powierzchni itp.

GUI[edytuj]

Podział wg złożoności:


Podział wg zależności od systemu operacyjnego ( OS )[34]

  • zależne od OS
    • bezpośredni ( rendering contexts and pixel formats )
      • direct rendering from OpenGl application to OpenGl DRIdriver
      • from framebuffer application to Direct Rendering Manager (DRM)
    • biblioteki
      • GLX (ang. OpenGL Extension to the X Window System) – interfejs łączący OpenGL z X Window System i zapewniający działającym w oknach X Window System dostęp do funkcji OpenGL
      • wgl
      • cgl
  • niezależne od OS
    • GLUT
    • GLFW
    • SDL
    • CPW
    • SFML

DRM[edytuj]

Direct Rendering Manager(DRM) – komponent Direct Rendering Infrastructure (DRI), czyli systemu sprzętowej akceleracji grafiki pod Linuksa. DRM odpowiada za bezpieczeństwo oraz zarządzaniem zasobami.

DRM składa się z dwóch modułów jądra systemu operacyjnego. Jednego wspólnego dla wszystkich kart graficznych, oraz sterowników właściwych dla konkretnego urządzenia. Obydwa te moduły pozwalają klientowi serwera X, na bezpośredni dostęp do urządzenia (z pominięciem serwera X).

GLUT[edytuj]

GLFW[edytuj]

Wymagania:

  • gcc
  • OpenGL (OpenGL header packages)
  • X11
  • xorg-dev
  • libglu1-mesa-dev
  • libglfw-dev
  • cmake




pakiety[edytuj]
 sudo apt-get update
 sudo apt-get install libglfw3 libglfw3-dev
git[edytuj]

Etapy:

  • ściągnięcie kodu źródłowego biblioteki[35]
  • kompilacja biblioteki [36]


git clone https://github.com/glfw/glfw.git
cd <glfw-root-dir>
cmake .


Sprawdzamy:

sudo updatedb
locate glfw3.pc

przykładowy wynik:

/home/a/cn/glfw-3.0.4/src/glfw3.pc
/home/a/cn/glfw-3.0.4/src/glfw3.pc.in
/home/a/glfw/src/glfw3.pc
/home/a/glfw/src/glfw3.pc.in


sudo apt-get update
sudo apt-get install build-essential cmake git xorg-dev libglu1-mesa-dev
git clone https://github.com/glfw/glfw.git /tmp/glfw
cd /tmp/glfw
git checkout latest
cmake . -DBUILD_SHARED_LIBS=ON
make
sudo make install
sudo ldconfig
# rm -rf /tmp/glfw


przykład=[edytuj]
/*
http://www.glfw.org/documentation.html


gcc g.c -lGL -lGLU -lglut -lglfw

./a.out



*/

#include <GLFW/glfw3.h>

int main(void)
{
    GLFWwindow* window;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

SFML[edytuj]

SFML = Simple and Fast Multimedia Library (ang.)

Rozszerzenia[edytuj]

Biblioteki rozszerzeń (ang. OpenGL Loading Library, Extension Loading Library)

  • nieoficalny OpenGL SDK [37]
  • GLEW
  • gl3w [38]
  • glxw

GLEW[edytuj]

GLEW = OpenGL Extension Wrangler Library (ang.) jest to programistyczna biblioteka międzyplatformowa, pomagająca w odpytywaniu i ładowaniu rozszerzeń OpenGL. GLEW dostarcza efektywne mechanizmy do określania w czasie uruchamiania programu dostępnych rozszerzeń na danej platformie. Wszystkie rozszerzenia OpenGL są wylistowane w jednym pliku nagłówkowym, który z kolei jest maszynowo generowany na podstawie oficjalnej listy rozszerzeń.

GLEW jest napisany w ANSI C.

#include<GL/glew.h>
#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h>

Kompilacja:

-lGLEW -lGLU -lGL - lglut

GLEW zawiera dodatkowe programy konsolowe, np.: glewinfo

glewinfo>i.txt

W pliku i.txt jest informacja:

 ---------------------------
    GLEW Extension Info
---------------------------

GLEW version 1.8.0
Reporting capabilities of display :0, visual 0x2b
Running on a GeForce GTX 770/PCIe/SSE2 from NVIDIA Corporation
OpenGL version 4.3.0 NVIDIA 319.60 is supported

Następnie jest lista rozszerzeń i informacja o dostępności (OK/MISSING).

matematyczne[edytuj]

glm[edytuj]

GLM is a C++ mathematics library (and to replace OpenGL fixed pipeline functions) for 3D software based on the OpenGL Shading Language (GLSL) specification.

  sudo apt-get install libglm-dev

graficzne[edytuj]

  • GLI (OpenGL Image, C++)

Przykłady[edytuj]

grafika 2d[edytuj]

Technika: [39]

  • old OpenGl
    • glDrawPixels
  • modern OpenGl
    • drawing a flat quadrilateral with an orthographic projection camera
    • applying a texture on top of it

Pierwszy program[edytuj]

Konsolowy program korzystający z bibliotek GL, GLU i GLUT. Tworzy okno wypełnione czerwonym kolorem [40]

/* 

gcc o.c -lGL -lGLU -lglut
./a.out

http://www.linuxforu.com/2013/04/graphics-programming-in-linux/

Graphics Programming in Linux

By Rajnish-Singh on April 1, 2013 in Developers, Features, Overview · 3 Comments

*/


# include <stdio.h>
#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h> 


void display() 
{ 
    glClearColor(1,0,0,0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 


void main(int argc, char**argv) { 
    glutInit(&argc, argv); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(500,500); 
    glutCreateWindow("Hello World"); 
    glutDisplayFunc(display); 
    glutMainLoop(); 
}

GLEW[edytuj]

Konsolowy program korzystający z glew:

//gcc c.c  -lGLEW -lGL -lGLU -lglut 
//./a.out
#include <stdio.h>
#include<GL/glew.h>
#include<GL/glut.h>
#include<GL/gl.h>
#include<GL/glu.h>

void main(int argc, char **argv)
{
	glutInit(&argc, argv);
	
	glewInit();
	if ( GL_VERSION_4_0) printf("OpenGL 4.0 is supported\n");
}

Konsolowy program korzystający z bibliotek GL, GLU, GLUT i GLEW. Tworzy okno wypełnione czerwonym kolorem oraz sprawdza wersję biblioteki GLEW

/*
gcc g.c  -lGLEW -lGL -lGLU -lglut 
./a.out

http://www.linuxforu.com/2013/04/graphics-programming-in-linux/
Graphics Programming in Linux By Rajnish-Singh on April 1, 2013 in Developers, Features, Overview · 3 Comments
http://www.opengl.org/sdk/libs/GLEW/
call glewInit(); once you've obtained a OpenGL context in your program.

*/
#include <stdio.h>
#include <GL/glew.h> // glew before gl 
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h> 
 


void display() 
{ 
    glClearColor(1,0,0,0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 


void main(int argc, char**argv) { 
    glutInit(&argc, argv); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(500,500); 
    glutCreateWindow("Hello World");

    GLenum err = glewInit();
    if (GLEW_OK != err)
      fprintf(stderr, "Error: %s\n", glewGetErrorString(err));/* Problem: glewInit failed, something is seriously wrong. */
      else fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); 
    glutDisplayFunc(display); 
    glutMainLoop(); 
}

Sprawdzamy rozszerzenia:[41]

/*


gcc g.c  -lGLEW -lGL -lGLU -lglut 
./a.out

http://www.linuxforu.com/2013/04/graphics-programming-in-linux/

Graphics Programming in Linux By Rajnish-Singh on April 1, 2013 in Developers, Features, Overview · 3 Comments


http://www.opengl.org/sdk/libs/GLEW/
call glewInit(); once you've obtained a OpenGL context in your program.
http://steps3d.narod.ru/tutorials/glew-tutorial.html


*/

#include <stdio.h>
#include <GL/glew.h> // glew before gl 
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h> 
 


void display() 
{ 
    glClearColor(1,0,0,0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glFlush(); 
} 


int main(int argc, char**argv) { 
    glutInit(&argc, argv); 
    glutInitWindowPosition(100,100); 
    glutInitWindowSize(500,500); 
    glutCreateWindow("Hello World");

    GLenum err = glewInit();
    if (GLEW_OK != err)
      {
       fprintf(stderr, "Error: %s\n", glewGetErrorString(err));/* Problem: glewInit failed, something is seriously wrong. */
       return 1; 
      }    
    fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
    
    // checking for extensions 
    if ( !GLEW_ARB_shading_language_100 )
    {
        printf ( "GL_ARB_shading_language_100 NOT supported.\n" );
        return 2;
    }
    printf ( "GL_ARB_shading_language_100 is supported.\n" );

    if ( !GLEW_ARB_shader_objects )
    {
        printf ( "GL_ARB_shader_objects NOT supported" );
        return 3;
    }
    printf ( "GL_ARB_shader_objects is supported" );
    if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
     {
           printf("No GLSL support\n");
          exit(4);
     }

   printf(" GLSL is supported\n");

    glutDisplayFunc(display); 
    glutMainLoop(); 
}

Zapisywanie obrazu[edytuj]

  • kod (paul bourke) [42]

Przeglądarka obrazów dla programistów[edytuj]

Ten program:

  • działa tylko dla legacy OpenGL API !
  • otwiera binarne pliki ppm (P6) i pgm (P5)
  • wyświetla je w nowym oknie (Glut)
  • na konsoli tekstowej wyświetla:
    • typ pliku,
    • szerokość, wysokość,
    • komentarz,
    • dane punktu nad którym znajduje się mysz (patrz procedura Motion, można to zmienić !!!)

Program służy do analizy plików graficznych.


/* 
 * image.c
 *
 * read in a PPM or PGM binary image and display it, full size
 
  Based on code by : 
   Dr. Lori L. Scarlatos
   Stony Brook University
   http://ms.cc.sunysb.edu/~lscarlatos/
   "I do not have a license for image.c; 
   it was created as an example for my students.
   Please feel free to use it.
   Best regards,
   Lori"

Warning: This article describes legacy OpenGL APIs that have been removed from core OpenGL 3.1 and above (they are only deprecated in OpenGL 3.0). It is recommended that you not use this functionality in your programs.
Fixed Function Pipeline
* ----------------------------
* it does not opens asci versions of these files 
* examples files : 
* http://people.sc.fsu.edu/~jburkardt/data/data.html


http://web.eecs.umich.edu/~sugih/courses/eecs487/glut-howto/sample.c

  // gcc v.c -lm -lGLU -lglut -Wall // ? windows 
    gcc v.c -lm -lglut -lGL -lGLU -Wall // ubuntu 
  ./a.out 5.pgm

 */

/*

locate glut.h
/usr/include/GL/freeglut.h
/usr/include/GL/glut.h

#ifdef FREEGLUT
#include <GL/freeglut.h>
#else
#include <GL/glut.h>
#endif

*/



//#include <Windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
//#include <GL/glut.h> // oryginal glut 
#include <GL/freeglut.h> // freeglut 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h> /* fabs*/
//#include <malloc.h>



/* Global variables */

#define MAXLINE 80	/* maximum length of a line of text */

/*

3.2 Conventions

In developing the freeglut library, we have taken careful steps to ensure consistency in function operation across the board, 
in such a manner as to maintain compatibility with GLUT's behavior whenever possible. In this section some of the important conventions of FreeGLUT, 
and their compatibility with GLUT, are made explicit.

3.2.1 Window placement and size

There is considerable confusion about the "right thing to do" concerning window size and position. GLUT itself is not consistent between Windows and UNIX/X11; 
since platform independence is a virtue for freeglut, we decided to break with GLUT's behaviour. 
Under UNIX/X11, it is apparently not possible to get the window border sizes in order to subtract them off the window's initial position until some time after the window has been created. 
Therefore we decided on the following behavior, both under Windows and under UNIX/X11:

When you create a window with position (x,y) and size (w,h), the upper left hand corner of the outside of the window (the non-client area) is at (x,y) and the size of the drawable (client) area is (w,h). 
The coordinates taken by glutInitPosition and glutPositionWindow, as well as the coordinates provided by FreeGLUT when it calls the glutPositionFunc callback, specify the top-left of the non-client area of the window.
When you query the size and position of the window using glutGet, FreeGLUT will return the size of the drawable area
--the (w,h) that you specified when you created the window
--and the coordinates of the upper left hand corner of the drawable (client) area
--which is NOT the (x,y) position of the window you specified when you created it.




*/




GLint ImageWidth, ImageHeight;	         /* size of the Image in pixels */
GLint WindowWidth, WindowHeight;	/* size of the window in pixels */
GLint MaxScreenWidth, MaxScreenHeight;	/* size of the screen in pixels */


GLubyte *Picture;	/* Array of colors (GLubyte)  */
int size; 



// mouse position as a global variables 
//static float mx=0.0f,my=0.0f ;
int iX, iY; // 
int centerX = 200, centerY = 200;
GLint iYmax,iXmax; // mouse coordinate inside image 

unsigned char pixel[3];

// change it manually !!!!!


const double  ZyMin=-1.0;
const double  ZxMin=-2.0;
const double  PixelHeight=0.0020010005002501  ;
const double  PixelWidth=0.0020010005002501  ;

int filetype;
enum {P2, P3, P5, P6};	/* possible file types */

/* gives position of point (iX,iY) in 1D array  ; uses also global variables */
unsigned int f(unsigned int _iX, unsigned int _iY)
{return (_iX + (iYmax-_iY-1)*iXmax );}

/* 
* Read from a PPM or PGM (binary) file 
* Output is a array of GLubyte 
*/
void readPPM (char *filename, GLubyte **pic) {

	FILE *fp;
	char line[MAXLINE];
	int i, rowsize;
        // int size; // moved to global var 
        int j ;
	GLubyte *ptr;

/* Read in file type */
  
  fp = fopen(filename, "r"); /* in Unix rb = r */
  if (fp==NULL) {perror(" perror : " ); printf("Error from fopen : I can't open %s file' ! ", filename); exit(1); }
  else printf("File %s has been opened !\n", filename);
  /* Each file starts with aa two-byte magic number (in ASCII) that explains :
   * - the type of file it is (PBM, PGM, and PPM) 
   * - its encoding (ASCII or binary). 
   * The magic number is a capital P followed by a single digit number. 
  */
  fgets (line, MAXLINE, fp); /* 1st line : Magic Number  */
  switch (line[1])
  {
   case '2':
       filetype = P2; 
       printf("This is PGM text file (P2), but now I do not have procedure for opening it \n");
       break;
   case '3' :
      filetype = P3;
      printf("This is PPM text file (P3), but now I do not have procedure for opening it !\n");
      break; 
   case '5':
       filetype = P5; 
       printf("This is PGM binary file (P5) and I can open it !\n");
       break;
   case '6' :
      filetype = P6;
      printf("This is PPM binary file (P6) and I can open it !\n");
      break;
   default : 
      printf("Error from readPPM : need binary PPM or binary PGM file as input!\n");
      exit(1);
   }
 /* if this is a comment, read next line. Maybe in binary files there is no comment ?*/
/* there maybe more then one line of comment */
 fgets (line, MAXLINE, fp); 
 while  (line[0]=='#') 
  { printf(" comment  = %s \n", line); /* 2nd or more line  starting with # =  comment, print it   */
    fgets (line, MAXLINE, fp); // read next line 
  } 

/* Read in width and height, & allocate space */
/* these 2 numbers should be in one line with space between them */
   /* 3nd line: width  and height */
  sscanf(line, "%d %d", &ImageWidth, &ImageHeight);
  printf ("iWidth = %d\n", ImageWidth);
  printf ("iHeight = %d\n",  ImageHeight);
  iXmax=ImageWidth-1;
  iYmax=ImageHeight-1;

  if (filetype == P5) {
	  size = ImageHeight * ImageWidth; /* greymap: 1 byte per pixel */
	  rowsize = ImageWidth;
  }
  else /* filetype == P6 */ {
	  size = ImageHeight * ImageWidth * 3; /* pixmap: 3 bytes per pixel */
	  rowsize = ImageWidth * 3;
  }
  *pic = (GLubyte *)malloc (size); /* create dynamic array */

/* Read in maximum value (ignore) */
  fgets (line, MAXLINE, fp); /* next  line */
  /*  */
  if (filetype==P5 || filetype==P6){
    /* Read in the pixel array row-by-row: 1st row = top scanline */
    ptr = *pic + (ImageHeight-1) * rowsize;
    for (i = ImageHeight; i > 0; i--) {
          /* For binary File I/O you use fread and fwrite */
	  j = fread((void *)ptr, 1, rowsize, fp); 
	  ptr -= rowsize;
    }
   if (j) printf("File %s has been read !\n", filename);
          else printf(" j Error from readPPM procedure : I can't read %d file !.\n", j);
  }
  else printf("Error from readPPM procedure : I can't read %s file !. It should be P5 or P6 file !\n", filename);
  fclose(fp);
  printf("File %s has been closed !\n", filename);
}






/* Draw the picture on the screen */

void Draw(void) {
        /* black background of GLUT window */
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to black
        glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
        glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations
        glFlush(); // Flush the OpenGL buffers to the window
        // left lower corner of displayed image 
	glRasterPos2i(-1,-1); // By default, OpenGL assumes a system running from -1 to 1, 
        switch (filetype){
          case P5 : 	/* greymap: use as illumination values */
		glDrawPixels(ImageWidth, ImageHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, Picture);
                printf("P5 Image has been drawn !\n");
                break;
	  case  P6 :
		glDrawPixels(ImageWidth, ImageHeight, GL_RGB, GL_UNSIGNED_BYTE, Picture);
                printf("P6 Image has been drawn !\n");
                break;
         default : 
                printf("Error from Draw procedure : There is no image to draw !\n");
          }


       
}




// Detecting Mouse Clicks
// x and y specify the location (in window-relative coordinates) of the mouse when
// the event occurred
void MouseClicks (int button, int state, int x, int y)
{
switch (button)
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
// do something
case GLUT_RIGHT_BUTTON: ;
// etc., etc.
}





// mouse motion 
//The x and y callback parameters 
// indicate the  mouse  location 
// in window relative coordinates
//
// x, y –> coordinates of the mouse relative to upper left corner of window

// setting the mouse position to be relative to the mouse
// position inside the window
//

void PassiveMouseMotion(int x, int y) {
  
   //double Zx,Zy;
   //double Ux; 
   //int index;
   //GLubyte Gray;

   // put your code here  ???? 
   iX = x;
   /* invert y axis */
   iY = WindowHeight - y -1 ; //+ (glutGet(GLUT_WINDOW_HEIGHT) - ImageHeight); ///glutGet(GLUT_WINDOW_HEIGHT) - y; // ????
   
  

   
   /* output : prints to console  */
  if ((filetype==P5 || filetype==P6) && -1<iX && iX< ImageWidth  && iY<ImageHeight) // && iY<ImageHeight
   {

     
     glReadPixels(iX, iY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
   // pixel coordinates of the mouse relative to upper left corner of window
   printf(" pixel iX=%3d / %d ;  iY=%3d  color = %d  \n", iX, MaxScreenWidth,  iY, pixel[1] );
  }
}




static void Key(unsigned char key, int x, int y)
{
    switch (key) {
	case 27 : {glutLeaveFullScreen(); break;}/* esc */
        case 'f': {glutFullScreen(); break; }
        case 'q': {printf("Key preseed and exit \n"); exit(1) ;}
        case 'Q': {printf("Key preseed and exit \n"); exit(1) ;}
        case 't': {glutFullScreenToggle(); break; } // GLUT does not include the glutLeaveFullScreen and glutFullScreenToggle functions from freeglut 
	default: return ;
    }
}



/* 
 Resize the picture  ; OpenGL calls this function whenever the window is resized 
 Called when window is resized,  also when window is first created,    before the first call to display().
*/
void Reshape(GLint w, GLint h) {

/* save new screen dimensions */
     WindowWidth = w;
     WindowHeight = h;
    /* the viewport is the rectangular region of the window where the image is drawn */
   // Viewport : A rectangular region in the screen for display  (in screen coordinate system) 
    glViewport(0, 0, ImageWidth-1, ImageHeight-1); // glViewport( 0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // Define a world window : A rectangular region in the world that is to be displayed (in world coordinate system)
    // By default, OpenGL assumes a system running from -1 to 1, 
    gluOrtho2D(-1, 1, -1, 1); // An orthographic projection is basically a 3D projection that does not have perspective
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}





/* 
Initialization: create window 
glutInitWindowSize(600, 600);
*/
void MyInit(int argc, char *argv[]) {
    char filename[MAXLINE];
  
  /* Read in the file (allocates space for Picture) */
  if (argc < 2) 
    {
	printf ("Enter the name of a binary PPM or PGM file: ");
	scanf("%s", filename);
	readPPM ((char *)filename, &Picture);
    }
    else { readPPM (argv[1], &Picture); }
  
  glutInit(&argc, argv);

  MaxScreenWidth  = glutGet(GLUT_SCREEN_WIDTH);
  MaxScreenHeight = glutGet(GLUT_SCREEN_HEIGHT);   
    
  glutInitWindowPosition(-1, 1); // upper  left  corner
  glutInitWindowSize(MaxScreenWidth, MaxScreenHeight ); // full screen of my monitor
 
  glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  if (glutCreateWindow("OpenGl binary pgm/ppm Image viewer ") == GL_FALSE) 
      {printf("Error from  MyInit , glutCreateWindow\n"); exit(1);}
       
}


/* ------------------ Main program ---------------------------------------*/
int main(int argc, char **argv)
{
  
    MyInit(argc, argv);
    glutPassiveMotionFunc(PassiveMouseMotion); // mouse move with no key pressed 
    glutReshapeFunc(Reshape); //  move or resize of screen window 
    glutDisplayFunc(Draw); // 
    glutKeyboardFunc(Key);
    //
    glutMainLoop();
    return 0;
}

Współrzędne[edytuj]

Współrzędne
world (float) screen (integer)
world
screen
screen window
world window viewport

Q: Czego lepiej używać, wymiarów typu 1.0f, -2,0f, czy wartości w pixelach 100, 550 - przy rysowaniu?

A: "Używaj tego co Ci wygodniej. Większość instrukcji operujących na wierzchołkach ma wersje dla liczb całkowitych - te z przedrostkiem i, jak i zmiennoprzecinkowych - te z przedrostkiem f(float) lub d(double)). np: glVertex2i(x,y), glVertex2f(x,y), glVertex3d(x,y,z) itd." [43]

Q: Gdzie definiujemy viewport?

A: W 2 miejscach:

  • w inicjalizacji, wtedy ma taki sam rozmiar jak całe okno
  • w funkcji zmieniającej rozmiar okna (glutReshapeFunc)

Typy[edytuj]

World[edytuj]

Domyślnie współrzędne okna światowego (world) w OpenGL mają zakres -1.0 do 1.0:

gluOrtho2D(-1.0, 1.0, -1.0, 1.0);


Miejsce lewego dolnego rogu wyświetlanego obrazu:

glRasterPos2i(-1.0, -1.0); // in Draw procedure 

Screen[edytuj]

W OpenGL mamy tu 3 elementy:

  • rozdzielczość ekranu (ang. screen)
  • wielkość okna ekranu (ang. window)
  • wielkość fragmentu okna ekranu gdzie jest wyświetlany obraz (ang. viewport) [44][45]


Współrzędne są liczbami całkowitymi:

 glutInitWindowSize(2560, 1440); // screen width, screen height in poixels 

 glViewport(50, 50, 350, 250); // viewport left down and upper right corners in window coordinate

Proporcje[edytuj]

Jeśli proporcja (ang. aspect ratio) r pomiędzy wymiarami World Window a VBiewport jest 1.0 to obraz nie jest zniekształcony.

r= width/height

Przeliczanie[edytuj]

Przeliczanie współrzędnych:[46]

  • World window: W_L, W_R, W_B, W_T
  • Viewport: V_L, V_R, V_B, V_T
  • punkt:
    • współrzędne world: (x,y)
    • współrzędne viewport: (sx, sy)
world_height=world_width*view_port_height/view_port_width
W_L=center_x‐world_width/2
W_B=center_y+world_height/2
W_R=center_x+world_width/2 
W_T=center_y+world_height/2
sx = (x ‐ W_L)(V_R ‐ V_L) / (W_R ‐ W_L) +V_L
sy = (y - W_B)(V_T ‐ V_B) / (W_T ‐ W_B) +V_B

Zobacz również[edytuj]

Źródła[edytuj]

  1. OpenGl tutorial
  2. Bufor ramki w Wikipedii
  3. [http://www.mathematik.uni-dortmund.de/~goeddeke/gpgpu/tutorial.html GPGPU::Basic Math / FBO Tutorial Modified from Dominik Göddeke]
  4. Radosław Mantiuk - wprowadzenie do grafiki
  5. Getting Started with OpenGL by Ray Toal
  6. askubuntu question: how-do-i-find-out-the-model-of-my-graphics-card
  7. stackoverflow question : is-it-possible-to-draw-anything-in-opengl-3-without-writing-glsl-shaders-will
  8. directfb
  9. glxinfo - linux command
  10. glxinfo code
  11. How to get the nvidia driver version from the command line ? - stackoverflow
  12. nvidia-detect
  13. Installing Nvidia Drivers In Linux Mint
  14. Using hardware accelerated 3D renderer on Linux from mgltools
  15. The NVIDIA Smart Scan page (requires the latest version of Java)
  16. Gpu test
  17. LuxRender
  18. askubuntu question: How to get GPU info?
  19. StackOverflow: undefined reference to symbol 'gluLookAt'
  20. unix.stackexchange question : what-is-the-difference-between-kernel-drivers-and-kernel-modules
  21. OpenGL - wsparcie przez sterowniki firmy Nvidia (ang.)
  22. How is Mesa different from OpenGL drivers - Stackoverflow
  23. Zyli: Instalacja zamkniętych (firmowych) sterowników Nvidia
  24. Nvidia Unix Driver Archive
  25. Nouveau: Accelerated Open Source driver for nVidia cards
  26. Ubuntu: BinaryDriverHowto/Nvidia
  27. Dynamic Kernel Module Support w wikipedii
  28. Why would modinfo say a module is not found when it appears with lsmod ?
  29. Alias w angielskiej Wikipedii
  30. stackoverflow question learning-opengl-in-ubuntu
  31. Różnice między bibliotekami
  32. GLFW
  33. GLUS
  34. opengl : window toolkits
  35. Kod źródłowy GLFW
  36. Kompilacja GLFW
  37. Unofficial OpenGL Software Development Kit
  38. gl3w
  39. stackoverflow question : how-to-draw-a-2d-image-using-opengl
  40. Graphics Programming in Linux By Rajnish-Singh
  41. glew tutorial - Alexey V. Boreskov
  42. Zapisywanie obrazu z aplikacji OpenGL - kod (paul bourke)
  43. Forum Serwisu programistycznego C i C++: [OPENGL glViewport a gluOtrho2d]
  44. glViewport
  45. The Viewport - Lazy Foo' Productions
  46. 2D Coordinate Systems and Drawing