Merge with latest lindenlab/viewer-development

master
simon@lindenlab.com 2011-06-21 09:36:31 -07:00
commit d11cabc489
481 changed files with 10932 additions and 3153 deletions

View File

@ -131,3 +131,4 @@ dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
0c4d0c24278074f219e5a32e72b449e78301d11b 2.7.1-beta1
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start

View File

@ -102,6 +102,16 @@ mesh-development.build_debug_release_separately = true
mesh-development.build_CYGWIN_Debug = false
mesh-development.build_viewer_update_version_manager = false
# ========================================
# mesh-asset-deprecation
# ========================================
mesh-asset-deprecation.viewer_channel = "Project Viewer - Mesh Asset Deprecation"
mesh-asset-deprecation.login_channel = "Project Viewer - Mesh Asset Deprecation"
mesh-asset-deprecation.viewer_grid = aditi
mesh-asset-deprecation.build_debug_release_separately = true
mesh-asset-deprecation.build_CYGWIN_Debug = false
mesh-asset-deprecation.build_viewer_update_version_manager = false
# ========================================
# viewer-mesh
# ========================================

View File

@ -18,9 +18,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>930bdd987a321eda1838caba8cd6098f</string>
<string>b2fe1c860613a68e74d4384be418ffee</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Darwin/installer/glod-1.0pre4-darwin-20110519.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Darwin/installer/glod-1.0pre4-darwin-20110610.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -30,9 +30,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>fb33b6cac2e6b98f93c5efa2af2e5a00</string>
<string>c0c64dae149d0892343e2ff300fd06b9</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/Linux/installer/glod-1.0pre4-linux-20110519.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/Linux/installer/glod-1.0pre4-linux-20110611.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -42,9 +42,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>388cf0e292f756b4bb37696622f0bbc5</string>
<string>842208365f5b108dac4c7c733b99da9c</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/230348/arch/CYGWIN/installer/glod-1.0pre4-windows-20110519.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-glod/rev/232684/arch/CYGWIN/installer/glod-1.0pre4-windows-20110610.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1290,9 +1290,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>c81bacf922bb3b540d92b660364c48ce</string>
<string>9bf7a96c1d2fadb180fda91740c945c6</string>
<key>url</key>
<string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ndofdev-linux-0.2-20101013.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-libndofdev-linux/rev/233137/arch/Linux/installer/libndofdev-0.3-linux-20110617.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
@ -1524,7 +1524,7 @@
<key>hash</key>
<string>bb0abe962b3b8208ed2dab0424aab33d</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-pcre/rev/228822/arch/Linux/installer/pcre-7.6-linux-20110504.tar.bz2</string>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-pcre/rev/228822/arch/Linux/installer/pcre-7.6-linux-20110504.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>

View File

@ -29,30 +29,38 @@
struct ParcelQuota
{
ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
F32 totalRenderCost, F32 totalPhysicsCost, F32 totalNetworkCost, F32 totalSimulationCost)
ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost,
F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
F32 parcelCapacity )
: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost )
, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
, mTotalRenderCost( totalRenderCost ), mTotalPhysicsCost( totalPhysicsCost )
, mTotalNetworkCost( totalNetworkCost ), mTotalSimulationCost( totalSimulationCost )
, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost )
, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost )
, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
, mParcelCapacity( parcelCapacity )
{
}
ParcelQuota(){}
F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
F32 mTotalRenderCost, mTotalPhysicsCost, mTotalNetworkCost, mTotalSimulationCost;
F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost;
F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
F32 mParcelCapacity;
};
struct SelectionQuota
{
SelectionQuota( S32 localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
: mLocalId( localId)
, mRenderCost( renderCost )
, mPhysicsCost( physicsCost )
@ -63,7 +71,7 @@ struct SelectionQuota
SelectionQuota() {}
F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;
S32 mLocalId;
LLUUID mLocalId;
};
#endif

View File

@ -2036,7 +2036,9 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
llerrs << "WTF?" << llendl;
free(output);
llwarns << "Failed to compress LLSD block." << llendl;
return std::string();
}
have = CHUNK-strm.avail_out;

View File

@ -737,7 +737,7 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats,
}
}
else
{ // WTF? Shouldn't have a NULL pointer in the map.
{ // Shouldn't have a NULL pointer in the map.
llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl;
}
}

View File

@ -29,7 +29,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 7;
const S32 LL_VERSION_PATCH = 4;
const S32 LL_VERSION_PATCH = 5;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";

View File

@ -35,12 +35,14 @@
#define OCT_ERRS LL_WARNS("OctreeErrors")
#define LL_OCTREE_PARANOIA_CHECK 0
extern U32 gOctreeMaxCapacity;
/*#define LL_OCTREE_PARANOIA_CHECK 0
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
#else
#define LL_OCTREE_MAX_CAPACITY 128
#endif
#endif*/
template <class T> class LLOctreeNode;
@ -74,6 +76,7 @@ template <class T>
class LLOctreeNode : public LLTreeNode<T>
{
public:
typedef LLOctreeTraveler<T> oct_traveler;
typedef LLTreeTraveler<T> tree_traveler;
typedef typename std::set<LLPointer<T> > element_list;
@ -294,8 +297,8 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
if ((getElementCount() < LL_OCTREE_MAX_CAPACITY && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
#if LL_OCTREE_PARANOIA_CHECK
//if this is a redundant insertion, error out (should never happen)

View File

@ -100,7 +100,7 @@ void assert_aligned(void* ptr, uintptr_t alignment)
uintptr_t t = (uintptr_t) ptr;
if (t%alignment != 0)
{
llerrs << "WTF?" << llendl;
llerrs << "Alignment check failed." << llendl;
}
#endif
}
@ -361,7 +361,7 @@ public:
}
else
{
llerrs << "WTF? Empty leaf" << llendl;
llerrs << "Empty leaf" << llendl;
}
for (S32 i = 0; i < branch->getChildCount(); ++i)
@ -416,6 +416,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO
return face;
}
//static
S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split)
{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
S32 np = 0;
// Generate an n-sided "circular" path.
// 0 is (1,0), and we go counter-clockwise along a circular path from there.
F32 t, t_step, t_first, t_fraction;
F32 begin = params.getBegin();
F32 end = params.getEnd();
t_step = 1.0f / sides;
t_first = floor(begin * sides) / (F32)sides;
// pt1 is the first point on the fractional face.
// Starting t and ang values for the first face
t = t_first;
// Increment to the next point.
// pt2 is the end point on the fractional face
t += t_step;
t_fraction = (begin - t_first)*sides;
// Only use if it's not almost exactly on an edge.
if (t_fraction < 0.9999f)
{
np++;
}
// There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02
while (t < end)
{
// Iterate through all the integer steps of t.
np++;
t += t_step;
}
t_fraction = (end - (t - t_step))*sides;
// Find the fraction that we need to add to the end point.
t_fraction = (end - (t - t_step))*sides;
if (t_fraction > 0.0001f)
{
np++;
}
// If we're sliced, the profile is open.
if ((end - begin)*ang_scale < 0.99f)
{
if (params.getHollow() <= 0)
{
// put center point if not hollow.
np++;
}
}
return np;
}
// What is the bevel parameter used for? - DJS 04/05/02
// Bevel parameter is currently unused but presumedly would support
// filleted and chamfered corners
@ -672,6 +736,117 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3
return face;
}
//static
S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
if (detail < MIN_LOD)
{
detail = MIN_LOD;
}
// Generate the face data
F32 hollow = params.getHollow();
S32 np = 0;
switch (params.getCurveType() & LL_PCODE_PROFILE_MASK)
{
case LL_PCODE_PROFILE_SQUARE:
{
np = getNumNGonPoints(params, 4,-0.375, 0, 1, split);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_ISOTRI:
case LL_PCODE_PROFILE_RIGHTTRI:
case LL_PCODE_PROFILE_EQUALTRI:
{
np = getNumNGonPoints(params, 3,0, 0, 1, split);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_CIRCLE:
{
// If this has a square hollow, we should adjust the
// number of faces a bit so that the geometry lines up.
U8 hole_type=0;
F32 circle_detail = MIN_DETAIL_FACES * detail;
if (hollow)
{
hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
if (hole_type == LL_PCODE_HOLE_SQUARE)
{
// Snap to the next multiple of four sides,
// so that corners line up.
circle_detail = llceil(circle_detail / 4.0f) * 4.0f;
}
}
S32 sides = (S32)circle_detail;
if (is_sculpted)
sides = sculpt_size;
np = getNumNGonPoints(params, sides);
if (hollow)
{
np *= 2;
}
}
break;
case LL_PCODE_PROFILE_CIRCLE_HALF:
{
// If this has a square hollow, we should adjust the
// number of faces a bit so that the geometry lines up.
U8 hole_type=0;
// Number of faces is cut in half because it's only a half-circle.
F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f;
if (hollow)
{
hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK;
if (hole_type == LL_PCODE_HOLE_SQUARE)
{
// Snap to the next multiple of four sides (div 2),
// so that corners line up.
circle_detail = llceil(circle_detail / 2.0f) * 2.0f;
}
}
np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f);
if (hollow)
{
np *= 2;
}
// Special case for openness of sphere
if ((params.getEnd() - params.getBegin()) < 1.f)
{
}
else if (!hollow)
{
np++;
}
}
break;
default:
break;
};
return np;
}
BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split,
@ -1133,6 +1308,32 @@ LLPath::~LLPath()
{
}
S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added
S32 ret = 0;
F32 step= 1.0f / sides;
F32 t = params.getBegin();
ret = 1;
t+=step;
// Snap to a quantized parameter, so that cut does not
// affect most sample points.
t = ((S32)(t * sides)) / (F32)sides;
// Run through the non-cut dependent points.
while (t < params.getEnd())
{
ret++;
t+=step;
}
ret++;
return ret;
}
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
@ -1310,6 +1511,56 @@ const LLVector2 LLPathParams::getEndScale() const
return end_scale;
}
S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail)
{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points
LLMemType m1(LLMemType::MTYPE_VOLUME);
if (detail < MIN_LOD)
{
detail = MIN_LOD;
}
S32 np = 2; // hardcode for line
// Is this 0xf0 mask really necessary? DK 03/02/05
switch (params.getCurveType() & 0xf0)
{
default:
case LL_PCODE_PATH_LINE:
{
// Take the begin/end twist into account for detail.
np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2;
}
break;
case LL_PCODE_PATH_CIRCLE:
{
// Increase the detail as the revolutions and twist increase.
F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist());
S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions());
np = sides;
}
break;
case LL_PCODE_PATH_CIRCLE2:
{
//genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f);
np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail));
}
break;
case LL_PCODE_PATH_TEST:
np = 5;
break;
};
return np;
}
BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
BOOL is_sculpted, S32 sculpt_size)
{
@ -2159,27 +2410,41 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 face_count = mdl.size();
if (face_count == 0)
{
llerrs << "WTF?" << llendl;
{ //no faces unpacked, treat as failed decode
llwarns << "found no faces!" << llendl;
return false;
}
mVolumeFaces.resize(face_count);
for (U32 i = 0; i < face_count; ++i)
{
LLVolumeFace& face = mVolumeFaces[i];
if (mdl[i].has("NoGeometry"))
{ //face has no geometry, continue
face.resizeIndices(3);
face.resizeVertices(1);
memset(face.mPositions, 0, sizeof(LLVector4a));
memset(face.mNormals, 0, sizeof(LLVector4a));
memset(face.mTexCoords, 0, sizeof(LLVector2));
memset(face.mIndices, 0, sizeof(U16)*3);
continue;
}
LLSD::Binary pos = mdl[i]["Position"];
LLSD::Binary norm = mdl[i]["Normal"];
LLSD::Binary tc = mdl[i]["TexCoord0"];
LLSD::Binary idx = mdl[i]["TriangleList"];
LLVolumeFace& face = mVolumeFaces[i];
//copy out indices
face.resizeIndices(idx.size()/2);
if (idx.empty() || face.mNumIndices < 3)
{ //why is there an empty index list?
llerrs <<"WTF?" << llendl;
llwarns <<"Empty face present!" << llendl;
continue;
}
@ -2377,14 +2642,20 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LLVector4a& min = face.mExtents[0];
LLVector4a& max = face.mExtents[1];
min.clear();
max.clear();
min = max = face.mPositions[0];
for (S32 i = 1; i < face.mNumVertices; ++i)
if (face.mNumVertices < 3)
{ //empty face, use a dummy 1cm (at 1m scale) bounding box
min.splat(-0.005f);
max.splat(0.005f);
}
else
{
min.setMin(min, face.mPositions[i]);
max.setMax(max, face.mPositions[i]);
min = max = face.mPositions[0];
for (S32 i = 1; i < face.mNumVertices; ++i)
{
min.setMin(min, face.mPositions[i]);
max.setMax(max, face.mPositions[i]);
}
}
}
}
@ -2980,7 +3251,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
// don't test lowest LOD to support legacy content DEV-33670
if (mDetail > SCULPT_MIN_AREA_DETAIL)
{
if (sculptGetSurfaceArea() < SCULPT_MIN_AREA)
F32 area = sculptGetSurfaceArea();
const F32 SCULPT_MAX_AREA = 32.f;
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
}
@ -4064,6 +4339,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
return index;
}
void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the
//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
F32 detail[] = {1.f, 1.5f, 2.5f, 4.f};
for (S32 i = 0; i < 4; i++)
{
S32 count = 0;
S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]);
S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]);
count = (profile_points-1)*2*(path_points-1);
count += profile_points*2;
counts[i] = count;
}
}
S32 LLVolume::getNumTriangleIndices() const
{
BOOL profile_open = getProfile().isOpen();
@ -5220,6 +5512,8 @@ LLVolumeFace::LLVolumeFace() :
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
mExtents[0].splat(-0.5f);
mExtents[1].splat(0.5f);
mCenter = mExtents+2;
}
@ -5741,6 +6035,11 @@ void LLVolumeFace::cacheOptimize()
LLVCacheLRU cache;
if (mNumVertices < 3)
{ //nothing to do
return;
}
//mapping of vertices to triangles and indices
std::vector<LLVCacheVertexData> vertex_data;

