diff options
Diffstat (limited to 'indra/newview')
135 files changed, 7734 insertions, 2149 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e532793a82..123f3b72a3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -30,6 +30,7 @@ include(LScript) include(Linking) include(Mozlib) include(NDOF) +include(GooglePerfTools) include(TemplateCheck) include(UI) include(UnixInstall) @@ -1330,8 +1331,8 @@ if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES - LINK_FLAGS "/debug /NODEFAULTLIB:MSVCRT /SUBSYSTEM:WINDOWS" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:LIBCMT /NODEFAULTLIB:MSVCRTD" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" LINK_FLAGS_RELEASE ${release_flags} ) diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index d7bb64ce8a..a49ccb77b4 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -40,6 +40,7 @@ </array> <key>tags</key> <array> + <string>ShaderLoading</string> </array> </map> </array> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2cc8224fc6..523032bf67 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2256,7 +2256,18 @@ <key>Value</key> <integer>0</integer> </map> - <key>DebugShowTime</key> + <key>DebugShowRenderMatrices</key> + <map> + <key>Comment</key> + <string>Display values of current view and projection matrices.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>DebugShowTime</key> <map> <key>Comment</key> <string>Show depth buffer contents</string> @@ -2635,6 +2646,17 @@ <key>Value</key> <real>60.0</real> </map> + <key>FPSLogFrequency</key> + <map> + <key>Comment</key> + <string>Seconds between display of FPS in log (0 for never)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> <key>FilterItemsPerFrame</key> <map> <key>Comment</key> @@ -6141,7 +6163,102 @@ <key>Value</key> <integer>1</integer> </map> - <key>RenderBumpmapMinDistanceSquared</key> + + <key>RenderShadowGaussian</key> + <map> + <key>Comment</key> + <string>Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>2.0</real> + <real>2.0</real> + <real>0.0</real> + </array> + </map> + + <key>RenderShadowNearDist</key> + <map> + <key>Comment</key> + <string>Near clip plane of shadow camera (affects precision of depth shadows).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>256</real> + <real>256</real> + <real>256</real> + </array> + </map> + <key>RenderShadowClipPlanes</key> + <map> + <key>Comment</key> + <string>Near clip plane split distances for shadow map frusta.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>4.0</real> + <real>8.0</real> + <real>24.0</real> + </array> + </map> + <key>RenderSSAOScale</key> + <map> + <key>Comment</key> + <string>Scaling factor for the area to sample for occluders (pixels at 1 meter away, inversely varying with distance)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>500.0</real> + </map> + <key>RenderSSAOMaxScale</key> + <map> + <key>Comment</key> + <string>Maximum screen radius for sampling (pixels)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>60</integer> + </map> + <key>RenderSSAOFactor</key> + <map> + <key>Comment</key> + <string>Occlusion sensitivity factor for ambient occlusion (larger is more)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.30</real> + </map> + <key>RenderSSAOEffect</key> + <map> + <key>Comment</key> + <string>Multiplier for (1) value and (2) saturation (HSV definition), for areas which are totally occluded. Blends with original color for partly-occluded areas. (Third component is unused.)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Vector3</string> + <key>Value</key> + <array> + <real>0.40</real> + <real>1.00</real> + <real>0.00</real> + </array> + </map> + <key>RenderBumpmapMinDistanceSquared</key> <map> <key>Comment</key> <string>Maximum distance at which to render bumpmapped primitives (distance in meters, squared)</string> @@ -6152,6 +6269,17 @@ <key>Value</key> <real>100.0</real> </map> + <key>RenderNormalMapScale</key> + <map> + <key>Comment</key> + <string>Scaler applied to height map when generating normal maps</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>128</real> + </map> <key>RenderCubeMap</key> <map> <key>Comment</key> @@ -6192,7 +6320,7 @@ <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> @@ -6207,18 +6335,129 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderDeferred</key> - <map> - <key>Comment</key> - <string>Use deferred rendering pipeline.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>RenderDynamicLOD</key> + <key>RenderDelayCreation</key> + <map> + <key>Comment</key> + <string>Throttle creation of drawables.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderAnimateRes</key> + <map> + <key>Comment</key> + <string>Animate rezing prims.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + + <key>RenderAnimateTrees</key> + <map> + <key>Comment</key> + <string>Use GL matrix ops to animate tree branches.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDeferredAlphaSoften</key> + <map> + <key>Comment</key> + <string>Scalar for softening alpha surfaces (for soft particles).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.75</real> + </map> + <key>RenderDeferredNoise</key> + <map> + <key>Comment</key> + <string>Noise scalar to hide banding in deferred render.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>4</real> + </map> + <key>RenderDeferred</key> + <map> + <key>Comment</key> + <string>Use deferred rendering pipeline.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>RenderDeferredSunShadow</key> + <map> + <key>Comment</key> + <string>Generate shadows from the sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>RenderDeferredSunWash</key> + <map> + <key>Comment</key> + <string>Amount local lights are washed out by sun.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.5</real> + </map> + <key>RenderShadowNoise</key> + <map> + <key>Comment</key> + <string>Magnitude of noise on shadow samples.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>-0.0001</real> + </map> + <key>RenderShadowBlurSize</key> + <map> + <key>Comment</key> + <string>Scale of shadow softening kernel.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.7</real> + </map> + <key>RenderShadowBlurSamples</key> + <map> + <key>Comment</key> + <string>Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>5</real> + </map> + <key>RenderDynamicLOD</key> <map> <key>Comment</key> <string>Dynamically adjust level of detail.</string> @@ -6368,13 +6607,13 @@ <key>RenderGlowMinLuminance</key> <map> <key>Comment</key> - <string>Min luminance intensity necessary to consider an object bright enough to automatically glow. (Gets clamped to 0 - 1.0 range)</string> + <string>Min luminance intensity necessary to consider an object bright enough to automatically glow.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>F32</string> <key>Value</key> - <real>1.0</real> + <real>2.5</real> </map> <key>RenderGlowResolutionPow</key> <map> @@ -6534,6 +6773,17 @@ <key>Value</key> <integer>4096</integer> </map> + <key>RenderMaxNodeSize</key> + <map> + <key>Comment</key> + <string>Maximum size of a single node's vertex data (in KB).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>4096</integer> + </map> <key>RenderMaxVBOSize</key> <map> <key>Comment</key> @@ -6543,7 +6793,7 @@ <key>Type</key> <string>S32</string> <key>Value</key> - <integer>32</integer> + <integer>512</integer> </map> <key>RenderName</key> <map> @@ -6644,6 +6894,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderShaderLightingMaxLevel</key> + <map> + <key>Comment</key> + <string>Max lighting level to use in the shader (class 3 is default, 2 is less lights, 1 is sun/moon only. Works around shader compiler bugs on certain platforms.)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>3</integer> + </map> <key>RenderShaderLODThreshold</key> <map> <key>Comment</key> @@ -9760,6 +10021,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>RenderDelayVBUpdate</key> + <map> + <key>Comment</key> + <string>Delay vertex buffer updates until just before rendering</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UseStartScreen</key> <map> <key>Comment</key> @@ -10507,7 +10779,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>WindowWidth</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl new file mode 100644 index 0000000000..a91e9fa15b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -0,0 +1,88 @@ +/** + * @file alphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; +uniform sampler2DRect positionMap; + +uniform mat4 shadow_matrix[4]; +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; + +uniform float alpha_soften; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + + float shadow = 1.0; + vec4 pos = vec4(vary_position, 1.0); + + if (pos.z > -shadow_clip.w) + { + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + if (samp_pos.z != 0.0) + { + float dist_factor = alpha_soften; + float a = gl_Color.a; + a *= a; + dist_factor *= 1.0/(1.0-a); + color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); + } + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1); + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl new file mode 100644 index 0000000000..b496bd674f --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -0,0 +1,69 @@ +/** + * @file alphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; + +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + vary_position = pos.xyz; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl new file mode 100644 index 0000000000..6c94f5c5a7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl @@ -0,0 +1,68 @@ +/** + * @file avatarAlphaF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec4 vary_position; +varying vec3 vary_normal; + +void main() +{ + float shadow = 1.0; + vec4 pos = vary_position; + vec3 norm = normalize(vary_normal); + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + + if (pos.z > -shadow_clip.w) + { + + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + + vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a); + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl new file mode 100644 index 0000000000..c1988d3c78 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -0,0 +1,78 @@ +/** + * @file avatarAlphaV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec4 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + gl_Position = gl_ProjectionMatrix * pos; + vary_position = pos; + vary_normal = norm; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col; + col.a = gl_Color.a; + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + col.rgb = scaleUpLight(col.rgb); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl new file mode 100644 index 0000000000..58aa5a9cb5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -0,0 +1,20 @@ +/** + * @file avatarF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + gl_FragData[0] = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl new file mode 100644 index 0000000000..27c09db922 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -0,0 +1,15 @@ +/** + * @file avatarShadowF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + + +void main() +{ + gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy)); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl new file mode 100644 index 0000000000..14da6b1ad4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -0,0 +1,38 @@ +/** + * @file avatarShadowV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +mat4 getSkinnedTransform(); + +attribute vec4 weight; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + pos = gl_ProjectionMatrix * pos; + //smash geometry against near clip plane + pos.z = max(pos.z, -1.0); + gl_Position = pos; + + gl_FrontColor = gl_Color; +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl new file mode 100644 index 0000000000..12a7ff7f29 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -0,0 +1,42 @@ +/** + * @file avatarV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +mat4 getSkinnedTransform(); + +attribute vec4 weight; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + vary_position = pos; + vary_normal = norm; + + gl_Position = gl_ProjectionMatrix * pos; + //gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + gl_FrontColor = gl_Color; +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl new file mode 100644 index 0000000000..3c6700a871 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -0,0 +1,48 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; + +uniform float blur_size; +uniform vec2 delta; +uniform vec3 kern[32]; +uniform int kern_length; +uniform float kern_scale; + +varying vec2 vary_fragcoord; + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz; + vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg; + + vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + + 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' + vec2 col = defined_weight * ccol; + + for (int i = 1; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; + vec3 samppos = texture2DRect(positionMap, tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc).rg*kern[i].xy; + defined_weight += kern[i].xy; + } + } + + col /= defined_weight; + + gl_FragColor = vec4(col.r, col.g, 0.0, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl new file mode 100644 index 0000000000..b7f07e5702 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl @@ -0,0 +1,17 @@ +/** + * @file blurLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl new file mode 100644 index 0000000000..a8712bc8cc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -0,0 +1,29 @@ +/** + * @file bumpF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; +varying vec4 vary_position; + +void main() +{ + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; + + vec3 tnorm = vec3(dot(norm,vary_mat0), + dot(norm,vary_mat1), + dot(norm,vary_mat2)); + + gl_FragData[0].rgb = gl_Color.rgb*col; + gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); + gl_FragData[2] = vec4(normalize(tnorm), 0.0); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl new file mode 100644 index 0000000000..ba180922cc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -0,0 +1,30 @@ +/** + * @file bumpV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + vec3 n = normalize(gl_NormalMatrix * gl_Normal); + vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); + vec3 t = cross(b, n); + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 14e6361f83..f2ba2df69a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -8,9 +8,13 @@ uniform sampler2D diffuseMap; varying vec3 vary_normal; +varying vec4 vary_position; void main() { - gl_FragColor = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); - gl_FragColor.rgb = vary_normal*0.5+0.5; + vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); + gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 8e9069368a..3413a7f9d6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -6,7 +6,7 @@ */ varying vec3 vary_normal; -varying vec3 vary_position; +varying vec4 vary_position; void main() { @@ -14,7 +14,7 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = (gl_ModelViewMatrix * gl_Vertex).xyz; + vary_position = gl_ModelViewMatrix * gl_Vertex; vary_normal = normalize(gl_NormalMatrix * gl_Normal); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl new file mode 100644 index 0000000000..2a811c5897 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -0,0 +1,63 @@ +/** + * @file fullbrightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; +uniform sampler2DRect positionMap; + +uniform mat4 shadow_matrix[4]; +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 float alpha_soften; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + + float shadow = 1.0; + vec4 pos = vary_position; + + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color; + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + if (samp_pos.z != 0.0) + { + float dist_factor = alpha_soften; + float a = gl_Color.a; + a *= a; + dist_factor *= 1.0/(1.0-a); + color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); + } + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1); + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl new file mode 100644 index 0000000000..6381a1ced8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -0,0 +1,41 @@ +/** + * @file fullbrightV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void calcAtmospherics(vec3 inPositionEye); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec4 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; +varying vec3 vary_fragcoord; +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vary_position = pos; + + 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); + +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl new file mode 100644 index 0000000000..20a3f3df5b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -0,0 +1,20 @@ +/** + * @file impostorF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform sampler2D normalMap; +uniform sampler2D specularMap; + +varying vec4 vary_position; + +void main() +{ + gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); + gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl new file mode 100644 index 0000000000..9c5ae31541 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl @@ -0,0 +1,19 @@ +/** + * @file impostorV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl new file mode 100644 index 0000000000..3689d12840 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -0,0 +1,83 @@ +/** + * @file multiPointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; + +uniform vec3 env_mat[3]; +uniform float sun_wash; + +uniform int light_count; + +uniform vec4 light[16]; +uniform vec4 light_col[16]; + +varying vec3 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; + vec3 pos = texture2DRect(positionMap, frag.xy).xyz; + vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz); + vec4 spec = texture2DRect(specularRect, frag.xy); + vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; + float noise = texture2D(noiseMap, frag.xy/128.0).b; + vec3 out_col = vec3(0,0,0); + + for (int i = 0; i < light_count; ++i) + { + vec3 lv = light[i].xyz-pos; + float dist2 = dot(lv,lv); + if (dist2 > light[i].w) + { + continue; + } + + float da = dot(norm, lv); + if (da < 0.0) + { + continue; + } + + lv = normalize(lv); + da = dot(norm, lv); + + float fa = light_col[i].a+1.0; + float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0); + dist_atten *= noise; + + float lit = da * dist_atten; + + vec3 col = light_col[i].rgb*lit*diff; + + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*light_col[i].rgb*spec.rgb; + } + + out_col += col; + } + + //attenuate point light contribution by SSAO component + out_col *= texture2DRect(lightMap, frag.xy).g; + + gl_FragColor.rgb = out_col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl new file mode 100644 index 0000000000..52bad1f34c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -0,0 +1,75 @@ +/** + * @file pointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; + +uniform vec3 env_mat[3]; +uniform float sun_wash; + +varying vec4 vary_light; + +varying vec3 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + vec3 pos = texture2DRect(positionMap, frag).xyz; + vec3 lv = vary_light.xyz-pos; + float dist2 = dot(lv,lv); + if (dist2 > vary_light.w) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag).xyz; + float da = dot(norm, lv); + if (da < 0.0) + { + discard; + } + + norm = normalize(norm); + lv = normalize(lv); + da = dot(norm, lv); + + float noise = texture2D(noiseMap, frag/128.0).b; + + vec3 col = texture2DRect(diffuseRect, frag).rgb; + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0); + float lit = da * dist_atten * noise; + + col = gl_Color.rgb*lit*col; + + vec4 spec = texture2DRect(specularRect, frag); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + float sa = dot(ref,lv); + sa = max(sa, 0.0); + sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*gl_Color.rgb*spec.rgb; + } + + //attenuate point light contribution by SSAO component + col *= texture2DRect(lightMap, frag.xy).g; + + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl new file mode 100644 index 0000000000..a4edb88259 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -0,0 +1,28 @@ +/** + * @file pointLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_light; +varying vec3 vary_fragcoord; + +uniform vec2 screen_res; +uniform float near_clip; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl new file mode 100644 index 0000000000..b3758c3638 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -0,0 +1,14 @@ +/** + * @file shadowF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + + +void main() +{ + gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl new file mode 100644 index 0000000000..aae1beeae3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -0,0 +1,17 @@ +/** + * @file shadowV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; + //smash geometry against the near clip plane (great for ortho projections) + pos.z = max(pos.z, -1.0); + gl_Position = pos; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl new file mode 100644 index 0000000000..d5671a6ce4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -0,0 +1,279 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; + +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; + +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; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec3 pos = texture2DRect(positionMap, tc).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = vec4(texture2DRect(diffuseRect, tc).rgb, 1.0); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = scol_ambocc.r; + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + vec3 col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(min(da, scol)); + + col *= diffuse.rgb; + + if (spec.a > 0.2) + { + vec3 ref = reflect(pos.xyz, norm.xyz); + vec3 rc; + rc.x = dot(ref, env_mat[0]); + rc.y = dot(ref, env_mat[1]); + rc.z = dot(ref, env_mat[2]); + + vec3 refcol = textureCube(environmentMap, rc).rgb; + col.rgb += refcol * spec.rgb; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl new file mode 100644 index 0000000000..ad8af4780d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl @@ -0,0 +1,24 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl new file mode 100644 index 0000000000..d43fe6ca95 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -0,0 +1,139 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect positionMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +// Inputs +uniform mat4 shadow_matrix[4]; +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 vec4 vary_light; + +//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; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.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 = texture2DRect(positionMap, samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces + // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + return 1.0 - (float(points != 0) * angle_hidden); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0); + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else if (pos.z > -shadow_clip.w) + { + if (pos.z < -shadow_clip.z) + { + vec4 lpos = shadow_matrix[3]*pos; + shadow = shadow2DProj(shadowMap3, lpos).x; + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = shadow_matrix[2]*pos; + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = shadow_matrix[1]*pos; + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = shadow_matrix[0]*pos; + shadow = shadow2DProj(shadowMap0, lpos).x; + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + } + else + { + // more distant than the shadow map covers - just use directional shading as shadow + shadow = dp_directional_light; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + //gl_FragColor[2] is unused as of August 2008, may be used for debugging +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl new file mode 100644 index 0000000000..5081485c4b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl @@ -0,0 +1,25 @@ +/** + * @file sunLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl new file mode 100644 index 0000000000..211b2e0397 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -0,0 +1,36 @@ +/** + * @file terrainF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D detail_0; +uniform sampler2D detail_1; +uniform sampler2D detail_2; +uniform sampler2D detail_3; +uniform sampler2D alpha_ramp; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + /// Note: This should duplicate the blending functionality currently used for the terrain rendering. + + vec4 color0 = texture2D(detail_0, gl_TexCoord[0].xy); + vec4 color1 = texture2D(detail_1, gl_TexCoord[0].xy); + vec4 color2 = texture2D(detail_2, gl_TexCoord[0].xy); + vec4 color3 = texture2D(detail_3, gl_TexCoord[0].xy); + + float alpha1 = texture2D(alpha_ramp, gl_TexCoord[0].zw).a; + float alpha2 = texture2D(alpha_ramp,gl_TexCoord[1].xy).a; + float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a; + vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); + + gl_FragData[0] = vec4(outColor.rgb, 1.0); + gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl new file mode 100644 index 0000000000..e9d6dcabff --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -0,0 +1,41 @@ +/** + * @file terrainV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_normal; +varying vec4 vary_position; + +vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) +{ + vec4 tcoord; + + tcoord.x = dot(vpos, tp0); + tcoord.y = dot(vpos, tp1); + tcoord.z = tc.z; + tcoord.w = tc.w; + + tcoord = mat * tcoord; + + return tcoord; +} + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + vary_normal = normalize(gl_NormalMatrix * gl_Normal); + + // Transform and pass tex coords + gl_TexCoord[0].xy = texgen_object(gl_Vertex, gl_MultiTexCoord0, gl_TextureMatrix[0], gl_ObjectPlaneS[0], gl_ObjectPlaneT[0]).xy; + + vec4 t = gl_MultiTexCoord1; + + gl_TexCoord[0].zw = t.xy; + gl_TexCoord[1].xy = t.xy-vec2(2.0, 0.0); + gl_TexCoord[1].zw = t.xy-vec2(1.0, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl new file mode 100644 index 0000000000..bc2c9816dc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -0,0 +1,20 @@ +/** + * @file treeF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = gl_Color*col; + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(normalize(vary_normal), 0.0); + gl_FragData[3] = vary_position; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl new file mode 100644 index 0000000000..9131d7c2b3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -0,0 +1,22 @@ +/** + * @file treeV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +varying vec3 vary_normal; +varying vec4 vary_position; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vary_position = gl_ModelViewMatrix * gl_Vertex; + + vary_normal = normalize(gl_NormalMatrix * gl_Normal); + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl new file mode 100644 index 0000000000..0a1f019e3d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -0,0 +1,157 @@ +/** + * @file waterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec3 scaleSoftClip(vec3 inColor); +vec3 atmosTransport(vec3 inColor); + +uniform sampler2D bumpMap; +uniform sampler2D screenTex; +uniform sampler2D refTex; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; +uniform sampler2D noiseMap; + +uniform mat4 shadow_matrix[4]; +uniform vec4 shadow_clip; + +uniform float sunAngle; +uniform float sunAngle2; +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform float refScale; +uniform float kd; +uniform vec2 screenRes; +uniform vec3 normScale; +uniform float fresnelScale; +uniform float fresnelOffset; +uniform float blurMultiplier; + + +//bigWave is (refCoord.w, view.w); +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; +varying vec4 vary_position; + +void main() +{ + vec4 color; + float dist = length(view.xy); + + //normalize view vector + vec3 viewVec = normalize(view.xyz); + + //get wave normals + vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0; + //get base fresnel components + + vec3 df = vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset; + df *= df; + + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + + float dist2 = dist; + dist = max(dist, 5.0); + + float dmod = sqrt(dist); + + vec2 dmod_scale = vec2(dmod*dmod, dmod); + + //get reflected color + vec2 refdistort1 = wave1.xy*normScale.x; + vec2 refvec1 = distort+refdistort1/dmod_scale; + vec4 refcol1 = texture2D(refTex, refvec1); + + vec2 refdistort2 = wave2.xy*normScale.y; + vec2 refvec2 = distort+refdistort2/dmod_scale; + vec4 refcol2 = texture2D(refTex, refvec2); + + vec2 refdistort3 = wave3.xy*normScale.z; + vec2 refvec3 = distort+refdistort3/dmod_scale; + vec4 refcol3 = texture2D(refTex, refvec3); + + vec4 refcol = refcol1 + refcol2 + refcol3; + float df1 = df.x + df.y + df.z; + refcol *= df1 * 0.333; + + vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; + wavef.z *= max(-viewVec.z, 0.1); + wavef = normalize(wavef); + + float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset; + + vec2 refdistort4 = wavef.xy*0.125; + refdistort4.y -= abs(refdistort4.y); + vec2 refvec4 = distort+refdistort4/dmod; + float dweight = min(dist2*blurMultiplier, 1.0); + vec4 baseCol = texture2D(refTex, refvec4); + refcol = mix(baseCol*df2, refcol, dweight); + + //get specular component + float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0); + + //harden specular + spec = pow(spec, 128.0); + + //figure out distortion vector (ripply) + vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0); + + vec4 fb = texture2D(screenTex, distort2); + + //mix with reflection + // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); + + float shadow = 1.0; + vec4 pos = vary_position; + + vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; + + if (pos.z > -shadow_clip.w) + { + vec4 spos = pos; + + if (pos.z < -shadow_clip.z) + { + vec4 lpos = (shadow_matrix[3]*spos); + shadow = shadow2DProj(shadowMap3, lpos).x; + } + else if (pos.z < -shadow_clip.y) + { + vec4 lpos = (shadow_matrix[2]*spos); + shadow = shadow2DProj(shadowMap2, lpos).x; + } + else if (pos.z < -shadow_clip.x) + { + vec4 lpos = (shadow_matrix[1]*spos); + shadow = shadow2DProj(shadowMap1, lpos).x; + } + else + { + vec4 lpos = (shadow_matrix[0]*spos); + shadow = shadow2DProj(shadowMap0, lpos).x; + } + } + + spec *= shadow; + color.rgb += spec * specular; + + color.rgb = atmosTransport(color.rgb); + color.rgb = scaleSoftClip(color.rgb); + color.a = spec * sunAngle2; + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl new file mode 100644 index 0000000000..b45e5c5302 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -0,0 +1,76 @@ +/** + * @file waterV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void calcAtmospherics(vec3 inPositionEye); + +uniform vec2 d1; +uniform vec2 d2; +uniform float time; +uniform vec3 eyeVec; +uniform float waterHeight; + +varying vec4 refCoord; +varying vec4 littleWave; +varying vec4 view; + +varying vec4 vary_position; + +float wave(vec2 v, float t, float f, vec2 d, float s) +{ + return (dot(d, v)*f + t*s)*f; +} + +void main() +{ + //transform vertex + vec4 position = gl_Vertex; + mat4 modelViewProj = gl_ModelViewProjectionMatrix; + + vec4 oPosition; + + //get view vector + vec3 oEyeVec; + oEyeVec.xyz = position.xyz-eyeVec; + + float d = length(oEyeVec.xy); + float ld = min(d, 2560.0); + + position.xy = eyeVec.xy + oEyeVec.xy/d*ld; + view.xyz = oEyeVec; + + d = clamp(ld/1536.0-0.5, 0.0, 1.0); + d *= d; + + oPosition = position; + oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d); + vary_position = gl_ModelViewMatrix * oPosition; + oPosition = modelViewProj * oPosition; + + refCoord.xyz = oPosition.xyz + vec3(0,0,0.2); + + //get wave position parameter (create sweeping horizontal waves) + vec3 v = position.xyz; + v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0; + + //push position for further horizon effect. + position.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z); + position.w = 1.0; + position = position*gl_ModelViewMatrix; + + calcAtmospherics((gl_ModelViewMatrix * gl_Vertex).xyz); + + + //pass wave parameters to pixel shader + vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055; + //get two normal map (detail map) texture coordinates + littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13; + littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1; + view.w = bigWave.y; + refCoord.w = bigWave.x; + + gl_Position = oPosition; +} diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index dbdfe1174c..5d7af2c13a 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -20,8 +20,8 @@ void main() /// CALCULATING LUMINANCE (Using NTSC lum weights) /// http://en.wikipedia.org/wiki/Luma_%28video%29 - float lum = smoothstep(minLuminance, 1.0, dot(col.rgb, lumWeights ) ); - float warmth = smoothstep(minLuminance, 1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); + float lum = smoothstep(minLuminance, minLuminance+1.0, dot(col.rgb, lumWeights ) ); + float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); gl_FragColor.rgb = col.rgb; gl_FragColor.a = max(col.a, mix(lum, warmth, warmthAmount) * maxExtractAlpha); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index bd9b30a075..7e1788678d 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -7,6 +7,7 @@ vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); +vec3 applyWaterFog(vec4 inColor); uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index c02ba86d6c..05bdf64b42 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -54,6 +54,8 @@ WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderTextureMemoryMultiple 1 1.0 +RenderShaderLightingMaxLevel 1 3 + // // Low Graphics Settings @@ -473,17 +475,47 @@ list NVIDIA_GeForce_Go_6 RenderVBOEnable 1 0 Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt index 5f6cf14c05..7e6d4b4561 100644 --- a/indra/newview/licenses-win32.txt +++ b/indra/newview/licenses-win32.txt @@ -735,3 +735,37 @@ From Vivox: Attn: customer support 40 Speen Street Suite 402 Framingham, MA 01701 + + +======================== +google-perftools license +======================== + +Copyright (c) 2005, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 7ef757f1ba..569de267e7 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -358,7 +358,6 @@ LLAgent::LLAgent() : mFrameAgent(), - mCrouching(FALSE), mIsBusy(FALSE), mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed @@ -477,8 +476,16 @@ void LLAgent::cleanup() { setSitCamera(LLUUID::null); mAvatarObject = NULL; - mLookAt = NULL; - mPointAt = NULL; + if(mLookAt) + { + mLookAt->markDead() ; + mLookAt = NULL; + } + if(mPointAt) + { + mPointAt->markDead() ; + mPointAt = NULL; + } mRegionp = NULL; setFocusObject(NULL); } @@ -2726,7 +2733,7 @@ BOOL LLAgent::needsRenderAvatar() // TRUE if we need to render your own avatar's head. BOOL LLAgent::needsRenderHead() { - return mShowAvatar && !cameraMouselook(); + return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook()); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index c9e256fbbc..9d08c94150 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -544,6 +544,7 @@ public: void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region ); BOOL getHomePosGlobal( LLVector3d* pos_global ); void setCameraAnimating( BOOL b ) { mCameraAnimating = b; } + BOOL getCameraAnimating( ) { return mCameraAnimating; } void setAnimationDuration( F32 seconds ) { mAnimationDuration = seconds; } F32 getNearChatRadius() { return mNearChatRadius; } @@ -811,7 +812,6 @@ private: LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates - BOOL mCrouching; BOOL mIsBusy; S32 mAtKey; // Either 1, 0, or -1... indicates that movement-key is pressed diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9a8d211cf6..fc37c42f99 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -159,7 +159,7 @@ #include "llimview.h" #include "llviewerthrottle.h" #include "llparcel.h" -// + #include "llinventoryview.h" @@ -508,7 +508,7 @@ LLWorkerThread* LLAppViewer::sImageDecodeThread = NULL; LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLAppViewer::LLAppViewer() : - mMarkerFile(NULL), + mMarkerFile(), mReportedCrash(false), mNumSessions(0), mPurgeCache(false), @@ -1056,6 +1056,9 @@ bool LLAppViewer::mainLoop() } else { + //output possible call stacks to log file. + LLError::LLCallStacks::print() ; + llerrs << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } } @@ -1091,6 +1094,16 @@ bool LLAppViewer::mainLoop() bool LLAppViewer::cleanup() { + //---------------------------------------------- + //this test code will be removed after the test + //test manual call stack tracer + if(gSavedSettings.getBOOL("QAMode")) + { + LLError::LLCallStacks::print() ; + } + //end of the test code + //---------------------------------------------- + //flag all elements as needing to be destroyed immediately // to ensure shutdown order LLMortician::setZealous(TRUE); @@ -1110,6 +1123,9 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; // Must clean up texture references before viewer window is destroyed. + LLHUDManager::getInstance()->updateEffects(); + LLHUDObject::updateAll(); + LLHUDManager::getInstance()->cleanupEffects(); LLHUDObject::cleanupHUDObjects(); llinfos << "HUD Objects cleaned up" << llendflush; @@ -2118,7 +2134,7 @@ bool LLAppViewer::initWindow() gViewerWindow->initBase(); // show viewer window - gViewerWindow->mWindow->show(); + //gViewerWindow->mWindow->show(); return true; @@ -2264,6 +2280,9 @@ void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; + //print out recorded call stacks if there are any. + LLError::LLCallStacks::print() ; + LLAppViewer* pApp = LLAppViewer::instance(); if (pApp->beingDebugged()) { @@ -2348,16 +2367,17 @@ void LLAppViewer::handleViewerCrash() if(gLLErrorActivated) crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LLERROR_MARKER_FILE_NAME); else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME); llinfos << "Creating crash marker file " << crash_file_name << llendl; - apr_file_t* crash_file = ll_apr_file_open(crash_file_name, LL_APR_W); - if (crash_file) + + LLAPRFile crash_file ; + crash_file.open(crash_file_name, LL_APR_W); + if (crash_file.getFileHandle()) { LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL; } else { LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_file_name << LL_ENDL; - } - apr_file_close(crash_file); + } } if (gMessageSystem && gDirUtilp) @@ -2411,13 +2431,13 @@ bool LLAppViewer::anotherInstanceRunning() LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL; //Freeze case checks - apr_file_t* fMarker = ll_apr_file_open(marker_file, LL_APR_RB); - if (fMarker != NULL) + if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB)) { // File exists, try opening with write permissions - apr_file_close(fMarker); - fMarker = ll_apr_file_open(marker_file, LL_APR_WB); - if (fMarker == NULL) + LLAPRFile outfile ; + outfile.open(marker_file, LL_APR_WB); + apr_file_t* fMarker = outfile.getFileHandle() ; + if (!fMarker) { // Another instance is running. Skip the rest of these operations. LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; @@ -2425,12 +2445,10 @@ bool LLAppViewer::anotherInstanceRunning() } if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) //flock(fileno(fMarker), LOCK_EX | LOCK_NB) == -1) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Marker file is locked." << LL_ENDL; return true; } - // No other instances; we'll lock this file now & delete on quit. - apr_file_close(fMarker); + // No other instances; we'll lock this file now & delete on quit. } LL_DEBUGS("MarkerFile") << "Marker file isn't locked." << LL_ENDL; return false; @@ -2456,33 +2474,27 @@ void LLAppViewer::initMarkerFile() std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); - apr_file_t* fMarker = ll_apr_file_open(logout_marker_file, LL_APR_RB); - if(fMarker != NULL) + if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << LL_ENDL; gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; - } - fMarker = ll_apr_file_open(llerror_marker_file, LL_APR_RB); - if(fMarker != NULL) + } + if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); llinfos << "Last exec LLError crashed, setting LastExecEvent to " << LAST_EXEC_LLERROR_CRASH << llendl; if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_LLERROR_CRASH; } - fMarker = ll_apr_file_open(error_marker_file, LL_APR_RB); - if(fMarker != NULL) + if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) { - apr_file_close(fMarker); LL_INFOS("MarkerFile") << "Last exec crashed, setting LastExecEvent to " << LAST_EXEC_OTHER_CRASH << LL_ENDL; if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; else gLastExecEvent = LAST_EXEC_OTHER_CRASH; } - - ll_apr_file_remove(logout_marker_file); - ll_apr_file_remove(llerror_marker_file); - ll_apr_file_remove(error_marker_file); + + LLAPRFile::remove(logout_marker_file); + LLAPRFile::remove(llerror_marker_file); + LLAPRFile::remove(error_marker_file); //Freeze case checks if(anotherInstanceRunning()) @@ -2490,17 +2502,17 @@ void LLAppViewer::initMarkerFile() return; } - fMarker = ll_apr_file_open(mMarkerFileName, LL_APR_RB); - if (fMarker != NULL) - { - apr_file_close(fMarker); + if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB)) + { gLastExecEvent = LAST_EXEC_FROZE; LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL; } - + // Create the marker file for this execution & lock it - mMarkerFile = ll_apr_file_open(mMarkerFileName, LL_APR_W); - if (mMarkerFile) + apr_status_t s; + s = mMarkerFile.open(mMarkerFileName, LL_APR_W, gAPRPoolp); + + if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) { LL_DEBUGS("MarkerFile") << "Marker file created." << LL_ENDL; } @@ -2509,9 +2521,9 @@ void LLAppViewer::initMarkerFile() LL_INFOS("MarkerFile") << "Failed to create marker file." << LL_ENDL; return; } - if (apr_file_lock(mMarkerFile, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) + if (apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) { - apr_file_close(mMarkerFile); + mMarkerFile.close() ; LL_INFOS("MarkerFile") << "Marker file cannot be locked." << LL_ENDL; return; } @@ -2522,14 +2534,14 @@ void LLAppViewer::initMarkerFile() void LLAppViewer::removeMarkerFile(bool leave_logout_marker) { LL_DEBUGS("MarkerFile") << "removeMarkerFile()" << LL_ENDL; - if (mMarkerFile != NULL) + if (mMarkerFile.getFileHandle()) { - ll_apr_file_remove( mMarkerFileName ); - mMarkerFile = NULL; + mMarkerFile.close() ; + LLAPRFile::remove( mMarkerFileName ); } if (mLogoutMarkerFile != NULL && !leave_logout_marker) { - ll_apr_file_remove( mLogoutMarkerFileName ); + LLAPRFile::remove( mLogoutMarkerFileName ); mLogoutMarkerFile = NULL; } } @@ -2556,6 +2568,7 @@ void LLAppViewer::requestQuit() effectp->setPositionGlobal(gAgent.getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLHUDManager::getInstance()->sendEffects(); + effectp->markDead() ;//remove it. // Attempt to close all floaters that might be // editing things. @@ -3228,6 +3241,7 @@ void LLAppViewer::idle() // gFrameStats.start(LLFrameStats::IDLE_NETWORK); + stop_glerror(); idleNetwork(); stop_glerror(); @@ -3535,7 +3549,10 @@ void LLAppViewer::sendLogoutRequest() //Set internal status variables and marker files gLogoutInProgress = TRUE; mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - mLogoutMarkerFile = ll_apr_file_open(mLogoutMarkerFileName, LL_APR_W); + + LLAPRFile outfile ; + outfile.open(mLogoutMarkerFileName, LL_APR_W); + mLogoutMarkerFile = outfile.getFileHandle() ; if (mLogoutMarkerFile) { llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl; @@ -3544,7 +3561,7 @@ void LLAppViewer::sendLogoutRequest() else { llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl; - } + } } } @@ -3562,6 +3579,8 @@ static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; void LLAppViewer::idleNetwork() { pingMainloopTimeout("idleNetwork"); + LLError::LLCallStacks::clear() ; + llpushcallstacks ; gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; @@ -3572,7 +3591,7 @@ void LLAppViewer::idleNetwork() // deal with any queued name requests and replies. gCacheName->processPending(); - + llpushcallstacks ; LLTimer check_message_timer; // Read all available packets from network stop_glerror(); @@ -3644,16 +3663,16 @@ void LLAppViewer::idleNetwork() gPrintMessagesThisFrame = FALSE; } } - + llpushcallstacks ; gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); gAssetStorage->checkForTimeouts(); - + llpushcallstacks ; gViewerThrottle.updateDynamicThrottle(); - + llpushcallstacks ; // Check that the circuit between the viewer and the agent's current // region is still alive LLViewerRegion *agent_region = gAgent.getRegion(); @@ -3669,6 +3688,7 @@ void LLAppViewer::idleNetwork() mAgentRegionLastID = this_region_id; mAgentRegionLastAlive = this_region_alive; } + llpushcallstacks ; } void LLAppViewer::disconnectViewer() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 638bd241ce..cb10ad3661 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -198,7 +198,7 @@ private: bool mSecondInstance; // Is this a second instance of the app? std::string mMarkerFileName; - apr_file_t* mMarkerFile; // A file created to indicate the app is running. + LLAPRFile mMarkerFile; // A file created to indicate the app is running. std::string mLogoutMarkerFileName; apr_file_t* mLogoutMarkerFile; // A file created to indicate the app is running. diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp index 4656fb45a6..0099817de4 100644 --- a/indra/newview/llcloud.cpp +++ b/indra/newview/llcloud.cpp @@ -122,7 +122,7 @@ void LLCloudGroup::updatePuffs(const F32 dt) mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f); - gPipeline.addObject(mVOCloudsp); + gPipeline.createObject(mVOCloudsp); } LLVector3 velocity; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index d5619f2bf0..47e4a2278f 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -532,10 +532,10 @@ F32 LLDrawable::updateXform(BOOL undamped) if ((mCurrentScale != target_scale) || (!isRoot() && - (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED) || + (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || !mVObjp->getAngularVelocity().isExactlyZero() || target_pos != mXform.getPosition() || - target_rot != mXform.getRotation())) + target_rot != mXform.getRotation()))) { //child prim moving or scale change requires immediate rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } @@ -1233,7 +1233,8 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f; LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f; - if (LLPipeline::sImpostorRender || + if ((LLPipeline::sShadowRender && camera_in.AABBInFrustum(center, size)) || + LLPipeline::sImpostorRender || (camera_in.AABBInFrustumNoFarClip(center, size) && AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist))) { @@ -1290,7 +1291,6 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in) LLDrawable* drawable = child->mDrawable; if (!drawable) { - llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl; continue; } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 77715cbedf..f5a66a3a78 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -98,6 +98,7 @@ public: const LLVector3 getPositionAgent() const; const LLVector3d& getPositionGroup() const { return mPositionGroup; } const LLVector3& getScale() const { return mCurrentScale; } + void setScale(const LLVector3& scale) { mCurrentScale = scale; } const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } const LLQuaternion& getRotation() const { return mXform.getRotation(); } F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index bd30d47426..9f05ce3c46 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -68,6 +68,12 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) case POOL_SIMPLE: poolp = new LLDrawPoolSimple(); break; + case POOL_GRASS: + poolp = new LLDrawPoolGrass(); + break; + case POOL_FULLBRIGHT: + poolp = new LLDrawPoolFullbright(); + break; case POOL_INVISIBLE: poolp = new LLDrawPoolInvisible(); break; @@ -133,11 +139,89 @@ void LLDrawPool::beginRenderPass( S32 pass ) { } +//virtual +S32 LLDrawPool::getNumPasses() +{ + return 1; +} + +//virtual +void LLDrawPool::beginDeferredPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endDeferredPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumDeferredPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderDeferred(S32 pass) +{ + +} + +//virtual +void LLDrawPool::beginPostDeferredPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endPostDeferredPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumPostDeferredPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderPostDeferred(S32 pass) +{ + +} + //virtual void LLDrawPool::endRenderPass( S32 pass ) { } +//virtual +void LLDrawPool::beginShadowPass(S32 pass) +{ + +} + +//virtual +void LLDrawPool::endShadowPass(S32 pass) +{ + +} + +//virtual +S32 LLDrawPool::getNumShadowPasses() +{ + return 0; +} + +//virtual +void LLDrawPool::renderShadow(S32 pass) +{ + +} + //============================= // Face Pool Implementation //============================= @@ -414,6 +498,10 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) if (params.mVertexBuffer.notNull()) { + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 45a47f4c3f..b75de02ffc 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -58,10 +58,12 @@ public: POOL_SKY, POOL_WL_SKY, POOL_GROUND, - POOL_BUMP, POOL_INVISIBLE, POOL_AVATAR, POOL_WATER, + POOL_GRASS, + POOL_FULLBRIGHT, + POOL_BUMP, POOL_GLOW, POOL_ALPHA, NUM_POOL_TYPES, @@ -78,7 +80,23 @@ public: virtual LLViewerImage *getDebugTexture(); virtual void beginRenderPass( S32 pass ); virtual void endRenderPass( S32 pass ); - virtual S32 getNumPasses() { return 1; } + virtual S32 getNumPasses(); + + virtual void beginDeferredPass(S32 pass); + virtual void endDeferredPass(S32 pass); + virtual S32 getNumDeferredPasses(); + virtual void renderDeferred(S32 pass = 0); + + virtual void beginPostDeferredPass(S32 pass); + virtual void endPostDeferredPass(S32 pass); + virtual S32 getNumPostDeferredPasses(); + virtual void renderPostDeferred(S32 pass = 0); + + virtual void beginShadowPass(S32 pass); + virtual void endShadowPass(S32 pass); + virtual S32 getNumShadowPasses(); + virtual void renderShadow(S32 pass = 0); + virtual void render(S32 pass = 0) = 0; virtual void prerender() = 0; virtual U32 getVertexDataMask() = 0; @@ -112,6 +130,9 @@ public: PASS_BUMP, PASS_GLOW, PASS_ALPHA, + PASS_ALPHA_MASK, + PASS_FULLBRIGHT_ALPHA_MASK, + PASS_ALPHA_SHADOW, NUM_RENDER_TYPES, }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 8c4a0ab2b5..7e470bd01f 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -57,7 +57,7 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; - +static BOOL deferred_render = FALSE; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : LLRenderPass(type), current_shader(NULL), target_shader(NULL), @@ -76,6 +76,67 @@ void LLDrawPoolAlpha::prerender() mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } +S32 LLDrawPoolAlpha::getNumDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAlpha::beginDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolAlpha::endDeferredPass(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.4f); + { + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + gDeferredTreeProgram.bind(); + LLGLEnable test(GL_ALPHA_TEST); + //render alpha masked objects + LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolAlpha::renderDeferred(S32 pass) +{ + +} + + +S32 LLDrawPoolAlpha::getNumPostDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + + simple_shader = &gDeferredAlphaProgram; + fullbright_shader = &gDeferredFullbrightProgram; + + deferred_render = TRUE; + if (mVertexShaderLevel > 0) + { + // Start out with no shaders. + current_shader = target_shader = NULL; + } + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) +{ + deferred_render = FALSE; + endRenderPass(pass); +} + +void LLDrawPoolAlpha::renderPostDeferred(S32 pass) +{ + render(pass); +} + void LLDrawPoolAlpha::beginRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); @@ -115,12 +176,40 @@ void LLDrawPoolAlpha::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); - LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); - LLGLSPipelineAlpha gls_pipeline_alpha; - + + if (LLPipeline::sFastAlpha && !deferred_render) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); + if (mVertexShaderLevel > 0) + { + if (!LLPipeline::sRenderDeferred) + { + simple_shader->bind(); + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + fullbright_shader->bind(); + pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); + LLGLSLShader::bindNoShader(); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); + gPipeline.enableLightsDynamic(); + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); renderAlpha(getVertexDataMask()); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + } + if (sShowDebugAlpha) { if(gPipeline.canUseWindLightShaders()) @@ -132,20 +221,7 @@ void LLDrawPoolAlpha::render(S32 pass) LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(0)->bind(LLViewerImage::sSmokeImagep.get()); renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD); - } -} - -void LLDrawPoolAlpha::renderAlpha(U32 mask) -{ - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (group->mSpatialPartition->mRenderByGroup && - !group->isDead()) - { - renderGroupAlpha(group,LLRenderPass::PASS_ALPHA,mask,TRUE); - } + LLVertexBuffer::MAP_TEXCOORD0); } } @@ -169,7 +245,10 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } LLRenderPass::applyModelMatrix(params); - + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -178,40 +257,15 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) } } -void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) +void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - BOOL is_particle = FALSE; + //BOOL is_particle = FALSE; BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) || gPipeline.canUseWindLightShadersOnObjects(); - F32 dist; - - // check to see if it's a particle and if it's "close" - is_particle = !LLPipeline::sUnderWaterRender && (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_PARTICLES); - dist = group->mDistance; - // don't use shader if debug setting is off and it's close or if it's a particle - // and it's close - if(is_particle && !gSavedSettings.getBOOL("RenderUseShaderNearParticles")) - { - if((dist < LLViewerCamera::getInstance()->getFar() * gSavedSettings.getF32("RenderShaderParticleThreshold"))) - { - use_shaders = FALSE; - } - } - - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - - if (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CLOUDS) - { - if (!gSavedSettings.getBOOL("SkyUseClassicClouds")) - { - return; - } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - } - else + // check to see if it's a particle and if it's "close" { if (LLPipeline::sImpostorRender) { @@ -223,79 +277,109 @@ void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask } } - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { - LLDrawInfo& params = **k; - - LLRenderPass::applyModelMatrix(params); - - if (texture && params.mTexture.notNull()) + LLSpatialGroup* group = *i; + if (group->mSpatialPartition->mRenderByGroup && + !group->isDead()) { - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(params.mTexture.get()); - params.mTexture->addTextureStats(params.mVSize); - if (params.mTextureMatrix) - { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; - if (params.mFullbright) - { - // Turn off lighting if it hasn't already been so. - if (light_enabled || !initialized_lighting) + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - initialized_lighting = TRUE; - if (use_shaders) + LLDrawInfo& params = **k; + + LLRenderPass::applyModelMatrix(params); + + if (params.mTexture.notNull()) { - target_shader = fullbright_shader; + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(params.mTexture.get()); + params.mTexture->addTextureStats(params.mVSize); + if (params.mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } } - else + + if (params.mFullbright) { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + // Turn off lighting if it hasn't already been so. + if (light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = fullbright_shader; + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + light_enabled = FALSE; + } + } + // Turn on lighting if it isn't already. + else if (!light_enabled || !initialized_lighting) + { + initialized_lighting = TRUE; + if (use_shaders) + { + target_shader = simple_shader; + } + else + { + gPipeline.enableLightsDynamic(); + } + light_enabled = TRUE; } - light_enabled = FALSE; - } - } - // Turn on lighting if it isn't already. - else if (!light_enabled || !initialized_lighting) - { - initialized_lighting = TRUE; - if (use_shaders) - { - target_shader = simple_shader; - } - else - { - gPipeline.enableLightsDynamic(); - } - light_enabled = TRUE; - } - // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) - { - llassert(target_shader != NULL); - current_shader = target_shader; - current_shader->bind(); - } - else if (!use_shaders && current_shader != NULL) - { - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } + // If we need shaders, and we're not ALREADY using the proper shader, then bind it + // (this way we won't rebind shaders unnecessarily). + if(use_shaders && (current_shader != target_shader)) + { + llassert(target_shader != NULL); + if (deferred_render && current_shader != NULL) + { + gPipeline.unbindDeferredShader(*current_shader); + } + current_shader = target_shader; + if (deferred_render) + { + gPipeline.bindDeferredShader(*current_shader); + } + else + { + current_shader->bind(); + } + } + else if (!use_shaders && current_shader != NULL) + { + LLGLSLShader::bindNoShader(); + if (deferred_render) + { + gPipeline.unbindDeferredShader(*current_shader); + } + current_shader = NULL; + } - params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } + params.mVertexBuffer->setBuffer(mask); + params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount/3); - if (params.mTextureMatrix && texture && params.mTexture.notNull()) - { - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); + if (params.mTextureMatrix && params.mTexture.notNull()) + { + gGL.getTexUnit(0)->activate(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + } } } diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h index bae3c6f225..3aa752f72c 100644 --- a/indra/newview/lldrawpoolalpha.h +++ b/indra/newview/lldrawpoolalpha.h @@ -48,13 +48,23 @@ public: VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA); /*virtual*/ ~LLDrawPoolAlpha(); + /*virtual*/ S32 getNumDeferredPasses(); + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumPostDeferredPasses(); + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + /*virtual*/ void beginRenderPass(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses() { return 1; } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 563f537b11..9db9197500 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -48,12 +48,19 @@ #include "pipeline.h" #include "llviewershadermgr.h" #include "llappviewer.h" +#include "llrendersphere.h" +#include "llviewerpartsim.h" static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; static LLGLSLShader* sVertexProgram = NULL; +BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; +BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; + +extern BOOL gUseGLPick; + F32 CLOTHING_GRAVITY_EFFECT = 0.7f; F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f; const S32 NUM_TEST_AVATARS = 30; @@ -85,6 +92,8 @@ S32 AVATAR_VERTEX_BYTES = 48; BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; +S32 normal_channel = -1; +S32 specular_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -111,6 +120,7 @@ S32 LLDrawPoolAvatar::getVertexShaderLevel() const void LLDrawPoolAvatar::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR); + sShaderLevel = mVertexShaderLevel; if (sShaderLevel > 0) @@ -139,6 +149,177 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() // render() //----------------------------------------------------------------------------- + +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ + return getNumPasses(); +} + +void LLDrawPoolAvatar::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + + if (LLPipeline::sImpostorRender) + { + beginDeferredSkinned(); + return; + } + + switch (pass) + { + case 0: + beginDeferredImpostor(); + break; + case 1: + beginDeferredRigid(); + break; + case 2: + beginDeferredSkinned(); + break; + } +} + +void LLDrawPoolAvatar::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + + if (LLPipeline::sImpostorRender) + { + endDeferredSkinned(); + return; + } + + switch (pass) + { + case 0: + endDeferredImpostor(); + break; + case 1: + endDeferredRigid(); + break; + case 2: + endDeferredSkinned(); + break; + } +} + +void LLDrawPoolAvatar::renderDeferred(S32 pass) +{ + render(pass); +} + +S32 LLDrawPoolAvatar::getNumPostDeferredPasses() +{ + return 1; +} + +void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + sSkipOpaque = TRUE; + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarAlphaProgram; + + sRenderingSkinned = TRUE; + + gPipeline.bindDeferredShader(*sVertexProgram); + + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); +} + +void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + sSkipOpaque = FALSE; + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + + gPipeline.unbindDeferredShader(*sVertexProgram); + + sShaderLevel = mVertexShaderLevel; +} + +void LLDrawPoolAvatar::renderPostDeferred(S32 pass) +{ + render(2); //pass 2 = skinned +} + + +S32 LLDrawPoolAvatar::getNumShadowPasses() +{ + return 1; +} + +void LLDrawPoolAvatar::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + + sVertexProgram = &gDeferredAvatarShadowProgram; + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); + + glColor4f(1,1,1,1); + + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + +} + +void LLDrawPoolAvatar::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + + if (sShaderLevel > 0) + { + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolAvatar::renderShadow(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); + if (!gRenderAvatar) + { + return; + } + + if (mDrawFace.empty()) + { + return; + } + + const LLFace *facep = mDrawFace[0]; + if (!facep->getDrawable()) + { + return; + } + LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); + + if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) + { + return; + } + + BOOL impostor = avatarp->isImpostor(); + if (impostor) + { + return; + } + + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + +} + S32 LLDrawPoolAvatar::getNumPasses() { return LLPipeline::sImpostorRender ? 1 : 3; @@ -254,6 +435,46 @@ void LLDrawPoolAvatar::endRigid() } } +void LLDrawPoolAvatar::beginDeferredImpostor() +{ + if (!LLPipeline::sReflectionRender) + { + LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); + LLVOAvatar::sNumVisibleAvatars = 0; + } + + sVertexProgram = &gDeferredImpostorProgram; + + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + + sVertexProgram->bind(); +} + +void LLDrawPoolAvatar::endDeferredImpostor() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->unbind(); + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::beginDeferredRigid() +{ + sVertexProgram = &gDeferredDiffuseProgram; + + sVertexProgram->bind(); +} + +void LLDrawPoolAvatar::endDeferredRigid() +{ + sShaderLevel = mVertexShaderLevel; + sVertexProgram->unbind(); + gGL.getTexUnit(0)->activate(); +} + + void LLDrawPoolAvatar::beginSkinned() { if (sShaderLevel > 0) @@ -283,7 +504,7 @@ void LLDrawPoolAvatar::beginSkinned() if (sShaderLevel > 0) // for hardware blending { sRenderingSkinned = TRUE; - + sVertexProgram->bind(); if (sShaderLevel >= SHADER_LEVEL_CLOTH) { @@ -344,6 +565,34 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } +void LLDrawPoolAvatar::beginDeferredSkinned() +{ + sSkipTransparent = TRUE; + sShaderLevel = mVertexShaderLevel; + sVertexProgram = &gDeferredAvatarProgram; + + sRenderingSkinned = TRUE; + + sVertexProgram->bind(); + + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolAvatar::endDeferredSkinned() +{ + sSkipTransparent = FALSE; + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + sRenderingSkinned = FALSE; + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + sVertexProgram->unbind(); + + sShaderLevel = mVertexShaderLevel; + + gGL.getTexUnit(0)->activate(); +} + void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) { @@ -393,27 +642,25 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } - if (!single_avatar && !avatarp->isFullyLoaded()) + if (!single_avatar && !avatarp->isFullyLoaded() ) { - - /* // debug code to draw a cube in place of avatar - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLVector3 pos = avatarp->getPositionAgent(); - - gGL.color4f(1.0f, 0.0f, 0.0f, 0.8f); - gGL.begin(GL_LINES); + if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) { - gGL.vertex3fv((pos - LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.2f, 0.f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.2f, 0.f)).mV); - gGL.vertex3fv((pos - LLVector3(0.f, 0.f, 0.2f)).mV); - gGL.vertex3fv((pos + LLVector3(0.f, 0.f, 0.2f)).mV); + // debug code to draw a sphere in place of avatar + gGL.getTexUnit(0)->bind(LLViewerImage::sWhiteImagep.get()); + gGL.setColorMask(true, true); + LLVector3 pos = avatarp->getPositionAgent(); + gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); + + gGL.pushMatrix(); + gGL.translatef((F32)(pos.mV[VX]), + (F32)(pos.mV[VY]), + (F32)(pos.mV[VZ])); + gGL.scalef(0.15f, 0.15f, 0.3f); + gSphere.render(); + gGL.popMatrix(); + gGL.setColorMask(true, false); } - gGL.end(); - */ - - // don't render please return; } @@ -441,9 +688,20 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (impostor) { + if (LLPipeline::sRenderDeferred && avatarp->mImpostor.isComplete()) + { + if (normal_channel > -1) + { + avatarp->mImpostor.bindTexture(2, normal_channel); + } + if (specular_channel > -1) + { + avatarp->mImpostor.bindTexture(1, specular_channel); + } + } avatarp->renderImpostor(); } - else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS)) + else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { avatarp->renderFootShadows(); } @@ -680,11 +938,7 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD])); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 9df510f1e0..0dc95ff536 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -52,7 +52,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_WEIGHT | LLVertexBuffer::MAP_CLOTHWEIGHT }; @@ -74,6 +74,21 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); + /*virtual*/ S32 getNumDeferredPasses(); + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumPostDeferredPasses(); + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses(); + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); + void beginRigid(); void beginFootShadow(); void beginSkinned(); @@ -81,11 +96,22 @@ public: void endRigid(); void endFootShadow(); void endSkinned(); + + void beginDeferredImpostor(); + void beginDeferredRigid(); + void beginDeferredSkinned(); + + void endDeferredImpostor(); + void endDeferredRigid(); + void endDeferredSkinned(); /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. + + static BOOL sSkipOpaque; + static BOOL sSkipTransparent; }; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 60c41159d2..b11dcc1608 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -71,13 +71,14 @@ LLBumpImageList gBumpImageList; const S32 STD_BUMP_LATEST_FILE_VERSION = 1; const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; -const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2; +const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY; static LLGLSLShader* shader = NULL; static S32 cube_channel = -1; static S32 diffuse_channel = -1; +static S32 bump_channel = -1; // static void LLStandardBumpmap::init() @@ -146,7 +147,8 @@ void LLStandardBumpmap::restoreGL() TRUE, FALSE, 0, - 0); + 0); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL ); LLStandardBumpmap::sStandardBumpmapCount++; } @@ -318,7 +320,7 @@ void LLDrawPoolBump::beginShiny(bool invisible) // Second pass: environment map if (!invisible && mVertexShaderLevel > 1) { - sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD; + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } if (LLPipeline::sUnderWaterRender) @@ -432,15 +434,7 @@ void LLDrawPoolBump::endShiny(bool invisible) shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } } - shader->unbind(); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - } - if (cube_channel >= 0) - { - gGL.getTexUnit(cube_channel)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(cube_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } } gGL.getTexUnit(diffuse_channel)->disable(); @@ -462,7 +456,7 @@ void LLDrawPoolBump::beginFullbrightShiny() return; } - sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD; + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; // Second pass: environment map @@ -561,6 +555,10 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL applyModelMatrix(params); + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -569,7 +567,7 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL // static -BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params) +BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { LLImageGL* bump = NULL; @@ -600,10 +598,19 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params) if (bump) { - gGL.getTexUnit(1)->bind(bump); - gGL.getTexUnit(0)->bind(bump); + if (channel == -2) + { + gGL.getTexUnit(1)->bind(bump); + gGL.getTexUnit(0)->bind(bump); + } + else + { + gGL.getTexUnit(channel)->bind(bump); + } + return TRUE; } + return FALSE; } @@ -691,6 +698,73 @@ void LLDrawPoolBump::endBump() gGL.setSceneBlendType(LLRender::BT_ALPHA); } +void LLDrawPoolBump::beginDeferredPass(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + mShiny = TRUE; + gDeferredBumpProgram.bind(); + diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE); +} + +void LLDrawPoolBump::endDeferredPass(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + mShiny = FALSE; + gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP); + gDeferredBumpProgram.unbind(); + gGL.getTexUnit(0)->activate(); +} + +void LLDrawPoolBump::renderDeferred(S32 pass) +{ + if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); + + U32 type = LLRenderPass::PASS_BUMP; + LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; + + for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; + + LLDrawPoolBump::bindBumpMap(params, bump_channel); + pushBatch(params, mask, TRUE); + } +} + +void LLDrawPoolBump::beginPostDeferredPass(S32 pass) +{ + beginFullbrightShiny(); +} + +void LLDrawPoolBump::endPostDeferredPass(S32 pass) +{ + endFullbrightShiny(); +} + +void LLDrawPoolBump::renderPostDeferred(S32 pass) +{ + renderFullbrightShiny(); +} + //////////////////////////////////////////////////////////////// // List of one-component bump-maps created from other texures. @@ -748,6 +822,7 @@ void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 void LLBumpImageList::updateImages() { + llpushcallstacks ; for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -774,7 +849,7 @@ void LLBumpImageList::updateImages() } } } - + llpushcallstacks ; for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -801,7 +876,7 @@ void LLBumpImageList::updateImages() } } } - + llpushcallstacks ; } @@ -886,6 +961,71 @@ void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerImage *src_v } } +void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerImage* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) +{ + if (success && LLPipeline::sRenderDeferred) + { + LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); + generateNormalMapFromAlpha(src, nrm_image); + src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); + src_vi->createGLTexture(0, nrm_image); + } +} + +void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image) +{ + U8* nrm_data = nrm_image->getData(); + S32 resX = src->getWidth(); + S32 resY = src->getHeight(); + + U8* src_data = src->getData(); + + S32 src_cmp = src->getComponents(); + + F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale"); + + U32 idx = 0; + //generate normal map from pseudo-heightfield + for (S32 j = 0; j < resY; ++j) + { + for (S32 i = 0; i < resX; ++i) + { + S32 rX = (i+1)%resX; + S32 rY = (j+1)%resY; + S32 lX = (i-1)%resX; + S32 lY = (j-1)%resY; + + if (lX < 0) + { + lX += resX; + } + if (lY < 0) + { + lY += resY; + } + + F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1]; + + LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH); + LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH); + LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH); + LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH); + + LLVector3 norm = right%down + down%left + left%up + up%right; + + norm.normVec(); + + norm *= 0.5f; + norm += LLVector3(0.5f,0.5f,0.5f); + + idx = (j*resX+i)*4; + nrm_data[idx+0]= (U8) (norm.mV[0]*255); + nrm_data[idx+1]= (U8) (norm.mV[1]*255); + nrm_data[idx+2]= (U8) (norm.mV[2]*255); + nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1]; + } + } +} // static void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code ) @@ -1005,14 +1145,26 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma } //--------------------------------------------------- - LLImageGL* bump = new LLImageGL( TRUE); //immediately assign bump to a global smart pointer in case some local smart pointer //accidently releases it. + LLPointer<LLImageGL> bump = new LLImageGL( TRUE); + + if (!LLPipeline::sRenderDeferred) + { + bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); + bump->createGLTexture(0, dst_image); + } + else + { + LLPointer<LLImageRaw> nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); + generateNormalMapFromAlpha(src, nrm_image); + bump->setExplicitFormat(GL_RGBA, GL_RGBA); + bump->createGLTexture(0, nrm_image); + } + + iter->second = bump; // derefs (and deletes) old image //--------------------------------------------------- - - bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - bump->createGLTexture(0, dst_image); } else { @@ -1040,21 +1192,6 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) } } -void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask) -{ - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - if (LLDrawPoolBump::bindBumpMap(params)) - { - pushBatch(params, mask, FALSE); - } - } -} - void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { applyModelMatrix(params); @@ -1088,10 +1225,14 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); } } + if (params.mGroup) + { + params.mGroup->rebuildMesh(); + } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); @@ -1131,3 +1272,33 @@ void LLDrawPoolInvisible::render(S32 pass) } } +void LLDrawPoolInvisible::beginDeferredPass(S32 pass) +{ + beginRenderPass(pass); +} + +void LLDrawPoolInvisible::endDeferredPass( S32 pass ) +{ + endRenderPass(pass); +} + +void LLDrawPoolInvisible::renderDeferred( S32 pass ) +{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff + LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + + U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; + glStencilMask(0); + glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE); + gGL.setColorMask(false, false); + pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE); + gGL.setColorMask(true, true); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFFFFFFFF); + + if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + { + beginShiny(true); + renderShiny(true); + endShiny(true); + } +} diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index f5cb0cb769..34c1e9c29f 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -49,7 +49,7 @@ protected : public: static U32 sVertexMask; BOOL mShiny; - + virtual U32 getVertexDataMask() { return sVertexMask; } LLDrawPoolBump(); @@ -63,8 +63,7 @@ public: void renderBump(U32 type, U32 mask); void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); - void renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask); - + S32 numBumpPasses(); void beginShiny(bool invisible = false); @@ -78,7 +77,18 @@ public: void beginBump(); void renderBump(); void endBump(); - BOOL bindBumpMap(LLDrawInfo& params); + + virtual S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + virtual S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); + + BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); }; enum EBumpEffect @@ -136,6 +146,9 @@ public: static void onSourceBrightnessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); static void onSourceDarknessLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); + static void onSourceStandardLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); + static void generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image); + private: static void onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump ); @@ -166,6 +179,11 @@ public: virtual void beginRenderPass( S32 pass ) { } virtual void endRenderPass( S32 pass ) { } virtual S32 getNumPasses() {return 1;} + + virtual S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); }; diff --git a/indra/newview/lldrawpoolclouds.h b/indra/newview/lldrawpoolclouds.h index 0346e1aa4e..c70dd41f78 100644 --- a/indra/newview/lldrawpoolclouds.h +++ b/indra/newview/lldrawpoolclouds.h @@ -42,7 +42,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; BOOL addFace(LLFace* face); diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h index 0badb59968..6c7d20beca 100644 --- a/indra/newview/lldrawpoolground.h +++ b/indra/newview/lldrawpoolground.h @@ -42,7 +42,7 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index d4bdfc494a..1fdf87f6d2 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -103,18 +103,15 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { simple_shader = &gObjectSimpleWaterProgram; - fullbright_shader = &gObjectFullbrightWaterProgram; } else { simple_shader = &gObjectSimpleProgram; - fullbright_shader = &gObjectFullbrightProgram; } if (mVertexShaderLevel > 0) { simple_shader->bind(); - simple_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 0.f); } else { @@ -140,39 +137,204 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) void LLDrawPoolSimple::render(S32 pass) { LLGLDisable blend(GL_BLEND); - LLGLState alpha_test(GL_ALPHA_TEST, gPipeline.canUseWindLightShadersOnObjects()); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + LLGLDisable alpha_test(GL_ALPHA_TEST); + { //render simple LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); gPipeline.enableLightsDynamic(); renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + + if (LLPipeline::sRenderDeferred) + { + renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask()); + } } +} + +//=============================== +//DEFERRED IMPLEMENTATION +//=============================== + +void LLDrawPoolSimple::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + gDeferredDiffuseProgram.bind(); +} + +void LLDrawPoolSimple::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + LLRenderPass::endRenderPass(pass); + + gDeferredDiffuseProgram.unbind(); +} + +void LLDrawPoolSimple::renderDeferred(S32 pass) +{ + LLGLDisable blend(GL_BLEND); + LLGLDisable alpha_test(GL_ALPHA_TEST); + + { //render simple + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + } +} + +// grass drawpool +LLDrawPoolGrass::LLDrawPoolGrass() : + LLRenderPass(POOL_GRASS) +{ + +} + +void LLDrawPoolGrass::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + + +void LLDrawPoolGrass::beginRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + + if (LLPipeline::sUnderWaterRender) + { + simple_shader = &gObjectSimpleWaterProgram; + } + else + { + simple_shader = &gObjectSimpleProgram; + } + + if (mVertexShaderLevel > 0) + { + simple_shader->bind(); + } + else + { + // don't use shaders! + if (gGLManager.mHasShaderObjects) + { + LLGLSLShader::bindNoShader(); + } + } +} + +void LLDrawPoolGrass::endRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLRenderPass::endRenderPass(pass); + + if (mVertexShaderLevel > 0) + { + simple_shader->unbind(); + } +} + +void LLDrawPoolGrass::render(S32 pass) +{ + LLGLDisable blend(GL_BLEND); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); LLGLEnable test(GL_ALPHA_TEST); - LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); } - { //render fullbright - if (mVertexShaderLevel > 0) - { - fullbright_shader->bind(); - fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); - } - else - { - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - } - LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR; - renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); - } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +void LLDrawPoolGrass::beginDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolGrass::endDeferredPass(S32 pass) +{ + +} + +void LLDrawPoolGrass::renderDeferred(S32 pass) +{ + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + + { + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + gDeferredTreeProgram.bind(); + LLGLEnable test(GL_ALPHA_TEST); + //render grass + LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); + } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } + +// Fullbright drawpool +LLDrawPoolFullbright::LLDrawPoolFullbright() : + LLRenderPass(POOL_FULLBRIGHT) +{ +} + +void LLDrawPoolFullbright::prerender() +{ + mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); +} + +void LLDrawPoolFullbright::beginRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + + if (LLPipeline::sUnderWaterRender) + { + fullbright_shader = &gObjectFullbrightWaterProgram; + } + else + { + fullbright_shader = &gObjectFullbrightProgram; + } +} + +void LLDrawPoolFullbright::endRenderPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + LLRenderPass::endRenderPass(pass); + + if (mVertexShaderLevel > 0) + { + fullbright_shader->unbind(); + } +} + +void LLDrawPoolFullbright::render(S32 pass) +{ //render fullbright + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + if (mVertexShaderLevel > 0) + { + fullbright_shader->bind(); + fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + } + + //gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); + + //LLGLEnable test(GL_ALPHA_TEST); + //LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; + renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); + + //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +} + +S32 LLDrawPoolFullbright::getNumPasses() +{ + return 1; +} + diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index 6702715b9e..f561510375 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -42,19 +42,77 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } LLDrawPoolSimple(); + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /// We need two passes so we can handle emissive materials separately. + /*virtual*/ S32 getNumPasses() { return 1; } + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); + +}; + +class LLDrawPoolGrass : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolGrass(); + + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + /*virtual*/ void beginRenderPass(S32 pass); /*virtual*/ void endRenderPass(S32 pass); /// We need two passes so we can handle emissive materials separately. /*virtual*/ S32 getNumPasses() { return 1; } /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); +}; + +class LLDrawPoolFullbright : public LLRenderPass +{ +public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR + }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolFullbright(); + + /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); + /*virtual*/ S32 getNumPasses(); + /*virtual*/ void render(S32 pass = 0); + /*virtual*/ void prerender(); }; @@ -66,13 +124,18 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } virtual void prerender() { } + /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + void render(S32 pass = 0); void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE); diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 027b925e09..7f21adcc94 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -62,7 +62,7 @@ LLDrawPool *LLDrawPoolSky::instancePool() void LLDrawPoolSky::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); - gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); +// gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); } void LLDrawPoolSky::render(S32 pass) diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h index a7fad72ea1..f35b114730 100644 --- a/indra/newview/lldrawpoolsky.h +++ b/indra/newview/lldrawpoolsky.h @@ -50,7 +50,7 @@ public: enum { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -59,6 +59,11 @@ public: /*virtual*/ LLDrawPool *instancePool(); + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 3080f99d9f..2c644b0fd5 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -74,14 +74,14 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); - mAlphaRampImagep->setClamp(TRUE, TRUE); + mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); m2DAlphaRampImagep = gImageList.getImageFromFile("alpha_gradient_2d.j2c", TRUE, TRUE, GL_ALPHA8, GL_ALPHA, LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); - m2DAlphaRampImagep->setClamp(TRUE, TRUE); + m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mTexturep->setBoostLevel(LLViewerImage::BOOST_TERRAIN); @@ -100,6 +100,18 @@ LLDrawPool *LLDrawPoolTerrain::instancePool() } +U32 LLDrawPoolTerrain::getVertexDataMask() +{ + if (LLPipeline::sShadowRender) + { + return LLVertexBuffer::MAP_VERTEX; + } + else + { + return VERTEX_DATA_MASK; + } +} + void LLDrawPoolTerrain::prerender() { mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); @@ -217,6 +229,60 @@ void LLDrawPoolTerrain::render(S32 pass) } } +void LLDrawPoolTerrain::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFacePool::beginRenderPass(pass); + + sShader = &gDeferredTerrainProgram; + + sShader->bind(); +} + +void LLDrawPoolTerrain::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + LLFacePool::endRenderPass(pass); + sShader->unbind(); +} + +void LLDrawPoolTerrain::renderDeferred(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); + if (mDrawFace.empty()) + { + return; + } + renderFullShader(); +} + +void LLDrawPoolTerrain::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFacePool::beginRenderPass(pass); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gDeferredShadowProgram.bind(); +} + +void LLDrawPoolTerrain::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + LLFacePool::endRenderPass(pass); + gDeferredShadowProgram.unbind(); +} + +void LLDrawPoolTerrain::renderShadow(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TERRAIN); + if (mDrawFace.empty()) + { + return; + } + //LLGLEnable offset(GL_POLYGON_OFFSET); + //glCullFace(GL_FRONT); + drawLoop(); + //glCullFace(GL_BACK); +} void LLDrawPoolTerrain::renderFullShader() { @@ -360,9 +426,6 @@ void LLDrawPoolTerrain::renderFullShader() void LLDrawPoolTerrain::renderFull4TU() { - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); @@ -390,7 +453,6 @@ void LLDrawPoolTerrain::renderFull4TU() // gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture0p); - glClientActiveTextureARB(GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); @@ -409,9 +471,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - + // Care about alpha only gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); @@ -423,9 +483,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -441,14 +498,12 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->bind(detail_texture1p); gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - + // Set alpha texture and do lighting modulation gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR); gGL.getTexUnit(0)->activate(); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - + // GL_BLEND disabled by default drawLoop(); @@ -459,9 +514,7 @@ void LLDrawPoolTerrain::renderFull4TU() // gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture3p); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -477,9 +530,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Set the texture matrix glMatrixMode(GL_TEXTURE); @@ -490,7 +540,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // // Stage 2: Interpolate detail2 with existing based on ramp // @@ -498,9 +547,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -517,9 +563,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - // Set the texture matrix glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -530,7 +573,6 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); gGL.getTexUnit(0)->activate(); - glClientActiveTextureARB(GL_TEXTURE0_ARB); { LLGLEnable blend(GL_BLEND); drawLoop(); @@ -541,9 +583,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(3)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(3)->disable(); gGL.getTexUnit(3)->activate(); - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -551,9 +591,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->disable(); gGL.getTexUnit(2)->activate(); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glMatrixMode(GL_TEXTURE); @@ -563,9 +601,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->disable(); gGL.getTexUnit(1)->activate(); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - + glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -579,9 +615,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glDisableClientState(GL_NORMAL_ARRAY); - + glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glMatrixMode(GL_TEXTURE); @@ -856,7 +890,7 @@ void LLDrawPoolTerrain::renderOwnership() { LLFace *facep = *iter; facep->renderIndexed(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD); + LLVertexBuffer::MAP_TEXCOORD0); } glMatrixMode(GL_TEXTURE); diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index b243486bf4..19d09e2feb 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -43,12 +43,14 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_TEXCOORD3 | LLVertexBuffer::MAP_COLOR }; - virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + virtual U32 getVertexDataMask(); static S32 getDetailMode(); LLDrawPoolTerrain(LLViewerImage *texturep); @@ -56,6 +58,15 @@ public: /*virtual*/ LLDrawPool *instancePool(); + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses() { return 1; } + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 616461d06e..2f2b07232a 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -43,6 +43,7 @@ #include "llviewercamera.h" #include "llviewershadermgr.h" #include "llrender.h" +#include "llviewercontrol.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -52,7 +53,7 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : mTexturep(texturep) { gGL.getTexUnit(0)->bind(mTexturep.get()); - mTexturep->setClamp(FALSE, FALSE); + mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } LLDrawPool *LLDrawPoolTree::instancePool() @@ -91,7 +92,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) void LLDrawPoolTree::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + LLFastTimer t(LLPipeline::sShadowRender ? LLFastTimer::FTM_SHADOW_TREE : LLFastTimer::FTM_RENDER_TREES); if (mDrawFace.empty()) { @@ -101,7 +102,23 @@ void LLDrawPoolTree::render(S32 pass) LLGLEnable test(GL_ALPHA_TEST); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); - renderTree(); + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + renderTree(); + } + else + { + gGL.getTexUnit(sDiffTex)->bind(mTexturep); + + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + } + } } void LLDrawPoolTree::endRenderPass(S32 pass) @@ -115,6 +132,54 @@ void LLDrawPoolTree::endRenderPass(S32 pass) } } +//============================================ +// deferred implementation +//============================================ +void LLDrawPoolTree::beginDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + + shader = &gDeferredTreeProgram; + shader->bind(); +} + +void LLDrawPoolTree::renderDeferred(S32 pass) +{ + render(pass); +} + +void LLDrawPoolTree::endDeferredPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + + shader->unbind(); +} + +//============================================ +// shadow implementation +//============================================ +void LLDrawPoolTree::beginShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + gDeferredShadowProgram.bind(); +} + +void LLDrawPoolTree::renderShadow(S32 pass) +{ + render(pass); +} + +void LLDrawPoolTree::endShadowPass(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + gDeferredShadowProgram.unbind(); +} + + void LLDrawPoolTree::renderForSelect() { if (mDrawFace.empty()) @@ -133,7 +198,43 @@ void LLDrawPoolTree::renderForSelect() gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - renderTree(TRUE); + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + renderTree(TRUE); + } + else + { + gGL.getTexUnit(sDiffTex)->bind(mTexturep); + + for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + LLDrawable *drawablep = face->getDrawable(); + + if (drawablep->isDead() || face->mVertexBuffer.isNull()) + { + continue; + } + + // Render each of the trees + LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get(); + + LLColor4U color(255,255,255,255); + + if (treep->mGLName != 0) + { + S32 name = treep->mGLName; + color = LLColor4U((U8)(name >> 16), (U8)(name >> 8), (U8)name, 255); + + LLFacePool::LLOverrideFaceColor col(this, color); + + face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + } + } + } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ALPHA); diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h index 5fbbb20bc0..80c4fdfffe 100644 --- a/indra/newview/lldrawpooltree.h +++ b/indra/newview/lldrawpooltree.h @@ -43,7 +43,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -53,6 +53,17 @@ public: /*virtual*/ LLDrawPool *instancePool(); /*virtual*/ void prerender(); + + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); + + /*virtual*/ S32 getNumShadowPasses() { return 1; } + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); + /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 2005184454..ce3425dd9e 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -59,6 +59,8 @@ const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004"); static float sTime; +BOOL deferred_render = FALSE; + BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE; BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE; @@ -70,14 +72,16 @@ LLDrawPoolWater::LLDrawPoolWater() : { mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE); gGL.getTexUnit(0)->bind(mHBTex[0].get()); - mHBTex[0]->setClamp(TRUE, TRUE); + mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE); gGL.getTexUnit(0)->bind(mHBTex[1].get()); - mHBTex[1]->setClamp(TRUE, TRUE); + mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); mWaterImagep = gImageList.getImage(WATER_TEST); + mWaterImagep->setNoDelete() ; mWaterNormp = gImageList.getImage(DEFAULT_WATER_NORMAL); + mWaterNormp->setNoDelete() ; restoreGL(); } @@ -121,6 +125,18 @@ S32 LLDrawPoolWater::getNumPasses() return 0; } +void LLDrawPoolWater::beginPostDeferredPass(S32 pass) +{ + beginRenderPass(pass); + deferred_render = TRUE; +} + +void LLDrawPoolWater::endPostDeferredPass(S32 pass) +{ + endRenderPass(pass); + deferred_render = FALSE; +} + void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); @@ -271,10 +287,7 @@ void LLDrawPoolWater::render(S32 pass) gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - if (gSky.mVOSkyp->getCubeMap()) - { - gSky.mVOSkyp->getCubeMap()->disable(); - } + gSky.mVOSkyp->getCubeMap()->disable(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); @@ -375,7 +388,11 @@ void LLDrawPoolWater::shade() F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight(); - if (eyedepth < 0.f && LLPipeline::sWaterReflections) + if (deferred_render) + { + shader = &gDeferredWaterProgram; + } + else if (eyedepth < 0.f && LLPipeline::sWaterReflections) { shader = &gUnderWaterProgram; } @@ -408,21 +425,36 @@ void LLDrawPoolWater::shade() mWaterNormp->addTextureStats(1024.f*1024.f); gGL.getTexUnit(bumpTex)->bind(mWaterNormp.get()); - mWaterNormp->setMipFilterNearest (mWaterNormp->getMipFilterNearest(), - !gSavedSettings.getBOOL("RenderWaterMipNormal")); + if (gSavedSettings.getBOOL("RenderWaterMipNormal")) + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + else + { + mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT); + } S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX); - stop_glerror(); + + if (deferred_render) + { + gPipeline.bindDeferredShader(*shader); + } + else + { + shader->bind(); + } - shader->bind(); - if (screentex > -1) { shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); shader->uniform1f(LLViewerShaderMgr::WATER_FOGDENSITY, param_mgr->getFogDensity()); + gPipeline.mWaterDis.bindTexture(0, screentex); } - + + stop_glerror(); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); if (mVertexShaderLevel == 1) @@ -534,7 +566,15 @@ void LLDrawPoolWater::shade() shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); shader->disableTexture(LLViewerShaderMgr::WATER_REFTEX); shader->disableTexture(LLViewerShaderMgr::WATER_SCREENDEPTH); - shader->unbind(); + + if (deferred_render) + { + gPipeline.unbindDeferredShader(*shader); + } + else + { + shader->unbind(); + } gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index 2eb358b289..6351041140 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -60,7 +60,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD + LLVertexBuffer::MAP_TEXCOORD0 }; virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } @@ -70,6 +70,11 @@ public: /*virtual*/ LLDrawPool *instancePool(); static void restoreGL(); + + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } /*virtual*/ S32 getNumPasses(); /*virtual*/ void render(S32 pass = 0); diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index 1eb3e5fd90..c7a1f3fe27 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -41,7 +41,7 @@ class LLDrawPoolWLSky : public LLDrawPool { public: static const U32 SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; static const U32 STAR_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; @@ -50,6 +50,11 @@ public: /*virtual*/ BOOL isDead() { return FALSE; } + /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } + /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } + /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } + /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void endRenderPass( S32 pass ); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 6951f3a96a..62fcf60e7f 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -112,7 +112,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima } // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; mTexture->createGLTexture(0, raw_image); - mTexture->setClamp(mClamp, mClamp); + mTexture->setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); mTexture->setGLTextureCreated(false); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index dc3e2f1896..e096bc07bd 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -165,6 +165,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mReferenceIndex = -1; mTextureMatrix = NULL; + mDrawInfo = NULL; mFaceColor = LLColor4(1,0,0,1); @@ -178,9 +179,6 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) void LLFace::destroy() { - mDrawablep = NULL; - mVObjp = NULL; - if (mDrawPoolp) { mDrawPoolp->removeFace(this); @@ -191,7 +189,21 @@ void LLFace::destroy() { delete mTextureMatrix; mTextureMatrix = NULL; + + if (mDrawablep.notNull()) + { + LLSpatialGroup* group = mDrawablep->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + } + } } + + setDrawInfo(NULL); + + mDrawablep = NULL; + mVObjp = NULL; } @@ -289,7 +301,7 @@ U16 LLFace::getGeometryAvatar( { mVertexBuffer->getVertexStrider (vertices, mGeomIndex); mVertexBuffer->getNormalStrider (normals, mGeomIndex); - mVertexBuffer->getTexCoordStrider (tex_coords, mGeomIndex); + mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex); mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex); mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex); } @@ -309,9 +321,9 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no { mVertexBuffer->getNormalStrider(normals, mGeomIndex); } - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD)) + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0)) { - mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex); + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); } mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); @@ -435,12 +447,13 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color) setFaceColor(color); renderSetColor(); - mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); #endif mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - + + unsetFaceColor(); unsetFaceColor(); gGL.popMatrix(); } @@ -477,9 +490,27 @@ void LLFace::renderSelectedUV() glMatrixMode(GL_MODELVIEW); gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); } - */ +void LLFace::setDrawInfo(LLDrawInfo* draw_info) +{ + if (draw_info) + { + if (draw_info->mFace) + { + draw_info->mFace->setDrawInfo(NULL); + } + draw_info->mFace = this; + } + + if (mDrawInfo) + { + mDrawInfo->mFace = NULL; + } + + mDrawInfo = draw_info; +} + void LLFace::printDebugInfo() const { LLFacePool *poolp = getPool(); @@ -587,11 +618,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) { - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - { //vertex buffer no longer valid - mVertexBuffer = NULL; - mLastVertexBuffer = NULL; - } + //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + //{ //vertex buffer no longer valid + // mVertexBuffer = NULL; + // mLastVertexBuffer = NULL; + //} LLVector3 min,max; @@ -739,6 +770,34 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, return tc; } +void LLFace::updateRebuildFlags() +{ + if (!mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + BOOL moved = TRUE; + if (mLastVertexBuffer == mVertexBuffer && + !mVertexBuffer->isEmpty()) + { //this face really doesn't need to be regenerated, try real hard not to do so + if (mLastGeomCount == mGeomCount && + mLastGeomIndex == mGeomIndex && + mLastIndicesCount == mIndicesCount && + mLastIndicesIndex == mIndicesIndex) + { //data is in same location in vertex buffer + moved = FALSE; + } + } + mLastMoveTime = gFrameTimeSeconds; + + if (moved) + { + mDrawablep->setState(LLDrawable::REBUILD_VOLUME); + } + } + else + { + mLastUpdateTime = gFrameTimeSeconds; + } +} BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, @@ -764,16 +823,16 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - LLStrider<LLVector3> old_verts,vertices; - LLStrider<LLVector2> old_texcoords,tex_coords; - LLStrider<LLVector2> old_texcoords2,tex_coords2; - LLStrider<LLVector3> old_normals,normals; - LLStrider<LLColor4U> old_colors,colors; + LLStrider<LLVector3> vertices; + LLStrider<LLVector2> tex_coords; + LLStrider<LLVector2> tex_coords2; + LLStrider<LLVector3> normals; + LLStrider<LLColor4U> colors; + LLStrider<LLVector3> binormals; LLStrider<U16> indicesp; BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); - BOOL moved = TRUE; - + BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; if (global_volume) @@ -784,35 +843,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { scale = mVObjp->getScale(); } - - if (!full_rebuild) - { - if (mLastVertexBuffer == mVertexBuffer && - !mVertexBuffer->isEmpty()) - { //this face really doesn't need to be regenerated, try real hard not to do so - if (mLastGeomCount == mGeomCount && - mLastGeomIndex == mGeomIndex && - mLastIndicesCount == mIndicesCount && - mLastIndicesIndex == mIndicesIndex) - { //data is in same location in vertex buffer - moved = FALSE; - } - - if (!moved && !mDrawablep->isState(LLDrawable::REBUILD_ALL)) - { //nothing needs to be done - return FALSE; - } - } - mLastMoveTime = gFrameTimeSeconds; - } - else - { - mLastUpdateTime = gFrameTimeSeconds; - } - BOOL rebuild_pos = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_POSITION); - BOOL rebuild_color = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_COLOR); - BOOL rebuild_tcoord = full_rebuild || moved || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); + BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); + BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); const LLTextureEntry *tep = mVObjp->getTE(f); U8 bump_code = tep ? tep->getBumpmap() : 0; @@ -820,14 +856,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (rebuild_pos) { mVertexBuffer->getVertexStrider(vertices, mGeomIndex); + } + if (rebuild_normal) + { mVertexBuffer->getNormalStrider(normals, mGeomIndex); } + if (rebuild_binormal) + { + mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); + } if (rebuild_tcoord) { - mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex); - if (bump_code) + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); + if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { - mVertexBuffer->getTexCoord2Strider(tex_coords2, mGeomIndex); + mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); } } if (rebuild_color) @@ -922,14 +965,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 0.75f }; - if (getPoolType() != LLDrawPool::POOL_ALPHA && LLPipeline::sRenderBump && tep->getShiny()) + if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } } // INDICES - if (full_rebuild || moved) + if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); for (U16 i = 0; i < num_indices; i++) @@ -1046,7 +1089,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords++ = tc; - if (bump_code) + if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) { LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; @@ -1066,38 +1109,31 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, *tex_coords2++ = tc; } } - else if (moved) - { - *tex_coords++ = *old_texcoords++; - if (bump_code) - { - *tex_coords2++ = *old_texcoords2++; - } - } if (rebuild_pos) { *vertices++ = vf.mVertices[i].mPosition * mat_vert; - + } + + if (rebuild_normal) + { LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; normal.normVec(); *normals++ = normal; } - else if (moved) + + if (rebuild_binormal) { - *normals++ = *old_normals++; - *vertices++ = *old_verts++; + LLVector3 binormal = vf.mVertices[i].mBinormal * mat_normal; + binormal.normVec(); + *binormals++ = binormal; } - + if (rebuild_color) { *colors++ = color; } - else if (moved) - { - *colors++ = *old_colors++; - } } if (rebuild_tcoord) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index dfe5ab6277..4a551ff261 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -134,7 +134,9 @@ public: const LLColor4& getFaceColor() const { return mFaceColor; } const LLColor4& getRenderColor() const; + //for volumes + void updateRebuildFlags(); BOOL getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, @@ -169,7 +171,7 @@ public: void updateCenterAgent(); // Update center when xform has changed. void renderSelectedUV(); - void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); + void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); void renderSelected(LLImageGL *image, const LLColor4 &color); F32 getKey() const { return mDistance; } @@ -182,10 +184,12 @@ public: void setGeomIndex(U16 idx) { mGeomIndex = idx; } void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } - + void setDrawInfo(LLDrawInfo* draw_info); + protected: public: + LLVector3 mCenterLocal; LLVector3 mCenterAgent; LLVector3 mExtents[2]; @@ -196,6 +200,7 @@ public: F32 mLastUpdateTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; + LLDrawInfo* mDrawInfo; protected: friend class LLGeometryManager; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 25a26f05d8..340254a909 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -162,8 +162,14 @@ static struct ft_display_info ft_display_table[] = // { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 }, { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 }, // { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 }, -// { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, - { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, + { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, + { LLFastTimer::FTM_SHADOW_RENDER, " Shadow", &LLColor4::green5, 1 }, + { LLFastTimer::FTM_SHADOW_SIMPLE, " Simple", &LLColor4::yellow2, 1 }, + { LLFastTimer::FTM_SHADOW_ALPHA, " Alpha", &LLColor4::yellow6, 1 }, + { LLFastTimer::FTM_SHADOW_TERRAIN, " Terrain", &LLColor4::green6, 1 }, + { LLFastTimer::FTM_SHADOW_AVATAR, " Avatar", &LLColor4::yellow1, 1 }, + { LLFastTimer::FTM_SHADOW_TREE, " Tree", &LLColor4::yellow8, 1 }, + { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 }, { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 }, { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 }, diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index c23d58cb7a..2652387bfe 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -122,6 +122,14 @@ LLFloaterAbout::LLFloaterAbout() std::string support; support.append("\n\n"); +#if LL_MSVC + support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER)); +#endif + +#if LL_GNUC + support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION)); +#endif + // Position LLViewerRegion* region = gAgent.getRegion(); if (region) diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 045ca6aa36..747b685b5e 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -236,9 +236,11 @@ BOOL LLFloaterAnimPreview::postBuild() // now load bvh file S32 file_size; - apr_file_t* fp = ll_apr_file_open(mFilenameAndPath, LL_APR_RB, &file_size); - - if (!fp) + + LLAPRFile infile ; + infile.open(mFilenameAndPath, LL_APR_RB, NULL, &file_size); + + if (!infile.getFileHandle()) { llwarns << "Can't open BVH file:" << mFilename << llendl; } @@ -248,14 +250,14 @@ BOOL LLFloaterAnimPreview::postBuild() file_buffer = new char[file_size + 1]; - if (file_size == ll_apr_file_read(fp, file_buffer, file_size)) + if (file_size == infile.read(file_buffer, file_size)) { file_buffer[file_size] = '\0'; llinfos << "Loading BVH file " << mFilename << llendl; loaderp = new LLBVHLoader(file_buffer); } - apr_file_close(fp); + infile.close() ; delete[] file_buffer; } } diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index 2dabb55eaa..747431fb19 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -207,7 +207,7 @@ void LLFloaterAuction::onClickSnapshot(void* data) self->mImage = new LLImageGL((LLImageRaw*)raw, FALSE); gGL.getTexUnit(0)->bind(self->mImage); - self->mImage->setClamp(TRUE, TRUE); + self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP); } else { diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 4f8c5ce4eb..f82d692dd3 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -167,7 +167,7 @@ createUI () } mRGBImage = new LLImageGL ( (LLImageRaw*)raw, FALSE ); gGL.getTexUnit(0)->bind(mRGBImage); - mRGBImage->setClamp(TRUE, TRUE); + mRGBImage->setAddressMode(LLTexUnit::TAM_CLAMP); // create palette for ( S32 each = 0; each < numPaletteColumns * numPaletteRows; ++each ) diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 67be553ae7..689f9f48d0 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -234,8 +234,7 @@ void LLFloaterImagePreview::draw() gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); if (mAvatarPreview) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 14caed9d97..164c33b10d 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -862,9 +862,17 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) } previewp->mViewerImage[previewp->mCurImageIndex] = new LLImageGL(scaled, FALSE); - previewp->mViewerImage[previewp->mCurImageIndex]->setMipFilterNearest(previewp->getSnapshotType() != SNAPSHOT_TEXTURE); - gGL.getTexUnit(0)->bind(previewp->mViewerImage[previewp->mCurImageIndex]); - previewp->mViewerImage[previewp->mCurImageIndex]->setClamp(TRUE, TRUE); + LLPointer<LLImageGL> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex]; + gGL.getTexUnit(0)->bind(curr_preview_image); + if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE) + { + curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT); + } + else + { + curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + } + curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP); previewp->mSnapshotUpToDate = TRUE; previewp->generateThumbnailImage(TRUE) ; diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index 0c7d785ae0..3535fe185c 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -184,7 +184,7 @@ void LLHUDIcon::renderIcon(BOOL for_select) void LLHUDIcon::setImage(LLViewerImage* imagep) { mImagep = imagep; - mImagep->setClamp(TRUE, TRUE); + mImagep->setAddressMode(LLTexUnit::TAM_CLAMP); } void LLHUDIcon::setScale(F32 fraction_of_fov) diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 0e9f7c16a6..bdff492948 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -131,7 +131,7 @@ void LLHUDObject::cleanupHUDObjects() (*object_it)->markDead(); if ((*object_it)->getNumRefs() > 1) { - llinfos << "LLHUDObject " << (LLHUDObject *)(*object_it) << " has " << (*object_it)->getNumRefs() << " refs!" << llendl; + llinfos << "LLHUDObject " << (LLHUDObject *)(*object_it) << " type " << (S32)(*object_it)->getType() << " has " << (*object_it)->getNumRefs() << " refs!" << llendl; } } sHUDObjects.clear(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index e3483fdaca..2e59240c49 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -737,11 +737,12 @@ void LLHUDText::updateVisibility() dir_from_camera.normVec(); if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f) - { - mPositionAgent -= projected_vec(vec_from_camera, LLViewerCamera::getInstance()->getAtAxis()) * 1.f; - mPositionAgent += LLViewerCamera::getInstance()->getAtAxis() * (LLViewerCamera::getInstance()->getNear() + 0.1f); + { //text is behind camera, don't render + mVisible = FALSE; + return; } - else if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius()) + + if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius()) { mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis())); } @@ -1068,6 +1069,10 @@ void LLHUDText::markDead() void LLHUDText::renderAllHUD() { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + LLGLEnable color_mat(GL_COLOR_MATERIAL); LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -1077,6 +1082,10 @@ void LLHUDText::renderAllHUD() { (*text_it)->renderText(FALSE); } + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } void LLHUDText::shiftAll(const LLVector3& offset) diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp index 95825aa2f2..326c511fcf 100644 --- a/indra/newview/lljoystickbutton.cpp +++ b/indra/newview/lljoystickbutton.cpp @@ -639,7 +639,7 @@ void LLJoystickCameraRotate::draw() } // Draws image rotated by multiples of 90 degrees -void LLJoystickCameraRotate::drawRotatedImage( const LLImageGL* image, S32 rotations ) +void LLJoystickCameraRotate::drawRotatedImage( LLImageGL* image, S32 rotations ) { S32 width = image->getWidth(); S32 height = image->getHeight(); diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h index e7d4beb375..076a506f14 100644 --- a/indra/newview/lljoystickbutton.h +++ b/indra/newview/lljoystickbutton.h @@ -134,7 +134,7 @@ public: protected: F32 getOrbitRate(); virtual void updateSlop(); - void drawRotatedImage( const LLImageGL* image, S32 rotations ); + void drawRotatedImage( LLImageGL* image, S32 rotations ); protected: BOOL mInLeft; diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 959a575950..dfa624a59c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -164,8 +164,7 @@ void LLManipTranslate::restoreGL() GLuint* d = new GLuint[rez*rez]; gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); while (rez >= 1) { @@ -261,9 +260,9 @@ void LLManipTranslate::restoreGL() } } #ifdef LL_WINDOWS - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_BYTE, d); + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); #else - glTexImage2D(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d); + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, d); #endif rez = rez >> 1; mip++; diff --git a/indra/newview/llmimetypes.h b/indra/newview/llmimetypes.h index 4b48bd8daa..7a50c29429 100644 --- a/indra/newview/llmimetypes.h +++ b/indra/newview/llmimetypes.h @@ -101,10 +101,10 @@ public: std::string mPlayTip; // custom tool tip to display for Play button - bool mAllowResize; + BOOL mAllowResize; // enable/disable media size edit fields - bool mAllowLooping; + BOOL mAllowLooping; // enable/disable media looping checkbox }; typedef std::map< std::string, LLMIMEInfo > mime_info_map_t; diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index 24fea645d4..b779aa0f83 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -285,18 +285,37 @@ LLColor4U LLSky::getFadeColor() const void LLSky::init(const LLVector3 &sun_direction) { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + mVOWLSkyp = static_cast<LLVOWLSky*>(gObjectList.createObjectViewer(LLViewerObject::LL_VO_WL_SKY, NULL)); mVOWLSkyp->initSunDirection(sun_direction, LLVector3::zero); - gPipeline.addObject(mVOWLSkyp.get()); + gPipeline.createObject(mVOWLSkyp.get()); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mVOSkyp = (LLVOSky *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SKY, NULL); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + mVOSkyp->initSunDirection(sun_direction, LLVector3()); - gPipeline.addObject((LLViewerObject *)mVOSkyp); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + + gPipeline.createObject((LLViewerObject *)mVOSkyp); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mVOGroundp = (LLVOGround*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_GROUND, NULL); LLVOGround *groundp = mVOGroundp; - gPipeline.addObject((LLViewerObject *)groundp); + gPipeline.createObject((LLViewerObject *)groundp); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio")); @@ -309,6 +328,8 @@ void LLSky::init(const LLVector3 &sun_direction) // Get the parameters. mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition"); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || mOverrideSimSunPosition) { @@ -319,6 +340,8 @@ void LLSky::init(const LLVector3 &sun_direction) setSunDirection(sun_direction, LLVector3(0.f, 0.f, 0.f)); } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); mUpdatedThisFrame = TRUE; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index dc4b8134dc..6e5231bddd 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -49,7 +49,7 @@ #include "lloctree.h" #include "llvoavatar.h" -const F32 SG_OCCLUSION_FUDGE = 1.01f; +const F32 SG_OCCLUSION_FUDGE = 0.25f; #define SG_DISCARD_TOLERANCE 0.01f #if LL_OCTREE_PARANOIA_CHECK @@ -191,7 +191,7 @@ static U8 sOcclusionIndices[] = b000, b110, b100, b101, b001, b011, b010, b110, }; -U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center) +U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center) { LLVector3 d = center - camera->getOrigin(); @@ -219,7 +219,7 @@ void LLSpatialGroup::buildOcclusion() mOcclusionVerts = new F32[8*3]; } - LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f); + LLVector3 r = mBounds[1] + LLVector3(SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE); for (U32 k = 0; k < 3; k++) { @@ -562,8 +562,21 @@ void LLSpatialGroup::rebuildGeom() } } +void LLSpatialGroup::rebuildMesh() +{ + if (!isDead()) + { + mSpatialPartition->rebuildMesh(this); + } +} + void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { + if (!gPipeline.hasRenderType(mDrawableType)) + { + return; + } + if (group->changeLOD()) { group->mLastUpdateDistance = group->mDistance; @@ -612,6 +625,11 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->clearState(LLSpatialGroup::GEOM_DIRTY); } +void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) +{ + +} + BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) { const OctreeNode* node = mOctreeNode; @@ -778,7 +796,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset) mObjectExtents[0] += offset; mObjectExtents[1] += offset; - if (!mSpatialPartition->mRenderByGroup) + //if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); } @@ -1271,8 +1289,8 @@ void LLSpatialGroup::checkOcclusion() clearState(QUERY_PENDING | DISCARD_QUERY); } - else if (mSpatialPartition->mOcclusionEnabled) - { + else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED)) + { //check occlusion has been issued for occluded node that has not had a query issued assert_states_valid(this); clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); assert_states_valid(this); @@ -1282,7 +1300,7 @@ void LLSpatialGroup::checkOcclusion() void LLSpatialGroup::doOcclusion(LLCamera* camera) { - if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1) + if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) { if (earlyFail(camera, this)) { @@ -1309,7 +1327,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery); glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_occlusion_indices(camera, mBounds[0])); + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); glEndQueryARB(GL_SAMPLES_PASSED_ARB); } @@ -1470,7 +1488,7 @@ public: group->checkOcclusion(); if (group->mOctreeNode->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled + LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isState(LLSpatialGroup::OCCLUDED)) { gPipeline.markOccluder(group); @@ -1594,6 +1612,86 @@ public: } }; +class LLOctreeCullShadow : public LLOctreeCull +{ +public: + LLOctreeCullShadow(LLCamera* camera) + : LLOctreeCull(camera) { } + + virtual S32 frustumCheck(const LLSpatialGroup* group) + { + return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); + } + + virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + { + return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); + } +}; + +class LLOctreeCullVisExtents: public LLOctreeCullShadow +{ +public: + LLOctreeCullVisExtents(LLCamera* camera, LLVector3& min, LLVector3& max) + : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } + + virtual bool earlyFail(LLSpatialGroup* group) + { + if (group->mOctreeNode->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + virtual void processGroup(LLSpatialGroup* group) + { + if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f) + { //megaprims and water edge patches be damned! + mEmpty = FALSE; + update_min_max(mMin, mMax, group->mObjectExtents[0]); + update_min_max(mMin, mMax, group->mObjectExtents[1]); + } + } + + BOOL mEmpty; + LLVector3& mMin; + LLVector3& mMax; +}; + +class LLOctreeCullDetectVisible: public LLOctreeCullShadow +{ +public: + LLOctreeCullDetectVisible(LLCamera* camera) + : LLOctreeCullShadow(camera), mResult(FALSE) { } + + virtual bool earlyFail(LLSpatialGroup* group) + { + if (mResult || //already found a node, don't check any more + group->mOctreeNode->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + virtual void processGroup(LLSpatialGroup* group) + { + if (group->isVisible()) + { + mResult = TRUE; + } + } + + BOOL mResult; +}; + class LLOctreeSelect : public LLOctreeCull { public: @@ -1747,6 +1845,25 @@ void LLSpatialPartition::resetVertexBuffers() dirty.traverse(mOctree); } +BOOL LLSpatialPartition::isOcclusionEnabled() +{ + return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2; +} + +BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) +{ + LLOctreeCullVisExtents vis(&camera, visMin, visMax); + vis.traverse(mOctree); + return vis.mEmpty; +} + +BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) +{ + LLOctreeCullDetectVisible vis(&camera); + vis.traverse(mOctree); + return vis.mResult; +} + S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1772,6 +1889,12 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result LLOctreeSelect selecter(&camera, results); selecter.traverse(mOctree); } + else if (LLPipeline::sShadowRender) + { + LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLOctreeCullShadow culler(&camera); + culler.traverse(mOctree); + } else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); @@ -1790,14 +1913,14 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) { - const F32 vel = (LLViewerCamera::getInstance()->getVelocityStat()->getCurrent()+0.2f); + const F32 vel = SG_OCCLUSION_FUDGE*2.f; LLVector3 c = group->mBounds[0]; - LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel); + LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel); - if (r.magVecSquared() > 1024.0*1024.0) + /*if (r.magVecSquared() > 1024.0*1024.0) { return TRUE; - } + }*/ LLVector3 e = camera->getOrigin(); @@ -1865,21 +1988,31 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) void pushBufferVerts(LLSpatialGroup* group, U32 mask) { - if (!group->mDrawMap.empty()) + if (group->mSpatialPartition->mRenderByGroup) { - LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); - LLRenderPass::applyModelMatrix(*params); - - pushBufferVerts(group->mVertexBuffer, mask); - - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + if (!group->mDrawMap.empty()) { - for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); + LLRenderPass::applyModelMatrix(*params); + + pushBufferVerts(group->mVertexBuffer, mask); + + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) { - pushBufferVerts(*j, mask); + for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k) + { + pushBufferVerts(*k, mask); + } + } } } } + else + { + drawBox(group->mBounds[0], group->mBounds[1]); + } } void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) @@ -2026,6 +2159,23 @@ void renderOctree(LLSpatialGroup* group) } drawBoxOutline(group->mBounds[0],group->mBounds[1]); + + + //draw bounding box for draw info + if (group->mSpatialPartition->mRenderByGroup) + { + gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f); + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* draw_info = *j; + LLVector3 center = (draw_info->mExtents[1] + draw_info->mExtents[0])*0.5f; + LLVector3 size = (draw_info->mExtents[1] - draw_info->mExtents[0])*0.5f; + drawBoxOutline(center, size); + } + } + } } // LLSpatialGroup::OctreeNode* node = group->mOctreeNode; @@ -2046,6 +2196,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) { LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); glColor4f(0, 0.5f, 0, 0.5f); + gGL.color4f(0, 0.5f, 0, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2055,6 +2206,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) if (render_objects) { glColor4f(0.f, 0.5f, 0.f,1.f); + gGL.color4f(0.f, 0.5f, 0.f, 1.f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2063,6 +2215,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) if (render_objects) { glColor4f(0.f, 0.75f, 0.f,0.5f); + gGL.color4f(0.f, 0.75f, 0.f, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } else if (camera && group->mOcclusionVerts) @@ -2071,60 +2224,63 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts); glColor4f(1.0f, 0.f, 0.f, 0.5f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor4f(1.0f, 1.f, 1.f, 1.0f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0])); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } } -void renderBoundingBox(LLDrawable* drawable) +void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { - if (drawable->isSpatialBridge()) - { - gGL.color4f(1,0.5f,0,1); - } - else if (drawable->getVOVolume()) + if (set_color) { - if (drawable->isRoot()) + if (drawable->isSpatialBridge()) { - gGL.color4f(1,1,0,1); + gGL.color4f(1,0.5f,0,1); } - else + else if (drawable->getVOVolume()) { - gGL.color4f(0,1,0,1); + if (drawable->isRoot()) + { + gGL.color4f(1,1,0,1); + } + else + { + gGL.color4f(0,1,0,1); + } } - } - else if (drawable->getVObj()) - { - switch (drawable->getVObj()->getPCode()) + else if (drawable->getVObj()) { - case LLViewerObject::LL_VO_SURFACE_PATCH: - gGL.color4f(0,1,1,1); - break; - case LLViewerObject::LL_VO_CLOUDS: - gGL.color4f(0.5f,0.5f,0.5f,1.0f); - break; - case LLViewerObject::LL_VO_PART_GROUP: + switch (drawable->getVObj()->getPCode()) + { + case LLViewerObject::LL_VO_SURFACE_PATCH: + gGL.color4f(0,1,1,1); + break; + case LLViewerObject::LL_VO_CLOUDS: + gGL.color4f(0.5f,0.5f,0.5f,1.0f); + break; + case LLViewerObject::LL_VO_PART_GROUP: case LLViewerObject::LL_VO_HUD_PART_GROUP: - gGL.color4f(0,0,1,1); - break; - case LLViewerObject::LL_VO_WATER: - gGL.color4f(0,0.5f,1,1); - break; - case LL_PCODE_LEGACY_TREE: - gGL.color4f(0,0.5f,0,1); - default: - gGL.color4f(1,0,1,1); - break; + gGL.color4f(0,0,1,1); + break; + case LLViewerObject::LL_VO_WATER: + gGL.color4f(0,0.5f,1,1); + break; + case LL_PCODE_LEGACY_TREE: + gGL.color4f(0,0.5f,0,1); + default: + gGL.color4f(1,0,1,1); + break; + } + } + else + { + gGL.color4f(1,0,0,1); } - } - else - { - gGL.color4f(1,0,0,1); } const LLVector3* ext; @@ -2156,7 +2312,8 @@ void renderBoundingBox(LLDrawable* drawable) if (vobj && vobj->onActiveList()) { gGL.flush(); - glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); + glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); + //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); stop_glerror(); drawBoxOutline(pos,size); gGL.flush(); @@ -2379,8 +2536,7 @@ public: } //render visibility wireframe - if (group->mSpatialPartition->mRenderByGroup && - gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { gGL.flush(); glPushMatrix(); @@ -2456,6 +2612,51 @@ public: } }; +class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable> +{ +public: + LLCamera* mCamera; + LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const LLSpatialGroup::OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + if (!mCamera || mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + } + } + + virtual void visit(const LLSpatialGroup::OctreeNode* branch) + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + + if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + { + return; + } + + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + { + LLDrawable* drawable = *i; + + renderBoundingBox(drawable, FALSE); + } + } +}; + +void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) +{ + LLOctreePushBBoxVerts pusher(camera); + pusher.traverse(mOctree); +} + void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | @@ -2661,9 +2862,22 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mParticle(particle), mPartSize(part_size), mVSize(0.f), - mGroup(NULL) + mGroup(NULL), + mFace(NULL), + mDistance(0.f) { mDebugColor = (rand() << 16) + rand(); + if (mStart >= mVertexBuffer->getRequestedVerts() || + mEnd >= mVertexBuffer->getRequestedVerts()) + { + llerrs << "Invalid draw info vertex range." << llendl; + } + + if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() || + mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices()) + { + llerrs << "Invalid draw info index range." << llendl; + } } LLDrawInfo::~LLDrawInfo() @@ -2672,6 +2886,11 @@ LLDrawInfo::~LLDrawInfo() { llerrs << "LLDrawInfo deleted illegally!" << llendl; } + + if (mFace) + { + mFace->setDrawInfo(NULL); + } } LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 2f0d80414d..4d67b374c8 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -42,6 +42,7 @@ #include "llgltypes.h" #include "llcubemap.h" #include "lldrawpool.h" +#include "llface.h" #include <queue> @@ -55,6 +56,9 @@ class LLSpatialGroup; S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); +// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera +U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center); + class LLDrawInfo : public LLRefCount { protected: @@ -82,6 +86,9 @@ public: F32 mPartSize; F32 mVSize; LLSpatialGroup* mGroup; + LLFace* mFace; //associated face + F32 mDistance; + LLVector3 mExtents[2]; struct CompareTexture { @@ -101,6 +108,16 @@ public: } }; + struct CompareVertexBuffer + { //sort by texture + bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) + { + // sort by pointer, sort NULL down to the end + return lhs.get() != rhs.get() + && (lhs.isNull() || (rhs.notNull() && lhs->mVertexBuffer.get() > rhs->mVertexBuffer.get())); + } + }; + struct CompareTexturePtrMatrix { bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) @@ -121,6 +138,16 @@ public: && (lhs.isNull() || (rhs.notNull() && lhs->mBump > rhs->mBump)); } }; + + struct CompareDistanceGreater + { + bool operator()(const LLPointer<LLDrawInfo>& lhs, const LLPointer<LLDrawInfo>& rhs) + { + // sort by mBump value, sort NULL down to the end + return lhs.get() != rhs.get() + && (lhs.isNull() || (rhs.notNull() && lhs->mDistance > rhs->mDistance)); + } + }; }; class LLSpatialGroup : public LLOctreeListener<LLDrawable> @@ -136,7 +163,8 @@ public: typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_map_t; + typedef std::map<LLPointer<LLViewerImage>, buffer_list_t> buffer_texture_map_t; + typedef std::map<U32, buffer_texture_map_t> buffer_map_t; typedef LLOctreeListener<LLDrawable> BaseType; typedef LLOctreeListener<LLDrawable> OctreeListener; @@ -226,6 +254,7 @@ public: BOOL needsUpdate(); BOOL changeLOD(); void rebuildGeom(); + void rebuildMesh(); void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } @@ -286,8 +315,10 @@ public: std::vector<LLFace*> mFaceList; virtual ~LLGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group) = 0; + virtual void rebuildMesh(LLSpatialGroup* group) = 0; virtual void getGeometry(LLSpatialGroup* group) = 0; virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count); + virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; @@ -320,7 +351,9 @@ public: virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); virtual void rebuildGeom(LLSpatialGroup* group); + virtual void rebuildMesh(LLSpatialGroup* group); + BOOL visibleObjectsInFrustum(LLCamera& camera); S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); @@ -329,9 +362,12 @@ public: virtual BOOL isBridge() { return asBridge() != NULL; } void renderDebug(); + void renderIntersectingBBoxes(LLCamera* camera); void restoreGL(); void resetVertexBuffers(); - + BOOL isOcclusionEnabled(); + BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax); + public: LLSpatialGroup::OctreeNode* mOctree; BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed @@ -445,6 +481,7 @@ private: drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; }; + //spatial partition for water (implemented in LLVOWater.cpp) class LLWaterPartition : public LLSpatialPartition { @@ -511,8 +548,11 @@ class LLVolumeGeometryManager: public LLGeometryManager public: virtual ~LLVolumeGeometryManager() { } virtual void rebuildGeom(LLSpatialGroup* group); + virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); + void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); + }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) @@ -522,6 +562,7 @@ public: LLVolumePartition(); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; @@ -532,6 +573,7 @@ public: LLVolumeBridge(LLDrawable* drawable); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } }; diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp index a819903d80..893ed22297 100644 --- a/indra/newview/llsprite.cpp +++ b/indra/newview/llsprite.cpp @@ -195,7 +195,7 @@ void LLSprite::updateFace(LLFace &face) if (face.mVertexBuffer.isNull()) { face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD, + LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); face.mVertexBuffer->allocateBuffer(4, 12, TRUE); face.setGeomIndex(0); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b4f8f6b71e..f6e3b14ddb 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -737,8 +737,6 @@ bool idle_startup() LL_DEBUGS("AppInit") << "Initializing Window" << LL_ENDL; gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - // Push our window frontmost - gViewerWindow->getWindow()->show(); timeout_count = 0; @@ -794,6 +792,10 @@ bool idle_startup() gLoginMenuBarView->setVisible( TRUE ); gLoginMenuBarView->setEnabled( TRUE ); + // Push our window frontmost + gViewerWindow->getWindow()->show(); + display_startup(); + // DEV-16927. The following code removes errant keystrokes that happen while the window is being // first made visible. #ifdef _WIN32 @@ -1800,7 +1802,13 @@ bool idle_startup() { LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL; // Initialize all of the viewer object classes for the first time (doing things like texture fetches. + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + gSky.init(initial_sun_direction); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); } LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL; @@ -2372,8 +2380,14 @@ bool idle_startup() { update_texture_fetch(); set_startup_status(0.60f + 0.30f * timeout_frac, - "Loading world...", + LLTrans::getString("LoginPrecaching"), gAgent.mMOTD); + display_startup(); + if (!LLViewerShaderMgr::sInitialized) + { + LLViewerShaderMgr::sInitialized = TRUE; + LLViewerShaderMgr::instance()->setShaders(); + } } return TRUE; diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index dcb8f6d5b1..a27f0e2254 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -253,7 +253,7 @@ void LLSurface::createSTexture() mSTexturep = new LLViewerImage(raw, FALSE); mSTexturep->dontDiscard(); gGL.getTexUnit(0)->bind(mSTexturep.get()); - mSTexturep->setClamp(TRUE, TRUE); + mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mSTexturep); } } @@ -278,7 +278,7 @@ void LLSurface::createWaterTexture() mWaterTexturep = new LLViewerImage(raw, FALSE); mWaterTexturep->dontDiscard(); gGL.getTexUnit(0)->bind(mWaterTexturep.get()); - mWaterTexturep->setClamp(TRUE, TRUE); + mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); gImageList.addImage(mWaterTexturep); } } @@ -299,7 +299,7 @@ void LLSurface::initTextures() { createWaterTexture(); mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); - gPipeline.addObject(mWaterObjp); + gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 59231b3d69..5fac5fd1e4 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -128,7 +128,7 @@ void LLSurfacePatch::setSurface(LLSurface *surfacep) mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion()); mVObjp->setPatch(this); mVObjp->setPositionRegion(mCenterRegion); - gPipeline.addObject(mVObjp); + gPipeline.createObject(mVObjp); } } diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 709fcd166b..6a7ba7b7f4 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -57,10 +57,6 @@ //#include "../tools/imdebug/imdebug.h" - -// SJB: We really always want to use the GL cache; -// let GL page textures in and out of video RAM instead of trying to do so by hand. - // static S32 LLTexLayerSetBuffer::sGLByteCount = 0; S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; @@ -151,10 +147,9 @@ void LLTexLayerSetBuffer::createBumpTexture() gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL); stop_glerror(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -1375,15 +1370,14 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) { LLGLDisable alpha_test(getInfo()->mWriteAllChannels ? GL_ALPHA_TEST : 0); - BOOL old_clamps = image_gl->getClampS(); - BOOL old_clampt = image_gl->getClampT(); + LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); - image_gl->setClamp(old_clamps, old_clampt); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -1575,14 +1569,14 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 { LLGLSNoAlphaTest gls_no_alpha_test; - BOOL old_clamps = image_gl->getClampS(); - BOOL old_clampt = image_gl->getClampT(); + LLTexUnit::eTextureAddressMode old_mode = image_gl->getAddressMode(); + gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); - image_gl->setClamp(old_clamps, old_clampt); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -1719,21 +1713,20 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i internal_format = GL_ALPHA8; } - GLuint name = 0; - glGenTextures(1, &name ); + U32 name = 0; + LLImageGL::generateTextures(1, &name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, in_width, in_height, - 0, format, GL_UNSIGNED_BYTE, in_data ); + format, GL_UNSIGNED_BYTE, in_data ); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -1741,7 +1734,7 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glDeleteTextures(1, &name ); + LLImageGL::deleteTextures(1, &name ); stop_glerror(); } else @@ -2016,7 +2009,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) if( !mCachedProcessedImageGL || (mCachedProcessedImageGL->getWidth() != image_tga_width) || (mCachedProcessedImageGL->getHeight() != image_tga_height) || - (weight_changed )) + (weight_changed) ) { // llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; mCachedEffectiveWeight = effective_weight; @@ -2028,7 +2021,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) // We now have something in one of our caches LLTexLayerSet::sHasCaches |= mCachedProcessedImageGL ? TRUE : FALSE; - mCachedProcessedImageGL->setExplicitFormat( GL_ALPHA8, GL_ALPHA ); } @@ -2047,9 +2039,8 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) { mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); mNeedsCreateTexture = FALSE; - gGL.getTexUnit(0)->bind(mCachedProcessedImageGL); - mCachedProcessedImageGL->setClamp(TRUE, TRUE); + mCachedProcessedImageGL->setAddressMode(LLTexUnit::TAM_CLAMP); } LLGLSNoAlphaTest gls_no_alpha_test; @@ -2504,7 +2495,7 @@ LLImageGL* LLTexStaticImageList::getImageGL(const std::string& file_name, BOOL i image_gl->createGLTexture(0, image_raw); gGL.getTexUnit(0)->bind(image_gl); - image_gl->setClamp(TRUE, TRUE); + image_gl->setAddressMode(LLTexUnit::TAM_CLAMP); mStaticImageListGL [ namekey ] = image_gl; mGLBytes += (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 97b55a3d06..5ab8c91f72 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -533,7 +533,6 @@ public: S32 mTGABytes; }; - // Used by LLTexLayerSetBuffer for a callback. class LLBakedUploadData { diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d3f1744f2f..69723f622a 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -175,7 +175,7 @@ private: bool LLTextureCacheLocalFileWorker::doRead() { - S32 local_size = ll_apr_file_size(mFileName, mCache->getFileAPRPool()); + S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool()); if (local_size > 0 && mFileName.size() > 4) { @@ -248,8 +248,9 @@ bool LLTextureCacheLocalFileWorker::doRead() mDataSize = local_size; } mReadData = new U8[mDataSize]; - S32 bytes_read = ll_apr_file_read_ex(mFileName, mCache->getFileAPRPool(), - mReadData, mOffset, mDataSize); + + S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); + if (bytes_read != mDataSize) { // llwarns << "Error reading file from local cache: " << mFileName @@ -317,11 +318,11 @@ bool LLTextureCacheRemoteWorker::doRead() { std::string filename = mCache->getLocalFileName(mID); local_filename = filename + ".j2c"; - local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size == 0) { local_filename = filename + ".tga"; - local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool()); if (local_size > 0) { mImageFormat = IMG_CODEC_TGA; @@ -389,8 +390,8 @@ bool LLTextureCacheRemoteWorker::doRead() mDataSize = local_size; } mReadData = new U8[mDataSize]; - S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(), - mReadData, mOffset, mDataSize); + S32 bytes_read = LLAPRFile::readEx(local_filename, + mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool()); if (bytes_read != mDataSize) { // llwarns << "Error reading file from local cache: " << local_filename @@ -483,8 +484,8 @@ bool LLTextureCacheRemoteWorker::doRead() S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; mReadData = new U8[size]; - S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), - mReadData, offset, size); + S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName, + mReadData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_read != size) { // llwarns << "LLTextureCacheWorker: " << mID @@ -510,7 +511,7 @@ bool LLTextureCacheRemoteWorker::doRead() if (mFileHandle == LLLFSThread::nullHandle()) { std::string filename = mCache->getTextureFileName(mID); - S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); if (filesize > mOffset) { S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; @@ -569,7 +570,7 @@ bool LLTextureCacheRemoteWorker::doRead() } #else std::string filename = mCache->getTextureFileName(mID); - S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool()); S32 bytes_read = 0; if (filesize > mOffset) { @@ -589,9 +590,10 @@ bool LLTextureCacheRemoteWorker::doRead() delete[] mReadData; } mReadData = data; - bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(), + bytes_read = LLAPRFile::readEx(filename, mReadData + data_offset, - file_offset, file_size); + file_offset, file_size, + mCache->getLocalAPRFilePool()); if (bytes_read != file_size) { // llwarns << "LLTextureCacheWorker: " << mID @@ -694,8 +696,7 @@ bool LLTextureCacheRemoteWorker::doWrite() llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; - S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), - mWriteData, offset, size); + S32 bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { @@ -770,9 +771,11 @@ bool LLTextureCacheRemoteWorker::doWrite() if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) { std::string filename = mCache->getTextureFileName(mID); - bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(), + + bytes_written = LLAPRFile::writeEx(filename, mWriteData + data_offset, - file_offset, file_size); + file_offset, file_size, + mCache->getLocalAPRFilePool()); if (bytes_written <= 0) { mDataSize = -1; // failed @@ -793,13 +796,14 @@ bool LLTextureCacheRemoteWorker::doWrite() //virtual bool LLTextureCacheWorker::doWork(S32 param) { +// *TODO reenable disabled apr_pool usage disabled due to maint-render-9 merge breakage -brad //allocate a new local apr_pool - LLAPRPool pool ; +// LLAPRPool pool ; //save the current mFileAPRPool to avoid breaking anything. - apr_pool_t* old_pool = mCache->getFileAPRPool() ; +// apr_pool_t* old_pool = mCache->getFileAPRPool() ; //make mFileAPRPool to point to the local one - mCache->setFileAPRPool(pool.getAPRPool()) ; +// mCache->setFileAPRPool(pool.getAPRPool()) ; bool res = false; if (param == 0) // read @@ -816,7 +820,7 @@ bool LLTextureCacheWorker::doWork(S32 param) } //set mFileAPRPool back, the local one will be released automatically. - mCache->setFileAPRPool(old_pool) ; +// mCache->setFileAPRPool(old_pool) ; return res; } @@ -880,20 +884,17 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted) LLTextureCache::LLTextureCache(bool threaded) : LLWorkerThread("TextureCache", threaded), - mWorkersMutex(getAPRPool()), - mHeaderMutex(getAPRPool()), - mListMutex(getAPRPool()), - mFileAPRPool(NULL), + mWorkersMutex(NULL), + mHeaderMutex(NULL), + mListMutex(NULL), mReadOnly(FALSE), mTexturesSizeTotal(0), mDoPurge(FALSE) { - apr_pool_create(&mFileAPRPool, NULL); } LLTextureCache::~LLTextureCache() { - apr_pool_destroy(mFileAPRPool); } ////////////////////////////////////////////////////////////////////////////// @@ -969,8 +970,10 @@ bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) { llassert_always(bodysize > 0); Entry* entry = new Entry(id, bodysize, time(NULL)); - ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(), - (U8*)entry, -1, 1*sizeof(Entry)); + + LLAPRFile::writeEx(mTexturesDirEntriesFileName, + (U8*)entry, -1, 1*sizeof(Entry), + getLocalAPRFilePool()); delete entry; if (iter != mTexturesSizeMap.end()) { @@ -1018,8 +1021,8 @@ void LLTextureCache::purgeCache(ELLPath location) { setDirNames(location); - ll_apr_file_remove(mHeaderEntriesFileName, NULL); - ll_apr_file_remove(mHeaderDataFileName, NULL); + LLAPRFile::remove(mHeaderEntriesFileName, getLocalAPRFilePool()); + LLAPRFile::remove(mHeaderDataFileName, getLocalAPRFilePool()); } purgeAllTextures(true); } @@ -1081,15 +1084,16 @@ struct lru_data }; // Called from either the main thread or the worker thread -void LLTextureCache::readHeaderCache(apr_pool_t* poolp) +void LLTextureCache::readHeaderCache() { LLMutexLock lock(&mHeaderMutex); mHeaderEntriesInfo.mVersion = 0.f; mHeaderEntriesInfo.mEntries = 0; - if (ll_apr_file_exists(mHeaderEntriesFileName, poolp)) + if (LLAPRFile::isExist(mHeaderEntriesFileName, getLocalAPRFilePool())) { - ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) { @@ -1097,8 +1101,10 @@ void LLTextureCache::readHeaderCache(apr_pool_t* poolp) { // Info with 0 entries mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; - ll_apr_file_write_ex(mHeaderEntriesFileName, poolp, - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } } else @@ -1107,8 +1113,11 @@ void LLTextureCache::readHeaderCache(apr_pool_t* poolp) if (num_entries) { Entry* entries = new Entry[num_entries]; - ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, - (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry)); + { + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry), + getLocalAPRFilePool()); + } typedef std::set<lru_data*, lru_data::Compare> lru_set_t; lru_set_t lru; for (S32 i=0; i<num_entries; i++) @@ -1153,7 +1162,7 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) LLFile::rmdir(dirname); } } - ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); + LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); if (purge_directories) { LLFile::rmdir(mTexturesDirName); @@ -1174,7 +1183,7 @@ void LLTextureCache::purgeTextures(bool validate) LLMutexLock lock(&mHeaderMutex); - S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL); + S32 filesize = LLAPRFile::size(mTexturesDirEntriesFileName, getLocalAPRFilePool()); S32 num_entries = filesize / sizeof(Entry); if (num_entries * (S32)sizeof(Entry) != filesize) { @@ -1188,8 +1197,9 @@ void LLTextureCache::purgeTextures(bool validate) } Entry* entries = new Entry[num_entries]; - S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL, - (U8*)entries, 0, num_entries*sizeof(Entry)); + S32 bytes_read = LLAPRFile::readEx(mTexturesDirEntriesFileName, + (U8*)entries, 0, num_entries*sizeof(Entry), + getLocalAPRFilePool()); if (bytes_read != filesize) { LL_WARNS("TextureCache") << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << LL_ENDL; @@ -1248,7 +1258,7 @@ void LLTextureCache::purgeTextures(bool validate) if (uuididx == validate_idx) { LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mSize << LL_ENDL; - S32 bodysize = ll_apr_file_size(filename, NULL); + S32 bodysize = LLAPRFile::size(filename, getLocalAPRFilePool()); if (bodysize != entries[idx].mSize) { LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize @@ -1261,7 +1271,7 @@ void LLTextureCache::purgeTextures(bool validate) { purge_count++; LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; - ll_apr_file_remove(filename, NULL); + LLAPRFile::remove(filename, getLocalAPRFilePool()); total_size -= entries[idx].mSize; entries[idx].mSize = 0; } @@ -1278,9 +1288,10 @@ void LLTextureCache::purgeTextures(bool validate) LL_DEBUGS("TextureCache") << "TEXTURE CACHE: Writing Entries: " << num_entries << LL_ENDL; - ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); - ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL, - (U8*)&entries[0], 0, num_entries*sizeof(Entry)); + LLAPRFile::remove(mTexturesDirEntriesFileName, getLocalAPRFilePool()); + LLAPRFile::writeEx(mTexturesDirEntriesFileName, + (U8*)&entries[0], 0, num_entries*sizeof(Entry), + getLocalAPRFilePool()); mTexturesSizeTotal = 0; mTexturesSizeMap.clear(); @@ -1351,8 +1362,9 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image idx = mHeaderEntriesInfo.mEntries++; mHeaderIDMap[id] = idx; // Update Info - ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo), + getLocalAPRFilePool()); } else if (!mLRU.empty()) { @@ -1377,8 +1389,9 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image llassert_always(imagesize && *imagesize > 0); Entry* entry = new Entry(id, *imagesize, time(NULL)); S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)entry, offset, sizeof(Entry)); + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)entry, offset, sizeof(Entry), + getLocalAPRFilePool()); delete entry; } else if (imagesize) @@ -1386,15 +1399,17 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image // Get the image size Entry entry; S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(), - (U8*)&entry, offset, sizeof(Entry)); + + LLAPRFile::readEx(mHeaderEntriesFileName, + (U8*)&entry, offset, sizeof(Entry), + getLocalAPRFilePool()); *imagesize = entry.mSize; } } } if (retry) { - readHeaderCache(getFileAPRPool()); // updates the lru + readHeaderCache(); // updates the lru llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion } @@ -1468,7 +1483,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio { // NOTE: This may cause an occasional hiccup, // but it really needs to be done on the control thread - // (i.e. here) + // (i.e. here) purgeTextures(false); mDoPurge = FALSE; } @@ -1540,8 +1555,10 @@ bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) { Entry* entry = new Entry(id, -1, time(NULL)); S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); - ll_apr_file_write_ex(mHeaderEntriesFileName, NULL, - (U8*)entry, offset, sizeof(Entry)); + + LLAPRFile::writeEx(mHeaderEntriesFileName, + (U8*)entry, offset, sizeof(Entry), + getLocalAPRFilePool()); delete entry; mLRU[idx] = id; mHeaderIDMap.erase(id); @@ -1558,7 +1575,7 @@ void LLTextureCache::removeFromCache(const LLUUID& id) if (!mReadOnly) { removeHeaderCacheEntry(id); - ll_apr_file_remove(getTextureFileName(id), NULL); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); } } diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index fa42b5d58e..68b1458e9a 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -109,18 +109,17 @@ public: protected: // Accessed by LLTextureCacheWorker - apr_pool_t* getFileAPRPool() { return mFileAPRPool; } bool appendToTextureEntryList(const LLUUID& id, S32 size); std::string getLocalFileName(const LLUUID& id); std::string getTextureFileName(const LLUUID& id); void addCompleted(Responder* responder, bool success); protected: - void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } + //void setFileAPRPool(apr_pool_t* pool) { mFileAPRPool = pool ; } private: void setDirNames(ELLPath location); - void readHeaderCache(apr_pool_t* poolp = NULL); + void readHeaderCache(); void purgeAllTextures(bool purge_directories); void purgeTextures(bool validate); S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); @@ -133,7 +132,6 @@ private: LLMutex mWorkersMutex; LLMutex mHeaderMutex; LLMutex mListMutex; - apr_pool_t* mFileAPRPool; typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t; handle_map_t mReaders; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 3fcb9c50be..e9dd7921cd 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -416,7 +416,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mInLocalCache(FALSE), mRetryAttempt(0), mActiveCount(0), - mWorkMutex(fetcher->getWorkerAPRPool()), + mWorkMutex(NULL), mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), @@ -435,7 +435,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, LLTextureFetchWorker::~LLTextureFetchWorker() { - llassert_always(LLWorkerClass::sDeleteLock) ; // llinfos << "Destroy: " << mID // << " Decoded=" << mDecodedDiscard // << " Requested=" << mRequestedDiscard diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 5a2230c34c..f54830f39f 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -83,6 +83,21 @@ glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloa 0, 0, -1.f, 0); } +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) +{ + LLVector3 f = center-eye; + f.normVec(); + up.normVec(); + LLVector3 s = f % up; + LLVector3 u = s % f; + + return glh::matrix4f(s[0], s[1], s[2], 0, + u[0], u[1], u[2], 0, + -f[0], -f[1], -f[2], 0, + 0, 0, 0, 1); + +} + LLViewerCamera::LLViewerCamera() : LLCamera() { calcProjection(getFar()); @@ -183,7 +198,7 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const // height. //static -void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip) +void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks) { GLint* viewport = (GLint*) gGLViewport; GLdouble* model = gGLModelView; @@ -192,7 +207,27 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli LLVector3 frust[8]; - if (zflip) + if (no_hacks) + { + gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); + + gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); + } + else if (zflip) { gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); @@ -232,7 +267,7 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zfli if (ortho) { - LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0); + LLVector3 far_shift = camera.getAtAxis()*camera.getFar()*2.f; for (U32 i = 0; i < 4; i++) { frust[i+4] = frust[i] + far_shift; @@ -369,13 +404,13 @@ void LLViewerCamera::setPerspective(BOOL for_selection, updateFrustumPlanes(*this); - if (gSavedSettings.getBOOL("CameraOffset")) + /*if (gSavedSettings.getBOOL("CameraOffset")) { glMatrixMode(GL_PROJECTION); glTranslatef(0,0,-50); glRotatef(20.0,1,0,0); glMatrixMode(GL_MODELVIEW); - } + }*/ } diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 5e21fda09d..6a0c42beec 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -60,7 +60,7 @@ public: const LLVector3 &up_direction, const LLVector3 &point_of_interest); - static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE); + static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE, BOOL no_hacks = FALSE); void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0); const LLMatrix4 &getProjection() const; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 16a830a110..1a40da9c1f 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -355,19 +355,24 @@ static bool handleRenderUseFBOChanged(const LLSD& newvalue) { gPipeline.releaseGLBuffers(); gPipeline.createGLBuffers(); + if (LLPipeline::sRenderDeferred && LLRenderTarget::sUseFBO) + { + LLViewerShaderMgr::instance()->setShaders(); + } } return true; } static bool handleRenderUseImpostorsChanged(const LLSD& newvalue) { - LLVOAvatar::sUseImpostors = FALSE; //newvalue.asBoolean(); + LLVOAvatar::sUseImpostors = newvalue.asBoolean(); return true; } static bool handleRenderDebugGLChanged(const LLSD& newvalue) { gDebugGL = newvalue.asBoolean(); + gGL.clearErrors(); return true; } @@ -437,6 +442,7 @@ void settings_setup_listeners() gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _1)); gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _1)); gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _1)); + gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); @@ -462,6 +468,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _1)); + gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderUseImpostors")->getSignal()->connect(boost::bind(&handleRenderUseImpostorsChanged, _1)); gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _1)); gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 9099ddc896..54c6f0a71f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -108,7 +108,7 @@ LLFrameTimer gRecentMemoryTime; // Rendering stuff void pre_show_depth_buffer(); void post_show_depth_buffer(); -void render_ui(); +void render_ui(F32 zoom_factor = 1.f, int subfield = 0); void render_hud_attachments(); void render_ui_3d(); void render_ui_2d(); @@ -161,9 +161,9 @@ void display_startup() glClear(GL_DEPTH_BUFFER_BIT); } - void display_update_camera() { + llpushcallstacks ; // TODO: cut draw distance down if customizing avatar? // TODO: cut draw distance on per-parcel basis? @@ -500,12 +500,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (LLDynamicTexture::updateAllInstances()) { gGL.setColorMask(true, true); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); } } gViewerWindow->setupViewport(); - + + gPipeline.resetFrameStats(); // Reset per-frame statistics. if (!gDisconnected) { LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); @@ -528,6 +529,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gFrameStats.start(LLFrameStats::UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time + gPipeline.createObjects(max_geom_update_time); gPipeline.updateGeom(max_geom_update_time); stop_glerror(); @@ -557,10 +559,17 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; + + if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) + { //force occlusion on for all render types if doing deferred render + LLPipeline::sUseOcclusion = 3; + } + LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); - + LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); + S32 occlusion = LLPipeline::sUseOcclusion; if (gDepthDirty) { //depth buffer is invalid, don't overwrite occlusion state @@ -568,18 +577,25 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gDepthDirty = FALSE; + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + static LLCullResult result; gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); stop_glerror(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + BOOL to_texture = !for_snapshot && gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); - // now do the swap buffer (just before rendering to framebuffer) - { //swap and flush state from previous frame + { { LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); LLVertexBuffer::clientCopy(0.016); @@ -593,14 +609,29 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gGL.setColorMask(true, true); glClearColor(0,0,0,0); - + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + if (!for_snapshot) { + if (gFrameCount > 1) + { //for some reason, ATI 4800 series will error out if you + //try to generate a shadow before the first frame is through + gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); + } + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + glh::matrix4f proj = glh_get_current_projection(); glh::matrix4f mod = glh_get_current_modelview(); glViewport(0,0,512,512); LLVOAvatar::updateFreezeCounter() ; LLVOAvatar::updateImpostors(); + glh_set_current_projection(proj); glh_set_current_modelview(mod); glMatrixMode(GL_PROJECTION); @@ -608,8 +639,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) glMatrixMode(GL_MODELVIEW); glLoadMatrixf(mod.m); gViewerWindow->setupViewport(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!for_snapshot) @@ -626,6 +662,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // // Doing this here gives hardware occlusion queries extra time to complete LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); + LLError::LLCallStacks::clear() ; + llpushcallstacks ; gFrameStats.start(LLFrameStats::IMAGE_UPDATE); { @@ -640,7 +678,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gImageList.updateImages(max_image_decode_time); stop_glerror(); } - + llpushcallstacks ; /////////////////////////////////// // // StateSort @@ -722,11 +760,25 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // glPopMatrix(); //} + LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; + LLPipeline::updateRenderDeferred(); + + stop_glerror(); + if (to_texture) { gGL.setColorMask(true, true); - gPipeline.mScreen.bindTarget(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.mDeferredScreen.bindTarget(); + gPipeline.mDeferredScreen.clear(); + } + else + { + gPipeline.mScreen.bindTarget(); + gPipeline.mScreen.clear(); + } + gGL.setColorMask(true, false); } @@ -737,9 +789,15 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { gGL.setColorMask(true, false); - LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; - gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); - LLPipeline::sUnderWaterRender = FALSE; + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); + } + else + { + gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); + } + gGL.setColorMask(true, true); //store this frame's modelview matrix for use @@ -755,8 +813,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (to_texture) { - - gPipeline.mScreen.flush(); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.mDeferredScreen.flush(); + } + else + { + gPipeline.mScreen.flush(); + } } /// We copy the frame buffer straight into a texture here, @@ -765,8 +829,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) /// grasp of their full display stack just yet. // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) + { + gPipeline.renderDeferredLighting(); + } + + LLPipeline::sUnderWaterRender = FALSE; + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); - if (!for_snapshot) { gFrameStats.start(LLFrameStats::RENDER_UI); @@ -818,7 +888,10 @@ void render_hud_attachments() //only render hud objects U32 mask = gPipeline.getRenderTypeMask(); gPipeline.setRenderTypeMask(0); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } BOOL has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); if (has_ui) @@ -829,16 +902,18 @@ void render_hud_attachments() S32 use_occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = 0; LLPipeline::sDisableShaders = TRUE; - + //cull, sort, and render hud objects static LLCullResult result; LLSpatialGroup::sNoDelete = TRUE; + gPipeline.updateCull(hud_cam, result); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); gPipeline.stateSort(hud_cam, result); @@ -935,7 +1010,7 @@ BOOL setup_hud_matrices(const LLRect& screen_region) } -void render_ui() +void render_ui(F32 zoom_factor, int subfield) { LLGLState::checkStates(); @@ -950,7 +1025,7 @@ void render_ui() if (to_texture) { - gPipeline.renderBloom(gSnapshot); + gPipeline.renderBloom(gSnapshot, zoom_factor, subfield); } render_hud_elements(); diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 5a21ac68d3..89490e08bf 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -244,6 +244,8 @@ void LLViewerJoint::setValid( BOOL valid, BOOL recursive ) //-------------------------------------------------------------------- U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass ) { + stop_glerror(); + U32 triangle_count = 0; //---------------------------------------------------------------- @@ -261,6 +263,10 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass ) { triangle_count += drawShape( pixelArea, first_pass ); } + else if (LLPipeline::sShadowRender) + { + triangle_count += drawShape(pixelArea, first_pass); + } else if ( isTransparent() && !LLPipeline::sReflectionRender) { // Hair and Skirt diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 0d5c19570a..4cacc5c97b 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -73,7 +73,7 @@ extern BOOL gRenderForSelect; static LLPointer<LLVertexBuffer> sRenderBuffer = NULL; static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; //----------------------------------------------------------------------------- @@ -459,14 +459,13 @@ void LLViewerJointMesh::uploadJointMatrices() for (S32 axis = 0; axis < NUM_AXES; axis++) { F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis]; - //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector); U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num; memcpy(mat+offset*4, vector, sizeof(GLfloat)*4); - //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+6, (GLfloat*)vector); - //cgGLSetParameterArray4f(gPipeline.mAvatarMatrix, offset, 1, vector); } } + stop_glerror(); glUniform4fvARB(gAvatarMatrixParam, 45, mat); + stop_glerror(); } } @@ -536,6 +535,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive + LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); @@ -565,11 +565,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) else if ( mTexture.notNull() ) { - if (!mTexture->getClampS() || !mTexture->getClampT()) - { - gGL.getTexUnit(0)->bind(mTexture.get()); - mTexture->overrideClamp (TRUE, TRUE); - } + old_mode = mTexture->getAddressMode(); + gGL.getTexUnit(0)->bind(mTexture.get()); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { @@ -628,7 +626,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) if (mTexture.notNull()) { gGL.getTexUnit(0)->bind(mTexture.get()); - mTexture->restoreClamp(); + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); } return triangle_count; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 417117bdf1..de16bbf8a1 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1047,6 +1047,7 @@ void init_debug_ui_menu(LLMenuGL* menu) menu->appendSeparator(); menu->append(new LLMenuItemCheckGL("Show Time", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowTime")); menu->append(new LLMenuItemCheckGL("Show Render Info", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderInfo")); + menu->append(new LLMenuItemCheckGL("Show Matrices", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowRenderMatrices")); menu->append(new LLMenuItemCheckGL("Show Color Under Cursor", menu_toggle_control, NULL, menu_check_control, (void*)"DebugShowColor")); menu->createJumpKeys(); @@ -1184,6 +1185,9 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("Octree", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCTREE)); + sub_menu->append(new LLMenuItemCheckGL("Shadow Frusta", &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)); sub_menu->append(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCCLUSION)); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index a6dede1e38..2925916e2a 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -788,8 +788,9 @@ void upload_new_resource(const std::string& src_filename, std::string name, uuid = tid.makeAssetID(gAgent.getSecureSessionID()); // copy this file into the vfs for upload S32 file_size; - apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size); - if (fp) + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + if (infile.getFileHandle()) { LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE); @@ -797,11 +798,10 @@ void upload_new_resource(const std::string& src_filename, std::string name, const S32 buf_size = 65536; U8 copy_buf[buf_size]; - while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size))) + while ((file_size = infile.read(copy_buf, buf_size))) { file.write(copy_buf, file_size); } - apr_file_close(fp); } else { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index bd433c0c73..e4ddbd42dd 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1406,7 +1406,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Setup object text - if (!mText) + if (!mText && (value & 0x4)) { mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); mText->setFont(LLFontGL::sSansSerif); @@ -1428,7 +1428,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(TEXTURE); } - else + else if(mText.notNull()) { mText->markDead(); mText = NULL; @@ -3730,11 +3730,11 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) else if (color != tep->getColor()) { retval = LLPrimitive::setTEColor(te, color); - setChanged(TEXTURE); + //setChanged(TEXTURE); if (mDrawable.notNull() && retval) { // These should only happen on updates which are not the initial update. - gPipeline.markTextured(mDrawable); + dirtyMesh(); } } return retval; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 45ab630e35..16a3b98d12 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -131,6 +131,8 @@ protected: public: typedef std::list<LLPointer<LLViewerObject> > child_list_t; + typedef std::list<LLPointer<LLViewerObject> > vobj_list_t; + typedef const child_list_t const_child_list_t; LLViewerObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp, BOOL is_global = FALSE); diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index b66f2c83be..866c2a91eb 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -74,8 +74,8 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_ mTexture->createGLTexture(0, mImageRaw); gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(mTexture); - mTexture->setClamp(TRUE, TRUE); - mTexture->setMipFilterNearest(TRUE); + mTexture->setAddressMode(LLTexUnit::TAM_CLAMP); + mTexture->setFilteringOption(LLTexUnit::TFO_POINT); // // Initialize the GL texture with empty data. diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index d513c021ee..b74f9e9f2c 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -152,7 +152,9 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo mVOPartGroupp->setPositionAgent(getCenterAgent()); F32 scale = box_side * 0.5f; mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); - gPipeline.addObject(mVOPartGroupp); + + //gPipeline.addObject(mVOPartGroupp); + gPipeline.createObject(mVOPartGroupp); LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index dfd97b8e65..38c75a84d1 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -102,7 +102,7 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) mPosAgent = mSourceObjectp->getPositionAgent(); mImagep = gImageList.getImageFromFile("pixiesmall.j2c"); gGL.getTexUnit(0)->bind(mImagep.get()); - mImagep->setClamp(TRUE, TRUE); + mImagep->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 1c025b42c9..b5bd2f93af 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -63,6 +63,8 @@ using std::pair; using std::make_pair; using std::string; +BOOL LLViewerShaderMgr::sInitialized = FALSE; + LLVector4 gShinyOrigin; //object shaders @@ -101,7 +103,23 @@ LLGLSLShader gPostColorFilterProgram; LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders +LLGLSLShader gDeferredImpostorProgram; +LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredBumpProgram; +LLGLSLShader gDeferredTerrainProgram; +LLGLSLShader gDeferredTreeProgram; +LLGLSLShader gDeferredAvatarProgram; +LLGLSLShader gDeferredAvatarAlphaProgram; +LLGLSLShader gDeferredLightProgram; +LLGLSLShader gDeferredMultiLightProgram; +LLGLSLShader gDeferredSunProgram; +LLGLSLShader gDeferredBlurLightProgram; +LLGLSLShader gDeferredSoftenProgram; +LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredAvatarShadowProgram; +LLGLSLShader gDeferredAlphaProgram; +LLGLSLShader gDeferredFullbrightProgram; //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -126,6 +144,15 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gAvatarWaterProgram); mShaderList.push_back(&gObjectShinyWaterProgram); mShaderList.push_back(&gUnderWaterProgram); + mShaderList.push_back(&gDeferredSunProgram); + mShaderList.push_back(&gDeferredBlurLightProgram); + mShaderList.push_back(&gDeferredSoftenProgram); + mShaderList.push_back(&gDeferredLightProgram); + mShaderList.push_back(&gDeferredMultiLightProgram); + mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredFullbrightProgram); + mShaderList.push_back(&gDeferredWaterProgram); + mShaderList.push_back(&gDeferredAvatarAlphaProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() @@ -188,6 +215,18 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedUniforms.push_back("gamma"); mReservedUniforms.push_back("scene_light_strength"); + mReservedUniforms.push_back("depthMap"); + mReservedUniforms.push_back("shadowMap0"); + mReservedUniforms.push_back("shadowMap1"); + mReservedUniforms.push_back("shadowMap2"); + mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("normalMap"); + mReservedUniforms.push_back("positionMap"); + mReservedUniforms.push_back("diffuseRect"); + mReservedUniforms.push_back("specularRect"); + mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightMap"); + mWLUniforms.push_back("camPosLocal"); mTerrainUniforms.reserve(5); @@ -240,7 +279,7 @@ S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type) void LLViewerShaderMgr::setShaders() { - if (!gPipeline.mInitialized) + if (!gPipeline.mInitialized || !sInitialized) { return; } @@ -254,6 +293,7 @@ void LLViewerShaderMgr::setShaders() { LLPipeline::sWaterReflections = gGLManager.mHasCubeMap; LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); + LLPipeline::updateRenderDeferred(); } else { @@ -290,36 +330,16 @@ void LLViewerShaderMgr::setShaders() S32 wl_class = 2; S32 water_class = 2; S32 deferred_class = 0; - if (!gSavedSettings.getBOOL("WindLightUseAtmosShaders")) + if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") + && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) { // user has disabled WindLight in their settings, downgrade // windlight shaders to stub versions. wl_class = 1; - - // if class one or less, turn off more shaders - // since higher end cards won't see any real gain - // from turning off most of the shaders, - // but class one would - // TODO: Make water on class one cards color things - // beneath it properly - if(LLFeatureManager::getInstance()->getGPUClass() < GPU_CLASS_2) - { - // use lesser water and other stuff - light_class = 2; - env_class = 0; - obj_class = 0; - effect_class = 1; - water_class = 1; - } } - if (gSavedSettings.getBOOL("RenderDeferred")) + if (LLPipeline::sRenderDeferred) { - light_class = 1; - env_class = 0; - obj_class = 0; - water_class = 1; - effect_class = 1; deferred_class = 1; } @@ -358,8 +378,7 @@ void LLViewerShaderMgr::setShaders() loadShadersWindLight(); loadShadersEffects(); loadShadersInterface(); - loadShadersDeferred(); - + // Load max avatar shaders to set the max level mVertexShaderLevel[SHADER_AVATAR] = 3; mMaxAvatarShaderLevel = 3; @@ -406,6 +425,11 @@ void LLViewerShaderMgr::setShaders() gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); loadShadersAvatar(); // unloads } + + if (!loadShadersDeferred()) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + } #endif } else @@ -511,6 +535,10 @@ BOOL LLViewerShaderMgr::loadBasicShaders() sum_lights_class = 1; } + // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. + S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); + sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); + // Load the Basic Vertex Shaders at the appropriate level. // (in order of shader function call depth for reference purposes, deepest level first) @@ -779,15 +807,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { if (mVertexShaderLevel[SHADER_DEFERRED] == 0) { + gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); + gDeferredBumpProgram.unload(); + gDeferredImpostorProgram.unload(); + gDeferredTerrainProgram.unload(); + gDeferredLightProgram.unload(); + gDeferredMultiLightProgram.unload(); + gDeferredSunProgram.unload(); + gDeferredBlurLightProgram.unload(); + gDeferredSoftenProgram.unload(); + gDeferredShadowProgram.unload(); + gDeferredAvatarShadowProgram.unload(); + gDeferredAvatarProgram.unload(); + gDeferredAvatarAlphaProgram.unload(); + gDeferredAlphaProgram.unload(); + gDeferredFullbrightProgram.unload(); + gDeferredWaterProgram.unload(); return FALSE; } + mVertexShaderLevel[SHADER_AVATAR] = 1; + BOOL success = TRUE; if (success) { - gDeferredDiffuseProgram.mName = "Deffered Diffuse Shader"; + gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -795,6 +841,187 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredBumpProgram.mName = "Deferred Bump Shader"; + gDeferredBumpProgram.mShaderFiles.clear(); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredBumpProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredTreeProgram.mName = "Deferred Tree Shader"; + gDeferredTreeProgram.mShaderFiles.clear(); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredTreeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; + gDeferredImpostorProgram.mShaderFiles.clear(); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredLightProgram.mName = "Deferred Light Shader"; + gDeferredLightProgram.mShaderFiles.clear(); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader"; + gDeferredMultiLightProgram.mShaderFiles.clear(); + gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredMultiLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSunProgram.mName = "Deferred Sun Shader"; + gDeferredSunProgram.mShaderFiles.clear(); + gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSunProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; + gDeferredBlurLightProgram.mShaderFiles.clear(); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredBlurLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; + gDeferredAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAlphaProgram.mFeatures.hasGamma = true; + gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredAlphaProgram.mFeatures.hasLighting = true; + gDeferredAlphaProgram.mShaderFiles.clear(); + gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAlphaProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader"; + gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightProgram.mFeatures.hasGamma = true; + gDeferredFullbrightProgram.mFeatures.hasTransport = true; + gDeferredFullbrightProgram.mFeatures.isFullbright = true; + gDeferredFullbrightProgram.mShaderFiles.clear(); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + // load water shader + gDeferredWaterProgram.mName = "Deferred Water Shader"; + gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true; + gDeferredWaterProgram.mFeatures.hasGamma = true; + gDeferredWaterProgram.mFeatures.hasTransport = true; + gDeferredWaterProgram.mShaderFiles.clear(); + gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredWaterProgram.createShader(NULL, &mWaterUniforms); + } + + if (success) + { + gDeferredSoftenProgram.mName = "Deferred Soften Shader"; + gDeferredSoftenProgram.mShaderFiles.clear(); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSoftenProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredShadowProgram.mName = "Deferred Shadow Shader"; + gDeferredShadowProgram.mShaderFiles.clear(); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; + gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; + gDeferredAvatarShadowProgram.mShaderFiles.clear(); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarShadowProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + + if (success) + { + gTerrainProgram.mName = "Deferred Terrain Shader"; + gDeferredTerrainProgram.mShaderFiles.clear(); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredTerrainProgram.createShader(NULL, &mTerrainUniforms); + } + + if (success) + { + gDeferredAvatarProgram.mName = "Avatar Shader"; + gDeferredAvatarProgram.mFeatures.hasSkinning = true; + gDeferredAvatarProgram.mShaderFiles.clear(); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + + if (success) + { + gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader"; + gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; + gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; + gDeferredAvatarAlphaProgram.mShaderFiles.clear(); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); + } + return success; } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 4cad3a23a8..a743966d93 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -38,6 +38,8 @@ class LLViewerShaderMgr: public LLShaderMgr { public: + static BOOL sInitialized; + LLViewerShaderMgr(); /* virtual */ ~LLViewerShaderMgr(); @@ -109,6 +111,17 @@ public: CLOUD_SCALE, GAMMA, SCENE_LIGHT_STRENGTH, + DEFERRED_DEPTH, + DEFERRED_SHADOW0, + DEFERRED_SHADOW1, + DEFERRED_SHADOW2, + DEFERRED_SHADOW3, + DEFERRED_NORMAL, + DEFERRED_POSITION, + DEFERRED_DIFFUSE, + DEFERRED_SPECULAR, + DEFERRED_NOISE, + DEFERRED_LIGHT, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -305,7 +318,23 @@ extern LLGLSLShader gPostColorFilterProgram; extern LLGLSLShader gPostNightVisionProgram; // Deferred rendering shaders +extern LLGLSLShader gDeferredImpostorProgram; +extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredBumpProgram; +extern LLGLSLShader gDeferredTerrainProgram; +extern LLGLSLShader gDeferredTreeProgram; +extern LLGLSLShader gDeferredLightProgram; +extern LLGLSLShader gDeferredMultiLightProgram; +extern LLGLSLShader gDeferredSunProgram; +extern LLGLSLShader gDeferredBlurLightProgram; +extern LLGLSLShader gDeferredAvatarProgram; +extern LLGLSLShader gDeferredSoftenProgram; +extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredAvatarShadowProgram; +extern LLGLSLShader gDeferredAlphaProgram; +extern LLGLSLShader gDeferredFullbrightProgram; +extern LLGLSLShader gDeferredAvatarAlphaProgram; //current avatar shader parameter pointer extern GLint gAvatarMatrixParam; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 2af3854816..648fbd4714 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -351,7 +351,6 @@ void LLViewerStats::addToMessage(LLSD &body) const // Moving them here, but not merging them into LLViewerStats yet. void reset_statistics() { - gPipeline.resetFrameStats(); // Reset per-frame statistics. if (LLSurface::sTextureUpdateTime) { LLSurface::sTexelsUpdatedPerSecStat.addValue(0.001f*(LLSurface::sTexelsUpdated / LLSurface::sTextureUpdateTime)); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e73736bc61..cddca66220 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -194,7 +194,7 @@ // // Globals // -void render_ui(); +void render_ui(F32 zoom_factor = 1.f, int subfield = 0); LLBottomPanel* gBottomPanel = NULL; extern BOOL gDebugClicks; @@ -447,7 +447,7 @@ public: if (gPipeline.mBatchCount > 0) { addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, - gPipeline.mMeanBatchSize)); + gPipeline.mTrianglesDrawn/gPipeline.mBatchCount)); gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize; gPipeline.mMaxBatchSize = 0; @@ -464,9 +464,46 @@ public: ypos += y_inc; + addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); + + ypos += y_inc; + LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = - gPipeline.mNumVisibleNodes = 0; + gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; + } + if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + { + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3])); + ypos += y_inc; + + addText(xpos, ypos, "Projection Matrix"); + ypos += y_inc; + + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7])); + ypos += y_inc; + + addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3])); + ypos += y_inc; + + addText(xpos, ypos, "View Matrix"); + ypos += y_inc; } if (gSavedSettings.getBOOL("DebugShowColor")) { @@ -3473,9 +3510,9 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) LLGLState scissor_state(GL_SCISSOR_TEST); scissor_state.enable(); glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight()); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClearColor(0.f, 0.f, 0.f, 0.f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } // build perspective transform and picking viewport @@ -4028,6 +4065,10 @@ void LLViewerWindow::playSnapshotAnimAndSound() BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) { + return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type); + + // *TODO below code was broken in deferred pipeline + /* if ((!raw) || preview_width < 10 || preview_height < 10) { return FALSE; @@ -4059,7 +4100,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame S32 w = preview_width ; - S32 h = preview_height ; + S32 h = preview_height ; LLVector2 display_scale = mDisplayScale ; mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ; LLRect window_rect = mWindowRect; @@ -4098,7 +4139,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p gltype = GL_UNSIGNED_BYTE ; } - raw->resize(w, h, glpixel_length); + raw->resize(w, h, glpixel_length); glReadPixels(0, 0, w, h, glformat, gltype, raw->getData()); if(SNAPSHOT_TYPE_DEPTH == type) @@ -4160,7 +4201,7 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p gSavedSettings.setS32("RenderName", render_name); - return TRUE; + return TRUE;*/ } // Saves the image from the screen to the specified filename and path. @@ -4210,7 +4251,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; snapshot_width = (S32)(ratio * image_width) ; snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; + scale_factor = llmax(1.0f, 1.0f / ratio) ; } else //the scene(window) proportion needs to be maintained. { @@ -4227,7 +4268,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei snapshot_width = image_width; snapshot_height = image_height; - target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE); + target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE); window_width = snapshot_width; window_height = snapshot_height; scale_factor = 1.f; @@ -4304,9 +4345,10 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei } else { - display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), TRUE); + const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); + display(do_rebuild, scale_factor, subfield, TRUE); // Required for showing the GUI in snapshots? See DEV-16350 for details. JC - render_ui(); + render_ui(scale_factor, subfield); } S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); @@ -4777,8 +4819,6 @@ BOOL LLViewerWindow::checkSettings() } mResDirty = false; - // This will force a state update the next frame. - mStatesDirty = true; } BOOL is_fullscreen = mWindow->getFullscreen(); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index b58f1147f3..b79d7d10ff 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -107,6 +107,7 @@ void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id) return; } mDetailTextures[corner] = gImageList.getImage(id); + mDetailTextures[corner]->setNoDelete() ; mRawImages[corner] = NULL; } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7e22eb40bb..3757923e27 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -684,9 +684,6 @@ LLVOAvatar::LLVOAvatar( mLowerMaskTexName(0), mCulled( FALSE ), mVisibilityRank(0), - mFadeTime(0.f), - mLastFadeTime(0.f), - mLastFadeDistance(1.f), mTexSkinColor( NULL ), mTexHairColor( NULL ), mTexEyeColor( NULL ), @@ -764,7 +761,7 @@ LLVOAvatar::LLVOAvatar( mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c"); gGL.getTexUnit(0)->bind(mShadowImagep.get()); - mShadowImagep->setClamp(TRUE, TRUE); + mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP); mInAir = FALSE; @@ -1362,11 +1359,11 @@ void LLVOAvatar::deleteCachedImages() LLTexLayerSet::sHasCaches = FALSE; } - for( GLuint* namep = (GLuint*)sScratchTexNames.getFirstData(); + for( LLGLuint * namep = sScratchTexNames.getFirstData(); namep; - namep = (GLuint*)sScratchTexNames.getNextData() ) + namep = sScratchTexNames.getNextData() ) { - glDeleteTextures(1, namep ); + LLImageGL::deleteTextures(1, (U32 *)namep ); stop_glerror(); } @@ -2868,12 +2865,15 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - mDrawable->movePartition(); - - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + if (mDrawable.notNull()) { - gPipeline.markMoved(mDrawable, TRUE); + mDrawable->movePartition(); + + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + { + gPipeline.markMoved(mDrawable, TRUE); + } } } @@ -3576,6 +3576,10 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) { //back 25% of max visible avatars are slow updating impostors mUpdatePeriod = 8; } + else if (visible && mVisibilityRank > (U32) LLVOAvatar::sMaxVisible) + { //background avatars are REALLY slow updating impostors + mUpdatePeriod = 16; + } else if (visible && mImpostorPixelArea <= impostor_area) { // stuff in between gets an update period based on pixel area mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8); @@ -4193,7 +4197,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mSkirtLOD.updateJointGeometry(); } - if (!mIsSelf || gAgent.needsRenderHead()) + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { mEyeLashLOD.updateJointGeometry(); mHeadLOD.updateJointGeometry(); @@ -4294,18 +4298,22 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { BOOL first_pass = TRUE; - if (!mIsSelf || gAgent.needsRenderHead()) + if (!LLDrawPoolAvatar::sSkipOpaque) { - num_indices += mHeadLOD.render(mAdjustedPixelArea); - first_pass = FALSE; + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + { + num_indices += mHeadLOD.render(mAdjustedPixelArea); + first_pass = FALSE; + } + num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { LLGLEnable blend(GL_BLEND); LLGLEnable test(GL_ALPHA_TEST); - num_indices += renderTransparent(); + num_indices += renderTransparent(first_pass); } } @@ -4318,10 +4326,9 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } -U32 LLVOAvatar::renderTransparent() +U32 LLVOAvatar::renderTransparent(BOOL first_pass) { U32 num_indices = 0; - BOOL first_pass = FALSE; if( isWearingWearableType( WT_SKIRT ) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); @@ -4330,7 +4337,7 @@ U32 LLVOAvatar::renderTransparent() gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } - if (!mIsSelf || gAgent.needsRenderHead()) + if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (LLPipeline::sImpostorRender) { @@ -4402,7 +4409,7 @@ U32 LLVOAvatar::renderFootShadows() } U32 foot_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; LLGLDepthTest test(GL_TRUE, GL_FALSE); //render foot shadows @@ -4435,23 +4442,6 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) LLGLEnable test(GL_ALPHA_TEST); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - F32 blend = gFrameTimeSeconds - mFadeTime; - - LLGLState gl_blend(GL_BLEND, blend < 1.f ? TRUE : FALSE); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - F32 alpha; - if (mVisibilityRank >= (U32) LLVOAvatar::sMaxVisible) - { //fade out - alpha = 1.f - llmin(blend, 1.f); - } - else - { //fade in - alpha = llmin(blend, 1.f); - } - - color.mV[3] = (U8) (alpha*255); - gGL.color4ubv(color.mV); gGL.getTexUnit(0)->bind(&mImpostor); gGL.begin(LLRender::QUADS); @@ -5945,6 +5935,11 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); + if (mDrawable.isNull()) + { + return; + } + const LLVector3* ext = mDrawable->getSpatialExtents(); LLVector3 center = (ext[1] + ext[0]) * 0.5f; LLVector3 size = (ext[1]-ext[0])*0.5f; @@ -6349,15 +6344,21 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) //----------------------------------------------------------------------------- void LLVOAvatar::lazyAttach() { + std::vector<LLPointer<LLViewerObject> > still_pending; + for (U32 i = 0; i < mPendingAttachment.size(); i++) { if (mPendingAttachment[i]->mDrawable) { attachObject(mPendingAttachment[i]); } + else + { + still_pending.push_back(mPendingAttachment[i]); + } } - mPendingAttachment.clear(); + mPendingAttachment = still_pending; } void LLVOAvatar::resetHUDAttachments() @@ -6957,8 +6958,7 @@ void LLVOAvatar::dumpTotalLocalTextureByteCount() BOOL LLVOAvatar::isVisible() { return mDrawable.notNull() - && (mDrawable->isVisible() || mIsDummy) - && (mVisibilityRank < (U32) sMaxVisible || gFrameTimeSeconds - mFadeTime < 1.f); + && (mDrawable->isVisible() || mIsDummy); } @@ -7133,23 +7133,21 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLGLSUIDefault gls_ui; - GLuint name = 0; - glGenTextures(1, &name ); + U32 name = 0; + LLImageGL::generateTextures(1, &name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, VOAVATAR_SCRATCH_TEX_WIDTH, VOAVATAR_SCRATCH_TEX_HEIGHT, - 0, format, GL_UNSIGNED_BYTE, NULL ); + format, GL_UNSIGNED_BYTE, NULL ); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -8758,20 +8756,19 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, } U32 gl_name; - glGenTextures(1, (GLuint*) &gl_name ); + LLImageGL::generateTextures(1, &gl_name ); stop_glerror(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); stop_glerror(); - glTexImage2D( + LLImageGL::setManualImage( GL_TEXTURE_2D, 0, GL_ALPHA8, aux_src->getWidth(), aux_src->getHeight(), - 0, GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); + GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); stop_glerror(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); if( id == head_baked->getID() ) { @@ -8783,7 +8780,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mHeadMaskDiscard = discard_level; if (self->mHeadMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mHeadMaskTexName); + LLImageGL::deleteTextures(1, &self->mHeadMaskTexName); } self->mHeadMaskTexName = gl_name; } @@ -8803,7 +8800,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mUpperMaskDiscard = discard_level; if (self->mUpperMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mUpperMaskTexName); + LLImageGL::deleteTextures(1, &self->mUpperMaskTexName); } self->mUpperMaskTexName = gl_name; } @@ -8823,7 +8820,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, self->mLowerMaskDiscard = discard_level; if (self->mLowerMaskTexName) { - glDeleteTextures(1, (GLuint*) &self->mLowerMaskTexName); + LLImageGL::deleteTextures(1, &self->mLowerMaskTexName); } self->mLowerMaskTexName = gl_name; } @@ -9010,7 +9007,9 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) void LLVOAvatar::dumpArchetypeXML( void* ) { LLVOAvatar* avatar = gAgent.getAvatarObject(); - apr_file_t* file = ll_apr_file_open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); + LLAPRFile outfile ; + outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle() ; if( !file ) { return; @@ -9053,7 +9052,6 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } apr_file_printf( file, "\t</archetype>\n" ); apr_file_printf( file, "\n</linden_genepool>\n" ); - apr_file_close( file ); } @@ -9069,33 +9067,7 @@ void LLVOAvatar::setVisibilityRank(U32 rank) return; } - BOOL stale = gFrameTimeSeconds - mLastFadeTime > 10.f; - - //only raise visibility rank or trigger a fade out every 10 seconds - if (mVisibilityRank >= (U32) LLVOAvatar::sMaxVisible && rank < (U32) LLVOAvatar::sMaxVisible || - (stale && mVisibilityRank < (U32) LLVOAvatar::sMaxVisible && rank >= (U32) LLVOAvatar::sMaxVisible)) - { //remember the time we became visible/invisible based on visibility rank - mVisibilityRank = rank; - mLastFadeTime = gFrameTimeSeconds; - mLastFadeDistance = mDrawable->mDistanceWRTCamera; - - F32 blend = gFrameTimeSeconds - mFadeTime; - mFadeTime = gFrameTimeSeconds; - if (blend < 1.f) - { //move the blend time back if a blend is already in progress (prevent flashes) - mFadeTime -= 1.f-blend; - } - } - else if (stale) - { - mLastFadeTime = gFrameTimeSeconds; - mLastFadeDistance = mDrawable->mDistanceWRTCamera; - mVisibilityRank = rank; - } - else - { - mVisibilityRank = llmin(mVisibilityRank, rank); - } + mVisibilityRank = rank; } // Assumes LLVOAvatar::sInstances has already been sorted. @@ -10023,7 +9995,7 @@ BOOL LLVOAvatar::isImpostor() const BOOL LLVOAvatar::needsImpostorUpdate() const { - return mNeedsImpostorUpdate ; + return mNeedsImpostorUpdate; } const LLVector3& LLVOAvatar::getImpostorOffset() const diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 81ab0fd49c..14f7bd6dcc 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -263,7 +263,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | (1 << LLVertexBuffer::TYPE_WEIGHT) | (1 << LLVertexBuffer::TYPE_CLOTHWEIGHT) }; @@ -306,7 +306,7 @@ public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255)); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); - U32 renderTransparent(); + U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, @@ -978,9 +978,6 @@ protected: BOOL mCulled; U32 mVisibilityRank; - F32 mFadeTime; - F32 mLastFadeTime; - F32 mLastFadeDistance; F32 mMinPixelArea; // debug F32 mMaxPixelArea; // debug BOOL mHasGrey; // debug diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 95c4550fde..5606398aaf 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -149,6 +149,8 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) mSoundSymbol.mWaveExpansion [i] = 1.0f; } + mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); + // The first instance loads the initial state from prefs. if (!sPrefsInitialized) { diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 322516fe56..6dfe23ba98 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -418,7 +418,9 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co void LLParticlePartition::getGeometry(LLSpatialGroup* group) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_PARTICLE_VB); + LLFastTimer ftm(mDrawableType == LLPipeline::RENDER_TYPE_GRASS ? + LLFastTimer::FTM_REBUILD_GRASS_VB : + LLFastTimer::FTM_REBUILD_PARTICLE_VB); std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); @@ -438,7 +440,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) buffer->getVertexStrider(verticesp); buffer->getNormalStrider(normalsp); buffer->getColorStrider(colorsp); - buffer->getTexCoordStrider(texcoordsp); + buffer->getTexCoord0Strider(texcoordsp); buffer->getIndexStrider(indicesp); LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass]; @@ -479,8 +481,12 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); + info->mExtents[0] = group->mObjectExtents[0]; + info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; draw_vec.push_back(info); + //for alpha sorting + facep->setDrawInfo(info); } } diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 30a3165826..3dc3292992 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -47,7 +47,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 3ec043eb39..c3366cad90 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -213,7 +213,7 @@ void LLSkyTex::init() for (S32 i = 0; i < 2; ++i) { mImageGL[i] = new LLImageGL(FALSE); - mImageGL[i]->setClamp(TRUE, TRUE); + mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP); mImageRaw[i] = new LLImageRaw(sResolution, sResolution, sComponents); initEmpty(i); @@ -231,7 +231,7 @@ void LLSkyTex::restoreGL() for (S32 i = 0; i < 2; i++) { mImageGL[i] = new LLImageGL(FALSE); - mImageGL[i]->setClamp(TRUE, TRUE); + mImageGL[i]->setAddressMode(LLTexUnit::TAM_CLAMP); } } @@ -290,7 +290,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { mImageGL[which]->createGLTexture(0, mImageRaw[which]); - mImageGL[which]->setClamp(TRUE, TRUE); + mImageGL[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } void LLSkyTex::bindTexture(BOOL curr) @@ -377,11 +377,12 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mMoon.setIntensity(0.1f * SUN_INTENSITY); mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE); - mSunTexturep->setClamp(TRUE, TRUE); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE); - mMoonTexturep->setClamp(TRUE, TRUE); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = gImageList.getImage(IMG_BLOOM1); - mBloomTexturep->setClamp(TRUE, TRUE); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mHeavenlyBodyUpdated = FALSE ; } @@ -447,6 +448,7 @@ void LLVOSky::initCubeMap() mCubeMap = new LLCubeMap(); mCubeMap->init(images); } + gGL.getTexUnit(0)->disable(); } @@ -471,11 +473,12 @@ void LLVOSky::restoreGL() mSkyTex[i].restoreGL(); } mSunTexturep = gImageList.getImage(gSunTextureID, TRUE, TRUE); - mSunTexturep->setClamp(TRUE, TRUE); + mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mMoonTexturep = gImageList.getImage(gMoonTextureID, TRUE, TRUE); - mMoonTexturep->setClamp(TRUE, TRUE); + mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = gImageList.getImage(IMG_BLOOM1); - mBloomTexturep->setClamp(TRUE, TRUE); + mBloomTexturep->setNoDelete() ; + mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); calcAtmospherics(); @@ -1153,6 +1156,7 @@ BOOL LLVOSky::updateSky() images.push_back(mShinyTex[side].getImageRaw(TRUE)); } mCubeMap->init(images); + gGL.getTexUnit(0)->disable(); } gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); @@ -2024,7 +2028,7 @@ void LLVOSky::updateFog(const F32 distance) const BOOL hide_clip_plane = TRUE; LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f); - const F32 water_height = gAgent.getRegion()->getWaterHeight(); + const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f; // LLWorld::getInstance()->getWaterHeight(); F32 camera_height = gAgent.getCameraPositionAgent().mV[2]; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 3a90a665a8..4980b50de4 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -57,40 +57,30 @@ class LLVertexBufferTerrain : public LLVertexBuffer { public: LLVertexBufferTerrain() : - LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD | MAP_TEXCOORD2 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) + LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0 | MAP_TEXCOORD1 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) { + //texture coordinates 2 and 3 exist, but use the same data as texture coordinate 1 + mOffsets[TYPE_TEXCOORD3] = mOffsets[TYPE_TEXCOORD2] = mOffsets[TYPE_TEXCOORD1]; + mTypeMask |= MAP_TEXCOORD2 | MAP_TEXCOORD3; }; - // virtual + /*// virtual void setupVertexBuffer(U32 data_mask) const { - if (LLDrawPoolTerrain::getDetailMode() == 0) + if (LLDrawPoolTerrain::getDetailMode() == 0 || LLPipeline::sShadowRender) { LLVertexBuffer::setupVertexBuffer(data_mask); } - else if (data_mask & LLVertexBuffer::MAP_TEXCOORD2) + else if (data_mask & LLVertexBuffer::MAP_TEXCOORD1) { - U8* base = useVBOs() ? NULL : mMappedData; - - glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); - glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - glColorPointer(4, GL_UNSIGNED_BYTE, mStride, (void*)(base + mOffsets[TYPE_COLOR])); - - glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + LLVertexBuffer::setupVertexBuffer(data_mask); } else { LLVertexBuffer::setupVertexBuffer(data_mask); } llglassertok(); - } + }*/ }; //============================================================================ @@ -1054,8 +1044,8 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); - llassert_always(buffer->getTexCoordStrider(texcoords)); - llassert_always(buffer->getTexCoord2Strider(texcoords2)); + llassert_always(buffer->getTexCoord0Strider(texcoords)); + llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getColorStrider(colors)); llassert_always(buffer->getIndexStrider(indices)); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 7b0529287c..2dd8651899 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -49,8 +49,8 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | - (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 4c7b90d8a1..3b76127eb2 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -86,6 +86,7 @@ LLVOTree::LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *region mSpecies = 0; mFrameCount = 0; mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + mTrunkLOD = 0; } @@ -343,41 +344,69 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } - F32 mass_inv; - - // For all tree objects, update the trunk bending with the current wind - // Walk sprite list in order away from viewer - if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) + if (gSavedSettings.getBOOL("RenderAnimateTrees")) { - // If needed, Get latest wind for this tree - mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + F32 mass_inv; + + // For all tree objects, update the trunk bending with the current wind + // Walk sprite list in order away from viewer + if (!(mFrameCount % FRAMES_PER_WIND_UPDATE)) + { + // If needed, Get latest wind for this tree + mWind = mRegionp->mWind.getVelocity(getPositionRegion()); + } + mFrameCount++; + + mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); + mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind + mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk + mTrunkBend += mTrunkVel; + mTrunkVel *= 0.99f; // Add damping + + if (mTrunkBend.length() > 1.f) + { + mTrunkBend.normalize(); + } + + if (mTrunkVel.length() > 1.f) + { + mTrunkVel.normalize(); + } } - mFrameCount++; - mass_inv = 1.f/(5.f + mDepth*mBranches*0.2f); - mTrunkVel += (mWind * mass_inv * TREE_WIND_SENSITIVITY); // Pull in direction of wind - mTrunkVel -= (mTrunkBend * mass_inv * TREE_TRUNK_STIFFNESS); // Restoring force in direction of trunk - mTrunkBend += mTrunkVel; - mTrunkVel *= 0.99f; // Add damping + S32 trunk_LOD = 0; + F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; - if (mTrunkBend.length() > 1.f) + for (S32 j = 0; j < 4; j++) { - mTrunkBend.normalize(); - } - if (mTrunkVel.length() > 1.f) + if (app_angle > LLVOTree::sLODAngles[j]) + { + trunk_LOD = j; + break; + } + } + + if (!gSavedSettings.getBOOL("RenderAnimateTrees")) { - mTrunkVel.normalize(); + if (mReferenceBuffer.isNull()) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + else if (trunk_LOD != mTrunkLOD) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, FALSE); + } } + mTrunkLOD = trunk_LOD; + return TRUE; } - const F32 TREE_BLEND_MIN = 1.f; const F32 TREE_BLEND_RANGE = 1.f; - void LLVOTree::render(LLAgent &agent) { } @@ -450,338 +479,604 @@ const S32 LEAF_VERTICES = 16; BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE); - const F32 SRR3 = 0.577350269f; // sqrt(1/3) - const F32 SRR2 = 0.707106781f; // sqrt(1/2) - U32 i, j; - U32 slices = MAX_SLICES; + if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull()) + { + const F32 SRR3 = 0.577350269f; // sqrt(1/3) + const F32 SRR2 = 0.707106781f; // sqrt(1/2) + U32 i, j; + + U32 slices = MAX_SLICES; + + S32 max_indices = LEAF_INDICES; + S32 max_vertices = LEAF_VERTICES; + S32 lod; + + LLFace *face = drawable->getFace(0); + + face->mCenterAgent = getPositionAgent(); + face->mCenterLocal = face->mCenterAgent; + + for (lod = 0; lod < 4; lod++) + { + slices = sLODSlices[lod]; + sLODVertexOffset[lod] = max_vertices; + sLODVertexCount[lod] = slices*slices; + sLODIndexOffset[lod] = max_indices; + sLODIndexCount[lod] = (slices-1)*(slices-1)*6; + max_indices += sLODIndexCount[lod]; + max_vertices += sLODVertexCount[lod]; + } + + mReferenceBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, gSavedSettings.getBOOL("RenderAnimateTrees") ? GL_STATIC_DRAW_ARB : 0); + mReferenceBuffer->allocateBuffer(max_vertices, max_indices, TRUE); + + LLStrider<LLVector3> vertices; + LLStrider<LLVector3> normals; + LLStrider<LLVector2> tex_coords; + LLStrider<U16> indicesp; + + mReferenceBuffer->getVertexStrider(vertices); + mReferenceBuffer->getNormalStrider(normals); + mReferenceBuffer->getTexCoord0Strider(tex_coords); + mReferenceBuffer->getIndexStrider(indicesp); + + S32 vertex_count = 0; + S32 index_count = 0; + + // First leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 1; + index_count++; + *(indicesp++) = 2; + index_count++; + + *(indicesp++) = 0; + index_count++; + *(indicesp++) = 3; + index_count++; + *(indicesp++) = 1; + index_count++; + + // Same leaf, inverse winding/normals + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); + vertex_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 6; + index_count++; + *(indicesp++) = 5; + index_count++; + + *(indicesp++) = 4; + index_count++; + *(indicesp++) = 5; + index_count++; + *(indicesp++) = 7; + index_count++; + + + // next leaf + *(normals++) = LLVector3(SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 9; + index_count++; + *(indicesp++) = 10; + index_count++; + + *(indicesp++) = 8; + index_count++; + *(indicesp++) = 11; + index_count++; + *(indicesp++) = 9; + index_count++; + + + // other side of same leaf + *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); + *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); + *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); + vertex_count++; + + *(normals++) = LLVector3(-SRR2, SRR2, 0.f); + *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); + *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); + vertex_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 14; + index_count++; + *(indicesp++) = 13; + index_count++; + + *(indicesp++) = 12; + index_count++; + *(indicesp++) = 13; + index_count++; + *(indicesp++) = 15; + index_count++; + + // Generate geometry for the cylinders + + // Different LOD's + + // Generate the vertices + // Generate the indices + + for (lod = 0; lod < 4; lod++) + { + slices = sLODSlices[lod]; + F32 base_radius = 0.65f; + F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; + //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl; + //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl; + F32 angle = 0; + F32 angle_inc = 360.f/(slices-1); + F32 z = 0.f; + F32 z_inc = 1.f; + if (slices > 3) + { + z_inc = 1.f/(slices - 3); + } + F32 radius = base_radius; + + F32 x1,y1; + F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; + LLVector3 nvec; + + const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch + + const S32 fractal_depth = 5; + F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; + F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; + + F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; + + F32 start_radius; + F32 nangle = 0; + F32 height = 1.f; + F32 r0; + + for (i = 0; i < slices; i++) + { + if (i == 0) + { + z = - cap_nudge; + r0 = 0.0; + } + else if (i == (slices - 1)) + { + z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; + r0 = 0.0; + } + else + { + z = (i - 1) * z_inc; + r0 = base_radius + (top_radius - base_radius)*z; + } - S32 max_indices = LEAF_INDICES; - S32 max_vertices = LEAF_VERTICES; - S32 lod; + for (j = 0; j < slices; j++) + { + if (slices - 1 == j) + { + angle = 0.f; + } + else + { + angle = j*angle_inc; + } + + nangle = angle; + + x1 = cos(angle * DEG_TO_RAD); + y1 = sin(angle * DEG_TO_RAD); + LLVector2 tc; + // This isn't totally accurate. Should compute based on slope as well. + start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); + nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, + z*nvec_scalez); + // First and last slice at 0 radius (to bring in top/bottom of structure) + radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; + + if (slices - 1 == j) + { + // Not 0.5 for slight slop factor to avoid edges on leaves + tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); + } + else + { + tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); + } + + *(vertices++) = LLVector3(x1*radius, y1*radius, z); + *(normals++) = LLVector3(x1, y1, 0.f); + *(tex_coords++) = tc; + vertex_count++; + } + } - LLFace *face = drawable->getFace(0); + for (i = 0; i < (slices - 1); i++) + { + for (j = 0; j < (slices - 1); j++) + { + S32 x1_offset = j+1; + if ((j+1) == slices) + { + x1_offset = 0; + } + // Generate the matching quads + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + + *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; + llassert(*(indicesp) < (U32)max_vertices); + indicesp++; + index_count++; + } + } + slices /= 2; + } - face->mCenterAgent = getPositionAgent(); - face->mCenterLocal = face->mCenterAgent; + mReferenceBuffer->setBuffer(0); + llassert(vertex_count == max_vertices); + llassert(index_count == max_indices); + } - for (lod = 0; lod < 4; lod++) + if (gSavedSettings.getBOOL("RenderAnimateTrees")) + { + mDrawable->getFace(0)->mVertexBuffer = mReferenceBuffer; + } + else { - slices = sLODSlices[lod]; - sLODVertexOffset[lod] = max_vertices; - sLODVertexCount[lod] = slices*slices; - sLODIndexOffset[lod] = max_indices; - sLODIndexCount[lod] = (slices-1)*(slices-1)*6; - max_indices += sLODIndexCount[lod]; - max_vertices += sLODVertexCount[lod]; + //generate tree mesh + updateMesh(); } + + return TRUE; +} +void LLVOTree::updateMesh() +{ + LLMatrix4 matrix; + + // Translate to tree base HACK - adjustment in Z plants tree underground + const LLVector3 &pos_agent = getPositionAgent(); + //glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + LLMatrix4 trans_mat; + trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat *= matrix; + + // Rotate to tree position and bend for current trunk/wind + // Note that trunk stiffness controls the amount of bend at the trunk as + // opposed to the crown of the tree + // + const F32 TRUNK_STIFF = 22.f; + + LLQuaternion rot = + LLQuaternion(mTrunkBend.magVec()*TRUNK_STIFF*DEG_TO_RAD, LLVector4(mTrunkBend.mV[VX], mTrunkBend.mV[VY], 0)) * + LLQuaternion(90.f*DEG_TO_RAD, LLVector4(0,0,1)) * + getRotation(); + + LLMatrix4 rot_mat(rot); + rot_mat *= trans_mat; + + F32 radius = getScale().magVec()*0.05f; + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = + scale_mat.mMatrix[1][1] = + scale_mat.mMatrix[2][2] = radius; + + scale_mat *= rot_mat; + +// const F32 THRESH_ANGLE_FOR_BILLBOARD = 15.f; +// const F32 BLEND_RANGE_FOR_BILLBOARD = 3.f; + + F32 droop = mDroop + 25.f*(1.f - mTrunkBend.magVec()); + + S32 stop_depth = 0; + F32 alpha = 1.0; + + + U32 vert_count = 0; + U32 index_count = 0; + + calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); + + LLFace* facep = mDrawable->getFace(0); + facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); + facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE); + LLStrider<LLVector3> vertices; LLStrider<LLVector3> normals; LLStrider<LLVector2> tex_coords; - LLStrider<U16> indicesp; - - face->setSize(max_vertices, max_indices); + LLStrider<U16> indices; + U16 idx_offset = 0; - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE); - face->setGeomIndex(0); - face->setIndicesIndex(0); + facep->mVertexBuffer->getVertexStrider(vertices); + facep->mVertexBuffer->getNormalStrider(normals); + facep->mVertexBuffer->getTexCoord0Strider(tex_coords); + facep->mVertexBuffer->getIndexStrider(indices); - face->getGeometry(vertices, normals, tex_coords, indicesp); + genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); + mReferenceBuffer->setBuffer(0); + facep->mVertexBuffer->setBuffer(0); + +} - S32 vertex_count = 0; - S32 index_count = 0; +void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& cur_idx, + LLMatrix4& matrix, + LLMatrix4& norm_mat, + S32 vert_start, + S32 vert_count, + S32 index_count, + S32 index_offset) +{ + LLStrider<LLVector3> v; + LLStrider<LLVector3> n; + LLStrider<LLVector2> t; + LLStrider<U16> idx; + + mReferenceBuffer->getVertexStrider(v); + mReferenceBuffer->getNormalStrider(n); + mReferenceBuffer->getTexCoord0Strider(t); + mReferenceBuffer->getIndexStrider(idx); - // First leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 1; - index_count++; - *(indicesp++) = 2; - index_count++; - - *(indicesp++) = 0; - index_count++; - *(indicesp++) = 3; - index_count++; - *(indicesp++) = 1; - index_count++; - - // Same leaf, inverse winding/normals - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f); - vertex_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 6; - index_count++; - *(indicesp++) = 5; - index_count++; - - *(indicesp++) = 4; - index_count++; - *(indicesp++) = 5; - index_count++; - *(indicesp++) = 7; - index_count++; - - - // next leaf - *(normals++) = LLVector3(SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 9; - index_count++; - *(indicesp++) = 10; - index_count++; - - *(indicesp++) = 8; - index_count++; - *(indicesp++) = 11; - index_count++; - *(indicesp++) = 9; - index_count++; - - - // other side of same leaf - *(normals++) = LLVector3(-SRR2, -SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR3, -SRR3, SRR3); - *(tex_coords++) = LLVector2(LEAF_LEFT, LEAF_TOP); - *(vertices++) = LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f); - vertex_count++; - - *(normals++) = LLVector3(-SRR2, SRR2, 0.f); - *(tex_coords++) = LLVector2(LEAF_RIGHT, LEAF_BOTTOM); - *(vertices++) = LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f); - vertex_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 14; - index_count++; - *(indicesp++) = 13; - index_count++; - - *(indicesp++) = 12; - index_count++; - *(indicesp++) = 13; - index_count++; - *(indicesp++) = 15; - index_count++; - - // Generate geometry for the cylinders - - // Different LOD's - - // Generate the vertices - // Generate the indices - - for (lod = 0; lod < 4; lod++) + //copy/transform vertices into mesh - check + for (S32 i = 0; i < vert_count; i++) + { + U16 index = vert_start + i; + *vertices++ = v[index] * matrix; + LLVector3 norm = n[index] * norm_mat; + norm.normalize(); + *normals++ = norm; + *tex_coords++ = t[index]; + } + + //copy offset indices into mesh - check + for (S32 i = 0; i < index_count; i++) { - slices = sLODSlices[lod]; - F32 base_radius = 0.65f; - F32 top_radius = base_radius * sSpeciesTable[mSpecies]->mTaper; - //llinfos << "Species " << ((U32) mSpecies) << ", taper = " << sSpeciesTable[mSpecies].mTaper << llendl; - //llinfos << "Droop " << mDroop << ", branchlength: " << mBranchLength << llendl; - F32 angle = 0; - F32 angle_inc = 360.f/(slices-1); - F32 z = 0.f; - F32 z_inc = 1.f; - if (slices > 3) + U16 index = index_offset + i; + if (idx[index] >= vert_start + vert_count || + idx[index] < vert_start) { - z_inc = 1.f/(slices - 3); + llerrs << "WTF?" << llendl; } - F32 radius = base_radius; - - F32 x1,y1; - F32 noise_scale = sSpeciesTable[mSpecies]->mNoiseMag; - LLVector3 nvec; - - const F32 cap_nudge = 0.1f; // Height to 'peak' the caps on top/bottom of branch - - const S32 fractal_depth = 5; - F32 nvec_scale = 1.f * sSpeciesTable[mSpecies]->mNoiseScale; - F32 nvec_scalez = 4.f * sSpeciesTable[mSpecies]->mNoiseScale; + *indices++ = idx[index]-vert_start+cur_idx; + } - F32 tex_z_repeat = sSpeciesTable[mSpecies]->mRepeatTrunkZ; + //increment index offset - check + cur_idx += vert_count; +} + + +void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& index_offset, + LLMatrix4& matrix, + S32 trunk_LOD, + S32 stop_level, + U16 depth, + U16 trunk_depth, + F32 scale, + F32 twist, + F32 droop, + F32 branches, + F32 alpha) +{ + // + // Generates a tree mesh by recursing, generating branches and then a 'leaf' texture. + + static F32 constant_twist; + static F32 width = 0; - F32 start_radius; - F32 nangle = 0; - F32 height = 1.f; - F32 r0; + F32 length = ((trunk_depth || (scale == 1.f))? mTrunkLength:mBranchLength); + F32 aspect = ((trunk_depth || (scale == 1.f))? mTrunkAspect:mBranchAspect); + + constant_twist = 360.f/branches; - for (i = 0; i < slices; i++) + if (stop_level >= 0) + { + if (depth > stop_level) { - if (i == 0) { - z = - cap_nudge; - r0 = 0.0; + llassert(sLODIndexCount[trunk_LOD] > 0); + width = scale * length * aspect; + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = width; + scale_mat.mMatrix[1][1] = width; + scale_mat.mMatrix[2][2] = scale*length; + scale_mat *= matrix; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + norm_mat.invert(); + appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, + sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[trunk_LOD]); } - else if (i == (slices - 1)) + + // Recurse to create more branches + for (S32 i=0; i < (S32)branches; i++) { - z = 1.f + cap_nudge;//((i - 2) * z_inc) + cap_nudge; - r0 = 0.0; + LLMatrix4 trans_mat; + trans_mat.setTranslation(0,0,scale*length); + trans_mat *= matrix; + + LLQuaternion rot = + LLQuaternion(20.f*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)) * + LLQuaternion(droop*DEG_TO_RAD, LLVector4(0.f, 1.f, 0.f)) * + LLQuaternion(((constant_twist + ((i%2==0)?twist:-twist))*i)*DEG_TO_RAD, LLVector4(0.f, 0.f, 1.f)); + + LLMatrix4 rot_mat(rot); + rot_mat *= trans_mat; + + genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha); } - else + // Recurse to continue trunk + if (trunk_depth) { - z = (i - 1) * z_inc; - r0 = base_radius + (top_radius - base_radius)*z; - } + LLMatrix4 trans_mat; + trans_mat.setTranslation(0,0,scale*length); + trans_mat *= matrix; - for (j = 0; j < slices; j++) + LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1)); + rot_mat *= trans_mat; // rotate a bit around Z when ascending + genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); + } + } + else + { + // + // Append leaves as two 90 deg crossed quads with leaf textures + // { - if (slices - 1 == j) - { - angle = 0.f; - } - else - { - angle = j*angle_inc; - } - - nangle = angle; - - x1 = cos(angle * DEG_TO_RAD); - y1 = sin(angle * DEG_TO_RAD); - LLVector2 tc; - // This isn't totally accurate. Should compute based on slope as well. - start_radius = r0 * (1.f + 1.2f*fabs(z - 0.66f*height)/height); - nvec.set( cos(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - sin(nangle * DEG_TO_RAD)*start_radius*nvec_scale, - z*nvec_scalez); - // First and last slice at 0 radius (to bring in top/bottom of structure) - radius = start_radius + turbulence3((F32*)&nvec.mV, (F32)fractal_depth)*noise_scale; - - if (slices - 1 == j) - { - // Not 0.5 for slight slop factor to avoid edges on leaves - tc = LLVector2(0.490f, (1.f - z/2.f)*tex_z_repeat); - } - else - { - tc = LLVector2((angle/360.f)*0.5f, (1.f - z/2.f)*tex_z_repeat); - } + LLMatrix4 scale_mat; + scale_mat.mMatrix[0][0] = + scale_mat.mMatrix[1][1] = + scale_mat.mMatrix[2][2] = scale*mLeafScale; - *(vertices++) = LLVector3(x1*radius, y1*radius, z); - *(normals++) = LLVector3(x1, y1, 0.f); - *(tex_coords++) = tc; - vertex_count++; + scale_mat *= matrix; + + glh::matrix4f norm((F32*) scale_mat.mMatrix); + LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m); + + appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0); } } + } +} + - for (i = 0; i < (slices - 1); i++) + +void LLVOTree::calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches) +{ + if (stop_level >= 0) + { + if (depth > stop_level) { - for (j = 0; j < (slices - 1); j++) + index_count += sLODIndexCount[trunk_LOD]; + vert_count += sLODVertexCount[trunk_LOD]; + + // Recurse to create more branches + for (S32 i=0; i < (S32)branches; i++) { - S32 x1_offset = j+1; - if ((j+1) == slices) - { - x1_offset = 0; - } - // Generate the matching quads - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = j + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - - *(indicesp) = j + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + (i*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; - *(indicesp) = x1_offset + ((i+1)*slices) + sLODVertexOffset[lod]; - llassert(*(indicesp) < (U32)max_vertices); - indicesp++; - index_count++; + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth - 1, 0, branches); } + + // Recurse to continue trunk + if (trunk_depth) + { + calcNumVerts(vert_count, index_count, trunk_LOD, stop_level, depth, trunk_depth-1, branches); + } + } + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; } - slices /= 2; } - - face->mVertexBuffer->setBuffer(0); - llassert(vertex_count == max_vertices); - llassert(index_count == max_indices); - - return TRUE; + else + { + index_count += LEAF_INDICES; + vert_count += LEAF_VERTICES; + } } U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha) diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 7e81dc3e08..473f1c340e 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -51,7 +51,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) + (1 << LLVertexBuffer::TYPE_TEXCOORD0) }; LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); @@ -79,6 +79,38 @@ public: void updateRadius(); + void calcNumVerts(U32& vert_count, U32& index_count, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 branches); + + void updateMesh(); + + void appendMesh(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& idx_offset, + LLMatrix4& matrix, + LLMatrix4& norm_mat, + S32 vertex_offset, + S32 vertex_count, + S32 index_count, + S32 index_offset); + + void genBranchPipeline(LLStrider<LLVector3>& vertices, + LLStrider<LLVector3>& normals, + LLStrider<LLVector2>& tex_coords, + LLStrider<U16>& indices, + U16& index_offset, + LLMatrix4& matrix, + S32 trunk_LOD, + S32 stop_level, + U16 depth, + U16 trunk_depth, + F32 scale, + F32 twist, + F32 droop, + F32 branches, + F32 alpha); + U32 drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha); @@ -127,6 +159,7 @@ protected: LLVector3 mTrunkVel; // LLVector3 mWind; + LLPointer<LLVertexBuffer> mReferenceBuffer; //reference geometry for generating tree mesh LLPointer<LLViewerImage> mTreeImagep; // Pointer to proper tree image U8 mSpecies; // Species of tree @@ -138,7 +171,7 @@ protected: U8 mDepth; // Number of recursions to tips of branches F32 mScaleStep; // Multiplier for scale at each recursion level U8 mTrunkDepth; - + U32 mTrunkLOD; F32 mLeafScale; // Scales leaf texture when rendering F32 mBillboardScale; // How big to draw the billboard? diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9023147a7d..9e051a6470 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -409,7 +409,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) void LLVOVolume::updateTextures(LLAgent &agent) { const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds - if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + if (mDrawable.notNull() && mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) { if (mDrawable->isVisible()) { @@ -468,17 +468,6 @@ void LLVOVolume::updateTextures() F32 old_size = face->getVirtualSize(); - if (face->getPoolType() == LLDrawPool::POOL_ALPHA) - { - - if (LLPipeline::sFastAlpha && - vsize < MIN_ALPHA_SIZE && old_size > MIN_ALPHA_SIZE || - vsize > MIN_ALPHA_SIZE && old_size < MIN_ALPHA_SIZE) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_COLOR, FALSE); - } - } - if (face->mTextureMatrix != NULL) { if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || @@ -1283,10 +1272,12 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { S32 res = LLViewerObject::setTEColor(te, color); - if (res) + if (res && mDrawable.notNull()) { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; + //gPipeline.markTextured(mDrawable); + mDrawable->setState(LLDrawable::REBUILD_COLOR); + dirtyMesh(); + //mFaceMappingChanged = TRUE; } return res; } @@ -1392,11 +1383,11 @@ S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) void LLVOVolume::updateTEData() { - if (mDrawable.notNull()) + /*if (mDrawable.notNull()) { mFaceMappingChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); - } + }*/ } //---------------------------------------------------------------------------- @@ -1824,7 +1815,9 @@ F32 LLVOVolume::getBinRadius() { LLFace* face = mDrawable->getFace(i); if (face->getPoolType() == LLDrawPool::POOL_ALPHA && - (!LLPipeline::sFastAlpha || face->getVirtualSize() > MIN_ALPHA_SIZE)) + (!LLPipeline::sFastAlpha || + face->getFaceColor().mV[3] != 1.f || + !face->getTexture()->getIsAlphaMask())) { alpha_wrap = TRUE; break; @@ -1849,14 +1842,20 @@ F32 LLVOVolume::getBinRadius() } else if (mDrawable->isStatic()) { - if (mDrawable->getRadius() < 2.0f) + /*if (mDrawable->getRadius() < 2.0f) { radius = 16.f; } else { radius = llmax(mDrawable->getRadius(), 32.f); - } + }*/ + + radius = (((S32) mDrawable->getRadius())/2+1)*8; + } + else if (mDrawable->getVObj()->isAttachment()) + { + radius = (((S32) (mDrawable->getRadius()*4)+1))*2; } else { @@ -2128,6 +2127,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, glow = (U8) (facep->getTextureEntry()->getGlow() * 255); } + if (facep->mVertexBuffer.isNull()) + { + llerrs << "WTF?" << llendl; + } + if (idx >= 0 && draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && @@ -2146,6 +2150,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); validate_draw_info(*draw_vec[idx]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); + update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); } else { @@ -2161,6 +2167,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mTextureMatrix = tex_mat; draw_info->mModelMatrix = model_mat; draw_info->mGlowColor.setVec(0,0,0,glow); + if (type == LLRenderPass::PASS_ALPHA) + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + draw_info->mExtents[0] = facep->mExtents[0]; + draw_info->mExtents[1] = facep->mExtents[1]; validate_draw_info(*draw_info); } } @@ -2184,89 +2196,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; - if (!group->isState(LLSpatialGroup::GEOM_DIRTY | - LLSpatialGroup::ALPHA_DIRTY)) + if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) { - if (group->isState(LLSpatialGroup::MESH_DIRTY)) + if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { - S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; - - group->mBuilt = 1.f; LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); - LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); - - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - if (drawablep->isState(LLDrawable::REBUILD_ALL)) - { - LLVOVolume* vobj = drawablep->getVOVolume(); - vobj->preRebuild(); - LLVolume* volume = vobj->getVolume(); - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull()) - { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); - } - } - - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } - - //unmap all the buffers - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) - { - LLSpatialGroup::buffer_list_t& list = i->second; - for (LLSpatialGroup::buffer_list_t::iterator j = list.begin(); j != list.end(); ++j) - { - LLVertexBuffer* buffer = *j; - if (buffer->isLocked()) - { - buffer->setBuffer(0); - } - } - } - - // don't forget alpha - if( group != NULL && - !group->mVertexBuffer.isNull() && - group->mVertexBuffer->isLocked()) - { - group->mVertexBuffer->setBuffer(0); - } - - //if not all buffers are unmapped - if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) - { - llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) - { - LLDrawable* drawablep = *drawable_iter; - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked()) - { - face->mVertexBuffer->setBuffer(0) ; - } - } - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY); + + rebuildMesh(group); } - return; } @@ -2279,15 +2217,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) mFaceList.clear(); + std::vector<LLFace*> fullbright_faces; + std::vector<LLFace*> bump_faces; + std::vector<LLFace*> simple_faces; + std::vector<LLFace*> alpha_faces; - U32 vertex_count = 0; - U32 index_count = 0; U32 useage = group->mSpatialPartition->mBufferUsage; U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); - //get all the faces into a list, putting alpha faces in their own list + U32 cur_total = 0; + + //get all the faces into a list for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -2313,6 +2256,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); + + if (cur_total > max_total) + { + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + continue; + } + + cur_total += facep->getGeomCount(); + if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) { const LLTextureEntry* te = facep->getTextureEntry(); @@ -2349,36 +2302,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - BOOL alpha_opt = LLPipeline::sFastAlpha && gPipeline.canUseWindLightShadersOnObjects() && facep->getVirtualSize() < MIN_ALPHA_SIZE; - - const LLColor4& col = facep->getTextureEntry()->getColor(); - - if (alpha_opt) - { //if we're applying the alpha optimization, only blend faces that have alpha (0.15, 0.5] - //for faces with alpha (0.5, 1.0], render with an alpha mask - //for faces with alpha [0.0, 0.15], don't render - if (col.mV[3] > 0.5f) - { - mFaceList.push_back(facep); - } - else if (col.mV[3] > 0.15f) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - alpha_faces.push_back(facep); - } - else - { //face has no renderable geometry - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; - //don't alpha wrap drawables that have only tiny tiny alpha faces - facep->setPoolType(LLDrawPool::POOL_SIMPLE); - } + if (LLPipeline::sFastAlpha && + (te->getColor().mV[VW] == 1.0f) && + facep->getTexture()->getIsAlphaMask()) + { //can be treated as alpha mask + simple_faces.push_back(facep); } else { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); alpha_faces.push_back(facep); } } @@ -2388,124 +2319,300 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { facep->mLastUpdateTime = gFrameTimeSeconds; } - mFaceList.push_back(facep); + + if (gPipeline.canUseWindLightShadersOnObjects() + && LLPipeline::sRenderBump) + { + if (te->getBumpmap()) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + fullbright_faces.push_back(facep); + } + } + else + { + if (te->getBumpmap() && LLPipeline::sRenderBump) + { //needs normal + binormal + bump_faces.push_back(facep); + } + else if (te->getShiny() && LLPipeline::sRenderBump || + !te->getFullbright()) + { //needs normal + simple_faces.push_back(facep); + } + else + { //doesn't need normal + fullbright_faces.push_back(facep); + } + } } } else { //face has no renderable geometry facep->mVertexBuffer = NULL; facep->mLastVertexBuffer = NULL; - //don't alpha wrap drawables that have only tiny tiny alpha faces - facep->setPoolType(LLDrawPool::POOL_SIMPLE); } } } - U16 alpha_vertex_count = vertex_count > 65535 ? 65535 : vertex_count; - U32 alpha_index_count = index_count; - group->mBufferUsage = useage; //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + if (LLPipeline::sRenderDeferred) { - //sort faces by things that break batches - std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareBatchBreaker()); - - std::vector<LLFace*>::iterator face_iter = mFaceList.begin(); - - LLSpatialGroup::buffer_map_t buffer_map; + bump_mask |= LLVertexBuffer::MAP_BINORMAL; + } - LLViewerImage* last_tex = NULL; - U32 buffer_index = 0; + genDrawInfo(group, simple_mask, simple_faces); + genDrawInfo(group, bump_mask, bump_faces); + genDrawInfo(group, fullbright_mask, fullbright_faces); + genDrawInfo(group, alpha_mask, alpha_faces, TRUE); - while (face_iter != mFaceList.end()) + if (!LLPipeline::sDelayVBUpdate) + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { - //pull off next face - LLFace* facep = *face_iter; - LLViewerImage* tex = facep->getTexture(); + LLDrawable* drawablep = *drawable_iter; + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } - if (last_tex == tex) - { - buffer_index++; - } - else + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + + if (LLPipeline::sDelayVBUpdate) + { + group->setState(LLSpatialGroup::MESH_DIRTY); + } + + mFaceList.clear(); +} + +void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) +{ + if (group->isState(LLSpatialGroup::MESH_DIRTY)) + { + S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; + + group->mBuilt = 1.f; + + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { - last_tex = tex; - buffer_index = 0; + continue; } - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); - - //sum up vertices needed for this texture - std::vector<LLFace*>::iterator i = face_iter; - ++i; - - while (i != mFaceList.end() && - (LLPipeline::sTextureBindTest || (*i)->getTexture() == tex)) + if (drawablep->isState(LLDrawable::REBUILD_ALL)) { - facep = *i; - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut vertex buffers on geom count too big - break; + LLVOVolume* vobj = drawablep->getVOVolume(); + vobj->preRebuild(); + LLVolume* volume = vobj->getVolume(); + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face && face->mVertexBuffer.notNull()) + { + face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + } } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + drawablep->clearState(LLDrawable::REBUILD_ALL); } + } - //create/delete/resize vertex buffer if needed - LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex); - if (found_iter != group->mBufferMap.end()) + //unmap all the buffers + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + { + LLSpatialGroup::buffer_texture_map_t& map = i->second; + for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j) { - if (buffer_index < found_iter->second.size()) + LLSpatialGroup::buffer_list_t& list = j->second; + for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k) { - buffer = found_iter->second[buffer_index]; + LLVertexBuffer* buffer = *k; + if (buffer->isLocked()) + { + buffer->setBuffer(0); + } } } - - if (!buffer) - { //create new buffer if needed + } + + // don't forget alpha + if( group != NULL && + !group->mVertexBuffer.isNull() && + group->mVertexBuffer->isLocked()) + { + group->mVertexBuffer->setBuffer(0); + } + + //if not all buffers are unmapped + if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) + { + llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked()) + { + face->mVertexBuffer->setBuffer(0) ; + } + } + } + } + + group->clearState(LLSpatialGroup::MESH_DIRTY); + } +} + +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) +{ + //calculate maximum number of vertices to store in a single buffer + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + if (!distance_sort) + { + //sort faces by things that break batches + std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker()); + } + else + { + //sort faces by distance + std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); + } + + std::vector<LLFace*>::iterator face_iter = faces.begin(); + + LLSpatialGroup::buffer_map_t buffer_map; + + LLViewerImage* last_tex = NULL; + S32 buffer_index = 0; + + if (distance_sort) + { + buffer_index = -1; + } + + while (face_iter != faces.end()) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerImage* tex = facep->getTexture(); + + if (distance_sort) + { + tex = NULL; + } + + if (last_tex == tex) + { + buffer_index++; + } + else + { + last_tex = tex; + buffer_index = 0; + } + + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); + + //sum up vertices needed for this texture + std::vector<LLFace*>::iterator i = face_iter; + ++i; + + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut vertex buffers on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } + + //create/delete/resize vertex buffer if needed + LLVertexBuffer* buffer = NULL; + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex); + + if (found_iter != group->mBufferMap[mask].end()) + { + if ((U32) buffer_index < found_iter->second.size()) + { + buffer = found_iter->second[buffer_index]; + } + } + + if (!buffer) + { //create new buffer if needed + buffer = createVertexBuffer(mask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { + if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) + { buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); + group->mBufferUsage); buffer->allocateBuffer(geom_count, index_count, TRUE); } - else + else { - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) - { - buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); - buffer->allocateBuffer(geom_count, index_count, TRUE); - } - else - { - buffer->resizeBuffer(geom_count, index_count); - } + buffer->resizeBuffer(geom_count, index_count); } + } - buffer_map[tex].push_back(buffer); + buffer_map[mask][tex].push_back(buffer); - //add face geometry + //add face geometry - U32 indices_index = 0; - U16 index_offset = 0; + U32 indices_index = 0; + U16 index_offset = 0; - while (face_iter < i) + while (face_iter < i) + { + facep = *face_iter; + facep->mIndicesIndex = indices_index; + facep->mGeomIndex = index_offset; + facep->mVertexBuffer = buffer; { - facep = *face_iter; - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - U32 te_idx = facep->getTEOffset(); - facep->mIndicesIndex = indices_index; - facep->mGeomIndex = index_offset; - facep->mVertexBuffer = buffer; + facep->updateRebuildFlags(); + if (!LLPipeline::sDelayVBUpdate) { + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + U32 te_idx = facep->getTEOffset(); + if (facep->getGeometryVolume(*volume, te_idx, vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) { @@ -2513,168 +2620,130 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->getIndicesStart(), facep->getIndicesCount()); } } + } - index_offset += facep->getGeomCount(); - indices_index += facep->mIndicesCount; - - BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - const LLTextureEntry* te = facep->getTextureEntry(); + index_offset += facep->getGeomCount(); + indices_index += facep->mIndicesCount; - BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; + BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + const LLTextureEntry* te = facep->getTextureEntry(); - if (!is_alpha - && gPipeline.canUseWindLightShadersOnObjects() - && LLPipeline::sRenderBump - && te->getShiny()) + BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE; + + if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (LLPipeline::sFastAlpha && + (te->getColor().mV[VW] == 1.0f) && + facep->getTexture()->getIsAlphaMask()) { - if (tex->getPrimaryFormat() == GL_ALPHA) + if (te->getFullbright()) { - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); } else { - registerFace(group, facep, LLRenderPass::PASS_SHINY); + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); } } else { - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + + if (LLPipeline::sRenderDeferred) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_SHADOW); + } + } + else if (gPipeline.canUseVertexShaders() + && LLPipeline::sRenderBump + && te->getShiny()) + { + if (tex->getPrimaryFormat() == GL_ALPHA) + { + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (LLPipeline::sRenderDeferred) + { + if (te->getBumpmap()) { - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + registerFace(group, facep, LLRenderPass::PASS_BUMP); } - else if (fullbright) + else if (te->getFullbright()) { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else { registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } - - if (!is_alpha && te->getShiny()) - { - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } } - - if (!is_alpha) + else if (fullbright) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else { - facep->setPoolType(LLDrawPool::POOL_SIMPLE); - - if (!force_simple && te->getBumpmap()) + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + else + { + if (LLPipeline::sRenderDeferred && te->getBumpmap()) { registerFace(group, facep, LLRenderPass::PASS_BUMP); } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } } - - if (LLPipeline::sRenderGlow && te->getGlow() > 0.f) + + if (!is_alpha && te->getShiny()) { - registerFace(group, facep, LLRenderPass::PASS_GLOW); + registerFace(group, facep, LLRenderPass::PASS_SHINY); } - - ++face_iter; - } - - buffer->setBuffer(0); - } - - group->mBufferMap.clear(); - for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i) - { - group->mBufferMap[i->first] = i->second; - } - } - - //PROCESS ALPHA FACES - if (!alpha_faces.empty()) - { - //sort alpha faces by distance - std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater()); - - //store alpha faces in root vertex buffer - if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage())) - { - group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, - group->mBufferUsage); - group->mVertexBuffer->allocateBuffer(alpha_vertex_count, alpha_index_count, true); - stop_glerror(); - } - else - { - group->mVertexBuffer->resizeBuffer(alpha_vertex_count, alpha_index_count); - stop_glerror(); - } - - //get vertex buffer striders - LLVertexBuffer* buffer = group->mVertexBuffer; - - U32 index_offset = 0; - U32 indices_index = 0; - - for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i) - { - LLFace* facep = *i; - - if (facep->mGeomCount + index_offset > 65535) - { //cut off alpha nodes at 64k vertices - facep->mVertexBuffer = NULL ; - facep->mLastVertexBuffer = NULL ; - continue ; } - - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - U32 te_idx = facep->getTEOffset(); - facep->mIndicesIndex = indices_index; - facep->mGeomIndex = index_offset; - facep->mVertexBuffer = group->mVertexBuffer; - if (facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), - index_offset)) + + if (!is_alpha && !LLPipeline::sRenderDeferred) { - buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), - facep->getIndicesStart(), facep->getIndicesCount()); + facep->setPoolType(LLDrawPool::POOL_SIMPLE); + + if (!force_simple && te->getBumpmap()) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } } - index_offset += facep->getGeomCount(); - indices_index += facep->mIndicesCount; - - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - - if (LLPipeline::sRenderGlow && facep->getTextureEntry()->getGlow() > 0.f) + if (LLPipeline::sRenderGlow && te->getGlow() > 0.f) { registerFace(group, facep, LLRenderPass::PASS_GLOW); - } + } + + ++face_iter; } buffer->setBuffer(0); } - else - { - group->mVertexBuffer = NULL; - } - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) { - LLDrawable* drawablep = *drawable_iter; - drawablep->clearState(LLDrawable::REBUILD_ALL); + group->mBufferMap[mask][i->first] = i->second; } - - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | - LLSpatialGroup::ALPHA_DIRTY | LLSpatialGroup::MESH_DIRTY); - - mFaceList.clear(); } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 50f754b882..155775510e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -84,8 +84,8 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) | - (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) | (1 << LLVertexBuffer::TYPE_COLOR) }; diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 8ea47387c8..cdda48f6f2 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -52,7 +52,7 @@ public: { VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD) + (1 << LLVertexBuffer::TYPE_TEXCOORD0) }; LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 635989e3af..abd25e6598 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -320,7 +320,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE); BOOL success = mFanVerts->getVertexStrider(vertices) - && mFanVerts->getTexCoordStrider(texCoords) + && mFanVerts->getTexCoord0Strider(texCoords) && mFanVerts->getIndexStrider(indices); if(!success) @@ -380,7 +380,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) // lock the buffer BOOL success = segment->getVertexStrider(vertices) - && segment->getTexCoordStrider(texCoords) + && segment->getTexCoord0Strider(texCoords) && segment->getIndexStrider(indices); if(!success) diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 4239996017..f11ef97b55 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -111,7 +111,7 @@ LLWorld::LLWorld() : mDefaultWaterTexturep = new LLViewerImage(raw, FALSE); gGL.getTexUnit(0)->bind(mDefaultWaterTexturep.get()); - mDefaultWaterTexturep->setClamp(TRUE, TRUE); + mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -872,7 +872,7 @@ void LLWorld::updateWaterObjects() y + rwidth/2, 256.f+DEFAULT_WATER_HEIGHT)); waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); - gPipeline.addObject(waterp); + gPipeline.createObject(waterp); mHoleWaterObjects.push_back(waterp); } } @@ -923,7 +923,7 @@ void LLWorld::updateWaterObjects() waterp = mEdgeWaterObjects[dir]; waterp->setUseTexture(FALSE); waterp->setIsEdgePatch(TRUE); - gPipeline.addObject(waterp); + gPipeline.createObject(waterp); } waterp->setRegion(gAgent.getRegion()); diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 4d46ff19cc..c9a3bd2112 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -506,9 +506,9 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) new_layer.LayerDefined = TRUE; msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block); new_layer.LayerImage = gImageList.getImage(new_layer.LayerImageID, MIPMAP_TRUE, FALSE); - + gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); - new_layer.LayerImage->setClamp(TRUE, TRUE); + new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); U32 left, right, top, bottom; msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Left, left, block); @@ -618,10 +618,11 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) siminfo->mRegionFlags = region_flags; siminfo->mWaterHeight = (F32) water_height; siminfo->mMapImageID[agent_flags] = image_id; + #ifdef IMMEDIATE_IMAGE_LOAD siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); gGL.getTexUnit(0)->bind(siminfo->mCurrentImage.get()); - siminfo->mCurrentImage->setClamp(TRUE, TRUE); + siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); #endif if (siminfo->mMapImageID[2].notNull()) diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 1cf8755e62..db36fa0ffe 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -511,7 +511,7 @@ void LLWorldMapView::draw() { textures_requested_this_tick++; info->mCurrentImage = gImageList.getImage(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE); - info->mCurrentImage->setClamp(TRUE, TRUE); + info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP); simimage = info->mCurrentImage; gGL.getTexUnit(0)->bind(simimage); } @@ -524,7 +524,7 @@ void LLWorldMapView::draw() { textures_requested_this_tick++; info->mOverlayImage = gImageList.getImage(info->mMapImageID[2], MIPMAP_TRUE, FALSE); - info->mOverlayImage->setClamp(TRUE, TRUE); + info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP); overlayimage = info->mOverlayImage; gGL.getTexUnit(0)->bind(overlayimage); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 62e337b2d1..3a5e41e3ca 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -139,21 +139,22 @@ LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; //---------------------------------------- - std::string gPoolNames[] = { // Correspond to LLDrawpool enum render type "NONE", "POOL_SIMPLE", - "POOL_TERRAIN", + "POOL_TERRAIN", + "POOL_BUMP", "POOL_TREE", "POOL_SKY", "POOL_WL_SKY", "POOL_GROUND", - "POOL_BUMP", "POOL_INVISIBLE", "POOL_AVATAR", "POOL_WATER", + "POOL_GRASS", + "POOL_FULLBRIGHT", "POOL_GLOW", "POOL_ALPHA", }; @@ -232,10 +233,12 @@ BOOL LLPipeline::sRenderSoundBeacons = FALSE; BOOL LLPipeline::sRenderBeacons = FALSE; BOOL LLPipeline::sRenderHighlight = TRUE; S32 LLPipeline::sUseOcclusion = 0; +BOOL LLPipeline::sDelayVBUpdate = TRUE; BOOL LLPipeline::sFastAlpha = TRUE; BOOL LLPipeline::sDisableShaders = FALSE; BOOL LLPipeline::sRenderBump = TRUE; BOOL LLPipeline::sUseFarClip = TRUE; +BOOL LLPipeline::sShadowRender = FALSE; BOOL LLPipeline::sSkipUpdate = FALSE; BOOL LLPipeline::sWaterReflections = FALSE; BOOL LLPipeline::sRenderGlow = FALSE; @@ -246,6 +249,8 @@ BOOL LLPipeline::sTextureBindTest = FALSE; BOOL LLPipeline::sRenderFrameTest = FALSE; BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; +BOOL LLPipeline::sRenderDeferred = FALSE; +S32 LLPipeline::sVisibleLightCount = 0; static LLCullResult* sCull = NULL; @@ -261,6 +266,13 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); +void addDeferredAttachments(LLRenderTarget& target) +{ + target.addColorAttachment(GL_RGBA16F_ARB); //specular + target.addColorAttachment(GL_RGBA16F_ARB); //normal+z + target.addColorAttachment(GL_RGBA16F_ARB); //position +} + LLPipeline::LLPipeline() : mBackfaceCull(FALSE), mBatchCount(0), @@ -276,9 +288,6 @@ LLPipeline::LLPipeline() : mGeometryChanges(0), mNumVisibleFaces(0), - mCubeBuffer(NULL), - mCubeFrameBuffer(0), - mCubeDepth(0), mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), @@ -293,6 +302,7 @@ LLPipeline::LLPipeline() : mWaterPool(NULL), mGroundPool(NULL), mSimplePool(NULL), + mFullbrightPool(NULL), mInvisiblePool(NULL), mGlowPool(NULL), mBumpPool(NULL), @@ -301,8 +311,7 @@ LLPipeline::LLPipeline() : mLightMovingMask(0), mLightingDetail(0) { - mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0; - mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0; + mNoiseMap = 0; } void LLPipeline::init() @@ -321,6 +330,8 @@ void LLPipeline::init() //create render pass pools getPool(LLDrawPool::POOL_ALPHA); getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_GRASS); + getPool(LLDrawPool::POOL_FULLBRIGHT); getPool(LLDrawPool::POOL_INVISIBLE); getPool(LLDrawPool::POOL_BUMP); getPool(LLDrawPool::POOL_GLOW); @@ -405,6 +416,8 @@ void LLPipeline::cleanup() mGroundPool = NULL; delete mSimplePool; mSimplePool = NULL; + delete mFullbrightPool; + mFullbrightPool = NULL; delete mInvisiblePool; mInvisiblePool = NULL; delete mGlowPool; @@ -456,52 +469,103 @@ void LLPipeline::resizeScreenTexture() GLuint resY = gViewerWindow->getWindowDisplayHeight(); U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); - if (res_mod > 1) + if (res_mod > 1 && res_mod < resX && res_mod < resY) { resX /= res_mod; resY /= res_mod; } - - mScreen.release(); - mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE); + + allocateScreenBuffer(resX,resY); llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl; } } - -void LLPipeline::releaseGLBuffers() +void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { - assertInitialized(); - - if (mCubeBuffer) + U32 samples = gSavedSettings.getU32("RenderFSAASamples"); + if (LLPipeline::sRenderDeferred) { - mCubeBuffer = NULL; + //allocate deferred rendering color buffers + mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + addDeferredAttachments(mDeferredScreen); + mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + + for (U32 i = 0; i < 2; i++) + { + mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } } - - if (mCubeFrameBuffer) + else { - glDeleteFramebuffersEXT(1, &mCubeFrameBuffer); - glDeleteRenderbuffersEXT(1, &mCubeDepth); - mCubeDepth = mCubeFrameBuffer = 0; + mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); } + - if (mBlurCubeBuffer[0]) + if (gGLManager.mHasFramebufferMultisample && samples > 1) { - glDeleteFramebuffersEXT(3, mBlurCubeBuffer); - mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0; + if (LLPipeline::sRenderDeferred) + { + mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + addDeferredAttachments(mSampleBuffer); + mDeferredScreen.setSampleBuffer(&mSampleBuffer); + } + else + { + mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + } + + mScreen.setSampleBuffer(&mSampleBuffer); + stop_glerror(); + } + else if (LLPipeline::sRenderDeferred) + { //share depth buffer between deferred targets + mDeferredScreen.shareDepthBuffer(mScreen); + for (U32 i = 0; i < 2; i++) + { + mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); + } } - if (mBlurCubeTexture[0]) + gGL.getTexUnit(0)->disable(); + + stop_glerror(); + +} + +//static +void LLPipeline::updateRenderDeferred() +{ + BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") && + LLRenderTarget::sUseFBO && + gSavedSettings.getBOOL("VertexShaderEnable") && + gSavedSettings.getBOOL("RenderAvatarVP") && + gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE; + + sRenderDeferred = deferred; +} + +void LLPipeline::releaseGLBuffers() +{ + assertInitialized(); + + if (mNoiseMap) { - glDeleteTextures(3, mBlurCubeTexture); - mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0; + LLImageGL::deleteTextures(1, &mNoiseMap); + mNoiseMap = 0; } mWaterRef.release(); mWaterDis.release(); mScreen.release(); - + mSampleBuffer.releaseSampleBuffer(); + mDeferredScreen.release(); + + + for (U32 i = 0; i < 4; i++) + { + mSunShadow[i].release(); + } for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -514,72 +578,17 @@ void LLPipeline::createGLBuffers() { assertInitialized(); + updateRenderDeferred(); + if (LLPipeline::sWaterReflections) { //water reflection texture U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution"); - mWaterRef.allocate(res,res,GL_RGBA,TRUE); - mWaterDis.allocate(res,res,GL_RGBA,TRUE); - -#if 0 //cube map buffers (keep for future work) - { - //reflection map generation buffers - if (mCubeFrameBuffer == 0) - { - glGenFramebuffersEXT(1, &mCubeFrameBuffer); - glGenRenderbuffersEXT(1, &mCubeDepth); - - U32 res = REFLECTION_MAP_RES; - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth); - - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,res,res); - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - } - - if (mCubeBuffer.isNull()) - { - res = 128; - mCubeBuffer = new LLCubeMap(); - mCubeBuffer->initGL(); - mCubeBuffer->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - - if (mBlurCubeBuffer[0] == 0) - { - glGenFramebuffersEXT(3, mBlurCubeBuffer); - } - - if (mBlurCubeTexture[0] == 0) - { - glGenTextures(3, mBlurCubeTexture); - } - - res = (U32) gSavedSettings.getS32("RenderReflectionRes"); - - for (U32 j = 0; j < 3; j++) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j]); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - } -#endif + mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE); + mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE); } + stop_glerror(); if (LLPipeline::sRenderGlow) @@ -589,14 +598,41 @@ void LLPipeline::createGLBuffers() for (U32 i = 0; i < 3; i++) { - mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE); + mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE); } - + } - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); + GLuint resX = gViewerWindow->getWindowDisplayWidth(); + GLuint resY = gViewerWindow->getWindowDisplayHeight(); - mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE); + allocateScreenBuffer(resX,resY); + + if (sRenderDeferred) + { + mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE); + mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE); + + if (!mNoiseMap) + { + const U32 noiseRes = 128; + LLVector3 noise[noiseRes*noiseRes]; + + F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; + for (U32 i = 0; i < noiseRes*noiseRes; ++i) + { + noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + noise[i].normVec(); + noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + } + + LLImageGL::generateTextures(1, &mNoiseMap); + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } } } @@ -627,7 +663,8 @@ void LLPipeline::restoreGL() BOOL LLPipeline::canUseVertexShaders() { - if (!gGLManager.mHasVertexShader || + if (sDisableShaders || + !gGLManager.mHasVertexShader || !gGLManager.mHasFragmentShader || !LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") || (assertInitialized() && mVertexShadersLoaded != 1) ) @@ -785,6 +822,14 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) poolp = mSimplePool; break; + case LLDrawPool::POOL_GRASS: + poolp = mGrassPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + poolp = mFullbrightPool; + break; + case LLDrawPool::POOL_INVISIBLE: poolp = mInvisiblePool; break; @@ -964,19 +1009,61 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) U32 LLPipeline::addObject(LLViewerObject *vobj) { - LLMemType mt(LLMemType::MTYPE_DRAWABLE); if (gNoRender) { return 0; } + if (gSavedSettings.getBOOL("RenderDelayCreation")) + { + mCreateQ.push_back(vobj); + } + else + { + createObject(vobj); + } + + return 1; +} + +void LLPipeline::createObjects(F32 max_dtime) +{ + LLFastTimer ftm(LLFastTimer::FTM_GEO_UPDATE); + LLMemType mt(LLMemType::MTYPE_DRAWABLE); + + LLTimer update_timer; + + while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) + { + LLViewerObject* vobj = mCreateQ.front(); + if (!vobj->isDead()) + { + createObject(vobj); + } + mCreateQ.pop_front(); + } + + //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) + //{ + // createObject(*iter); + //} + + //mCreateQ.clear(); +} + +void LLPipeline::createObject(LLViewerObject* vobj) +{ LLDrawable* drawablep = vobj->mDrawable; if (!drawablep) { drawablep = vobj->createDrawable(this); } - + else + { + llerrs << "Redundant drawable creation!" << llendl; + } + llassert(drawablep); if (vobj->getParent()) @@ -990,7 +1077,14 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); - return 1; + if (drawablep->getVOVolume() && gSavedSettings.getBOOL("RenderAnimateRes")) + { + // fun animated res + drawablep->updateXform(TRUE); + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + drawablep->setScale(LLVector3(0,0,0)); + drawablep->makeActive(); + } } @@ -1195,6 +1289,65 @@ void LLPipeline::grabReferences(LLCullResult& result) sCull = &result; } +BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) +{ + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (part->visibleObjectsInFrustum(camera)) + { + return TRUE; + } + } + } + } + } + + return FALSE; +} + +BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) +{ + min = LLVector3(F32_MAX, F32_MAX, F32_MAX); + max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX); + + + BOOL res = TRUE; + + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (!part->getVisibleExtents(camera, min, max)) + { + res = FALSE; + } + } + } + } + } + + return res; +} + + void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip) { LLFastTimer t(LLFastTimer::FTM_CULL); @@ -1207,6 +1360,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl BOOL to_texture = LLPipeline::sUseOcclusion > 1 && !hasRenderType(LLPipeline::RENDER_TYPE_HUD) && !sReflectionRender && + !sShadowRender && gPipeline.canUseVertexShaders() && sRenderGlow; @@ -1217,6 +1371,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl glPushMatrix(); gGLLastMatrix = NULL; + //glLoadMatrixd(gGLModelView); glLoadMatrixd(gGLLastModelView); LLVertexBuffer::unbind(); @@ -1224,7 +1379,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setColorMask(false, false); + if (sUseOcclusion > 1) + { + gGL.setColorMask(false, false); + } + LLGLDepthTest depth(GL_TRUE, GL_FALSE); for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -1282,13 +1441,17 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl sCull->pushDrawable(gSky.mVOGroundp->mDrawable); } - gGL.setColorMask(true, false); + glPopMatrix(); + if (sUseOcclusion > 1) + { + gGL.setColorMask(true, false); + } + if (to_texture) { mScreen.flush(); - LLRenderTarget::unbindTarget(); } else if (LLPipeline::sUseOcclusion > 1) { @@ -1357,6 +1520,7 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) void LLPipeline::doOcclusion(LLCamera& camera) { LLVertexBuffer::unbind(); + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { gGL.setColorMask(true, false, false, false); @@ -1525,7 +1689,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) if (!drawablep) { - llerrs << "Sending null drawable to moved list!" << llendl; + //llerrs << "Sending null drawable to moved list!" << llendl; return; } @@ -1595,8 +1759,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) assertInitialized(); glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = FALSE; - + gDepthDirty = TRUE; + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); iter++) { @@ -1772,6 +1936,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) stateSort(drawablep, camera); } } + } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) @@ -2045,6 +2210,22 @@ void LLPipeline::postSort(LLCamera& camera) } LLSpatialGroup::sNoDelete = TRUE; + + const S32 bin_count = 1024*8; + + static LLCullResult::drawinfo_list_t alpha_bins[bin_count]; + static U32 bin_size[bin_count]; + + //clear one bin per frame to avoid memory bloat + static S32 clear_idx = 0; + clear_idx = (1+clear_idx)%bin_count; + alpha_bins[clear_idx].clear(); + + for (U32 j = 0; j < bin_count; j++) + { + bin_size[j] = 0; + } + //build render map for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { @@ -2064,7 +2245,7 @@ void LLPipeline::postSort(LLCamera& camera) sCull->pushDrawInfo(j->first, *k); } } - + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); if (alpha != group->mDrawMap.end()) @@ -2090,28 +2271,26 @@ void LLPipeline::postSort(LLCamera& camera) } } + if (!sShadowRender) { //sort by texture or bump map for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i) { - //if (!mRenderMap[i].empty()) + if (i == LLRenderPass::PASS_BUMP) { - if (i == LLRenderPass::PASS_BUMP) - { - std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump()); - } - else - { - std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix()); - } + std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump()); } + else + { + std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix()); + } } std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater()); } - + // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus - if (gSavedSettings.getBOOL("BeaconAlwaysOn")) + if (gSavedSettings.getBOOL("BeaconAlwaysOn") && !sShadowRender) { if (sRenderScriptedTouchBeacons) { @@ -2164,23 +2343,26 @@ void LLPipeline::postSort(LLCamera& camera) LLFloaterTelehub::addBeacons(); } - mSelectedFaces.clear(); - - // Draw face highlights for selected faces. - if (LLSelectMgr::getInstance()->getTEMode()) + if (!sShadowRender) { - struct f : public LLSelectedTEFunctor + mSelectedFaces.clear(); + + // Draw face highlights for selected faces. + if (LLSelectMgr::getInstance()->getTEMode()) { - virtual bool apply(LLViewerObject* object, S32 te) + struct f : public LLSelectedTEFunctor { - if (object->mDrawable) + virtual bool apply(LLViewerObject* object, S32 te) { - gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + if (object->mDrawable) + { + gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te)); + } + return true; } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + } func; + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + } } LLSpatialGroup::sNoDelete = FALSE; @@ -2328,8 +2510,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) stop_glerror(); gFrameStats.start(LLFrameStats::RENDER_SYNC); - glEnableClientState(GL_VERTEX_ARRAY); - LLVertexBuffer::unbind(); // Do verification of GL state @@ -2379,7 +2559,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } gGL.getTexUnit(0)->bind(LLViewerImage::sDefaultImagep); - LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE); + LLViewerImage::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP); ////////////////////////////////////////////// // @@ -2387,37 +2567,39 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) // // stop_glerror(); - BOOL occlude = sUseOcclusion > 1; - U32 cur_type = 0; - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools"); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) - { LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); - gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } } - else if (gSavedSettings.getBOOL("RenderDeferred")) + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred"); - renderGeomDeferred(); + gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); } else { - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + LLFastTimer t(LLFastTimer::FTM_POOLS); + + // HACK: don't calculate local lights if we're rendering the HUD! + // Removing this check will cause bad flickering when there are + // HUD elements being rendered AND the user is in flycam mode -nyx + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) - { - poolp->prerender(); - } + calcNearbyLights(camera); + setupHWLights(NULL); } - - LLFastTimer t(LLFastTimer::FTM_POOLS); - calcNearbyLights(camera); - setupHWLights(NULL); + BOOL occlude = sUseOcclusion > 1; + U32 cur_type = 0; pool_set_t::iterator iter1 = mPools.begin(); while ( iter1 != mPools.end() ) @@ -2426,7 +2608,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) cur_type = poolp->getType(); - if (occlude && cur_type > LLDrawPool::POOL_AVATAR) + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) { occlude = FALSE; gGLLastMatrix = NULL; @@ -2444,6 +2626,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) for( S32 i = 0; i < poolp->getNumPasses(); i++ ) { + LLVertexBuffer::unbind(); poolp->beginRenderPass(i); for (iter2 = iter1; iter2 != mPools.end(); iter2++) { @@ -2487,25 +2670,29 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) iter1 = iter2; stop_glerror(); } - } LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd"); LLVertexBuffer::unbind(); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + if (occlude) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + } + } + + LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); - gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); - - if (occlude) - { - occlude = FALSE; - gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); - doOcclusion(camera); - } + stop_glerror(); @@ -2530,7 +2717,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLVertexBuffer::unbind(); - if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { // Render debugging beacons. gObjectList.renderObjectBeacons(); @@ -2557,13 +2744,283 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLGLState::checkClientArrays(); } -void LLPipeline::renderGeomDeferred() +void LLPipeline::renderGeomDeferred(LLCamera& camera) { - gDeferredDiffuseProgram.bind(); - gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE); - gDeferredDiffuseProgram.unbind(); + LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); + + LLFastTimer t2(LLFastTimer::FTM_POOLS); + + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); + stop_glerror(); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + stop_glerror(); + + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + + U32 cur_type = 0; + + gGL.setColorMask(true, true); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderDeferred(i); + } + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); + + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + gGL.setColorMask(true, false); +} + +void LLPipeline::renderGeomPostDeferred(LLCamera& camera) +{ + LLFastTimer t(LLFastTimer::FTM_POOLS); + U32 cur_type = 0; + + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + calcNearbyLights(camera); + setupHWLights(NULL); + + gGL.setColorMask(true, false); + + pool_set_t::iterator iter1 = mPools.begin(); + BOOL occlude = LLPipeline::sUseOcclusion > 1; + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + gGL.setColorMask(true, false); + } + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) + { + LLFastTimer t(LLFastTimer::FTM_POOLRENDER); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginPostDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderPostDeferred(i); + } + poolp->endPostDeferredPass(i); + LLVertexBuffer::unbind(); + + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); + } + + if (occlude) + { + occlude = FALSE; + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(camera); + } } +void LLPipeline::renderGeomShadow(LLCamera& camera) +{ + U32 cur_type = 0; + + LLGLEnable cull(GL_CULL_FACE); + + LLVertexBuffer::unbind(); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) + { + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + + for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginShadowPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderShadow(i); + } + poolp->endShadowPass(i); + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); +} + + void LLPipeline::addTrianglesDrawn(S32 count) { assertInitialized(); @@ -2621,6 +3078,99 @@ void LLPipeline::renderDebug() } } + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + gGL.color4f(1,1,1,1); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + F32 col[] = + { + 1,1,0, + 0,1,1, + 1,0,1, + 1,1,1, + 1,0,0, + 0,1,0, + 0,0,1, + 0,0,0 + }; + + for (U32 i = 0; i < 8; i++) + { + gGL.color3fv(col+i*3); + + gGL.begin(LLRender::LINES); + + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + + if (i < 4) + { + LLVector3* ext = mShadowExtents[i]; + + LLVector3 box[] = + { + LLVector3(ext[0][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[0][1], ext[0][2]), + LLVector3(ext[1][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[1][1], ext[0][2]), + LLVector3(ext[0][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[0][1], ext[1][2]), + LLVector3(ext[1][0], ext[1][1], ext[1][2]), + LLVector3(ext[0][0], ext[1][1], ext[1][2]), + }; + + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV); + + gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV); + gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV); + + gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV); + gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV); + gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV); + gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV); + } + + gGL.end(); + + for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + part->renderIntersectingBBoxes(&mShadowCamera[i]); + } + } + } + } + } + } + if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) { // Debug composition layers @@ -2653,6 +3203,7 @@ void LLPipeline::renderDebug() gGL.end(); } } + gGL.flush(); } @@ -2735,7 +3286,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); U32 prim_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD; + LLVertexBuffer::MAP_TEXCOORD0; for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i) { @@ -2891,6 +3442,30 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_GRASS: + if (mGrassPool) + { + llassert(0); + llwarns << "Ignoring duplicate grass pool." << llendl; + } + else + { + mGrassPool = (LLRenderPass*) new_poolp; + } + break; + + case LLDrawPool::POOL_FULLBRIGHT: + if (mFullbrightPool) + { + llassert(0); + llwarns << "Ignoring duplicate simple pool." << llendl; + } + else + { + mFullbrightPool = (LLRenderPass*) new_poolp; + } + break; + case LLDrawPool::POOL_INVISIBLE: if (mInvisiblePool) { @@ -3024,6 +3599,16 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mSimplePool = NULL; break; + case LLDrawPool::POOL_GRASS: + llassert(mGrassPool == poolp); + mGrassPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + llassert(mFullbrightPool == poolp); + mFullbrightPool = NULL; + break; + case LLDrawPool::POOL_INVISIBLE: llassert(mInvisiblePool == poolp); mInvisiblePool = NULL; @@ -3117,7 +3702,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) if (for_edit) { - LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f); + LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); LLMatrix4 camera_rot(camera_mat.getMat3()); @@ -3288,6 +3873,10 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { continue; } + if (!sRenderAttachedLights && light && light->isAttachment()) + { + continue; + } new_nearby_lights.insert(Light(drawable, dist, 0.f)); if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) { @@ -4282,11 +4871,11 @@ void LLPipeline::resetVertexBuffers() void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture) { assertInitialized(); + glLoadMatrixd(gGLModelView); gGLLastMatrix = NULL; - glLoadMatrixd(gGLLastModelView); - mSimplePool->renderGroups(type, mask, texture); - gGLLastMatrix = NULL; - glLoadMatrixd(gGLLastModelView); + mSimplePool->pushBatches(type, mask); + glLoadMatrixd(gGLModelView); + gGLLastMatrix = NULL; } void LLPipeline::setUseVBO(BOOL use_vbo) @@ -4334,191 +4923,6 @@ void apply_cube_face_rotation(U32 face) break; } } -void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam) -{ - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - assertInitialized(); - - //render dynamic cube map - U32 type_mask = gPipeline.getRenderTypeMask(); - S32 use_occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - LLPipeline::sSkipUpdate = TRUE; - U32 res = REFLECTION_MAP_RES; - - LLPipeline::sReflectionRender = TRUE; - - gGL.getTexUnit(cube_map->getStage())->bind(cube_map); - gGL.getTexUnit(0)->activate(); - GLint width; - glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width); - if (width != res) - { - cube_map->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - gGL.getTexUnit(cube_map->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - gGL.getTexUnit(cube_map->getStage())->disable(); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - - BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - if (toggle_ui) - { - gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) | - (1 << LLPipeline::RENDER_TYPE_WATER) | - //(1 << LLPipeline::RENDER_TYPE_BUMP) | - (1 << LLPipeline::RENDER_TYPE_ALPHA) | - (1 << LLPipeline::RENDER_TYPE_TREE) | - //(1 << LLPipeline::RENDER_TYPE_PARTICLES) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | - //(1 << LLPipeline::RENDER_TYPE_STARS) | - //(1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_GLOW) | - (1 << LLPipeline::RENDER_TYPE_GRASS) | - (1 << LLPipeline::RENDER_TYPE_VOLUME) | - (1 << LLPipeline::RENDER_TYPE_TERRAIN) | - (1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WL_SKY) | - (1 << LLPipeline::RENDER_TYPE_GROUND); - - LLDrawPoolWater::sSkipScreenCopy = TRUE; - LLPipeline::sSkipUpdate = TRUE; - cube_mask = cube_mask & type_mask; - gPipeline.setRenderTypeMask(cube_mask); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glViewport(0,0,res,res); - - glClearColor(0,0,0,0); - - LLVector3 origin = cube_cam.getOrigin(); - - gPipeline.calcNearbyLights(cube_cam); - - stop_glerror(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, mCubeDepth); - stop_glerror(); - - for (S32 i = 0; i < 6; i++) - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - gl_cube_face[i], cube_map->getGLName(), 0); - validate_framebuffer_object(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.f, 1.f, 0.1f, 1024.f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - apply_cube_face_rotation(i); - - glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]); - cube_cam.setOrigin(origin); - LLViewerCamera::updateFrustumPlanes(cube_cam); - cube_cam.setOrigin(LLViewerCamera::getInstance()->getOrigin()); - static LLCullResult result; - gPipeline.updateCull(cube_cam, result); - gPipeline.stateSort(cube_cam, result); - - glClearColor(0,0,0,0); - gGL.setColorMask(true, true); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - gGL.setColorMask(true, false); - stop_glerror(); - gPipeline.renderGeom(cube_cam); - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - - cube_cam.setOrigin(origin); - gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - gViewerWindow->setupViewport(); - - gPipeline.setRenderTypeMask(type_mask); - LLPipeline::sUseOcclusion = use_occlusion; - LLPipeline::sSkipUpdate = FALSE; - - if (toggle_ui) - { - gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - LLDrawPoolWater::sSkipScreenCopy = FALSE; - LLPipeline::sSkipUpdate = FALSE; - LLPipeline::sReflectionRender = FALSE; - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); -} - -//send cube map vertices and texture coordinates -void render_cube_map() -{ - U16 idx[36]; - - idx[0] = 1; idx[1] = 0; idx[2] = 2; //front - idx[3] = 3; idx[4] = 2; idx[5] = 0; - - idx[6] = 4; idx[7] = 5; idx[8] = 1; //top - idx[9] = 0; idx[10] = 1; idx[11] = 5; - - idx[12] = 5; idx[13] = 4; idx[14] = 6; //back - idx[15] = 7; idx[16] = 6; idx[17] = 4; - - idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom - idx[21] = 2; idx[22] = 3; idx[23] = 7; - - idx[24] = 0; idx[25] = 5; idx[26] = 3; //left - idx[27] = 6; idx[28] = 3; idx[29] = 5; - - idx[30] = 4; idx[31] = 1; idx[32] = 7; //right - idx[33] = 2; idx[34] = 7; idx[35] = 1; - - LLVector3 vert[8]; - LLVector3 r = LLVector3(1,1,1); - - vert[0] = r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front - vert[1] = r.scaledVec(LLVector3(1,1,1)); // 1 - right top front - vert[2] = r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front - vert[3] = r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front - - vert[4] = r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back - vert[5] = r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back - vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back - vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(3, GL_FLOAT, 0, vert); - glVertexPointer(3, GL_FLOAT, 0, vert); - - glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (GLushort*) idx); - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} void validate_framebuffer_object() { @@ -4547,132 +4951,12 @@ void validate_framebuffer_object() } } -void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out) -{ - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - assertInitialized(); - - U32 res = (U32) gSavedSettings.getS32("RenderReflectionRes"); - enableLightsFullbright(LLColor4::white); - LLGLDepthTest depth(GL_FALSE); - gGL.setColorMask(true, true); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - cube_out->enableTexture(0); - gGL.getTexUnit(cube_out->getStage())->bind(cube_out); - gGL.getTexUnit(0)->activate(); - GLint width; - glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width); - if (width != res) - { - cube_out->setReflection(); - - for (U32 i = 0; i < 6; i++) - { - glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL); - } - } - gGL.getTexUnit(cube_out->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - gGL.getTexUnit(0)->activate(); - glViewport(0, 0, res, res); - LLGLEnable blend(GL_BLEND); - - S32 kernel = 2; - F32 step = 90.f/res; - F32 alpha = 1.f / ((kernel*2)+1); - - gGL.color4f(alpha,alpha,alpha,alpha*1.25f); - - LLVector3 axis[] = - { - LLVector3(1,0,0), - LLVector3(0,1,0), - LLVector3(0,0,1) - }; - - stop_glerror(); - glViewport(0,0,res, res); - gGL.setSceneBlendType(LLRender::BT_ADD); - cube_in->enableTexture(0); - //3-axis blur - for (U32 j = 0; j < 3; j++) - { - stop_glerror(); - - if (j == 0) - { - gGL.getTexUnit(cube_in->getStage())->bind(cube_in); - } - else - { - gGL.getTexUnit(cube_in->getStage())->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j-1]); - } - gGL.getTexUnit(0)->activate(); - - stop_glerror(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mBlurCubeBuffer[j]); - stop_glerror(); - - for (U32 i = 0; i < 6; i++) - { - stop_glerror(); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, - gl_cube_face[i], - j < 2 ? mBlurCubeTexture[j] : cube_out->getGLName(), 0); - validate_framebuffer_object(); - gGL.setColorMask(true, true); - glClear(GL_COLOR_BUFFER_BIT); - glLoadIdentity(); - apply_cube_face_rotation(i); - for (S32 x = -kernel; x <= kernel; ++x) - { - glPushMatrix(); - glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]); - render_cube_map(); - glPopMatrix(); - } - stop_glerror(); - } - } - - stop_glerror(); - - gGL.getTexUnit(cube_in->getStage())->unbind(LLTexUnit::TT_CUBE_MAP); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - gGL.setColorMask(true, false); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - gGL.getTexUnit(cube_in->getStage())->disable(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gViewerWindow->setupViewport(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); -} - void LLPipeline::bindScreenToTexture() { } -void LLPipeline::renderBloom(BOOL for_snapshot) +void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) { if (!(gPipeline.canUseVertexShaders() && sRenderGlow)) @@ -4694,8 +4978,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot) U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); LLVector2 tc1(0,0); - LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); + LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth()*2, + (F32) gViewerWindow->getWindowDisplayHeight()*2); if (res_mod > 1) { @@ -4732,9 +5016,22 @@ void LLPipeline::renderBloom(BOOL for_snapshot) //glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF); //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); //LLGLDisable blend(GL_BLEND); + + // If the snapshot is constructed from tiles, calculate which + // tile we're in. + const S32 num_horizontal_tiles = llceil(zoom_factor); + const LLVector2 tile(subfield % num_horizontal_tiles, + (S32)(subfield / num_horizontal_tiles)); + llassert(zoom_factor > 0.0); // Non-zero, non-negative. + const F32 tile_size = 1.0/zoom_factor; + + tc1 = tile*tile_size; // Top left texture coordinates + tc2 = (tile+LLVector2(1,1))*tile_size; // Bottom right texture coordinates + LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ADD); - tc2.setVec(1,1); + + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.color4f(1,1,1,1); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); @@ -4748,6 +5045,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); gGL.vertex2f(1,1); + gGL.end(); gGL.flush(); @@ -4771,7 +5069,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } gGlowExtractProgram.bind(); - F32 minLum = llclamp(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f, 1.0f); + F32 minLum = llmax(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f); F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); @@ -4798,13 +5096,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.vertex2f(-1,-1); gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); + gGL.vertex2f(-1,3); gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); + gGL.vertex2f(3,-1); - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); gGL.end(); gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); @@ -4813,7 +5109,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } tc1.setVec(0,0); - tc2.setVec(1,1); + tc2.setVec(2,2); @@ -4867,13 +5163,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gGL.vertex2f(-1,-1); gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); + gGL.vertex2f(-1,3); gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); + gGL.vertex2f(3,-1); - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); gGL.end(); mGlow[i%2].flush(); @@ -4889,81 +5183,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot) gViewerWindow->setupViewport(); - /*mGlow[1].bindTexture(); - { - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - LLGLDisable blend(GL_BLEND); - - gGL.begin(LLVertexBuffer::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); - - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); - gGL.end(); - - gGL.flush(); - } - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW)) - { - tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); - - if (res_mod > 1) - { - tc2 /= (F32) res_mod; - } - - LLGLEnable blend(GL_BLEND); - gGL.blendFunc(GL_ONE, GL_ONE); - - gGL.getTexUnit(0)->disable(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); - mScreen.bindTexture(); - - gGL.begin(LLVertexBuffer::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); - gGL.vertex2f(-1,-1); - - gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); - gGL.vertex2f(-1,1); - - gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); - gGL.vertex2f(1,-1); - - gGL.texCoord2f(tc2.mV[0], tc2.mV[1]); - gGL.vertex2f(1,1); - gGL.end(); - - gGL.flush(); - - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - }*/ gGL.flush(); { LLVertexBuffer::unbind(); - F32 uv0[] = - { - tc1.mV[0], tc1.mV[1], - tc1.mV[0], tc2.mV[1], - tc2.mV[0], tc1.mV[1], - tc2.mV[0], tc2.mV[1] - }; + tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), (F32) gViewerWindow->getWindowDisplayHeight()); @@ -4973,55 +5198,56 @@ void LLPipeline::renderBloom(BOOL for_snapshot) tc2 /= (F32) res_mod; } - F32 uv1[] = - { - tc1.mV[0], tc1.mV[1], - tc1.mV[0], tc2.mV[1], - tc2.mV[0], tc1.mV[1], - tc2.mV[0], tc2.mV[1] - }; + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1; + LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0); + buff->allocateBuffer(3,0,TRUE); - F32 v[] = - { - -1,-1, - -1,1, - 1,-1, - 1,1 - }; + LLStrider<LLVector3> v; + LLStrider<LLVector2> uv1; + LLStrider<LLVector2> uv2; + + buff->getVertexStrider(v); + buff->getTexCoord0Strider(uv1); + buff->getTexCoord1Strider(uv2); + uv1[0] = LLVector2(0, 0); + uv1[1] = LLVector2(0, 2); + uv1[2] = LLVector2(2, 0); + + uv2[0] = LLVector2(0, 0); + uv2[1] = LLVector2(0, tc2.mV[1]*2.f); + uv2[2] = LLVector2(tc2.mV[0]*2.f, 0); + + v[0] = LLVector3(-1,-1,0); + v[1] = LLVector3(-1,3,0); + v[2] = LLVector3(3,-1,0); + + buff->setBuffer(0); + LLGLDisable blend(GL_BLEND); //tex unit 0 gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); gGL.getTexUnit(0)->bind(&mGlow[1]); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, uv0); gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE); //tex unit 1 gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, uv1); - - glVertexPointer(2, GL_FLOAT, 0, v); - gGL.getTexUnit(1)->bind(&mScreen); gGL.getTexUnit(1)->activate(); LLGLEnable multisample(GL_MULTISAMPLE_ARB); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + buff->setBuffer(mask); + buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); gGL.getTexUnit(1)->disable(); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } @@ -5038,6 +5264,515 @@ void LLPipeline::renderBloom(BOOL for_snapshot) } +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) +{ + shader.bind(); + S32 channel = 0; + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(0,channel); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(1, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(2, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredScreen.bindTexture(3, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + } + + stop_glerror(); + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[light_index].bindTexture(0, channel); + } + + stop_glerror(); + + for (U32 i = 0; i < 4; i++) + { + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i); + stop_glerror(); + if (channel > -1) + { + stop_glerror(); + gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + stop_glerror(); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + stop_glerror(); + } + } + + stop_glerror(); + + F32 mat[64]; + for (U32 i = 0; i < 16; i++) + { + mat[i] = mSunShadowMatrix[0].m[i]; + mat[i+16] = mSunShadowMatrix[1].m[i]; + mat[i+32] = mSunShadowMatrix[2].m[i]; + mat[i+48] = mSunShadowMatrix[3].m[i]; + } + + shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat); + + stop_glerror(); + + channel = shader.enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->enable(channel); + cube_map->bind(); + F64* m = gGLModelView; + + + F32 mat[] = { m[0], m[1], m[2], + m[4], m[5], m[6], + m[8], m[9], m[10] }; + + shader.uniform3fv("env_mat[0]", 3, mat); + shader.uniform3fv("env_mat", 3, mat); + } + } + + shader.uniform4fv("shadow_clip", 1, mSunClipPlanes.mV); + shader.uniform1f("sun_wash", gSavedSettings.getF32("RenderDeferredSunWash")); + shader.uniform1f("shadow_noise", gSavedSettings.getF32("RenderShadowNoise")); + shader.uniform1f("blur_size", gSavedSettings.getF32("RenderShadowBlurSize")); + + shader.uniform1f("ssao_radius", gSavedSettings.getF32("RenderSSAOScale")); + shader.uniform1f("ssao_max_radius", gSavedSettings.getU32("RenderSSAOMaxScale")); + + F32 ssao_factor = gSavedSettings.getF32("RenderSSAOFactor"); + shader.uniform1f("ssao_factor", ssao_factor); + shader.uniform1f("ssao_factor_inv", 1.0/ssao_factor); + + LLVector3 ssao_effect = gSavedSettings.getVector3("RenderSSAOEffect"); + F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; + F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; + // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by + // value factor, and scales remainder by saturation factor + F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, + matrix_nondiag, matrix_diag, matrix_nondiag, + matrix_nondiag, matrix_nondiag, matrix_diag}; + shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat); + + shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); + shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); + shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); +} + +void LLPipeline::renderDeferredLighting() +{ + if (!sCull) + { + return; + } + + LLGLEnable multisample(GL_MULTISAMPLE_ARB); + + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + //ati doesn't seem to love actually using the stencil buffer on FBO's + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gGL.setColorMask(true, true); + + mDeferredLight[0].bindTarget(); + + //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + //draw a cube around every light + LLVertexBuffer::unbind(); + + glBlendFunc(GL_ONE, GL_ONE); + LLGLEnable cull(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + + glh::matrix4f mat = glh_copy_matrix(gGLModelView); + + F32 vert[] = + { + -1,1, + -1,-3, + 3,1, + }; + + bindDeferredShader(gDeferredSunProgram); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv("offset", slice, offset); + gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + + setupHWLights(NULL); //to set mSunDir; + + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + LLVector4 dir(mSunDir, 0.f); + + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); + glColor3f(1,1,1); + + glVertexPointer(2, GL_FLOAT, 0, vert); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + + mDeferredLight[0].flush(); + + //blur lightmap + mDeferredLight[1].bindTarget(); + + //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + bindDeferredShader(gDeferredBlurLightProgram); + + LLVector3 gauss[32]; // xweight, yweight, offset + + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = -(kern_length/2.0f) + 0.5f; + + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go.mV[0]); + gauss[i].mV[1] = llgaussian(x, go.mV[1]); + gauss[i].mV[2] = x; + x += 1.f; + } + /* swap the x=0 position to the start of gauss[] so we can + treat it specially as an optimization. */ + LLVector3 swap; + swap = gauss[kern_length/2]; + gauss[kern_length/2] = gauss[0]; + gauss[0] = swap; + llassert(gauss[0].mV[2] == 0.0f); + + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); + + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + stop_glerror(); + } + mDeferredLight[0].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); + + stop_glerror(); + glPopMatrix(); + stop_glerror(); + glMatrixMode(GL_MODELVIEW); + stop_glerror(); + glPopMatrix(); + stop_glerror(); + + //copy depth and stencil from deferred screen + //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), + // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + + mScreen.bindTarget(); + mScreen.clear(GL_COLOR_BUFFER_BIT); + + bindDeferredShader(gDeferredSoftenProgram); + { + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glVertexPointer(2, GL_FLOAT, 0, vert); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + + unbindDeferredShader(gDeferredSoftenProgram); + + bindDeferredShader(gDeferredLightProgram); + + std::list<LLVector4> fullscreen_lights; + std::list<LLVector4> light_colors; + + F32 v[24]; + glVertexPointer(3, GL_FLOAT, 0, v); + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + { + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + if (!volume) + { + continue; + } + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) + { + continue; + } + + sVisibleLightCount++; + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + //vertex positions are encoded so the 3 bits of their vertex index + //correspond to their axis facing, with bit position 3,2,1 matching + //axis facing x,y,z, bit set meaning positive facing, bit clear + //meaning negative facing + v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 + v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 + v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 + v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 + + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 + v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 + v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 + v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 + + if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f || + LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f) + { //draw box if camera is outside box + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center)); + } + else + { + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); + light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); + } + } + } + + unbindDeferredShader(gDeferredLightProgram); + + if (!fullscreen_lights.empty()) + { + bindDeferredShader(gDeferredMultiLightProgram); + LLGLDepthTest depth(GL_FALSE); + + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + U32 count = 0; + + LLVector4 light[16]; + LLVector4 col[16]; + + glVertexPointer(2, GL_FLOAT, 0, vert); + + while (!fullscreen_lights.empty()) + { + light[count] = fullscreen_lights.front(); + fullscreen_lights.pop_front(); + col[count] = light_colors.front(); + light_colors.pop_front(); + + count++; + if (count == 16 || fullscreen_lights.empty()) + { + gDeferredMultiLightProgram.uniform1i("light_count", count); + gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); + gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); + gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); + count = 0; + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + } + } + + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + unbindDeferredShader(gDeferredMultiLightProgram); + } + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + { //render non-deferred geometry + LLGLDisable blend(GL_BLEND); + LLGLDisable stencil(GL_STENCIL_TEST); + + U32 render_mask = mRenderTypeMask; + mRenderTypeMask = mRenderTypeMask & + ((1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + (1 << LLPipeline::RENDER_TYPE_WL_SKY) | + (1 << LLPipeline::RENDER_TYPE_ALPHA) | + (1 << LLPipeline::RENDER_TYPE_AVATAR) | + (1 << LLPipeline::RENDER_TYPE_WATER) | + (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1 << LLPipeline::RENDER_TYPE_VOLUME) | + (1 << LLPipeline::RENDER_TYPE_GLOW) | + (1 << LLPipeline::RENDER_TYPE_BUMP)); + + renderGeomPostDeferred(*LLViewerCamera::getInstance()); + mRenderTypeMask = render_mask; + } + + mScreen.flush(); + +} + +void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) +{ + stop_glerror(); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + for (U32 i = 0; i < 4; i++) + { + if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + } + } + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + + S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->disable(); + } + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->activate(); + shader.unbind(); +} + inline float sgn(float a) { if (a > 0.0F) return (1.0F); @@ -5049,6 +5784,16 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate) { + LLVOAvatar* agent = gAgent.getAvatarObject(); + if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) + { + agent = NULL; + } + + if (agent) + { + agent->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON); + } LLVertexBuffer::unbind(); LLGLState::checkStates(); @@ -5060,6 +5805,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPipeline::sReflectionRender = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = llmin(occlusion, 1); + U32 type_mask = gPipeline.mRenderTypeMask; glh::matrix4f projection = glh_get_current_projection(); @@ -5127,15 +5873,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) //initial sky pass (no user clip plane) { //mask out everything but the sky U32 tmp = mRenderTypeMask; - mRenderTypeMask &= ((1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | (1 << LLPipeline::RENDER_TYPE_WL_SKY)); - static LLCullResult result; updateCull(camera, result); stateSort(camera, result); + mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + (1 << LLPipeline::RENDER_TYPE_WL_SKY)); renderGeom(camera, TRUE); - mRenderTypeMask = tmp; } @@ -5227,6 +5973,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; LLRenderTarget::unbindTarget(); + LLPipeline::sReflectionRender = FALSE; if (!LLRenderTarget::sUseFBO) @@ -5245,9 +5992,424 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); + + if (agent) + { + agent->updateAttachmentVisibility(gAgent.getCameraMode()); + } } } +glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) +{ + glh::matrix4f ret; + + LLVector3 dirN; + LLVector3 upN; + LLVector3 lftN; + + lftN = dir % up; + lftN.normVec(); + + upN = lftN % dir; + upN.normVec(); + + dirN = dir; + dirN.normVec(); + + + ret.m[ 0] = lftN[0]; + ret.m[ 1] = upN[0]; + ret.m[ 2] = -dirN[0]; + ret.m[ 3] = 0.f; + + ret.m[ 4] = lftN[1]; + ret.m[ 5] = upN[1]; + ret.m[ 6] = -dirN[1]; + ret.m[ 7] = 0.f; + + ret.m[ 8] = lftN[2]; + ret.m[ 9] = upN[2]; + ret.m[10] = -dirN[2]; + ret.m[11] = 0.f; + + ret.m[12] = -(lftN*pos); + ret.m[13] = -(upN*pos); + ret.m[14] = dirN*pos; + ret.m[15] = 1.f; + + return ret; +} + +glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) +{ + glh::matrix4f ret; + ret.m[ 0] = 2/(max[0]-min[0]); + ret.m[ 4] = 0; + ret.m[ 8] = 0; + ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); + + ret.m[ 1] = 0; + ret.m[ 5] = 2/(max[1]-min[1]); + ret.m[ 9] = 0; + ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); + + ret.m[ 2] = 0; + ret.m[ 6] = 0; + ret.m[10] = 2/(max[2]-min[2]); + ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); + + ret.m[ 3] = 0; + ret.m[ 7] = 0; + ret.m[11] = 0; + ret.m[15] = 1; + + return ret; +} + +void LLPipeline::generateSunShadow(LLCamera& camera) +{ + + if (!sRenderDeferred) + { + return; + } + + //temporary hack to disable shadows but keep local lights + static BOOL clear = TRUE; + BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); + if (!gen_shadow) + { + if (clear) + { + clear = FALSE; + for (U32 i = 0; i < 4; i++) + { + mSunShadow[i].bindTarget(); + mSunShadow[i].clear(); + mSunShadow[i].flush(); + } + } + return; + } + clear = TRUE; + + gGL.setColorMask(false, false); + + //get sun view matrix + + F32 range = 128.f; + + //store current projection/modelview matrix + glh::matrix4f saved_proj = glh_get_current_projection(); + glh::matrix4f saved_view = glh_get_current_modelview(); + glh::matrix4f inv_view = saved_view.inverse(); + + glh::matrix4f view[4]; + glh::matrix4f proj[4]; + LLVector3 up; + + //clip contains parallel split distances for 3 splits + LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes"); + + //far clip on last split is minimum of camera view distance and 128 + mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]); + + const LLPickInfo& pick_info = gViewerWindow->getLastPick(); + + if (!pick_info.mPosGlobal.isExactlyZero()) + { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object + F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec(); + mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]); + } + + // convenience array of 4 near clip plane distances + F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; + + //currently used for amount to extrude frusta corners for constructing shadow frusta + LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist"); + F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; + + for (S32 j = 0; j < 4; j++) + { + //restore render matrices + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); + + //get center of far clip plane (for point of interest later) + LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range; + + LLVector3 eye = camera.getOrigin(); + + //camera used for shadow cull/render + LLCamera shadow_cam; + + // perspective shadow map + glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space) + glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space) + + LLVector3 lightDir = -mSunDir; + glh::vec3f light_dir(lightDir.mV); + + //create light space camera matrix + LLVector3 at; + F32 dl = camera.getLeftAxis() * lightDir; + F32 du = camera.getUpAxis() * lightDir; + + //choose an at axis such that up will be most aligned with lightDir + if (dl*dl < du*du) + { + at = lightDir%camera.getLeftAxis(); + } + else + { + at = lightDir%camera.getUpAxis(); + } + + if (at * camera.getAtAxis() < 0) + { + at = -at; + } + + LLVector3 left = lightDir%at; + up = left%lightDir; + up.normVec(); + + //create world space camera frustum for this split + shadow_cam = camera; + shadow_cam.setFar(16.f); + + LLViewerCamera::updateFrustumPlanes(shadow_cam); + + LLVector3* frust = shadow_cam.mAgentFrustum; + + LLVector3 pn = shadow_cam.getAtAxis(); + + LLVector3 frust_center; + + LLVector3 min, max; + + //construct 8 corners of split frustum section + for (U32 i = 0; i < 4; i++) + { + LLVector3 delta = frust[i+4]-eye; + delta.normVec(); + F32 dp = delta*pn; + frust[i] = eye + (delta*dist[j])/dp; + frust[i+4] = eye + (delta*dist[j+1])/dp; + frust_center += frust[i] + frust[i+4]; + } + + //get frustum center + frust_center /= 8.f; + + shadow_cam.calcAgentFrustumPlanes(frust); + + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowCamera[j] = shadow_cam; + } + + if (gPipeline.getVisibleExtents(shadow_cam, min, max)) + { + //no possible shadow receivers + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowExtents[j][0] = LLVector3(); + mShadowExtents[j][1] = LLVector3(); + mShadowCamera[j+4] = shadow_cam; + } + + continue; + } + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowExtents[j][0] = min; + mShadowExtents[j][1] = max; + } + + view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up); + F32 shadow_dist = nearDist[j]; + + for (U32 i = 0; i < 8; i++) + { + //points in worldspace (wp) and light camera space (p) + //that must be included in shadow generation + wp[i] = glh::vec3f(frust[i].mV); + wp[i+8] = wp[i] - light_dir*shadow_dist; + view[j].mult_matrix_vec(wp[i], p[i]); + view[j].mult_matrix_vec(wp[i+8], p[i+8]); + } + + min = LLVector3(p[0].v); + max = LLVector3(p[0].v); + + LLVector3 fmin = min; + LLVector3 fmax = max; + + for (U32 i = 1; i < 16; i++) + { //find camera space AABB of frustum in light camera space + update_min_max(min, max, LLVector3(p[i].v)); + if (i < 8) + { + update_min_max(fmin, fmax, LLVector3(p[i].v)); + } + } + + //generate perspective matrix that contains frustum + //proj[j] = matrix_perspective(min, max); + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + + shadow_cam.setFar(128.f); + shadow_cam.setOriginAndLookAt(eye, up, center); + + glh_set_current_modelview(view[j]); + glh_set_current_projection(proj[j]); + + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + + proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0], + fmin.mV[1], fmax.mV[1], + -fmax.mV[2], -fmin.mV[2]); + + //translate and scale to from [-1, 1] to [0, 1] + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); + + glh_set_current_modelview(view[j]); + glh_set_current_projection(proj[j]); + + mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; + + U32 type_mask = mRenderTypeMask; + mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_ALPHA) | + (1<<LLPipeline::RENDER_TYPE_GRASS) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | + (1<<LLPipeline::RENDER_TYPE_BUMP) | + (1<<LLPipeline::RENDER_TYPE_VOLUME) | + (1<<LLPipeline::RENDER_TYPE_AVATAR) | + (1<<LLPipeline::RENDER_TYPE_TREE) | + (1<<LLPipeline::RENDER_TYPE_TERRAIN) | + 0); + + //clip out geometry on the same side of water as the camera + static LLCullResult result; + S32 occlude = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 1; + LLPipeline::sShadowRender = TRUE; + //hack to prevent LOD updates from using sun camera origin + shadow_cam.setOrigin(camera.getOrigin()); + updateCull(shadow_cam, result); + stateSort(shadow_cam, result); + + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + mShadowCamera[j+4] = shadow_cam; + } + + LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + + stop_glerror(); + + mSunShadow[j].bindTarget(); + mSunShadow[j].getViewport(gGLViewport); + + { + LLGLDepthTest depth(GL_TRUE); + mSunShadow[j].clear(); + } + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; + LLGLEnable cull(GL_CULL_FACE); + + //generate sun shadow map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj[j].m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view[j].m); + + stop_glerror(); + gGLLastMatrix = NULL; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + glColor4f(1,1,1,1); + + glCullFace(GL_FRONT); + + stop_glerror(); + + gGL.setColorMask(false, false); + + gDeferredShadowProgram.bind(); + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->disable(); + for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) + { + renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + } + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLGLEnable test(GL_ALPHA_TEST); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); + glColor4f(1,1,1,1); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + gDeferredShadowProgram.unbind(); + + renderGeomShadow(shadow_cam); + + gGL.setColorMask(true, true); + + glCullFace(GL_BACK); + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; + mRenderTypeMask = type_mask; + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + mSunShadow[j].flush(); + } + + if (!gSavedSettings.getBOOL("CameraOffset")) + { + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); + } + else + { + glh_set_current_modelview(view[1]); + glh_set_current_projection(proj[1]); + glLoadMatrixf(view[1].m); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj[1].m); + glMatrixMode(GL_MODELVIEW); + } + gGL.setColorMask(true, false); +} + void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) { for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) @@ -5265,6 +6427,10 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu void LLPipeline::generateImpostor(LLVOAvatar* avatar) { + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + static LLCullResult result; result.clear(); grabReferences(result); @@ -5290,6 +6456,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) (1<<LLPipeline::RENDER_TYPE_BUMP) | (1<<LLPipeline::RENDER_TYPE_GRASS) | (1<<LLPipeline::RENDER_TYPE_SIMPLE) | + (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) | (1<<LLPipeline::RENDER_TYPE_ALPHA) | (1<<LLPipeline::RENDER_TYPE_INVISIBLE); } @@ -5300,7 +6467,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) S32 occlusion = sUseOcclusion; sUseOcclusion = 0; - sReflectionRender = TRUE; + sReflectionRender = sRenderDeferred ? FALSE : TRUE; sImpostorRender = TRUE; markVisible(avatar->mDrawable, *LLViewerCamera::getInstance()); @@ -5377,10 +6544,17 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE); + if (LLPipeline::sRenderDeferred) + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE); + addDeferredAttachments(avatar->mImpostor); + } + else + { + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE); + } gGL.getTexUnit(0)->bind(&avatar->mImpostor); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -5388,8 +6562,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, resX, resY); avatar->mImpostor.bindTarget(); - avatar->mImpostor.getViewport(gGLViewport); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + avatar->mImpostor.clear(); } LLGLEnable stencil(GL_STENCIL_TEST); @@ -5397,11 +6570,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - renderGeom(camera); + if (LLPipeline::sRenderDeferred) + { + stop_glerror(); + renderGeomDeferred(camera); + } + else + { + renderGeom(camera); + } glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFFFFFF); + if (!sRenderDeferred || muted) { LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f; LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f; @@ -5432,7 +6614,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.end(); gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -5454,6 +6635,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) avatar->mNeedsImpostorUpdate = FALSE; avatar->cacheImpostorValues(); + + LLVertexBuffer::unbind(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); } BOOL LLPipeline::hasRenderBatches(const U32 type) const diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5ab3831753..e8673c7d4c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -57,6 +57,7 @@ class LLRenderFunc; class LLCubeMap; class LLCullResult; class LLVOAvatar; +class LLGLSLShader; typedef enum e_avatar_skinning_method { @@ -75,6 +76,7 @@ glh::matrix4f glh_get_current_projection(); void glh_set_current_projection(glh::matrix4f& mat); glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar); glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar); +glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up); class LLPipeline { @@ -88,14 +90,13 @@ public: void resizeScreenTexture(); void releaseGLBuffers(); void createGLBuffers(); + void allocateScreenBuffer(U32 resX, U32 resY); void resetVertexBuffers(LLDrawable* drawable); void setUseVBO(BOOL use_vbo); void generateImpostor(LLVOAvatar* avatar); - void generateReflectionMap(LLCubeMap* cube_map, LLCamera& camera); - void blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out); void bindScreenToTexture(); - void renderBloom(BOOL for_snapshot); + void renderBloom(BOOL for_snapshot, F32 zoom_factor = 1.f, int subfield = 0); void init(); void cleanup(); @@ -176,7 +177,11 @@ public: void updateMoveNormalAsync(LLDrawable* drawablep); void updateMovedList(LLDrawable::drawable_vector_t& move_list); void updateMove(); + BOOL visibleObjectsInFrustum(LLCamera& camera); + BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane + void createObjects(F32 max_dtime); + void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); //calculate pixel area of given box from vantage point of given camera @@ -195,9 +200,15 @@ public: void grabReferences(LLCullResult& result); void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE); - void renderGeomDeferred(); - + void renderGeomDeferred(LLCamera& camera); + void renderGeomPostDeferred(LLCamera& camera); + void renderGeomShadow(LLCamera& camera); + void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0); + void unbindDeferredShader(LLGLSLShader& shader); + void renderDeferredLighting(); + void generateWaterReflection(LLCamera& camera); + void generateSunShadow(LLCamera& camera); void renderHighlights(); void renderDebug(); @@ -230,7 +241,7 @@ public: LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); - + void addTrianglesDrawn(S32 count); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; } BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } @@ -276,6 +287,8 @@ public: static void toggleRenderHighlights(void* data); static BOOL getRenderHighlights(void* data); + static void updateRenderDeferred(); + private: void unloadShaders(); void addToQuickLookup( LLDrawPool* new_poolp ); @@ -295,6 +308,8 @@ public: RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, @@ -306,7 +321,6 @@ public: // Following are object types (only used in drawable mRenderType) RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES, RENDER_TYPE_VOLUME, - RENDER_TYPE_GRASS, RENDER_TYPE_PARTICLES, RENDER_TYPE_CLOUDS, }; @@ -326,24 +340,26 @@ public: enum LLRenderDebugMask { - RENDER_DEBUG_COMPOSITION = 0x000020, - RENDER_DEBUG_VERIFY = 0x000080, - RENDER_DEBUG_BBOXES = 0x000200, - RENDER_DEBUG_OCTREE = 0x000400, - RENDER_DEBUG_PICKING = 0x000800, - RENDER_DEBUG_OCCLUSION = 0x001000, - RENDER_DEBUG_POINTS = 0x002000, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x004000, - RENDER_DEBUG_TEXTURE_AREA = 0x008000, - RENDER_DEBUG_FACE_AREA = 0x010000, - RENDER_DEBUG_PARTICLES = 0x020000, - RENDER_DEBUG_GLOW = 0x040000, - RENDER_DEBUG_TEXTURE_ANIM = 0x080000, - RENDER_DEBUG_LIGHTS = 0x100000, - RENDER_DEBUG_BATCH_SIZE = 0x200000, - RENDER_DEBUG_RAYCAST = 0x400000, - RENDER_DEBUG_SHAME = 0x800000, - RENDER_DEBUG_SCULPTED = 0x1000000 + RENDER_DEBUG_COMPOSITION = 0x0000001, + RENDER_DEBUG_VERIFY = 0x0000002, + RENDER_DEBUG_BBOXES = 0x0000004, + RENDER_DEBUG_OCTREE = 0x0000008, + RENDER_DEBUG_PICKING = 0x0000010, + RENDER_DEBUG_OCCLUSION = 0x0000020, + RENDER_DEBUG_POINTS = 0x0000040, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x0000080, + RENDER_DEBUG_TEXTURE_AREA = 0x0000100, + RENDER_DEBUG_FACE_AREA = 0x0000200, + RENDER_DEBUG_PARTICLES = 0x0000400, + RENDER_DEBUG_GLOW = 0x0000800, + RENDER_DEBUG_TEXTURE_ANIM = 0x0001000, + RENDER_DEBUG_LIGHTS = 0x0002000, + RENDER_DEBUG_BATCH_SIZE = 0x0004000, + RENDER_DEBUG_ALPHA_BINS = 0x0008000, + RENDER_DEBUG_RAYCAST = 0x0010000, + RENDER_DEBUG_SHAME = 0x0020000, + RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000, + RENDER_DEBUG_SCULPTED = 0x0080000, }; public: @@ -376,11 +392,13 @@ public: static BOOL sShowHUDAttachments; static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write + static BOOL sDelayVBUpdate; static BOOL sFastAlpha; static BOOL sDisableShaders; // if TRUE, rendering will be done without shaders static BOOL sRenderBump; static BOOL sUseFBO; static BOOL sUseFarClip; + static BOOL sShadowRender; static BOOL sSkipUpdate; //skip lod updates static BOOL sWaterReflections; static BOOL sDynamicLOD; @@ -393,10 +411,22 @@ public: static BOOL sRenderFrameTest; static BOOL sRenderAttachedLights; static BOOL sRenderAttachedParticles; - + static BOOL sRenderDeferred; + static S32 sVisibleLightCount; + //screen texture LLRenderTarget mScreen; - + LLRenderTarget mDeferredScreen; + LLRenderTarget mDeferredLight[2]; + LLMultisampleBuffer mSampleBuffer; + + //sun shadow map + LLRenderTarget mSunShadow[4]; + LLCamera mShadowCamera[8]; + LLVector3 mShadowExtents[4][2]; + glh::matrix4f mSunShadowMatrix[4]; + LLVector4 mSunClipPlanes; + LLVector2 mScreenScale; //water reflection texture @@ -408,20 +438,9 @@ public: //texture for making the glow LLRenderTarget mGlow[3]; - //dynamic cube map scratch space - LLPointer<LLCubeMap> mCubeBuffer; - - //cube map anti-aliasing buffers - GLuint mBlurCubeBuffer[3]; - GLuint mBlurCubeTexture[3]; + //noise map + U32 mNoiseMap; - //frambuffer object for rendering dynamic cube maps - GLuint mCubeFrameBuffer; - - //depth buffer object for rendering dynamic cube maps - GLuint mCubeDepth; - - LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -481,6 +500,7 @@ protected: // LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority + LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mActiveQ; @@ -525,6 +545,8 @@ protected: LLDrawPool* mWaterPool; LLDrawPool* mGroundPool; LLRenderPass* mSimplePool; + LLRenderPass* mGrassPool; + LLRenderPass* mFullbrightPool; LLDrawPool* mInvisiblePool; LLDrawPool* mGlowPool; LLDrawPool* mBumpPool; diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index f249f53105..249787ad8d 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -260,6 +260,12 @@ class WindowsManifest(ViewerManifest): "../win_updater/relwithdebinfo/windows-updater.exe"), dst="updater.exe") + # For google-perftools tcmalloc allocator. + #if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""): + # self.path("libtcmalloc_minimal.dll") + # self.end_prefix() + + def nsi_file_commands(self, install=True): def wpath(path): if path.endswith('/') or path.endswith(os.path.sep): |