/* Simplified OpenGL 4.5 demo * Seth Long, Fall 2020 * Simple demo, C++ version * Note operator overloading for matrix multiplication! * * Linux build: g++ simple_demo.cpp -lglfw -lGLEW -lGL -lGLU */ #include #include #include #include #include // glad on Windows #include #include #include #include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" using namespace glm; const float height = 800; const float width = 1280; void GLAPIENTRY debug_callback(GLenum, GLenum type, GLuint, GLenum severity, GLsizei, const GLchar* message, const void*){ if(severity != GL_DEBUG_SEVERITY_HIGH && severity != GL_DEBUG_SEVERITY_MEDIUM ) return; fprintf( stderr, "GL ERROR MESSAGE: %s type = 0x%x, severity = 0x%x, message = %s\n", ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), type, severity, message ); } int main(int argc, char ** argv){ glfwInit(); GLFWwindow* window = glfwCreateWindow(width, height, "Simple OpenGL 4.0+ Demo", 0, 0); glfwMakeContextCurrent(window); glewInit(); // During init, enable debug output glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(debug_callback, 0); // Initialization part float vertices[] = { -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1 }; unsigned int vbuf; glGenBuffers(1, &vbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); unsigned short elements[] = { 0, 1, 2, // Front 0, 2, 3, 4, 0, 3, // Top 4, 3, 7, 3, 2, 6, // Right 3, 6, 7, 7, 6, 4, // Back 4, 6, 5, 4, 5, 1, // Left 4, 1, 0, 5, 1, 2, // Bottom 5, 2, 6 }; unsigned int ebuf; glGenBuffers(1, &ebuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); /* Setup texture here */ int img_width, img_height; unsigned char* image = stbi_load("brick.jpg", &img_width, &img_height, 0, STBI_rgb); if(!image){ printf("image failed to load\n"); return 1; } else { printf("Image size is %d by %d\n", img_width, img_height); } unsigned int tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img_width, img_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); free(image); int fd = open("vertex_shader.glsl", O_RDONLY); char *source = (char*)malloc(2048); size_t readlen = read(fd, source, 2048); if(2048 == readlen) printf("Warning: vertex shader is probably too long for this read routine\n"); source[readlen] = 0; puts(source); close(fd); unsigned int vs_reference = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs_reference, 1, (const char**)&source, 0); glCompileShader(vs_reference); glGetShaderInfoLog(vs_reference, 2048, NULL, source); puts(source); int compile_ok; glGetShaderiv(vs_reference, GL_COMPILE_STATUS, &compile_ok); if(!compile_ok){ printf("Vertex shader failed to compile\n"); return 1; } fd = open("fragment_shader.glsl", O_RDONLY); readlen = read(fd, source, 2048); source[readlen] = 0; puts(source); close(fd); unsigned int fs_reference = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs_reference, 1, (const char**)&source, 0); glCompileShader(fs_reference); glGetShaderInfoLog(fs_reference, 2048, NULL, source); puts(source); glGetShaderiv(fs_reference, GL_COMPILE_STATUS, &compile_ok); if(!compile_ok){ printf("Fragment shader failed to compile\n"); return 1; } unsigned int program = glCreateProgram(); glAttachShader(program, vs_reference); glAttachShader(program, fs_reference); glLinkProgram(program); int link_ok; glGetProgramiv(program, GL_LINK_STATUS, &link_ok); glGetProgramInfoLog(program, 2048, NULL, source); puts(source); if(!link_ok){ printf("Link failure\n"); return 1; } free(source); unsigned int v_attrib = glGetAttribLocation(program, "in_vertex"); unsigned int mvp_uniform = glGetUniformLocation(program, "mvp"); int count = 0; glUseProgram(program); glEnableVertexAttribArray(v_attrib); glBindBuffer(GL_ARRAY_BUFFER, vbuf); glVertexAttribPointer(v_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); glEnable(GL_DEPTH_TEST); while(!glfwWindowShouldClose(window)){ count++; glfwPollEvents(); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); mat4 model = mat4(1.0); model = rotate(model, count / 100.0f, vec3(0, 1, 0)); model = translate(model, vec3(-5, 0, 0)); model = rotate(model, count / 20.0f, vec3(0, 1, 0)); model = rotate(model, radians(45.0f), vec3(0, 0, 1)); // model = scale(model, vec3(sin(count/200.0f) + 1.2, 1.0, 1.0)); mat4 view = lookAt(vec3(0.0f, 5.0f, 15.0f), vec3(0, 0, 0), vec3(0, 1, 0)); mat4 projection = perspective(radians(45.0f), width/height, 0.1f, 1000.0f); mat4 mvp = projection * view * model; glUniformMatrix4fv(mvp_uniform, 1, 0, value_ptr(mvp)); glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0, 1); glfwSwapBuffers(window); // usleep(10000); } glDeleteProgram(program); glfwDestroyWindow(window); glfwTerminate(); }