View File

@ -690,6 +690,9 @@ public:
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
BOOL isOpen() const { return mOpen; }
void setDirty() { mDirty = TRUE; }
static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
BOOL isConcave() const { return mConcave; }
@ -714,6 +717,7 @@ public:
protected:
void genNormals(const LLProfileParams& params);
static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
@ -756,6 +760,9 @@ public:
virtual ~LLPath();
static S32 getNumPoints(const LLPathParams& params, F32 detail);
static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
@ -981,6 +988,7 @@ public:
// returns number of triangle indeces required for path/profile mesh
S32 getNumTriangleIndices() const;
static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
S32 getNumTriangles() const;

View File

@ -742,6 +742,7 @@ char const* const _PREHASH_MoneyData = LLMessageStringTable::getInstance()->getS
char const* const _PREHASH_ObjectDeselect = LLMessageStringTable::getInstance()->getString("ObjectDeselect");
char const* const _PREHASH_NewAssetID = LLMessageStringTable::getInstance()->getString("NewAssetID");
char const* const _PREHASH_ObjectAdd = LLMessageStringTable::getInstance()->getString("ObjectAdd");
char const* const _PREHASH_SimulatorFeatures = LLMessageStringTable::getInstance()->getString("SimulatorFeatures");
char const* const _PREHASH_RayEndIsIntersection = LLMessageStringTable::getInstance()->getString("RayEndIsIntersection");
char const* const _PREHASH_CompleteAuction = LLMessageStringTable::getInstance()->getString("CompleteAuction");
char const* const _PREHASH_CircuitCode = LLMessageStringTable::getInstance()->getString("CircuitCode");

View File

@ -742,6 +742,7 @@ extern char const* const _PREHASH_MoneyData;
extern char const* const _PREHASH_ObjectDeselect;
extern char const* const _PREHASH_NewAssetID;
extern char const* const _PREHASH_ObjectAdd;
extern char const* const _PREHASH_SimulatorFeatures;
extern char const* const _PREHASH_RayEndIsIntersection;
extern char const* const _PREHASH_CompleteAuction;
extern char const* const _PREHASH_CircuitCode;

View File

@ -50,7 +50,7 @@ std::string model_names[] =
"low_lod",
"medium_lod",
"high_lod",
"physics_shape"
"physics_mesh"
};
const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string);
@ -84,7 +84,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
domInputLocal_Array& v_inp = vertices->getInput_array();
if (inputs[j]->getOffset() != 0)
{
llerrs << "WTF?" << llendl;
llerrs << "Vertex array offset MUST be zero." << llendl;
}
for (U32 k = 0; k < v_inp.getCount(); ++k)
@ -98,7 +98,7 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
{
llerrs << "WTF?" << llendl;
llerrs << "Vertex array stride MUST be three." << llendl;
}
domListOfFloats& v = src->getFloat_array()->getValue();
@ -149,9 +149,10 @@ void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Arr
}
}
void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
{
idx_stride = 0;
for (U32 j = 0; j < inputs.getCount(); ++j)
@ -163,7 +164,11 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
if ( !vertices )
{
return false;
}
domInputLocal_Array& v_inp = vertices->getInput_array();
@ -207,6 +212,8 @@ void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S
}
idx_stride += 1;
return true;
}
LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri)
@ -227,8 +234,12 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
S32 idx_stride = 0;
get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
{
return LLModel::BAD_ELEMENT;
}
domPRef p = tri->getP();
domListOfUInts& idx = p->getValue();
@ -367,7 +378,10 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
S32 idx_stride = 0;
get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source);
if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
{
return LLModel::BAD_ELEMENT;
}
LLVolumeFace face;
@ -564,7 +578,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
if (!vertices)
{
return LLModel::BAD_ELEMENT;
}
domInputLocal_Array& v_inp = vertices->getInput_array();
for (U32 k = 0; k < v_inp.getCount(); ++k)
@ -574,6 +591,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = v_inp[k]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
if (!src)
{
return LLModel::BAD_ELEMENT;
}
v = &(src->getFloat_array()->getValue());
}
}
@ -585,6 +606,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
if (!src)
{
return LLModel::BAD_ELEMENT;
}
n = &(src->getFloat_array()->getValue());
}
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0)
@ -593,6 +618,10 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
const domURIFragmentType& uri = inputs[i]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
if (!src)
{
return LLModel::BAD_ELEMENT;
}
t = &(src->getFloat_array()->getValue());
}
}
@ -667,11 +696,6 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
}
}
if (cur_idx != vert_idx.size())
{
llerrs << "WTF?" << llendl;
}
//build vertex array from map
std::vector<LLVolumeFace::VertexData> new_verts;
new_verts.resize(vert_idx.size());
@ -717,7 +741,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
//static
std::string LLModel::getStatusString(U32 status)
{
const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow"};
const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"};
if(status < INVALID_STATUS)
{
@ -755,7 +779,6 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
for (U32 i = 0; i < polys.getCount(); ++i)
{
domPolylistRef& poly = polys.get(i);
mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@ -765,12 +788,12 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
domPolygons_Array& polygons = mesh->getPolygons_array();
for (U32 i = 0; i < polygons.getCount(); ++i)
{
domPolygonsRef& poly = polygons.get(i);
mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly);
if(mStatus != NO_ERRORS)
@ -780,7 +803,7 @@ void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh)
return ; //abort
}
}
}
BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
@ -926,11 +949,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVector4a min, max;
if (mVolumeFaces[0].mNumVertices <= 0)
{
llerrs << "WTF?" << llendl;
}
// For all of the volume faces
// in the model, loop over
// them and see what the extents
@ -942,11 +960,6 @@ void LLModel::normalizeVolumeFaces()
{
LLVolumeFace& face = mVolumeFaces[i];
if (face.mNumVertices <= 0)
{
llerrs << "WTF?" << llendl;
}
update_min_max(min, max, face.mExtents[0]);
update_min_max(min, max, face.mExtents[1]);
}
@ -1289,11 +1302,6 @@ void LLModel::generateNormals(F32 angle_cutoff)
{
LLVector4a& n = iter->second[k].getNormal();
if (!iter->second[k].getPosition().equals3(new_face.mPositions[i]))
{
llerrs << "WTF?" << llendl;
}
F32 cur = n.dot3(ref_norm).getF32();
if (cur > best)
@ -1410,7 +1418,11 @@ LLSD LLModel::writeModel(
if (!decomp.mBaseHull.empty() ||
!decomp.mHull.empty())
{
mdl["decomposition"] = decomp.asLLSD();
mdl["physics_convex"] = decomp.asLLSD();
if (!decomp.mHull.empty())
{ //convex decomposition exists, physics mesh will not be used
model[LLModel::LOD_PHYSICS] = NULL;
}
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
@ -1435,8 +1447,9 @@ LLSD LLModel::writeModel(
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
{ //for each face
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
if (!face.mNumVertices)
if (face.mNumVertices < 3)
{ //don't export an empty face
mdl[model_names[idx]][i]["NoGeometry"] = true;
continue;
}
LLSD::Binary verts(face.mNumVertices*3*2);
@ -1469,7 +1482,6 @@ LLSD LLModel::writeModel(
//position + normal
for (U32 k = 0; k < 3; ++k)
{ //for each component
//convert to 16-bit normalized across domain
U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535);
@ -1513,7 +1525,6 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
@ -1539,11 +1550,6 @@ LLSD LLModel::writeModel(
weight_list& weights = high->getJointInfluences(pos);
if (weights.size() > 4)
{
llerrs << "WTF?" << llendl;
}
S32 count = 0;
for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)
{
@ -1607,23 +1613,19 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
else
{
llerrs << "WTF?" << llendl;
}
}
std::string decomposition;
if (mdl.has("decomposition"))
if (mdl.has("physics_convex"))
{ //write out convex decomposition
decomposition = zip_llsd(mdl["decomposition"]);
decomposition = zip_llsd(mdl["physics_convex"]);
U32 size = decomposition.size();
if (size > 0)
{
header["decomposition"]["offset"] = (LLSD::Integer) cur_offset;
header["decomposition"]["size"] = (LLSD::Integer) size;
header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset;
header["physics_convex"]["size"] = (LLSD::Integer) size;
cur_offset += size;
bytes += size;
}
@ -1644,11 +1646,6 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
cur_offset += size;
bytes += size;
}
else
{
header[model_names[i]]["offset"] = -1;
header[model_names[i]]["size"] = 0;
}
}
if (!nowrite)
@ -1662,7 +1659,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
if (!decomposition.empty())
{ //write decomposition block
ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger());
ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger());
}
for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++)
@ -1685,7 +1682,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
if ((iter->first - pos).magVec() > 0.1f)
{
llerrs << "WTF?" << llendl;
llerrs << "Couldn't find weight list." << llendl;
}
return iter->second;
@ -1778,7 +1775,7 @@ void LLModel::updateHullCenters()
if (mHullPoints > 0)
{
mCenterOfHullCenters *= 1.f / mHullPoints;
llassert(mPhysics.asLLSD().has("HullList"));
llassert(mPhysics.hasHullList());
}
}
@ -1801,7 +1798,7 @@ bool LLModel::loadModel(std::istream& is)
"low_lod",
"medium_lod",
"high_lod",
"physics_shape",
"physics_mesh",
};
const S32 MODEL_LODS = 5;
@ -1900,8 +1897,8 @@ bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
{
S32 offset = header["decomposition"]["offset"].asInteger();
S32 size = header["decomposition"]["size"].asInteger();
S32 offset = header["physics_convex"]["offset"].asInteger();
S32 size = header["physics_convex"]["size"].asInteger();
if (offset >= 0 && size > 0)
{
@ -2041,7 +2038,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
const LLSD::Binary& position = decomp["Position"].asBinary();
const LLSD::Binary& position = decomp["Positions"].asBinary();
U16* p = (U16*) &position[0];
@ -2051,11 +2048,19 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
LLVector3 max;
LLVector3 range;
min.setValue(decomp["Min"]);
max.setValue(decomp["Max"]);
if (decomp.has("Min"))
{
min.setValue(decomp["Min"]);
max.setValue(decomp["Max"]);
}
else
{
min.set(-0.5f, -0.5f, -0.5f);
max.set(0.5f, 0.5f, 0.5f);
}
range = max-min;
for (U32 i = 0; i < hulls.size(); ++i)
{
U16 count = (hulls[i] == 0) ? 256 : hulls[i];
@ -2071,6 +2076,7 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
//point must be unique
//llassert(valid.find(test) == valid.end());
valid.insert(test);
mHull[i].push_back(LLVector3(
(F32) p[0]/65535.f*range.mV[0]+min.mV[0],
(F32) p[1]/65535.f*range.mV[1]+min.mV[1],
@ -2085,9 +2091,9 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
}
}
if (decomp.has("Hull"))
if (decomp.has("BoundingVerts"))
{
const LLSD::Binary& position = decomp["Hull"].asBinary();
const LLSD::Binary& position = decomp["BoundingVerts"].asBinary();
U16* p = (U16*) &position[0];
@ -2123,10 +2129,15 @@ void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
//empty base hull mesh to indicate decomposition has been loaded
//but contains no base hull
mBaseHullMesh.clear();;
mBaseHullMesh.clear();
}
}
bool LLModel::Decomposition::hasHullList() const
{
return !mHull.empty() ;
}
LLSD LLModel::Decomposition::asLLSD() const
{
LLSD ret;
@ -2137,11 +2148,9 @@ LLSD LLModel::Decomposition::asLLSD() const
}
//write decomposition block
// ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
// ["decomposition"]["PositionDomain"]["Min"/"Max"]
// ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
// ["decomposition"]["Hull"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
// ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points
// ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points
// ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape
//get minimum and maximum
LLVector3 min;
@ -2190,6 +2199,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@ -2205,17 +2216,24 @@ LLSD LLModel::Decomposition::asLLSD() const
U64 test = 0;
for (U32 k = 0; k < 3; k++)
{
F32* src = (F32*) (mHull[i][j].mV);
llassert(src[k] <= 0.501f && src[k] >= -0.501f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((mHull[i][j].mV[k]-min.mV[k])/range.mV[k])*65535);
U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
switch (k)
if(valid.size() < 3)
{
case 0: test = test | (U64) val; break;
case 1: test = test | ((U64) val << 16); break;
case 2: test = test | ((U64) val << 32); break;
};
switch (k)
{
case 0: test = test | (U64) val; break;
case 1: test = test | ((U64) val << 16); break;
case 2: test = test | ((U64) val << 32); break;
};
valid.insert(test);
valid.insert(test);
}
U8* buff = (U8*) &val;
//write to binary buffer
@ -2227,17 +2245,21 @@ LLSD LLModel::Decomposition::asLLSD() const
}
}
//must have at least 4 unique points
llassert(valid.size() > 3);
//must have at least 3 unique points
llassert(valid.size() > 2);
}
ret["Position"] = p;
ret["Positions"] = p;
}
//llassert(!mBaseHull.empty());
if (!mBaseHull.empty())
{
LLSD::Binary p(mBaseHull.size()*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
@ -2245,6 +2267,8 @@ LLSD LLModel::Decomposition::asLLSD() const
{
for (U32 k = 0; k < 3; k++)
{
llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
@ -2255,12 +2279,12 @@ LLSD LLModel::Decomposition::asLLSD() const
if (vert_idx > p.size())
{
llerrs << "WTF?" << llendl;
llerrs << "Index out of bounds" << llendl;
}
}
}
ret["Hull"] = p;
ret["BoundingVerts"] = p;
}
return ret;
@ -2290,10 +2314,5 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
{ //take physics shape mesh from rhs
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
if (!mHull.empty())
{ //verify
llassert(asLLSD().has("HullList"));
}
}

View File

@ -73,6 +73,7 @@ public:
{
NO_ERRORS = 0,
VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535.
BAD_ELEMENT,
INVALID_STATUS
} ;
@ -106,6 +107,7 @@ public:
Decomposition(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD() const;
bool hasHullList() const;
void merge(const Decomposition* rhs);

View File

@ -127,6 +127,11 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
// GL_ARB_map_buffer_range
PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
// vertex object prototypes
PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL;
@ -178,6 +183,12 @@ PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;
PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;
//GL_ARB_texture_multisample
PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
PFNGLSAMPLEMASKIPROC glSampleMaski;
// GL_EXT_blend_func_separate
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
@ -321,9 +332,11 @@ LLGLManager::LLGLManager() :
mHasMipMapGeneration(FALSE),
mHasCompressedTextures(FALSE),
mHasFramebufferObject(FALSE),
mMaxSamples(0),
mHasBlendFuncSeparate(FALSE),
mHasVertexBufferObject(FALSE),
mHasMapBufferRange(FALSE),
mHasPBuffer(FALSE),
mHasShaderObjects(FALSE),
mHasVertexShader(FALSE),
@ -334,6 +347,11 @@ LLGLManager::LLGLManager() :
mHasPointParameters(FALSE),
mHasDrawBuffers(FALSE),
mHasTextureRectangle(FALSE),
mHasTextureMultisample(FALSE),
mMaxSampleMaskWords(0),
mMaxColorTextureSamples(0),
mMaxDepthTextureSamples(0),
mMaxIntegerSamples(0),
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
@ -539,7 +557,20 @@ bool LLGLManager::initGL()
{
GLint num_tex_image_units;
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
mNumTextureImageUnits = num_tex_image_units;
mNumTextureImageUnits = llmin(num_tex_image_units, 32);
}
if (mHasTextureMultisample)
{
glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
}
if (mHasFramebufferObject)
{
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
}
setToDebugGPU();
@ -648,6 +679,14 @@ std::string LLGLManager::getRawGLString()
return gl_string;
}
U32 LLGLManager::getNumFBOFSAASamples(U32 samples)
{
samples = llmin(samples, (U32) mMaxColorTextureSamples);
samples = llmin(samples, (U32) mMaxDepthTextureSamples);
samples = llmin(samples, (U32) 4);
return samples;
}
void LLGLManager::shutdownGL()
{
if (mInited)
@ -728,6 +767,7 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", 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
#ifdef GL_ARB_framebuffer_object
@ -742,6 +782,7 @@ void LLGLManager::initExtensions()
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@ -921,6 +962,11 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
if (mHasMapBufferRange)
{
glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange");
glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange");
}
if (mHasFramebufferObject)
{
llinfos << "initExtensions() FramebufferObject-related procs..." << llendl;
@ -953,6 +999,13 @@ void LLGLManager::initExtensions()
{
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
}
if (mHasTextureMultisample)
{
glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample");
glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
}
#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
@ -1370,10 +1423,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
}
}
GLint maxTextureUnits = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
stop_glerror();
static const char* label[] =
{
"GL_TEXTURE_2D",
@ -1384,7 +1433,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
"GL_TEXTURE_GEN_T",
"GL_TEXTURE_GEN_Q",
"GL_TEXTURE_GEN_R",
"GL_TEXTURE_RECTANGLE_ARB"
"GL_TEXTURE_RECTANGLE_ARB",
"GL_TEXTURE_2D_MULTISAMPLE"
};
static GLint value[] =
@ -1397,7 +1447,8 @@ void LLGLState::checkTextureChannels(const std::string& msg)
GL_TEXTURE_GEN_T,
GL_TEXTURE_GEN_Q,
GL_TEXTURE_GEN_R,
GL_TEXTURE_RECTANGLE_ARB
GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_2D_MULTISAMPLE
};
GLint stackDepth = 0;
@ -1406,68 +1457,96 @@ void LLGLState::checkTextureChannels(const std::string& msg)
glh::matrix4f identity;
identity.identity();
for (GLint i = 1; i < maxTextureUnits; i++)
for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
stop_glerror();
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
stop_glerror();
if (stackDepth != 1)
if (i < gGLManager.mNumTextureUnits)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
stop_glerror();
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
stop_glerror();
if (gDebugSession)
{
gFailLog << "Texture matrix stack corrupted." << std::endl;
}
}
glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
if (gDebugSession)
{
gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
}
}
for (S32 j = (i == 0 ? 1 : 0);
j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
{
if (glIsEnabled(value[j]))
if (stackDepth != 1)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
if (gDebugSession)
{
gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
gFailLog << "Texture matrix stack corrupted." << std::endl;
}
}
glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
if (gDebugSession)
{
gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
}
}
for (S32 j = (i == 0 ? 1 : 0);
j < 9; j++)
{
if (j == 8 && !gGLManager.mHasTextureRectangle ||
j == 9 && !gGLManager.mHasTextureMultisample)
{
continue;
}
if (glIsEnabled(value[j]))
{
error = TRUE;
LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
if (gDebugSession)
{
gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
}
}
stop_glerror();
}
glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
if (gDebugSession)
{
gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
}
}
}
glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
if (gDebugSession)
GLint tex = 0;
stop_glerror();
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex);
stop_glerror();
if (tex != 0)
{
gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
error = TRUE;
LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << llendl;
if (gDebugSession)
{
gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl;
}
}
}
}
stop_glerror();
gGL.getTexUnit(0)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB);
stop_glerror();

