PIGLIT_GL_TEST_CONFIG_END void piglit_init(int argc, char **argv) { bool pass = true; const int buffer_size = 1<<20; unsigned int buffer; char *mapped_data; static const char *const data_zero = "\x00\x00\x00\x00"; static const char *const data_one = "\xff\xff\xff\xff"; static const char *const data_init = "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x55\x55\x55\x55" "\x55\x55\x55\x55" "\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa" "\xff\x00\xff\x00" "\xff\x00\xff\x00" "\x00\xff\x00\xff" "\x00\xff\x00\xff" "\x91\xcc\x45\x36" "\xd3\xe4\xe3\x5b" "\x79\x1e\x21\x39" "\xa8\xfa\x69\x6a"; piglit_require_extension("GL_ARB_clear_buffer_object"); glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_READ); fill_array_buffer(64, data_init); mapped_data = glMapBufferRange(GL_ARRAY_BUFFER, 0, buffer_size/2, GL_MAP_WRITE_BIT); memset(mapped_data, '\x00', buffer_size/2); glClearBufferSubData(GL_ARRAY_BUFFER, GL_RGBA8, buffer_size/2, buffer_size/2, GL_RGBA, GL_UNSIGNED_BYTE, data_one); glUnmapBuffer(GL_ARRAY_BUFFER); pass = check_array_buffer_sub_data(0, buffer_size/2, 4, data_zero) && pass; pass = check_array_buffer_sub_data(buffer_size/2, buffer_size/2, 4, data_one) && pass; glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &buffer); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void OGL_StructuredBuffer::BindToRenderTarget(unsigned int currentBindingPoint) { // clear atomic counter if(flags & APPEND_SBF) { glBindBuffer(GL_SHADER_STORAGE_BUFFER, structuredBufferName); GLuint clearData = 0; glClearBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_R32UI, 0, sizeof(GLuint), GL_LUMINANCE, GL_UNSIGNED_INT, &clearData); } glBindBufferBase(GL_SHADER_STORAGE_BUFFER, currentBindingPoint, structuredBufferName); }
static void clear_buffer(int i, unsigned offset, unsigned size, unsigned char value, char *cpu) { glClearBufferSubData(GL_ARRAY_BUFFER, GL_R8, offset, size, GL_RED, GL_UNSIGNED_BYTE, &value); memset(cpu+offset, value, size); if (debug && !check_array_buffer_data(SIZE, cpu)) { printf("Clear %i failed: offset=%i (%%4 = %i), size=%i (%%4 = %i)\n", i, offset, offset % 4, size, size % 4); piglit_report_result(PIGLIT_FAIL); } }
void Buffer::clearSubData(GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void* data) { if (m_directStateAccess) { glClearNamedBufferSubDataEXT(m_id, internalformat, offset, size, format, type, data); CheckGLError(); } else { bind(); glClearBufferSubData(m_target, internalformat, offset, size, format, type, data); CheckGLError(); } }
void display() { // Setup blending glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Compute the MVP (Model View Projection matrix) { glBindBuffer(GL_UNIFORM_BUFFER, BufferName[buffer::TRANSFORM]); glm::mat4* Pointer = (glm::mat4*)glMapBufferRange( GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f); glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Window.TranlationCurrent.y)); glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Window.RotationCurrent.y, glm::vec3(1.f, 0.f, 0.f)); glm::mat4 View = glm::rotate(ViewRotateX, Window.RotationCurrent.x, glm::vec3(0.f, 1.f, 0.f)); glm::mat4 Model = glm::mat4(1.0f); glm::mat4 MVP = Projection * View * Model; *Pointer = MVP; glUnmapBuffer(GL_UNIFORM_BUFFER); } glm::uint Data(0); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, BufferName[buffer::ATOMIC_COUNTER]); glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER, GL_R8UI, 0, sizeof(glm::uint), GL_RGBA, GL_UNSIGNED_INT, &Data); glViewportIndexedf(0, 0, 0, float(Window.Size.x), float(Window.Size.y)); glClearBufferfv(GL_COLOR, 0, &glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)[0]); glBindProgramPipeline(PipelineName); glBindVertexArray(VertexArrayName); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, BufferName[buffer::ATOMIC_COUNTER]); glBindBufferBase(GL_UNIFORM_BUFFER, glf::semantic::uniform::TRANSFORM0, BufferName[buffer::TRANSFORM]); glDrawElementsInstancedBaseVertexBaseInstance( GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, 0, 5, 0, 0); glf::swapBuffers(); }
void wined3d_unordered_access_view_clear_uint(struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value, struct wined3d_context *context) { const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_format *format; struct wined3d_resource *resource; struct wined3d_buffer *buffer; unsigned int offset, size; resource = view->resource; if (resource->type != WINED3D_RTYPE_BUFFER) { FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type)); return; } if (!gl_info->supported[ARB_CLEAR_BUFFER_OBJECT]) { FIXME("OpenGL implementation does not support ARB_clear_buffer_object.\n"); return; } format = view->format; if (format->id != WINED3DFMT_R32_UINT && format->id != WINED3DFMT_R32_SINT && format->id != WINED3DFMT_R32G32B32A32_UINT && format->id != WINED3DFMT_R32G32B32A32_SINT) { FIXME("Not implemented for format %s.\n", debug_d3dformat(format->id)); return; } buffer = buffer_from_resource(resource); wined3d_buffer_load_location(buffer, context, WINED3D_LOCATION_BUFFER); wined3d_unordered_access_view_invalidate_location(view, ~WINED3D_LOCATION_BUFFER); get_buffer_view_range(buffer, &view->desc, format, &offset, &size); context_bind_bo(context, buffer->buffer_type_hint, buffer->buffer_object); GL_EXTCALL(glClearBufferSubData(buffer->buffer_type_hint, format->glInternal, offset, size, format->glFormat, format->glType, clear_value)); checkGLcall("clear unordered access view"); }
void VisibilityExtractionDemo::run() { const GLuint zero = 0; render(window, [&] (float deltaTime) { numberOfFrames++; frameInterval += deltaTime; if (frameInterval > 1.0f) { fps = numberOfFrames / frameInterval; std::cout << "FPS: " << fps << std::endl; numberOfFrames = 0; frameInterval = 0.0f; } if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) (rotY - deltaTime < 0)? rotY -= deltaTime + 6.283 : rotY -= deltaTime; if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) (rotY + deltaTime > 6.283)? rotY += deltaTime - 6.283 : rotY += deltaTime; if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) (rotX - deltaTime < 0)? rotX -= deltaTime + 6.283 : rotX -= deltaTime; if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) (rotX + deltaTime > 6.283)? rotX += deltaTime - 6.283 : rotX += deltaTime; if (glfwGetKey(window, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS) distance += deltaTime * 50; if (glfwGetKey(window, GLFW_KEY_PAGE_UP) == GLFW_PRESS) distance = max(distance - deltaTime * 50, 0.0f); if (glfwGetKey(window, GLFW_KEY_PERIOD) == GLFW_PRESS) scale += deltaTime*4; if (glfwGetKey(window, GLFW_KEY_COMMA) == GLFW_PRESS) scale = glm::max(scale - deltaTime*4, 0.01f); if (glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) {updateVisibilityMapLock = true; updateVisibilityMap = true;} if (glfwGetKey(window, GLFW_KEY_U) == GLFW_PRESS) updateVisibilityMapLock = false; if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) pingPongOff = false; if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) pingPongOff = true; if (glfwGetKey(window, GLFW_KEY_F11) == GLFW_PRESS) { vsync = !vsync; vsync ? glfwSwapInterval(1) : glfwSwapInterval(0); vsync ? std::cout << "VSync enabled\n" : std::cout << "VSync disabled\n"; } // Render impostor geometry if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) { renderBalls->setShaderProgram(&spRenderImpostor); renderBalls->texture("sortedVisibleIDsBuffer", tex_sortedVisibleIDsBuffer); result->update("maxRange", 1.0f); result->texture("tex", renderBalls->get("fragColor")); } // Render impostor geometry as disc if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) { renderBalls->setShaderProgram(&spRenderDiscs); renderBalls->texture("sortedVisibleIDsBuffer", tex_sortedVisibleIDsBuffer); result->update("maxRange", 1.0f); result->texture("tex", renderBalls->get("fragColor")); } // Render faked geometry if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) { renderBalls->setShaderProgram(&spRenderBalls); renderBalls->texture("sortedVisibleIDsBuffer", tex_sortedVisibleIDsBuffer); result->update("maxRange", 1.0f); result->texture("tex", renderBalls->get("fragColor")); } // Render instance IDs geometry if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) { renderBalls->setShaderProgram(&spRenderBalls); renderBalls->texture("sortedVisibleIDsBuffer", tex_sortedVisibleIDsBuffer); result->update("maxRange", float(impSph->num_balls)); result->texture("tex", renderBalls->get("InstanceID")); } if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { if(animate) { animate = false; lastTime = glfwGetTime(); } else { animate = true; glfwSetTime(lastTime); } } if (animate) { elapsedTime = glfwGetTime(); if (elapsedTime > 628) { elapsedTime = 0; glfwSetTime(0); } } mat4 view = translate(mat4(1), vec3(0,0,-distance)) * eulerAngleXY(-rotX, -rotY); // reset the detected instance IDs glBindTexture(GL_TEXTURE_1D, tex_collectedIDsBuffer->getHandle()); glTexImage1D(GL_TEXTURE_1D, 0, GL_R8UI, num_balls, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, zeros); //glBindTexture(GL_TEXTURE_1D, visibleIDsBuff->getHandle()); //glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, num_balls, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &identityInstancesMap[0]); glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomBuff); glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER, GL_R32UI, 0, sizeof(GLuint), GL_RED_INTEGER, GL_UNSIGNED_INT, zero); renderBalls->clear(-1,-1,-1,-1); // the clear color may not interfere with the detected instance IDs renderBalls->clearDepth(); renderBalls->update("scale", vec2(scale)); renderBalls->update("view", view); renderBalls->update("probeRadius", probeRadius); renderBalls->run(); // Depending on user input: sort out instances for the next frame or not, // or lock the current set of visible instances if(useAtomicCounters) if (updateVisibilityMap && !pingPongOff) { // the following shaders in detectVisible look at what has been written to the screen (framebuffer0) // better render the instance stuff to a texture and read from there collectSurfaceIDs->run(); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT|GL_BUFFER_UPDATE_BARRIER_BIT); glBeginQuery(GL_TIME_ELAPSED, timeQuery); computeSortedIDs->run(16,1,1); // 16 work groups * 1024 work items = 16384 atoms and IDs glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT|GL_SHADER_IMAGE_ACCESS_BARRIER_BIT|GL_BUFFER_UPDATE_BARRIER_BIT); glEndQuery(GL_TIME_ELAPSED); glGetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &queryTime); std::cout << "compute shader time: " << queryTime << std::endl; // Check buffer data // GLuint visibilityMapFromBuff[ImpostorSpheres::num_balls]; // GLuint visibleIDsFromBuff[ImpostorSpheres::num_balls]; // glBindTexture(GL_TEXTURE_1D, bufferTex->getHandle()); // glGetTexImage(GL_TEXTURE_1D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, visibilityMapFromBuff); // glBindTexture(GL_TEXTURE_1D, visibleIDsBuff->getHandle()); // glGetTexImage(GL_TEXTURE_1D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, visibleIDsFromBuff); //get the value of the atomic counter glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomBuff); GLuint* counterVal = (GLuint*) glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT ); glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER); impSph->instancesToRender = *counterVal; std::cout << "Number of visible instances by atomic Counter: " << *counterVal << std::endl; updateVisibilityMap = false; }else { if(!updateVisibilityMapLock) { // ToDo // instead of uploading the data, swap the buffer glBindTexture(GL_TEXTURE_1D, tex_sortedVisibleIDsBuffer->getHandle()); glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, num_balls, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &identityInstancesMap[0]); impSph->instancesToRender = impSph->num_balls; updateVisibilityMap = true; // sort out every other frame } } else if (updateVisibilityMap && !pingPongOff) { collectSurfaceIDs->run(); // detect visible instances glBeginQuery(GL_TIME_ELAPSED, timeQuery); GLuint visibilityMapFromBuff[impSph->num_balls]; glBindTexture(GL_TEXTURE_1D, tex_collectedIDsBuffer->getHandle()); glGetTexImage(GL_TEXTURE_1D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, visibilityMapFromBuff); // copy visible instance information to a vector with size = num_balls int num_vis = 0; std::vector<GLint> newMap; newMap.resize(num_balls); for (int i = 0; i < num_balls; i++) { newMap[i] = (int)visibilityMapFromBuff[i]; if(visibilityMapFromBuff[i] != 0) num_vis++; } glEndQuery(GL_TIME_ELAPSED); glGetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &queryTime); std::cout << "cpu time: " << queryTime << std::endl; // print number of visible instances std::cout << "Number of visible instances: " << num_vis << std::endl; impSph->updateVisibilityMap(newMap); updateVisibilityMap = false; }else { if(!updateVisibilityMapLock) { impSph->updateVisibilityMap(mapAllVisible); updateVisibilityMap = true; // sort out every other frame } } result->clear(num_balls,num_balls,num_balls,num_balls); result->run(); }); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglClearBufferSubData(JNIEnv *__env, jclass clazz, jint target, jint internalformat, jlong offset, jlong size, jint format, jint type, jlong dataAddress, jlong __functionAddress) { const GLvoid *data = (const GLvoid *)(intptr_t)dataAddress; glClearBufferSubDataPROC glClearBufferSubData = (glClearBufferSubDataPROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) glClearBufferSubData(target, internalformat, (GLintptr)offset, (GLsizeiptr)size, format, type, data); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglClearBufferSubData__IIJJIIJ(JNIEnv *__env, jclass clazz, jint target, jint internalformat, jlong offset, jlong size, jint format, jint type, jlong dataAddress) { glClearBufferSubDataPROC glClearBufferSubData = (glClearBufferSubDataPROC)tlsGetFunction(871); intptr_t data = (intptr_t)dataAddress; UNUSED_PARAM(clazz) glClearBufferSubData(target, internalformat, (intptr_t)offset, (intptr_t)size, format, type, data); }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL43_nglClearBufferSubData(JNIEnv *env, jclass clazz, jint target, jint internalformat, jlong offset, jlong size, jint format, jint type, jlong data, jlong function_pointer) { const GLvoid *data_address = (const GLvoid *)(intptr_t)data; glClearBufferSubDataPROC glClearBufferSubData = (glClearBufferSubDataPROC)((intptr_t)function_pointer); glClearBufferSubData(target, internalformat, offset, size, format, type, data_address); }
void GLBufferObject::Clear( GLenum internalformat, int offset, int size, GLenum format, GLenum type, const void* data ) { Bind(); glClearBufferSubData(target, internalformat, offset, size, format, type, data); Unbind(); }
PIGLIT_GL_TEST_CONFIG_END void piglit_init(int argc, char **argv) { bool pass = true; const int buffer_size = 1<<20; unsigned int buffer; static const char *const data_7f = "\x7f\x7f\x7f\x7f"; static const char *const data_zero = "\x00\x00\x00\x00"; static const char *const data_one = "\xff\xff\xff\xff"; static const char *const data_init = "\xff\xff\xff\xff" "\xff\xff\xff\xff" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x55\x55\x55\x55" "\x55\x55\x55\x55" "\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa" "\xff\x00\xff\x00" "\xff\x00\xff\x00" "\x00\xff\x00\xff" "\x00\xff\x00\xff" "\x91\xcc\x45\x36" "\xd3\xe4\xe3\x5b" "\x79\x1e\x21\x39" "\xa8\xfa\x69\x6a"; piglit_require_extension("GL_ARB_clear_buffer_object"); glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_READ); fill_array_buffer(64, data_init); /* Buffer contents: * xx xx xx xx xx xx xx xx */ glClearBufferSubData(GL_ARRAY_BUFFER, GL_RGBA8, 1*buffer_size/8, buffer_size/4, GL_RGBA, GL_UNSIGNED_BYTE, data_7f); /* xx 7f 7f xx xx xx xx xx */ glClearBufferSubData(GL_ARRAY_BUFFER, GL_RGBA8, 2*buffer_size/8, buffer_size/4, GL_RGBA, GL_UNSIGNED_BYTE, data_zero); /* xx 7f 00 00 xx xx xx xx */ glClearBufferSubData(GL_ARRAY_BUFFER, GL_RGBA8, 3*buffer_size/8, buffer_size/4, GL_RGBA, GL_UNSIGNED_BYTE, data_one); /* xx 7f 00 FF FF xx xx xx */ pass = check_array_buffer_sub_data(0, buffer_size/8, 64, data_init) && pass; pass = check_array_buffer_sub_data(1*buffer_size/8, buffer_size/8, 4, data_7f) && pass; pass = check_array_buffer_sub_data(2*buffer_size/8, buffer_size/8, 4, data_zero) && pass; pass = check_array_buffer_sub_data(3*buffer_size/8, buffer_size/4, 4, data_one) && pass; pass = check_array_buffer_sub_data(5*buffer_size/8, 3*buffer_size/8, 64, data_init) && pass; glBindBuffer(GL_ARRAY_BUFFER, 0); glDeleteBuffers(1, &buffer); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }
void cullindirect_app::render(double currentTime) { static const GLfloat farplane[] = { 1.0f }; static float lastTime = 0.0f; static int frames = 0; float nowTime = float(currentTime); int i; // Set viewport and clear glViewport(0, 0, info.windowWidth, info.windowHeight); glClearBufferfv(GL_COLOR, 0, sb7::color::Black); glClearBufferfv(GL_DEPTH, 0, farplane); // Bind and clear atomic counter glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buffers.parameters); glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER, GL_R32UI, 0, sizeof(GLuint), GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr); // Bind shader storage buffers glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffers.drawCandidates); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, buffers.drawCommands); // Bind model matrix UBO and fill with data glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffers.modelMatrices); vmath::mat4* pModelMatrix = (vmath::mat4*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, 1024 * sizeof(vmath::mat4), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); for (i = 0; i < 1024; i++) { float f = float(i) / 127.0f + nowTime * 0.025f; float g = float(i) / 127.0f; const vmath::mat4 model_matrix = vmath::translate(70.0f * vmath::vec3(sinf(f * 3.0f), cosf(f * 5.0f), cosf(f * 9.0f))) * vmath::rotate(nowTime * 140.0f, vmath::normalize(vmath::vec3(sinf(g * 35.0f), cosf(g * 75.0f), cosf(g * 39.0f)))); pModelMatrix[i] = model_matrix; } glUnmapBuffer(GL_UNIFORM_BUFFER); // Bind view + projection matrix UBO and fill glBindBufferBase(GL_UNIFORM_BUFFER, 1, buffers.transforms); TransformBuffer* pTransforms = (TransformBuffer*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(TransformBuffer), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); float t = nowTime * 0.1f; const vmath::mat4 view_matrix = vmath::lookat(vmath::vec3(150.0f * cosf(t), 0.0f, 150.0f * sinf(t)), vmath::vec3(0.0f, 0.0f, 0.0f), vmath::vec3(0.0f, 1.0f, 0.0f)); const vmath::mat4 proj_matrix = vmath::perspective(50.0f, (float)info.windowWidth / (float)info.windowHeight, 1.0f, 2000.0f); pTransforms->view_matrix = view_matrix; pTransforms->proj_matrix = proj_matrix; pTransforms->view_proj_matrix = proj_matrix * view_matrix; glUnmapBuffer(GL_UNIFORM_BUFFER); // Bind the culling compute shader and dispatch it glUseProgram(programs.cull); glDispatchCompute(CANDIDATE_COUNT / 16, 1, 1); // Barrier glMemoryBarrier(GL_COMMAND_BARRIER_BIT); // Get ready to render glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glBindVertexArray(object.get_vao()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); // Bind indirect command buffer and parameter buffer glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffers.drawCommands); glBindBuffer(GL_PARAMETER_BUFFER_ARB, buffers.parameters); glUseProgram(programs.draw); // Draw glMultiDrawArraysIndirectCountARB(GL_TRIANGLES, 0, 0, CANDIDATE_COUNT, 0); // Update overlay if (nowTime > (lastTime + 0.25f)) { fps = float(frames) / (nowTime - lastTime); frames = 0; lastTime = nowTime; } glDisable(GL_CULL_FACE); updateOverlay(); frames++; }