歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> OpenGL的GLSL編程初探

OpenGL的GLSL編程初探

日期:2017/3/1 10:06:45   编辑:Linux編程

先發個截圖:當然看到這個界面大家肯定覺得這不就是個三角形,這不是我想說的,重點在後邊。

先附上代碼,首先是main.cpp文件:

  1. #include "GL\glew.h"
  2. #include "GL\glut.h"
  3. #include <gl\GL.h>
  4. #include <gl\GLU.h>
  5. #include <Windows.h>
  6. #include <stdio.h>
  7. GLuint program;
  8. GLint attribute_coord2d;
  9. char* file_read(const char* filename)
  10. {
  11. FILE* input = fopen(filename, "rb");
  12. if(input == NULL) return NULL;
  13. if(fseek(input, 0, SEEK_END) == -1) return NULL;
  14. long size = ftell(input);
  15. if(size == -1) return NULL;
  16. if(fseek(input, 0, SEEK_SET) == -1) return NULL;
  17. /*if using c-compiler: dont cast malloc's return value*/
  18. char *content = (char*) malloc( (size_t) size +1 );
  19. if(content == NULL) return NULL;
  20. fread(content, 1, (size_t)size, input);
  21. if(ferror(input)) {
  22. free(content);
  23. return NULL;
  24. }
  25. fclose(input);
  26. content[size] = '\0';
  27. return content;
  28. }
  29. /**
  30. * Display compilation errors from the OpenGL shader compiler
  31. */
  32. void print_log(GLuint object)
  33. {
  34. GLint log_length = 0;
  35. if (glIsShader(object))
  36. glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
  37. else if (glIsProgram(object))
  38. glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
  39. else {
  40. fprintf(stderr, "printlog: Not a shader or a program\n");
  41. return;
  42. }
  43. char* log = (char*)malloc(log_length);
  44. if (glIsShader(object))
  45. glGetShaderInfoLog(object, log_length, NULL, log);
  46. else if (glIsProgram(object))
  47. glGetProgramInfoLog(object, log_length, NULL, log);
  48. fprintf(stderr, "%s", log);
  49. free(log);
  50. }
  51. /**
  52. * Compile the shader from file 'filename', with error handling
  53. */
  54. GLuint create_shader(const char* filename, GLenum type)
  55. {
  56. const GLchar* source = file_read(filename);
  57. if (source == NULL) {
  58. fprintf(stderr, "Error opening %s: ", filename); perror("");
  59. return 0;
  60. }
  61. GLuint res = glCreateShader(type);
  62. const GLchar* sources[2] = {
  63. #ifdef GL_ES_VERSION_2_0
  64. "#version 100\n"
  65. "#define GLES2\n",
  66. #else
  67. "#version 120\n",
  68. #endif
  69. source };
  70. glShaderSource(res, 2, sources, NULL);
  71. free((void*)source);
  72. glCompileShader(res);
  73. GLint compile_ok = GL_FALSE;
  74. glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
  75. if (compile_ok == GL_FALSE) {
  76. fprintf(stderr, "%s:", filename);
  77. print_log(res);
  78. glDeleteShader(res);
  79. return 0;
  80. }
  81. return res;
  82. }
  83. int init_resources(void)
  84. {
  85. /* FILLED IN LATER */
  86. GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
  87. GLuint vs, fs;
  88. if ((vs = create_shader("triangle.v.glsl", GL_VERTEX_SHADER)) == 0) return 0;
  89. if ((fs = create_shader("triangle.f.glsl", GL_FRAGMENT_SHADER)) == 0) return 0;
  90. program = glCreateProgram();
  91. glAttachShader(program, vs);
  92. glAttachShader(program, fs);
  93. glLinkProgram(program);
  94. glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
  95. if (!link_ok) {
  96. fprintf(stderr, "glLinkProgram:");
  97. print_log(program);
  98. }
  99. return 0;
  100. }
  101. void onDisplay()
  102. {
  103. /* Clear the background as white */
  104. glClearColor(1.0, 1.0, 1.0, 1.0);
  105. glClear(GL_COLOR_BUFFER_BIT);
  106. glUseProgram(program);
  107. glEnableVertexAttribArray(attribute_coord2d);
  108. GLfloat triangle_vertices[] = {
  109. 0.0, 0.8,
  110. -0.8, -0.8,
  111. 0.8, -0.8,
  112. };
  113. /* Describe our vertices array to OpenGL (it can't guess its format automatically) */
  114. glVertexAttribPointer(
  115. attribute_coord2d, // attribute
  116. 2, // number of elements per vertex, here (x,y)
  117. GL_FLOAT, // the type of each element
  118. GL_FALSE, // take our values as-is
  119. 0, // no extra data between each position
  120. triangle_vertices // pointer to the C array
  121. );
  122. /* Push each element in buffer_vertices to the vertex shader */
  123. glDrawArrays(GL_TRIANGLES, 0, 3);
  124. glDisableVertexAttribArray(attribute_coord2d);
  125. /* Display the result */
  126. glutSwapBuffers();
  127. }
  128. void free_resources()
  129. {
  130. glDeleteProgram(program);
  131. }
  132. int main(int argc, char* argv[])
  133. {
  134. /* Glut-related initialising functions */
  135. glutInit(&argc, argv);
  136. glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
  137. glEnable(GL_BLEND);
  138. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  139. glutInitWindowSize(640, 480);
  140. glutCreateWindow("My First Triangle");
  141. /* Extension wrangler initialising */
  142. GLenum glew_status = glewInit();
  143. if (glew_status != GLEW_OK)
  144. {
  145. fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
  146. return EXIT_FAILURE;
  147. }
  148. /* When all init functions runs without errors,
  149. the program can initialise the resources */
  150. if (0 == init_resources())
  151. {
  152. /* We can display it if everything goes OK */
  153. glutDisplayFunc(onDisplay);
  154. glutMainLoop();
  155. }
  156. /* If the program exits in the usual way,
  157. free resources and exit with a success */
  158. free_resources();
  159. return EXIT_SUCCESS;
  160. }

我的操作系統是win7 x64位,采用了glew 和freeglut庫,這些庫可以從相應的網站上下載,這裡就不說了,主要看一個函數create_shader這個函數,裡面負責從文件中讀取GLSL的代碼,然後將其編譯,後面將其連接然後進行執行。將三個文件放在同一目錄下即可編譯通過,那些繁瑣的理論知識這裡就不廢話了。

接下來來看這兩個文件吧(triangle.v.glsl和triangle.f.glsl):

//triangle.v.glsl

  1. attribute vec2 coord2d;
  2. void main(void)
  3. {
  4. gl_Position = vec4(coord2d, 0.0, 1.0);
  5. }

//triangle.f.glsl

  1. void main(void)
  2. {
  3. gl_FragColor[0] = gl_FragCoord.x/640.0;
  4. gl_FragColor[1] = gl_FragCoord.y/480.0;
  5. gl_FragColor[2] = 0.5;
  6. gl_FragColor[3] = floor(mod(gl_FragCoord.y, 2.0));
  7. };
Copyright © Linux教程網 All Rights Reserved