View File

@ -83,10 +83,12 @@ public:
BOOL mHasMipMapGeneration;
BOOL mHasCompressedTextures;
BOOL mHasFramebufferObject;
S32 mMaxSamples;
BOOL mHasBlendFuncSeparate;
// ARB Extensions
BOOL mHasVertexBufferObject;
BOOL mHasMapBufferRange;
BOOL mHasPBuffer;
BOOL mHasShaderObjects;
BOOL mHasVertexShader;
@ -98,6 +100,11 @@ public:
BOOL mHasDrawBuffers;
BOOL mHasDepthClamp;
BOOL mHasTextureRectangle;
BOOL mHasTextureMultisample;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
S32 mMaxIntegerSamples;
// Other extensions.
BOOL mHasAnisotropic;
@ -139,6 +146,7 @@ public:
void printGLInfoString();
void getGLInfo(LLSD& info);
U32 getNumFBOFSAASamples(U32 desired_samples = 32);
// In ALL CAPS
std::string mGLVendor;
std::string mGLVendorShort;

View File

@ -68,6 +68,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@ -306,6 +310,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@ -474,6 +482,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
//GL_ARB_texture_multisample
extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_WINDOWS
//----------------------------------------------------------------------------
@ -506,6 +519,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
// GL_ARB_map_buffer_range
extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@ -673,6 +690,11 @@ extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
//GL_ARB_draw_buffers
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
//GL_ARB_texture_multisample
extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
extern PFNGLSAMPLEMASKIPROC glSampleMaski;
#elif LL_DARWIN
//----------------------------------------------------------------------------
@ -714,13 +736,55 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#ifndef GL_ARB_framebuffer_object
#define glGenerateMipmap glGenerateMipmapEXT
#define GL_MAX_SAMPLES 0x8D57
#endif
// GL_ARB_draw_buffers
extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
#ifdef __cplusplus
extern "C" {
#endif
//
// Define map buffer range headers on Mac
//
#ifndef GL_ARB_map_buffer_range
#define GL_MAP_READ_BIT 0x0001
#define GL_MAP_WRITE_BIT 0x0002
#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
#endif
//
// Define multisample headers on Mac
//
#ifndef GL_ARB_texture_multisample
#define GL_SAMPLE_POSITION 0x8E50
#define GL_SAMPLE_MASK 0x8E51
#define GL_SAMPLE_MASK_VALUE 0x8E52
#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
#define GL_TEXTURE_SAMPLES 0x9106
#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
#define GL_MAX_INTEGER_SAMPLES 0x9110
#endif
//
// Define vertex buffer object headers on Mac
//
@ -757,7 +821,7 @@ extern "C" {
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_DYNAMIC_COPY_ARB 0x88EA
#endif
#ifndef GL_ARB_vertex_buffer_object

View File

@ -48,6 +48,8 @@ using std::pair;
using std::make_pair;
using std::string;
GLhandleARB LLGLSLShader::sCurBoundShader = 0;
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
return v1 != v2;
@ -56,7 +58,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false)
{
}
@ -107,16 +109,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
// Create program
mProgramObject = glCreateProgramObjectARB();
// Attach existing objects
if (!LLShaderMgr::instance()->attachShaderFeatures(this))
{
return FALSE;
}
//compile new source
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
{
GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second);
GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels);
LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
if (shaderhandle > 0)
{
@ -128,6 +125,12 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
}
}
// Attach existing objects
if (!LLShaderMgr::instance()->attachShaderFeatures(this))
{
return FALSE;
}
// Map attributes and uniforms
if (success)
{
@ -149,6 +152,29 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
return createShader(attributes,uniforms);
}
}
else if (mFeatures.mIndexedTextureChannels > 0)
{ //override texture channels for indexed texture rendering
bind();
S32 channel_count = mFeatures.mIndexedTextureChannels;
for (S32 i = 0; i < channel_count; i++)
{
uniform1i(llformat("tex%d", i), i);
}
S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
for (U32 i = 0; i < mTexture.size(); i++)
{
if (mTexture[i] > -1 && mTexture[i] < channel_count)
{
llassert(cur_tex < gGLManager.mNumTextureImageUnits);
uniform1i(i, cur_tex);
mTexture[i] = cur_tex++;
}
}
unbind();
}
return success;
}
@ -293,7 +319,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
{
if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB)
if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB ||
type == GL_SAMPLER_2D_MULTISAMPLE)
{ //this here is a texture
glUniform1iARB(location, mActiveTextureChannels);
LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
@ -342,7 +369,7 @@ void LLGLSLShader::bind()
if (gGLManager.mHasShaderObjects)
{
glUseProgramObjectARB(mProgramObject);
sCurBoundShader = mProgramObject;
if (mUniformsDirty)
{
LLShaderMgr::instance()->updateShaderUniforms(this);
@ -365,6 +392,7 @@ void LLGLSLShader::unbind()
}
}
glUseProgramObjectARB(0);
sCurBoundShader = 0;
stop_glerror();
}
}
@ -372,6 +400,7 @@ void LLGLSLShader::unbind()
void LLGLSLShader::bindNoShader(void)
{
glUseProgramObjectARB(0);
sCurBoundShader = 0;
}
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)

View File

@ -45,6 +45,8 @@ public:
bool hasObjectSkinning;
bool hasAtmospherics;
bool hasGamma;
S32 mIndexedTextureChannels;
bool disableTextureIndex;
// char numLights;
@ -64,6 +66,8 @@ public:
LLGLSLShader();
static GLhandleARB sCurBoundShader;
void unload();
BOOL createShader(std::vector<std::string> * attributes,
std::vector<std::string> * uniforms);

View File

@ -1083,12 +1083,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
}
// static
void LLImageGL::deleteTextures(S32 numTextures, U32 *textures)
void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
{
for (S32 i = 0; i < numTextures; i++)
{
sDeadTextureList.push_back(textures[i]);
}
if (immediate)
{
LLImageGL::deleteDeadTextures();
}
}
// static
@ -1413,11 +1418,13 @@ void LLImageGL::deleteDeadTextures()
{
GLuint tex = sDeadTextureList.front();
sDeadTextureList.pop_front();
for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
{
if (sCurrentBoundTextures[i] == tex)
LLTexUnit* tex_unit = gGL.getTexUnit(i);
if (tex_unit->getCurrTexture() == tex)
{
gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
tex_unit->unbind(tex_unit->getCurrType());
stop_glerror();
}
}

View File

@ -98,7 +98,7 @@ public:
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
// for tracking purposes and will be deprecated in the future
static void generateTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels);
BOOL createGLTexture() ;

View File

