void InstancedTessellation::drawModelLit() {

   m_time += getFrameDeltaTime();
    if (m_instancing&&m_hwInstancing)
        drawModelLitInstancingON();
    else
        drawModelLitInstancingOFF();

    CHECK_GL_ERROR();
}
void OptimizationApp::draw(void)
{
    GLuint prevFBO = 0;
    // Enum has MANY names based on extension/version
    // but they all map to 0x8CA6
    glGetIntegerv(0x8CA6, (GLint*)&prevFBO);

    m_sceneRenderer->getSceneFBOParams()->particleDownsample =
        m_sceneRenderer->getParticleParams()->renderLowResolution ? 2.0f : 1.0f;
    m_sceneRenderer->getSceneFBOParams()->sceneDownsample =
        m_sceneRenderer->getSceneParams()->renderLowResolution ? 2.0f : 1.0f;

    m_sceneRenderer->updateFrame(getFrameDeltaTime());

    // To maintain correct rendering of the blur we have to detect when we've been paused by PerfHUD.
    // This logic ensures that the time-dependent blur remains when the frame debugger is activated.
    m_pausedByPerfHUD = (getFrameDeltaTime() == 0.0f);

    // WARNING!!!!!  This is NOT a great idea for perf, but if we cannot disable
    // vsync, then the CPU stats will be wrong (because some GL call will block on last
    // frame's vsync)
    if (!getGLContext()->setSwapInterval(0))
        glFlush();

    if (!m_pausedByPerfHUD)
        updateViewDependentParams();

    glViewport(0, 0, m_width, m_height);

    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    m_sceneRenderer->renderFrame();

    glBindFramebuffer(GL_FRAMEBUFFER, prevFBO);
    glViewport(0, 0, m_sceneRenderer->getScreenWidth(), m_sceneRenderer->getScreenHeight());
    char buffer[1024];
    if (m_sceneRenderer->stats(buffer, 1024)) {
        m_timingStats->SetString(buffer);
    }
}
예제 #3
0
void MotionBlur::draw(void)
{
    // Get the current view matrix (according to user input through mouse,
    // gamepad, etc.)
    mViewMatrix = m_transformer->getModelViewMat();

    float deltaFrameTime = getFrameDeltaTime();

    // Clamp dt.  If the frame rate goes very low, the stretch becomes huge 
    // and the blurred geometry covers more of the screen which in turns 
    // decreases the FPS even further.  The sample gets into a feedback loop
    // of ever-decreasing FPS.
    const float FPS_CLAMP = 1.0f / 15.0f;
    if (deltaFrameTime > FPS_CLAMP)
        deltaFrameTime = FPS_CLAMP;

    // If the animation is pasued, we still want to show motion blur on the
    // windmill sails
    if (mAnimPaused)
        deltaFrameTime = mLastDt;

    mCurrSailAngle = mLastSailAngle + mSailSpeed * deltaFrameTime;

    // houseXform puts the axle of the sails about centre-screen.
    nv::matrix4f tmp;
    const nv::matrix4f houseXform = nv::translation(tmp, 0.0f, -10.0f, 0.0f);
    const nv::matrix4f currSailsXform = houseXform *
                                        sailTransform(mCurrSailAngle);
    const nv::matrix4f prevSailsXform = houseXform *
                                        sailTransform(mLastSailAngle);

    // Cleaning GL state
    freeGLBindings();

    if (!mDoMotionBlur)
        renderSceneUnblurred(houseXform, currSailsXform);
    else
        renderSceneBlurred(houseXform, currSailsXform, prevSailsXform);

    // Cleaning GL state
    freeGLBindings();

    // If the animation is paused, we update these values to keep the motion
    // blur visible in the windmill sails
    if (!mAnimPaused)
    {
        mLastSailAngle = mCurrSailAngle;
        mLastDt = deltaFrameTime;
    }
}
예제 #4
0
////////////////////////////////////////////////////////////////////////////////
//
//  Method: SkinningApp::draw()
//
//    Performs the actual rendering
//
////////////////////////////////////////////////////////////////////////////////
void SkinningApp::draw(void)
{
    // This function does the actual rendering of the skinned mesh
    GLfloat bones[4 * 4 * 9];

    // Clear the backbuffer
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    
    // enable our vertex and pixel shader
    m_skinningProgram->enable();

    // Compute and update the ModelViewProjection matrix
    nv::matrix4f temp;
    nv::perspective(m_MVP, 45.0f, (GLfloat)m_width / (GLfloat)m_height, 0.1f, 100.0f);
    m_MVP *= m_transformer->getModelViewMat();
    m_skinningProgram->setUniformMatrix4fv(m_ModelViewProjectionLocation, m_MVP._array, 1, false);

    // Compute and update the bone matrices
    computeBones(m_time, bones);
    m_time += m_timeScalar * getFrameDeltaTime();
    m_skinningProgram->setUniformMatrix4fv(m_BonesLocation, bones, 9, false);

    // Update other uniforms
    m_skinningProgram->setUniform3i(m_RenderModeLocation, (int32_t)m_singleBoneSkinning, (int32_t)m_renderMode, 0);
    m_skinningProgram->setUniform3f(m_LightDir0Location, 0.267f, 0.535f, 0.802f);
    m_skinningProgram->setUniform3f(m_LightDir1Location, -0.408f, 0.816f, -0.408f);

    // Render the mesh
    m_mesh.render(m_iPositionLocation, m_iNormalLocation, m_iWeightsLocation);

    // enable our vertex and pixel shader
    m_skinningProgram->disable();
}
예제 #5
0
////////////////////////////////////////////////////////////////////////////////
//
//  Method: BindlessApp::draw()
//
//    Performs the actual rendering
//
////////////////////////////////////////////////////////////////////////////////
void BindlessApp::draw(void)
{
    nv::matrix4f modelviewMatrix;

    glClearColor( 0.5, 0.5, 0.5, 1.0);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    // Enable the vertex and pixel shader
    m_shader->enable();

	if (m_useBindlessTextures) {
		GLuint samplersLocation(m_shader->getUniformLocation("samplers"));
		glUniform1ui64vNV(samplersLocation, m_numTextures, m_textureHandles);

	}

	GLuint bBindlessTexture(m_shader->getUniformLocation("useBindless"));
	glUniform1i(bBindlessTexture, m_useBindlessTextures);

	GLuint currentTexture(m_shader->getUniformLocation("currentFrame"));
	glUniform1i(currentTexture, m_currentFrame);

    // Set up the transformation matices up
    modelviewMatrix = m_transformer->getModelViewMat();
    m_transformUniformsData.ModelView = modelviewMatrix;
    m_transformUniformsData.ModelViewProjection= m_projectionMatrix * modelviewMatrix;
    m_transformUniformsData.UseBindlessUniforms = m_useBindlessUniforms;
    glBindBufferBase(GL_UNIFORM_BUFFER, 2, m_transformUniforms);
    glNamedBufferSubDataEXT(m_transformUniforms, 0, sizeof(TransformUniforms), &m_transformUniformsData);

    
    // If we are going to update the uniforms every frame, do it now
    if(m_updateUniformsEveryFrame == true)
    {
        float deltaTime;
        float dt;

        deltaTime = getFrameDeltaTime();

        if(deltaTime < m_minimumFrameDeltaTime)
        {
            m_minimumFrameDeltaTime = deltaTime;
        }

        dt = std::min(0.00005f / m_minimumFrameDeltaTime, .01f);
        m_t += dt * (float)Mesh::m_drawCallsPerState;

        updatePerMeshUniforms(m_t);
    }


    // Set up default per mesh uniforms. These may be changed on a per mesh basis in the rendering loop below 
    if(m_useBindlessUniforms == true)
    {
        // *** INTERESTING ***
        // Pass a GPU pointer to the vertex shader for the per mesh uniform data via a vertex attribute
        glVertexAttribI2i(m_bindlessPerMeshUniformsPtrAttribLocation, 
                             (int)(m_perMeshUniformsGPUPtr & 0xFFFFFFFF), 
                             (int)((m_perMeshUniformsGPUPtr >> 32) & 0xFFFFFFFF));
    }
예제 #6
0
void SkinningAppVk::draw(void)
{
	VkResult result = VK_ERROR_INITIALIZATION_FAILED;

	NvSimpleUBO<SkinnedMesh::UBOBlock>& uboObj = mMesh.mUBO;
	SkinnedMesh::UBOBlock& ubo = *uboObj;

	// Compute and update the ModelViewProjection matrix
	nv::perspectiveLH(ubo.mMVP, 45.0f, (float)m_width / (float)m_height, 0.1f, 100.0f);
	
	ubo.mMVP *= m_transformer->getModelViewMat();

	// Compute and update the bone matrices
	computeBones(mTime, ubo);
	mTime += mTimeScalar * getFrameDeltaTime();

	// Update other uniforms
	ubo.mRenderMode[0] = (int32_t)mSingleBoneSkinning;
	ubo.mRenderMode[1] = (int32_t)mRenderMode;

	uboObj.Update();

	VkCommandBuffer cmd = vk().getMainCommandBuffer();

	VkRenderPassBeginInfo renderPassBeginInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO };

	renderPassBeginInfo.renderPass = vk().mainRenderTarget()->clearRenderPass();
	renderPassBeginInfo.framebuffer = vk().mainRenderTarget()->frameBuffer();
	renderPassBeginInfo.renderArea.offset.x = 0;
	renderPassBeginInfo.renderArea.offset.y = 0;
	renderPassBeginInfo.renderArea.extent.width = m_width;
	renderPassBeginInfo.renderArea.extent.height = m_height;

	VkClearValue clearValues[2];
	clearValues[0].color.float32[0] = 0.33f;
	clearValues[0].color.float32[1] = 0.44f;
	clearValues[0].color.float32[2] = 0.66f;
	clearValues[0].color.float32[3] = 1.0f;
	clearValues[1].depthStencil.depth = 1.0f;
	clearValues[1].depthStencil.stencil = 0;


	renderPassBeginInfo.pClearValues = clearValues;
	renderPassBeginInfo.clearValueCount = 2;


	vkCmdBeginRenderPass(cmd, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
	{
		// Bind the mPipeline state
		vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline);

		VkViewport vp;
		VkRect2D sc;
		vp.x = 0;
		vp.y = 0;
		vp.height = (float)(m_height);
		vp.width = (float)(m_width);
		vp.minDepth = 0.0f;
		vp.maxDepth = 1.0f;

		sc.offset.x = 0;
		sc.offset.y = 0;
		sc.extent.width = vp.width;
		sc.extent.height = vp.height;

		vkCmdSetViewport(cmd, 0, 1, &vp);
		vkCmdSetScissor(cmd, 0, 1, &sc);

		mMesh.draw(mPipelineLayout, cmd);
	}

	vkCmdEndRenderPass(cmd);

	vk().submitMainCommandBuffer();
}
void CascadedShadowMapping::draw(void) {
    float dt = getFrameDeltaTime();
    m_renderer->render(dt);
    CHECK_GL_ERROR();
}
예제 #8
0
void Mercury::draw(void)
{   
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    if (mReset) {
        mReset = false;
        mParticles->reset();
        mTweakBar->syncValues();
    }

    //
    // Compute matrices without the legacy matrix stack support
    //
    nv::matrix4f projectionMatrix;
    nv::perspective( projectionMatrix, 45.0f * 2.0f*3.14159f / 360.0f, (float)m_width/(float)m_height, 0.1f, 10.0f);

    nv::matrix4f viewMatrix = m_transformer->getModelViewMat();

    //
    // update struct representing UBO
    //
    mShaderParams.numParticles = mParticles->getSize();
    mShaderParams.ModelView = viewMatrix;
	mShaderParams.InvViewMatrix = inverse(viewMatrix);
    mShaderParams.ModelViewProjection = projectionMatrix * viewMatrix;
    mShaderParams.ProjectionMatrix = projectionMatrix;

    // bind the buffer for the UBO, and update it with the latest values from the CPU-side struct
    glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
    glBindBuffer( GL_UNIFORM_BUFFER, mUBO);
    glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(ShaderParams), &mShaderParams);

    if (mAnimate) {
		float timeDelta = getFrameDeltaTime();
        mParticles->update(timeDelta);
    } 
	else {
//		float timeDelta = getFrameDeltaTime();
		mParticles->update(0);
	}

	// Display Binary Space Partitions
	if (mPolygonize) {
		mSurfaceRenderProg->enable();
		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		uint32_t cellsDim = mParticles->getMCPolygonizer()->getCellsDim();
		mShaderParams.cellsize = mParticles->getMCPolygonizer()->getCellSize();


		glEnable(GL_CULL_FACE);
		glEnable(GL_DEPTH_TEST);

		// Bind packed vertex-isovalue buffer.
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mParticles->getMCPolygonizer()->getPackedPosValBuffer());
		// Bind triangle list hash table for marching cubes algorithm to be referenced from Geometry Shader
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, mParticles->getMCPolygonizer()->getTriTableBuffer());

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mParticles->getMCPolygonizer()->getIndexBuffer());

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_CUBE_MAP, mSkyBoxTexID);
		GLuint loc = glGetUniformLocation(mSurfaceRenderProg->getProgram(), "skyBoxTex");
		glProgramUniform1i(mSurfaceRenderProg->getProgram(), loc, 1);	

		glDrawElements(GL_TRIANGLES, cellsDim * cellsDim * cellsDim * 3, GL_UNSIGNED_INT, 0);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_CULL_FACE);

		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		mSurfaceRenderProg->disable();
		
		glClearColor(0.0, 0.0, 0.0, 1.0);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		
		// Draw final scene
		mQuadProg->enable();
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D, gbuffer_tex[0]);
		loc = glGetUniformLocation(mQuadProg->getProgram(), "gbuf0");
		glProgramUniform1i(mQuadProg->getProgram(), loc, 3);
		glActiveTexture(GL_TEXTURE4);
		glBindTexture(GL_TEXTURE_2D, gbuffer_tex[1]);
		loc = glGetUniformLocation(mQuadProg->getProgram(), "gbuf1");
		glProgramUniform1i(mQuadProg->getProgram(), loc, 4);
		glActiveTexture(GL_TEXTURE5);
		glBindTexture(GL_TEXTURE_2D, gbuffer_tex[2]);
		loc = glGetUniformLocation(mQuadProg->getProgram(), "gbuf2");
		glProgramUniform1i(mQuadProg->getProgram(), loc, 5);
		drawScreenAlignedQuad(mQuadProg->getProgram());		
		mQuadProg->disable();
		
		
	} 
	else {
		mParticlesRenderProg->enable();
		// draw particles  

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE);  // additive blend

		glDisable(GL_DEPTH_TEST);
		glDisable(GL_CULL_FACE);

		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, mParticles->getPosBuffer()->getBuffer());
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mParticles->getIndexBuffer()->getBuffer());
		glDrawElements(GL_TRIANGLES, mParticles->getSize() * 6, GL_UNSIGNED_INT, 0);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);

		glDisable(GL_BLEND);
		mParticlesRenderProg->disable();
	}
}
예제 #9
0
void InstancingApp::drawModelLit(void)
{
    int32_t i = m_sceneIndex;
    int32_t si = i; // shader index

    m_time += getFrameDeltaTime();

    // if hardware instancing is on => use second set of shaders
    // that draw instancing data in an attributes
    if( m_instancingOptions == HARDWARE_INSTANCING )
        si = i + 2;

    m_shaders[si]->enable();

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_textureIDs[si]);

    // send time
    glUniform1f(m_timeHandle[si], m_time );

    //send matrices
    glUniformMatrix4fv(m_modelViewMatrixHandle[si], 1, GL_FALSE, m_viewMatrix._array);
    glUniformMatrix4fv(m_projectionMatrixHandle[si], 1, GL_FALSE,
                       m_projectionMatrix._array);
    glUniform3fv(m_instanceColorsHandle[si], 6, &(m_instanceColor[i][0]) );

    glBindBuffer(GL_ARRAY_BUFFER, m_vboID[i]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_iboID[i]);

    glVertexAttribPointer(m_positionHandle[si], 3, GL_FLOAT, GL_FALSE, m_pModel[i]->getModel()->getCompiledVertexSize() * sizeof(float), OFFSET( m_pModel[i]->getModel()->getCompiledPositionOffset() * sizeof(float) )) ;
    glVertexAttribPointer(m_texCoordHandle[si], 3, GL_FLOAT, GL_FALSE, m_pModel[i]->getModel()->getCompiledVertexSize() * sizeof(float), OFFSET(m_pModel[i]->getModel()->getCompiledTexCoordOffset() * sizeof(float)));
    glEnableVertexAttribArray(m_positionHandle[si]);
    glEnableVertexAttribArray(m_texCoordHandle[si]);
    if( m_instancingOptions == SHADER_INSTANCING )
    {
        int32_t offset = 0;

        for( int32_t toDraw = m_instanceCount; toDraw > 0; toDraw -= MAX_INSTANCES )
        {
            NvModelPrimType::Enum prim;
            int32_t draw_count = toDraw < MAX_INSTANCES ? toDraw : MAX_INSTANCES;
            glUniform3fv( m_instanceOffsetHandle[si], draw_count, &(m_instanceOffsets[i][ offset * 3  ]) );
            glUniform3fv( m_instanceRotationHandle[si], draw_count, &(m_instanceRotation[i][ offset * 3  ]) );
            glDrawElements(GL_TRIANGLES, m_pModel[i]->getModel()->getCompiledIndexCount(prim) * draw_count, GL_UNSIGNED_INT, 0);
            offset += draw_count;
        }
    }
    else if( m_instancingOptions == HARDWARE_INSTANCING )
    {
        NvModelPrimType::Enum prim;
        int32_t    floatCount = m_pModel[i]->getModel()->getCompiledVertexCount() * m_pModel[i]->getModel()->getCompiledVertexSize() * MAX_INSTANCES;

        glEnableVertexAttribArray(m_instanceOffsetHandle[si]);
        glEnableVertexAttribArray(m_instanceRotationHandle[si]);

        glVertexAttribPointer(m_instanceOffsetHandle[si], 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), OFFSET( floatCount * sizeof(float) )) ;
        glVertexAttribPointer(m_instanceRotationHandle[si], 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), OFFSET( ( floatCount + 3 ) * sizeof(float) ) );

        glVertexAttribDivisorInternal( m_instanceOffsetHandle[si], 1 );
        glVertexAttribDivisorInternal( m_instanceRotationHandle[si], 1  );

        glDrawElementsInstancedInternal(GL_TRIANGLES, m_pModel[i]->getModel()->getCompiledIndexCount(prim), GL_UNSIGNED_INT, 0, m_instanceCount );

        glVertexAttribDivisorInternal( m_instanceOffsetHandle[si], 0 );
        glVertexAttribDivisorInternal( m_instanceRotationHandle[si], 0  );

        glDisableVertexAttribArray(m_instanceOffsetHandle[si]);
        glDisableVertexAttribArray(m_instanceRotationHandle[si]);
    }
    else if( m_instancingOptions == NO_INSTANCING )
    {
        for( uint32_t j = 0; j < m_instanceCount; ++j )
        {
            NvModelPrimType::Enum prim;
            glUniform3fv(m_instanceOffsetHandle[si], 1, &(m_instanceOffsets[i][j * 3]));
            glUniform3fv( m_instanceRotationHandle[si], 1, &(m_instanceRotation[i][ j * 3  ]) );
            glDrawElements(GL_TRIANGLES, m_pModel[i]->getModel()->getCompiledIndexCount(prim), GL_UNSIGNED_INT, 0);
        }
    }
    glDisableVertexAttribArray(m_positionHandle[si]);
    glDisableVertexAttribArray(m_texCoordHandle[si]);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glBindTexture(GL_TEXTURE_2D, 0);

    m_shaders[si]->disable();
}
예제 #10
0
void TerrainTessellation::draw(void)
{
    glClearColor( 0.7f, 0.8f, 1.0f, 1.0f);
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    //
    // Compute matrices without the legacy matrix stack support
    //
    nv::matrix4f projectionMatrix;
    nv::perspective( projectionMatrix, 45.0f * 2.0f*NV_PI / 360.0f, (float)m_width/(float)m_height, 0.01f, 100.0f);
    nv::matrix4f invProjection = nv::inverse(projectionMatrix);

    nv::matrix4f viewMatrix;
    viewMatrix = m_transformer->getModelViewMat();
    nv::matrix4f invView = nv::inverse(viewMatrix);

    // compute frustum planes for culling
    nv::vec4f frustumPlanes[6];
    computeFrustumPlanes(viewMatrix, projectionMatrix, frustumPlanes);

    glViewport(0, 0, m_width, m_height);

    glBindProgramPipeline(0);

    //
    // update struct representing UBO
    //
    mParams.ModelView = viewMatrix;
    mParams.ModelViewProjection= projectionMatrix * viewMatrix;
    mParams.Projection = projectionMatrix;
    mParams.InvProjection = invProjection;
    mParams.InvView = invView;

    mParams.cull = mCull;
    mParams.lod = mLod;
    mParams.viewport = nv::vec4f(0.0, 0.0, (float) m_width, (float) m_height);
    mParams.lightDirWorld = mLightDir;
    mParams.lightDir = nv::vec3f(viewMatrix * nv::vec4f(normalize(mLightDir), 0.0));   // transform to eye space
    mParams.smoothNormals = mSmoothNormals;
    mParams.time = mTime;
    mParams.eyePosWorld = invView * nv::vec4f(0.0f, 0.0f, 0.0f, 1.0f);

    if (mAnimate) {
        mParams.translate.y -= getFrameDeltaTime()*2.0f;
    }

    for(int i=0; i<6; i++) {
        mParams.frustumPlanes[i] = frustumPlanes[i];
    }

    // bind the buffer for the UBO, and update it with the latest values from the CPU-side struct
    glBindBufferBase( GL_UNIFORM_BUFFER, 1, mUBO);
    glBindBuffer( GL_UNIFORM_BUFFER, mUBO);
    glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(TessellationParams), &mParams);

    // enable / disable wireframe
    glPolygonMode( GL_FRONT_AND_BACK, mWireframe ? GL_LINE : GL_FILL);

    // query number of primitives
    glBeginQuery(GL_PRIMITIVES_GENERATED, mGPUQuery);

    drawTerrain();

    glEndQuery(GL_PRIMITIVES_GENERATED);

    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);

    drawSky();

    // update triangle count so we can display in UI
    glGetQueryObjectuiv(mGPUQuery, GL_QUERY_RESULT, &mNumPrimitives);
    mStatsText->SetValue(mNumPrimitives);

    if (mReload) {
        loadShaders();
        mReload = false;
        mTweakBar->syncValues();
    }
}