struct StoneBlock { unsigned int vbuf, ebuf, lbuf; unsigned int vertex_shader; unsigned int fragment_shader; unsigned int program; unsigned int vertex_attrib; unsigned int mvp_uniform; unsigned int tex_uniform; unsigned int element_count; unsigned int tex; vector locations; // initialization: Texture and vertices into memory bool init(){ GLfloat cube_vertices[] = { // front -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, // back -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, }; glGenBuffers(1, &vbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW); GLushort cube_elements[] = { // front 0, 1, 2, 2, 3, 0, // top 1, 5, 6, 6, 2, 1, // back 7, 6, 5, 5, 4, 7, // bottom 4, 0, 3, 3, 7, 4, // left 4, 5, 1, 1, 0, 4, // right 3, 2, 6, 6, 7, 3, }; element_count = sizeof(cube_elements) / sizeof(GLushort); glGenBuffers(1, &ebuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW); glGenBuffers(1, &lbuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbuf); float test_position[] = {0, 1, 3, 0}; glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vec4) * locations.size(), locations.data(), GL_STATIC_DRAW); int texwidth, texheight; unsigned char *image_data = SOIL_load_image("brick.jpg", &texwidth, &texheight, 0, SOIL_LOAD_RGB); printf("Loaded texture %d by %d\n", texwidth, texheight); if(!image_data) return false; 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, texwidth, texheight, 0, GL_RGB, GL_UNSIGNED_BYTE, image_data); free(image_data); vertex_shader = make_shader("cube_vertex.glsl", GL_VERTEX_SHADER); fragment_shader = make_shader("cube_fragment.glsl", GL_FRAGMENT_SHADER); if(!(vertex_shader && fragment_shader)) return 0; program = glCreateProgram(); glAttachShader(program, vertex_shader); glAttachShader(program, fragment_shader); glLinkProgram(program); GLint link_ok; glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if(!link_ok){ glGetProgramInfoLog(program, GBLEN, NULL, general_buffer); puts(general_buffer); printf(RED("Link Failed\n").c_str()); return false; } vertex_attrib = glGetAttribLocation(program, "in_vertex"); mvp_uniform = glGetUniformLocation(program, "mvp"); tex_uniform = glGetUniformLocation(program, "tex"); return true; } // drawing: set up and call glDrawElementsInstanced void draw(const mat4 &vp){ glUseProgram(program); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); glUniform1i(tex_uniform, 0); glUniformMatrix4fv(mvp_uniform, 1, 0, glm::value_ptr(vp)); glEnableVertexAttribArray(vertex_attrib); glBindBuffer(GL_ARRAY_BUFFER, vbuf); glVertexAttribPointer(vertex_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, lbuf); printf("Element count = %d, locations.size = %d\n", element_count, locations.size()); glDrawElementsInstanced(GL_TRIANGLES, element_count, GL_UNSIGNED_SHORT, 0, locations.size()); } // movement: for falling calculations // Returns the effective floor level float movement(){ return 0.0; } };