Port of SNOW-643 : Water flicker at high altitude. This doesn't fix the low altitude flicker though (STORM-306)
parent
df67c34b42
commit
c7b6ebaf76
|
|
@ -610,41 +610,46 @@ void LLGLManager::shutdownGL()
|
|||
void LLGLManager::initExtensions()
|
||||
{
|
||||
#if LL_MESA_HEADLESS
|
||||
# if GL_ARB_multitexture
|
||||
# ifdef GL_ARB_multitexture
|
||||
mHasMultitexture = TRUE;
|
||||
# else
|
||||
mHasMultitexture = FALSE;
|
||||
# endif
|
||||
# if GL_ARB_texture_env_combine
|
||||
# ifdef GL_ARB_texture_env_combine
|
||||
mHasARBEnvCombine = TRUE;
|
||||
# else
|
||||
mHasARBEnvCombine = FALSE;
|
||||
# endif
|
||||
# if GL_ARB_texture_compression
|
||||
# ifdef GL_ARB_texture_compression
|
||||
mHasCompressedTextures = TRUE;
|
||||
# else
|
||||
mHasCompressedTextures = FALSE;
|
||||
# endif
|
||||
# if GL_ARB_vertex_buffer_object
|
||||
# ifdef GL_ARB_vertex_buffer_object
|
||||
mHasVertexBufferObject = TRUE;
|
||||
# else
|
||||
mHasVertexBufferObject = FALSE;
|
||||
# endif
|
||||
# if GL_EXT_framebuffer_object
|
||||
# ifdef GL_EXT_framebuffer_object
|
||||
mHasFramebufferObject = TRUE;
|
||||
# else
|
||||
mHasFramebufferObject = FALSE;
|
||||
# endif
|
||||
# if GL_EXT_framebuffer_multisample
|
||||
# ifdef GL_EXT_framebuffer_multisample
|
||||
mHasFramebufferMultisample = TRUE;
|
||||
# else
|
||||
mHasFramebufferMultisample = FALSE;
|
||||
# endif
|
||||
# if GL_ARB_draw_buffers
|
||||
# ifdef GL_ARB_draw_buffers
|
||||
mHasDrawBuffers = TRUE;
|
||||
#else
|
||||
mHasDrawBuffers = FALSE;
|
||||
# endif
|
||||
# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
|
||||
mHasDepthClamp = TRUE;
|
||||
#else
|
||||
mHasDepthClamp = FALSE;
|
||||
#endif
|
||||
# if GL_EXT_blend_func_separate
|
||||
mHasBlendFuncSeparate = TRUE;
|
||||
#else
|
||||
|
|
@ -671,6 +676,7 @@ void LLGLManager::initExtensions()
|
|||
mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression");
|
||||
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
|
||||
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
|
||||
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
|
||||
// mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
|
||||
mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts)
|
||||
&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
|
||||
|
|
@ -694,6 +700,7 @@ void LLGLManager::initExtensions()
|
|||
if (getenv("LL_GL_NOEXT"))
|
||||
{
|
||||
//mHasMultitexture = FALSE; // NEEDED!
|
||||
mHasDepthClamp = FALSE;
|
||||
mHasARBEnvCombine = FALSE;
|
||||
mHasCompressedTextures = FALSE;
|
||||
mHasVertexBufferObject = FALSE;
|
||||
|
|
@ -755,6 +762,7 @@ void LLGLManager::initExtensions()
|
|||
if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;
|
||||
if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE;
|
||||
if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S
|
||||
if (strchr(blacklist,'v')) mHasDepthClamp = FALSE;
|
||||
|
||||
}
|
||||
#endif // LL_LINUX || LL_SOLARIS
|
||||
|
|
@ -2037,7 +2045,7 @@ void LLGLDepthTest::checkState()
|
|||
}
|
||||
}
|
||||
|
||||
LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P)
|
||||
{
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
@ -2050,7 +2058,7 @@ LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
|
|||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
LLGLClampToFarClip::~LLGLClampToFarClip()
|
||||
LLGLSquashToFarClip::~LLGLSquashToFarClip()
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ public:
|
|||
BOOL mHasOcclusionQuery;
|
||||
BOOL mHasPointParameters;
|
||||
BOOL mHasDrawBuffers;
|
||||
BOOL mHasDepthClamp;
|
||||
BOOL mHasTextureRectangle;
|
||||
|
||||
// Other extensions.
|
||||
|
|
@ -315,11 +316,11 @@ private:
|
|||
leaves this class.
|
||||
Does not stack.
|
||||
*/
|
||||
class LLGLClampToFarClip
|
||||
class LLGLSquashToFarClip
|
||||
{
|
||||
public:
|
||||
LLGLClampToFarClip(glh::matrix4f projection);
|
||||
~LLGLClampToFarClip();
|
||||
LLGLSquashToFarClip(glh::matrix4f projection);
|
||||
~LLGLSquashToFarClip();
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -829,5 +829,15 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
|
|||
|
||||
#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
|
||||
|
||||
// Even when GL_ARB_depth_clamp is available in the driver, the (correct)
|
||||
// headers, and therefore GL_DEPTH_CLAMP might not be defined.
|
||||
// In that case GL_DEPTH_CLAMP_NV should be defined, but why not just
|
||||
// use the known numeric.
|
||||
//
|
||||
// To avoid #ifdef's in the code. Just define this here.
|
||||
#ifndef GL_DEPTH_CLAMP
|
||||
// Probably (still) called GL_DEPTH_CLAMP_NV.
|
||||
#define GL_DEPTH_CLAMP 0x864F
|
||||
#endif
|
||||
|
||||
#endif // LL_LLGLHEADERS_H
|
||||
|
|
|
|||
|
|
@ -358,6 +358,7 @@ void LLDrawable::makeActive()
|
|||
{
|
||||
U32 pcode = mVObjp->getPCode();
|
||||
if (pcode == LLViewerObject::LL_VO_WATER ||
|
||||
pcode == LLViewerObject::LL_VO_VOID_WATER ||
|
||||
pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
|
||||
pcode == LLViewerObject::LL_VO_PART_GROUP ||
|
||||
pcode == LLViewerObject::LL_VO_HUD_PART_GROUP ||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
|
|||
case POOL_SKY:
|
||||
poolp = new LLDrawPoolSky();
|
||||
break;
|
||||
case POOL_VOIDWATER:
|
||||
case POOL_WATER:
|
||||
poolp = new LLDrawPoolWater();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
POOL_BUMP,
|
||||
POOL_INVISIBLE, // see below *
|
||||
POOL_AVATAR,
|
||||
POOL_VOIDWATER,
|
||||
POOL_WATER,
|
||||
POOL_GLOW,
|
||||
POOL_ALPHA,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ void LLDrawPoolGround::render(S32 pass)
|
|||
|
||||
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
|
||||
|
||||
LLGLClampToFarClip far_clip(glh_get_current_projection());
|
||||
LLGLSquashToFarClip far_clip(glh_get_current_projection());
|
||||
|
||||
F32 water_height = gAgent.getRegion()->getWaterHeight();
|
||||
glPushMatrix();
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ void LLDrawPoolSky::render(S32 pass)
|
|||
|
||||
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
|
||||
|
||||
LLGLClampToFarClip far_clip(glh_get_current_projection());
|
||||
LLGLSquashToFarClip far_clip(glh_get_current_projection());
|
||||
|
||||
LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -532,6 +532,7 @@ void LLDrawPoolWater::shade()
|
|||
glColor4fv(water_color.mV);
|
||||
|
||||
{
|
||||
LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
|
||||
iter != mDrawFace.end(); iter++)
|
||||
|
|
@ -548,30 +549,19 @@ void LLDrawPoolWater::shade()
|
|||
|
||||
sNeedsReflectionUpdate = TRUE;
|
||||
|
||||
if (water->getUseTexture())
|
||||
if (water->getUseTexture() || !water->getIsEdgePatch())
|
||||
{
|
||||
sNeedsDistortionUpdate = TRUE;
|
||||
face->renderIndexed();
|
||||
}
|
||||
else if (gGLManager.mHasDepthClamp || deferred_render)
|
||||
{
|
||||
face->renderIndexed();
|
||||
}
|
||||
else
|
||||
{ //smash background faces to far clip plane
|
||||
if (water->getIsEdgePatch())
|
||||
{
|
||||
if (deferred_render)
|
||||
{
|
||||
face->renderIndexed();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLClampToFarClip far_clip(glh_get_current_projection());
|
||||
face->renderIndexed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sNeedsDistortionUpdate = TRUE;
|
||||
face->renderIndexed();
|
||||
}
|
||||
{
|
||||
LLGLSquashToFarClip far_clip(glh_get_current_projection());
|
||||
face->renderIndexed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ void LLDrawPoolWLSky::render(S32 pass)
|
|||
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
||||
LLGLDisable clip(GL_CLIP_PLANE0);
|
||||
|
||||
LLGLClampToFarClip far_clip(glh_get_current_projection());
|
||||
LLGLSquashToFarClip far_clip(glh_get_current_projection());
|
||||
|
||||
renderSkyHaze(camHeightLocal);
|
||||
|
||||
|
|
|
|||
|
|
@ -210,13 +210,6 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
|
|||
llassert(msg);
|
||||
if (!msg) return;
|
||||
|
||||
LLHost host = msg->getSender();
|
||||
if (host != gAgent.getRegionHost())
|
||||
{
|
||||
// update is for a different region than the one we're in
|
||||
return;
|
||||
}
|
||||
|
||||
//const S32 SIM_NAME_BUF = 256;
|
||||
U32 region_flags;
|
||||
U8 sim_access;
|
||||
|
|
@ -234,6 +227,8 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
|
|||
S32 redirect_grid_y;
|
||||
LLUUID cache_id;
|
||||
|
||||
LLHost host = msg->getSender();
|
||||
|
||||
msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name);
|
||||
msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id);
|
||||
msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id);
|
||||
|
|
@ -243,6 +238,15 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
|
|||
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor);
|
||||
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor);
|
||||
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height);
|
||||
|
||||
if (host != gAgent.getRegionHost())
|
||||
{
|
||||
// Update is for a different region than the one we're in.
|
||||
// Just check for a waterheight change.
|
||||
LLWorld::getInstance()->waterHeightRegionInfo(sim_name, water_height);
|
||||
return;
|
||||
}
|
||||
|
||||
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit);
|
||||
msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit);
|
||||
msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, price_per_meter);
|
||||
|
|
|
|||
|
|
@ -1555,7 +1555,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
|||
{
|
||||
if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
|
||||
{
|
||||
if (earlyFail(camera, this))
|
||||
// Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
|
||||
if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) ||
|
||||
earlyFail(camera, this))
|
||||
{
|
||||
setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
|
||||
assert_states_valid(this);
|
||||
|
|
@ -1576,7 +1578,18 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
|||
{
|
||||
buildOcclusion();
|
||||
}
|
||||
|
||||
|
||||
// Depth clamp all water to avoid it being culled as a result of being
|
||||
// behind the far clip plane, and in the case of edge water to avoid
|
||||
// it being culled while still visible.
|
||||
bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
|
||||
(mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
|
||||
mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
|
||||
if (use_depth_clamp)
|
||||
{
|
||||
glEnable(GL_DEPTH_CLAMP);
|
||||
}
|
||||
|
||||
glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
|
||||
glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
|
||||
if (camera->getOrigin().isExactlyZero())
|
||||
|
|
@ -1592,6 +1605,11 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
|||
GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
|
||||
}
|
||||
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
|
||||
|
||||
if (use_depth_clamp)
|
||||
{
|
||||
glDisable(GL_DEPTH_CLAMP);
|
||||
}
|
||||
}
|
||||
|
||||
setOcclusionState(LLSpatialGroup::QUERY_PENDING);
|
||||
|
|
@ -2591,9 +2609,10 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
|
|||
gGL.color4f(0.5f,0.5f,0.5f,1.0f);
|
||||
break;
|
||||
case LLViewerObject::LL_VO_PART_GROUP:
|
||||
case LLViewerObject::LL_VO_HUD_PART_GROUP:
|
||||
case LLViewerObject::LL_VO_HUD_PART_GROUP:
|
||||
gGL.color4f(0,0,1,1);
|
||||
break;
|
||||
case LLViewerObject::LL_VO_VOID_WATER:
|
||||
case LLViewerObject::LL_VO_WATER:
|
||||
gGL.color4f(0,0.5f,1,1);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -551,6 +551,13 @@ public:
|
|||
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
|
||||
};
|
||||
|
||||
//spatial partition for hole and edge water (implemented in LLVOWater.cpp)
|
||||
class LLVoidWaterPartition : public LLWaterPartition
|
||||
{
|
||||
public:
|
||||
LLVoidWaterPartition();
|
||||
};
|
||||
|
||||
//spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp)
|
||||
class LLTerrainPartition : public LLSpatialPartition
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1162,8 +1162,13 @@ void LLSurface::setWaterHeight(F32 height)
|
|||
if (!mWaterObjp.isNull())
|
||||
{
|
||||
LLVector3 water_pos_region = mWaterObjp->getPositionRegion();
|
||||
bool changed = water_pos_region.mV[VZ] != height;
|
||||
water_pos_region.mV[VZ] = height;
|
||||
mWaterObjp->setPositionRegion(water_pos_region);
|
||||
if (changed)
|
||||
{
|
||||
LLWorld::getInstance()->updateWaterObjects();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -573,7 +573,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
|
||||
S32 water_clip = 0;
|
||||
if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
|
||||
gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
|
||||
(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||
|
||||
gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
|
||||
{
|
||||
if (LLViewerCamera::getInstance()->cameraUnderWater())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,8 +167,10 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco
|
|||
res = new LLVOSurfacePatch(id, pcode, regionp); break;
|
||||
case LL_VO_SKY:
|
||||
res = new LLVOSky(id, pcode, regionp); break;
|
||||
case LL_VO_VOID_WATER:
|
||||
res = new LLVOVoidWater(id, pcode, regionp); break;
|
||||
case LL_VO_WATER:
|
||||
res = new LLVOWater(id, pcode, regionp); break;
|
||||
res = new LLVOWater(id, pcode, regionp); break;
|
||||
case LL_VO_GROUND:
|
||||
res = new LLVOGround(id, pcode, regionp); break;
|
||||
case LL_VO_PART_GROUP:
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public:
|
|||
|
||||
typedef const child_list_t const_child_list_t;
|
||||
|
||||
LLViewerObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp, BOOL is_global = FALSE);
|
||||
LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE);
|
||||
MEM_TYPE_NEW(LLMemType::MTYPE_OBJECT);
|
||||
|
||||
virtual void markDead(); // Mark this object as dead, and clean up its references
|
||||
|
|
@ -518,14 +518,14 @@ public:
|
|||
{
|
||||
LL_VO_CLOUDS = LL_PCODE_APP | 0x20,
|
||||
LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30,
|
||||
//LL_VO_STARS = LL_PCODE_APP | 0x40,
|
||||
LL_VO_WL_SKY = LL_PCODE_APP | 0x40,
|
||||
LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50,
|
||||
LL_VO_SKY = LL_PCODE_APP | 0x60,
|
||||
LL_VO_WATER = LL_PCODE_APP | 0x70,
|
||||
LL_VO_GROUND = LL_PCODE_APP | 0x80,
|
||||
LL_VO_PART_GROUP = LL_PCODE_APP | 0x90,
|
||||
LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xa0,
|
||||
LL_VO_WL_SKY = LL_PCODE_APP | 0xb0, // should this be moved to 0x40?
|
||||
LL_VO_VOID_WATER = LL_PCODE_APP | 0x70,
|
||||
LL_VO_WATER = LL_PCODE_APP | 0x80,
|
||||
LL_VO_GROUND = LL_PCODE_APP | 0x90,
|
||||
LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0,
|
||||
LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0,
|
||||
LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0,
|
||||
} EVOType;
|
||||
|
||||
|
|
@ -717,8 +717,8 @@ public:
|
|||
class LLAlphaObject : public LLViewerObject
|
||||
{
|
||||
public:
|
||||
LLAlphaObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp)
|
||||
: LLViewerObject(id,type,regionp)
|
||||
LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
|
||||
: LLViewerObject(id,pcode,regionp)
|
||||
{ mDepth = 0.f; }
|
||||
|
||||
virtual F32 getPartSize(S32 idx);
|
||||
|
|
@ -735,8 +735,8 @@ public:
|
|||
class LLStaticViewerObject : public LLViewerObject
|
||||
{
|
||||
public:
|
||||
LLStaticViewerObject(const LLUUID& id, const LLPCode type, LLViewerRegion* regionp, BOOL is_global = FALSE)
|
||||
: LLViewerObject(id,type,regionp, is_global)
|
||||
LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE)
|
||||
: LLViewerObject(id,pcode,regionp, is_global)
|
||||
{ }
|
||||
|
||||
virtual void updateDrawable(BOOL force_damped);
|
||||
|
|
|
|||
|
|
@ -261,6 +261,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
|
|||
//MUST MATCH declaration of eObjectPartitions
|
||||
mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
|
||||
mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
|
||||
mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER
|
||||
mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
|
||||
mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
|
||||
mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ public:
|
|||
{
|
||||
PARTITION_HUD=0,
|
||||
PARTITION_TERRAIN,
|
||||
PARTITION_VOIDWATER,
|
||||
PARTITION_WATER,
|
||||
PARTITION_TREE,
|
||||
PARTITION_PARTICLE,
|
||||
|
|
|
|||
|
|
@ -335,8 +335,8 @@ void LLViewerShaderMgr::setShaders()
|
|||
}
|
||||
else
|
||||
{
|
||||
LLPipeline::sRenderGlow =
|
||||
LLPipeline::sWaterReflections = FALSE;
|
||||
LLPipeline::sRenderGlow = FALSE;
|
||||
LLPipeline::sWaterReflections = FALSE;
|
||||
}
|
||||
|
||||
//hack to reset buffers that change behavior with shaders
|
||||
|
|
|
|||
|
|
@ -1406,6 +1406,11 @@ LLViewerWindow::LLViewerWindow(
|
|||
gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
|
||||
}
|
||||
|
||||
if (!gGLManager.mHasDepthClamp)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
|
||||
}
|
||||
|
||||
// If we crashed while initializng GL stuff last time, disable certain features
|
||||
if (gSavedSettings.getBOOL("RenderInitError"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public:
|
|||
//============================================================================
|
||||
|
||||
LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
|
||||
: LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp),
|
||||
: LLStaticViewerObject(id, pcode, regionp),
|
||||
mDirtiedPatch(FALSE),
|
||||
mPool(NULL),
|
||||
mBaseComp(0),
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ const F32 WAVE_STEP_INV = (1. / WAVE_STEP);
|
|||
|
||||
|
||||
LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
|
||||
: LLStaticViewerObject(id, LL_VO_WATER, regionp)
|
||||
: LLStaticViewerObject(id, pcode, regionp),
|
||||
mRenderType(LLPipeline::RENDER_TYPE_WATER)
|
||||
{
|
||||
// Terrain must draw during selection passes so it can block objects behind it.
|
||||
mbCanSelect = FALSE;
|
||||
|
|
@ -114,7 +115,7 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
|
|||
{
|
||||
pipeline->allocDrawable(this);
|
||||
mDrawable->setLit(FALSE);
|
||||
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_WATER);
|
||||
mDrawable->setRenderType(mRenderType);
|
||||
|
||||
LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
|
||||
|
||||
|
|
@ -268,6 +269,11 @@ U32 LLVOWater::getPartitionType() const
|
|||
return LLViewerRegion::PARTITION_WATER;
|
||||
}
|
||||
|
||||
U32 LLVOVoidWater::getPartitionType() const
|
||||
{
|
||||
return LLViewerRegion::PARTITION_VOIDWATER;
|
||||
}
|
||||
|
||||
LLWaterPartition::LLWaterPartition()
|
||||
: LLSpatialPartition(0, FALSE, 0)
|
||||
{
|
||||
|
|
@ -275,3 +281,9 @@ LLWaterPartition::LLWaterPartition()
|
|||
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
|
||||
mPartitionType = LLViewerRegion::PARTITION_WATER;
|
||||
}
|
||||
|
||||
LLVoidWaterPartition::LLVoidWaterPartition()
|
||||
{
|
||||
mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER;
|
||||
mPartitionType = LLViewerRegion::PARTITION_VOIDWATER;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "llviewerobject.h"
|
||||
#include "llviewertexture.h"
|
||||
#include "pipeline.h"
|
||||
#include "v2math.h"
|
||||
|
||||
const U32 N_RES = 16; //32 // number of subdivisions of wave tile
|
||||
|
|
@ -77,6 +78,19 @@ public:
|
|||
protected:
|
||||
BOOL mUseTexture;
|
||||
BOOL mIsEdgePatch;
|
||||
S32 mRenderType;
|
||||
};
|
||||
|
||||
class LLVOVoidWater : public LLVOWater
|
||||
{
|
||||
public:
|
||||
LLVOVoidWater(LLUUID const& id, LLPCode pcode, LLViewerRegion* regionp) : LLVOWater(id, pcode, regionp)
|
||||
{
|
||||
mRenderType = LLPipeline::RENDER_TYPE_VOIDWATER;
|
||||
}
|
||||
|
||||
/*virtual*/ U32 getPartitionType() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_VOSURFACEPATCH_H
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@
|
|||
#include "pipeline.h"
|
||||
#include "llappviewer.h" // for do_disconnect()
|
||||
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
|
||||
//
|
||||
// Globals
|
||||
//
|
||||
|
|
@ -834,10 +839,69 @@ F32 LLWorld::getLandFarClip() const
|
|||
|
||||
void LLWorld::setLandFarClip(const F32 far_clip)
|
||||
{
|
||||
static S32 const rwidth = (S32)REGION_WIDTH_U32;
|
||||
S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
|
||||
S32 const n2 = (llceil(far_clip) - 1) / rwidth;
|
||||
bool need_water_objects_update = n1 != n2;
|
||||
|
||||
mLandFarClip = far_clip;
|
||||
|
||||
if (need_water_objects_update)
|
||||
{
|
||||
updateWaterObjects();
|
||||
}
|
||||
}
|
||||
|
||||
// Some region that we're connected to, but not the one we're in, gave us
|
||||
// a (possibly) new water height. Update it in our local copy.
|
||||
void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
|
||||
{
|
||||
for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->getName() == sim_name)
|
||||
{
|
||||
(*iter)->setWaterHeight(water_height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There are three types of water objects:
|
||||
// Region water objects: the water in a region.
|
||||
// Hole water objects: water in the void but within current draw distance.
|
||||
// Edge water objects: the water outside the draw distance, up till the horizon.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// -----------------------horizon-------------------------
|
||||
// | | | |
|
||||
// | Edge Water | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | rwidth | |
|
||||
// | | <-----> | |
|
||||
// -------------------------------------------------------
|
||||
// | |Hole |other| | |
|
||||
// | |Water|reg. | | |
|
||||
// | |-----------------| |
|
||||
// | |other|cur. |<--> | |
|
||||
// | |reg. | reg.| \__|_ draw distance |
|
||||
// | |-----------------| |
|
||||
// | | | |<--->| |
|
||||
// | | | | \__|_ range |
|
||||
// -------------------------------------------------------
|
||||
// | |<----width------>|<--horizon ext.->|
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// -------------------------------------------------------
|
||||
//
|
||||
void LLWorld::updateWaterObjects()
|
||||
{
|
||||
if (!gAgent.getRegion())
|
||||
|
|
@ -850,128 +914,265 @@ void LLWorld::updateWaterObjects()
|
|||
return;
|
||||
}
|
||||
|
||||
// First, determine the min and max "box" of water objects
|
||||
S32 min_x = 0;
|
||||
S32 min_y = 0;
|
||||
S32 max_x = 0;
|
||||
S32 max_y = 0;
|
||||
// Region width in meters.
|
||||
S32 const rwidth = (S32)REGION_WIDTH_U32;
|
||||
|
||||
// The distance we might see into the void
|
||||
// when standing on the edge of a region, in meters.
|
||||
S32 const draw_distance = llceil(mLandFarClip);
|
||||
|
||||
// We can only have "holes" in the water (where there no region) if we
|
||||
// can have existing regions around it. Taking into account that this
|
||||
// code is only executed when we enter a region, and not when we walk
|
||||
// around in it, we (only) need to take into account regions that fall
|
||||
// within the draw_distance.
|
||||
//
|
||||
// Set 'range' to draw_distance, rounded up to the nearest multiple of rwidth.
|
||||
S32 const nsims = (draw_distance + rwidth - 1) / rwidth;
|
||||
S32 const range = nsims * rwidth;
|
||||
|
||||
// Get South-West corner of current region.
|
||||
LLViewerRegion const* regionp = gAgent.getRegion();
|
||||
U32 region_x, region_y;
|
||||
|
||||
S32 rwidth = 256;
|
||||
|
||||
// We only want to fill in water for stuff that's near us, say, within 256 or 512m
|
||||
S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
|
||||
|
||||
LLViewerRegion* regionp = gAgent.getRegion();
|
||||
from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y);
|
||||
|
||||
min_x = (S32)region_x - range;
|
||||
min_y = (S32)region_y - range;
|
||||
max_x = (S32)region_x + range;
|
||||
max_y = (S32)region_y + range;
|
||||
// The min. and max. coordinates of the South-West corners of the Hole water objects.
|
||||
S32 const min_x = (S32)region_x - range;
|
||||
S32 const min_y = (S32)region_y - range;
|
||||
S32 const max_x = (S32)region_x + range;
|
||||
S32 const max_y = (S32)region_y + range;
|
||||
|
||||
F32 height = 0.f;
|
||||
|
||||
for (region_list_t::iterator iter = mRegionList.begin();
|
||||
iter != mRegionList.end(); ++iter)
|
||||
// Attempt to determine a sensible water height for all the
|
||||
// Hole Water objects.
|
||||
//
|
||||
// It make little sense to try to guess what the best water
|
||||
// height should be when that isn't completely obvious: if it's
|
||||
// impossible to satisfy every region's water height without
|
||||
// getting a jump in the water height.
|
||||
//
|
||||
// In order to keep the reasoning simple, we assume something
|
||||
// logical as a group of connected regions, where the coastline
|
||||
// is at the outer edge. Anything more complex that would "break"
|
||||
// under such an assumption would probably break anyway (would
|
||||
// depend on terrain editing and existing mega prims, say, if
|
||||
// anything would make sense at all).
|
||||
//
|
||||
// So, what we do is find all connected regions within the
|
||||
// draw distance that border void, and then pick the lowest
|
||||
// water height of those (coast) regions.
|
||||
S32 const n = 2 * nsims + 1;
|
||||
S32 const origin = nsims + nsims * n;
|
||||
std::vector<F32> water_heights(n * n);
|
||||
std::vector<U8> checked(n * n, 0); // index = nx + ny * n + origin;
|
||||
U8 const region_bit = 1;
|
||||
U8 const hole_bit = 2;
|
||||
U8 const bordering_hole_bit = 4;
|
||||
U8 const bordering_edge_bit = 8;
|
||||
// Use the legacy waterheight for the Edge water in the case
|
||||
// that we don't find any Hole water at all.
|
||||
F32 water_height = DEFAULT_WATER_HEIGHT;
|
||||
int max_count = 0;
|
||||
LL_DEBUGS("WaterHeight") << "Current region: " << regionp->getName() << "; water height: " << regionp->getWaterHeight() << " m." << LL_ENDL;
|
||||
std::map<S32, int> water_height_counts;
|
||||
typedef std::queue<std::pair<S32, S32>, std::deque<std::pair<S32, S32> > > nxny_pairs_type;
|
||||
nxny_pairs_type nxny_pairs;
|
||||
nxny_pairs.push(nxny_pairs_type::value_type(0, 0));
|
||||
water_heights[origin] = regionp->getWaterHeight();
|
||||
checked[origin] = region_bit;
|
||||
// For debugging purposes.
|
||||
int number_of_connected_regions = 1;
|
||||
int uninitialized_regions = 0;
|
||||
int bordering_hole = 0;
|
||||
int bordering_edge = 0;
|
||||
while(!nxny_pairs.empty())
|
||||
{
|
||||
S32 const nx = nxny_pairs.front().first;
|
||||
S32 const ny = nxny_pairs.front().second;
|
||||
LL_DEBUGS("WaterHeight") << "nx,ny = " << nx << "," << ny << LL_ENDL;
|
||||
S32 const index = nx + ny * n + origin;
|
||||
nxny_pairs.pop();
|
||||
for (S32 dir = 0; dir < 4; ++dir)
|
||||
{
|
||||
S32 const cnx = nx + gDirAxes[dir][0];
|
||||
S32 const cny = ny + gDirAxes[dir][1];
|
||||
LL_DEBUGS("WaterHeight") << "dir = " << dir << "; cnx,cny = " << cnx << "," << cny << LL_ENDL;
|
||||
S32 const cindex = cnx + cny * n + origin;
|
||||
bool is_hole = false;
|
||||
bool is_edge = false;
|
||||
LLViewerRegion* new_region_found = NULL;
|
||||
if (cnx < -nsims || cnx > nsims ||
|
||||
cny < -nsims || cny > nsims)
|
||||
{
|
||||
LL_DEBUGS("WaterHeight") << " Edge Water!" << LL_ENDL;
|
||||
// Bumped into Edge water object.
|
||||
is_edge = true;
|
||||
}
|
||||
else if (checked[cindex])
|
||||
{
|
||||
LL_DEBUGS("WaterHeight") << " Already checked before!" << LL_ENDL;
|
||||
// Already checked.
|
||||
is_hole = (checked[cindex] & hole_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 x = (S32)region_x + cnx * rwidth;
|
||||
S32 y = (S32)region_y + cny * rwidth;
|
||||
U64 region_handle = to_region_handle(x, y);
|
||||
new_region_found = getRegionFromHandle(region_handle);
|
||||
is_hole = !new_region_found;
|
||||
checked[cindex] = is_hole ? hole_bit : region_bit;
|
||||
}
|
||||
if (is_hole)
|
||||
{
|
||||
// This was a region that borders at least one 'hole'.
|
||||
// Count the found coastline.
|
||||
F32 new_water_height = water_heights[index];
|
||||
LL_DEBUGS("WaterHeight") << " This is void; counting coastline with water height of " << new_water_height << LL_ENDL;
|
||||
S32 new_water_height_cm = llround(new_water_height * 100);
|
||||
int count = (water_height_counts[new_water_height_cm] += 1);
|
||||
// Just use the lowest water height: this is mainly about the horizon water,
|
||||
// and whatever we do, we don't want it to be possible to look under the water
|
||||
// when looking in the distance: it is better to make a step downwards in water
|
||||
// height when going away from the avie than a step upwards. However, since
|
||||
// everyone is used to DEFAULT_WATER_HEIGHT, don't allow a single region
|
||||
// to drag the water level below DEFAULT_WATER_HEIGHT on it's own.
|
||||
if (bordering_hole == 0 || // First time we get here.
|
||||
(new_water_height >= DEFAULT_WATER_HEIGHT &&
|
||||
new_water_height < water_height) ||
|
||||
(new_water_height < DEFAULT_WATER_HEIGHT &&
|
||||
count > max_count)
|
||||
)
|
||||
{
|
||||
water_height = new_water_height;
|
||||
}
|
||||
if (count > max_count)
|
||||
{
|
||||
max_count = count;
|
||||
}
|
||||
if (!(checked[index] & bordering_hole_bit))
|
||||
{
|
||||
checked[index] |= bordering_hole_bit;
|
||||
++bordering_hole;
|
||||
}
|
||||
}
|
||||
else if (is_edge && !(checked[index] & bordering_edge_bit))
|
||||
{
|
||||
checked[index] |= bordering_edge_bit;
|
||||
++bordering_edge;
|
||||
}
|
||||
if (!new_region_found)
|
||||
{
|
||||
// Dead end, there is no region here.
|
||||
continue;
|
||||
}
|
||||
// Found a new connected region.
|
||||
++number_of_connected_regions;
|
||||
if (new_region_found->getName().empty())
|
||||
{
|
||||
// Uninitialized LLViewerRegion, don't use it's water height.
|
||||
LL_DEBUGS("WaterHeight") << " Uninitialized region." << LL_ENDL;
|
||||
++uninitialized_regions;
|
||||
continue;
|
||||
}
|
||||
nxny_pairs.push(nxny_pairs_type::value_type(cnx, cny));
|
||||
water_heights[cindex] = new_region_found->getWaterHeight();
|
||||
LL_DEBUGS("WaterHeight") << " Found a new region (name: " << new_region_found->getName() << "; water height: " << water_heights[cindex] << " m)!" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
llinfos << "Number of connected regions: " << number_of_connected_regions << " (" << uninitialized_regions <<
|
||||
" uninitialized); number of regions bordering Hole water: " << bordering_hole <<
|
||||
"; number of regions bordering Edge water: " << bordering_edge << llendl;
|
||||
llinfos << "Coastline count (height, count): ";
|
||||
bool first = true;
|
||||
for (std::map<S32, int>::iterator iter = water_height_counts.begin(); iter != water_height_counts.end(); ++iter)
|
||||
{
|
||||
if (!first) llcont << ", ";
|
||||
llcont << "(" << (iter->first / 100.f) << ", " << iter->second << ")";
|
||||
first = false;
|
||||
}
|
||||
llcont << llendl;
|
||||
llinfos << "Water height used for Hole and Edge water objects: " << water_height << llendl;
|
||||
|
||||
// Update all Region water objects.
|
||||
for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
|
||||
{
|
||||
LLViewerRegion* regionp = *iter;
|
||||
LLVOWater* waterp = regionp->getLand().getWaterObj();
|
||||
height += regionp->getWaterHeight();
|
||||
if (waterp)
|
||||
{
|
||||
gObjectList.updateActive(waterp);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up all existing Hole water objects.
|
||||
for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
|
||||
iter != mHoleWaterObjects.end(); ++ iter)
|
||||
iter != mHoleWaterObjects.end(); ++iter)
|
||||
{
|
||||
LLVOWater* waterp = *iter;
|
||||
gObjectList.killObject(waterp);
|
||||
}
|
||||
mHoleWaterObjects.clear();
|
||||
|
||||
// Now, get a list of the holes
|
||||
S32 x, y;
|
||||
for (x = min_x; x <= max_x; x += rwidth)
|
||||
// Let the Edge and Hole water boxes be 1024 meter high so that they
|
||||
// are never too small to be drawn (A LL_VO_*_WATER box has water
|
||||
// rendered on it's bottom surface only), and put their bottom at
|
||||
// the current regions water height.
|
||||
F32 const box_height = 1024;
|
||||
F32 const water_center_z = water_height + box_height / 2;
|
||||
|
||||
// Create new Hole water objects within 'range' where there is no region.
|
||||
for (S32 x = min_x; x <= max_x; x += rwidth)
|
||||
{
|
||||
for (y = min_y; y <= max_y; y += rwidth)
|
||||
for (S32 y = min_y; y <= max_y; y += rwidth)
|
||||
{
|
||||
U64 region_handle = to_region_handle(x, y);
|
||||
if (!getRegionFromHandle(region_handle))
|
||||
{
|
||||
LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
|
||||
LLVOWater* waterp = (LLVOWater*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
|
||||
waterp->setUseTexture(FALSE);
|
||||
waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
|
||||
y + rwidth/2,
|
||||
256.f+DEFAULT_WATER_HEIGHT));
|
||||
waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
|
||||
waterp->setPositionGlobal(LLVector3d(x + rwidth / 2, y + rwidth / 2, water_center_z));
|
||||
waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, box_height));
|
||||
gPipeline.createObject(waterp);
|
||||
mHoleWaterObjects.push_back(waterp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update edge water objects
|
||||
S32 wx, wy;
|
||||
S32 center_x, center_y;
|
||||
wx = (max_x - min_x) + rwidth;
|
||||
wy = (max_y - min_y) + rwidth;
|
||||
center_x = min_x + (wx >> 1);
|
||||
center_y = min_y + (wy >> 1);
|
||||
|
||||
S32 add_boundary[4] = {
|
||||
512 - (max_x - region_x),
|
||||
512 - (max_y - region_y),
|
||||
512 - (region_x - min_x),
|
||||
512 - (region_y - min_y) };
|
||||
// Center of the region.
|
||||
S32 const center_x = region_x + rwidth / 2;
|
||||
S32 const center_y = region_y + rwidth / 2;
|
||||
// Width of the area with Hole water objects.
|
||||
S32 const width = rwidth + 2 * range;
|
||||
S32 const horizon_extend = 2048 + 512 - range; // Legacy value.
|
||||
// The overlap is needed to get rid of sky pixels being visible between the
|
||||
// Edge and Hole water object at greater distances (due to floating point
|
||||
// round off errors).
|
||||
S32 const edge_hole_overlap = 1; // Twice the actual overlap.
|
||||
|
||||
S32 dir;
|
||||
for (dir = 0; dir < 8; dir++)
|
||||
for (S32 dir = 0; dir < 8; ++dir)
|
||||
{
|
||||
S32 dim[2] = { 0 };
|
||||
switch (gDirAxes[dir][0])
|
||||
{
|
||||
case -1: dim[0] = add_boundary[2]; break;
|
||||
case 0: dim[0] = wx; break;
|
||||
default: dim[0] = add_boundary[0]; break;
|
||||
}
|
||||
switch (gDirAxes[dir][1])
|
||||
{
|
||||
case -1: dim[1] = add_boundary[3]; break;
|
||||
case 0: dim[1] = wy; break;
|
||||
default: dim[1] = add_boundary[1]; break;
|
||||
}
|
||||
// Size of the Edge water objects.
|
||||
S32 const dim_x = (gDirAxes[dir][0] == 0) ? width : (horizon_extend + edge_hole_overlap);
|
||||
S32 const dim_y = (gDirAxes[dir][1] == 0) ? width : (horizon_extend + edge_hole_overlap);
|
||||
// And their position.
|
||||
S32 const water_center_x = center_x + (width + horizon_extend) / 2 * gDirAxes[dir][0];
|
||||
S32 const water_center_y = center_y + (width + horizon_extend) / 2 * gDirAxes[dir][1];
|
||||
|
||||
// Resize and reshape the water objects
|
||||
const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
|
||||
const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
|
||||
|
||||
LLVOWater* waterp = mEdgeWaterObjects[dir];
|
||||
if (!waterp || waterp->isDead())
|
||||
{
|
||||
// The edge water objects can be dead because they're attached to the region that the
|
||||
// agent was in when they were originally created.
|
||||
mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER,
|
||||
gAgent.getRegion());
|
||||
mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, gAgent.getRegion());
|
||||
waterp = mEdgeWaterObjects[dir];
|
||||
waterp->setUseTexture(FALSE);
|
||||
waterp->setIsEdgePatch(TRUE);
|
||||
waterp->setIsEdgePatch(TRUE); // Mark that this is edge water and not hole water.
|
||||
gPipeline.createObject(waterp);
|
||||
}
|
||||
|
||||
waterp->setRegion(gAgent.getRegion());
|
||||
LLVector3d water_pos(water_center_x, water_center_y,
|
||||
DEFAULT_WATER_HEIGHT+256.f);
|
||||
LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
|
||||
|
||||
//stretch out to horizon
|
||||
water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
|
||||
water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
|
||||
|
||||
water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
|
||||
water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
|
||||
LLVector3d water_pos(water_center_x, water_center_y, water_center_z);
|
||||
LLVector3 water_scale((F32) dim_x, (F32) dim_y, box_height);
|
||||
|
||||
waterp->setPositionGlobal(water_pos);
|
||||
waterp->setScale(water_scale);
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ public:
|
|||
|
||||
LLViewerTexture *getDefaultWaterTexture();
|
||||
void updateWaterObjects();
|
||||
void waterHeightRegionInfo(std::string const& sim_name, F32 water_height);
|
||||
void shiftRegions(const LLVector3& offset);
|
||||
|
||||
void setSpaceTimeUSec(const U64 space_time_usec);
|
||||
|
|
|
|||
|
|
@ -628,14 +628,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
|
|||
//static
|
||||
void LLPipeline::updateRenderDeferred()
|
||||
{
|
||||
BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") &&
|
||||
LLRenderTarget::sUseFBO &&
|
||||
LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
|
||||
gSavedSettings.getBOOL("VertexShaderEnable") &&
|
||||
gSavedSettings.getBOOL("RenderAvatarVP") &&
|
||||
(gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
|
||||
!gUseWireframe;
|
||||
|
||||
BOOL deferred = ((gSavedSettings.getBOOL("RenderDeferred") &&
|
||||
LLRenderTarget::sUseFBO &&
|
||||
LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
|
||||
gSavedSettings.getBOOL("VertexShaderEnable") &&
|
||||
gSavedSettings.getBOOL("RenderAvatarVP") &&
|
||||
gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE) &&
|
||||
!gUseWireframe;
|
||||
|
||||
sRenderDeferred = deferred;
|
||||
}
|
||||
|
||||
|
|
@ -1632,20 +1632,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
|
|||
|
||||
camera.disableUserClipPlane();
|
||||
|
||||
if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull())
|
||||
if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) &&
|
||||
gSky.mVOSkyp.notNull() &&
|
||||
gSky.mVOSkyp->mDrawable.notNull())
|
||||
{
|
||||
// Hack for sky - always visible.
|
||||
if (hasRenderType(LLPipeline::RENDER_TYPE_SKY))
|
||||
{
|
||||
gSky.mVOSkyp->mDrawable->setVisible(camera);
|
||||
sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
|
||||
gSky.updateCull();
|
||||
stop_glerror();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "No sky drawable!" << llendl;
|
||||
gSky.mVOSkyp->mDrawable->setVisible(camera);
|
||||
sCull->pushDrawable(gSky.mVOSkyp->mDrawable);
|
||||
gSky.updateCull();
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) &&
|
||||
|
|
@ -2214,6 +2208,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
|
|||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_TREE,
|
||||
LLPipeline::RENDER_TYPE_SKY,
|
||||
LLPipeline::RENDER_TYPE_VOIDWATER,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::END_RENDER_TYPES))
|
||||
{
|
||||
|
|
@ -5005,6 +5000,10 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light)
|
|||
void LLPipeline::toggleRenderType(U32 type)
|
||||
{
|
||||
gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type];
|
||||
if (type == LLPipeline::RENDER_TYPE_WATER)
|
||||
{
|
||||
gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER];
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -7331,6 +7330,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
|
|||
gPipeline.pushRenderTypeMask();
|
||||
|
||||
clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_VOIDWATER,
|
||||
LLPipeline::RENDER_TYPE_GROUND,
|
||||
LLPipeline::RENDER_TYPE_SKY,
|
||||
LLPipeline::RENDER_TYPE_CLOUDS,
|
||||
|
|
@ -7383,6 +7383,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
|
|||
{
|
||||
camera.setFar(camera_in.getFar());
|
||||
clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_VOIDWATER,
|
||||
LLPipeline::RENDER_TYPE_GROUND,
|
||||
END_RENDER_TYPES);
|
||||
stop_glerror();
|
||||
|
|
@ -7899,6 +7900,7 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector<L
|
|||
LLPipeline::RENDER_TYPE_TREE,
|
||||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_VOIDWATER,
|
||||
LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
|
||||
LLPipeline::RENDER_TYPE_AVATAR,
|
||||
LLPipeline::RENDER_TYPE_PASS_SIMPLE,
|
||||
|
|
@ -8082,6 +8084,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
|
|||
LLPipeline::RENDER_TYPE_TREE,
|
||||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_VOIDWATER,
|
||||
LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW,
|
||||
LLPipeline::RENDER_TYPE_PASS_SIMPLE,
|
||||
LLPipeline::RENDER_TYPE_PASS_BUMP,
|
||||
|
|
|
|||
|
|
@ -358,6 +358,7 @@ public:
|
|||
RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR,
|
||||
RENDER_TYPE_TREE = LLDrawPool::POOL_TREE,
|
||||
RENDER_TYPE_INVISIBLE = LLDrawPool::POOL_INVISIBLE,
|
||||
RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER,
|
||||
RENDER_TYPE_WATER = LLDrawPool::POOL_WATER,
|
||||
RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
|
||||
RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
|
||||
|
|
|
|||
Loading…
Reference in New Issue