@ -30,6 +30,7 @@
#include "llvertexbuffer.h"
#include "llcubemap.h"
#include "llglslshader.h"
#include "llimagegl.h"
#include "llrendertarget.h"
#include "lltexture.h"
@ -46,14 +47,15 @@ S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 0;
static const U32 LL_NUM_TEXTURE_LAYERS = 16;
static const U32 LL_NUM_TEXTURE_LAYERS = 32;
static const U32 LL_NUM_LIGHT_UNITS = 8;
static GLenum sGLTextureType[] =
{
GL_TEXTURE_2D,
GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_CUBE_MAP_ARB
GL_TEXTURE_CUBE_MAP_ARB,
GL_TEXTURE_2D_MULTISAMPLE
};
static GLint sGLAddressMode[] =
@ -124,7 +126,7 @@ void LLTexUnit::refreshState(void)
// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
//
bool enableDisable = (mIndex < gGLManager.mNumTextureUnits);
bool enableDisable = (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE;
if (mCurrTexType != TT_NONE)
{
@ -182,8 +184,8 @@ void LLTexUnit::enable(eTextureType type)
mCurrTexType = type;
gGL.flush();
if (mIndex < gGLManager.mNumTextureUnits)
if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
mIndex < gGLManager.mNumTextureUnits)
{
glEnable(sGLTextureType[type]);
}
@ -199,8 +201,8 @@ void LLTexUnit::disable(void)
activate();
unbind(mCurrTexType);
gGL.flush();
if (mIndex < gGLManager.mNumTextureUnits)
if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
mIndex < gGLManager.mNumTextureUnits)
{
glDisable(sGLTextureType[mCurrTexType]);
}
@ -292,7 +294,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
texture->updateBindStats(texture->mTextureMemory);
mHasMipMaps = texture->mHasMipMaps;
if (texture->mTexOptionsDirty)
if (mIndex == 0 && texture->mTexOptionsDirty)
{
texture->mTexOptionsDirty = false;
setTextureAddressMode(texture->mAddressMode);
@ -402,6 +404,7 @@ void LLTexUnit::unbind(eTextureType type)
activate();
mCurrTexture = 0;
glBindTexture(sGLTextureType[type], 0);
stop_glerror();
}
}
@ -423,7 +426,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
if (mIndex < 0 || mCurrTexture == 0) return;
if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
gGL.flush();

View File

@ -57,6 +57,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_NONE // No texture type is currently enabled
} eTextureType;

View File

@ -63,8 +63,7 @@ LLRenderTarget::LLRenderTarget() :
mUseDepth(false),
mRenderDepth(false),
mUsage(LLTexUnit::TT_TEXTURE),
mSamples(0),
mSampleBuffer(NULL)
mSamples(0)
{
}
@ -73,23 +72,32 @@ LLRenderTarget::~LLRenderTarget()
release();
}
void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer)
{
mSampleBuffer = buffer;
}
void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo)
void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
stop_glerror();
release();
mResX = resx;
mResY = resy;
mStencil = stencil;
mUsage = usage;
mUseDepth = depth;
mSamples = samples;
release();
mSamples = gGLManager.getNumFBOFSAASamples(mSamples);
if (mSamples > 1 && gGLManager.mHasTextureMultisample)
{
mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE;
//no support for multisampled stencil targets yet
mStencil = false;
}
else
{
mSamples = 0;
}
if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
{
@ -146,29 +154,51 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
stop_glerror();
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#ifdef GL_ARB_texture_multisample
if (mSamples > 1)
{
glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
}
else
#else
llassert_always(mSamples <= 1);
#endif
{
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 (mSamples == 0)
{
if (offset == 0)
{ //use bilinear filtering on single texture render targets that aren't multisampled
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
stop_glerror();
}
else
{ //don't filter data attachments
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
stop_glerror();
}
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
{
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
stop_glerror();
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
}
if (mFBO)
{
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
LLTexUnit::getInternalType(mUsage), tex, 0);
@ -181,6 +211,12 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt)
mTex.push_back(tex);
if (gDebugGL)
{ //bind and unbind to validate target
bindTarget();
flush();
}
}
void LLRenderTarget::allocateDepth()
@ -197,9 +233,20 @@ void LLRenderTarget::allocateDepth()
{
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
if (mSamples == 0)
{
U32 internal_type = LLTexUnit::getInternalType(mUsage);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
#ifdef GL_ARB_texture_multisample
else
{
glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
}
#else
llassert_always(mSamples <= 1);
#endif
}
}
@ -239,6 +286,9 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
}
check_framebuffer_status();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
target.mUseDepth = true;
@ -256,7 +306,7 @@ void LLRenderTarget::release()
}
else
{
LLImageGL::deleteTextures(1, &mDepth);
LLImageGL::deleteTextures(1, &mDepth, true);
stop_glerror();
}
mDepth = 0;
@ -285,11 +335,12 @@ void LLRenderTarget::release()
if (mTex.size() > 0)
{
LLImageGL::deleteTextures(mTex.size(), &mTex[0]);
LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
mTex.clear();
}
mResX = mResY = 0;
mSampleBuffer = NULL;
sBoundTarget = NULL;
}
@ -298,34 +349,27 @@ void LLRenderTarget::bindTarget()
if (mFBO)
{
stop_glerror();
if (mSampleBuffer)
{
mSampleBuffer->bindTarget(this);
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);
}
else
{
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();
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);
@ -407,50 +451,8 @@ void LLRenderTarget::flush(bool fetch_depth)
else
{
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
if (mSampleBuffer)
{
LLGLEnable multisample(GL_MULTISAMPLE);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
stop_glerror();
check_framebuffer_status();
glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO);
check_framebuffer_status();
stop_glerror();
glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
stop_glerror();
if (mTex.size() > 1)
{
for (U32 i = 1; i < mTex.size(); ++i)
{
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
LLTexUnit::getInternalType(mUsage), mTex[i], 0);
stop_glerror();
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
stop_glerror();
glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST);
stop_glerror();
}
for (U32 i = 0; i < mTex.size(); ++i)
{
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i,
LLTexUnit::getInternalType(mUsage), mTex[i], 0);
stop_glerror();
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]);
stop_glerror();
}
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
@ -467,37 +469,36 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
}
if (mSampleBuffer)
if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
{
mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
check_framebuffer_status();
gGL.getTexUnit(0)->bind(this, true);
stop_glerror();
glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
else
{
if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil)
{
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO);
gGL.getTexUnit(0)->bind(this, true);
stop_glerror();
glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
else
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
stop_glerror();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
stop_glerror();
check_framebuffer_status();
stop_glerror();
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO);
stop_glerror();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO);
stop_glerror();
check_framebuffer_status();
stop_glerror();
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
stop_glerror();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
stop_glerror();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
}
@ -540,179 +541,3 @@ void LLRenderTarget::getViewport(S32* viewport)
viewport[3] = mResY;
}
//==================================================
// LLMultisampleBuffer implementation
//==================================================
LLMultisampleBuffer::LLMultisampleBuffer()
{
}
LLMultisampleBuffer::~LLMultisampleBuffer()
{
release();
}
void LLMultisampleBuffer::release()
{
if (mFBO)
{
glDeleteFramebuffers(1, (GLuint *) &mFBO);
mFBO = 0;
}
if (mTex.size() > 0)
{
glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]);
mTex.clear();
}
if (mDepth)
{
glDeleteRenderbuffers(1, (GLuint *) &mDepth);
mDepth = 0;
}
}
void LLMultisampleBuffer::bindTarget()
{
bindTarget(this);
}
void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref)
{
if (!ref)
{
ref = this;
}
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
if (gGLManager.mHasDrawBuffers)
{ //setup multiple render targets
GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
glDrawBuffersARB(ref->mTex.size(), drawbuffers);
}
check_framebuffer_status();
glViewport(0, 0, mResX, mResY);
sBoundTarget = this;
}
void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo )
{
allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2);
}
void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples )
{
stop_glerror();
mResX = resx;
mResY = resy;
mUsage = usage;
mUseDepth = depth;
mStencil = stencil;
release();
mSamples = samples;
if (mSamples <= 1)
{
llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl;
}
stop_glerror();
if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
{
if (depth)
{
stop_glerror();
allocateDepth();
stop_glerror();
}
glGenFramebuffers(1, (GLuint *) &mFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
if (mDepth)
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
if (mStencil)
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth);
}
}
stop_glerror();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
stop_glerror();
}
addColorAttachment(color_fmt);
}
void LLMultisampleBuffer::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;
glGenRenderbuffers(1, &tex);
glBindRenderbuffer(GL_RENDERBUFFER, tex);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY);
stop_glerror();
if (mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex);
stop_glerror();
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status)
{
case GL_FRAMEBUFFER_COMPLETE:
break;
default:
llerrs << "WTF? " << std::hex << status << llendl;
break;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
mTex.push_back(tex);
}
void LLMultisampleBuffer::allocateDepth()
{
glGenRenderbuffers(1, (GLuint* ) &mDepth);
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
if (mStencil)
{
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY);
}
else
{
glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16, mResX, mResY);
}
}

View File

@ -71,10 +71,7 @@ public:
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE);
//provide this render target with a multisample resource.
void setSampleBuffer(LLMultisampleBuffer* buffer);
void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
//add color buffer attachment
//limit of 4 color attachments per render target
@ -141,7 +138,6 @@ public:
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
protected:
friend class LLMultisampleBuffer;
U32 mResX;
U32 mResY;
std::vector<U32> mTex;
@ -152,26 +148,8 @@ protected:
bool mRenderDepth;
LLTexUnit::eTextureType mUsage;
U32 mSamples;
LLMultisampleBuffer* mSampleBuffer;
static LLRenderTarget* sBoundTarget;
};
class LLMultisampleBuffer : public LLRenderTarget
{
public:
LLMultisampleBuffer();
virtual ~LLMultisampleBuffer();
virtual void release();
virtual void bindTarget();
void bindTarget(LLRenderTarget* ref);
virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo);
void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples);
virtual void addColorAttachment(U32 color_fmt);
virtual void allocateDepth();
static LLRenderTarget* sBoundTarget;
};
#endif //!LL_MESA_HEADLESS

View File

@ -209,17 +209,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
if (!shader->attachObject("lighting/lightWaterF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightWaterF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
if (!shader->attachObject("lighting/lightF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@ -230,32 +252,76 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->isShiny && features->hasWaterFog)
{
if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->hasWaterFog)
{
if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else if (features->isShiny)
{
if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@ -266,17 +332,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
else
{
if (!shader->attachObject("lighting/lightShinyF.glsl"))
if (features->disableTextureIndex)
{
return FALSE;
if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl"))
{
return FALSE;
}
}
else
{
if (!shader->attachObject("lighting/lightShinyF.glsl"))
{
return FALSE;
}
shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@ -315,12 +403,12 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
else
{
LL_INFOS("ShaderLoading") << log << LL_ENDL;
LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
}
}
}
GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels)
{
GLenum error = GL_NO_ERROR;
if (gDebugGL)
@ -374,6 +462,106 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
GLcharARB* text[1024];
GLuint count = 0;
if (gGLManager.mGLVersion < 3.f)
{
//set version to 1.20
text[count++] = strdup("#version 120\n");
}
else
{ //set version to 1.30
text[count++] = strdup("#version 130\n");
}
//copy preprocessor definitions into buffer
for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
text[count++] = (GLcharARB *) strdup(define.c_str());
}
if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB)
{
//use specified number of texture channels for indexed texture rendering
/* prepend shader code that looks like this:
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
.
.
.
uniform sampler2D texN;
varying float vary_texture_index;
vec4 diffuseLookup(vec2 texcoord)
{
switch (int(vary_texture_index+0.25))
{
case 0: return texture2D(tex0, texcoord);
case 1: return texture2D(tex1, texcoord);
case 2: return texture2D(tex2, texcoord);
.
.
.
case N: return texture2D(texN, texcoord);
}
return vec4(0,0,0,0);
}
*/
//uniform declartion
for (S32 i = 0; i < texture_index_channels; ++i)
{
std::string decl = llformat("uniform sampler2D tex%d;\n", i);
text[count++] = strdup(decl.c_str());
}
text[count++] = strdup("varying float vary_texture_index;\n");
text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
text[count++] = strdup("{\n");
if (gGLManager.mGLVersion >= 3.f)
{
text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
text[count++] = strdup("\t{\n");
//switch body
for (S32 i = 0; i < texture_index_channels; ++i)
{
std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i);
text[count++] = strdup(case_str.c_str());
}
text[count++] = strdup("\t}\n");
}
else
{
//switches aren't supported, make block that looks like:
/*
int ti = int(vary_texture_index+0.25);
if (ti == 0) return texture2D(tex0, texcoord);
if (ti == 1) return texture2D(tex1, texcoord);
.
.
.
if (ti == N) return texture2D(texN, texcoord);
*/
text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n");
for (S32 i = 0; i < texture_index_channels; ++i)
{
std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
text[count++] = strdup(if_str.c_str());
}
}
text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
text[count++] = strdup("}\n");
}
//copy file into memory
while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) )
@ -457,7 +645,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (shader_level > 1)
{
shader_level--;
return loadShaderFile(filename,shader_level,type);
return loadShaderFile(filename,shader_level,type,texture_index_channels);
}
LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
}

View File

@ -43,7 +43,7 @@ public:
void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type);
GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
@ -60,6 +60,9 @@ public:
std::vector<std::string> mReservedUniforms;
//preprocessor definitions (name/value)
std::map<std::string, std::string> mDefinitions;
protected:
// our parameter manager singleton instance

View File

