Advertisement
Guest User

Untitled

a guest
Oct 19th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.69 KB | None | 0 0
  1. // lighting.c
  2. // By M.Szwoch, Based on
  3. // OpenGL SuperBible, Chapter 17
  4. // Demonstrates vertex and fragment shaders together
  5. // Program by Benjamin Lipchak
  6.  
  7. #include "../shared/gltools.h" // OpenGL toolkit
  8. #include "../shared/glFrame.h" // Frame toolkit
  9.  
  10. #include <stdio.h>
  11.  
  12. // 3. Dodaj swoje imię i nazwisko do belki tytułowej
  13. // ...
  14. const char *authorName = "Marek Lewandowski";
  15.  
  16. enum ShaderTypes { SIMPLE, DIFFUSE, SPECULAR, THREELIGHTS, FOG, PARAMS, SHADERS_NUM };
  17.  
  18. GLuint vShader[ SHADERS_NUM ]; // identyfikatory programów cieniowania wierzchołków (VS)
  19. GLuint fShader[ SHADERS_NUM ]; // identyfikatory programów cieniowania fragmentów (FS)
  20. GLuint progObj[ SHADERS_NUM ]; // obiekty programów cieniowania (VS+FS)
  21. GLboolean needsValidation[ SHADERS_NUM ]; // informacja o aktualności programu cieniownaia
  22. char *shaderNames[ SHADERS_NUM ] =
  23. { // nazwy programów cieniowania
  24. "simple",
  25. "diffuse",
  26. "specular",
  27. "3lights",
  28. "fog",
  29. "params"
  30. };
  31. // aktualny program cieniowania
  32. ShaderTypes actualShader = SIMPLE;
  33. // rozmiary okna
  34. GLint windowWidth = 1024;
  35. GLint windowHeight = 768;
  36.  
  37. GLint mainMenu, shaderMenu; // menu handles
  38.  
  39. GLfloat cameraPos[] = { 100.0f, 75.0f, 150.0f, 1.0f };
  40. GLdouble cameraZoom = 0.4;
  41.  
  42. GLfloat lightPos0[] = { 140.0f, 250.0f, 140.0f, 1.0f };
  43. GLfloat lightPos1[] = { -140.0f, 250.0f, 140.0f, 1.0f };
  44. GLfloat lightPos2[] = { 0.0f, 250.0f, -200.0f, 1.0f };
  45.  
  46. GLfloat lightRotation = 0.0f;
  47.  
  48. #define MAX_INFO_LOG_SIZE 2048
  49. GLchar infoLog[ MAX_INFO_LOG_SIZE ]; // bufor na błędy obsługi programów cieniowania
  50. void FatalError( char *errorKind, char *errorDescription, char *errorDetails )
  51. { // wyświetlenie informacji o błędzie i zakończenie programu ("radykalna" obsługa błędów)
  52. fprintf( stderr, "!!! %s ERROR !!!\n", errorKind );
  53. fprintf( stderr, " %s \"%s\"\n", errorDescription, errorDetails );
  54. Sleep( 5000 );
  55. exit( 0 );
  56. }
  57. GLchar *LoadShaderText( const char *fileName )
  58. { // Załadowanie z pliku kodu źródłowego programu cieniowania jako tekstu w formacie ASCIIZ
  59. GLchar *shaderText = NULL;
  60. GLint shaderLength = 0;
  61. FILE *fp;
  62. fp = fopen( fileName, "r" );
  63. if ( fp != NULL )
  64. {
  65. while ( fgetc( fp ) != EOF )
  66. shaderLength++;
  67. rewind( fp );
  68. shaderText = (GLchar *)malloc( shaderLength + 1 );
  69. if ( shaderText != NULL )
  70. fread( shaderText, 1, shaderLength, fp );
  71. shaderText[ shaderLength ] = '\0';
  72. fclose( fp );
  73. }
  74. return shaderText;
  75. }
  76. void LoadAndCompileShader( char * fullFileName, GLuint shaderKind, GLuint *shaderNum )
  77. { // załadowanie programu cieniowania z dysku i jego kompilacja
  78. // załadowanie programu cieniowania z dysku
  79. GLint success;
  80. GLchar *shString = LoadShaderText( fullFileName ); // załadowanie kodu źródłowego
  81. fprintf( stdout, "Loading '%s' shader\n", fullFileName );
  82.  
  83. if ( !shString )
  84. FatalError( "LOADING", "Unable to load", fullFileName );
  85.  
  86. // 5. Utworzenie obiektu cieniowania funkcją glCreateShader()
  87. // Parametrem jest rodzaj obiektu cieniowania (shaderKind)
  88. // Wynik wywołania należy podstawić do identyfikator obiektu (*shaderNum)
  89. // ...
  90. *shaderNum = glCreateShader(shaderKind);
  91.  
  92. // 6. Wskazanie kodu źródłowego obiektu cieniowania funkcją glShaderSource()
  93. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  94. // drugim liczba obiektów (1),
  95. // trzecim wskaźnik na wskaźnik (const GLchar **)& na kod źródłowy
  96. // czwartym NULL
  97. // ...
  98. const char * src = shString;
  99. glShaderSource(*shaderNum, 1, &src, NULL);
  100.  
  101.  
  102. free( shString );
  103.  
  104. // 7. Kompilacja obiektu cieniowania funkcją glCompileShader()
  105. // Parametrem jest identyfikator obiektu cieniowania,
  106. // ...
  107. glCompileShader(*shaderNum);
  108.  
  109.  
  110. // 8. Sprawdzenie statusu kompilacji funkcją glGetShaderiv()
  111. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  112. // drugim rodzaj sprawdzanego błędu (GL_COMPILE_STATUS)
  113. // trzecim adres zmiennej na zwracany kod błędu (success)
  114. // ...
  115. glGetShaderiv(*shaderNum, GL_COMPILE_STATUS, &success);
  116.  
  117. // 9. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  118. // Tekst komunikatu pobierany jest funkcją glGetShaderInfoLog()
  119. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  120. // drugim rozmiar bufora (MAX_INFO_LOG_SIZE)
  121. // trzecim NULL
  122. // czwartym bufor (infoLog)
  123. // Tekst błędu należy wypisać funkcją FatalError()
  124. // ...
  125. if (success == 0) {
  126. glGetShaderInfoLog(*shaderNum, MAX_INFO_LOG_SIZE, NULL, infoLog);
  127. FatalError("Błąd kmpilacji", "nw", infoLog);
  128. }
  129.  
  130.  
  131. }
  132. void PrepareShader( GLint shaderNum )
  133. { // Przygotowanie programu cieniowania
  134. char fullFileName[ 255 ];
  135. GLint success;
  136.  
  137. // Określenie w fullFileName nazwy względnej pliku ze wskazanym przez shaderNum programem cieniowania wierzchołków
  138. sprintf( fullFileName, "./shaders/%s.vs", shaderNames[ shaderNum ] );
  139.  
  140. // 11. Załadowanie i kompilacja programu cieniowania wierzchołków funkcją LoadAndCompileShader()
  141. // Pierwszym parametrem jest nazwa pliku,
  142. // drugim rodzaj programu cieniowania (GL_VERTEX_SHADER)
  143. // trzecim adres odpowiedniego pola w tablicy identyfikatorów obiektów cieniowania vShader
  144. // ...
  145. LoadAndCompileShader(fullFileName, GL_VERTEX_SHADER, &vShader[shaderNum]);
  146.  
  147. // 12. Określenie nazwy względnej pliku ze wskazanym (shaderNum) programem cieniowania fragmentów
  148. // Pliki mają rozszerzenie "fs"
  149. // ...
  150. sprintf(fullFileName, "./shaders/%s.fs", shaderNames[shaderNum]);
  151.  
  152.  
  153. // 13. Załadowanie i kompilacja programu cieniowania fragmentów: (GL_FRAGMENT_SHADER, fShader)
  154. // ...
  155. LoadAndCompileShader(fullFileName, GL_FRAGMENT_SHADER, &fShader[shaderNum]);
  156.  
  157. // 14. Utworzenie obiektu programu cieniowania funkcją glCreateProgram()
  158. // Identyfikator obiektu programu cieniowania należy podstawić do odpowiedniego miejsca tablicy progObj
  159. // ...
  160. progObj[shaderNum] = glCreateProgram();
  161.  
  162. // 15. Dołączenie do obiektu programu cieniowania skompilowanego kodu VS funkcją glAttachShader()
  163. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  164. // drugim parametrem identyfikator obiektu VS
  165. // ...
  166. glAttachShader(progObj[shaderNum], vShader[shaderNum]);
  167.  
  168. // 16. Dołączenie do obiektu programu cieniowania skompilowanego kodu FS
  169. // ...
  170. glAttachShader(progObj[shaderNum], fShader[shaderNum]);
  171.  
  172. // 17. Łączenie programu cieniowania funkcją glLinkProgram()
  173. // Parametrem jest identyfikator obiektu programu cieniowania
  174. // ...
  175. glLinkProgram(progObj[shaderNum]);
  176.  
  177.  
  178. // 18. Sprawdzenie statusu łączenia funkcją glGetProgramiv()
  179. // Pierwszym parametrem jest identyfikator obiektu programu cieniowania,
  180. // drugim rodzaj sprawdzanego błędu (GL_LINK_STATUS)
  181. // trzecim adres zmiennej na zwracany kod błędu (success)
  182. // ...
  183. glGetProgramiv(progObj[shaderNum], GL_LINK_STATUS, &success);
  184.  
  185.  
  186. // 19. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  187. // SHADER LINKING", "Unable to link"
  188. // ...
  189. if (success == 0) {
  190. FatalError("SHADER LINKING", "Unable to link", "");
  191. }
  192.  
  193.  
  194.  
  195. // 20. Ustawienie w odpowiednim miejscu tablicy needsValidation[]
  196. // informacji o konieczności walidacji programu cieniowania (GL_TRUE)
  197. // ...
  198. needsValidation[shaderNum] = GL_TRUE;
  199. }
  200. // ------------------------------------------------------------------------
  201. void DrawModels(void)
  202. { // narysowanie obiektów na scenie, ustawienie parametrów Uniform dla jednostek cieniowania
  203. M3DVector3f lightPos0Eye, lightPos1Eye, lightPos2Eye;
  204. M3DMatrix44f mv;
  205.  
  206. // transformacja światła do przestrzeni kamery (eye space)
  207. glPushMatrix();
  208. glRotatef( lightRotation, 0.0, 1.0, 0.0 );
  209. glGetFloatv( GL_MODELVIEW_MATRIX, mv );
  210. m3dTransformVector3( lightPos0Eye, lightPos0, mv );
  211.  
  212.  
  213. if ( actualShader >= THREELIGHTS )
  214. {
  215. m3dTransformVector3( lightPos1Eye, lightPos1, mv );
  216. m3dTransformVector3( lightPos2Eye, lightPos2, mv );
  217. }
  218.  
  219. glPopMatrix();
  220. GLint uniformLoc;
  221.  
  222. // 29. Pobranie identyfikatora zmiennej Uniform dla źródła światła nr 0 funkcją glGetUniformLocation()
  223. // Pierwszym parametrem jest aktualny identyfikator obiektu programu cieniowania
  224. // drugim parametrem jest nazwa zmiennej Uniform "lightPos[0]"
  225. // Wynik należy podstawić do zmiennej uniformLoc
  226. // ...
  227. uniformLoc = glGetUniformLocation(progObj[actualShader], "lightPos0");
  228.  
  229. // 30. Jeżeli zwrócony identyfikator jest różny od -1, ustawienie aktualnej pozycji światła 0 funkcją glUniform3fv()
  230. // Pierwszym parametrem jest identyfikator zmiennej,
  231. // drugim parametrem jest liczba argumentów (1)
  232. // trzecim parametrem wektor współrzędnych oświetlenia o (lightPos0Eye)
  233. // ...
  234. if (uniformLoc != 1)
  235. {
  236. glUniform3fv(uniformLoc, 1, lightPos0Eye);
  237. }
  238.  
  239.  
  240. // 37. Analogiczne ustawienie parametru dla światła nr 1
  241. // ...
  242.  
  243.  
  244.  
  245.  
  246. // 37. Analogiczne ustawienie parametru dla światła nr 2
  247. // ...
  248.  
  249.  
  250.  
  251.  
  252. // Narysowanie niebieskiej podstawy obiektów
  253. glColor3f( 0.0f, 0.0f, 0.90f );
  254. glNormal3f( 0.0f, 1.0f, 0.0f );
  255. glBegin( GL_QUADS );
  256. glVertex3f( -100.0f, -25.0f, -100.0f );
  257. glVertex3f( -100.0f, -25.0f, 100.0f );
  258. glVertex3f( 100.0f, -25.0f, 100.0f );
  259. glVertex3f( 100.0f, -25.0f, -100.0f );
  260. glEnd();
  261. // czerwony sześcian
  262. glColor3f( 1.0f, 0.0f, 0.0f );
  263. glutSolidCube( 48.0f );
  264. // zielona sfera
  265. glColor3f( 0.0f, 1.0f, 0.0f );
  266. glPushMatrix();
  267. glTranslatef( -60.0f, 0.0f, 0.0f );
  268. glutSolidSphere( 25.0f, 50, 50 );
  269. glPopMatrix();
  270. // bordowy torus
  271. glColor3f( 1.0f, 0.0f, 1.0f );
  272. glPushMatrix();
  273. glTranslatef( 0.0f, 0.0f, 60.0f );
  274. glutSolidTorus( 8.0f, 16.0f, 50, 50 );
  275. glPopMatrix();
  276. // żółty stożek
  277. glColor3f( 1.0f, 1.0f, 0.0f );
  278. glPushMatrix();
  279. glRotatef( -90.0f, 1.0f, 0.0f, 0.0f );
  280. glTranslatef( 60.0f, 0.0f, -24.0f );
  281. glutSolidCone( 25.0f, 50.0f, 50, 50 );
  282. glPopMatrix();
  283. // morski czajniczek
  284. glColor3f( 0.0f, 1.0f, 1.0f );
  285. glPushMatrix();
  286. glTranslatef( 0.0f, 0.0f, -60.0f );
  287. glutSolidTeapot( 25.0f );
  288. glPopMatrix();
  289. }
  290. void RenderScene( void )
  291. { // rysowanie sceny
  292. // ustawienie perspektywy
  293. glMatrixMode( GL_PROJECTION );
  294. glLoadIdentity();
  295. if ( windowWidth > windowHeight )
  296. {
  297. GLdouble ar = (GLdouble)windowWidth / (GLdouble)windowHeight;
  298. glFrustum( -ar * cameraZoom, ar * cameraZoom, -cameraZoom, cameraZoom, 1.0, 1000.0 );
  299. }
  300. else
  301. {
  302. GLdouble ar = (GLdouble)windowHeight / (GLdouble)windowWidth;
  303. glFrustum( -cameraZoom, cameraZoom, -ar * cameraZoom, ar * cameraZoom, 1.0, 1000.0 );
  304. }
  305. glMatrixMode( GL_MODELVIEW );
  306. glLoadIdentity();
  307. gluLookAt( cameraPos[ 0 ], cameraPos[ 1 ], cameraPos[ 2 ], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f );
  308. glViewport( 0, 0, windowWidth, windowHeight );
  309. // wyczyszczenie okna
  310. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  311.  
  312. GLint success;
  313. // 20. Walidacja aktualnego (actualShader) programu cieniowania.
  314. // WYŁĄCZNIE w przypadku, gdy potrzebuje walidacji needsValidation[]
  315. // UWAGA! actualShader jest indeksem!!!!!
  316. // ...
  317. if ( needsValidation[ actualShader ] )
  318. {
  319.  
  320. // 21. Walidacja aktualnego (actualShader) programu cieniowania funkcją glValidateProgram()
  321. // Parametrem jest aktualny identyfikator obiektu programu cieniowania
  322. // ...
  323. glValidateProgram(progObj[actualShader]);
  324.  
  325. // 22. Sprawdzenie statusu walidacji funkcją glGetProgramiv()
  326. // Pierwszym parametrem jest identyfikator obiektu programu cieniowania,
  327. // drugim rodzaj sprawdzanego błędu (GL_VALIDATE_STATUS)
  328. // trzecim adres zmiennej na zwracany kod błędu (success)
  329. // ...
  330. glGetProgramiv(progObj[actualShader], GL_VALIDATE_STATUS, &success);
  331.  
  332. // 23. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  333. // "SHADER VALIDATION", "Unable to validate"
  334. // ...
  335. if (success == 0) {
  336. FatalError("SHADER VALIDATION", "Unable to validate", "");
  337. }
  338.  
  339.  
  340. // 24. Wyzerowanie informacji o potrzebie walidacji aktualnego programu cieniowania
  341. // ...
  342. needsValidation[actualShader] = GL_FALSE;
  343. }
  344. // Narysowanie modeli
  345. DrawModels();
  346. if ( glGetError() != GL_NO_ERROR )
  347. fprintf( stderr, "GL Error!\n" );
  348. // narysowanie sceny
  349. glutSwapBuffers();
  350. }
  351.  
  352. // This function does any needed initialization on the rendering
  353. // context.
  354. void SetupRC()
  355. { // inicjalizacja sceny
  356. fprintf( stdout, "Masters of GLSL shaders (2016)\n\n" );
  357. // 4. Sprawdzenie spełnienia minimalnych wymogów wersji cieniowania SM (shadermodel)
  358. if ( !GLEE_VERSION_2_0 && ( !GLEE_ARB_fragment_shader || !GLEE_ARB_vertex_shader ||
  359. !GLEE_ARB_shader_objects || !GLEE_ARB_shading_language_100 ) )
  360. FatalError( "OpenGL version", "OpenGL version", "earlier then 2.0" );
  361.  
  362. fprintf( stdout, "Controls:\n" );
  363. fprintf( stdout, "\tR/L arrows\t+/- rotate lights\n\n" );
  364. fprintf( stdout, "\tx/X\t\tMove +/- in x direction\n" );
  365. fprintf( stdout, "\ty/Y\t\tMove +/- in y direction\n" );
  366. fprintf( stdout, "\tz/Z\t\tMove +/- in z direction\n\n" );
  367. fprintf( stdout, "\tq, ESC\t\tExit demo\n\n" );
  368.  
  369. // ustawienia OpenGL
  370. glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // czarne tło
  371. glEnable( GL_DEPTH_TEST );
  372. glDepthFunc( GL_LEQUAL );
  373. glShadeModel( GL_SMOOTH );
  374.  
  375. // 25. Wczytanie i przygotowanie wszystkich SHADERS_NUM programów cieniowania funkcją PrepareShader()
  376. // ...
  377. for (int i = 0; i < SHADERS_NUM; i++) {
  378. PrepareShader(i);
  379. }
  380.  
  381.  
  382. // 26. Ustawienie aktualnego (actualShader) programu cieniowania funkcją glUseProgram()
  383. // Parametrem jest identyfikator aktualnego programu cieniowania
  384. // UWAGA! actualShader jest indeksem!!!!!
  385. // ...
  386. glUseProgram(progObj[actualShader]);
  387.  
  388. }
  389. char *SetTitle( void )
  390. {
  391. static char buffer[ 200 ];
  392. sprintf( buffer, "Master of GLSL shaders by %s [%s]", authorName, shaderNames[ actualShader ] );
  393. return( buffer );
  394. }
  395. void KeyPressFunc( unsigned char key, int x, int y )
  396. {
  397. switch ( key )
  398. {
  399. case ' ': // spacja
  400. actualShader = (ShaderTypes)( ( actualShader + 1 ) % SHADERS_NUM ); // naprzemienne włączenie kolejnych programów cieniowania
  401. glutSetWindowTitle( SetTitle() );
  402.  
  403. // 27. Ustawienie nowego (actualShader) programu cieniowania funkcją glUseProgram()
  404. // Parametrem jest identyfikator aktualnego programu cieniowania
  405. // ...
  406. glUseProgram(progObj[actualShader]);
  407. break;
  408. case 'x':
  409. cameraPos[ 0 ] += 5.0f;
  410. break;
  411. case 'X':
  412. cameraPos[0] -= 5.0f;
  413. break;
  414. case 'y':
  415. cameraPos[ 1 ] += 5.0f;
  416. break;
  417. case 'Y':
  418. cameraPos[ 1 ] -= 5.0f;
  419. break;
  420. case 'z':
  421. cameraPos[ 2 ] += 5.0f;
  422. break;
  423. case 'Z':
  424. cameraPos[2] -= 5.0f;
  425. break;
  426. case 'q':
  427. case 'Q':
  428. case 27 : /* ESC */
  429. glutDestroyWindow( glutGetWindow() );
  430. break;
  431. }
  432. glutPostRedisplay(); // odświeżenie okna
  433. }
  434. void SpecialKeys(int key, int x, int y)
  435. {
  436. switch ( key )
  437. {
  438. case GLUT_KEY_LEFT:
  439. lightRotation -= 5.0f;
  440. break;
  441. case GLUT_KEY_RIGHT:
  442. lightRotation += 5.0f;
  443. break;
  444. case GLUT_KEY_UP:
  445. cameraPos[ 1 ] += 5.0f;
  446. break;
  447. case GLUT_KEY_DOWN:
  448. cameraPos[1] -= 5.0f;
  449. break;
  450. }
  451. glutPostRedisplay(); // odświeżenie okna
  452. }
  453. void ChangeSize( int w, int h )
  454. {
  455. windowWidth = w;
  456. windowHeight = h;
  457. }
  458.  
  459. int main( int argc, char* argv[] )
  460. {
  461. GLint i;
  462. glutInit( &argc, argv );
  463. glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
  464. glutInitWindowSize( windowWidth, windowHeight );
  465. glutCreateWindow( SetTitle() ); // utworzenie okna
  466. glutReshapeFunc( ChangeSize );
  467. glutKeyboardFunc( KeyPressFunc );
  468. glutSpecialFunc( SpecialKeys );
  469. glutDisplayFunc( RenderScene );
  470. SetupRC();
  471. glutMainLoop();
  472.  
  473. if ( glDeleteProgram && glDeleteShader )
  474. {
  475. // 26. Zwolnienie pamięci dla wszystkich (SHADERS_NUM) obiektów programu cieniowania
  476. // oraz jednostek cieniowania VS i FS funkcjami glDeleteProgram() oraz glDeleteShader()
  477. // ...
  478. for ( i = 0; i < SHADERS_NUM; i++ )
  479. {
  480. glDeleteProgram( progObj[ i ] );
  481. glDeleteShader( vShader[ i ] );
  482. glDeleteShader( fShader[ i ] );
  483. }
  484. }
  485. return 0;
  486. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement