#include #include #include #include #include #include GLuint loadShader(const char *source, GLenum shader_type) { GLuint shaderId = glCreateShader(shader_type); GLint result = GL_FALSE; int infoLogLength; // Compile Vertex Shader glShaderSource(shaderId, 1, &source, nullptr); glCompileShader(shaderId); glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result); glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLength); if (infoLogLength > 0) { std::vector VertexShaderErrorMessage(infoLogLength + 1); glGetShaderInfoLog(shaderId, infoLogLength, nullptr, &VertexShaderErrorMessage[0]); printf("%s\n", &VertexShaderErrorMessage[0]); exit(-1); } return shaderId; } GLuint loadProgram(const std::vector &shaders) { GLuint programId = glCreateProgram(); for (const auto &item : shaders) { glAttachShader(programId, item); } glLinkProgram(programId); GLint result = GL_FALSE; int infoLogLength; glGetProgramiv(programId, GL_LINK_STATUS, &result); glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength); if (infoLogLength > 0) { std::vector ProgramErrorMessage(infoLogLength + 1); glGetProgramInfoLog(programId, infoLogLength, nullptr, &ProgramErrorMessage[0]); printf("%s\n", &ProgramErrorMessage[0]); } return programId; } static const char *vertex_shader = "#version 460\n" "layout(location = 0) in vec3 vertexPosition_modelspace;\n" "out vec2 coord;\n" "void main(){\n" " gl_Position.xyz = vertexPosition_modelspace;\n" " gl_Position.w = 1.0;\n" " coord.xy = vertexPosition_modelspace.xy;\n" "}"; static const char *fragment_shader = "#version 460\n" "out vec3 color;\n" "in vec2 coord;\n" "layout (std430, binding = 2) restrict readonly buffer shader_data\n" "{\n" " int c[];\n" "};\n" "void main(){\n" " int x = int(255. * (coord.x + 1.) / 2.);" " color = vec3(c[x]/255., 0.5,0.5);\n" "}"; int main() { glewExperimental = true; if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); return -1; } glfwWindowHint(GLFW_SAMPLES, 0); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow *window = glfwCreateWindow(1024, 768, "Tutorial 01", nullptr, nullptr); if (window == nullptr) { fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are " "not 3.3 compatible. Try the 2.1 version of the tutorials.\n"); glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // Initialize GLEW glewExperimental = true; // Needed in core profile if (glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); return -1; } glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); GLuint VertexArrayID; glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); const GLfloat g_vertex_buffer_data[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, }; GLuint vertexbuffer; glGenBuffers(1, &vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); GLuint programId = loadProgram({ loadShader(vertex_shader, GL_VERTEX_SHADER), loadShader(fragment_shader, GL_FRAGMENT_SHADER), }); int c[256]; for (size_t i = 0; i < 256; ++i) { c[i] = i; } GLuint ssbo = 0; glGenBuffers(1, &ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int)*256, &c,GL_DYNAMIC_COPY); glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); unsigned int block_index = glGetProgramResourceIndex(programId, GL_SHADER_STORAGE_BLOCK, "shader_data"); GLuint ssbo_binding_point_index = 2; glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ssbo_binding_point_index, ssbo); glShaderStorageBlockBinding(programId, block_index, ssbo_binding_point_index); do { glClear(GL_COLOR_BUFFER_BIT); glUseProgram(programId); for (int & i : c) { i = (i + 1) % 256; } glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); GLvoid *p = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY); std::memcpy(p, &c, sizeof(int) * 256); glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glDrawArrays(GL_TRIANGLES, 0,3); glDisableVertexAttribArray(0); glfwSwapBuffers(window); glfwPollEvents(); } // Check if the ESC key was pressed or the window was closed while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0); }