@ -934,8 +934,26 @@ void LLVertexBuffer::allocateClientIndexBuffer()
}
}
bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
{
S32 end = index+count;
S32 region_end = region.mIndex+region.mCount;
if (end < region.mIndex ||
index > region_end)
{ //gap exists, do not merge
return false;
}
S32 new_end = llmax(end, region_end);
S32 new_index = llmin(index, region.mIndex);
region.mIndex = new_index;
region.mCount = new_end-new_index;
return true;
}
// Map for data access
U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@ -947,8 +965,45 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
}
if (!mVertexLocked && useVBOs())
if (useVBOs())
{
if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
{
if (count == -1)
{
count = mNumVerts-index;
}
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
MappedRegion& region = mMappedVertexRegions[i];
if (region.mType == type)
{
if (expand_region(region, index, count))
{
mapped = true;
break;
}
}
}
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count);
mMappedVertexRegions.push_back(region);
}
}
if (mVertexLocked && map_range)
{
llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
}
if (!mVertexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
setBuffer(0, type);
@ -957,61 +1012,95 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
if(sDisableVBOMapping)
{
map_range = false;
allocateClientVertexBuffer() ;
}
else
{
U8* src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
U8* src = NULL;
#ifdef GL_ARB_map_buffer_range
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
S32 offset = mOffsets[type] + sTypeSize[type]*index;
S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
}
else
{
src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
}
}
else
#else
llassert_always(!gGLManager.mHasMapBufferRange);
#endif
{
map_range = false;
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedOffset = mMappedData - src;
stop_glerror();
}
}
if (!mMappedData)
{
log_glerror();
if (!mMappedData)
{
log_glerror();
//check the availability of memory
U32 avail_phy_mem, avail_vir_mem;
LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
//check the availability of memory
U32 avail_phy_mem, avail_vir_mem;
LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ;
llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ;
llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl;
if(!sDisableVBOMapping)
{
//--------------------
//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 ;
//--------------------
if(!sDisableVBOMapping)
{
//--------------------
//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 ((GLuint)buff != mGLBuffer)
{
llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
}
GLint buff;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
if ((GLuint)buff != mGLBuffer)
{
llerrs << "Invalid GL vertex buffer bound: " << buff << llendl;
}
llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
}
else
{
llerrs << "memory allocation for vertex data failed." << llendl ;
llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl;
}
else
{
llerrs << "memory allocation for vertex data failed." << llendl ;
}
}
sMappedCount++;
}
sMappedCount++;
}
else
{
map_range = false;
}
return mMappedData;
if (map_range && !sDisableVBOMapping)
{
return mMappedData;
}
else
{
return mMappedData+mOffsets[type]+sTypeSize[type]*index;
}
}
U8* LLVertexBuffer::mapIndexBuffer(S32 access)
U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER);
if (mFinal)
@ -1023,8 +1112,41 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
}
if (!mIndexLocked && useVBOs())
if (useVBOs())
{
if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
{
if (count == -1)
{
count = mNumIndices-index;
}
bool mapped = false;
//see if range is already mapped
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
MappedRegion& region = mMappedIndexRegions[i];
if (expand_region(region, index, count))
{
mapped = true;
break;
}
}
if (!mapped)
{
//not already mapped, map new region
MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count);
mMappedIndexRegions.push_back(region);
}
}
if (mIndexLocked && map_range)
{
llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl;
}
if (!mIndexLocked)
{
LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
@ -1034,12 +1156,36 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
if(sDisableVBOMapping)
{
map_range = false;
allocateClientIndexBuffer() ;
}
else
{
U8* src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
mMappedIndexData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
U8* src = NULL;
#ifdef GL_ARB_map_buffer_range
if (gGLManager.mHasMapBufferRange)
{
if (map_range)
{
S32 offset = sizeof(U16)*index;
S32 length = sizeof(U16)*count;
src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
}
else
{
src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
}
}
else
#else
llassert_always(!gGLManager.mHasMapBufferRange);
#endif
{
map_range = false;
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
}
mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedIndexOffset = mMappedIndexData - src;
stop_glerror();
}
@ -1068,31 +1214,81 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
sMappedCount++;
}
else
{
map_range = false;
}
return mMappedIndexData ;
if (map_range && !sDisableVBOMapping)
{
return mMappedIndexData;
}
else
{
return mMappedIndexData + sizeof(U16)*index;
}
}
void LLVertexBuffer::unmapBuffer(S32 type)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
if (!useVBOs())
if (!useVBOs() || type == -2)
{
return ; //nothing to unmap
}
bool updated_all = false ;
if (mMappedData && mVertexLocked && type != TYPE_INDEX)
{
updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating
if(sDisableVBOMapping)
{
stop_glerror();
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
stop_glerror();
if (!mMappedVertexRegions.empty())
{
stop_glerror();
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
const MappedRegion& region = mMappedVertexRegions[i];
S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
S32 length = sTypeSize[region.mType]*region.mCount;
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset);
stop_glerror();
}
mMappedVertexRegions.clear();
}
else
{
stop_glerror();
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData);
stop_glerror();
}
}
else
{
#ifdef GL_ARB_map_buffer_range
if (gGLManager.mHasMapBufferRange)
{
if (!mMappedVertexRegions.empty())
{
stop_glerror();
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
{
const MappedRegion& region = mMappedVertexRegions[i];
S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
S32 length = sTypeSize[region.mType]*region.mCount;
glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
stop_glerror();
}
mMappedVertexRegions.clear();
}
}
#else
llassert_always(!gGLManager.mHasMapBufferRange);
#endif
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
@ -1103,17 +1299,53 @@ void LLVertexBuffer::unmapBuffer(S32 type)
mVertexLocked = FALSE ;
sMappedCount--;
}
if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX))
{
if(sDisableVBOMapping)
{
stop_glerror();
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
stop_glerror();
if (!mMappedIndexRegions.empty())
{
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
const MappedRegion& region = mMappedIndexRegions[i];
S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
S32 length = sizeof(U16)*region.mCount;
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset);
stop_glerror();
}
mMappedIndexRegions.clear();
}
else
{
stop_glerror();
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData);
stop_glerror();
}
}
else
{
#ifdef GL_ARB_map_buffer_range
if (gGLManager.mHasMapBufferRange)
{
if (!mMappedIndexRegions.empty())
{
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
{
const MappedRegion& region = mMappedIndexRegions[i];
S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
S32 length = sizeof(U16)*region.mCount;
glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
stop_glerror();
}
mMappedIndexRegions.clear();
}
}
#else
llassert_always(!gGLManager.mHasMapBufferRange);
#endif
stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
@ -1152,19 +1384,19 @@ template <class T,S32 type> struct VertexBufferStrider
typedef LLStrider<T> strider_t;
static bool get(LLVertexBuffer& vbo,
strider_t& strider,
S32 index)
S32 index, S32 count, bool map_range)
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
S32 stride = sizeof(T);
U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
if (vbo.mapIndexBuffer() == NULL)
if (ptr == NULL)
{
llwarns << "mapIndexBuffer failed!" << llendl;
return FALSE;
}
strider = (T*)(vbo.getMappedIndices() + index*stride);
strider = (T*)ptr;
strider.setStride(0);
return TRUE;
}
@ -1172,13 +1404,15 @@ template <class T,S32 type> struct VertexBufferStrider
{
S32 stride = LLVertexBuffer::sTypeSize[type];
if (vbo.mapVertexBuffer(type) == NULL)
U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
if (ptr == NULL)
{
llwarns << "mapVertexBuffer failed!" << llendl;
return FALSE;
}
strider = (T*)(vbo.getMappedData() + vbo.getOffset(type)+index*stride);
strider = (T*)ptr;
strider.setStride(stride);
return TRUE;
}
@ -1190,55 +1424,48 @@ template <class T,S32 type> struct VertexBufferStrider
}
};
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index)
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index);
return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index)
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index);
return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index)
bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index);
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index)
bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index);
}
/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index);
}
bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index)
{
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index);
}*/
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index)
{
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index);
}
bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index)
{
return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index);
}
bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index)
{
return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index);
}
bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
{
return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index)
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index);
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range);
}
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range)
{
return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range);
}
//----------------------------------------------------------------------------
@ -1497,17 +1724,16 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
}
if (data_mask & MAP_VERTEX)
{
glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
if (data_mask & MAP_TEXTURE_INDEX)
{
glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
}
else
{
glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0));
}
}
llglassertok();
}
void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count)
{
// TODO: use GL_APPLE_flush_buffer_range here
/*if (useVBOs() && !mFilthy)
{
}*/
}

View File

@ -77,6 +77,18 @@ protected:
class LLVertexBuffer : public LLRefCount
{
public:
class MappedRegion
{
public:
S32 mType;
S32 mIndex;
S32 mCount;
MappedRegion(S32 type, S32 index, S32 count)
: mType(type), mIndex(index), mCount(count)
{ }
};
LLVertexBuffer(const LLVertexBuffer& rhs)
{
*this = rhs;
@ -130,6 +142,9 @@ public:
TYPE_CLOTHWEIGHT,
TYPE_MAX,
TYPE_INDEX,
//no actual additional data, but indicates position.w is texture index
TYPE_TEXTURE_INDEX,
};
enum {
MAP_VERTEX = (1<<TYPE_VERTEX),
@ -144,6 +159,7 @@ public:
MAP_WEIGHT = (1<<TYPE_WEIGHT),
MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
};
protected:
@ -173,8 +189,8 @@ public:
LLVertexBuffer(U32 typemask, S32 usage);
// map for data access
U8* mapVertexBuffer(S32 type = -1, S32 access = -1);
U8* mapIndexBuffer(S32 access = -1);
U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
// set for rendering
virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0
@ -189,16 +205,16 @@ public:
// vb->getNormalStrider(norms);
// setVertsNorms(verts, norms);
// vb->unmapBuffer();
bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
BOOL isEmpty() const { return mEmpty; }
BOOL isLocked() const { return mVertexLocked || mIndexLocked; }
@ -218,8 +234,6 @@ public:
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count);
void draw(U32 mode, U32 count, U32 indices_offset) const;
void drawArrays(U32 mode, U32 offset, U32 count) const;
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
@ -253,20 +267,8 @@ protected:
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
S32 mOffsets[TYPE_MAX];
class DirtyRegion
{
public:
U32 mIndex;
U32 mCount;
U32 mIndicesIndex;
U32 mIndicesCount;
DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
: mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
{ }
};
std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
std::vector<MappedRegion> mMappedVertexRegions;
std::vector<MappedRegion> mMappedIndexRegions;
public:
static S32 sCount;

View File

@ -337,7 +337,7 @@ LLLocale::LLLocale(const std::string& locale_string)
char* new_locale_string = setlocale( LC_ALL, locale_string.c_str());
if ( new_locale_string == NULL)
{
llwarns << "Failed to set locale " << locale_string << llendl;
LL_WARNS_ONCE("LLLocale") << "Failed to set locale " << locale_string << LL_ENDL;
setlocale(LC_ALL, SYSTEM_LOCALE.c_str());
}
//else

View File

@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
: label_width("label_width"),
decimal_digits("decimal_digits"),
allow_text_entry("allow_text_entry", true),
label_wrap("label_wrap", false),
text_enabled_color("text_enabled_color"),
text_disabled_color("text_disabled_color"),
up_button("up_button"),
@ -80,6 +81,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
{
LLRect label_rect( 0, centered_top, label_width, centered_bottom );
LLTextBox::Params params;
params.wrap(p.label_wrap);
params.name("SpinCtrl Label");
params.rect(label_rect);
params.initial_value(p.label());

View File

@ -44,6 +44,7 @@ public:
Optional<S32> label_width;
Optional<U32> decimal_digits;
Optional<bool> allow_text_entry;
Optional<bool> label_wrap;
Optional<LLUIColor> text_enabled_color;
Optional<LLUIColor> text_disabled_color;

View File

@ -20,6 +20,7 @@
<key>tags</key>
<array>
<string>AppInit</string>
<string>Capabilities</string>
<string>SystemInfo</string>
<string>TextureCache</string>
<string>AppCache</string>
@ -43,6 +44,7 @@
<array>
<!-- sample entry for debugging a specific item -->
<!-- <string>Voice</string> -->
<string>Capabilities</string>
</array>
</map>
</array>

View File

@ -5589,10 +5589,10 @@
<key>Value</key>
<real>0</real>
</map>
<key>MeshUseWholeModelUpload</key>
<key>MeshUploadLogXML</key>
<map>
<key>Comment</key>
<string>Upload model in its entirety instead of mesh-by-mesh (new caps)</string>
<string>Verbose XML logging on mesh upload</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -5600,6 +5600,17 @@
<key>Value</key>
<real>0</real>
</map>
<key>MeshUploadFakeErrors</key>
<map>
<key>Comment</key>
<string>Force upload errors (for testing)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>0</real>
</map>
<key>MigrateCacheDirectory</key>
<map>
<key>Comment</key>
@ -7102,7 +7113,76 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderAnisotropic</key>
<key>OctreeMaxNodeCapacity</key>
<map>
<key>Comment</key>
<string>Maximum number of elements to store in a single octree node</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>128</integer>
</map>
<key>OctreeStaticObjectSizeFactor</key>
<map>
<key>Comment</key>
<string>Multiplier on static object size for determining octree node size </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>OctreeAlphaDistanceFactor</key>
<map>
<key>Comment</key>
<string>Multiplier on alpha object distance for determining octree node size </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
<real>0.1</real>
<real>0.0</real>
<real>0.0</real>
</array>
</map>
<key>OctreeAttachmentSizeFactor</key>
<map>
<key>Comment</key>
<string>Multiplier on attachment size for determining octree node size </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>OctreeDistanceFactor</key>
<map>
<key>Comment</key>
<string>Multiplier on distance for determining octree node size </string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Vector3</string>
<key>Value</key>
<array>
<real>0.01</real>
<real>0.0</real>
<real>0.0</real>
</array>
</map>
<key>RenderAnisotropic</key>
<map>
<key>Comment</key>
<string>Render textures using anisotropic filtering</string>
@ -7199,7 +7279,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>1.0</integer>
<real>1.0</real>
</map>
<key>RenderAvatarVP</key>
<map>
@ -7455,6 +7535,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderMaxTextureIndex</key>
<map>
<key>Comment</key>
<string>Maximum texture index to use for indexed texture rendering.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>6</integer>
</map>
<key>RenderDebugTextureBind</key>
<map>
<key>Comment</key>
@ -8600,7 +8691,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>8192</integer>
<integer>65536</integer>
</map>
<key>RenderMaxVBOSize</key>
<map>
@ -8942,7 +9033,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>0</integer>
</map>
<key>RenderUseStreamVBO</key>
<map>
@ -9052,7 +9143,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>3.0</real>
<real>2.0</real>
</map>
<key>MeshThreadCount</key>
<map>

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
void default_lighting();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
attribute vec4 weight; //1

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
void default_lighting();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
attribute vec4 object_weight;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
mat4 getSkinnedTransform();

View File

@ -5,13 +5,14 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
uniform sampler2DRect depthMap;
vec4 diffuseLookup(vec2 texcoord);
uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
@ -47,7 +48,7 @@ void main()
vec4 pos = vec4(vary_position, 1.0);
vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy);
vec4 diff= diffuseLookup(gl_TexCoord[0].xy);
vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
vec4 color = diff * col;

