示例#1
0
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();
}
示例#2
0
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();
}
示例#5
0
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();
}
示例#7
0
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();
	}
}
示例#10
0
// 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;
}
示例#11
0
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();
	}
}
示例#17
0
//-----------------------------------------------------------------------------
// 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();
}
示例#19
0
//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();
}
示例#20
0
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();
		}		
	}
}
示例#25
0
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();
		}
	}
}
示例#28
0
//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;
			}
		}
	}
}