void DynamicMarchingTetrahedra::update(GLContext * gl) {

		GLContext::Program * prog = gl->getProgram(m_sceneShader.c_str());
		prog->use();

		Vec3i numBlocks(64);
		Vec3i threadBlockSize(4);
		Vec3i gridSize = (numBlocks + threadBlockSize - 1) / threadBlockSize;

		gl->setUniform(prog->getUniformLoc("cubeInfo"), m_cubeInfo);
		gl->setUniform(prog->getUniformLoc("isPrefixSumPass"), true);

		gl->setUniform(prog->getUniformLoc("numCubes"), numBlocks);

		gl->setUniform(prog->getUniformLoc("sync1"), m_disp1);
		gl->setUniform(prog->getUniformLoc("sync2"), m_disp2);
		gl->setUniform(prog->getUniformLoc("sync3"), m_disp3);
		gl->setUniform(prog->getUniformLoc("sync4"), m_disp4);
		gl->setUniform(prog->getUniformLoc("maxTetrahedras"), 6);

		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffers[DMT_Buffer_Types::INDEX_BUFFER]);
		glDispatchCompute(gridSize.x, gridSize.y, gridSize.z);

		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

		GPUPrefixScan::scan(gl, m_buffers[DMT_Buffer_Types::INDEX_BUFFER], m_buffers[DMT_Buffer_Types::BLOCK_BUFFER], 100*100*100);

		prog->use();
		gl->setUniform(prog->getUniformLoc("isPrefixSumPass"), false);

		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffers[DMT_Buffer_Types::MESH_BUFFER]);
		
		glDispatchCompute(gridSize.x, gridSize.y, gridSize.z);

		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

		m_numTriangles = GPUPrefixScan::getSum(gl, m_buffers[DMT_Buffer_Types::BLOCK_BUFFER]);
	}
void App::renderFrame(GLContext* gl)
{
	// Setup transformations.

	Mat4f worldToCamera = m_cameraCtrl.getWorldToCamera();
	Mat4f projection = gl->xformFitToView(Vec2f(-1.0f, -1.0f), Vec2f(2.0f, 2.0f)) * m_cameraCtrl.getCameraToClip();

	// Initialize GL state.

	glClearColor(0.2f, 0.4f, 0.8f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	if (m_cullMode == CullMode_None)
		glDisable(GL_CULL_FACE);
	else
	{
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
		glFrontFace((m_cullMode == CullMode_CW) ? GL_CCW : GL_CW);
	}

	// No mesh => skip.

	if (!m_mesh)
	{
		gl->drawModalMessage("No mesh loaded!");
		return;
	}

	// if we are computing radiosity, refresh mesh colors every 0.5 seconds
	if ( m_radiosity->isRunning() && m_updateClock.getElapsed() > 0.5f )
	{
		m_radiosity->updateMeshColors();
		m_radiosity->checkFinish();

		// restart cycle
		m_updateClock.start();
	}

	// setup up tone mapping
	GLContext::Program* prog = gl->getProgram("MeshBase::draw_generic");
	prog->use();
    gl->setUniform(prog->getUniformLoc("reinhardLWhite"), m_toneMapWhite);
    gl->setUniform(prog->getUniformLoc("tonemapBoost"), m_toneMapBoost);

	// Render.

	if (!gl->getConfig().isStereo)
		renderScene(gl, worldToCamera, projection);
	else
	{
		glDrawBuffer(GL_BACK_LEFT);
		renderScene(gl, m_cameraCtrl.getCameraToLeftEye() * worldToCamera, projection);
		glDrawBuffer(GL_BACK_RIGHT);
		glClear(GL_DEPTH_BUFFER_BIT);
		renderScene(gl, m_cameraCtrl.getCameraToRightEye() * worldToCamera, projection);
		glDrawBuffer(GL_BACK);
	}

	m_areaLight->setSize( Vec2f( m_lightSize ) );
	m_areaLight->draw( worldToCamera, projection );

	// Display status line.

	m_commonCtrl.message(sprintf("Triangles = %d, vertices = %d, materials = %d",
		m_mesh->numTriangles(),
		m_mesh->numVertices(),
		m_mesh->numSubmeshes()),
		"meshStats");
}