View File

@ -0,0 +1,67 @@
/**
* @file alphaF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect depthMap;
uniform sampler2D diffuseMap;
uniform mat4 shadow_matrix[6];
uniform vec4 shadow_clip;
uniform vec2 screen_res;
vec3 atmosLighting(vec3 light);
vec3 scaleSoftClip(vec3 light);
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
varying vec3 vary_pointlight_col;
uniform mat4 inv_proj;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
vec4 pos = vec4(vary_position, 1.0);
vec4 diff= texture2D(diffuseMap,gl_TexCoord[0].xy);
vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a);
vec4 color = diff * col;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
color.rgb += diff.rgb * vary_pointlight_col.rgb;
gl_FragColor = color;
//gl_FragColor = vec4(1,0,1,1);
//gl_FragColor = vec4(1,0,1,1)*shadow;
}

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getObjectSkinnedTransform();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
@ -23,6 +23,7 @@ varying vec3 vary_fragcoord;
varying vec3 vary_position;
varying vec3 vary_light;
varying vec3 vary_pointlight_col;
varying float vary_texture_index;
uniform float near_clip;
uniform float shadow_offset;
@ -61,11 +62,13 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
void main()
{
//transform vertex
gl_Position = ftransform();
vec4 vert = vec4(gl_Vertex.xyz, 1.0);
vary_texture_index = gl_Vertex.w;
gl_Position = gl_ModelViewProjectionMatrix * vert;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
vec4 pos = (gl_ModelViewMatrix * vert);
vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
@ -102,7 +105,7 @@ void main()
gl_FogFragCoord = pos.z;
pos = gl_ModelViewProjectionMatrix * gl_Vertex;
pos = gl_ModelViewProjectionMatrix * vert;
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
uniform sampler2D diffuseMap;

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
mat4 getObjectSkinnedTransform();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getSkinnedTransform();

View File

@ -0,0 +1,21 @@
/**
* @file avatarEyesV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
varying vec3 vary_normal;
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;

View File

@ -5,14 +5,17 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;
varying vec4 post_pos;
void main()
{
//gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
gl_FragColor = vec4(1,1,1,1);
gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
}

View File

@ -5,12 +5,14 @@
* $/LicenseInfo$
*/
#version 120
mat4 getSkinnedTransform();
attribute vec4 weight;
varying vec4 post_pos;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
@ -30,8 +32,9 @@ void main()
norm = normalize(norm);
pos = gl_ProjectionMatrix * pos;
pos.z = max(pos.z, -pos.w+0.01);
gl_Position = pos;
post_pos = pos;
gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
gl_FrontColor = gl_Color;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
mat4 getSkinnedTransform();

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
@ -26,7 +26,7 @@ uniform vec2 screen_res;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
@ -39,7 +39,7 @@ vec4 getPosition(vec2 pos_screen)
void main()
{
vec2 tc = vary_fragcoord.xy;
vec2 tc = vary_fragcoord.xy;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
vec3 pos = getPosition(tc).xyz;

View File

@ -0,0 +1,113 @@
/**
* @file blurLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS depthMap;
uniform sampler2DMS normalMap;
uniform sampler2DRect lightMap;
uniform float dist_factor;
uniform float blur_size;
uniform vec2 delta;
uniform vec3 kern[4];
uniform float kern_scale;
varying vec2 vary_fragcoord;
uniform mat4 inv_proj;
uniform vec2 screen_res;
vec3 texture2DMS3(sampler2DMS tex, ivec2 tc)
{
vec3 ret = vec3(0,0,0);
for (int i = 0; i < samples; i++)
{
ret += texelFetch(tex, tc, i).rgb;
}
return ret/samples;
}
float texture2DMS1(sampler2DMS tex, ivec2 tc)
{
float ret = 0;
for (int i = 0; i < samples; i++)
{
ret += texelFetch(tex, tc, i).r;
}
return ret/samples;
}
vec4 getPosition(ivec2 pos_screen)
{
float depth = texture2DMS1(depthMap, pos_screen.xy);
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
vec3 norm = texture2DMS3(normalMap, itc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
vec3 pos = getPosition(itc).xyz;
vec4 ccol = texture2DRect(lightMap, tc).rgba;
vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
dlt /= max(-pos.z*dist_factor, 1.0);
vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
vec4 col = defined_weight.xyxx * ccol;
// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 );
for (int i = 1; i < 4; i++)
{
vec2 samptc = tc + kern[i].z*dlt;
vec3 samppos = getPosition(ivec2(samptc)).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
for (int i = 1; i < 4; i++)
{
vec2 samptc = vec2(tc - kern[i].z*dlt);
vec3 samppos = getPosition(ivec2(samptc)).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
col /= defined_weight.xyxx;
col.y *= col.y;
gl_FragColor = col;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec2 vary_fragcoord;
uniform vec2 screen_res;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
varying vec3 vary_mat0;
varying vec3 vary_mat1;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec3 vary_mat0;
varying vec3 vary_mat1;

View File

@ -0,0 +1,79 @@
/**
* @file WLCloudsF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* $/LicenseInfo$
*/
/////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
varying vec4 vary_CloudColorSun;
varying vec4 vary_CloudColorAmbient;
varying float vary_CloudDensity;
uniform sampler2D cloud_noise_texture;
uniform vec4 cloud_pos_density1;
uniform vec4 cloud_pos_density2;
uniform vec4 gamma;
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light) {
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, gamma.xxx);
return light;
}
void main()
{
// Set variables
vec2 uv1 = gl_TexCoord[0].xy;
vec2 uv2 = gl_TexCoord[1].xy;
vec4 cloudColorSun = vary_CloudColorSun;
vec4 cloudColorAmbient = vary_CloudColorAmbient;
float cloudDensity = vary_CloudDensity;
vec2 uv3 = gl_TexCoord[2].xy;
vec2 uv4 = gl_TexCoord[3].xy;
// Offset texture coords
uv1 += cloud_pos_density1.xy; //large texture, visible density
uv2 += cloud_pos_density1.xy; //large texture, self shadow
uv3 += cloud_pos_density2.xy; //small texture, visible density
uv4 += cloud_pos_density2.xy; //small texture, self shadow
// Compute alpha1, the main cloud opacity
float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z;
alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.);
// And smooth
alpha1 = 1. - alpha1 * alpha1;
alpha1 = 1. - alpha1 * alpha1;
// Compute alpha2, for self shadowing effect
// (1 - alpha2) will later be used as percentage of incoming sunlight
float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5);
alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
// And smooth
alpha2 = 1. - alpha2;
alpha2 = 1. - alpha2 * alpha2;
// Combine
vec4 color;
color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
color *= 2.;
/// Gamma correct for WL (soft clip effect).
gl_FragData[0] = vec4(scaleSoftClip(color.rgb), alpha1);
gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
gl_FragData[2] = vec4(0,0,1,0);
}

View File

@ -0,0 +1,165 @@
/**
* @file WLCloudsV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* $/LicenseInfo$
*/
//////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
///////////////////////////////////////////////////////////////////////////////
// Output parameters
varying vec4 vary_CloudColorSun;
varying vec4 vary_CloudColorAmbient;
varying float vary_CloudDensity;
// Inputs
uniform vec3 camPosLocal;
uniform vec4 lightnorm;
uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
uniform vec4 haze_horizon;
uniform vec4 haze_density;
uniform vec4 cloud_shadow;
uniform vec4 density_multiplier;
uniform vec4 max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
uniform vec4 cloud_scale;
void main()
{
// World / view / projection
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
// Get relative position
vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
// Set altitude
if (P.y > 0.)
{
P *= (max_y.x / P.y);
}
else
{
P *= (-32000. / P.y);
}
// Can normalize then
vec3 Pn = normalize(P);
float Plen = length(P);
// Initialize temp variables
vec4 temp1 = vec4(0.);
vec4 temp2 = vec4(0.);
vec4 blue_weight;
vec4 haze_weight;
vec4 sunlight = sunlight_color;
vec4 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
// Calculate relative weights
temp1 = blue_density + haze_density.x;
blue_weight = blue_density / temp1;
haze_weight = haze_density.x / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
temp2.y = 1. / temp2.y;
sunlight *= exp( - light_atten * temp2.y);
// Distance
temp2.z = Plen * density_multiplier.x;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
// compiler gets confused.
temp1 = exp(-temp1 * temp2.z);
// Compute haze glow
temp2.x = dot(Pn, lightnorm.xyz);
temp2.x = 1. - temp2.x;
// temp2.x is 0 at the sun and increases away from sun
temp2.x = max(temp2.x, .001);
// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
temp2.x *= glow.x;
// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
temp2.x = pow(temp2.x, glow.z);
// glow.z should be negative, so we're doing a sort of (1 / "angle") function
// Add "minimum anti-solar illumination"
temp2.x += .25;
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= (1. - cloud_shadow.x);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// CLOUDS
sunlight = sunlight_color;
temp2.y = max(0., lightnorm.y * 2.);
temp2.y = 1. / temp2.y;
sunlight *= exp( - light_atten * temp2.y);
// Cloud color out
vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
vary_CloudColorAmbient = tmpAmbient * cloud_color;
// Attenuate cloud color by atmosphere
temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
vary_CloudColorSun *= temp1;
vary_CloudColorAmbient *= temp1;
vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
// Make a nice cloud density based on the cloud_shadow value that was passed in.
vary_CloudDensity = 2. * (cloud_shadow.x - 0.25);
// Texture coords
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[0].xy -= 0.5;
gl_TexCoord[0].xy /= cloud_scale.x;
gl_TexCoord[0].xy += 0.5;
gl_TexCoord[1] = gl_TexCoord[0];
gl_TexCoord[1].x += lightnorm.x * 0.0125;
gl_TexCoord[1].y += lightnorm.z * 0.0125;
gl_TexCoord[2] = gl_TexCoord[0] * 16.;
gl_TexCoord[3] = gl_TexCoord[1] * 16.;
// Combine these to minimize register use
vary_CloudColorAmbient += oHazeColorBelowCloud;
// needs this to compile on mac
//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
// END CLOUDS
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;
@ -20,3 +20,4 @@ void main()
vec3 nvn = normalize(vary_normal);
gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
}

View File

@ -0,0 +1,19 @@
/**
* @file diffuseIndexedF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
varying vec3 vary_normal;
void main()
{
vec3 col = gl_Color.rgb * diffuseLookup(gl_TexCoord[0].xy).rgb;
gl_FragData[0] = vec4(col, 0.0);
gl_FragData[1] = gl_Color.aaaa; // spec
//gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(vary_normal);
gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0);
}

View File

@ -5,7 +5,7 @@
* $License$
*/
#version 120
varying vec3 vary_normal;

View File

@ -5,16 +5,18 @@
* $/LicenseInfo$
*/
#version 120
varying vec3 vary_normal;
varying float vary_texture_index;
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
vary_texture_index = gl_Vertex.w;
vary_normal = normalize(gl_NormalMatrix * gl_Normal);
gl_FrontColor = gl_Color;

View File

