void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { validateRange(start, end, count, indices_offset); llassert(mRequestedNumVerts >= 0); if (mGLIndices != sGLRenderIndices) { llerrs << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { llerrs << "Wrong vertex buffer bound." << llendl; } if (mode >= LLRender::NUM_MODES) { llerrs << "Invalid draw mode: " << mode << llendl; return; } U16* idx = ((U16*) getIndicesPointer())+indices_offset; stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, idx); stop_glerror(); }
void render_ui_3d() { LLGLSPipeline gls_pipeline; ////////////////////////////////////// // // Render 3D UI elements // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD, // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD // ///////////////////////////////////////////////////////////// // // Render 2.5D elements (2D elements in the world) // Stuff without z writes // // Debugging stuff goes before the UI. if (gSavedSettings.getBOOL("ShowDepthBuffer")) { post_show_depth_buffer(); } // Coordinate axes if (gSavedSettings.getBOOL("ShowAxes")) { draw_axes(); } stop_glerror(); gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements stop_glerror(); }
void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); if (fetch_depth) { if (!mDepth) { allocateDepth(); } gGL.getTexUnit(0)->bind(this); glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); } else { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } }
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(mRequestedNumVerts >= 0); if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl; } if (mGLBuffer != sGLRenderBuffer || useVBOs() != sVBOActive) { llerrs << "Wrong vertex buffer bound." << llendl; } if (mode >= LLRender::NUM_MODES) { llerrs << "Invalid draw mode: " << mode << llendl; return; } stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); }
bool LLRenderTarget::allocateDepth() { if (mStencil) { //use render buffers where stencil buffers are in play glGenRenderbuffers(1, (GLuint *) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); stop_glerror(); clear_glerror(); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { LLImageGL::generateTextures(1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); stop_glerror(); clear_glerror(); LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } sBytesAllocated += mResX*mResY*4; if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for render target." << llendl; return false; } return true; }
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(mRequestedNumIndices >= 0); if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { llerrs << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { llerrs << "Wrong vertex buffer bound." << llendl; } if (mode >= LLRender::NUM_MODES) { llerrs << "Invalid draw mode: " << mode << llendl; return; } stop_glerror(); glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); }
void LLWLParamSet::update(LLGLSLShader * shader) const { LLFastTimer t(FTM_WL_PARAM_UPDATE); for(LLSD::map_const_iterator i = mParamValues.beginMap(); i != mParamValues.endMap(); ++i) { const std::string& param = i->first; if( param == "star_brightness" || param == "preset_num" || param == "sun_angle" || param == "east_angle" || param == "enable_cloud_scroll" || param == "cloud_scroll_rate" || param == "lightnorm" ) { continue; } if(param == "cloud_pos_density1") { LLVector4 val; val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset; val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset; val.mV[2] = (F32) i->second[2].asReal(); val.mV[3] = (F32) i->second[3].asReal(); stop_glerror(); shader->uniform4fv(param, 1, val.mV); stop_glerror(); } else // param is the uniform name { LLVector4 val; // handle all the different cases if(i->second.isArray() && i->second.size() == 4) { val.mV[0] = (F32) i->second[0].asReal(); val.mV[1] = (F32) i->second[1].asReal(); val.mV[2] = (F32) i->second[2].asReal(); val.mV[3] = (F32) i->second[3].asReal(); } else if(i->second.isReal()) { val.mV[0] = (F32) i->second.asReal(); } else if(i->second.isInteger()) { val.mV[0] = (F32) i->second.asReal(); } else if(i->second.isBoolean()) { val.mV[0] = i->second.asBoolean(); } stop_glerror(); shader->uniform4fv(param, 1, val.mV); stop_glerror(); } } }
void LLRenderTarget::bindTarget() { if (mFBO) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; glDrawBuffersARB(mTex.size(), drawbuffers); } if (mTex.empty()) { //no color buffer to draw to glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } check_framebuffer_status(); stop_glerror(); } glViewport(0, 0, mResX, mResY); sBoundTarget = this; }
//static void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { if (!source.mFBO) { llwarns << "Cannot copy framebuffer contents for non FBO render targets." << llendl; return; } { GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; LLGLDepthTest depth(write_depth, write_depth); glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO); stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } }
// Map for data access U8* LLVertexBuffer::mapBuffer(S32 access) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) { llwarns << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { llwarns << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; } if (!mLocked && useVBOs()) { setBuffer(0); mLocked = TRUE; stop_glerror(); mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); stop_glerror(); mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); stop_glerror(); if (!mMappedData) { //-------------------- //print out more debug info before crash llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; GLint size ; glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; //-------------------- GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLBuffer) { llwarns << "Invalid GL vertex buffer bound: " << buff << llendl; } llwarns << "glMapBuffer returned NULL (no vertex data)" << llendl; } if (!mMappedIndexData) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if (buff != mGLIndices) { llwarns << "Invalid GL index buffer bound: " << buff << llendl; } llwarns << "glMapBuffer returned NULL (no index data)" << llendl; } sMappedCount++; } return mMappedData; }
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { llwarns << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; } if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { llwarns << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } if (mGLIndices != sGLRenderIndices) { llwarns << "Wrong index buffer bound." << llendl; } if (mGLBuffer != sGLRenderBuffer) { llwarns << "Wrong vertex buffer bound." << llendl; } if (mode > LLRender::NUM_MODES) { llwarns << "Invalid draw mode: " << mode << llendl; return; } stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); }
void LLRenderTarget::release() { if (mDepth) { if (mStencil && mFBO) { glDeleteRenderbuffers(1, (GLuint*) &mDepth); stop_glerror(); } else { //Release before delete. if(mFBO) { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); } LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true); stop_glerror(); } mDepth = 0; sBytesAllocated -= mResX*mResY*4; } else if (mUseDepth && mFBO) { //detach shared depth buffer glBindFramebuffer(GL_FRAMEBUFFER, mFBO); if (mStencil) { //attached as a renderbuffer glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); mStencil = false; } else { //attached as a texture glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); } mUseDepth = false; } if (mFBO) { glDeleteFramebuffers(1, (GLuint *) &mFBO); mFBO = 0; } if (mTex.size() > 0) { sBytesAllocated -= mResX*mResY*4*mTex.size(); LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true); mTex.clear(); mInternalFormat.clear(); } mResX = mResY = 0; mSampleBuffer = NULL; sBoundTarget = NULL; }
U8* LLVertexBuffer::mapIndexBuffer(S32 access) { LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); if (mFinal) { llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl; } if (!useVBOs() && !mMappedData && !mMappedIndexData) { llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl; } if (!mIndexLocked && useVBOs()) { { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); setBuffer(0, TYPE_INDEX); mIndexLocked = TRUE; stop_glerror(); if(sDisableVBOMapping) { allocateClientIndexBuffer() ; } else { mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); } stop_glerror(); } if (!mMappedIndexData) { log_glerror(); if(!sDisableVBOMapping) { GLint buff; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { llerrs << "Invalid GL index buffer bound: " << buff << llendl; } llerrs << "glMapBuffer returned NULL (no index data)" << llendl; } else { llerrs << "memory allocation for Index data failed. " << llendl ; } } sMappedCount++; } return mMappedIndexData ; }
void LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { return; } U32 offset = mTex.size(); if (offset >= 4 || (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) { llerrs << "Too many color attachments!" << llendl; } U32 tex; LLImageGL::generateTextures(1, &tex); gGL.getTexUnit(0)->bindManual(mUsage, tex); stop_glerror(); LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); stop_glerror(); if (offset == 0) { gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } else { //don't filter data attachments gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } if (mUsage != LLTexUnit::TT_RECT_TEXTURE) { gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); } else { // ATI doesn't support mirrored repeat for rectangular textures. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } if (mFBO) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } mTex.push_back(tex); }
void render_ui_2d() { LLGLSUIDefault gls_ui; ///////////////////////////////////////////////////////////// // // Render 2D UI elements that overlay the world (no z compare) // Disable wireframe mode below here, as this is HUD/menus glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Menu overlays, HUD, etc gViewerWindow->setup2DRender(); F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); if (zoom_factor > 1.f) { //decompose subregion number to x and y values int pos_y = sub_region / llceil(zoom_factor); int pos_x = sub_region - (pos_y*llceil(zoom_factor)); // offset for this tile LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidth() * (F32)pos_x / zoom_factor); LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor); } stop_glerror(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); // render outline for HUD if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f) { glPushMatrix(); S32 half_width = (gViewerWindow->getWindowWidth() / 2); S32 half_height = (gViewerWindow->getWindowHeight() / 2); glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); glTranslatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgent.mHUDCurZoom; glScalef(zoom,zoom,1.f); gGL.color4fv(LLColor4::white.mV); gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); glPopMatrix(); stop_glerror(); } gViewerWindow->draw(); if (gDebugSelect) { gViewerWindow->drawPickBuffer(); } // reset current origin for font rendering, in case of tiling render LLFontGL::sCurOrigin.set(0, 0); }
void LLDrawPoolSimple::endRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_SIMPLE); stop_glerror(); LLRenderPass::endRenderPass(pass); stop_glerror(); if (mVertexShaderLevel > 0) { simple_shader->unbind(); } }
//----------------------------------------------------------------------------- // updateFaceData() //----------------------------------------------------------------------------- void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) { mFace = face; if (mFace->mVertexBuffer.isNull()) { return; } LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> tex_coordsp; LLStrider<F32> vertex_weightsp; LLStrider<LLVector4> clothing_weightsp; LLStrider<U16> indicesp; // Copy data into the faces from the polymesh data. if (mMesh && mValid) { if (mMesh->getNumVertices()) { stop_glerror(); face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp); stop_glerror(); face->mVertexBuffer->getIndexStrider(indicesp); stop_glerror(); for (U16 i = 0; i < mMesh->getNumVertices(); i++) { verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i); tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i); normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i); vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i); if (damp_wind) { clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0); } else { clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i)); } } for (S32 i = 0; i < mMesh->getNumFaces(); i++) { for (U32 j = 0; j < 3; j++) { U32 k = i*3+j+mMesh->mFaceIndexOffset; indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset; } } } } }
// static void LLScreenClipRect::updateScissorRegion() { LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]); y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]); w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1; h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1; gGL.setScissor( x,y,w,h ); stop_glerror(); }
//static void LLDrawPoolBump::beginBump(U32 pass) { if (!gPipeline.hasRenderBatches(pass)) { return; } sVertexMask = VERTEX_MASK_BUMP; LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); // Optional second pass: emboss bump map stop_glerror(); if (LLGLSLShader::sNoFixedFunction) { gObjectBumpProgram.bind(); } else { // TEXTURE UNIT 0 // Output.rgb = texture at texture coord 0 gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); // TEXTURE UNIT 1 gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); // src = tex0 + (1 - tex1) - 0.5 // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 // = (1 + bump0 - bump1) / 2 // Blend: src * dst + dst * src // = 2 * src * dst // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] // = (1 + bump0 - bump1) * dst.rgb // = dst.rgb + dst.rgb * (bump0 - bump1) gGL.getTexUnit(0)->activate(); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); } gGL.setSceneBlendType(LLRender::BT_MULT_X2); stop_glerror(); }
BOOL LLFontGL::addChar(const llwchar wch) { if (!LLFont::addChar(wch)) { return FALSE; } stop_glerror(); mImageGLp->setSubImage(mRawImageGLp, 0, 0, mImageGLp->getWidth(), mImageGLp->getHeight()); mImageGLp->bind(); mImageGLp->setMipFilterNearest(TRUE, TRUE); stop_glerror(); return TRUE; }
void LLDrawPoolFullbright::endRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_FULLBRIGHT); LLRenderPass::endRenderPass(pass); stop_glerror(); if (mVertexShaderLevel > 0) { fullbright_shader->unbind(); } stop_glerror(); }
bool LLMultisampleBuffer::allocateDepth() { glGenRenderbuffers(1, (GLuint* ) &mDepth); glBindRenderbuffer(GL_RENDERBUFFER, mDepth); stop_glerror(); clear_glerror(); if (mStencil) { glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); } else { glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY); } if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for multisample render target." << llendl; return false; } sBytesAllocated += mResX*mResY*4; return true; }
void LLPostProcess::initialize(unsigned int width, unsigned int height) { destroyGL(); mScreenWidth = width; mScreenHeight = height; createScreenTextures(); createNoiseTexture(); //Setup our VBO. { mVBO = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1,3); mVBO->allocateBuffer(4,0,TRUE); LLStrider<LLVector3> v; LLStrider<LLVector2> uv1; LLStrider<LLVector2> uv2; mVBO->getVertexStrider(v); mVBO->getTexCoord0Strider(uv1); mVBO->getTexCoord1Strider(uv2); v[0] = LLVector3( uv2[0] = uv1[0] = LLVector2(0, 0) ); v[1] = LLVector3( uv2[1] = uv1[1] = LLVector2(0, mScreenHeight) ); v[2] = LLVector3( uv2[2] = uv1[2] = LLVector2(mScreenWidth, 0) ); v[3] = LLVector3( uv2[3] = uv1[3] = LLVector2(mScreenWidth, mScreenHeight) ); mVBO->flush(); } stop_glerror(); }
void LLDrawPoolGrass::beginRenderPass(S32 pass) { LLFastTimer t(FTM_RENDER_GRASS); stop_glerror(); if (LLPipeline::sUnderWaterRender) { simple_shader = &gObjectAlphaMaskNonIndexedWaterProgram; } else { simple_shader = &gObjectAlphaMaskNonIndexedProgram; } if (mVertexShaderLevel > 0) { simple_shader->bind(); simple_shader->setMinimumAlpha(0.5f); } else { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); // don't use shaders! if (gGLManager.mHasShaderObjects) { LLGLSLShader::bindNoShader(); } } }
void LLCubeMap::initGL() { llassert(gGLManager.mInited); if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) { // Not initialized, do stuff. if (mImages[0].isNull()) { U32 texname = 0; LLImageGL::generateTextures(1, &texname); for (int i = 0; i < 6; i++) { mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE)); mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); mRawImages[i] = new LLImageRaw(64, 64, 4); mImages[i]->createGLTexture(0, mRawImages[i], texname); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); } gGL.getTexUnit(0)->disable(); } disable(); } else { llwarns << "Using cube map without extension!" << llendl; } }
void LLRenderTarget::release() { if (mDepth) { if (mStencil) { glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth); stop_glerror(); } else { LLImageGL::deleteTextures(1, &mDepth); stop_glerror(); } mDepth = 0; } else if (mUseDepth && mFBO) { //detach shared depth buffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); if (mStencil) { //attached as a renderbuffer glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); mStencil = false; } else { //attached as a texture glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), 0, 0); } mUseDepth = false; } if (mFBO) { glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); mFBO = 0; } if (mTex.size() > 0) { LLImageGL::deleteTextures(mTex.size(), &mTex[0]); mTex.clear(); } mSampleBuffer = NULL; sBoundTarget = NULL; }
void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; LLGLDepthTest depth(write_depth, write_depth); gGL.flush(); if (!source.mFBO || !mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } if (mSampleBuffer) { mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); } else { if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) { stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO); gGL.getTexUnit(0)->bind(this, true); stop_glerror(); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } else { glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); stop_glerror(); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } } }
//static void LLScreenClipRect::updateScissorRegion() { if (sClipRectStack.empty()) return; // finish any deferred calls in the old clipping region gGL.flush(); LLRect rect = sClipRectStack.top(); stop_glerror(); S32 x,y,w,h; x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]); y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]); w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1; h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1; glScissor( x,y,w,h ); stop_glerror(); }
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { if (!mFBO || !target.mFBO) { llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } if (target.mDepth) { llerrs << "Attempting to override existing depth buffer. Detach existing buffer first." << llendl; } if (target.mUseDepth) { llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl; } if (mDepth) { stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); stop_glerror(); if (mStencil) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); target.mStencil = true; } else { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } check_framebuffer_status(); glBindFramebuffer(GL_FRAMEBUFFER, 0); target.mUseDepth = true; } }
void LLWLParamManager::update(LLViewerCamera * cam) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); // update clouds, sun, and general mCurParams.updateCloudScrolling(); // update only if running if(mAnimator.mIsRunning) { mAnimator.update(mCurParams); } // update the shaders and the menu propagateParameters(); // sync menus if they exist if(LLFloaterWindLight::isOpen()) { LLFloaterWindLight::instance()->syncMenu(); } if(LLFloaterDayCycle::isOpen()) { LLFloaterDayCycle::instance()->syncMenu(); } if(LLFloaterEnvSettings::isOpen()) { LLFloaterEnvSettings::instance()->syncMenu(); } F32 camYaw = cam->getYaw(); stop_glerror(); // *TODO: potential optimization - this block may only need to be // executed some of the time. For example for water shaders only. { F32 camYawDelta = mSunDeltaYaw * DEG_TO_RAD; LLVector3 lightNorm3(mLightDir); lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f)); mRotatedLightDir = LLVector4(lightNorm3, 0.f); LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; end_shaders = LLViewerShaderMgr::instance()->endShaders(); for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) { if (shaders_iter->mProgramObject != 0 && (gPipeline.canUseWindLightShaders() || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)) { shaders_iter->mUniformsDirty = TRUE; } } } }