Informacje i porady dotyczące pisania shaderów.

Podobne dokumenty
Gry Komputerowe Laboratorium 4. Teksturowanie Kolizje obiektów z otoczeniem. mgr inż. Michał Chwesiuk 1/29. Szczecin, r

Shadery. Artur Staszczyk Bartłomiej Filipek

1 Temat: Vertex Shader

Bartłomiej Filipek

OpenGL : Oświetlenie. mgr inż. Michał Chwesiuk mgr inż. Tomasz Sergej inż. Patryk Piotrowski. Szczecin, r 1/23

Poniżej pokazane są poszczególne etapy, w nawiasach kwadratowych znajdują się nazwy tekstur, które utworzymy w projekcie, a przy strzałkach nazwy

Mapowanie tekstur Mip-mapy (level of detail) Filtrowanie Multiteksturowanie

OpenGL - tekstury Mapowanie tekstur

Potok graficzny i shadery. Hubert Rutkowski

Implementacja sieci neuronowych na karcie graficznej. Waldemar Pawlaszek

Różne rodzaje efektów

Janusz Ganczarski. OpenGL Pierwszy program

1 Podstawy c++ w pigułce.

Wprowadzenie do QT OpenGL

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Język C++ zajęcia nr 2

1 Podstawy c++ w pigułce.

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Systemy wirtualnej rzeczywistości. Komponenty i serwisy

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Programowanie obiektowe

Programowanie i struktury danych

Programowanie Procesorów Graficznych

Zadanie 1. Ściana. 1. Potrzebne zmienne w dołączonym do zadania kodzie źródłowym

Podstawy języka C++ Maciej Trzebiński. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. Praktyki studenckie na LHC IVedycja,2016r.

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

Plan wykładu. Akcelerator 3D Potok graficzny

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

// Potrzebne do memset oraz memcpy, czyli kopiowania bloków

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Intro 4kb. sphere tracing. Maciej Matyka (maq / floppy) Dla koła naukowego Voxel

Stereoskopia. Implementacja w XNA 4.0

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

Grafika Komputerowa Wykład 6. Teksturowanie. mgr inż. Michał Chwesiuk 1/23

Wykład VII. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

GLKit. Wykład 10. Programowanie aplikacji mobilnych na urządzenia Apple (IOS i ObjectiveC) #import "Fraction.h" #import <stdio.h>

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Rysowanie punktów na powierzchni graficznej

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Programowanie w języku C++ Grażyna Koba

Konstruktor kopiujacy

Laboratorium nr 12. Temat: Struktury, klasy. Zakres laboratorium:

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

GRAFIKA KOMPUTEROWA 7: Kolory i cieniowanie

Wprowadzenie do języka Java

DYNAMICZNE PRZYDZIELANIE PAMIECI

Programowanie w C++ Wykład 1. Katarzyna Grzelak. 26 luty K.Grzelak (Wykład 1) Programowanie w C++ 1 / 28

Podłączanie bibliotek Zapis danych do pliku graficznego Generowanie promienia pierwotnego Import sceny z pliku Algorytm ray tracingu

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Język JAVA podstawy. wykład 2, część 2. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Mobilne aplikacje multimedialne. OpenGL

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

Języki i techniki programowania Ćwiczenia 2

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Programowanie obiektowe i C++ dla matematyków

OpenGL Światło (cieniowanie)

Programowanie w C++ Wykład 8. Katarzyna Grzelak. 15 kwietnia K.Grzelak (Wykład 8) Programowanie w C++ 1 / 33

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

ZASADY PROGRAMOWANIA KOMPUTERÓW

Pola i metody statyczne. Klasy zawierające pola i metody statyczne

Obiektowy PHP. Czym jest obiekt? Definicja klasy. Składowe klasy pola i metody

W powyższym kodzie utworzono wyliczenie dni tygodnia.

8 Przygotował: mgr inż. Maciej Lasota

OpenGL teksturowanie

Lab 9 Podstawy Programowania

TEMAT : KLASY DZIEDZICZENIE

OpenGL Światło (cieniowanie)

Systemy wirtualnej rzeczywistości. Podstawy grafiki 3D

Programowanie obiektowe

Szybkie tworzenie grafiki w GcIde

Rozdział 4 KLASY, OBIEKTY, METODY

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Ok. Rozbijmy to na czynniki pierwsze, pomijając fragmenty, które już znamy:

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Programowanie w Turbo Pascal

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Algorytmy i język C++