@ -5,60 +5,24 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
uniform sampler2D diffuseMap;
uniform sampler2DRect depthMap;
uniform sampler2D noiseMap;
uniform vec4 shadow_clip;
uniform vec2 screen_res;
vec3 fullbrightAtmosTransport(vec3 light);
vec3 fullbrightScaleSoftClip(vec3 light);
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec4 vary_position;
varying vec3 vary_normal;
varying vec3 vary_fragcoord;
uniform mat4 inv_proj;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
frag *= screen_res;
vec3 samp_pos = getPosition(frag).xyz;
float shadow = 1.0;
vec4 pos = vary_position;
vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color;
vec4 color = diffuseLookup(gl_TexCoord[0].xy)*gl_Color;
color.rgb = fullbrightAtmosTransport(color.rgb);
color.rgb = fullbrightScaleSoftClip(color.rgb);
//gl_FragColor = gl_Color;
gl_FragColor = color;
//gl_FragColor = vec4(1,0,1,1);
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
void calcAtmospherics(vec3 inPositionEye);
@ -14,30 +14,23 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_normal;
varying vec3 vary_fragcoord;
uniform float near_clip;
varying vec4 vary_position;
varying float vary_texture_index;
void main()
{
//transform vertex
gl_Position = ftransform();
vec4 vert = vec4(gl_Vertex.xyz, 1.0);
vary_texture_index = gl_Vertex.w;
gl_Position = gl_ModelViewProjectionMatrix*vert;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
vary_position = pos;
vec4 pos = (gl_ModelViewMatrix * vert);
calcAtmospherics(pos.xyz);
gl_FrontColor = gl_Color;
gl_FogFragCoord = pos.z;
pos = gl_ModelViewProjectionMatrix * gl_Vertex;
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec2 vary_fragcoord;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
void main()
{

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2DRect diffuseMap;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec2 vary_fragcoord;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
@ -36,7 +36,7 @@ uniform mat4 inv_proj;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);

View File

@ -0,0 +1,137 @@
/**
* @file multiPointLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS depthMap;
uniform sampler2DMS diffuseRect;
uniform sampler2DMS specularRect;
uniform sampler2DMS normalMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform vec3 env_mat[3];
uniform float sun_wash;
uniform int light_count;
#define MAX_LIGHT_COUNT 16
uniform vec4 light[MAX_LIGHT_COUNT];
uniform vec4 light_col[MAX_LIGHT_COUNT];
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform float far_z;
uniform mat4 inv_proj;
vec4 getPosition(ivec2 pos_screen, int sample)
{
float depth = texelFetch(depthMap, pos_screen, sample).r;
vec2 sc = vec2(pos_screen.xy)*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
ivec2 itc = ivec2(frag);
int wght = 0;
vec3 fcol = vec3(0,0,0);
for (int s = 0; s < samples; ++s)
{
vec3 pos = getPosition(itc, s).xyz;
if (pos.z >= far_z)
{
vec3 norm = texelFetch(normalMap, itc, s).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
norm = normalize(norm);
vec4 spec = texelFetch(specularRect, itc, s);
vec3 diff = texelFetch(diffuseRect, itc, s).rgb;
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 out_col = vec3(0,0,0);
vec3 npos = normalize(-pos);
// As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
for (int i = 0; i < MAX_LIGHT_COUNT; ++i)
{
bool light_contrib = (i < light_count);
vec3 lv = light[i].xyz-pos;
float dist2 = dot(lv,lv);
dist2 /= light[i].w;
if (dist2 > 1.0)
{
light_contrib = false;
}
float da = dot(norm, lv);
if (da < 0.0)
{
light_contrib = false;
}
if (light_contrib)
{
lv = normalize(lv);
da = dot(norm, lv);
float fa = light_col[i].a+1.0;
float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
dist_atten *= noise;
float lit = da * dist_atten;
vec3 col = light_col[i].rgb*lit*diff;
//vec3 col = vec3(dist2, light_col[i].a, lit);
if (spec.a > 0.0)
{
//vec3 ref = dot(pos+lv, norm);
float sa = dot(normalize(lv+npos),norm);
if (sa > 0.0)
{
sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
sa *= noise;
col += da*sa*light_col[i].rgb*spec.rgb;
}
}
out_col += col;
}
}
fcol += out_col;
++wght;
}
}
if (wght <= 0)
{
discard;
}
gl_FragColor.rgb = fcol/samples;
gl_FragColor.a = 0.0;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec4 vary_fragcoord;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
//class 1 -- no shadows

View File

@ -0,0 +1,232 @@
/**
* @file multiSpotLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
//class 1 -- no shadows
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS diffuseRect;
uniform sampler2DMS specularRect;
uniform sampler2DMS depthMap;
uniform sampler2DMS normalMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform sampler2D projectionMap;
uniform mat4 proj_mat; //screen space to light space
uniform float proj_near; //near clip for projection
uniform vec3 proj_p; //plane projection is emitting from (in screen space)
uniform vec3 proj_n;
uniform float proj_focus; //distance from plane to begin blurring
uniform float proj_lod; //(number of mips in proj map)
uniform float proj_range; //range between near clip and far clip plane of projection
uniform float proj_ambient_lod;
uniform float proj_ambiance;
uniform float near_clip;
uniform float far_clip;
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
uniform float sun_wash;
uniform float shadow_fade;
varying vec4 vary_light;
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform mat4 inv_proj;
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = tc-vec2(0.5);
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
float d = dot(dist,dist);
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
return ret;
}
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
float det = min(lod/(proj_lod*0.5), 1.0);
float d = min(dist.x, dist.y);
float edge = 0.25*det;
ret *= clamp(d/edge, 0.0, 1.0);
return ret;
}
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = tc-vec2(0.5);
float d = dot(dist,dist);
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
return ret;
}
vec4 getPosition(ivec2 pos_screen, int sample)
{
float depth = texelFetch(depthMap, pos_screen, sample).r;
vec2 sc = vec2(pos_screen.xy)*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
int wght = 0;
vec3 fcol = vec3(0,0,0);
vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
ivec2 itc = ivec2(frag.xy);
for (int i = 0; i < samples; ++i)
{
vec3 pos = getPosition(itc, i).xyz;
vec3 lv = vary_light.xyz-pos.xyz;
float dist2 = dot(lv,lv);
dist2 /= vary_light.w;
if (dist2 <= 1.0)
{
vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
norm = normalize(norm);
float l_dist = -dot(lv, proj_n);
vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
if (proj_tc.z >= 0.0)
{
proj_tc.xyz /= proj_tc.w;
float fa = gl_Color.a+1.0;
float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
if (dist_atten > 0.0)
{
lv = proj_origin-pos.xyz;
lv = normalize(lv);
float da = dot(norm, lv);
vec3 col = vec3(0,0,0);
vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
float noise = texture2D(noiseMap, frag.xy/128.0).b;
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
proj_tc.x > 0.0 &&
proj_tc.y > 0.0)
{
float lit = 0.0;
float amb_da = proj_ambiance;
if (da > 0.0)
{
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
float lod = diff * proj_lod;
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
lit = da * dist_atten * noise;
col = lcol*lit*diff_tex;
amb_da += (da*0.5)*proj_ambiance;
}
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
amb_da += (da*da*0.5+0.5)*proj_ambiance;
amb_da *= dist_atten * noise;
amb_da = min(amb_da, 1.0-lit);
col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
}
vec4 spec = texelFetch(specularRect, itc, i);
if (spec.a > 0.0)
{
vec3 ref = reflect(normalize(pos), norm);
//project from point pos in direction ref to plane proj_p, proj_n
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
if (ds < 0.0)
{
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
if (stc.z > 0.0)
{
stc.xy /= stc.w;
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
if (stc.x < 1.0 &&
stc.y < 1.0 &&
stc.x > 0.0 &&
stc.y > 0.0)
{
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
}
}
}
}
fcol += col;
++wght;
}
}
}
}
if (wght <= 0)
{
discard;
}
gl_FragColor.rgb = fcol/samples;
gl_FragColor.a = 0.0;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
@ -30,7 +30,7 @@ uniform vec4 viewport;
vec4 getPosition(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen.xy).a;
float depth = texture2DRect(depthMap, pos_screen.xy).r;
vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
sc /= viewport.zw;
sc -= vec2(1.0,1.0);

View File

@ -0,0 +1,108 @@
/**
* @file pointLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS depthMap;
uniform sampler2DMS diffuseRect;
uniform sampler2DMS specularRect;
uniform sampler2DMS normalMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform vec3 env_mat[3];
uniform float sun_wash;
varying vec4 vary_light;
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform mat4 inv_proj;
uniform vec4 viewport;
vec4 getPosition(ivec2 pos_screen, int sample)
{
float depth = texelFetch(depthMap, pos_screen, sample).r;
vec2 sc = (vec2(pos_screen.xy)-viewport.xy)*2.0;
sc /= viewport.zw;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
frag.xy *= screen_res;
ivec2 itc = ivec2(frag.xy);
int wght = 0;
vec3 fcol = vec3(0,0,0);
for (int s = 0; s < samples; ++s)
{
vec3 pos = getPosition(itc, s).xyz;
vec3 lv = vary_light.xyz-pos;
float dist2 = dot(lv,lv);
dist2 /= vary_light.w;
if (dist2 <= 1.0)
{
vec3 norm = texelFetch(normalMap, itc, s).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
float da = dot(norm, lv);
if (da >= 0.0)
{
norm = normalize(norm);
lv = normalize(lv);
da = dot(norm, lv);
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 col = texelFetch(diffuseRect, itc, s).rgb;
float fa = gl_Color.a+1.0;
float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
float lit = da * dist_atten * noise;
col = gl_Color.rgb*lit*col;
vec4 spec = texelFetch(specularRect, itc, s);
if (spec.a > 0.0)
{
float sa = dot(normalize(lv-normalize(pos)),norm);
if (sa > 0.0)
{
sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
sa *= noise;
col += da*sa*gl_Color.rgb*spec.rgb;
}
}
fcol += col;
++wght;
}
}
}
if (wght <= 0)
{
discard;
}
gl_FragColor.rgb = fcol/samples;
gl_FragColor.a = 0.0;
}

View File

@ -5,19 +5,14 @@
* $/LicenseInfo$
*/
#version 120
varying vec4 vary_light;
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform float near_clip;
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
vary_fragcoord = pos;
@ -25,6 +20,8 @@ void main()
tex.w = 1.0;
vary_light = gl_MultiTexCoord0;
gl_Position = pos;
gl_FrontColor = gl_Color;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
@ -29,7 +29,7 @@ varying vec2 vary_fragcoord;
float getDepth(vec2 pos_screen)
{
float z = texture2DRect(depthMap, pos_screen.xy).a;
float z = texture2DRect(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;

View File

@ -0,0 +1,133 @@
/**
* @file postDeferredF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS diffuseRect;
uniform sampler2DMS edgeMap;
uniform sampler2DMS depthMap;
uniform sampler2DMS normalMap;
uniform sampler2D bloomMap;
uniform float depth_cutoff;
uniform float norm_cutoff;
uniform float focal_distance;
uniform float blur_constant;
uniform float tan_pixel_angle;
uniform float magnification;
uniform mat4 inv_proj;
uniform vec2 screen_res;
varying vec2 vary_fragcoord;
vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
{
vec4 ret = vec4(0,0,0,0);
for (int i = 0; i < samples; ++i)
{
ret += texelFetch(tex, tc, i);
}
return ret/samples;
}
float getDepth(ivec2 pos_screen)
{
float z = texture2DMS(depthMap, pos_screen.xy).r;
z = z*2.0-1.0;
vec4 ndc = vec4(0.0, 0.0, z, 1.0);
vec4 p = inv_proj*ndc;
return p.z/p.w;
}
float calc_cof(float depth)
{
float sc = abs(depth-focal_distance)/-depth*blur_constant;
sc /= magnification;
// tan_pixel_angle = pixel_length/-depth;
float pixel_length = tan_pixel_angle*-focal_distance;
sc = sc/pixel_length;
sc *= 1.414;
return sc;
}
void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, ivec2 tc)
{
float d = getDepth(tc);
float sc = calc_cof(d);
if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
|| d < cur_depth) //sampled pixel is further away than current pixel
{
float wg = 0.25;
vec4 s = texture2DMS(diffuseRect, tc);
// de-weight dull areas to make highlights 'pop'
wg += s.r+s.g+s.b;
diff += wg*s;
w += wg;
}
}
void main()
{
ivec2 itc = ivec2(vary_fragcoord.xy);
vec3 norm = texture2DMS(normalMap, itc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
float depth = getDepth(itc);
vec4 diff = texture2DMS(diffuseRect, itc);
{
float w = 1.0;
float sc = calc_cof(depth);
sc = min(abs(sc), 10.0);
float fd = depth*0.5f;
float PI = 3.14159265358979323846264;
int isc = int(sc);
// sample quite uniformly spaced points within a circle, for a circular 'bokeh'
//if (depth < focal_distance)
{
for (int x = -isc; x <= isc; x+=2)
{
for (int y = -isc; y <= isc; y+=2)
{
ivec2 cur_samp = ivec2(x,y);
float cur_sc = length(vec2(cur_samp));
if (cur_sc < sc)
{
dofSample(diff, w, cur_sc, depth, itc+cur_samp);
}
}
}
}
diff /= w;
}
vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
gl_FragColor = diff + bloom;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable

View File

@ -0,0 +1,37 @@
/**
* @file postDeferredF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS diffuseRect;
uniform sampler2D bloomMap;
uniform vec2 screen_res;
varying vec2 vary_fragcoord;
vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
{
vec4 ret = vec4(0,0,0,0);
for (int i = 0; i < samples; ++i)
{
ret += texelFetch(tex,tc,i);
}
return ret/samples;
}
void main()
{
vec4 diff = texture2DMS(diffuseRect, ivec2(vary_fragcoord.xy));
vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
gl_FragColor = diff + bloom;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec2 vary_fragcoord;
uniform vec2 screen_res;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec2 vary_fragcoord;
uniform vec2 screen_res;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform sampler2D diffuseMap;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
varying vec4 post_pos;

View File

@ -0,0 +1,44 @@
/**
* @file WLSkyF.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* $/LicenseInfo$
*/
/////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
varying vec4 vary_HazeColor;
uniform sampler2D cloud_noise_texture;
uniform vec4 gamma;
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light) {
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, gamma.xxx);
return light;
}
void main()
{
// Potential Fill-rate optimization. Add cloud calculation
// back in and output alpha of 0 (so that alpha culling kills
// the fragment) if the sky wouldn't show up because the clouds
// are fully opaque.
vec4 color;
color = vary_HazeColor;
color *= 2.;
/// Gamma correct for WL (soft clip effect).
gl_FragData[0] = vec4(scaleSoftClip(color.rgb), 1.0);
gl_FragData[1] = vec4(0.0,0.0,0.0,0.0);
gl_FragData[2] = vec4(0,0,1,0);
}

View File

@ -0,0 +1,140 @@
/**
* @file WLSkyV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* $/LicenseInfo$
*/
// SKY ////////////////////////////////////////////////////////////////////////
// The vertex shader for creating the atmospheric sky
///////////////////////////////////////////////////////////////////////////////
// Output parameters
varying vec4 vary_HazeColor;
// Inputs
uniform vec3 camPosLocal;
uniform vec4 lightnorm;
uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
uniform vec4 haze_horizon;
uniform vec4 haze_density;
uniform vec4 cloud_shadow;
uniform vec4 density_multiplier;
uniform vec4 max_y;
uniform vec4 glow;
uniform vec4 cloud_color;
uniform vec4 cloud_scale;
void main()
{
// World / view / projection
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
// Get relative position
vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0);
//vec3 P = gl_Vertex.xyz + vec3(0,50,0);
// Set altitude
if (P.y > 0.)
{
P *= (max_y.x / P.y);
}
else
{
P *= (-32000. / P.y);
}
// Can normalize then
vec3 Pn = normalize(P);
float Plen = length(P);
// Initialize temp variables
vec4 temp1 = vec4(0.);
vec4 temp2 = vec4(0.);
vec4 blue_weight;
vec4 haze_weight;
vec4 sunlight = sunlight_color;
vec4 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x);
// Calculate relative weights
temp1 = blue_density + haze_density.x;
blue_weight = blue_density / temp1;
haze_weight = haze_density.x / temp1;
// Compute sunlight from P & lightnorm (for long rays like sky)
temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
temp2.y = 1. / temp2.y;
sunlight *= exp( - light_atten * temp2.y);
// Distance
temp2.z = Plen * density_multiplier.x;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
// compiler gets confused.
temp1 = exp(-temp1 * temp2.z);
// Compute haze glow
temp2.x = dot(Pn, lightnorm.xyz);
temp2.x = 1. - temp2.x;
// temp2.x is 0 at the sun and increases away from sun
temp2.x = max(temp2.x, .001);
// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
temp2.x *= glow.x;
// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
temp2.x = pow(temp2.x, glow.z);
// glow.z should be negative, so we're doing a sort of (1 / "angle") function
// Add "minimum anti-solar illumination"
temp2.x += .25;
// Haze color above cloud
vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient)
+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient)
);
// Increase ambient when there are more clouds
vec4 tmpAmbient = ambient;
tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= (1. - cloud_shadow.x);
// Haze color below cloud
vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient)
+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient)
);
// Final atmosphere additive
vary_HazeColor *= (1. - temp1);
// Attenuate cloud color by atmosphere
temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1));
// won't compile on mac without this being set
//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
@ -259,7 +259,7 @@ vec3 scaleSoftClip(vec3 light)
void main()
{
vec2 tc = vary_fragcoord.xy;
float depth = texture2DRect(depthMap, tc.xy).a;
float depth = texture2DRect(depthMap, tc.xy).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm

View File

@ -0,0 +1,318 @@
/**
* @file softenLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS diffuseRect;
uniform sampler2DMS specularRect;
uniform sampler2DMS normalMap;
uniform sampler2DMS depthMap;
uniform sampler2D noiseMap;
uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
uniform float blur_size;
uniform float blur_fidelity;
// Inputs
uniform vec4 morphFactor;
uniform vec3 camPosLocal;
//uniform vec4 camPosWorld;
uniform vec4 gamma;
uniform vec4 lightnorm;
uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
uniform vec4 haze_horizon;
uniform vec4 haze_density;
uniform vec4 cloud_shadow;
uniform vec4 density_multiplier;
uniform vec4 distance_multiplier;
uniform vec4 max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform vec3 env_mat[3];
//uniform mat4 shadow_matrix[3];
//uniform vec4 shadow_clip;
uniform mat3 ssao_effect_mat;
varying vec4 vary_light;
varying vec2 vary_fragcoord;
vec3 vary_PositionEye;
vec3 vary_SunlitColor;
vec3 vary_AmblitColor;
vec3 vary_AdditiveColor;
vec3 vary_AtmosAttenuation;
uniform mat4 inv_proj;
uniform vec2 screen_res;
vec4 getPosition_d(vec2 pos_screen, float depth)
{
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
vec3 getPositionEye()
{
return vary_PositionEye;
}
vec3 getSunlitColor()
{
return vary_SunlitColor;
}
vec3 getAmblitColor()
{
return vary_AmblitColor;
}
vec3 getAdditiveColor()
{
return vary_AdditiveColor;
}
vec3 getAtmosAttenuation()
{
return vary_AtmosAttenuation;
}
void setPositionEye(vec3 v)
{
vary_PositionEye = v;
}
void setSunlitColor(vec3 v)
{
vary_SunlitColor = v;
}
void setAmblitColor(vec3 v)
{
vary_AmblitColor = v;
}
void setAdditiveColor(vec3 v)
{
vary_AdditiveColor = v;
}
void setAtmosAttenuation(vec3 v)
{
vary_AtmosAttenuation = v;
}
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
vec3 P = inPositionEye;
setPositionEye(P);
//(TERRAIN) limit altitude
if (P.y > max_y.x) P *= (max_y.x / P.y);
if (P.y < -max_y.x) P *= (-max_y.x / P.y);
vec3 tmpLightnorm = lightnorm.xyz;
vec3 Pn = normalize(P);
float Plen = length(P);
vec4 temp1 = vec4(0);
vec3 temp2 = vec3(0);
vec4 blue_weight;
vec4 haze_weight;
vec4 sunlight = sunlight_color;
vec4 light_atten;
//sunlight attenuation effect (hue and brightness) due to atmosphere
//this is used later for sunlight modulation at various altitudes
light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
//I had thought blue_density and haze_density should have equal weighting,
//but attenuation due to haze_density tends to seem too strong
temp1 = blue_density + vec4(haze_density.r);
blue_weight = blue_density / temp1;
haze_weight = vec4(haze_density.r) / temp1;
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
temp2.y = max(0.0, tmpLightnorm.y);
temp2.y = 1. / temp2.y;
sunlight *= exp( - light_atten * temp2.y);
// main atmospheric scattering line integral
temp2.z = Plen * density_multiplier.x;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
// compiler gets confused.
temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
//final atmosphere attenuation factor
setAtmosAttenuation(temp1.rgb);
//compute haze glow
//(can use temp2.x as temp because we haven't used it yet)
temp2.x = dot(Pn, tmpLightnorm.xyz);
temp2.x = 1. - temp2.x;
//temp2.x is 0 at the sun and increases away from sun
temp2.x = max(temp2.x, .03); //was glow.y
//set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
temp2.x *= glow.x;
//higher glow.x gives dimmer glow (because next step is 1 / "angle")
temp2.x = pow(temp2.x, glow.z);
//glow.z should be negative, so we're doing a sort of (1 / "angle") function
//add "minimum anti-solar illumination"
temp2.x += .25;
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
* // The following line of code performs the equivalent of:
* float ambAlpha = tmpAmbient.a;
* float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
* vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
* tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
*/
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
setSunlitColor(vec3(sunlight * .5));
setAmblitColor(vec3(tmpAmbient * .25));
setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
}
vec3 atmosLighting(vec3 light)
{
light *= getAtmosAttenuation().r;
light += getAdditiveColor();
return (2.0 * light);
}
vec3 atmosTransport(vec3 light) {
light *= getAtmosAttenuation().r;
light += getAdditiveColor() * 2.0;
return light;
}
vec3 atmosGetDiffuseSunlightColor()
{
return getSunlitColor();
}
vec3 scaleDownLight(vec3 light)
{
return (light / scene_light_strength );
}
vec3 scaleUpLight(vec3 light)
{
return (light * scene_light_strength);
}
vec3 atmosAmbient(vec3 light)
{
return getAmblitColor() + light / 2.0;
}
vec3 atmosAffectDirectionalLight(float lightIntensity)
{
return getSunlitColor() * lightIntensity;
}
vec3 scaleSoftClip(vec3 light)
{
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, gamma.xxx);
return light;
}
vec4 texture2DMS(sampler2DMS tex, ivec2 tc)
{
vec4 ret = vec4(0,0,0,0);
for (int i = 0; i < samples; ++i)
{
ret += texelFetch(tex,tc,i);
}
return ret/samples;
}
void main()
{
vec2 tc = vary_fragcoord.xy;
ivec2 itc = ivec2(tc);
vec3 fcol = vec3(0,0,0);
for (int i = 0; i < samples; ++i)
{
float depth = texelFetch(depthMap, itc, i).r;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texelFetch(normalMap, itc, i).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texelFetch(diffuseRect, itc, i);
if (diffuse.a >= 1.0)
{
fcol += diffuse.rgb;
}
else
{
vec4 spec = texelFetch(specularRect, itc, i);
calcAtmospherics(pos.xyz, 1.0);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
// add the two types of shiny together
col += dumbshiny * spec.rgb;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
fcol += col;
}
}
gl_FragColor.rgb = fcol.rgb/samples;
gl_FragColor.a = 0.0;
}

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
uniform vec2 screen_res;

