Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "cassert"
- #include "cmath"
- #include "cstdio"
- #include "cstdlib"
- #include "cstdint"
- #include "GL/glew.h"
- #include "glm/fwd.hpp"
- #include "glm/glm.hpp"
- #include "glm/gtc/matrix_transform.hpp"
- #include "glm/gtc/type_ptr.hpp"
- #include "iostream"
- #include "SDL2/SDL.h"
- #define PROJ_NAME "example"
- #define WIN_NAME "Example"
- #define SCR_WIDTH 640
- #define SCR_HEIGHT 480
- #define TEST_GL_ERROR(ERR_MSG) \
- do { \
- GLenum err; \
- if((err = glGetError()) != GL_NO_ERROR) \
- { \
- cerr << PROJ_NAME << ": " << ERR_MSG << ": " << gluErrorString(err) << endl;\
- exit(EXIT_FAILURE); \
- } \
- } while(false)
- using namespace std;
- SDL_Window * g_window = nullptr;
- SDL_GLContext g_context = 0;
- GLuint g_textures[6];
- glm::mat4 g_proj = glm::perspective(glm::radians(60.0f), (float)SCR_WIDTH /
- (float)SCR_HEIGHT, 1.0f, 100.0f),
- g_view,
- g_model;
- void init(int * argc, char ** argv);
- void loadMedia();
- void cleanup();
- GLuint loadTexture(const uint8_t * texels, int w, int h);
- GLuint loadShader(const char * src, GLenum type);
- GLuint loadAttrib
- (
- GLuint program,
- const char * name,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- GLsizei offset
- );
- int main(int argc, char ** argv)
- {
- init(&argc, argv);
- loadMedia();
- GLenum err;
- float angle = 0;
- SDL_Event e;
- struct {
- glm::vec3 pos;
- glm::vec2 textCoord;
- GLuint textNum;
- } vertices[] = {
- { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(0, 1), 0 },
- { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(0, 0), 0 },
- { glm::vec3(0.5, -0.5, 0.5), glm::vec2(1, 0), 0 },
- { glm::vec3(0.5, 0.5, 0.5), glm::vec2(1, 1), 0 },
- { glm::vec3(0, 0, 0.5), glm::vec2(0.5, 0.5), 0 },
- { glm::vec3(0.5, 0.5, 0.5), glm::vec2(0, 1), 1 },
- { glm::vec3(0.5, -0.5, 0.5), glm::vec2(0, 0), 1 },
- { glm::vec3(0.5, -0.5, -0.5), glm::vec2(1, 0), 1 },
- { glm::vec3(0.5, 0.5, -0.5), glm::vec2(1, 1), 1 },
- { glm::vec3(0.5, 0, 0), glm::vec2(0.5, 0.5), 1 },
- { glm::vec3(0.5, 0.5, -0.5), glm::vec2(0, 1), 2 },
- { glm::vec3(0.5, -0.5, -0.5), glm::vec2(0, 0), 2 },
- { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(1, 0), 2 },
- { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(1, 1), 2 },
- { glm::vec3(0, 0, -0.5), glm::vec2(0.5, 0.5), 2 },
- { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(0, 1), 3 },
- { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(0, 0), 3 },
- { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(1, 0), 3 },
- { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(1, 1), 3 },
- { glm::vec3(-0.5, 0, 0), glm::vec2(0.5, 0.5), 3 },
- { glm::vec3(-0.5, 0.5, -0.5), glm::vec2(0, 1), 4 },
- { glm::vec3(-0.5, 0.5, 0.5), glm::vec2(0, 0), 4 },
- { glm::vec3(0.5, 0.5, 0.5), glm::vec2(1, 0), 4 },
- { glm::vec3(0.5, 0.5, -0.5), glm::vec2(1, 1), 4 },
- { glm::vec3(0, 0.5, 0), glm::vec2(0.5, 0.5), 4 },
- { glm::vec3(0.5, -0.5, 0.5), glm::vec2(0, 1), 5 },
- { glm::vec3(0.5, -0.5, -0.5), glm::vec2(0, 0), 5 },
- { glm::vec3(-0.5, -0.5, -0.5), glm::vec2(1, 0), 5 },
- { glm::vec3(-0.5, -0.5, 0.5), glm::vec2(1, 1), 5 },
- { glm::vec3(0, -0.5, 0), glm::vec2(0.5, 0.5), 5 }
- };
- GLuint elements[] = {
- 0, 1, 4, 1, 2, 4, 2, 3, 4, 3, 0, 4,
- 5, 6, 9, 6, 7, 9, 7, 8, 9, 8, 5, 9,
- 10, 11, 14, 11, 12, 14, 12, 13, 14, 13, 10, 14,
- 15, 16, 19, 16, 17, 19, 17, 18, 19, 18, 15, 19,
- 20, 21, 24, 21, 22, 24, 22, 23, 24, 23, 20, 24,
- 25, 26, 29, 26, 27, 29, 27, 28, 29, 28, 25, 29
- };
- const char * vsSrc = R"(
- #version 150
- in vec3 pos;
- in vec2 textCoord;
- in uint textNum;
- out vec2 TextCoord;
- out uint TextNum;
- uniform mat4 model, view, proj;
- void main()
- {
- TextNum = textNum;
- TextCoord = textCoord;
- gl_Position = proj * view * model * vec4(pos, 1);
- }
- )";
- const char * fsSrc = R"(
- #version 150
- in vec2 TextCoord;
- in uint TextNum;
- out vec4 outColor;
- uniform sampler2D tex[6];
- void main()
- {
- vec4 textColors[6];
- for(int i = 0; i < 6; ++i)
- textColors[i] = texture(tex[i], TextCoord);
- outColor = textColors[TextNum];
- }
- )";
- // Create new Vertex Array Object
- GLuint vao;
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
- // Create new Vertex Buffer Object
- GLuint vbo = 0;
- glGenBuffers(1, &vbo);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- // Create new Element Buffer Object
- GLuint ebo;
- glGenBuffers(1, &ebo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
- // Load shaders
- GLuint vs = loadShader(vsSrc, GL_VERTEX_SHADER),
- fs = loadShader(fsSrc, GL_FRAGMENT_SHADER);
- // Create and link program
- GLuint program = glCreateProgram();
- glAttachShader(program, vs);
- TEST_GL_ERROR("could not attach vertex shader");
- glAttachShader(program, fs);
- TEST_GL_ERROR("could not attach fragment shader");
- glBindFragDataLocation(program, 0, "outColor");
- TEST_GL_ERROR("could not bind data location");
- glLinkProgram(program);
- TEST_GL_ERROR("could not link program");
- glUseProgram(program);
- TEST_GL_ERROR("program could not be made part of the current state");
- // Load attributes
- loadAttrib(program, "pos", 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), 0);
- loadAttrib(program, "textCoord", 2, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), sizeof(glm::vec3));
- loadAttrib(program, "textNum", 1, GL_UNSIGNED_INT, GL_FALSE, sizeof(vertices[0]), sizeof(glm::vec3) + sizeof(glm::vec2));
- // Load uniform variables
- GLint uniProj = glGetUniformLocation(program, "proj");
- glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(g_proj));
- TEST_GL_ERROR("could not load uniform variable 'proj'");
- GLint uniView = glGetUniformLocation(program, "view");
- glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(g_view));
- TEST_GL_ERROR("could not load uniform variable 'view'");
- GLint tex[] = { 0, 1, 2, 3, 4, 5 };
- GLint uniTex = glGetUniformLocation(program, "tex");
- glUniform1iv(uniTex, 6, tex);
- TEST_GL_ERROR("could not load uniform variable 'tex'");
- // Bind textures
- for(int i = 0; i < 6; ++i)
- {
- glActiveTexture(GL_TEXTURE0 + i);
- glBindTexture(GL_TEXTURE_2D, g_textures[i]);
- TEST_GL_ERROR("could not load uniform variable 'tex'");
- }
- while(true)
- {
- while(SDL_PollEvent(&e) != 0)
- {
- if(e.type == SDL_QUIT)
- return 0;
- }
- // Increase the angle every frame
- angle += 1;
- if(angle >= 360)
- angle = fmod(angle, 360);
- // Rotate and load model matrix
- g_model = glm::mat4();
- g_model = glm::translate(g_model, glm::vec3(0, 0, -4));
- g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(1, 0, 0));
- g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(0, 1, 0));
- g_model = glm::rotate(g_model, glm::radians(angle), glm::vec3(0, 0, 1));
- GLint uniModel = glGetUniformLocation(program, "model");
- glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(g_model));
- // Display the result
- glEnable(GL_DEPTH_TEST);
- glClearColor(1, 0, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glDrawElements(GL_TRIANGLES, sizeof(elements) / sizeof(GLuint), GL_UNSIGNED_INT, nullptr);
- SDL_GL_SwapWindow(g_window);
- }
- }
- void init(int * argc, char ** argv)
- {
- // Initialize SDL
- if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
- {
- cerr << PROJ_NAME ": " << SDL_GetError() << endl;
- goto cleanup0;
- }
- // Manage OpenGL attributes
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, true);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
- // Create window
- g_window = SDL_CreateWindow(WIN_NAME, SDL_WINDOWPOS_CENTERED,
- SDL_WINDOWPOS_CENTERED, SCR_WIDTH, SCR_HEIGHT, SDL_WINDOW_OPENGL);
- if(!g_window)
- {
- cerr << PROJ_NAME ": " << SDL_GetError() << endl;
- goto cleanup1;
- }
- // Create a new device context
- g_context = SDL_GL_CreateContext(g_window);
- if(!g_context)
- {
- cerr << PROJ_NAME ": " << SDL_GetError() << endl;
- goto cleanup2;
- }
- // Initialize GLEW
- glewExperimental = GL_TRUE;
- if(glewInit() != GLEW_OK)
- {
- cerr << PROJ_NAME ": failed to initialize GLEW" << endl;
- goto cleanup3;
- }
- // GLEW can make glGetError return invalid enumerant even if everything went smoothly
- while(glGetError() == GL_INVALID_ENUM);
- // Register cleanup function
- if(atexit(cleanup))
- {
- cerr << PROJ_NAME ": failed to register cleanup function" << endl;
- goto cleanup3;
- }
- return;
- cleanup3:
- SDL_GL_DeleteContext(g_context);
- cleanup2:
- SDL_DestroyWindow(g_window);
- cleanup1:
- SDL_Quit();
- cleanup0:
- exit(EXIT_FAILURE);
- }
- void loadMedia()
- {
- // Load all six textures
- const uint8_t texels[][16] = {
- {
- 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- },
- {
- 0xFF, 0xFF, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0xFF, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- },
- {
- 0x00, 0xFF, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0xFF, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- },
- {
- 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- },
- {
- 0x00, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- },
- {
- 0xFF, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0x00, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0xFF
- }
- };
- for(int i = 0; i < 6; ++i)
- g_textures[i] = loadTexture(texels[i], 2, 2);
- }
- GLuint loadTexture(const uint8_t * texels, int w, int h)
- {
- // Create a new texture, set its parameters, and fill it with data
- GLuint tex;
- glGenTextures(1, &tex);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // Fill the texture with data
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texels);
- TEST_GL_ERROR("could not load texture");
- return tex;
- }
- GLuint loadShader(const char * src, GLenum type)
- {
- // Create and compile a new shader
- GLuint shader = glCreateShader(type);
- glShaderSource(shader, 1, &src, nullptr);
- glCompileShader(shader);
- GLint status;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if(status != GL_TRUE)
- {
- char buf[4096];
- glGetShaderInfoLog(shader, 4096, nullptr, buf);
- cerr << buf << PROJ_NAME ": shader compilation failed" << endl;
- exit(EXIT_FAILURE);
- }
- return shader;
- }
- GLuint loadAttrib
- (
- GLuint program,
- const char * name,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- GLsizei offset
- )
- {
- GLint attrib = glGetAttribLocation(program, name);
- glEnableVertexAttribArray(attrib);
- TEST_GL_ERROR("could not enable attribute '" << name << '\'');
- glVertexAttribPointer(attrib, size, type, normalized, stride, (void *)(size_t)offset);
- TEST_GL_ERROR("could not load attribute '" << name << '\'');
- }
- void cleanup()
- {
- SDL_GL_DeleteContext(g_context);
- SDL_DestroyWindow(g_window);
- SDL_Quit();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement