// Renders the result of the "MotionBlur" sample for comparison purposes. // NOTE: this cannot show fullscreen motion blur. void MotionBlur::renderSceneBlurred(const nv::matrix4f& houseXform, const nv::matrix4f& sailsXform, const nv::matrix4f& prevSailsXform) const { // Render to color/depth FBO glBindFramebuffer(GL_FRAMEBUFFER, mFboID); glViewport(0, 0, NvSampleApp::m_width, NvSampleApp::m_height); // Black glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawModelUnblurred(mSailsModel, sailsXform); // Pass 2: Render the motion blurred moving geometry over static geometry. // Render the Static geometry's depth, Use pass2 (color texture) as motion // blur lookup and write onto Pass1 (color texture). glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glViewport(0, 0, NvSampleApp::m_width, NvSampleApp::m_height); // Yellow, high-contrast if we're not showing the sky box. glClearColor(1.0f, 1.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawModelUnblurred(mHouseModel, houseXform); glDepthMask(false); drawSkybox(); drawModelBlurred(mSailsModel, sailsXform, prevSailsXform); glDepthMask(true); }
bool FXAA::genRenderTexture() { int width = getGLContext()->width(); int height = getGLContext()->height(); glGenFramebuffers(1, &m_sourceFrameBuffer); glBindFramebuffer(GL_FRAMEBUFFER, m_sourceFrameBuffer); glGenTextures(1, &m_sourceTexture); glBindTexture(GL_TEXTURE_2D, m_sourceTexture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_sourceTexture, 0); glGenRenderbuffers(1, &m_sourceDepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, m_sourceDepthBuffer); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_sourceDepthBuffer); glBindRenderbuffer(GL_RENDERBUFFER, 0); // Finalize if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return false; } glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); return true; }
void DeferredShadingMSAA::PerformSinglePassLighting() { glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glDisable(GL_DEPTH_TEST); m_shaderLighting->enable(); // Pass our current matrices to the shader m_shaderLighting->setUniformMatrix4fv("uProjViewMatrix", inverse(m_proj)._array); m_shaderLighting->setUniformMatrix4fv("uViewWorldMatrix", inverse(m_transformer->getModelViewMat())._array); // Pass all of the parameters that define our lighting and MSAA mode to the shader m_shaderLighting->setUniform1i("uSeparateEdgePass", m_bSeparateComplexPass); m_shaderLighting->setUniform1i("uSecondPass", GL_FALSE); m_shaderLighting->setUniform1i("uUseDiscontinuity", (m_approach == APPROACH_DISCONTINUITY)); m_shaderLighting->setUniform1i("uAdaptiveShading", m_bAdaptiveShading); m_shaderLighting->setUniform1i("uShowComplexPixels", m_bMarkComplexPixels); m_shaderLighting->setUniform1i("uLightingModel", m_brdf); m_shaderLighting->setUniform1i("uMSAACount", m_iMSAACount); m_shaderLighting->setUniform1i("uSampleMask", (1 << m_iMSAACount) - 1); // Use our G-Buffer as source textures m_shaderLighting->bindTexture2DMultisample("uTexGBuffer1", 0, m_texGBuffer[0]); m_shaderLighting->bindTexture2DMultisample("uTexGBuffer2", 1, m_texGBuffer[1]); m_shaderLighting->bindTexture2DMultisample("uTexCoverage", 2, m_texGBuffer[2]); // Provide the resolved non-MSAA color buffer so the shader can use it for certain lighting modes m_shaderLighting->bindTextureRect("uResolvedColorBuffer", 3, m_texGBufResolved2); RenderFullscreenQuad(m_shaderLighting); m_shaderLighting->disable(); }
// Additional rendering setup methods void MotionBlur::freeGLBindings(void) const { glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); CHECK_GL_ERROR(); }
void XBScene1::setup(XBBaseGUI *_gui) { XBBaseScene::setup(_gui); wavesMask.allocate(ofGetWidth(), ofGetHeight(), GL_RGB); wavesMask.begin(); ofSetBackgroundAuto(false); ofBackground(0, 0, 0); wavesMask.end(); initWindows(); initParticles(); initWaves(); initStones(); initLines(); blur.setup(getMainFBO().getWidth(), getMainFBO().getHeight(), 0); XBScene1GUI *myGUI = (XBScene1GUI *) gui; myGUI->flashDirector.getParameter().cast<bool>().addListener(this, &XBScene1::flashDirector); }
void DeferredShadingMSAA::reshape(int32_t width, int32_t height) { // Avoid destroying render targets unnecessarily. Only do it if our dimensions have actually changed. if (m_imageWidth != width || m_imageHeight != height) { m_imageWidth = width; m_imageHeight = height; // Destroy the current render targets and let them get recreated on our next draw DestroyRenderTargets(); } glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glViewport(0, 0, m_imageWidth, m_imageHeight); }
void MotionBlur::initFBO(void) { // *** Clean up (in case of a reshape) cleanFBO(); // *** TEXTURES (for FBO attachments) glGenTextures(1, &mTargetTexID); glBindTexture(GL_TEXTURE_2D, mTargetTexID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, NvSampleApp::m_width, NvSampleApp::m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CHECK_GL_ERROR(); glBindTexture(GL_TEXTURE_2D, 0); // *** RENDERBUFFERS (for FBO attachments) glGenRenderbuffers(1, &mRboID); glBindRenderbuffer(GL_RENDERBUFFER, mRboID); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, NvSampleApp::m_width, NvSampleApp::m_height); CHECK_GL_ERROR(); glBindRenderbuffer(GL_RENDERBUFFER, 0); // *** FRAMEBUFFER OBJECTS (for individual pass) glGenFramebuffers(1, &mFboID); glBindFramebuffer(GL_FRAMEBUFFER, mFboID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTargetTexID, 0); CHECK_GL_ERROR(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRboID); CHECK_GL_ERROR(); GLint st = glCheckFramebufferStatus(GL_FRAMEBUFFER); LOGI("Frame Buffer Status : %d", st); if(st == GL_FRAMEBUFFER_COMPLETE) LOGI("GL_FRAMEBUFFER_COMPLETE"); glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); }
void DeferredShadingMSAA::initRendering(void) { NvAssetLoaderAddSearchPath("gl4-kepler/DeferredShadingMSAA"); NvAssetLoaderAddSearchPath("gl4-kepler/DeferredShadingMSAA/models"); if(!requireMinAPIVersion(NvGLAPIVersionGL4(), true)) return; // Require at least one of these multisample extensions if (!requireExtension("GL_NV_framebuffer_multisample", false)) { if (!requireExtension("GL_ARB_multisample", true)) return; } glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); BuildShaders(); // As a demo, we'll use both methods of loading meshes, and time each of them, // to illustrate the differences NvStopWatch* pStopwatch = createStopWatch(); pStopwatch->start(); m_models[SPONZA_MODEL] = LoadModel("models/sponza.obj"); pStopwatch->stop(); float time = pStopwatch->getTime(); LOGI("Standard Model Loading Complete: %f seconds", time); pStopwatch->start(); m_modelsExt[SPONZA_MODEL] = LoadModelExt("models/sponza.obj"); pStopwatch->stop(); time = pStopwatch->getTime(); LOGI("Extended Model Loading Complete: %f seconds", time); m_modelID = SPONZA_MODEL; glDisable(GL_CULL_FACE); glGenQueries(1, &m_queryId); #if ENABLE_GPU_TIMERS for (uint32_t i = 0; i < TIMER_COUNT; ++i) { m_timers[i].init(); } #endif }
// Renders the color buffer for the scene and skybox void MotionBlur::renderSceneUnblurred(const nv::matrix4f& houseXform, const nv::matrix4f& sailsXform) const { // Render to framebuffer glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glViewport(0, 0, NvSampleApp::m_width, NvSampleApp::m_height); // Yellow, high-contrast if we're not showing the sky box. glClearColor(1.0f, 1.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); drawModelUnblurred(mSailsModel, sailsXform); drawModelUnblurred(mHouseModel, houseXform); glDepthMask(false); drawSkybox(); glDepthMask(true); }
void FXAA::draw(void) { nv::matrix4f rotation; nv::matrix4f model; nv::matrix4f mvp; float color0[4]= {0.5,0.5,0.8,1.0}; float color1[4]= {0.5,0.9,0.5,1.0}; m_transformer->setRotationVel(nv::vec3f(0.0f, m_autoSpin ? (NV_PI*0.05f) : 0.0f, 0.0f)); glBindFramebuffer(GL_FRAMEBUFFER, m_sourceFrameBuffer); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLineWidth(m_lineWidth); //draw lined sphere nv::matrix4f vp = m_projection_matrix * m_transformer->getModelViewMat(); nv::rotationX(rotation, float(0.2)); mvp = m_projection_matrix * m_transformer->getModelViewMat() * rotation; drawSphere(&mvp); //draw rings model.make_identity(); model.set_scale(0.04); nv::rotationX(rotation, float(0.1)); mvp = m_projection_matrix * m_transformer->getModelViewMat() * rotation* model; drawObjects(&mvp, color0, 0); model.make_identity(); model.set_scale(0.04); nv::rotationX(rotation, float(NV_PI/2+0.1)); mvp = m_projection_matrix * m_transformer->getModelViewMat() * rotation * model; drawObjects(&mvp, color0, 0); //draw triangle model.make_identity(); model.set_scale(0.03); model.set_translate(nv::vec3f(0.0f, -0.3f, 0.0f)); mvp = m_projection_matrix * m_transformer->getModelViewMat() * model; drawObjects(&mvp, color1, 1); glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); FXAABlit(m_FXAALevel); return; }
void DeferredShadingMSAA::PerformSinglePassLighting_NoMSAA() { glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); m_shaderLighting_NoMSAA->enable(); m_shaderLighting_NoMSAA->setUniformMatrix4fv("uProjViewMatrix", inverse(m_proj)._array); m_shaderLighting_NoMSAA->setUniformMatrix4fv("uViewWorldMatrix", inverse(m_transformer->getModelViewMat())._array); m_shaderLighting_NoMSAA->setUniform1i("uLightingModel", m_brdf); m_shaderLighting_NoMSAA->bindTextureRect("uTexGBuffer1", 0, m_texGBuffer[0]); m_shaderLighting_NoMSAA->bindTextureRect("uTexGBuffer2", 1, m_texGBuffer[1]); RenderFullscreenQuad(m_shaderLighting_NoMSAA); m_shaderLighting_NoMSAA->disable(); }
void DeferredShadingMSAA::draw(void) { nv::perspective(m_proj, 45.0f, (GLfloat)m_width / (GLfloat)m_height, 0.1f, 100.0f); m_MVP = m_proj * m_transformer->getModelViewMat(); m_normalMat = m_transformer->getRotationMat(); if (!UpdateRenderTargetMode()) { // We weren't able to update our render targets properly, so // there's no reason to render anything. return; } glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); glClearDepth(1.0f); glClearStencil(0); glStencilMask(0xFF); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Render scene geometry to G-Buffer if (m_currentRTMode == RTMODE_NOMSAA) { RenderToGBuffer_NoMSAA(); } else { RenderToGBuffer(); } // Resolve G-Buffer if we're using a technique that requires it if (m_approach == APPROACH_COVERAGEMASK) { ResolveMSAAGBuffer(); } if (m_currentRTMode == RTMODE_NOMSAA) { PerformSinglePassLighting_NoMSAA(); } else if (m_bSeparateComplexPass) { // Since we are doing two passes, we need a stencil buffer to identify // which pixels to process as complex (edge) pixels FillStencilBuffer(); if (m_bUsePerSamplePixelShader) { PerformDualPassLighting_PerSample(); } else { PerformDualPassLighting_PerPixel(); } } else { PerformSinglePassLighting(); } #if ENABLE_GPU_TIMERS if (m_statsText) { static float gpuTimesMS[TIMER_COUNT] = { 0.f }; for (int32_t i = 0; i < TIMER_COUNT; ++i) { if (m_timers[i].getStartStopCycles() >= NUM_FRAMES_PER_GPU_TIME) { gpuTimesMS[i] = m_timers[i].getScaledCycles() / m_timers[i].getStartStopCycles(); m_timers[i].reset(); } } std::ostringstream s; s << "geometry: " << std::fixed << std::setprecision(2) << gpuTimesMS[TIMER_GEOMETRY] << " ms" << std::endl; s << "compositing: " << std::fixed << std::setprecision(2) << gpuTimesMS[TIMER_COMPOSITING] << " ms" << std::endl; m_statsText->SetString(s.str().c_str()); } #endif }
void DeferredShadingMSAA::PerformDualPassLighting_PerSample() { glBindFramebuffer(GL_FRAMEBUFFER, m_texOffscreenMSAAFboId); glDisable(GL_DEPTH_TEST); m_shaderLighting->enable(); // Pass our current matrices to the shader m_shaderLighting->setUniformMatrix4fv("uProjViewMatrix", inverse(m_proj)._array); m_shaderLighting->setUniformMatrix4fv("uViewWorldMatrix", inverse(m_transformer->getModelViewMat())._array); // Pass all of the parameters that define our lighting and MSAA mode to the shader m_shaderLighting->setUniform1i("uSeparateEdgePass", m_bSeparateComplexPass); m_shaderLighting->setUniform1i("uSecondPass", GL_FALSE); m_shaderLighting->setUniform1i("uUseDiscontinuity", (m_approach == APPROACH_DISCONTINUITY)); m_shaderLighting->setUniform1i("uAdaptiveShading", m_bAdaptiveShading); m_shaderLighting->setUniform1i("uShowComplexPixels", m_bMarkComplexPixels); m_shaderLighting->setUniform1i("uLightingModel", m_brdf); m_shaderLighting->setUniform1i("uMSAACount", m_iMSAACount); m_shaderLighting->setUniform1i("uSampleMask", (1 << m_iMSAACount) - 1); // Use our G-Buffer as source textures m_shaderLighting->bindTexture2DMultisample("uTexGBuffer1", 0, m_texGBuffer[0]); m_shaderLighting->bindTexture2DMultisample("uTexGBuffer2", 1, m_texGBuffer[1]); m_shaderLighting->bindTexture2DMultisample("uTexCoverage", 2, m_texGBuffer[2]); // Provide the resolved non-MSAA color buffer so the shader can use it for certain lighting modes m_shaderLighting->bindTextureRect("uResolvedColorBuffer", 3, m_texGBufResolved2); // Render First (Simple Pixel) Pass glEnable(GL_STENCIL_TEST); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilMask(0x00); // Disable writing to the stencil mask RenderFullscreenQuad(m_shaderLighting); m_shaderLighting->disable(); // Render Second (Complex Pixel) Pass glStencilFunc(GL_EQUAL, 0, 0xFF); if (m_bMarkComplexPixels) { m_shaderLightingMarkComplex->enable(); RenderFullscreenQuad(m_shaderLightingMarkComplex); m_shaderLightingMarkComplex->disable(); } else { m_shaderLightingPerSample->enable(); m_shaderLightingPerSample->setUniformMatrix4fv("uProjViewMatrix", inverse(m_proj)._array); m_shaderLightingPerSample->setUniformMatrix4fv("uViewWorldMatrix", inverse(m_transformer->getModelViewMat())._array); m_shaderLightingPerSample->setUniform1i("uSecondPass", GL_TRUE); m_shaderLightingPerSample->setUniform1i("uLightingModel", m_brdf); m_shaderLightingPerSample->bindTexture2DMultisample("uTexGBuffer1", 0, m_texGBuffer[0]); m_shaderLightingPerSample->bindTexture2DMultisample("uTexGBuffer2", 1, m_texGBuffer[1]); m_shaderLightingPerSample->bindTexture2DMultisample("uTexCoverage", 2, m_texGBuffer[2]); m_shaderLightingPerSample->bindTextureRect("uResolvedColorBuffer", 3, m_texGBufResolved2); glEnable(GL_SAMPLE_SHADING); RenderFullscreenQuad(m_shaderLightingPerSample); glDisable(GL_SAMPLE_SHADING); m_shaderLightingPerSample->disable(); } // Now resolve from our off-screen MSAA lighting accumulation buffer to our final, presentable framebuffer glBindFramebuffer(GL_READ_FRAMEBUFFER, m_texOffscreenMSAAFboId); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getMainFBO()); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glBlitFramebuffer(0, 0, m_imageWidth, m_imageWidth, 0, 0, m_imageWidth, m_imageWidth, GL_COLOR_BUFFER_BIT, GL_NEAREST); }
void NormalBlendedDecal::draw(void) { if ((m_width == 0) || (m_height == 0)) return; nv::matrix4f proj; nv::perspective(proj, 45.0f, (GLfloat)m_width / (GLfloat)m_height, 0.01f, 100.0f); float uScreenSize[] = { (float)m_width, (float)m_height, 0, 0 }; static const GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); // Draw world geometries into gbuffer { glBindFramebuffer(GL_FRAMEBUFFER, mGbufferFBO); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Enable all color buffers glDrawBuffers(3, drawBuffers); // Clear render targets static const GLfloat floatZeroes[] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const GLfloat floatOnes[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glClearBufferfv(GL_COLOR, 0, floatZeroes); glClearBufferfv(GL_COLOR, 1, floatZeroes); glClearBufferfv(GL_COLOR, 2, floatZeroes); glClearBufferfv(GL_DEPTH, 0, floatOnes); // Enable GBuffer program mGbufferProgram->enable(); // Draw scene objects for (unsigned int j = 0; j < mSqrtNumModels; j++) { for (unsigned int i = 0; i < mSqrtNumModels; i++) { // Model transform nv::matrix4f matModel; matModel.set_scale(1.0f); matModel.set_translate(nv::vec3f( .5f*mModelDistance*(mSqrtNumModels - 1.0f) - mModelDistance*i, .5f*mModelDistance*(mSqrtNumModels - 1.0f) - mModelDistance*j, 0.0f)); // Model view transform nv::matrix4f matMV = m_transformer->getModelViewMat() * matModel; // Movel view projection transform nv::matrix4f matMVP = proj * matMV; // Set uniforms mGbufferProgram->setUniformMatrix4fv("uModelViewMatrix", matMV._array); mGbufferProgram->setUniformMatrix4fv("uModelViewProjMatrix", matMVP._array); mGbufferProgram->setUniformMatrix4fv("uModelMatrix", matModel._array); // Draw model mModels[mModelID]->drawElements(0, 1, 2, 3); } } } // Draw decal box into gbuffer { glBindFramebuffer(GL_FRAMEBUFFER, mGbufferDecalFBO); // Enable only color buffer glDrawBuffers(1, drawBuffers); if (mViewOption == VIEW_DECAL_BOXES) { glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE); } mDecalProgram->enable(); // uNormalImage glBindImageTexture(0, mGbufferTextures[NORMAL_TEXTURE], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); // uWorldPosTex glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mGbufferTextures[WORLDPOS_TEXTURE]); mDecalProgram->setUniform4fv("uScreenSize", uScreenSize); mDecalProgram->setUniform1i("uShowDecalBox", (mViewOption == VIEW_DECAL_BOXES) ? true : false); float gridSize = mModelDistance*(mSqrtNumModels - 1.0f); for (unsigned int idx = 0; idx < mNumDecals; idx++) { nv::matrix4f matDecal; matDecal.make_identity(); matDecal.set_scale(nv::vec3f(mDecalSize, mDecalSize, 2.0f)); matDecal.set_translate(nv::vec3f(gridSize*mDecalDistance*mDecalPos[idx].x, gridSize*mDecalDistance*mDecalPos[idx].y, 0)); nv::matrix4f matMVP = proj * m_transformer->getModelViewMat() * matDecal; nv::matrix4f invMVP = inverse(matMVP); nv::matrix4f invModel = inverse(matDecal); mDecalProgram->setUniformMatrix4fv("uModelMatrix", matDecal._array); mDecalProgram->setUniformMatrix4fv("uInvModelMatrix", invModel._array); mDecalProgram->setUniformMatrix4fv("uModelViewProjMatrix", matMVP._array); mDecalProgram->setUniformMatrix4fv("uViewMatrix", m_transformer->getModelViewMat()._array); float weight = mBlendWeight; for (int blendIdx = 0; blendIdx < NUM_DECAL_BLENDS; ++blendIdx) { // uDecalNormalTex glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, mDecalNormals[blendIdx]); mDecalProgram->setUniform1f("uBlendWeight", weight); weight = (blendIdx == (NUM_DECAL_BLENDS - 2)) ? (1.0f - weight) : weight*mBlendWeight; // Draw decal cube mCube->drawElements(0, 1, 2, 3); if (mLock == LOCK_MEMORY_BARRIER) { glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); } } } // Restore states glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); } // Draw combiner pass { // Back to main FBO glBindFramebuffer(GL_FRAMEBUFFER, getMainFBO()); // Disable depth testing glDisable(GL_DEPTH_TEST); // Enable combiner program mCombinerProgram->enable(); // uColorTex glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, mGbufferTextures[COLOR_TEXTURE]); // uNormalTex glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, mGbufferTextures[NORMAL_TEXTURE]); // Set decal box option mCombinerProgram->setUniform1i("uShowDecalBox", (mViewOption == VIEW_DECAL_BOXES) ? true : false); // Set decal box option mCombinerProgram->setUniform1i("uShowNormals", (mViewOption == VIEW_NORMALS) ? true : false); // Set light direction nv::matrix4f invViewMatrix = inverse(m_transformer->getModelViewMat()); nv::vec4f lightDir = invViewMatrix * nv::vec4f(0, 0, 1.0f, 0); lightDir = normalize(lightDir); mCombinerProgram->setUniform4fv("uLightDir", lightDir); // Set view direction nv::vec4f viewDir = invViewMatrix * nv::vec4f(0, 0, -1.0f, 0); viewDir = normalize(viewDir); mCombinerProgram->setUniform4fv("uViewDir", viewDir); // Draw combiner program with screen quad draw2d(0, mCombinerProgram); // Restore states glEnable(GL_DEPTH_TEST); } }