View File

@ -5,7 +5,7 @@
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable

View File

@ -0,0 +1,234 @@
/**
* @file multiSpotLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
//class 1 -- no shadows
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_texture_multisample : enable
uniform sampler2DMS diffuseRect;
uniform sampler2DMS specularRect;
uniform sampler2DMS depthMap;
uniform sampler2DMS normalMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform sampler2D projectionMap;
uniform mat4 proj_mat; //screen space to light space
uniform float proj_near; //near clip for projection
uniform vec3 proj_p; //plane projection is emitting from (in screen space)
uniform vec3 proj_n;
uniform float proj_focus; //distance from plane to begin blurring
uniform float proj_lod; //(number of mips in proj map)
uniform float proj_range; //range between near clip and far clip plane of projection
uniform float proj_ambient_lod;
uniform float proj_ambiance;
uniform float near_clip;
uniform float far_clip;
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
uniform float sun_wash;
uniform int proj_shadow_idx;
uniform float shadow_fade;
varying vec4 vary_light;
varying vec4 vary_fragcoord;
uniform vec2 screen_res;
uniform mat4 inv_proj;
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = tc-vec2(0.5);
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
float d = dot(dist,dist);
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
return ret;
}
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
float det = min(lod/(proj_lod*0.5), 1.0);
float d = min(dist.x, dist.y);
float edge = 0.25*det;
ret *= clamp(d/edge, 0.0, 1.0);
return ret;
}
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
vec2 dist = tc-vec2(0.5);
float d = dot(dist,dist);
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
return ret;
}
vec4 getPosition(ivec2 pos_screen, int sample)
{
float depth = texelFetch(depthMap, pos_screen, sample).r;
vec2 sc = vec2(pos_screen.xy)*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
void main()
{
vec4 frag = vary_fragcoord;
frag.xyz /= frag.w;
frag.xyz = frag.xyz*0.5+0.5;
frag.xy *= screen_res;
ivec2 itc = ivec2(frag.xy);
vec3 fcol = vec3(0,0,0);
int wght = 0;
for (int i = 0; i < samples; ++i)
{
vec3 pos = getPosition(itc, i).xyz;
vec3 lv = vary_light.xyz-pos.xyz;
float dist2 = dot(lv,lv);
dist2 /= vary_light.w;
if (dist2 <= 1.0)
{
vec3 norm = texelFetch(normalMap, itc, i).xyz*2.0-1.0;
norm = normalize(norm);
float l_dist = -dot(lv, proj_n);
vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
if (proj_tc.z >= 0.0)
{
proj_tc.xyz /= proj_tc.w;
float fa = gl_Color.a+1.0;
float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
if (dist_atten > 0.0)
{
lv = proj_origin-pos.xyz;
lv = normalize(lv);
float da = dot(norm, lv);
vec3 col = vec3(0,0,0);
vec3 diff_tex = texelFetch(diffuseRect, itc, i).rgb;
float noise = texture2D(noiseMap, frag.xy/128.0).b;
if (proj_tc.z > 0.0 &&
proj_tc.x < 1.0 &&
proj_tc.y < 1.0 &&
proj_tc.x > 0.0 &&
proj_tc.y > 0.0)
{
float lit = 0.0;
float amb_da = proj_ambiance;
if (da > 0.0)
{
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
float lod = diff * proj_lod;
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
lit = da * dist_atten * noise;
col = lcol*lit*diff_tex;
amb_da += (da*0.5)*proj_ambiance;
}
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
amb_da += (da*da*0.5+0.5)*proj_ambiance;
amb_da *= dist_atten * noise;
amb_da = min(amb_da, 1.0-lit);
col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
}
vec4 spec = texelFetch(specularRect, itc, i);
if (spec.a > 0.0)
{
vec3 ref = reflect(normalize(pos), norm);
//project from point pos in direction ref to plane proj_p, proj_n
vec3 pdelta = proj_p-pos;
float ds = dot(ref, proj_n);
if (ds < 0.0)
{
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
if (stc.z > 0.0)
{
stc.xy /= stc.w;
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
if (stc.x < 1.0 &&
stc.y < 1.0 &&
stc.x > 0.0 &&
stc.y > 0.0)
{
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
}
}
}
}
fcol += col;
++wght;
}
}
}
}
if (wght <= 0)
{
discard;
}
gl_FragColor.rgb = fcol/samples;
gl_FragColor.a = 0.0;
}

View File

@ -0,0 +1,19 @@
/**
* @file starsF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
uniform sampler2D diffuseMap;
void main()
{
vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy);
gl_FragData[0] = col;
gl_FragData[1] = vec4(0,0,0,0);
gl_FragData[2] = vec4(0,0,1,0);
}

View File

@ -0,0 +1,17 @@
/**
* @file starsV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
void main()
{
//transform vertex
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}

Some files were not shown because too many files have changed in this diff Show More