Advertisement
Guest User

Untitled

a guest
Jan 18th, 2017
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.53 KB | None | 0 0
  1. #include "cassert"
  2. #include "cmath"
  3. #include "cstdio"
  4. #include "cstdlib"
  5. #include "cstdint"
  6. #include "GL/glew.h"
  7. #include "glm/fwd.hpp"
  8. #include "glm/glm.hpp"
  9. #include "glm/gtc/matrix_transform.hpp"
  10. #include "glm/gtc/type_ptr.hpp"
  11. #include "iostream"
  12. #include "SDL2/SDL.h"
  13.  
  14. #define PROJ_NAME   "example"
  15. #define WIN_NAME    "Example"
  16. #define SCR_WIDTH   640
  17. #define SCR_HEIGHT  480
  18.  
  19. #define TEST_GL_ERROR(ERR_MSG)                                                      \
  20. do {                                                                                \
  21.     GLenum err;                                                                     \
  22.     if((err = glGetError()) != GL_NO_ERROR)                                         \
  23.     {                                                                               \
  24.         cerr << PROJ_NAME << ": " << ERR_MSG << ": " << gluErrorString(err) << endl;\
  25.         exit(EXIT_FAILURE);                                                         \
  26.     }                                                                               \
  27. } while(false)
  28.  
  29. using namespace std;
  30.  
  31. SDL_Window *        g_window = nullptr;
  32. SDL_GLContext       g_context = 0;
  33. GLuint              g_textures[6];
  34. glm::mat4           g_proj = glm::perspective(glm::radians(60.0f), (float)SCR_WIDTH /
  35.                     (float)SCR_HEIGHT, 1.0f, 100.0f),
  36.                     g_view,
  37.                     g_model;
  38.  
  39.  
  40. void init(int * argc, char ** argv);
  41. void loadMedia();
  42. void cleanup();
  43. GLuint loadTexture(const uint8_t * texels, int w, int h);
  44. GLuint loadShader(const char * src, GLenum type);
  45. GLuint loadAttrib
  46. (
  47.     GLuint program,
  48.     const char * name,
  49.     GLint size,
  50.     GLenum type,
  51.     GLboolean normalized,
  52.     GLsizei stride,
  53.     GLsizei offset
  54. );
  55.  
  56. int main(int argc, char ** argv)
  57. {
  58.     init(&argc, argv);
  59.     loadMedia();
  60.    
  61.     GLenum err;
  62.     float angle = 0;
  63.     SDL_Event e;
  64.    
  65.     struct {
  66.         glm::vec3 pos;
  67.         glm::vec2 textCoord;
  68.         GLuint textNum;
  69.     } vertices[] = {
  70.         { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(0, 1), 0 },
  71.         { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(0, 0), 0 },
  72.         { glm::vec3(0.5, -0.5, 0.5), glm::vec2(1, 0), 0 },
  73.         { glm::vec3(0.5, 0.5, 0.5), glm::vec2(1, 1), 0 },
  74.         { glm::vec3(0, 0, 0.5), glm::vec2(0.5, 0.5), 0 },
  75.        
  76.         { glm::vec3(0.5, 0.5, 0.5), glm::vec2(0, 1), 1 },
  77.         { glm::vec3(0.5, -0.5, 0.5), glm::vec2(0, 0), 1 },
  78.         { glm::vec3(0.5, -0.5, -0.5), glm::vec2(1, 0), 1 },
  79.         { glm::vec3(0.5, 0.5, -0.5), glm::vec2(1, 1), 1 },
  80.         { glm::vec3(0.5, 0, 0), glm::vec2(0.5, 0.5), 1 },
  81.        
  82.         { glm::vec3(0.5, 0.5, -0.5), glm::vec2(0, 1), 2 },
  83.         { glm::vec3(0.5, -0.5, -0.5), glm::vec2(0, 0), 2 },
  84.         { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(1, 0), 2 },
  85.         { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(1, 1), 2 },
  86.         { glm::vec3(0, 0, -0.5), glm::vec2(0.5, 0.5), 2 },
  87.        
  88.         { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(0, 1), 3 },
  89.         { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(0, 0), 3 },
  90.         { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(1, 0), 3 },
  91.         { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(1, 1), 3 },
  92.         { glm::vec3(-0.5, 0, 0), glm::vec2(0.5, 0.5), 3 },
  93.        
  94.         { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(0, 1), 4 },
  95.         { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(0, 0), 4 },
  96.         { glm::vec3(0.5, 0.5, 0.5), glm::vec2(1, 0), 4 },
  97.         { glm::vec3(0.5, 0.5, -0.5), glm::vec2(1, 1), 4 },
  98.         { glm::vec3(0, 0.5, 0), glm::vec2(0.5, 0.5), 4 },
  99.        
  100.         { glm::vec3(0.5, -0.5, 0.5), glm::vec2(0, 1), 5 },
  101.         { glm::vec3(0.5, -0.5, -0.5), glm::vec2(0, 0), 5 },
  102.         { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(1, 0), 5 },
  103.         { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(1, 1), 5 },
  104.         { glm::vec3(0, -0.5, 0), glm::vec2(0.5, 0.5), 5 }
  105.     };
  106.    
  107.     GLuint elements[] = {
  108.         0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4,
  109.         5, 6, 9, 6, 7, 9, 7, 8, 9, 8, 5, 9,
  110.         10, 11, 14, 11, 12, 14, 12, 13, 14, 13, 10, 14,
  111.         15, 16, 19, 16, 17, 19, 17, 18, 19, 18, 15, 19,
  112.         20, 21, 24, 21, 22, 24, 22, 23, 24, 23, 20, 24,
  113.         25, 26, 29, 26, 27, 29, 27, 28, 29, 28, 25, 29
  114.     };
  115.    
  116.     const char * vsSrc = R"(
  117.         #version 150
  118.        
  119.         in vec3 pos;
  120.         in vec2 textCoord;
  121.         in uint textNum;
  122.        
  123.         out vec2 TextCoord;
  124.         out uint TextNum;
  125.        
  126.         uniform mat4 model, view, proj;
  127.        
  128.         void main()
  129.         {
  130.             TextNum = textNum;
  131.             TextCoord = textCoord;
  132.             gl_Position = proj * view * model * vec4(pos, 1);
  133.         }
  134.     )";
  135.    
  136.     const char * fsSrc = R"(
  137.         #version 150
  138.        
  139.         in vec2 TextCoord;
  140.         in uint TextNum;
  141.        
  142.         out vec4 outColor;
  143.        
  144.         uniform sampler2D tex[6];
  145.        
  146.         void main()
  147.         {
  148.             vec4 textColors[6];
  149.             for(int i = 0; i < 6; ++i)
  150.                 textColors[i] = texture(tex[i], TextCoord);
  151.             outColor = textColors[TextNum];
  152.         }
  153.     )";
  154.    
  155.     // Create new Vertex Array Object
  156.     GLuint vao;
  157.     glGenVertexArrays(1, &vao);
  158.     glBindVertexArray(vao);
  159.    
  160.     // Create new Vertex Buffer Object
  161.     GLuint vbo = 0;
  162.     glGenBuffers(1, &vbo);
  163.     glBindBuffer(GL_ARRAY_BUFFER, vbo);
  164.     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  165.    
  166.     // Create new Element Buffer Object
  167.     GLuint ebo;
  168.     glGenBuffers(1, &ebo);
  169.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  170.     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
  171.    
  172.     // Load shaders
  173.     GLuint vs = loadShader(vsSrc, GL_VERTEX_SHADER),
  174.            fs = loadShader(fsSrc, GL_FRAGMENT_SHADER);
  175.    
  176.     // Create and link program
  177.     GLuint program = glCreateProgram();
  178.     glAttachShader(program, vs);
  179.     TEST_GL_ERROR("could not attach vertex shader");
  180.     glAttachShader(program, fs);
  181.     TEST_GL_ERROR("could not attach fragment shader");
  182.     glBindFragDataLocation(program, 0, "outColor");
  183.     TEST_GL_ERROR("could not bind data location");
  184.     glLinkProgram(program);
  185.     TEST_GL_ERROR("could not link program");
  186.     glUseProgram(program);
  187.     TEST_GL_ERROR("program could not be made part of the current state");
  188.    
  189.     // Load attributes
  190.     loadAttrib(program, "pos", 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), 0);
  191.     loadAttrib(program, "textCoord", 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), sizeof(glm::vec3));
  192.     loadAttrib(program, "textNum", 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(vertices[0]), sizeof(glm::vec3) + sizeof(glm::vec2));
  193.    
  194.     // Load uniform variables
  195.     GLint uniProj = glGetUniformLocation(program, "proj");
  196.     glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(g_proj));
  197.     TEST_GL_ERROR("could not load uniform variable 'proj'");
  198.     GLint uniView = glGetUniformLocation(program, "view");
  199.     glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(g_view));
  200.     TEST_GL_ERROR("could not load uniform variable 'view'");
  201.     GLint tex[] = { 0, 1, 2, 3, 4, 5 };
  202.     GLint uniTex = glGetUniformLocation(program, "tex");
  203.     glUniform1iv(uniTex, 6, tex);
  204.     TEST_GL_ERROR("could not load uniform variable 'tex'");
  205.    
  206.     // Bind textures
  207.     for(int i = 0; i < 6; ++i)
  208.     {
  209.         glActiveTexture(GL_TEXTURE0 + i);
  210.         glBindTexture(GL_TEXTURE_2D, g_textures[i]);
  211.         TEST_GL_ERROR("could not load uniform variable 'tex'");
  212.     }
  213.    
  214.     while(true)
  215.     {
  216.         while(SDL_PollEvent(&e) != 0)
  217.         {
  218.             if(e.type == SDL_QUIT)
  219.                 return 0;
  220.         }
  221.        
  222.         // Increase the angle every frame
  223.         angle += 1;
  224.         if(angle >= 360)
  225.             angle = fmod(angle, 360);
  226.        
  227.         // Rotate and load model matrix
  228.         g_model = glm::mat4();
  229.         g_model = glm::translate(g_model, glm::vec3(0, 0, -4));
  230.         g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(1, 0, 0));
  231.         g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(0, 1, 0));
  232.         g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(0, 0, 1));
  233.         GLint uniModel = glGetUniformLocation(program, "model");
  234.         glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(g_model));
  235.        
  236.         // Display the result
  237.         glEnable(GL_DEPTH_TEST);
  238.         glClearColor(1, 0, 1, 1);
  239.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  240.         glDrawElements(GL_TRIANGLES, sizeof(elements) / sizeof(GLuint), GL_UNSIGNED_INT, nullptr);
  241.         SDL_GL_SwapWindow(g_window);
  242.     }
  243. }
  244.  
  245. void init(int * argc, char ** argv)
  246. {  
  247.     // Initialize SDL
  248.     if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
  249.     {
  250.         cerr << PROJ_NAME ": " << SDL_GetError() << endl;
  251.         goto cleanup0;
  252.     }
  253.    
  254.     // Manage OpenGL attributes
  255.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  256.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
  257.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
  258.     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);
  259.     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
  260.     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
  261.     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
  262.     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
  263.     SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
  264.    
  265.     // Create window
  266.     g_window = SDL_CreateWindow(WIN_NAME, SDL_WINDOWPOS_CENTERED,
  267.       SDL_WINDOWPOS_CENTERED, SCR_WIDTH, SCR_HEIGHT, SDL_WINDOW_OPENGL);
  268.     if(!g_window)
  269.     {
  270.         cerr << PROJ_NAME ": " << SDL_GetError() << endl;
  271.         goto cleanup1;
  272.     }
  273.    
  274.     // Create a new device context
  275.     g_context = SDL_GL_CreateContext(g_window);
  276.     if(!g_context)
  277.     {
  278.         cerr << PROJ_NAME ": " << SDL_GetError() << endl;
  279.         goto cleanup2;
  280.     }
  281.    
  282.     // Initialize GLEW
  283.     glewExperimental = GL_TRUE;
  284.     if(glewInit() != GLEW_OK)
  285.     {
  286.         cerr << PROJ_NAME ": failed to initialize GLEW" << endl;
  287.         goto cleanup3;
  288.     }
  289.    
  290.     // GLEW can make glGetError return invalid enumerant even if everything went smoothly
  291.     while(glGetError() == GL_INVALID_ENUM);
  292.    
  293.     // Register cleanup function
  294.     if(atexit(cleanup))
  295.     {
  296.         cerr << PROJ_NAME ": failed to register cleanup function" << endl;
  297.         goto cleanup3;
  298.     }
  299.    
  300.     return;
  301.    
  302. cleanup3:
  303.     SDL_GL_DeleteContext(g_context);
  304.    
  305. cleanup2:
  306.     SDL_DestroyWindow(g_window);
  307.    
  308. cleanup1:
  309.     SDL_Quit();
  310.    
  311. cleanup0:
  312.     exit(EXIT_FAILURE);
  313. }
  314.  
  315. void loadMedia()
  316. {
  317.     // Load all six textures
  318.     const uint8_t texels[][16] = {
  319.         {
  320.             0xFF, 0x00, 0x00, 0xFF,
  321.             0x00, 0x00, 0x00, 0xFF,
  322.             0xFF, 0x00, 0x00, 0xFF,
  323.             0x00, 0x00, 0x00, 0xFF
  324.         },
  325.         {
  326.             0xFF, 0xFF, 0x00, 0xFF,
  327.             0x00, 0x00, 0x00, 0xFF,
  328.             0xFF, 0xFF, 0x00, 0xFF,
  329.             0x00, 0x00, 0x00, 0xFF
  330.         },
  331.         {
  332.             0x00, 0xFF, 0x00, 0xFF,
  333.             0x00, 0x00, 0x00, 0xFF,
  334.             0x00, 0xFF, 0x00, 0xFF,
  335.             0x00, 0x00, 0x00, 0xFF
  336.         },
  337.         {
  338.             0x00, 0xFF, 0xFF, 0xFF,
  339.             0x00, 0x00, 0x00, 0xFF,
  340.             0x00, 0xFF, 0xFF, 0xFF,
  341.             0x00, 0x00, 0x00, 0xFF
  342.         },
  343.         {
  344.             0x00, 0x00, 0xFF, 0xFF,
  345.             0x00, 0x00, 0x00, 0xFF,
  346.             0x00, 0x00, 0xFF, 0xFF,
  347.             0x00, 0x00, 0x00, 0xFF
  348.         },
  349.         {
  350.             0xFF, 0x00, 0xFF, 0xFF,
  351.             0x00, 0x00, 0x00, 0xFF,
  352.             0xFF, 0x00, 0xFF, 0xFF,
  353.             0x00, 0x00, 0x00, 0xFF
  354.         }
  355.     };
  356.    
  357.     for(int i = 0; i < 6; ++i)
  358.         g_textures[i] = loadTexture(texels[i], 2, 2);
  359. }
  360.  
  361. GLuint loadTexture(const uint8_t * texels, int w, int h)
  362. {
  363.     // Create a new texture, set its parameters, and fill it with data
  364.     GLuint tex;
  365.     glGenTextures(1, &tex);
  366.     glActiveTexture(GL_TEXTURE0);
  367.     glBindTexture(GL_TEXTURE_2D, tex);
  368.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  369.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  370.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  371.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  372.    
  373.     // Fill the texture with data
  374.     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels);
  375.     TEST_GL_ERROR("could not load texture");
  376.     return tex;
  377. }
  378.  
  379. GLuint loadShader(const char * src, GLenum type)
  380. {
  381.     // Create and compile a new shader
  382.     GLuint shader = glCreateShader(type);
  383.     glShaderSource(shader, 1, &src, nullptr);
  384.     glCompileShader(shader);
  385.     GLint status;
  386.     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
  387.     if(status != GL_TRUE)
  388.     {
  389.         char buf[4096];
  390.         glGetShaderInfoLog(shader, 4096, nullptr, buf);
  391.         cerr << buf << PROJ_NAME ": shader compilation failed" << endl;
  392.         exit(EXIT_FAILURE);
  393.     }
  394.     return shader;
  395. }
  396.  
  397. GLuint loadAttrib
  398. (
  399.     GLuint program,
  400.     const char * name,
  401.     GLint size,
  402.     GLenum type,
  403.     GLboolean normalized,
  404.     GLsizei stride,
  405.     GLsizei offset
  406. )
  407. {
  408.     GLint attrib = glGetAttribLocation(program, name);
  409.     glEnableVertexAttribArray(attrib);
  410.     TEST_GL_ERROR("could not enable attribute '" << name << '\'');
  411.     glVertexAttribPointer(attrib, size, type, normalized, stride, (void *)(size_t)offset);
  412.     TEST_GL_ERROR("could not load attribute '" << name << '\'');
  413. }
  414.  
  415. void cleanup()
  416. {
  417.     SDL_GL_DeleteContext(g_context);
  418.     SDL_DestroyWindow(g_window);
  419.     SDL_Quit();
  420. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement