Merge branch 'master' of https://github.com/singularity-viewer/SingularityViewer
This commit is contained in:
@@ -484,7 +484,9 @@ LLJoint* LLKeyframeMotion::getJoint(U32 index)
|
|||||||
index = (S32)mJointStates.size() - 1;
|
index = (S32)mJointStates.size() - 1;
|
||||||
// </edit>
|
// </edit>
|
||||||
LLJoint* joint = mJointStates[index]->getJoint();
|
LLJoint* joint = mJointStates[index]->getJoint();
|
||||||
llassert_always (joint);
|
if(!joint) {
|
||||||
|
LL_WARNS_ONCE("Animation") << "Missing joint index:"<< index << " ID:" << mID << " Name:" << mName << LL_ENDL;
|
||||||
|
}
|
||||||
return joint;
|
return joint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -554,7 +554,7 @@ bool LLApp::isQuitting()
|
|||||||
// static
|
// static
|
||||||
bool LLApp::isExiting()
|
bool LLApp::isExiting()
|
||||||
{
|
{
|
||||||
return isQuitting() || isError();
|
return isQuitting() || isError() || isStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLApp::disableCrashlogger()
|
void LLApp::disableCrashlogger()
|
||||||
|
|||||||
@@ -1177,6 +1177,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||||||
mReservedUniforms.push_back("depth_cutoff");
|
mReservedUniforms.push_back("depth_cutoff");
|
||||||
mReservedUniforms.push_back("norm_cutoff");
|
mReservedUniforms.push_back("norm_cutoff");
|
||||||
mReservedUniforms.push_back("shadow_target_width");
|
mReservedUniforms.push_back("shadow_target_width");
|
||||||
|
mReservedUniforms.push_back("downsampled_depth_scale");
|
||||||
|
|
||||||
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
|
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
|
||||||
|
|
||||||
@@ -1195,6 +1196,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||||||
mReservedUniforms.push_back("dof_height");
|
mReservedUniforms.push_back("dof_height");
|
||||||
|
|
||||||
mReservedUniforms.push_back("depthMap");
|
mReservedUniforms.push_back("depthMap");
|
||||||
|
mReservedUniforms.push_back("depthMapDownsampled");
|
||||||
mReservedUniforms.push_back("shadowMap0");
|
mReservedUniforms.push_back("shadowMap0");
|
||||||
mReservedUniforms.push_back("shadowMap1");
|
mReservedUniforms.push_back("shadowMap1");
|
||||||
mReservedUniforms.push_back("shadowMap2");
|
mReservedUniforms.push_back("shadowMap2");
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ public:
|
|||||||
DEFERRED_DEPTH_CUTOFF,
|
DEFERRED_DEPTH_CUTOFF,
|
||||||
DEFERRED_NORM_CUTOFF,
|
DEFERRED_NORM_CUTOFF,
|
||||||
DEFERRED_SHADOW_TARGET_WIDTH,
|
DEFERRED_SHADOW_TARGET_WIDTH,
|
||||||
|
DEFERRED_DOWNSAMPLED_DEPTH_SCALE,
|
||||||
|
|
||||||
FXAA_TC_SCALE,
|
FXAA_TC_SCALE,
|
||||||
FXAA_RCP_SCREEN_RES,
|
FXAA_RCP_SCREEN_RES,
|
||||||
@@ -152,6 +153,7 @@ public:
|
|||||||
DOF_HEIGHT,
|
DOF_HEIGHT,
|
||||||
|
|
||||||
DEFERRED_DEPTH,
|
DEFERRED_DEPTH,
|
||||||
|
DEFERRED_DOWNSAMPLED_DEPTH,
|
||||||
DEFERRED_SHADOW0,
|
DEFERRED_SHADOW0,
|
||||||
DEFERRED_SHADOW1,
|
DEFERRED_SHADOW1,
|
||||||
DEFERRED_SHADOW2,
|
DEFERRED_SHADOW2,
|
||||||
|
|||||||
@@ -229,5 +229,16 @@
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<real>1</real>
|
<real>1</real>
|
||||||
</map>
|
</map>
|
||||||
|
<key>SHRenderSSAOResolutionScale</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>SSAO resolution scale. Valid values: 0.01-1.0</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>F32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>.5</real>
|
||||||
|
</map>
|
||||||
</map>
|
</map>
|
||||||
</llsd>
|
</llsd>
|
||||||
|
|||||||
140
indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl
Normal file
140
indra/newview/app_settings/shaders/class1/deferred/SSAOF.glsl
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* @file sunLightF.glsl
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2007, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#extension GL_ARB_texture_rectangle : enable
|
||||||
|
|
||||||
|
#ifdef DEFINE_GL_FRAGCOLOR
|
||||||
|
out vec4 frag_color;
|
||||||
|
#else
|
||||||
|
#define frag_color gl_FragColor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VARYING vec2 vary_fragcoord;
|
||||||
|
|
||||||
|
uniform sampler2DRect depthMapDownsampled;
|
||||||
|
uniform sampler2DRect normalMap;
|
||||||
|
uniform sampler2D noiseMap;
|
||||||
|
|
||||||
|
uniform vec2 screen_res;
|
||||||
|
uniform mat4 inv_proj;
|
||||||
|
|
||||||
|
uniform float downsampled_depth_scale;
|
||||||
|
|
||||||
|
uniform float ssao_radius;
|
||||||
|
uniform float ssao_max_radius;
|
||||||
|
uniform float ssao_factor;
|
||||||
|
|
||||||
|
vec3 decode_normal (vec2 enc)
|
||||||
|
{
|
||||||
|
vec2 fenc = enc*4-2;
|
||||||
|
float f = dot(fenc,fenc);
|
||||||
|
float g = sqrt(1-f/4);
|
||||||
|
vec3 n;
|
||||||
|
n.xy = fenc*g;
|
||||||
|
n.z = 1-f/2;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getPosition(vec2 pos_screen)
|
||||||
|
{
|
||||||
|
float depth = texture2DRect(depthMapDownsampled, pos_screen.xy*downsampled_depth_scale).r;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 getKern(int i)
|
||||||
|
{
|
||||||
|
vec2 kern[8];
|
||||||
|
// exponentially (^2) distant occlusion samples spread around origin
|
||||||
|
kern[0] = vec2(-1.0, 0.0) * (0.125*0.125*.9+.1);
|
||||||
|
kern[1] = vec2(1.0, 0.0) * (0.250*0.250*.9+.1);
|
||||||
|
kern[2] = vec2(0.0, 1.0) * (0.375*0.375*.9+.1);
|
||||||
|
kern[3] = vec2(0.0, -1.0) * (0.500*0.500*.9+.1);
|
||||||
|
kern[4] = vec2(0.7071, 0.7071) * (0.625*0.625*.9+.1);
|
||||||
|
kern[5] = vec2(-0.7071, -0.7071) * (0.750*0.750*.9+.1);
|
||||||
|
kern[6] = vec2(-0.7071, 0.7071) * (0.875*0.875*.9+.1);
|
||||||
|
kern[7] = vec2(0.7071, -0.7071) * (1.000*1.000*.9+.1);
|
||||||
|
|
||||||
|
return kern[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculate decreases in ambient lighting when crowded out (SSAO)
|
||||||
|
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||||
|
{
|
||||||
|
vec2 pos_screen = vary_fragcoord.xy;
|
||||||
|
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
||||||
|
|
||||||
|
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
|
||||||
|
float points = 1.0;
|
||||||
|
float angle_hidden = 0.0;
|
||||||
|
|
||||||
|
// use a kernel scale that diminishes with distance.
|
||||||
|
// a scale of less than 32 is just wasting good samples, though.
|
||||||
|
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
|
||||||
|
|
||||||
|
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
|
||||||
|
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
||||||
|
|
||||||
|
vec3 diff = samppos_world - pos.xyz;
|
||||||
|
|
||||||
|
if (diff.z < ssao_factor && diff.z != 0.0)
|
||||||
|
{
|
||||||
|
float dist = length(diff);
|
||||||
|
float angrel = max(0.0, dot(norm.xyz, diff/dist));
|
||||||
|
float distrel = 1.0/(1.0+dist*dist);
|
||||||
|
float samplehidden = min(angrel, distrel);
|
||||||
|
|
||||||
|
angle_hidden += (samplehidden);
|
||||||
|
points += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
angle_hidden /= points;
|
||||||
|
float rtn = (1.0 - angle_hidden);
|
||||||
|
return (rtn * rtn) * (rtn * rtn); //Pow2 to increase darkness to match previous behavior.
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 pos_screen = vary_fragcoord.xy;
|
||||||
|
|
||||||
|
//try doing an unproject here
|
||||||
|
|
||||||
|
vec4 pos = getPosition(pos_screen);
|
||||||
|
|
||||||
|
vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
|
||||||
|
norm = decode_normal(norm.xy);
|
||||||
|
|
||||||
|
frag_color = vec4(calcAmbientOcclusion(pos,norm),0,0,0);
|
||||||
|
}
|
||||||
@@ -51,7 +51,6 @@ uniform float max_y;
|
|||||||
uniform vec4 glow;
|
uniform vec4 glow;
|
||||||
uniform float scene_light_strength;
|
uniform float scene_light_strength;
|
||||||
uniform mat3 env_mat;
|
uniform mat3 env_mat;
|
||||||
uniform mat3 ssao_effect_mat;
|
|
||||||
|
|
||||||
uniform vec3 sun_dir;
|
uniform vec3 sun_dir;
|
||||||
|
|
||||||
@@ -312,7 +311,7 @@ void setAtmosAttenuation(vec3 v)
|
|||||||
vary_AtmosAttenuation = v;
|
vary_AtmosAttenuation = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
void calcAtmospherics(vec3 inPositionEye) {
|
||||||
|
|
||||||
vec3 P = inPositionEye;
|
vec3 P = inPositionEye;
|
||||||
setPositionEye(P);
|
setPositionEye(P);
|
||||||
@@ -373,16 +372,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
|||||||
//increase ambient when there are more clouds
|
//increase ambient when there are more clouds
|
||||||
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
|
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 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
|
//haze color
|
||||||
setAdditiveColor(
|
setAdditiveColor(
|
||||||
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
|
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
|
||||||
@@ -568,7 +557,7 @@ void main()
|
|||||||
|
|
||||||
vec3 norm = vary_norm;
|
vec3 norm = vary_norm;
|
||||||
|
|
||||||
calcAtmospherics(pos.xyz, 1.0);
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
vec2 abnormal = encode_normal(norm.xyz);
|
vec2 abnormal = encode_normal(norm.xyz);
|
||||||
norm.xyz = decode_normal(abnormal.xy);
|
norm.xyz = decode_normal(abnormal.xy);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ uniform sampler2DRect lightMap;
|
|||||||
uniform float dist_factor;
|
uniform float dist_factor;
|
||||||
uniform float blur_size;
|
uniform float blur_size;
|
||||||
uniform vec2 delta;
|
uniform vec2 delta;
|
||||||
uniform vec3 kern[4];
|
//uniform vec3 kern[4];
|
||||||
uniform float kern_scale;
|
uniform float kern_scale;
|
||||||
|
|
||||||
VARYING vec2 vary_fragcoord;
|
VARYING vec2 vary_fragcoord;
|
||||||
@@ -46,8 +46,14 @@ VARYING vec2 vary_fragcoord;
|
|||||||
uniform mat4 inv_proj;
|
uniform mat4 inv_proj;
|
||||||
uniform vec2 screen_res;
|
uniform vec2 screen_res;
|
||||||
|
|
||||||
vec3 getKern(int i)
|
vec2 getKern(int i)
|
||||||
{
|
{
|
||||||
|
vec2 kern[4];
|
||||||
|
|
||||||
|
kern[0] = vec2(0.3989422804,0.1994711402);
|
||||||
|
kern[1] = vec2(0.2419707245,0.1760326634);
|
||||||
|
kern[2] = vec2(0.0539909665,0.1209853623);
|
||||||
|
kern[3] = vec2(0.0044318484,0.0647587978);
|
||||||
return kern[i];
|
return kern[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,33 +108,37 @@ void main()
|
|||||||
// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
|
// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
|
||||||
vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5
|
vec2 tc_v = fract(0.5 * tc.xy); // we now have floor(mod(tc,2.0))*0.5
|
||||||
float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard
|
float tc_mod = 2.0 * abs(tc_v.x - tc_v.y); // diff of x,y makes checkerboard
|
||||||
tc += ( (tc_mod - 0.5) * getKern(1).z * dlt * 0.5 );
|
tc += ( (tc_mod - 0.5) * dlt * 0.5 );
|
||||||
|
|
||||||
for (int i = 1; i < 4; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
vec2 samptc = (tc + getKern(i).z * dlt);
|
vec2 samptc = (tc + i * dlt);
|
||||||
vec3 samppos = getPosition(samptc).xyz;
|
vec3 samppos = getPosition(samptc).xyz;
|
||||||
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
||||||
|
|
||||||
if (d*d <= pointplanedist_tolerance_pow2)
|
if (d*d <= pointplanedist_tolerance_pow2)
|
||||||
{
|
{
|
||||||
col += texture2DRect(lightMap, samptc)*getKern(i).xyxx;
|
vec4 weight = getKern(i).xyxx;
|
||||||
defined_weight += getKern(i).xy;
|
col += texture2DRect(lightMap, samptc)*weight;
|
||||||
|
defined_weight += weight.xy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 1; i < 4; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
vec2 samptc = (tc - getKern(i).z * dlt);
|
vec2 samptc = (tc - i * dlt);
|
||||||
vec3 samppos = getPosition(samptc).xyz;
|
vec3 samppos = getPosition(samptc).xyz;
|
||||||
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
||||||
|
|
||||||
if (d*d <= pointplanedist_tolerance_pow2)
|
if (d*d <= pointplanedist_tolerance_pow2)
|
||||||
{
|
{
|
||||||
col += texture2DRect(lightMap, samptc)*getKern(i).xyxx;
|
vec4 weight = getKern(i).xyxx;
|
||||||
defined_weight += getKern(i).xy;
|
col += texture2DRect(lightMap, samptc)*weight;
|
||||||
|
defined_weight += weight.xy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
col /= defined_weight.xyxx;
|
col /= defined_weight.xyxx;
|
||||||
col.y *= col.y; // delinearize SSAO effect post-blur
|
//col.y *= col.y; // delinearize SSAO effect post-blur // Singu note: Performed pre-blur as to remove blur requirement
|
||||||
|
|
||||||
frag_color = col;
|
frag_color = col;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @file sunLightF.glsl
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2007, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#extension GL_ARB_texture_rectangle : enable
|
||||||
|
|
||||||
|
#ifdef DEFINE_GL_FRAGCOLOR
|
||||||
|
out vec4 frag_color;
|
||||||
|
#else
|
||||||
|
#define frag_color gl_FragColor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2DRect depthMap;
|
||||||
|
|
||||||
|
VARYING vec2 vary_fragcoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragDepth = texture2DRect(depthMap, vary_fragcoord.xy).r;
|
||||||
|
}
|
||||||
@@ -134,7 +134,6 @@ uniform float max_y;
|
|||||||
uniform vec4 glow;
|
uniform vec4 glow;
|
||||||
uniform float scene_light_strength;
|
uniform float scene_light_strength;
|
||||||
uniform mat3 env_mat;
|
uniform mat3 env_mat;
|
||||||
uniform mat3 ssao_effect_mat;
|
|
||||||
|
|
||||||
uniform vec3 sun_dir;
|
uniform vec3 sun_dir;
|
||||||
|
|
||||||
@@ -335,7 +334,7 @@ void setAtmosAttenuation(vec3 v)
|
|||||||
vary_AtmosAttenuation = v;
|
vary_AtmosAttenuation = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
void calcAtmospherics(vec3 inPositionEye) {
|
||||||
|
|
||||||
vec3 P = inPositionEye;
|
vec3 P = inPositionEye;
|
||||||
setPositionEye(P);
|
setPositionEye(P);
|
||||||
@@ -396,16 +395,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
|||||||
//increase ambient when there are more clouds
|
//increase ambient when there are more clouds
|
||||||
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
|
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 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
|
//haze color
|
||||||
setAdditiveColor(
|
setAdditiveColor(
|
||||||
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
|
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
|
||||||
@@ -677,7 +666,7 @@ void main()
|
|||||||
vec3 col = vec3(0.0f,0.0f,0.0f);
|
vec3 col = vec3(0.0f,0.0f,0.0f);
|
||||||
|
|
||||||
float bloom = 0.0;
|
float bloom = 0.0;
|
||||||
calcAtmospherics(pos.xyz, 1.0);
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
|
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,6 @@ uniform vec4 glow;
|
|||||||
uniform float global_gamma;
|
uniform float global_gamma;
|
||||||
uniform float scene_light_strength;
|
uniform float scene_light_strength;
|
||||||
uniform mat3 env_mat;
|
uniform mat3 env_mat;
|
||||||
uniform float ssao_effect;
|
|
||||||
|
|
||||||
uniform vec3 sun_dir;
|
uniform vec3 sun_dir;
|
||||||
VARYING vec2 vary_fragcoord;
|
VARYING vec2 vary_fragcoord;
|
||||||
@@ -238,7 +237,7 @@ vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
void calcAtmospherics(vec3 inPositionEye) {
|
||||||
|
|
||||||
vec3 P = inPositionEye;
|
vec3 P = inPositionEye;
|
||||||
setPositionEye(P);
|
setPositionEye(P);
|
||||||
@@ -305,9 +304,6 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
|||||||
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
|
+ (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
|
||||||
+ tmpAmbient)));
|
+ tmpAmbient)));
|
||||||
|
|
||||||
// decrease value for occluded areas
|
|
||||||
tmpAmbient = vec4(mix(ssao_effect * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
|
|
||||||
|
|
||||||
//brightness of surface both sunlight and ambient
|
//brightness of surface both sunlight and ambient
|
||||||
setSunlitColor(vec3(sunlight * .5));
|
setSunlitColor(vec3(sunlight * .5));
|
||||||
setAmblitColor(vec3(tmpAmbient * .25));
|
setAmblitColor(vec3(tmpAmbient * .25));
|
||||||
@@ -408,7 +404,7 @@ void main()
|
|||||||
float final_da = max(0.0,da);
|
float final_da = max(0.0,da);
|
||||||
final_da = min(final_da, 1.0f);
|
final_da = min(final_da, 1.0f);
|
||||||
final_da = pow(final_da, 1.0/1.3);
|
final_da = pow(final_da, 1.0/1.3);
|
||||||
calcAtmospherics(pos.xyz, 1.0);
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
col = atmosAmbient(vec3(0));
|
col = atmosAmbient(vec3(0));
|
||||||
float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
|
float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
|
||||||
|
|||||||
@@ -31,120 +31,19 @@ out vec4 frag_color;
|
|||||||
#define frag_color gl_FragColor
|
#define frag_color gl_FragColor
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//class 1 -- no shadow, SSAO only
|
|
||||||
|
|
||||||
uniform sampler2DRect depthMap;
|
|
||||||
uniform sampler2DRect normalMap;
|
|
||||||
uniform sampler2D noiseMap;
|
|
||||||
|
|
||||||
|
|
||||||
// Inputs
|
|
||||||
uniform float ssao_radius;
|
|
||||||
uniform float ssao_max_radius;
|
|
||||||
uniform float ssao_factor;
|
|
||||||
uniform float ssao_factor_inv;
|
|
||||||
|
|
||||||
VARYING vec2 vary_fragcoord;
|
VARYING vec2 vary_fragcoord;
|
||||||
|
|
||||||
uniform mat4 inv_proj;
|
uniform sampler2DRect depthMapDownsampled;
|
||||||
|
uniform sampler2DRect depthMap;
|
||||||
|
|
||||||
|
uniform sampler2DRect diffuseRect;
|
||||||
|
uniform float downsampled_depth_scale;
|
||||||
uniform vec2 screen_res;
|
uniform vec2 screen_res;
|
||||||
|
|
||||||
vec2 encode_normal(vec3 n)
|
|
||||||
{
|
|
||||||
float f = sqrt(8 * n.z + 8);
|
|
||||||
return n.xy / f + 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 decode_normal (vec2 enc)
|
|
||||||
{
|
|
||||||
vec2 fenc = enc*4-2;
|
|
||||||
float f = dot(fenc,fenc);
|
|
||||||
float g = sqrt(1-f/4);
|
|
||||||
vec3 n;
|
|
||||||
n.xy = fenc*g;
|
|
||||||
n.z = 1-f/2;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 getPosition(vec2 pos_screen)
|
|
||||||
{
|
|
||||||
float depth = texture2DRect(depthMap, pos_screen.xy).r;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
|
||||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
|
||||||
{
|
|
||||||
vec2 kern[8];
|
|
||||||
// exponentially (^2) distant occlusion samples spread around origin
|
|
||||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
|
||||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
|
||||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
|
||||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
|
||||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
|
||||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
|
||||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
|
||||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
|
||||||
|
|
||||||
vec2 pos_screen = vary_fragcoord.xy;
|
|
||||||
vec3 pos_world = pos.xyz;
|
|
||||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
|
||||||
|
|
||||||
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
|
|
||||||
float points = 1.0;
|
|
||||||
float angle_hidden = 0.0;
|
|
||||||
|
|
||||||
// use a kernel scale that diminishes with distance.
|
|
||||||
// a scale of less than 32 is just wasting good samples, though.
|
|
||||||
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
|
|
||||||
|
|
||||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
|
|
||||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
|
||||||
|
|
||||||
vec3 diff = samppos_world - pos.xyz;
|
|
||||||
|
|
||||||
if (diff.z < ssao_factor && diff.z != 0.0)
|
|
||||||
{
|
|
||||||
float dist = length(diff);
|
|
||||||
float angrel = max(0.0, dot(norm.xyz, diff/dist));
|
|
||||||
float distrel = 1.0/(1.0+dist*dist);
|
|
||||||
float samplehidden = min(angrel, distrel);
|
|
||||||
|
|
||||||
angle_hidden += (samplehidden);
|
|
||||||
points += 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
angle_hidden /= points;
|
|
||||||
|
|
||||||
float rtn = (1.0 - angle_hidden);
|
|
||||||
|
|
||||||
return (rtn * rtn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 pos_screen = vary_fragcoord.xy;
|
|
||||||
|
|
||||||
//try doing an unproject here
|
|
||||||
|
|
||||||
vec4 pos = getPosition(pos_screen);
|
|
||||||
|
|
||||||
vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
|
|
||||||
norm = decode_normal(norm.xy);
|
|
||||||
|
|
||||||
frag_color[0] = 1.0;
|
frag_color[0] = 1.0;
|
||||||
frag_color[1] = calcAmbientOcclusion(pos, norm);
|
frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord.xy*downsampled_depth_scale).r;
|
||||||
frag_color[2] = 1.0;
|
frag_color[2] = 1.0;
|
||||||
frag_color[3] = 1.0;
|
frag_color[3] = 1.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ out vec4 frag_color;
|
|||||||
|
|
||||||
//class 2 -- shadows and SSAO
|
//class 2 -- shadows and SSAO
|
||||||
|
|
||||||
|
uniform sampler2DRect diffuseRect;
|
||||||
uniform sampler2DRect depthMap;
|
uniform sampler2DRect depthMap;
|
||||||
uniform sampler2DRect normalMap;
|
uniform sampler2DRect normalMap;
|
||||||
uniform sampler2DShadow shadowMap0;
|
uniform sampler2DShadow shadowMap0;
|
||||||
@@ -40,16 +41,12 @@ uniform sampler2DShadow shadowMap2;
|
|||||||
uniform sampler2DShadow shadowMap3;
|
uniform sampler2DShadow shadowMap3;
|
||||||
uniform sampler2DShadow shadowMap4;
|
uniform sampler2DShadow shadowMap4;
|
||||||
uniform sampler2DShadow shadowMap5;
|
uniform sampler2DShadow shadowMap5;
|
||||||
uniform sampler2D noiseMap;
|
//uniform sampler2D noiseMap;
|
||||||
|
|
||||||
|
|
||||||
// Inputs
|
// Inputs
|
||||||
uniform mat4 shadow_matrix[6];
|
uniform mat4 shadow_matrix[6];
|
||||||
uniform vec4 shadow_clip;
|
uniform vec4 shadow_clip;
|
||||||
uniform float ssao_radius;
|
|
||||||
uniform float ssao_max_radius;
|
|
||||||
uniform float ssao_factor;
|
|
||||||
uniform float ssao_factor_inv;
|
|
||||||
|
|
||||||
VARYING vec2 vary_fragcoord;
|
VARYING vec2 vary_fragcoord;
|
||||||
|
|
||||||
@@ -66,6 +63,8 @@ uniform float shadow_offset;
|
|||||||
uniform float spot_shadow_bias;
|
uniform float spot_shadow_bias;
|
||||||
uniform float spot_shadow_offset;
|
uniform float spot_shadow_offset;
|
||||||
|
|
||||||
|
uniform float downsampled_depth_scale;
|
||||||
|
|
||||||
vec2 encode_normal(vec3 n)
|
vec2 encode_normal(vec3 n)
|
||||||
{
|
{
|
||||||
float f = sqrt(8 * n.z + 8);
|
float f = sqrt(8 * n.z + 8);
|
||||||
@@ -96,61 +95,6 @@ vec4 getPosition(vec2 pos_screen)
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 getKern(int i)
|
|
||||||
{
|
|
||||||
vec2 kern[8];
|
|
||||||
// exponentially (^2) distant occlusion samples spread around origin
|
|
||||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
|
||||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
|
||||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
|
||||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
|
||||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
|
||||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
|
||||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
|
||||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
|
||||||
|
|
||||||
return kern[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
|
||||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
|
||||||
{
|
|
||||||
vec2 pos_screen = vary_fragcoord.xy;
|
|
||||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
|
||||||
|
|
||||||
// We treat the first sample as the origin, which definitely doesn't obscure itself thanks to being visible for sampling in the first place.
|
|
||||||
float points = 1.0;
|
|
||||||
float angle_hidden = 0.0;
|
|
||||||
|
|
||||||
// use a kernel scale that diminishes with distance.
|
|
||||||
// a scale of less than 32 is just wasting good samples, though.
|
|
||||||
float scale = max(32.0, min(ssao_radius / -pos.z, ssao_max_radius));
|
|
||||||
|
|
||||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
|
|
||||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
|
||||||
|
|
||||||
vec3 diff = samppos_world - pos.xyz;
|
|
||||||
|
|
||||||
if (diff.z < ssao_factor && diff.z != 0.0)
|
|
||||||
{
|
|
||||||
float dist = length(diff);
|
|
||||||
float angrel = max(0.0, dot(norm.xyz, diff/dist));
|
|
||||||
float distrel = 1.0/(1.0+dist*dist);
|
|
||||||
float samplehidden = min(angrel, distrel);
|
|
||||||
|
|
||||||
angle_hidden += (samplehidden);
|
|
||||||
points += 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
angle_hidden /= points;
|
|
||||||
float rtn = (1.0 - angle_hidden);
|
|
||||||
return (rtn * rtn);
|
|
||||||
}
|
|
||||||
|
|
||||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
||||||
{
|
{
|
||||||
stc.xyz /= stc.w;
|
stc.xyz /= stc.w;
|
||||||
@@ -301,7 +245,7 @@ void main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
frag_color[0] = shadow;
|
frag_color[0] = shadow;
|
||||||
frag_color[1] = calcAmbientOcclusion(pos, norm);
|
frag_color[1] = texture2DRect(diffuseRect,vary_fragcoord*downsampled_depth_scale);
|
||||||
|
|
||||||
spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
|
spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
|
||||||
|
|
||||||
|
|||||||
@@ -2972,14 +2972,17 @@ void LLAppViewer::removeMarkerFile(bool leave_logout_marker)
|
|||||||
mMarkerFile.close() ;
|
mMarkerFile.close() ;
|
||||||
LLAPRFile::remove( mMarkerFileName );
|
LLAPRFile::remove( mMarkerFileName );
|
||||||
}
|
}
|
||||||
if (mLogoutMarkerFile != NULL && !leave_logout_marker)
|
if (mLogoutMarkerFile != NULL)
|
||||||
{
|
{
|
||||||
LLAPRFile::remove( mLogoutMarkerFileName );
|
if(!leave_logout_marker)
|
||||||
mLogoutMarkerFile = NULL;
|
{
|
||||||
}
|
LLAPRFile::remove( mLogoutMarkerFileName );
|
||||||
else
|
mLogoutMarkerFile = NULL;
|
||||||
{
|
}
|
||||||
LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
|
else
|
||||||
|
{
|
||||||
|
LL_WARNS("MarkerFile") << "leaving markers because this is a second instance" << LL_ENDL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ void LLDrawPoolAlpha::endRenderPass( S32 pass )
|
|||||||
LLFastTimer t(FTM_RENDER_ALPHA);
|
LLFastTimer t(FTM_RENDER_ALPHA);
|
||||||
LLRenderPass::endRenderPass(pass);
|
LLRenderPass::endRenderPass(pass);
|
||||||
|
|
||||||
if(gPipeline.canUseWindLightShaders())
|
if(mVertexShaderLevel > 0) //Singu Note: Unbind if shaders are enabled at all, not just windlight atmospherics..
|
||||||
{
|
{
|
||||||
LLGLSLShader::bindNoShader();
|
LLGLSLShader::bindNoShader();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ public:
|
|||||||
|
|
||||||
~LLMeshLODResponder()
|
~LLMeshLODResponder()
|
||||||
{
|
{
|
||||||
if (!LLApp::isQuitting())
|
if (!LLApp::isExiting())
|
||||||
{
|
{
|
||||||
if (!mProcessed)
|
if (!mProcessed)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -118,12 +118,7 @@ LLPanelNetwork::~LLPanelNetwork()
|
|||||||
|
|
||||||
void LLPanelNetwork::apply()
|
void LLPanelNetwork::apply()
|
||||||
{
|
{
|
||||||
U32 cache_size = (U32)childGetValue("cache_size").asInteger();
|
gSavedSettings.setU32("CacheSize", childGetValue("cache_size").asInteger());
|
||||||
if (gSavedSettings.getU32("CacheSize") != cache_size)
|
|
||||||
{
|
|
||||||
onClickClearCache(this);
|
|
||||||
gSavedSettings.setU32("CacheSize", cache_size);
|
|
||||||
}
|
|
||||||
gSavedSettings.setF32("ThrottleBandwidthKBPS", childGetValue("max_bandwidth").asReal());
|
gSavedSettings.setF32("ThrottleBandwidthKBPS", childGetValue("max_bandwidth").asReal());
|
||||||
gSavedSettings.setF32("HTTPThrottleBandwidth", childGetValue("tex_bandwidth").asReal());
|
gSavedSettings.setF32("HTTPThrottleBandwidth", childGetValue("tex_bandwidth").asReal());
|
||||||
gSavedSettings.setBOOL("ImagePipelineUseHTTP", childGetValue("http_textures"));
|
gSavedSettings.setBOOL("ImagePipelineUseHTTP", childGetValue("http_textures"));
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE;//1024;
|
|||||||
const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
|
const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
|
||||||
const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
|
const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
|
||||||
|
|
||||||
|
static std::queue<LLUUID> sgDelayedPurgeQueue;
|
||||||
|
|
||||||
class LLTextureCacheWorker : public LLWorkerClass
|
class LLTextureCacheWorker : public LLWorkerClass
|
||||||
{
|
{
|
||||||
friend class LLTextureCache;
|
friend class LLTextureCache;
|
||||||
@@ -1541,6 +1543,20 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
|
|||||||
llinfos << "The entire texture cache is cleared." << llendl;
|
llinfos << "The entire texture cache is cleared." << llendl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLTextureCache::performDelayedPurge()
|
||||||
|
{
|
||||||
|
LLMutexLock lock(&mHeaderMutex);
|
||||||
|
while(!sgDelayedPurgeQueue.empty())
|
||||||
|
{
|
||||||
|
removeFromCache(sgDelayedPurgeQueue.front());
|
||||||
|
sgDelayedPurgeQueue.pop();
|
||||||
|
if (mTexturesSizeTotal < sCacheMaxTexturesSize)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LLTextureCache::purgeTextures(bool validate)
|
void LLTextureCache::purgeTextures(bool validate)
|
||||||
{
|
{
|
||||||
if (mReadOnly)
|
if (mReadOnly)
|
||||||
@@ -1558,6 +1574,9 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||||||
|
|
||||||
llinfos << "TEXTURE CACHE: Purging." << llendl;
|
llinfos << "TEXTURE CACHE: Purging." << llendl;
|
||||||
|
|
||||||
|
std::queue<LLUUID> empty;
|
||||||
|
std::swap(sgDelayedPurgeQueue, empty);
|
||||||
|
|
||||||
// Read the entries list
|
// Read the entries list
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
U32 num_entries = openAndReadEntries(entries);
|
U32 num_entries = openAndReadEntries(entries);
|
||||||
@@ -1567,8 +1586,8 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use mTexturesSizeMap to collect UUIDs of textures with bodies
|
// Use mTexturesSizeMap to collect UUIDs of textures with bodies
|
||||||
typedef std::set<std::pair<U32,S32> > time_idx_set_t;
|
typedef std::vector<std::pair<U32,S32> > time_idx_set_t;
|
||||||
std::set<std::pair<U32,S32> > time_idx_set;
|
time_idx_set_t time_idx_set;
|
||||||
for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
|
for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
|
||||||
iter1 != mTexturesSizeMap.end(); ++iter1)
|
iter1 != mTexturesSizeMap.end(); ++iter1)
|
||||||
{
|
{
|
||||||
@@ -1578,7 +1597,7 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||||||
if (iter2 != mHeaderIDMap.end())
|
if (iter2 != mHeaderIDMap.end())
|
||||||
{
|
{
|
||||||
S32 idx = iter2->second;
|
S32 idx = iter2->second;
|
||||||
time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
|
time_idx_set.push_back(std::make_pair(entries[idx].mTime, idx));
|
||||||
// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl;
|
// llinfos << "TIME: " << entries[idx].mTime << " TEX: " << entries[idx].mID << " IDX: " << idx << " Size: " << entries[idx].mImageSize << llendl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1587,6 +1606,8 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::sort(time_idx_set.begin(), time_idx_set.end());
|
||||||
|
|
||||||
// Validate 1/256th of the files on startup
|
// Validate 1/256th of the files on startup
|
||||||
U32 validate_idx = 0;
|
U32 validate_idx = 0;
|
||||||
@@ -1637,7 +1658,14 @@ void LLTextureCache::purgeTextures(bool validate)
|
|||||||
purge_count++;
|
purge_count++;
|
||||||
LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
|
LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
|
||||||
cache_size -= entries[idx].mBodySize;
|
cache_size -= entries[idx].mBodySize;
|
||||||
removeEntry(idx, entries[idx], filename) ;
|
if(validate)
|
||||||
|
{
|
||||||
|
removeEntry(idx, entries[idx], filename);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sgDelayedPurgeQueue.push(entries[idx].mID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1791,7 +1819,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
|
|||||||
delete responder;
|
delete responder;
|
||||||
return LLWorkerThread::nullHandle();
|
return LLWorkerThread::nullHandle();
|
||||||
}
|
}
|
||||||
if (mDoPurge)
|
if (sgDelayedPurgeQueue.empty() && mDoPurge)
|
||||||
{
|
{
|
||||||
// NOTE: This may cause an occasional hiccup,
|
// NOTE: This may cause an occasional hiccup,
|
||||||
// but it really needs to be done on the control thread
|
// but it really needs to be done on the control thread
|
||||||
@@ -1799,6 +1827,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
|
|||||||
purgeTextures(false);
|
purgeTextures(false);
|
||||||
mDoPurge = FALSE;
|
mDoPurge = FALSE;
|
||||||
}
|
}
|
||||||
|
performDelayedPurge();
|
||||||
LLMutexLock lock(&mWorkersMutex);
|
LLMutexLock lock(&mWorkersMutex);
|
||||||
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
|
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
|
||||||
data, datasize, 0,
|
data, datasize, 0,
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ private:
|
|||||||
void setDirNames(ELLPath location);
|
void setDirNames(ELLPath location);
|
||||||
void readHeaderCache();
|
void readHeaderCache();
|
||||||
void clearCorruptedCache();
|
void clearCorruptedCache();
|
||||||
|
void performDelayedPurge();
|
||||||
void purgeAllTextures(bool purge_directories);
|
void purgeAllTextures(bool purge_directories);
|
||||||
void purgeTextures(bool validate);
|
void purgeTextures(bool validate);
|
||||||
LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
|
LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
|
||||||
|
|||||||
@@ -693,6 +693,7 @@ void settings_setup_listeners()
|
|||||||
gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2));
|
gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2));
|
||||||
gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
||||||
gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
||||||
|
gSavedSettings.getControl("SHRenderSSAOResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
|
||||||
gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
||||||
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2));
|
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2));
|
||||||
gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
|
gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2));
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ LLGLSLShader gDeferredLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
|||||||
LLGLSLShaderArray<LLViewerShaderMgr::SHADER_DEFERRED> gDeferredMultiLightProgram[16];
|
LLGLSLShaderArray<LLViewerShaderMgr::SHADER_DEFERRED> gDeferredMultiLightProgram[16];
|
||||||
LLGLSLShader gDeferredSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
|
LLGLSLShader gDeferredSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
|
||||||
LLGLSLShader gDeferredMultiSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
|
LLGLSLShader gDeferredMultiSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
|
||||||
|
LLGLSLShader gDeferredSSAOProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
||||||
|
LLGLSLShader gDeferredDownsampleDepthNearestProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
||||||
LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
||||||
LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
||||||
LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED);
|
||||||
@@ -1336,6 +1338,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
|
|||||||
success = gDeferredSunProgram.createShader(NULL, NULL);
|
success = gDeferredSunProgram.createShader(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(gSavedSettings.getBOOL("RenderDeferredSSAO"))
|
||||||
|
{
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
gDeferredSSAOProgram.mName = "Deferred Ambient Occlusion Shader";
|
||||||
|
gDeferredSSAOProgram.mShaderFiles.clear();
|
||||||
|
gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
|
||||||
|
gDeferredSSAOProgram.mShaderFiles.push_back(make_pair("deferred/SSAOF.glsl", GL_FRAGMENT_SHADER_ARB));
|
||||||
|
gDeferredSSAOProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
|
||||||
|
success = gDeferredSSAOProgram.createShader(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
gDeferredDownsampleDepthNearestProgram.mName = "Deferred Nearest Downsample Depth Shader";
|
||||||
|
gDeferredDownsampleDepthNearestProgram.mShaderFiles.clear();
|
||||||
|
gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB));
|
||||||
|
gDeferredDownsampleDepthNearestProgram.mShaderFiles.push_back(make_pair("deferred/downsampleDepthNearestF.glsl", GL_FRAGMENT_SHADER_ARB));
|
||||||
|
gDeferredDownsampleDepthNearestProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
|
||||||
|
success = gDeferredDownsampleDepthNearestProgram.createShader(NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
|
gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
|
||||||
|
|||||||
@@ -313,6 +313,8 @@ extern LLGLSLShaderArray<LLViewerShaderMgr::SHADER_DEFERRED> gDeferredMultiLig
|
|||||||
extern LLGLSLShader gDeferredSpotLightProgram;
|
extern LLGLSLShader gDeferredSpotLightProgram;
|
||||||
extern LLGLSLShader gDeferredMultiSpotLightProgram;
|
extern LLGLSLShader gDeferredMultiSpotLightProgram;
|
||||||
extern LLGLSLShader gDeferredSunProgram;
|
extern LLGLSLShader gDeferredSunProgram;
|
||||||
|
extern LLGLSLShader gDeferredSSAOProgram;
|
||||||
|
extern LLGLSLShader gDeferredDownsampleDepthNearestProgram;
|
||||||
extern LLGLSLShader gDeferredBlurLightProgram;
|
extern LLGLSLShader gDeferredBlurLightProgram;
|
||||||
extern LLGLSLShader gDeferredAvatarProgram;
|
extern LLGLSLShader gDeferredAvatarProgram;
|
||||||
extern LLGLSLShader gDeferredSoftenProgram;
|
extern LLGLSLShader gDeferredSoftenProgram;
|
||||||
|
|||||||
@@ -1270,7 +1270,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
|
|||||||
mNeedsCreateTexture = FALSE;
|
mNeedsCreateTexture = FALSE;
|
||||||
if (mRawImage.isNull())
|
if (mRawImage.isNull())
|
||||||
{
|
{
|
||||||
llerrs << "LLViewerTexture trying to create texture with no Raw Image" << llendl;
|
llwarns << "LLViewerTexture trying to create texture with no Raw Image" << llendl;
|
||||||
}
|
}
|
||||||
// llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ",
|
// llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ",
|
||||||
// mRawDiscardLevel,
|
// mRawDiscardLevel,
|
||||||
@@ -1712,7 +1712,7 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
}
|
}
|
||||||
if (mIsMissingAsset)
|
if (mIsMissingAsset)
|
||||||
{
|
{
|
||||||
llassert_always(!mHasFetcher);
|
llassert(!mHasFetcher);
|
||||||
return false; // skip
|
return false; // skip
|
||||||
}
|
}
|
||||||
if (!mLoadedCallbackList.empty() && mRawImage.notNull())
|
if (!mLoadedCallbackList.empty() && mRawImage.notNull())
|
||||||
@@ -1942,8 +1942,8 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
mHasFetcher = FALSE;
|
mHasFetcher = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid));
|
llassert(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid));
|
||||||
|
|
||||||
return mIsFetching ? true : false;
|
return mIsFetching ? true : false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,11 +207,11 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");
|
|||||||
static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
|
static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");
|
||||||
static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
|
static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort");
|
||||||
|
|
||||||
static LLStaticHashedString sTint("tint");
|
//static LLStaticHashedString sTint("tint");
|
||||||
static LLStaticHashedString sAmbiance("ambiance");
|
//static LLStaticHashedString sAmbiance("ambiance");
|
||||||
static LLStaticHashedString sAlphaScale("alpha_scale");
|
//static LLStaticHashedString sAlphaScale("alpha_scale");
|
||||||
static LLStaticHashedString sNormMat("norm_mat");
|
static LLStaticHashedString sNormMat("norm_mat");
|
||||||
static LLStaticHashedString sOffset("offset");
|
//static LLStaticHashedString sOffset("offset");
|
||||||
static LLStaticHashedString sScreenRes("screenRes");
|
static LLStaticHashedString sScreenRes("screenRes");
|
||||||
static LLStaticHashedString sDelta("delta");
|
static LLStaticHashedString sDelta("delta");
|
||||||
static LLStaticHashedString sDistFactor("dist_factor");
|
static LLStaticHashedString sDistFactor("dist_factor");
|
||||||
@@ -796,12 +796,15 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||||||
mSampleBuffer.release();
|
mSampleBuffer.release();
|
||||||
mScreen.release();
|
mScreen.release();
|
||||||
|
|
||||||
|
mDeferredDownsampledDepth.release();
|
||||||
|
|
||||||
if (LLPipeline::sRenderDeferred)
|
if (LLPipeline::sRenderDeferred)
|
||||||
{
|
{
|
||||||
S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
|
static const LLCachedControl<S32> shadow_detail("RenderShadowDetail",0);
|
||||||
BOOL ssao = gSavedSettings.getBOOL("RenderDeferredSSAO");
|
static const LLCachedControl<bool> ssao ("RenderDeferredSSAO",false);
|
||||||
BOOL RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField");
|
static const LLCachedControl<bool> RenderDepthOfField("RenderDepthOfField",false);
|
||||||
static const LLCachedControl<F32> RenderShadowResolutionScale("RenderShadowResolutionScale",1.0f);
|
static const LLCachedControl<F32> RenderShadowResolutionScale("RenderShadowResolutionScale",1.0f);
|
||||||
|
static const LLCachedControl<F32> RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
|
||||||
|
|
||||||
const U32 occlusion_divisor = 3;
|
const U32 occlusion_divisor = 3;
|
||||||
|
|
||||||
@@ -835,6 +838,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||||||
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
|
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
|
||||||
{ //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
|
{ //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
|
||||||
if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
|
if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
|
||||||
|
if(ssao)
|
||||||
|
{
|
||||||
|
F32 scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
|
||||||
|
if( scale < 1.f && !mDeferredDownsampledDepth.allocate(llceil(F32(resX)*scale), llceil(F32(resY)*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE) ) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -901,6 +909,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||||||
mScreen.release();
|
mScreen.release();
|
||||||
mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
|
mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
|
||||||
mDeferredDepth.release();
|
mDeferredDepth.release();
|
||||||
|
mDeferredDownsampledDepth.release();
|
||||||
mOcclusionDepth.release();
|
mOcclusionDepth.release();
|
||||||
|
|
||||||
if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
|
if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
|
||||||
@@ -1022,6 +1031,7 @@ void LLPipeline::releaseScreenBuffers()
|
|||||||
mPhysicsDisplay.release();
|
mPhysicsDisplay.release();
|
||||||
mDeferredScreen.release();
|
mDeferredScreen.release();
|
||||||
mDeferredDepth.release();
|
mDeferredDepth.release();
|
||||||
|
mDeferredDownsampledDepth.release();
|
||||||
mDeferredLight.release();
|
mDeferredLight.release();
|
||||||
mOcclusionDepth.release();
|
mOcclusionDepth.release();
|
||||||
|
|
||||||
@@ -7648,6 +7658,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
|
|||||||
static const LLCachedControl<F32> RenderSpotShadowBias("RenderSpotShadowBias",0.f);
|
static const LLCachedControl<F32> RenderSpotShadowBias("RenderSpotShadowBias",0.f);
|
||||||
static const LLCachedControl<F32> RenderEdgeDepthCutoff("RenderEdgeDepthCutoff",.01f);
|
static const LLCachedControl<F32> RenderEdgeDepthCutoff("RenderEdgeDepthCutoff",.01f);
|
||||||
static const LLCachedControl<F32> RenderEdgeNormCutoff("RenderEdgeNormCutoff",.25f);
|
static const LLCachedControl<F32> RenderEdgeNormCutoff("RenderEdgeNormCutoff",.25f);
|
||||||
|
static const LLCachedControl<F32> RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
|
||||||
|
|
||||||
if (noise_map == 0xFFFFFFFF)
|
if (noise_map == 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
@@ -7677,10 +7688,21 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
|
|||||||
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
S32 channel2 = shader.enableTexture(LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH, mDeferredDepth.getUsage());
|
||||||
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
|
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
|
||||||
if (channel > -1)
|
if (channel > -1 || channel2 >= -1)
|
||||||
{
|
{
|
||||||
gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
|
if(channel > -1)
|
||||||
|
gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
|
||||||
|
if(channel2 > -1)
|
||||||
|
{
|
||||||
|
F32 scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
|
||||||
|
if(scale < 1.f)
|
||||||
|
gGL.getTexUnit(channel2)->bind(&mDeferredDownsampledDepth, TRUE);
|
||||||
|
else
|
||||||
|
gGL.getTexUnit(channel2)->bind(&mDeferredDepth, TRUE); //Bind full res depth instead, as downsampling is disabled if scale == 1.f
|
||||||
|
}
|
||||||
|
|
||||||
//gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
//gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
|
|
||||||
@@ -7774,21 +7796,24 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
|
|||||||
|
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
|
|
||||||
F32 mat[16*6];
|
if(shader.getUniformLocation(LLShaderMgr::DEFERRED_SHADOW_MATRIX) >= 0)
|
||||||
for (U32 i = 0; i < 16; i++)
|
|
||||||
{
|
{
|
||||||
mat[i] = mSunShadowMatrix[0].m[i];
|
F32 mat[16*6];
|
||||||
mat[i+16] = mSunShadowMatrix[1].m[i];
|
for (U32 i = 0; i < 16; i++)
|
||||||
mat[i+32] = mSunShadowMatrix[2].m[i];
|
{
|
||||||
mat[i+48] = mSunShadowMatrix[3].m[i];
|
mat[i] = mSunShadowMatrix[0].m[i];
|
||||||
mat[i+64] = mSunShadowMatrix[4].m[i];
|
mat[i+16] = mSunShadowMatrix[1].m[i];
|
||||||
mat[i+80] = mSunShadowMatrix[5].m[i];
|
mat[i+32] = mSunShadowMatrix[2].m[i];
|
||||||
|
mat[i+48] = mSunShadowMatrix[3].m[i];
|
||||||
|
mat[i+64] = mSunShadowMatrix[4].m[i];
|
||||||
|
mat[i+80] = mSunShadowMatrix[5].m[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
|
||||||
|
|
||||||
|
stop_glerror();
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat);
|
|
||||||
|
|
||||||
stop_glerror();
|
|
||||||
|
|
||||||
channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||||
if (channel > -1)
|
if (channel > -1)
|
||||||
{
|
{
|
||||||
@@ -7844,6 +7869,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
|
|||||||
glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
|
glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
|
||||||
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
|
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shader.uniform1f(LLShaderMgr::DEFERRED_DOWNSAMPLED_DEPTH_SCALE, llclamp(RenderSSAOResolutionScale.get(),.01f,1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
|
static LLFastTimer::DeclareTimer FTM_GI_TRACE("Trace");
|
||||||
@@ -7867,6 +7894,7 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
|
|
||||||
static const LLCachedControl<U32> RenderFSAASamples("RenderFSAASamples",0);
|
static const LLCachedControl<U32> RenderFSAASamples("RenderFSAASamples",0);
|
||||||
static const LLCachedControl<bool> RenderDeferredSSAO("RenderDeferredSSAO",false);
|
static const LLCachedControl<bool> RenderDeferredSSAO("RenderDeferredSSAO",false);
|
||||||
|
static const LLCachedControl<F32> RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
|
||||||
static const LLCachedControl<S32> RenderShadowDetail("RenderShadowDetail",0);
|
static const LLCachedControl<S32> RenderShadowDetail("RenderShadowDetail",0);
|
||||||
static const LLCachedControl<LLVector3> RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
|
static const LLCachedControl<LLVector3> RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
|
||||||
static const LLCachedControl<F32> RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
|
static const LLCachedControl<F32> RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
|
||||||
@@ -7933,6 +7961,54 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
gGL.pushMatrix();
|
gGL.pushMatrix();
|
||||||
gGL.loadIdentity();
|
gGL.loadIdentity();
|
||||||
|
|
||||||
|
if (RenderDeferredSSAO)
|
||||||
|
{
|
||||||
|
F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
|
||||||
|
|
||||||
|
LLGLDisable blend(GL_BLEND);
|
||||||
|
|
||||||
|
//Downsample with fullscreen quad. GL_NEAREST
|
||||||
|
if(ssao_scale < 1.f)
|
||||||
|
{
|
||||||
|
mDeferredDownsampledDepth.bindTarget();
|
||||||
|
mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0);
|
||||||
|
gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
|
||||||
|
mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||||
|
{
|
||||||
|
LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
|
||||||
|
stop_glerror();
|
||||||
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
|
stop_glerror();
|
||||||
|
}
|
||||||
|
mDeferredDownsampledDepth.flush();
|
||||||
|
unbindDeferredShader(gDeferredDownsampleDepthNearestProgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Run SSAO
|
||||||
|
{
|
||||||
|
mScreen.bindTarget();
|
||||||
|
glClearColor(1,1,1,1);
|
||||||
|
mScreen.clear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
bindDeferredShader(gDeferredSSAOProgram, 0);
|
||||||
|
if(ssao_scale < 1.f)
|
||||||
|
{
|
||||||
|
glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight());
|
||||||
|
gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
|
||||||
|
}
|
||||||
|
mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||||
|
{
|
||||||
|
LLGLDepthTest depth(GL_FALSE);
|
||||||
|
stop_glerror();
|
||||||
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
|
stop_glerror();
|
||||||
|
}
|
||||||
|
mScreen.flush();
|
||||||
|
unbindDeferredShader(gDeferredSSAOProgram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (RenderDeferredSSAO || RenderShadowDetail > 0)
|
if (RenderDeferredSSAO || RenderShadowDetail > 0)
|
||||||
{
|
{
|
||||||
mDeferredLight.bindTarget();
|
mDeferredLight.bindTarget();
|
||||||
@@ -7944,7 +8020,7 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
|
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
|
||||||
glClearColor(0,0,0,0);
|
glClearColor(0,0,0,0);
|
||||||
|
|
||||||
glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
|
/*glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
|
||||||
|
|
||||||
const U32 slice = 32;
|
const U32 slice = 32;
|
||||||
F32 offset[slice*3];
|
F32 offset[slice*3];
|
||||||
@@ -7978,8 +8054,18 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
|
gDeferredSunProgram.uniform3fv(sOffset, slice, offset);*/
|
||||||
|
|
||||||
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
|
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
|
||||||
|
|
||||||
|
//Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO
|
||||||
|
// diffuse map should only be found if the sun shader is the SSAO variant.
|
||||||
|
S32 channel = gDeferredSunProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
|
||||||
|
if (channel > -1)
|
||||||
|
{
|
||||||
|
mScreen.bindTexture(0,channel);
|
||||||
|
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
LLGLDisable blend(GL_BLEND);
|
LLGLDisable blend(GL_BLEND);
|
||||||
@@ -7988,6 +8074,11 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel > -1)
|
||||||
|
{
|
||||||
|
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||||
|
}
|
||||||
|
|
||||||
unbindDeferredShader(gDeferredSunProgram);
|
unbindDeferredShader(gDeferredSunProgram);
|
||||||
}
|
}
|
||||||
@@ -8106,6 +8197,9 @@ void LLPipeline::renderDeferredLighting()
|
|||||||
gPipeline.pushRenderTypeMask();
|
gPipeline.pushRenderTypeMask();
|
||||||
|
|
||||||
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
||||||
|
#if ENABLE_CLASSIC_CLOUDS
|
||||||
|
LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS,
|
||||||
|
#endif
|
||||||
LLPipeline::RENDER_TYPE_WL_CLOUDS,
|
LLPipeline::RENDER_TYPE_WL_CLOUDS,
|
||||||
LLPipeline::RENDER_TYPE_WL_SKY,
|
LLPipeline::RENDER_TYPE_WL_SKY,
|
||||||
LLPipeline::END_RENDER_TYPES);
|
LLPipeline::END_RENDER_TYPES);
|
||||||
@@ -8500,6 +8594,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
|
|
||||||
static const LLCachedControl<U32> RenderFSAASamples("RenderFSAASamples",0);
|
static const LLCachedControl<U32> RenderFSAASamples("RenderFSAASamples",0);
|
||||||
static const LLCachedControl<bool> RenderDeferredSSAO("RenderDeferredSSAO",false);
|
static const LLCachedControl<bool> RenderDeferredSSAO("RenderDeferredSSAO",false);
|
||||||
|
static const LLCachedControl<F32> RenderSSAOResolutionScale("SHRenderSSAOResolutionScale",.5f);
|
||||||
static const LLCachedControl<S32> RenderShadowDetail("RenderShadowDetail",0);
|
static const LLCachedControl<S32> RenderShadowDetail("RenderShadowDetail",0);
|
||||||
static const LLCachedControl<LLVector3> RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
|
static const LLCachedControl<LLVector3> RenderShadowGaussian("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
|
||||||
static const LLCachedControl<F32> RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
|
static const LLCachedControl<F32> RenderShadowBlurSize("RenderShadowBlurSize",1.4f);
|
||||||
@@ -8560,6 +8655,54 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
gGL.pushMatrix();
|
gGL.pushMatrix();
|
||||||
gGL.loadIdentity();
|
gGL.loadIdentity();
|
||||||
|
|
||||||
|
if (RenderDeferredSSAO)
|
||||||
|
{
|
||||||
|
F32 ssao_scale = llclamp(RenderSSAOResolutionScale.get(),.01f,1.f);
|
||||||
|
|
||||||
|
LLGLDisable blend(GL_BLEND);
|
||||||
|
|
||||||
|
//Downsample with fullscreen quad. GL_NEAREST
|
||||||
|
if(ssao_scale < 1.f)
|
||||||
|
{
|
||||||
|
mDeferredDownsampledDepth.bindTarget();
|
||||||
|
mDeferredDownsampledDepth.clear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
bindDeferredShader(gDeferredDownsampleDepthNearestProgram, 0);
|
||||||
|
gDeferredDownsampleDepthNearestProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
|
||||||
|
mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||||
|
{
|
||||||
|
LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
|
||||||
|
stop_glerror();
|
||||||
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
|
stop_glerror();
|
||||||
|
}
|
||||||
|
mDeferredDownsampledDepth.flush();
|
||||||
|
unbindDeferredShader(gDeferredDownsampleDepthNearestProgram);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Run SSAO
|
||||||
|
{
|
||||||
|
mScreen.bindTarget();
|
||||||
|
glClearColor(1,1,1,1);
|
||||||
|
mScreen.clear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
bindDeferredShader(gDeferredSSAOProgram, 0);
|
||||||
|
if(ssao_scale < 1.f)
|
||||||
|
{
|
||||||
|
glViewport(0,0,mDeferredDownsampledDepth.getWidth(),mDeferredDownsampledDepth.getHeight());
|
||||||
|
gDeferredSSAOProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredDownsampledDepth.getWidth()/ssao_scale, mDeferredDownsampledDepth.getHeight()/ssao_scale);
|
||||||
|
}
|
||||||
|
mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||||
|
{
|
||||||
|
LLGLDepthTest depth(GL_FALSE);
|
||||||
|
stop_glerror();
|
||||||
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
|
stop_glerror();
|
||||||
|
}
|
||||||
|
mScreen.flush();
|
||||||
|
unbindDeferredShader(gDeferredSSAOProgram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (RenderDeferredSSAO || RenderShadowDetail > 0)
|
if (RenderDeferredSSAO || RenderShadowDetail > 0)
|
||||||
{
|
{
|
||||||
mDeferredLight.bindTarget();
|
mDeferredLight.bindTarget();
|
||||||
@@ -8571,7 +8714,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
|
mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
|
||||||
glClearColor(0,0,0,0);
|
glClearColor(0,0,0,0);
|
||||||
|
|
||||||
glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
|
/*glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
|
||||||
|
|
||||||
const U32 slice = 32;
|
const U32 slice = 32;
|
||||||
F32 offset[slice*3];
|
F32 offset[slice*3];
|
||||||
@@ -8590,9 +8733,18 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset);
|
gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset);*/
|
||||||
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
|
gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
|
||||||
|
|
||||||
|
//Enable bilinear filtering, as the screen tex resolution may not match current framebuffer resolution. Eg, half-res SSAO
|
||||||
|
// diffuse map should only be found if the sun shader is the SSAO variant.
|
||||||
|
S32 channel = gDeferredSunProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
|
||||||
|
if (channel > -1)
|
||||||
|
{
|
||||||
|
mScreen.bindTexture(0,channel);
|
||||||
|
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
LLGLDisable blend(GL_BLEND);
|
LLGLDisable blend(GL_BLEND);
|
||||||
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
|
LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
|
||||||
@@ -8600,6 +8752,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel > -1)
|
||||||
|
{
|
||||||
|
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||||
|
}
|
||||||
|
|
||||||
unbindDeferredShader(gDeferredSunProgram);
|
unbindDeferredShader(gDeferredSunProgram);
|
||||||
}
|
}
|
||||||
@@ -8656,7 +8813,10 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
|
|||||||
gPipeline.pushRenderTypeMask();
|
gPipeline.pushRenderTypeMask();
|
||||||
|
|
||||||
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
||||||
|
#if ENABLE_CLASSIC_CLOUDS
|
||||||
LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS,
|
LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS,
|
||||||
|
#endif
|
||||||
|
LLPipeline::RENDER_TYPE_WL_CLOUDS,
|
||||||
LLPipeline::RENDER_TYPE_WL_SKY,
|
LLPipeline::RENDER_TYPE_WL_SKY,
|
||||||
LLPipeline::END_RENDER_TYPES);
|
LLPipeline::END_RENDER_TYPES);
|
||||||
|
|
||||||
|
|||||||
@@ -615,6 +615,7 @@ public:
|
|||||||
LLRenderTarget mFXAABuffer;
|
LLRenderTarget mFXAABuffer;
|
||||||
LLRenderTarget mEdgeMap;
|
LLRenderTarget mEdgeMap;
|
||||||
LLRenderTarget mDeferredDepth;
|
LLRenderTarget mDeferredDepth;
|
||||||
|
LLRenderTarget mDeferredDownsampledDepth;
|
||||||
LLRenderTarget mOcclusionDepth;
|
LLRenderTarget mOcclusionDepth;
|
||||||
LLRenderTarget mDeferredLight;
|
LLRenderTarget mDeferredLight;
|
||||||
LLMultisampleBuffer mSampleBuffer;
|
LLMultisampleBuffer mSampleBuffer;
|
||||||
|
|||||||
Reference in New Issue
Block a user