Pliki. Informacje ogólne. Obsługa plików w języku C

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

Struktury. Przykład W8_1

Wstęp do programowania

Nowoczesna OpenGL - rendering wielokątów Rendering wielokątów w kontekście biblioteki SFML

Laboratorium 1. I. Zainstaluj program Eclipse (wersja C/C++ w odpowiednim systemie operacyjnym

Druga aplikacja Prymitywy, alpha blending, obracanie bitmap oraz mały zestaw przydatnych funkcji wyświetlających własnej roboty.

Delphi podstawy programowania. Środowisko Delphi

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

IX. Wskaźniki.(3 godz.)

Programowanie komputerowe. Zajęcia 7

Podstawy języka C++ Maciej Trzebiński. Praktyki studenckie na LHC IFJ PAN. Instytut Fizyki Jądrowej Polskiej Akademii Nauk. M. Trzebiński C++ 1/16

Po uruchomieniu programu nasza litera zostanie wyświetlona na ekranie

Idź do. Spis treści Przykładowy rozdział Skorowidz. Katalog książek. Katalog online Zamów drukowany katalog. Twój koszyk.

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Transkrypt:

Informacje i porady dotyczące pisania shaderów. 1. Informacje ogólne Będziemy się zajmować shaderami w wersji 2.0, które są obsługiwane przez karty graficzne z procesorami ATI Radeon serii 9000 (premiera w 2002 roku) i późniejszymi oraz NVIDIA GeForce serii FX 5000 (premiera w 2003 roku) i późniejszymi. Komputery w laboratoriach komputerowych w sali 317 mają dobre karty graficzne, na których nie będzie problemów z uruchomieniem shaderów. Shadery można pisać w dowolnym edytorze i kompilować z użyciem funkcji DirectX/OpenGL, które również zwracają informacje o błędach w kodzie. Poza tym istnieją narzędzia do testowania samych shaderów takie jak ATI Rendermonkey (http://ati.amd.com/developer/rendermonkey/downloads.html), czy NVIDIA FX Composer, z którego jednak nigdy nie korzystałem (http://developer.nvidia.com/object/fx_composer_home.html). Produkt ATI obsługuje języki HLSL i GLSL, produkt NVIDII HLSL i CgFX, oba zawierają sporo przykładów. W dalszej części tego tekstu omawiane będą tylko języki HLSL dla DirectX i GLSL dla OpenGL. Shadery to programy wykonywane na karcie graficznej. Początkowo istniały dwa rodzaje shaderów i tylko one będą przedmiotem zajęć: shadery wierzchołków i shadery pikseli (w dokumentacji OpenGL nazywane programami wierzchołków i programami fragmentów). Shader wierzchołków, po jego uaktywnieniu, wywoływany jest raz dla każdego wierzchołka renderowanej siatki trójkątów. Otrzymuje na wejściu wszystkie dane związane z wierzchołkiem (pozycja w lokalnym układzie współrzędnych, normalna, współrzędne tekstury) i musi policzyć pozycję wierzchołka w układzie kamery. Poza tym może policzyć i przekazać do shadera pikseli dowolne dodatkowe informacje, przydatne potem przy wyliczeniach koloru piksela. Shader pikseli wywoływany jest raz dla każdego rysowanego piksela. Jego zadaniem jest policzenie koloru, wraz z wartością kanału alfa. Shader pikseli otrzymuje na wejściu to wszystko, co jest wyjściem shadera wierzchołków. Dokładniej po wywołaniu shadera wierzchołków dla każdego z wierzchołków rysowanego trójkąta, każda z wartości zwracanych przez shader wierzchołków jest interpolowana liniowo z korekcją perspektywy na powierzchni trójkąta i po interpolacji przekazywana do shadera pikseli.

2. Obsługa shaderów w DirectX. Skompilowane zbiory shaderów przechowywane są w obiektach typu Effect. Na początku po uruchomieniu aplikacji i zainicjowaniu urządzenia DirectX trzeba wczytać ich kod źródłowy w języku HLSL z pliku tekstowego (zwykle ma on rozszerzenie.fx ) i skompilować. Służy do tego na przykład polecenie Effect.FromFile(...). W jednym pliku HLSL może mieścić się dowolnie dużo shaderów wierzchołków i pikseli. Fragment pliku w języku HLSL postaci: technique render pass p0 VertexShader = compile vs_2_0 RenderVS(); PixelShader = compile ps_2_0 RenderPS(); definiuje technikę o nazwie render, na którą składa się para złożona z shadera wierzchołków (procedura RenderVS() w programie HLSL) i pikseli (procedura RenderPS() w programie HLSL). Wybranie aktywnej techniki dla obiektu typu Effect odbywa się poprzez przypisanie jej nazwy do pola.technique. Renderowanie z użyciem shaderów odbywa się tak: numpasses = effect.begin(fx.none); for (int passnumber = 0; passnumber < numpasses; ++passnumber) effect.beginpass(passnumber);... // tu wstawić wywołania funkcji rysujących effect.endpass(); effect.end(); Zmienne globalne w programie HLSL (stałe shadera) można i trzeba zmieniać z poziomu DirectX. Służy do tego metoda SetValue, której pierwszy parametr to napis z nazwą zmiennej globalnej, a drugim może być w zależności od typu tej zmiennej, obiekt tekstury, macierz, wektor, liczba. W kodzie HLSL macierz deklarujemy tak: float4x4 ViewProjectionMatrix;, wektor tak: float4 LightDir;, a teksturę tak: texture ColorTexture <string TextureType = "2D";>; sampler ColorSampler = sampler_state Texture = <ColorTexture>; MipFilter = LINEAR; MagFilter = LINEAR; MinFilter = LINEAR; ADDRESSU = clamp; ADDRESSV = clamp; ; (do tekstury będziemy się odwoływać poprzez ColorSampler ; widać, że w samym programie HLSL ustawiane są parametry filtrowania i zawijania tekstur). Wejście i wyjście shadera wierzchołków i pikseli najczęściej delkaruje się w HLSL w postaci struktur np.: struct VSInput float4 p : POSITION; float3 n : NORMAL;

float3 t : TEXCOORD0; ; Dla wejścia shadera wierzchołków napisy :POSITION, czy :NORMAL informują DirectX jak powiązać dane siatki trójkątów z odpowiednimi polami struktury. Takie same opisy muszą mieć wszystkie pola dla wyjścia oraz zarówno wejścia jak i wyjścia shadera pikseli. Shader wierzchołków musi zwrócić strukturę z wypełnionym polem z opisem :POSITION, a shader pikseli z :COLOR. Wejście shadera pikseli różni się zwykle od wyjścia shadera wierzchołków tylko tym, że nie posiada pola postaci float4 pos : POSITION;. Pola z opisami :TEXCOORD0 do :TEXCOORD7 należy traktować jako ogólnego przeznaczenia mogą przechowywać dowolne wartości, nie mające nic wspólnego z teksturowaniem. Shader wierzchołków i shader pikseli to pojedyncze funkcje, które mogą się odwoływać do innych funkcji w programie HLSL. Po resztę informacji na temat języka HLSL odsyłam do dokumentacji DirectX oraz analizy załączonych tam tutoriali i przykładów. Trzeba jeszcze tylko pamiętać, że uaktywnienie shaderów, wyłącza część funkcjonalności DirectX: światła, teksturowanie, macierze przekształceń odpowiedzialność za te zadania zostaje przeniesiona na shadery.

3. Obsługa shaderów w OpenGL Opisane tu zostanie korzystanie z języka GLSL (OpenGL Shading Language), który wszedł do standardu OpenGL w wersji 2.0. Aby mieć dostęp do funkcji standardu w wersji 2.0, w C/C++ wygodnie jest skorzystać z GLEW (OpenGL Extension Wrangler: http://glew.sourceforge.net/), a w C# z bibliotek TAO. Dokumentację OpenGL i GLSL można znaleźć tutaj: http://www.opengl.org/documentation/specs/. W GLSL najprościej przechowywać każdy shader w osobnym pliku tekstowym (shader wierzchołków i pikseli związany z jednym efektem w dwóch osobnych plikach). Na początku po zainicjowaniu OpenGL, trzeba wczytać i skompilować wszystkie shadery. Poniżej zamieszczam przykładowy fragment kodu w C, który to wykonuje: char * read_text_file(const char *filename) FILE *file = fopen(filename, "rt"); fseek(file, 0L, SEEK_END); long size = ftell(file); fseek(file, 0L, SEEK_SET); char *buf = new char[size+1]; int bytes = (int)fread(buf, 1, size, file); buf[bytes] = 0; fclose(file); return buf; void print_info_log(glhandlearb object) int maxlength = 0; glgetobjectparameterivarb(object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxlength); char *infolog = new char[maxlength]; glgetinfologarb(object, maxlength, &maxlength, infolog); MessageBoxA(NULL, infolog, "GLSL_ERROR", MB_OK); delete[] infolog; void add_shader(glhandlearb programobject, const char *filename, GLenum shadertype) GLcharARB *shaderdata = read_text_file(filename); const GLcharARB *const_shaderdata = shaderdata; GLhandleARB object = glcreateshaderobjectarb(shadertype); glshadersourcearb(object, 1, &const_shaderdata, NULL); glcompileshaderarb(object); GLint compiled = 0; glgetobjectparameterivarb(object, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); if (!compiled) print_info_log(object); exit(1); glattachobjectarb(programobject, object); gldeleteobjectarb(object); delete[] shaderdata; GLhandleARB init(const char *filenamevp, const char *filenamefp) GLhandleARB program = glcreateprogramobjectarb();

if (filenamevp) add_shader(program, filenamevp, GL_VERTEX_SHADER_ARB); add_shader(program, filenamefp, GL_FRAGMENT_SHADER_ARB); gllinkprogramarb(program); GLint linked = false; glgetobjectparameterivarb(program, GL_OBJECT_LINK_STATUS_ARB, &linked); if (!linked) print_info_log(program); exit(1); return program; Wywołanie funkcji init(...) z podanymi nazwami plików z programem wierzchołków (shaderem wierzchołków) i programem fragmentów (shaderem pikseli) w GLSL, utworzy obiekt typu GLhandleARB, przez który będzie można się od tej pory odwoływać do shaderów z poziomu OpenGL. W przypadku błędów w kodzie GLSL, funkcja print_info_log wypisze odpowiednie komunikaty w okienku informacyjnym. Renderowanie siatki trójkątów z użyciem shaderów odbywa się następująco: gluseprogramobjectarb(program);...// tu wywołujemy funkcje rysujące gluseprogramobjectarb(0); W OpenGL shadery mogą korzystać z macierzy przekształceń OpenGL, oraz ustawień tekstur OpenGL. Mimo to można i trzeba korzystać ze zmiennych globalnych (stałych shadera) w programach GLSL, które zmieniane są z poziomu OpenGL. W kodzie GLSL deklarujemy liczby, wektory, macierze, tekstury w postaci: uniform float fvalue; varying vec3 vvalue; uniform mat4 mvalue; uniform sampler2d texture;. Z poziomu OpenGL modyfikujemy ich wartość za pomocą wywołań: gluniform1farb(glgetuniformlocationarb(program, "fvalue"), fvalue); gluniform3fvarb(glgetuniformlocationarb(program, "vvalue"), 1, &(vvalue.x)); gluniformmatrix4fvarb(glgetuniformlocationarb(program, "mvalue"), 1, false, &(mvalue[0][0])); gluniform1iarb(glgetuniformlocationarb(program, "texture"), 0); W przypadku tekstury widać, że podajemy nie obiekt tekstury, tylko numer tekstury (numer aktywnej tekstury, której dotyczą wywołania OpenGL można zmienić z domyślnego 0 poprzez wywołanie glactivetexture(...)). Shader wierzchołków musi zawierać funkcję void main(), która musi zapisać do zmiennej gl_position pozycję wierzchołka w układzie kamery (normalnie jest to: gl_position = gl_projectionmatrix * gl_modelviewmatrix * gl_vertex; co jest równoważne w GLSL gl_position = ftransform();). W GLSL istnieje wiele nazw specjalnych zmiennych i stałych rozpoczynających się od gl_, które związane są z odpowiednimi obiektami w OpenGL i które są dostępne w dowolnym miejscu podczas pisania shaderów. Shader pikseli musi zawierać funkcję void main(), która zapisze kolor piksela wraz z wartością kanału alfa, do gl_fragcolor. Przekazywanie danych pomiędzy shaderem wierzchołków i shaderem pikseli odbywa się w bardzo wygodny sposób. Wystarczy zadeklarować w każdym z nich zmienną globalną o tej samej nazwie poprzedzoną słowem varying, a następnie zapisać do niej odpowiednio wyliczoną wartość w shaderze wierzchołków.