summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorGraham Linden <graham@lindenlab.com>2018-08-16 00:31:39 +0100
committerGraham Linden <graham@lindenlab.com>2018-08-16 00:31:39 +0100
commit3237923e10a34d14ac4aac17400811cb1c7c3bdf (patch)
tree94815c2fd75507f0cee47562af427a4426e86e69 /indra/newview
parent3983f5b1e2d79602a7d685633271d824a906ed2f (diff)
MAINT-3699 new shaders supporting alpha blend/mask rigged content.
Make shader loading debug logging of uniforms use ShaderUniform to make supression simpler.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl65
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl82
-rw-r--r--indra/newview/lldrawpoolavatar.cpp236
-rw-r--r--indra/newview/lldrawpoolavatar.h212
-rw-r--r--indra/newview/llviewershadermgr.cpp52
-rw-r--r--indra/newview/llviewershadermgr.h4
10 files changed, 799 insertions, 126 deletions
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
new file mode 100644
index 0000000000..a08550d69c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
@@ -0,0 +1,64 @@
+/**
+ * @file attachmentAlphaMaskShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 post_pos;
+VARYING vec2 vary_texcoord0;
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+
+void main()
+{
+ float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+ if (alpha < 0.05) // treat as totally transparent
+ {
+ discard;
+ }
+
+ if (alpha < minimum_alpha) // treat as semi-transparent
+ {
+ if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+ {
+ discard;
+ }
+ }
+
+ frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
new file mode 100644
index 0000000000..b54c580ce9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
@@ -0,0 +1,68 @@
+/**
+ * @file attachmentAlphaShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+uniform sampler2D diffuseMap;
+
+VARYING float pos_w;
+VARYING float target_pos_x;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main()
+{
+ float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+ if (alpha < 0.05) // treat as totally transparent
+ {
+ discard;
+ }
+
+ if (alpha < minimum_alpha)
+ {
+ if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+ {
+ discard;
+ }
+ }
+
+ frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
new file mode 100644
index 0000000000..31b93dc36a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
@@ -0,0 +1,74 @@
+/**
+ * @file attachmentShadowV.glsl
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+uniform mat4 texture_matrix0;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+mat4 getObjectSkinnedTransform();
+void passTextureIndex();
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+VARYING vec2 vary_texcoord0;
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+
+void main()
+{
+ //transform vertex
+ mat4 mat = getObjectSkinnedTransform();
+
+ mat = modelview_matrix * mat;
+ vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+
+ vec4 p = projection_matrix * vec4(pos, 1.0);
+
+ pos_w = p.w;
+
+ target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+ vertex_color = diffuse_color;
+
+#if !DEPTH_CLAMP
+ p.z = max(p.z, -p.w+0.01);
+ post_pos = p;
+ gl_Position = p;
+#else
+ gl_Position = p;
+#endif
+
+ passTextureIndex();
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
new file mode 100644
index 0000000000..b8ce54bcb1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
@@ -0,0 +1,65 @@
+/**
+ * @file treeShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+uniform sampler2D diffuseMap;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING float target_pos_x;
+VARYING float pos_w;
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+ float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
+
+ if (alpha < 0.05) // treat as totally transparent
+ {
+ discard;
+ }
+
+ if (alpha < minimum_alpha)
+ {
+ if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+ {
+ discard;
+ }
+ }
+
+ frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
new file mode 100644
index 0000000000..ef49b6f4e8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
@@ -0,0 +1,68 @@
+/**
+ * @file avatarAlphaShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+
+uniform sampler2D diffuseMap;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main()
+{
+ float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+ if (alpha < 0.05) // treat as totally transparent
+ {
+ discard;
+ }
+
+ if (alpha < minimum_alpha) // treat as semi-transparent
+ {
+ if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+ {
+ discard;
+ }
+ }
+
+ frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP
+ gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
new file mode 100644
index 0000000000..d1d7ece6fe
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
@@ -0,0 +1,82 @@
+/**
+ * @file avatarShadowV.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 projection_matrix;
+uniform float shadow_target_width;
+
+mat4 getSkinnedTransform();
+void passTextureIndex();
+
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main()
+{
+ vec4 pos;
+ vec3 norm;
+
+ vec4 pos_in = vec4(position.xyz, 1.0);
+ mat4 trans = getSkinnedTransform();
+ pos.x = dot(trans[0], pos_in);
+ pos.y = dot(trans[1], pos_in);
+ pos.z = dot(trans[2], pos_in);
+ pos.w = 1.0;
+
+ norm.x = dot(trans[0].xyz, normal);
+ norm.y = dot(trans[1].xyz, normal);
+ norm.z = dot(trans[2].xyz, normal);
+ norm = normalize(norm);
+
+ pos = projection_matrix * pos;
+
+ target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+ pos_w = pos.w;
+
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+ vertex_color = diffuse_color;
+#if !DEPTH_CLAMP
+ post_pos = pos;
+
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+ gl_Position = pos;
+#endif
+
+ passTextureIndex();
+}
+
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index ef69990170..b318156cf8 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -60,6 +60,7 @@ static U32 sShaderLevel = 0;
LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
+S32 LLDrawPoolAvatar::sShadowPass = -1;
S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f;
@@ -403,19 +404,33 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
S32 LLDrawPoolAvatar::getNumShadowPasses()
{
- return 2;
+ // avatars opaque, avatar alpha, avatar alpha mask, alpha attachments, alpha mask attachments, opaque attachments...
+ return NUM_SHADOW_PASSES;
}
void LLDrawPoolAvatar::beginShadowPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR);
- if (pass == 0)
+ if (pass == SHADOW_PASS_AVATAR_OPAQUE)
{
sVertexProgram = &gDeferredAvatarShadowProgram;
- //gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
+ if ((sShaderLevel > 0)) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ }
+ gGL.diffuseColor4f(1,1,1,1);
+ }
+ else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND)
+ {
+ sVertexProgram = &gDeferredAvatarAlphaShadowProgram;
+
+ // bind diffuse tex so we can reference the alpha channel...
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
if ((sShaderLevel > 0)) // for hardware blending
{
sRenderingSkinned = TRUE;
@@ -424,7 +439,52 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
gGL.diffuseColor4f(1,1,1,1);
}
- else
+ else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK)
+ {
+ sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram;
+
+ // bind diffuse tex so we can reference the alpha channel...
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
+ if ((sShaderLevel > 0)) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ }
+
+ gGL.diffuseColor4f(1,1,1,1);
+ }
+ else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)
+ {
+ sVertexProgram = &gDeferredAttachmentAlphaShadowProgram;
+
+ // bind diffuse tex so we can reference the alpha channel...
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
+ if ((sShaderLevel > 0)) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ }
+
+ gGL.diffuseColor4f(1,1,1,1);
+ }
+ else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK)
+ {
+ sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram;
+
+ // bind diffuse tex so we can reference the alpha channel...
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
+ if ((sShaderLevel > 0)) // for hardware blending
+ {
+ sRenderingSkinned = TRUE;
+ sVertexProgram->bind();
+ }
+
+ gGL.diffuseColor4f(1,1,1,1);
+ }
+ else // SHADOW_PASS_ATTACHMENT_OPAQUE
{
sVertexProgram = &gDeferredAttachmentShadowProgram;
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -435,20 +495,19 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
void LLDrawPoolAvatar::endShadowPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR);
- if (pass == 0)
- {
- if (sShaderLevel > 0)
- {
- sRenderingSkinned = FALSE;
- sVertexProgram->unbind();
- }
- }
- else
+
+ if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE)
{
LLVertexBuffer::unbind();
+ }
+
+ if (sShaderLevel > 0)
+ {
sVertexProgram->unbind();
- sVertexProgram = NULL;
}
+ sVertexProgram = NULL;
+ sRenderingSkinned = FALSE;
+ LLDrawPoolAvatar::sShadowPass = -1;
}
void LLDrawPoolAvatar::renderShadow(S32 pass)
@@ -480,16 +539,68 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
return;
}
- if (pass == 0)
+ LLDrawPoolAvatar::sShadowPass = pass;
+
+ if (pass == SHADOW_PASS_AVATAR_OPAQUE)
{
+ LLDrawPoolAvatar::sSkipTransparent = true;
avatarp->renderSkinned();
+ LLDrawPoolAvatar::sSkipTransparent = false;
}
- else
+ else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND)
{
- for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
- {
- renderRigged(avatarp, i);
- }
+ LLDrawPoolAvatar::sSkipOpaque = true;
+ avatarp->renderSkinned();
+ LLDrawPoolAvatar::sSkipOpaque = false;
+ }
+ else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK)
+ {
+ LLDrawPoolAvatar::sSkipOpaque = true;
+ avatarp->renderSkinned();
+ LLDrawPoolAvatar::sSkipOpaque = false;
+ }
+ else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha
+ {
+ LLDrawPoolAvatar::sSkipOpaque = true;
+ renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
+ renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
+ renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
+ renderRigged(avatarp, RIGGED_ALPHA);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);
+ renderRigged(avatarp, RIGGED_GLOW);
+ LLDrawPoolAvatar::sSkipOpaque = false;
+ }
+ else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask
+ {
+ LLDrawPoolAvatar::sSkipOpaque = true;
+ renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
+ renderRigged(avatarp, RIGGED_NORMMAP_MASK);
+ renderRigged(avatarp, RIGGED_SPECMAP_MASK);
+ renderRigged(avatarp, RIGGED_NORMSPEC_MASK);
+ renderRigged(avatarp, RIGGED_GLOW);
+ LLDrawPoolAvatar::sSkipOpaque = false;
+ }
+ else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE
+ {
+ LLDrawPoolAvatar::sSkipTransparent = true;
+ renderRigged(avatarp, RIGGED_MATERIAL);
+ renderRigged(avatarp, RIGGED_SPECMAP);
+ renderRigged(avatarp, RIGGED_SPECMAP_BLEND);
+ renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
+ renderRigged(avatarp, RIGGED_NORMMAP);
+ renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
+ renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
+ renderRigged(avatarp, RIGGED_NORMSPEC);
+ renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
+ renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
+ renderRigged(avatarp, RIGGED_SIMPLE);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT);
+ renderRigged(avatarp, RIGGED_SHINY);
+ renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY);
+ renderRigged(avatarp, RIGGED_GLOW);
+ renderRigged(avatarp, RIGGED_DEFERRED_BUMP);
+ renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE);
+ LLDrawPoolAvatar::sSkipTransparent = false;
}
}
@@ -1737,8 +1848,81 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
LLVertexBuffer* buff = face->getVertexBuffer();
+ const LLTextureEntry* tex_entry = face->getTextureEntry();
+ LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr;
+
+ if (LLDrawPoolAvatar::sShadowPass >= 0)
+ {
+ bool is_alpha_blend = false;
+ bool is_alpha_mask = false;
+
+ if (mat)
+ {
+ switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
+ {
+ case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
+ {
+ is_alpha_mask = true;
+ }
+ break;
+
+ case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
+ {
+ is_alpha_blend = true;
+ }
+ break;
+
+ case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
+ case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT:
+ case LLMaterial::DIFFUSE_ALPHA_MODE_NONE:
+ default:
+ break;
+ }
+ }
+
+ if (tex_entry)
+ {
+ if (tex_entry->getAlpha() <= 0.99f)
+ {
+ is_alpha_blend = true;
+ }
+ }
+
+ LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
+ if (tex)
+ {
+ LLGLenum image_format = tex->getPrimaryFormat();
+ if (tex->getIsAlphaMask())
+ {
+ is_alpha_mask = true;
+ }
+ else if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA))
+ {
+ is_alpha_blend = true;
+ }
+ }
+
+ // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass...
+ if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK))
+ {
+ return;
+ }
+
+ // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass...
+ if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND))
+ {
+ return;
+ }
+
+ // if this is opaque content and we're skipping opaques...
+ if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque)
+ {
+ return;
+ }
+ }
+
if (buff)
- {
+ {
if (sShaderLevel > 0)
{
// upload matrix palette to shader
@@ -1794,9 +1978,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow());
}*/
- const LLTextureEntry* te = face->getTextureEntry();
- LLMaterial* mat = te->getMaterialParams().get();
-
if (mat)
{
//order is important here LLRender::DIFFUSE_MAP should be last, becouse it change
@@ -1827,12 +2008,12 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (mat->getSpecularID().isNull())
{
- env = te->getShiny()*0.25f;
+ env = tex_entry->getShiny()*0.25f;
col.set(env,env,env,0);
spec = env;
}
- BOOL fullbright = te->getFullbright();
+ BOOL fullbright = tex_entry->getFullbright();
sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f);
sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
@@ -1840,7 +2021,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
{
- sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f);
+ F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
+ sVertexProgram->setMinimumAlpha(cutoff);
}
else
{
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index b9d2204052..8afe6788ff 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -55,105 +55,7 @@ public:
LLVertexBuffer::MAP_CLOTHWEIGHT
};
- virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
-
- virtual S32 getVertexShaderLevel() const;
-
- LLDrawPoolAvatar();
-
- static LLMatrix4& getModelView();
-
- /*virtual*/ LLDrawPool *instancePool();
-
- /*virtual*/ S32 getNumPasses();
- /*virtual*/ void beginRenderPass(S32 pass);
- /*virtual*/ void endRenderPass(S32 pass);
- /*virtual*/ void prerender();
- /*virtual*/ void render(S32 pass = 0);
-
- /*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 beginImpostor();
- void beginSkinned();
-
- void endRigid();
- void endImpostor();
- void endSkinned();
-
- void beginDeferredImpostor();
- void beginDeferredRigid();
- void beginDeferredSkinned();
-
- void endDeferredImpostor();
- void endDeferredRigid();
- void endDeferredSkinned();
-
- void beginPostDeferredAlpha();
- void endPostDeferredAlpha();
-
- void beginRiggedSimple();
- void beginRiggedFullbright();
- void beginRiggedFullbrightShiny();
- void beginRiggedShinySimple();
- void beginRiggedAlpha();
- void beginRiggedFullbrightAlpha();
- void beginRiggedGlow();
- void beginDeferredRiggedAlpha();
- void beginDeferredRiggedMaterial(S32 pass);
- void beginDeferredRiggedMaterialAlpha(S32 pass);
-
- void endRiggedSimple();
- void endRiggedFullbright();
- void endRiggedFullbrightShiny();
- void endRiggedShinySimple();
- void endRiggedAlpha();
- void endRiggedFullbrightAlpha();
- void endRiggedGlow();
- void endDeferredRiggedAlpha();
- void endDeferredRiggedMaterial(S32 pass);
- void endDeferredRiggedMaterialAlpha(S32 pass);
-
- void beginDeferredRiggedSimple();
- void beginDeferredRiggedBump();
-
- void endDeferredRiggedSimple();
- void endDeferredRiggedBump();
-
- void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
- void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
- LLFace* facep,
- const LLMeshSkinInfo* skin,
- LLVolume* volume,
- const LLVolumeFace& vol_face);
- void updateRiggedVertexBuffers(LLVOAvatar* avatar);
-
- void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
- void renderRiggedSimple(LLVOAvatar* avatar);
- void renderRiggedAlpha(LLVOAvatar* avatar);
- void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
- void renderRiggedFullbright(LLVOAvatar* avatar);
- void renderRiggedShinySimple(LLVOAvatar* avatar);
- void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
- void renderRiggedGlow(LLVOAvatar* avatar);
- void renderDeferredRiggedSimple(LLVOAvatar* avatar);
- void renderDeferredRiggedBump(LLVOAvatar* avatar);
- void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass);
-
- typedef enum
+ typedef enum
{
RIGGED_MATERIAL=0,
RIGGED_MATERIAL_ALPHA,
@@ -258,6 +160,117 @@ public:
LLVertexBuffer::MAP_WEIGHT4,
} eRiggedDataMask;
+typedef enum
+ {
+ SHADOW_PASS_AVATAR_OPAQUE,
+ SHADOW_PASS_AVATAR_ALPHA_BLEND,
+ SHADOW_PASS_AVATAR_ALPHA_MASK,
+ SHADOW_PASS_ATTACHMENT_ALPHA_BLEND,
+ SHADOW_PASS_ATTACHMENT_ALPHA_MASK,
+ SHADOW_PASS_ATTACHMENT_OPAQUE,
+ NUM_SHADOW_PASSES
+ } eShadowPass;
+
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+ virtual S32 getVertexShaderLevel() const;
+
+ LLDrawPoolAvatar();
+
+ static LLMatrix4& getModelView();
+
+ /*virtual*/ LLDrawPool *instancePool();
+
+ /*virtual*/ S32 getNumPasses();
+ /*virtual*/ void beginRenderPass(S32 pass);
+ /*virtual*/ void endRenderPass(S32 pass);
+ /*virtual*/ void prerender();
+ /*virtual*/ void render(S32 pass = 0);
+
+ /*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 beginImpostor();
+ void beginSkinned();
+
+ void endRigid();
+ void endImpostor();
+ void endSkinned();
+
+ void beginDeferredImpostor();
+ void beginDeferredRigid();
+ void beginDeferredSkinned();
+
+ void endDeferredImpostor();
+ void endDeferredRigid();
+ void endDeferredSkinned();
+
+ void beginPostDeferredAlpha();
+ void endPostDeferredAlpha();
+
+ void beginRiggedSimple();
+ void beginRiggedFullbright();
+ void beginRiggedFullbrightShiny();
+ void beginRiggedShinySimple();
+ void beginRiggedAlpha();
+ void beginRiggedFullbrightAlpha();
+ void beginRiggedGlow();
+ void beginDeferredRiggedAlpha();
+ void beginDeferredRiggedMaterial(S32 pass);
+ void beginDeferredRiggedMaterialAlpha(S32 pass);
+
+ void endRiggedSimple();
+ void endRiggedFullbright();
+ void endRiggedFullbrightShiny();
+ void endRiggedShinySimple();
+ void endRiggedAlpha();
+ void endRiggedFullbrightAlpha();
+ void endRiggedGlow();
+ void endDeferredRiggedAlpha();
+ void endDeferredRiggedMaterial(S32 pass);
+ void endDeferredRiggedMaterialAlpha(S32 pass);
+
+ void beginDeferredRiggedSimple();
+ void beginDeferredRiggedBump();
+
+ void endDeferredRiggedSimple();
+ void endDeferredRiggedBump();
+
+ void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
+ void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
+ LLFace* facep,
+ const LLMeshSkinInfo* skin,
+ LLVolume* volume,
+ const LLVolumeFace& vol_face);
+ void updateRiggedVertexBuffers(LLVOAvatar* avatar);
+
+ void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
+ void renderRiggedSimple(LLVOAvatar* avatar);
+ void renderRiggedAlpha(LLVOAvatar* avatar);
+ void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
+ void renderRiggedFullbright(LLVOAvatar* avatar);
+ void renderRiggedShinySimple(LLVOAvatar* avatar);
+ void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
+ void renderRiggedGlow(LLVOAvatar* avatar);
+ void renderDeferredRiggedSimple(LLVOAvatar* avatar);
+ void renderDeferredRiggedBump(LLVOAvatar* avatar);
+ void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass);
+
+
+
void addRiggedFace(LLFace* facep, U32 type);
void removeRiggedFace(LLFace* facep);
@@ -271,6 +284,7 @@ public:
static BOOL sSkipOpaque;
static BOOL sSkipTransparent;
+ static S32 sShadowPass;
static S32 sDiffuseChannel;
static F32 sMinimumAlpha;
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index d2acfa291c..2468aeffa2 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -212,7 +212,11 @@ LLGLSLShader gDeferredShadowProgram;
LLGLSLShader gDeferredShadowCubeProgram;
LLGLSLShader gDeferredShadowAlphaMaskProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
+LLGLSLShader gDeferredAvatarAlphaShadowProgram;
+LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram;
LLGLSLShader gDeferredAttachmentShadowProgram;
+LLGLSLShader gDeferredAttachmentAlphaShadowProgram;
+LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
LLGLSLShader gDeferredAlphaImpostorProgram;
LLGLSLShader gDeferredAlphaWaterProgram;
@@ -1836,6 +1840,30 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader";
+ gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true;
+ gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear();
+ gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAvatarAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader";
+ gDeferredAvatarAlphaMaskShadowProgram.mFeatures.hasSkinning = true;
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear();
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL);
+ }
+
if (success)
{
gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader";
@@ -1847,6 +1875,30 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
}
+
+ if (success)
+ {
+ gDeferredAttachmentAlphaShadowProgram.mName = "Deferred Attachment Alpha Shadow Shader";
+ gDeferredAttachmentAlphaShadowProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredAttachmentAlphaShadowProgram.mShaderFiles.clear();
+ gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAttachmentAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredAttachmentAlphaMaskShadowProgram.mName = "Deferred Attachment Alpha Mask Shadow Shader";
+ gDeferredAttachmentAlphaMaskShadowProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.clear();
+ gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAttachmentAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+ gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL);
+ }
if (success)
{
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 923aa522ad..9ba7d7f742 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -319,6 +319,10 @@ extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredPostGammaCorrectProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
extern LLGLSLShader gDeferredAttachmentShadowProgram;
+extern LLGLSLShader gDeferredAttachmentAlphaShadowProgram;
+extern LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram;
+extern LLGLSLShader gDeferredAvatarAlphaShadowProgram;
+extern LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredAlphaImpostorProgram;
extern LLGLSLShader gDeferredFullbrightProgram;