Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.99 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 = "Bartłomiej Gągol";
  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. glShaderSource(*shaderNum, 1, (const GLchar **)& shString, NULL);
  99.  
  100. free( shString );
  101.  
  102. // 7. Kompilacja obiektu cieniowania funkcją glCompileShader()
  103. // Parametrem jest identyfikator obiektu cieniowania,
  104. // ...
  105. glCompileShader(*shaderNum);
  106.  
  107.  
  108. // 8. Sprawdzenie statusu kompilacji funkcją glGetShaderiv()
  109. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  110. // drugim rodzaj sprawdzanego błędu (GL_COMPILE_STATUS)
  111. // trzecim adres zmiennej na zwracany kod błędu (success)
  112. // ...
  113. glGetShaderiv(*shaderNum, GL_COMPILE_STATUS, &success);
  114.  
  115. // 9. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  116. // Tekst komunikatu pobierany jest funkcją glGetShaderInfoLog()
  117. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  118. // drugim rozmiar bufora (MAX_INFO_LOG_SIZE)
  119. // trzecim NULL
  120. // czwartym bufor (infoLog)
  121. // Tekst błędu należy wypisać funkcją FatalError()
  122. // ...
  123. if(success == 0){
  124. glGetShaderInfoLog(*shaderNum, MAX_INFO_LOG_SIZE, NULL, infoLog);
  125. FatalError(infoLog, NULL, NULL);
  126. }
  127.  
  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.  
  158. // 14. Utworzenie obiektu programu cieniowania funkcją glCreateProgram()
  159. // Identyfikator obiektu programu cieniowania należy podstawić do odpowiedniego miejsca tablicy progObj
  160. // ...
  161. progObj[shaderNum] = glCreateProgram();
  162.  
  163. // 15. Dołączenie do obiektu programu cieniowania skompilowanego kodu VS funkcją glAttachShader()
  164. // Pierwszym parametrem jest identyfikator obiektu cieniowania,
  165. // drugim parametrem identyfikator obiektu VS
  166. // ...
  167. glAttachShader(progObj[shaderNum], vShader[shaderNum]);
  168.  
  169. // 16. Dołączenie do obiektu programu cieniowania skompilowanego kodu FS
  170. // ...
  171. glAttachShader(progObj[shaderNum], fShader[shaderNum]);
  172.  
  173.  
  174. // 17. Łączenie programu cieniowania funkcją glLinkProgram()
  175. // Parametrem jest identyfikator obiektu programu cieniowania
  176. // ...
  177. glLinkProgram(progObj[shaderNum]);
  178.  
  179. // 18. Sprawdzenie statusu łączenia funkcją glGetProgramiv()
  180. // Pierwszym parametrem jest identyfikator obiektu programu cieniowania,
  181. // drugim rodzaj sprawdzanego błędu (GL_LINK_STATUS)
  182. // trzecim adres zmiennej na zwracany kod błędu (success)
  183. // ...
  184. glGetProgramiv(progObj[shaderNum], GL_LINK_STATUS, &success);
  185.  
  186. // 19. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  187. // SHADER LINKING", "Unable to link"
  188. // ...
  189.  
  190. if(success == 0){
  191. FatalError("SHADER LINKING", "Unable to link", NULL);
  192. }
  193.  
  194.  
  195.  
  196.  
  197.  
  198. // 20. Ustawienie w odpowiednim miejscu tablicy needsValidation[]
  199. // informacji o konieczności walidacji programu cieniowania (GL_TRUE)
  200. // ...
  201. needsValidation[shaderNum] = GL_TRUE;
  202.  
  203. }
  204. // ------------------------------------------------------------------------
  205. void DrawModels(void)
  206. { // narysowanie obiektów na scenie, ustawienie parametrów Uniform dla jednostek cieniowania
  207. M3DVector3f lightPos0Eye, lightPos1Eye, lightPos2Eye;
  208. M3DMatrix44f mv;
  209.  
  210. // transformacja światła do przestrzeni kamery (eye space)
  211. glPushMatrix();
  212. glRotatef( lightRotation, 0.0, 1.0, 0.0 );
  213. glGetFloatv( GL_MODELVIEW_MATRIX, mv );
  214. m3dTransformVector3( lightPos0Eye, lightPos0, mv );
  215.  
  216.  
  217. if ( actualShader >= THREELIGHTS )
  218. {
  219. m3dTransformVector3( lightPos1Eye, lightPos1, mv );
  220. m3dTransformVector3( lightPos2Eye, lightPos2, mv );
  221. }
  222.  
  223. glPopMatrix();
  224. GLint uniformLoc;
  225.  
  226. // 29. Pobranie identyfikatora zmiennej Uniform dla źródła światła nr 0 funkcją glGetUniformLocation()
  227. // Pierwszym parametrem jest aktualny identyfikator obiektu programu cieniowania
  228. // drugim parametrem jest nazwa zmiennej Uniform "lightPos[0]"
  229. // Wynik należy podstawić do zmiennej uniformLoc
  230. // ...
  231. uniformLoc = glGetUniformLocation(progObj[actualShader], "lightPos[0]");
  232.  
  233.  
  234. // 30. Jeżeli zwrócony identyfikator jest różny od -1, ustawienie aktualnej pozycji światła 0 funkcją glUniform3fv()
  235. // Pierwszym parametrem jest identyfikator zmiennej,
  236. // drugim parametrem jest liczba argumentów (1)
  237. // trzecim parametrem wektor współrzędnych oświetlenia o (lightPos0Eye)
  238. // ...
  239. if(uniformLoc != -1){
  240. glUniform3fv(uniformLoc, 1, lightPos0Eye);
  241. }
  242.  
  243.  
  244. // 37. Analogiczne ustawienie parametru dla światła nr 1
  245. // ...
  246. uniformLoc = glGetUniformLocation(progObj[actualShader], "lightPos[1]");
  247.  
  248. if(uniformLoc != -1){
  249. glUniform3fv(uniformLoc, 1, lightPos1Eye);
  250. }
  251.  
  252.  
  253.  
  254. // 37. Analogiczne ustawienie parametru dla światła nr 2
  255. // ...
  256. uniformLoc = glGetUniformLocation(progObj[actualShader], "lightPos[2]");
  257.  
  258. if(uniformLoc != -1){
  259. glUniform3fv(uniformLoc, 1, lightPos2Eye);
  260. }
  261.  
  262.  
  263.  
  264.  
  265. // Narysowanie niebieskiej podstawy obiektów
  266. glColor3f( 0.0f, 0.0f, 0.90f );
  267. glNormal3f( 0.0f, 1.0f, 0.0f );
  268. glBegin( GL_QUADS );
  269. glVertex3f( -100.0f, -25.0f, -100.0f );
  270. glVertex3f( -100.0f, -25.0f, 100.0f );
  271. glVertex3f( 100.0f, -25.0f, 100.0f );
  272. glVertex3f( 100.0f, -25.0f, -100.0f );
  273. glEnd();
  274. // czerwony sześcian
  275. glColor3f( 1.0f, 0.0f, 0.0f );
  276. glutSolidCube( 48.0f );
  277. // zielona sfera
  278. glColor3f( 0.0f, 1.0f, 0.0f );
  279. glPushMatrix();
  280. glTranslatef( -60.0f, 0.0f, 0.0f );
  281. glutSolidSphere( 25.0f, 50, 50 );
  282. glPopMatrix();
  283. // bordowy torus
  284. glColor3f( 1.0f, 0.0f, 1.0f );
  285. glPushMatrix();
  286. glTranslatef( 0.0f, 0.0f, 60.0f );
  287. glutSolidTorus( 8.0f, 16.0f, 50, 50 );
  288. glPopMatrix();
  289. // żółty stożek
  290. glColor3f( 1.0f, 1.0f, 0.0f );
  291. glPushMatrix();
  292. glRotatef( -90.0f, 1.0f, 0.0f, 0.0f );
  293. glTranslatef( 60.0f, 0.0f, -24.0f );
  294. glutSolidCone( 25.0f, 50.0f, 50, 50 );
  295. glPopMatrix();
  296. // morski czajniczek
  297. glColor3f( 0.0f, 1.0f, 1.0f );
  298. glPushMatrix();
  299. glTranslatef( 0.0f, 0.0f, -60.0f );
  300. glutSolidTeapot( 25.0f );
  301. glPopMatrix();
  302. }
  303. void RenderScene( void )
  304. { // rysowanie sceny
  305. // ustawienie perspektywy
  306. glMatrixMode( GL_PROJECTION );
  307. glLoadIdentity();
  308. if ( windowWidth > windowHeight )
  309. {
  310. GLdouble ar = (GLdouble)windowWidth / (GLdouble)windowHeight;
  311. glFrustum( -ar * cameraZoom, ar * cameraZoom, -cameraZoom, cameraZoom, 1.0, 1000.0 );
  312. }
  313. else
  314. {
  315. GLdouble ar = (GLdouble)windowHeight / (GLdouble)windowWidth;
  316. glFrustum( -cameraZoom, cameraZoom, -ar * cameraZoom, ar * cameraZoom, 1.0, 1000.0 );
  317. }
  318. glMatrixMode( GL_MODELVIEW );
  319. glLoadIdentity();
  320. gluLookAt( cameraPos[ 0 ], cameraPos[ 1 ], cameraPos[ 2 ], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f );
  321. glViewport( 0, 0, windowWidth, windowHeight );
  322. // wyczyszczenie okna
  323. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  324.  
  325. GLint success;
  326. // 20. Walidacja aktualnego (actualShader) programu cieniowania.
  327. // WYŁĄCZNIE w przypadku, gdy potrzebuje walidacji needsValidation[]
  328. // UWAGA! actualShader jest indeksem!!!!!
  329. // ...
  330. if ( needsValidation[ actualShader ] )
  331. {
  332.  
  333. // 21. Walidacja aktualnego (actualShader) programu cieniowania funkcją glValidateProgram()
  334. // Parametrem jest aktualny identyfikator obiektu programu cieniowania
  335. // ...
  336. glValidateProgram(progObj[actualShader]);
  337.  
  338. // 22. Sprawdzenie statusu walidacji funkcją glGetProgramiv()
  339. // Pierwszym parametrem jest identyfikator obiektu programu cieniowania,
  340. // drugim rodzaj sprawdzanego błędu (GL_VALIDATE_STATUS)
  341. // trzecim adres zmiennej na zwracany kod błędu (success)
  342. // ...
  343. glGetProgramiv(progObj[actualShader], GL_VALIDATE_STATUS, &success);
  344.  
  345. // 23. Informacja o ewentualnym błędzie w przypadku, gdy success == 0
  346. // "SHADER VALIDATION", "Unable to validate"
  347. // ...
  348.  
  349. if(success == 0){
  350. FatalError("SHADER VALIDATION", "Unable to validate", NULL);
  351. }
  352.  
  353.  
  354.  
  355.  
  356.  
  357. // 24. Wyzerowanie informacji o potrzebie walidacji aktualnego programu cieniowania
  358. // ...
  359. needsValidation[actualShader] = GL_FALSE;
  360.  
  361. }
  362. // Narysowanie modeli
  363. DrawModels();
  364. if ( glGetError() != GL_NO_ERROR )
  365. fprintf( stderr, "GL Error!\n" );
  366. // narysowanie sceny
  367. glutSwapBuffers();
  368. }
  369.  
  370. // This function does any needed initialization on the rendering
  371. // context.
  372. void SetupRC()
  373. { // inicjalizacja sceny
  374. fprintf( stdout, "Masters of GLSL shaders (2016)\n\n" );
  375. // 4. Sprawdzenie spełnienia minimalnych wymogów wersji cieniowania SM (shadermodel)
  376. if ( !GLEE_VERSION_2_0 && ( !GLEE_ARB_fragment_shader || !GLEE_ARB_vertex_shader ||
  377. !GLEE_ARB_shader_objects || !GLEE_ARB_shading_language_100 ) )
  378. FatalError( "OpenGL version", "OpenGL version", "earlier then 2.0" );
  379.  
  380. fprintf( stdout, "Controls:\n" );
  381. fprintf( stdout, "\tR/L arrows\t+/- rotate lights\n\n" );
  382. fprintf( stdout, "\tx/X\t\tMove +/- in x direction\n" );
  383. fprintf( stdout, "\ty/Y\t\tMove +/- in y direction\n" );
  384. fprintf( stdout, "\tz/Z\t\tMove +/- in z direction\n\n" );
  385. fprintf( stdout, "\tq, ESC\t\tExit demo\n\n" );
  386.  
  387. // ustawienia OpenGL
  388. glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // czarne tło
  389. glEnable( GL_DEPTH_TEST );
  390. glDepthFunc( GL_LEQUAL );
  391. glShadeModel( GL_SMOOTH );
  392.  
  393. // 25. Wczytanie i przygotowanie wszystkich SHADERS_NUM programów cieniowania funkcją PrepareShader()
  394. // ...
  395. for(int i = 0; i < SHADERS_NUM; i++){
  396. PrepareShader(i);
  397. }
  398.  
  399.  
  400. // 26. Ustawienie aktualnego (actualShader) programu cieniowania funkcją glUseProgram()
  401. // Parametrem jest identyfikator aktualnego programu cieniowania
  402. // UWAGA! actualShader jest indeksem!!!!!
  403. // ...
  404. glUseProgram(progObj[actualShader]);
  405.  
  406. }
  407. char *SetTitle( void )
  408. {
  409. static char buffer[ 200 ];
  410. sprintf( buffer, "Master of GLSL shaders by %s [%s]", authorName, shaderNames[ actualShader ] );
  411. return( buffer );
  412. }
  413. void KeyPressFunc( unsigned char key, int x, int y )
  414. {
  415. switch ( key )
  416. {
  417. case ' ': // spacja
  418. actualShader = (ShaderTypes)( ( actualShader + 1 ) % SHADERS_NUM ); // naprzemienne włączenie kolejnych programów cieniowania
  419. glutSetWindowTitle( SetTitle() );
  420.  
  421. // 27. Ustawienie nowego (actualShader) programu cieniowania funkcją glUseProgram()
  422. // Parametrem jest identyfikator aktualnego programu cieniowania
  423. // ...
  424. glUseProgram(progObj[actualShader]);
  425.  
  426. break;
  427. case 'x':
  428. cameraPos[ 0 ] += 5.0f;
  429. break;
  430. case 'X':
  431. cameraPos[0] -= 5.0f;
  432. break;
  433. case 'y':
  434. cameraPos[ 1 ] += 5.0f;
  435. break;
  436. case 'Y':
  437. cameraPos[ 1 ] -= 5.0f;
  438. break;
  439. case 'z':
  440. cameraPos[ 2 ] += 5.0f;
  441. break;
  442. case 'Z':
  443. cameraPos[2] -= 5.0f;
  444. break;
  445. case 'q':
  446. case 'Q':
  447. case 27 : /* ESC */
  448. glutDestroyWindow( glutGetWindow() );
  449. break;
  450. }
  451. glutPostRedisplay(); // odświeżenie okna
  452. }
  453. void SpecialKeys(int key, int x, int y)
  454. {
  455. switch ( key )
  456. {
  457. case GLUT_KEY_LEFT:
  458. lightRotation -= 5.0f;
  459. break;
  460. case GLUT_KEY_RIGHT:
  461. lightRotation += 5.0f;
  462. break;
  463. case GLUT_KEY_UP:
  464. cameraPos[ 1 ] += 5.0f;
  465. break;
  466. case GLUT_KEY_DOWN:
  467. cameraPos[1] -= 5.0f;
  468. break;
  469. }
  470. glutPostRedisplay(); // odświeżenie okna
  471. }
  472. void ChangeSize( int w, int h )
  473. {
  474. windowWidth = w;
  475. windowHeight = h;
  476. }
  477.  
  478. int main( int argc, char* argv[] )
  479. {
  480. GLint i;
  481. glutInit( &argc, argv );
  482. glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
  483. glutInitWindowSize( windowWidth, windowHeight );
  484. glutCreateWindow( SetTitle() ); // utworzenie okna
  485. glutReshapeFunc( ChangeSize );
  486. glutKeyboardFunc( KeyPressFunc );
  487. glutSpecialFunc( SpecialKeys );
  488. glutDisplayFunc( RenderScene );
  489. SetupRC();
  490. glutMainLoop();
  491.  
  492. if ( glDeleteProgram && glDeleteShader )
  493. {
  494. // 26. Zwolnienie pamięci dla wszystkich (SHADERS_NUM) obiektów programu cieniowania
  495. // oraz jednostek cieniowania VS i FS funkcjami glDeleteProgram() oraz glDeleteShader()
  496. // ...
  497. for ( i = 0; i < SHADERS_NUM; i++ )
  498. {
  499. glDeleteProgram( progObj[ i ] );
  500. glDeleteShader( vShader[ i ] );
  501. glDeleteShader( fShader[ i ] );
  502. }
  503. }
  504. return 0;
  505. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement