diff options
| -rw-r--r-- | indra/llrender/llcubemap.cpp | 218 | ||||
| -rw-r--r-- | indra/llrender/llcubemap.h | 16 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/llenvironmentmap.cpp | 116 | ||||
| -rw-r--r-- | indra/newview/llenvironmentmap.h | 48 | ||||
| -rw-r--r-- | indra/newview/llviewermenu.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 7 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 7 | 
9 files changed, 231 insertions, 195 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 834084674e..40d15280d3 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -166,6 +166,39 @@ void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)  	}  } +void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages) +{ +    llassert(rawimages.size() == 6); + +    U32 texname = 0; + +    LLImageGL::generateTextures(1, &texname); + +    U32 resolution = rawimages[0]->getWidth(); +    U32 components = rawimages[0]->getComponents(); + +    for (int i = 0; i < 6; i++) +    { +        llassert(rawimages[i]->getWidth() == resolution); +        llassert(rawimages[i]->getHeight() == resolution); +        llassert(rawimages[i]->getComponents() == components); + + +        mImages[i] = new LLImageGL(resolution, resolution, components, FALSE); +        mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP); +        mRawImages[i] = rawimages[i]; +        mImages[i]->createGLTexture(0, mRawImages[i], texname); + +        gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); +        mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP); +        stop_glerror(); + +        mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution); +    } +    gGL.getTexUnit(0)->disable(); +    disable(); +} +  GLuint LLCubeMap::getGLName()  {  	return mImages[0]->getTexName(); @@ -256,191 +289,6 @@ void LLCubeMap::restoreMatrix()  	}*/  } -void LLCubeMap::setReflection (void) -{ -	gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName()); -	mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); -	mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP); -} - -LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const -{ -	LLVector3 dir; - -	const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z -	const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1 -	const U8 i_coef = (curr_coef + 1) % 3; -	const U8 j_coef = (i_coef + 1) % 3; - -	dir.mV[curr_coef] = side_dir; - -	switch (side) -	{ -	case 0: // negative X -		dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1; -		dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1; -		break; -	case 1: // positive X -		dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1; -		dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1; -		break; -	case 2:	// negative Y -		dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1; -		dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1; -		break; -	case 3:	// positive Y -		dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1; -		dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1; -		break; -	case 4:	// negative Z -		dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1; -		dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1; -		break; -	case 5: // positive Z -		dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1; -		dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1; -		break; -	default: -		dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1; -		dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1; -	} - -	dir.normVec(); -	return dir; -} - - -BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside, -						U8 side, const LLVector3& dir) const -{ -	const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z -	const S8 side_dir = (((side & 1) << 1) - 1);  // even = -1, odd = 1 -	const U8 i_coef = (curr_coef + 1) % 3; -	const U8 j_coef = (i_coef + 1) % 3; - -	outside = TRUE; -	if (side_dir * dir.mV[curr_coef] < 0) -		return FALSE; - -	LLVector3 ray; - -	F32 norm_val = fabs(dir.mV[curr_coef]); - -	if (norm_val < epsilon) -		norm_val = 1e-5f; - -	ray.mV[curr_coef] = side_dir; -	ray.mV[i_coef] = dir.mV[i_coef] / norm_val; -	ray.mV[j_coef] = dir.mV[j_coef] / norm_val; - - -	const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION; -	const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION; - -	switch (side) -	{ -	case 0: // negative X -		v_val = RESOLUTION - i_val; -		h_val = j_val; -		break; -	case 1: // positive X -		v_val = RESOLUTION - i_val; -		h_val = RESOLUTION - j_val; -		break; -	case 2:	// negative Y -		v_val = RESOLUTION - i_val; -		h_val = j_val; -		break; -	case 3:	// positive Y -		v_val = i_val; -		h_val = j_val; -		break; -	case 4:	// negative Z -		v_val = RESOLUTION - j_val; -		h_val = RESOLUTION - i_val; -		break; -	case 5: // positive Z -		v_val = RESOLUTION - j_val; -		h_val = i_val; -		break; -	default: -		v_val = i_val; -		h_val = j_val; -	} - -	outside =  ((v_val < 0) || (v_val > RESOLUTION) || -		(h_val < 0) || (h_val > RESOLUTION)); - -	return TRUE; -} - -BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,  -						U8 side, LLVector3 dir[4]) const -{ -	v_min = h_min = RESOLUTION; -	v_max = h_max = 0; - -	BOOL fully_outside = TRUE; -	for (U8 vtx = 0; vtx < 4; ++vtx) -	{ -		F32 v_val, h_val; -		BOOL outside; -		BOOL consider = project(v_val, h_val, outside, side, dir[vtx]); -		if (!outside) -			fully_outside = FALSE; -		if (consider) -		{ -			if (v_val < v_min) v_min = v_val; -			if (v_val > v_max) v_max = v_val; -			if (h_val < h_min) h_min = h_val; -			if (h_val > h_max) h_max = h_val; -		} -	} - -	v_min = llmax(0.0f, v_min); -	v_max = llmin(RESOLUTION - epsilon, v_max); -	h_min = llmax(0.0f, h_min); -	h_max = llmin(RESOLUTION - epsilon, h_max); - -	return !fully_outside; -} - - -void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col) -{ -    LL_PROFILE_ZONE_SCOPED; -	F32 v_min, v_max, h_min, h_max; -	LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3]; -	center.normVec(); - -	for (U8 side = 0; side < 6; ++side) -	{ -		if (!project(v_min, v_max, h_min, h_max, side, dir)) -			continue; - -		U8 *td = mRawImages[side]->getData(); -		 -		U16 v_minu = (U16) v_min; -		U16 v_maxu = (U16) (ceil(v_max) + 0.5); -		U16 h_minu = (U16) h_min; -		U16 h_maxu = (U16) (ceil(h_max) + 0.5); - -		for (U16 v = v_minu; v < v_maxu; ++v) -			for (U16 h = h_minu; h < h_maxu; ++h) -		//for (U16 v = 0; v < RESOLUTION; ++v) -		//	for (U16 h = 0; h < RESOLUTION; ++h) -			{ -				const LLVector3 ray = map(side, v, h); -				if (ray * center > 0.999) -				{ -					const U32 offset = (RESOLUTION * v + h) * 4; -					for (U8 cc = 0; cc < 3; ++cc) -						td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5); -				} -			} -		mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION); -	} -}  void LLCubeMap::destroyGL()  { diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h index a01636d8d4..9ce4a94bca 100644 --- a/indra/llrender/llcubemap.h +++ b/indra/llrender/llcubemap.h @@ -40,6 +40,13 @@ class LLCubeMap : public LLRefCount  public:  	LLCubeMap(bool init_as_srgb);  	void init(const std::vector<LLPointer<LLImageRaw> >& rawimages); + +    // init from environment map images +    // Similar to init, but takes ownership of rawimages and makes this cubemap +    // respect the resolution of rawimages +    // Raw images must point to array of six square images that are all the same resolution +    // For example usage, see LLEnvironmentMap +    void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);  	void initGL();  	void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);  	void initGLData(); @@ -54,18 +61,9 @@ public:  	void disableTexture(void);  	void setMatrix(S32 stage);  	void restoreMatrix(); -	void setReflection (void); - -	void finishPaint();  	GLuint getGLName(); -	LLVector3 map(U8 side, U16 v_val, U16 h_val) const; -	BOOL project(F32& v_val, F32& h_val, BOOL& outside, -						U8 side, const LLVector3& dir) const; -	BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,  -						U8 side, LLVector3 dir[4]) const; -	void paintIn(LLVector3 dir[4], const LLColor4U& col);  	void destroyGL();  public: diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 964615320d..5e50f58595 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -196,6 +196,7 @@ set(viewer_SOURCE_FILES      lldynamictexture.cpp      llemote.cpp      llenvironment.cpp +    llenvironmentmap.cpp      llestateinfomodel.cpp      lleventnotifier.cpp      lleventpoll.cpp @@ -832,6 +833,7 @@ set(viewer_HEADER_FILES      lldynamictexture.h      llemote.h      llenvironment.h +    llenvironmentmap.h      llestateinfomodel.h      lleventnotifier.h      lleventpoll.h diff --git a/indra/newview/llenvironmentmap.cpp b/indra/newview/llenvironmentmap.cpp new file mode 100644 index 0000000000..7f23c630f1 --- /dev/null +++ b/indra/newview/llenvironmentmap.cpp @@ -0,0 +1,116 @@ +/** + * @file llenvironmentmap.cpp + * @brief LLEnvironmentMap class implementation + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llenvironmentmap.h" +#include "pipeline.h" +#include "llviewerwindow.h" + +LLEnvironmentMap::LLEnvironmentMap() +{ +    mOrigin.setVec(0, 0, 0); +} + +void LLEnvironmentMap::update(const LLVector3& origin, U32 resolution) +{ +    LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + +    mOrigin = origin; + +    // allocate images +    std::vector<LLPointer<LLImageRaw> > rawimages; +    rawimages.reserve(6); + +    for (int i = 0; i < 6; ++i) +    { +        rawimages.push_back(new LLImageRaw(resolution, resolution, 3)); +    } + +    // ============== modified copy/paste of LLFloater360Capture::capture360Images() follows ============== + +    // these are the 6 directions we will point the camera, see LLCubeMap::mTargets +    LLVector3 look_dirs[6] = { +        LLVector3(-1, 0, 0), +        LLVector3(1, 0, 0), +        LLVector3(0, -1, 0), +        LLVector3(0, 1, 0), +        LLVector3(0, 0, -1), +        LLVector3(0, 0, 1) +    }; + +    LLVector3 look_upvecs[6] = {  +        LLVector3(0, -1, 0),  +        LLVector3(0, -1, 0),  +        LLVector3(0, 0, -1),  +        LLVector3(0, 0, 1),  +        LLVector3(0, 1, 0),  +        LLVector3(0, -1, 0)  +    }; + +    // save current view/camera settings so we can restore them afterwards +    S32 old_occlusion = LLPipeline::sUseOcclusion; + +    // set new parameters specific to the 360 requirements +    LLPipeline::sUseOcclusion = 0; +    LLViewerCamera* camera = LLViewerCamera::getInstance(); +    LLVector3 old_origin = camera->getOrigin(); +    F32 old_fov = camera->getView(); +    F32 old_aspect = camera->getAspect(); +    F32 old_yaw = camera->getYaw(); + +    // camera constants for the square, cube map capture image +    camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV +    camera->setView(F_PI_BY_TWO); +    camera->yaw(0.0); +    camera->setOrigin(mOrigin); + +    // for each of the 6 directions we shoot... +    for (int i = 0; i < 6; i++) +    { +        // set up camera to look in each direction +        camera->lookDir(look_dirs[i], look_upvecs[i]); + +        // call the (very) simplified snapshot code that simply deals +        // with a single image, no sub-images etc. but is very fast +        gViewerWindow->simpleSnapshot(rawimages[i], +            resolution, resolution, 1); +    } + +    // restore original view/camera/avatar settings settings +    camera->setAspect(old_aspect); +    camera->setView(old_fov); +    camera->yaw(old_yaw); +    camera->setOrigin(old_origin); + +    LLPipeline::sUseOcclusion = old_occlusion; + +    // ==================================================== +     +    mCubeMap = new LLCubeMap(false); +    mCubeMap->initEnvironmentMap(rawimages); +} + diff --git a/indra/newview/llenvironmentmap.h b/indra/newview/llenvironmentmap.h new file mode 100644 index 0000000000..7d951eb678 --- /dev/null +++ b/indra/newview/llenvironmentmap.h @@ -0,0 +1,48 @@ +/** + * @file llenvironmentmap.h + * @brief LLEnvironmentMap class declaration + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#pragma once + +#include "llcubemap.h" + +class LLEnvironmentMap +{ +public: +    // allocate an environment map of the given resolution  +    LLEnvironmentMap(); + +    // update this environment map +    // origin - position in agent space to generate environment map from in agent space +    // resolution - size of cube map to generate +    void update(const LLVector3& origin, U32 resolution); +     +    // cube map used to sample this environment map +    LLPointer<LLCubeMap> mCubeMap; + +    // point at which environment map was generated from (in agent space) +    LLVector3 mOrigin; +}; + diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e3de4267dc..f5ea060e82 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8304,6 +8304,12 @@ void handle_cache_clear_immediately()  	LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);  } +void handle_override_environment_map() +{ +    gPipeline.overrideEnvironmentMap(); +} + +  void handle_web_content_test(const LLSD& param)  {  	std::string url = param.asString(); @@ -9402,6 +9408,8 @@ void initialize_menus()  	view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");  	//Develop (clear cache immediately)  	commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); +    //Develop (override environment map) +    commit.add("Develop.OverrideEnvironmentMap", boost::bind(&handle_override_environment_map));  	// Admin >Object  	view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 20d6fe39e3..09437473d9 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8191,7 +8191,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_  	channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);  	if (channel > -1)  	{ -		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; +		LLCubeMap* cube_map = mEnvironmentMap.mCubeMap.notNull() ? mEnvironmentMap.mCubeMap : gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;  		if (cube_map)  		{  			cube_map->enable(channel); @@ -11467,3 +11467,8 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )  	}  } +void LLPipeline::overrideEnvironmentMap() +{ +    mEnvironmentMap.update(LLViewerCamera::instance().getOrigin(), 1024); +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 62d3ae7a39..150d3c7d58 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -38,6 +38,7 @@  #include "llgl.h"  #include "lldrawable.h"  #include "llrendertarget.h" +#include "llenvironmentmap.h"  #include <stack> @@ -426,6 +427,9 @@ public:  	void hideObject( const LLUUID& id );  	void restoreHiddenObject( const LLUUID& id ); +    LLEnvironmentMap mEnvironmentMap; +    void overrideEnvironmentMap(); +  private:  	void unloadShaders();  	void addToQuickLookup( LLDrawPool* new_poolp ); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 8d7cfe1116..db4e794ed4 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3250,6 +3250,13 @@ function="World.EnvPreset"                   function="ToggleControl"                   parameter="RenderHoverGlowEnable" />              </menu_item_check> +            <menu_item_call +              enabled="true" +              label="Override Environment Map" +              name="Override Environment Map"> +              <menu_item_call.on_click +               function="Develop.OverrideEnvironmentMap" /> +            </menu_item_call>            <menu_item_separator />            <menu_item_call  | 
