From 3e80fa3dbc943de9b784fedc202ba38cf238f46d Mon Sep 17 00:00:00 2001 From: David Parks Date: Mon, 2 Nov 2009 19:55:37 +0000 Subject: Sync up with render-pipeline-7 ignore-dead-branch --- .../newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl | 2 +- indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 651959413c..45884d5732 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -137,7 +137,7 @@ void main() } //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod); + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*proj_ambiance; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index a0026edcd2..4333cc64a7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -224,11 +224,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; -- cgit v1.3 From e833e7ad442f5b59f95c6ccfcaaf1d103d247d69 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 4 Jan 2010 11:50:04 -0600 Subject: CTS-54 Fix for SSAO artifacts far away. --- .../shaders/class1/deferred/sunLightF.glsl | 82 ++++++++++++---------- .../shaders/class2/deferred/sunLightF.glsl | 82 ++++++++++++---------- 2 files changed, 92 insertions(+), 72 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index 22bdd2c7f3..fafc2ae3cc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -53,51 +53,61 @@ vec4 getPosition(vec2 pos_screen) //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 ret = 1.0; - float angle_hidden = 0.0; - int points = 0; + float dist = dot(pos.xyz,pos.xyz); - 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++) + if (dist < 64.0*64.0) { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; + 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; - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); + float angle_hidden = 0.0; + int points = 0; - // 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) + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - //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); + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = 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); + } - // '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); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); } - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return (1.0 - (float(points != 0) * angle_hidden)); + return min(ret, 1.0); } void main() diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 4333cc64a7..74a948f584 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -55,51 +55,61 @@ vec4 getPosition(vec2 pos_screen) //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 ret = 1.0; - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + float dist = dot(pos.xyz,pos.xyz); - // 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++) + if (dist < 64.0*64.0) { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = getPosition(samppos_screen).xyz; + 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; - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); + float angle_hidden = 0.0; + int points = 0; - // 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) + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - //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); + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = 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); + } - // '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); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); } - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return (1.0 - (float(points != 0) * angle_hidden)); + return min(ret, 1.0); } float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) -- cgit v1.3 From 728463b40b9794b9fa4cd5b7bad3f169033d0bc8 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 8 Jan 2010 13:31:04 -0600 Subject: Cleaned up visible edges of projector frustum in diffuse/specular/ambient lighting from projectors. --- .../shaders/class1/deferred/multiSpotLightF.glsl | 102 +++++++++++++++------ .../shaders/class2/deferred/multiSpotLightF.glsl | 58 +++++++++++- .../shaders/class2/deferred/spotLightF.glsl | 11 --- 3 files changed, 128 insertions(+), 43 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 28bcd720c0..2c8d90d1a6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -5,7 +5,6 @@ * $License$ */ - #version 120 #extension GL_ARB_texture_rectangle : enable @@ -15,6 +14,7 @@ uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D lightFunc; uniform sampler2D projectionMap; @@ -26,12 +26,15 @@ uniform vec3 proj_n; uniform float proj_focus; //distance from plane to begin blurring uniform float proj_lod; //(number of mips in proj map) uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; uniform float proj_ambiance; uniform float near_clip; uniform float far_clip; uniform vec3 proj_origin; //origin of projection to be used for angular attenuation uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; varying vec4 vary_light; @@ -40,6 +43,52 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -68,7 +117,7 @@ void main() { discard; } - + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; norm = normalize(norm); @@ -83,7 +132,11 @@ void main() proj_tc.xyz /= proj_tc.w; float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } lv = proj_origin-pos.xyz; lv = normalize(lv); @@ -101,32 +154,32 @@ void main() proj_tc.y > 0.0) { float lit = 0.0; + float amb_da = proj_ambiance; + if (da > 0.0) { float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; lit = da * dist_atten * noise; col = lcol*lit*diff_tex; + amb_da += (da*0.5)*proj_ambiance; } - float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - float lod = diff * proj_lod; - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); - //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); - float amb_da = proj_ambiance; - + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + amb_da += (da*da*0.5+0.5)*proj_ambiance; - + amb_da *= dist_atten * noise; - + amb_da = min(amb_da, 1.0-lit); - + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; } @@ -144,35 +197,28 @@ void main() { vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; - vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); if (stc.z > 0.0) { - stc.xy /= stc.z+proj_near; - + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb; } } } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 45884d5732..3e29c684e8 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -43,6 +43,52 @@ uniform vec2 screen_res; uniform mat4 inv_proj; +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); + + float det = min(lod/(proj_lod*0.5), 1.0); + + float d = min(dist.x, dist.y); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -126,7 +172,7 @@ void main() float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); float lod = diff * proj_lod; - vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; @@ -137,7 +183,7 @@ void main() } //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); - vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_lod); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); amb_da += (da*da*0.5+0.5)*proj_ambiance; @@ -167,13 +213,17 @@ void main() if (stc.z > 0.0) { stc.xy /= stc.w; - + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + if (stc.x < 1.0 && stc.y < 1.0 && stc.x > 0.0 && stc.y > 0.0) { - vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; } } diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index d6534083cf..6617e33c0d 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -179,17 +179,6 @@ void main() } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - //attenuate point light contribution by SSAO component col *= texture2DRect(lightMap, frag.xy).g; -- cgit v1.3 From 73c98e1c1e3899aaae1de6bac51f9e21ea6432a1 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 28 Jan 2010 18:01:12 -0800 Subject: enable basic directional lighting for basic/atmospheric shaders - yay. next, needs the non-shader GL lighting model to be equally dumb (it's too smart - kill the spot angle. --- .../shaders/class1/lighting/lightFuncV.glsl | 21 +++++++++++++++++++++ .../shaders/class2/lighting/sumLightsV.glsl | 8 +++++--- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 3e8fdfb3e4..211de830fa 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -28,7 +28,28 @@ float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) //angular attenuation da *= calcDirectionalLight(n, lv); + + return da; +} + + +float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la) +{ + //get light vector + vec3 lv = lp.xyz-v; + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float da = clamp(1.0/(la * d), 0.0, 1.0); + + //angular attenuation + da *= dot(lv, -ln) * calcDirectionalLight(n, lv); + return da; } diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index f4c59734a4..fd264b9e74 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -7,6 +7,7 @@ float calcDirectionalLight(vec3 n, vec3 l); float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -18,9 +19,10 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + + col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation); + col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation); + //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation); col.rgb = scaleDownLight(col.rgb); // Add windlight lights -- cgit v1.3 From bc0a9fd5fe0675d7327ee182ff4ac20c39e76305 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 28 Jan 2010 21:48:22 -0800 Subject: getting closer to point/spot interchangability --- indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl | 6 +++--- indra/newview/pipeline.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index fd264b9e74..e5bf76db55 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -20,9 +20,9 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation); - //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); col.rgb = scaleDownLight(col.rgb); // Add windlight lights diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6cd8b94405..e12412c58c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4613,8 +4613,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight - const float specular = {0.f, 0.f, 0.f, 1.f}, - glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); + const float specular[] = {0.f, 0.f, 0.f, 1.f}; + glLightfv(gllight, GL_SPECULAR, specular); } cur_light++; if (cur_light >= 8) -- cgit v1.3 From fcaca49a9496154419a8f44c17cba16b028d3518 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 28 Jan 2010 23:58:50 -0800 Subject: cheap no-branch goodness for rendering both spotlights and pointlights with the same shader code. kill already-nerfed quadratic attenuation which it seems we won't be supporting any decade soon. --- .../shaders/class1/lighting/lightFuncV.glsl | 6 +++- .../shaders/class2/lighting/sumLightsV.glsl | 2 +- indra/newview/pipeline.cpp | 42 ++++++++-------------- 3 files changed, 21 insertions(+), 29 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 4525bf80b2..2e41f24afe 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -47,8 +47,12 @@ float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_omnid //distance attenuation float da = clamp(1.0/(la * d), 0.0, 1.0); + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_omnidirectional); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + //angular attenuation - da *= max(dot(-ln, lv),is_omnidirectional) * calcDirectionalLight(n, lv); + da *= calcDirectionalLight(n, lv); return da; } diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index e5bf76db55..4577b4be55 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -7,7 +7,7 @@ float calcDirectionalLight(vec3 n, vec3 l); float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); -float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la); +float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_omnidirectional); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e12412c58c..2ad0bad11f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4572,40 +4572,30 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos_gl(light_pos, 1.0f); F32 light_radius = llmax(light->getLightRadius(), 0.001f); - F32 atten, quad; -#if 0 //1.9.1 - if (pool->getVertexShaderLevel() > 0) - { - atten = light_radius; - quad = llmax(light->getLightFalloff(), 0.0001f); - } - else -#endif - { - F32 x = (3.f * (1.f + light->getLightFalloff())); - atten = x / (light_radius); // % of brightness at radius - quad = 0.0f; - } + F32 x = (3.f * (1.f + light->getLightFalloff())); + float linatten = x / (light_radius); // % of brightness at radius + mHWLightColors[cur_light] = light_color; S32 gllight = GL_LIGHT0+cur_light; glLightfv(gllight, GL_POSITION, light_pos_gl.mV); glLightfv(gllight, GL_DIFFUSE, light_color.mV); glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, atten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad); + glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); + glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); if (light->getLightTexture()) // directional (spot-)light { LLVector3 spotparams = light->getSpotLightParams(); LLQuaternion quat = light->getRenderRotation(); LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction at_axis *= quat; - llinfos << "SPOT!!!!!!! fov: " << spotparams.mV[0] << " focus: " << spotparams.mV[1] << " dir: " << at_axis << llendl; + //llinfos << "SPOT!!!!!!! fov: " << spotparams.mV[0] << " focus: " << spotparams.mV[1] << " dir: " << at_axis << llendl; glLightfv(gllight, GL_SPOT_DIRECTION, at_axis.mV); - glLightf (gllight, GL_SPOT_EXPONENT, 1.0f); // 1.0 = good old dot product + glLightf (gllight, GL_SPOT_EXPONENT, 2.0f); // 2.0 = good old dot product ^ 2 glLightf (gllight, GL_SPOT_CUTOFF, 90.0f); // hemisphere - glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); + const float specular[] = {0.f, 0.f, 0.f, 0.f}; + glLightfv(gllight, GL_SPECULAR, specular); } else // omnidirectional (point) light { @@ -4615,6 +4605,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight const float specular[] = {0.f, 0.f, 0.f, 1.f}; glLightfv(gllight, GL_SPECULAR, specular); + //llinfos << "boring light" << llendl; } cur_light++; if (cur_light >= 8) @@ -4641,13 +4632,10 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos_gl(light_pos, 1.0f); F32 light_radius = 16.f; - F32 atten, quad; - { - F32 x = 3.f; - atten = x / (light_radius); // % of brightness at radius - quad = 0.0f; - } + F32 x = 3.f; + float linatten = x / (light_radius); // % of brightness at radius + mHWLightColors[2] = light_color; S32 gllight = GL_LIGHT2; glLightfv(gllight, GL_POSITION, light_pos_gl.mV); @@ -4655,8 +4643,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, atten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, quad); + glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); + glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); } -- cgit v1.3 From d0cf5b03f4fec29db367d8f1f387f2b0996f67e6 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 29 Jan 2010 00:22:13 -0800 Subject: spot-aware light func usage in ALL shaders. --- .../shaders/class1/deferred/alphaV.glsl | 14 +++++++------- .../shaders/class1/deferred/avatarAlphaV.glsl | 14 +++++++------- .../shaders/class1/lighting/lightFuncV.glsl | 22 +--------------------- .../shaders/class2/deferred/alphaV.glsl | 14 +++++++------- .../shaders/class2/deferred/avatarAlphaV.glsl | 14 +++++++------- .../shaders/class2/lighting/sumLightsV.glsl | 9 ++++----- .../shaders/class3/lighting/sumLightsV.glsl | 15 ++++++++------- 7 files changed, 41 insertions(+), 61 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 1a7d58b07b..91793a29d3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -9,7 +9,7 @@ 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); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -49,12 +49,12 @@ void main() 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[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index c1988d3c78..e36564df10 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -10,7 +10,7 @@ mat4 getSkinnedTransform(); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -55,12 +55,12 @@ void main() 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[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 2e41f24afe..d0f58cc1a4 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -12,28 +12,8 @@ float calcDirectionalLight(vec3 n, vec3 l) return a; } -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) -{ - //get light vector - vec3 lv = lp.xyz-v; - - //get distance - float d = length(lv); - - //normalize light vector - lv *= 1.0/d; - - //distance attenuation - float da = clamp(1.0/(la * d), 0.0, 1.0); - - //angular attenuation - da *= calcDirectionalLight(n, lv); - - return da; -} - -float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_omnidirectional) +float calcPointlightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) { //get light vector vec3 lv = lp.xyz-v; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 5991e1f3b5..eec655e3df 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -9,7 +9,7 @@ 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); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -50,12 +50,12 @@ void main() 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[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index a939499b17..488bd677e1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -10,7 +10,7 @@ mat4 getSkinnedTransform(); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -61,12 +61,12 @@ void main() 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[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index 4577b4be55..19800d96dc 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -6,8 +6,7 @@ */ float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); -float calcPointLight2(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_omnidirectional); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -20,9 +19,9 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); - col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); - //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight2(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); col.rgb = scaleDownLight(col.rgb); // Add windlight lights diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 1c5234c450..0fdfdf2dde 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -6,7 +6,7 @@ */ float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -24,12 +24,13 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) 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, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); -- cgit v1.3 From 71b35bd63daecfe6ca60560a13f72990afae81ac Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 29 Jan 2010 00:31:39 -0800 Subject: Don't scale windlight lights up just to scale them down again later. avoid this with rearrangement. not tested. --- .../app_settings/shaders/class1/deferred/alphaV.glsl | 10 ++++------ .../app_settings/shaders/class1/deferred/avatarAlphaV.glsl | 10 ++++------ .../app_settings/shaders/class2/deferred/alphaV.glsl | 10 ++++------ .../app_settings/shaders/class2/deferred/avatarAlphaV.glsl | 10 ++++------ .../app_settings/shaders/class3/lighting/sumLightsV.glsl | 14 +++++--------- 5 files changed, 21 insertions(+), 33 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 91793a29d3..cb0d7b797b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -41,12 +41,7 @@ void main() 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); + vec4 col(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); @@ -58,6 +53,9 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index e36564df10..e34f6ba552 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -47,12 +47,7 @@ void main() 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); + vec4 col(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); @@ -64,6 +59,9 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + 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))); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index eec655e3df..05a32578c1 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -42,12 +42,7 @@ void main() 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); + vec4 col(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); @@ -59,6 +54,9 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 488bd677e1..d63baeb913 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -53,12 +53,7 @@ void main() 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); + vec4 col(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); @@ -70,6 +65,9 @@ void main() col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + 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))); diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 0fdfdf2dde..371d6b526c 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -15,16 +15,9 @@ vec3 scaleUpLight(vec3 light); vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { - vec4 col; - col.a = color.a; + vec4 col(0.0, 0.0, 0.0, color.a); - // Add windlight lights - col.rgb = atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); - col.rgb += atmosAmbient(baseLight.rgb); - 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*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); @@ -33,7 +26,10 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); - + + // Add windlight lights + col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); + col.rgb += atmosAmbient(baseLight.rgb); col.rgb = min(col.rgb*color.rgb, 1.0); -- cgit v1.3 From aaae230bb135b9e57edb12a7374c711fd7e4adb4 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 29 Jan 2010 01:45:13 -0800 Subject: fix a variety of shader errors, mostly due to my confusing glsl with C++... again --- indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl | 3 ++- indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl | 3 ++- indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl | 2 +- indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl | 2 +- indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl | 3 ++- indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index cb0d7b797b..04e556c11a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -41,7 +41,8 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col(0.0, 0.0, 0.0, gl_Color.a); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index e34f6ba552..650fbcc3f5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -47,7 +47,8 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col(0.0, 0.0, 0.0, gl_Color.a); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 2b7e8b125b..da49e59b89 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -13,7 +13,7 @@ float calcDirectionalLight(vec3 n, vec3 l) } -float calcPointlightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) { //get light vector vec3 lv = lp.xyz-v; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 05a32578c1..1fae8c4da3 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -42,7 +42,7 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col(0.0, 0.0, 0.0, gl_Color.a); + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index d63baeb913..f8dd1b7431 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -53,7 +53,8 @@ void main() calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col(0.0, 0.0, 0.0, gl_Color.a); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 371d6b526c..f129a1517b 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -15,7 +15,7 @@ vec3 scaleUpLight(vec3 light); vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { - vec4 col(0.0, 0.0, 0.0, color.a); + vec4 col = vec4(0.0, 0.0, 0.0, color.a); // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); -- cgit v1.3 From 372212ae764a32bf667d3cb4cf5b99e6c6147b0f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 5 Mar 2010 10:49:52 -0600 Subject: Fix for sun specular highlights showing up in shadow when diffuse ambiance greater than 0. --- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 531f7376a3..249ac7ef9b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -275,7 +275,7 @@ void main() { vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; } col = atmosLighting(col); -- cgit v1.3 From 64797175a14785ac740ae27e647a5b0241700577 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Sun, 7 Mar 2010 11:34:31 +0000 Subject: Add a touch of fakey ripple to shadows on the surface of water, as if the water has depth. Using 4th component of the normal map to encode a position displacement (along the normal) in the class2 shadow lookup. --- indra/newview/app_settings/shaders/class1/deferred/waterF.glsl | 4 ++-- indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 55c893d73b..ceb7e0fb56 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -133,9 +133,9 @@ void main() //wavef.z *= 0.1f; //wavef = normalize(wavef); - wavef = (norm_mat*vec4(wavef, 1.0)).xyz; + vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - gl_FragData[2] = vec4(wavef*0.5+0.5, 0.0); // normal + gl_FragData[2] = vec4(screenspacewavef*0.5+0.5, screenspacewavef.z*0.5); // normal, displace } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 74a948f584..50502dbdad 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -159,7 +159,9 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + float displace = nmap4.w; + vec3 norm = nmap4.xyz*2.0-1.0; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { @@ -168,9 +170,9 @@ void main() }*/ float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); if (spos.z > -shadow_clip.w) { -- cgit v1.3 From 0afe2491ab6a05bf62a2fce438dfdbbaf0b191df Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 17 Mar 2010 22:22:02 -0500 Subject: CTS-110 Remove soft alpha in deferred pipeline (breaks some content). Will revisit soft alpha in materials project. --- .../newview/app_settings/shaders/class1/deferred/alphaF.glsl | 11 ----------- .../app_settings/shaders/class1/deferred/fullbrightF.glsl | 11 ----------- .../newview/app_settings/shaders/class2/deferred/alphaF.glsl | 11 ----------- indra/newview/pipeline.cpp | 1 - 4 files changed, 34 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 4fb109d687..fea2e16090 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -24,8 +24,6 @@ varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; -uniform float alpha_soften; - uniform mat4 inv_proj; vec4 getPosition(vec2 pos_screen) @@ -57,15 +55,6 @@ void main() color.rgb = scaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && gl_Color.a < 1.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/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index e518bddb98..0db9586a88 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -23,8 +23,6 @@ varying vec4 vary_position; varying vec3 vary_normal; varying vec3 vary_fragcoord; -uniform float alpha_soften; - uniform mat4 inv_proj; vec4 getPosition(vec2 pos_screen) @@ -56,15 +54,6 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && color.a < 1.0) - { - float dist_factor = alpha_soften; - float a = 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/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index ad16de6d81..665fe16b43 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -29,8 +29,6 @@ varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; -uniform float alpha_soften; - uniform float shadow_bias; uniform mat4 inv_proj; @@ -115,15 +113,6 @@ void main() color.rgb = scaleSoftClip(color.rgb); - if (samp_pos.z != 0.0 && gl_Color.a < 1.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)*shadow; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e65c8b9af8..ee5ed32a83 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6249,7 +6249,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften")); shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")); shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")); shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale")); -- cgit v1.3 From bbfacbd50d6e8beac36fd8de1dc51ceb109a4a7d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 19 Mar 2010 18:14:17 -0500 Subject: RenderDeferredSSAO works as an independent setting -- decoupled shadows from SSAO. --- .../shaders/class1/deferred/blurLightF.glsl | 20 +- .../shaders/class1/deferred/multiSpotLightF.glsl | 3 +- .../shaders/class1/deferred/softenLightF.glsl | 27 ++- .../shaders/class1/deferred/spotLightF.glsl | 11 -- .../shaders/class1/deferred/sunLightF.glsl | 201 +-------------------- .../shaders/class2/deferred/multiSpotLightF.glsl | 3 - .../shaders/class2/deferred/softenLightF.glsl | 10 +- .../shaders/class2/deferred/spotLightF.glsl | 4 - .../shaders/class2/deferred/sunLightF.glsl | 64 +------ indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewershadermgr.cpp | 14 +- indra/newview/pipeline.cpp | 156 ++++++++-------- 12 files changed, 138 insertions(+), 376 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index bd5e9dd758..0fad5b4b50 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -10,13 +10,11 @@ uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; -uniform sampler2DRect giLightMap; uniform float dist_factor; uniform float blur_size; uniform vec2 delta; -uniform vec3 kern[32]; -uniform int kern_length; +uniform vec3 kern[4]; uniform float kern_scale; varying vec2 vary_fragcoord; @@ -50,7 +48,7 @@ void main() vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; - for (int i = 1; i < kern_length; i++) + for (int i = 1; i < 4; i++) { vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; vec3 samppos = getPosition(tc).xyz; @@ -61,12 +59,22 @@ void main() defined_weight += kern[i].xy; } } + for (int i = 1; i < 4; i++) + { + vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; + vec3 samppos = getPosition(tc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= 0.003) + { + col += texture2DRect(lightMap, tc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } col /= defined_weight.xyxx; gl_FragColor = col; - - //gl_FragColor = ccol; } + diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index 2c8d90d1a6..82e9450e68 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -7,6 +7,8 @@ #version 120 +//class 1 -- no shadows + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; @@ -14,7 +16,6 @@ uniform sampler2DRect specularRect; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; uniform sampler2D noiseMap; uniform sampler2D lightFunc; uniform sampler2D projectionMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index b4b0d0ce9d..9cf60aad48 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; uniform sampler2DRect depthMap; uniform sampler2D noiseMap; uniform samplerCube environmentMap; @@ -40,7 +41,7 @@ uniform float scene_light_strength; uniform vec3 env_mat[3]; //uniform mat4 shadow_matrix[3]; //uniform vec4 shadow_clip; -//uniform mat3 ssao_effect_mat; +uniform mat3 ssao_effect_mat; varying vec4 vary_light; varying vec2 vary_fragcoord; @@ -178,7 +179,17 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) { temp2.x += .25; //increase ambient when there are more clouds - vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + 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( @@ -250,10 +261,14 @@ void main() vec4 diffuse = texture2DRect(diffuseRect, tc); vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - calcAtmospherics(pos.xyz, 0.0); + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(clamp(da, diffuse.a, 1.0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); col *= diffuse.rgb; @@ -261,12 +276,12 @@ void main() { vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; } col = atmosLighting(col); col = scaleSoftClip(col); - + gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 2a7234fd83..f320dbb400 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -161,17 +161,6 @@ void main() } } - /*if (spec.a > 0.0) - { - //vec3 ref = reflect(normalize(pos), norm); - float sa = dot(normalize(lv-normalize(pos)),norm);; - //sa = max(sa, 0.0); - //sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*lcol*spec.rgb; - }*/ - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index fafc2ae3cc..56e4055c02 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -5,206 +5,11 @@ * $License$ */ -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; -uniform sampler2DRectShadow shadowMap4; -uniform sampler2DRectShadow shadowMap5; -uniform sampler2D noiseMap; - -uniform sampler2D lightFunc; - - -// Inputs -uniform mat4 shadow_matrix[6]; -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; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -uniform float shadow_bias; -uniform float shadow_offset; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} +//class 1, no shadow, no SSAO, should never be called -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - float ret = 1.0; - - float dist = dot(pos.xyz,pos.xyz); - - if (dist < 64.0*64.0) - { - 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 = getPosition(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); - - ret = (1.0 - (float(points != 0) * angle_hidden)); - ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); - } - - return min(ret, 1.0); -} +#extension GL_ARB_texture_rectangle : enable void main() { - vec2 pos_screen = vary_fragcoord.xy; - - //try doing an unproject here - - vec4 pos = getPosition(pos_screen); - - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; - - /*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)); - - vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0); - - //vec3 debug = vec3(0,0,0); - - 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 (spos.z > -shadow_clip.w) - { - vec4 lpos; - - if (spos.z < -shadow_clip.z) - { - lpos = shadow_matrix[3]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (spos.z < -shadow_clip.y) - { - lpos = shadow_matrix[2]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap2, lpos).x; - } - else if (spos.z < -shadow_clip.x) - { - lpos = shadow_matrix[1]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(shadowMap1, lpos).x; - } - else - { - lpos = shadow_matrix[0]*spos; - lpos.xy *= screen_res; - shadow = shadow2DRectProj(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); - - /*debug.r = lpos.y / (lpos.w*screen_res.y); - - lpos.xy /= lpos.w*32.0; - if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) - { - debug.gb = vec2(0.5, 0.5); - } - - debug += (1.0-shadow)*0.5;*/ - - } - 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); - - //spotlight shadow 1 - vec4 lpos = shadow_matrix[4]*spos; - lpos.xy *= screen_res; - gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x; - - //spotlight shadow 2 - lpos = shadow_matrix[5]*spos; - lpos.xy *= screen_res; - gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x; - - //gl_FragColor.rgb = pos.xyz; - //gl_FragColor.b = shadow; - //gl_FragColor.rgb = debug; + gl_FragColor = vec4(0,0,0,0); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 3e29c684e8..5308e5bb1e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -230,9 +230,6 @@ void main() } } - //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/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 249ac7ef9b..589a292751 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; +uniform sampler2DRect depthMap; uniform sampler2D noiseMap; uniform samplerCube environmentMap; uniform sampler2D lightFunc; @@ -41,7 +42,6 @@ uniform vec3 env_mat[3]; uniform vec4 shadow_clip; uniform mat3 ssao_effect_mat; -uniform sampler2DRect depthMap; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -282,13 +282,5 @@ void main() col = scaleSoftClip(col); gl_FragColor.rgb = col; - - //gl_FragColor.rgb = gi_col.rgb; gl_FragColor.a = 0.0; - - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; - //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/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index 6617e33c0d..eeaecc157f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -179,10 +179,6 @@ void main() } } - //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/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 50502dbdad..04c9a4d19a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -7,6 +7,8 @@ #extension GL_ARB_texture_rectangle : enable +//class 2, shadows, no SSAO + uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRectShadow shadowMap0; @@ -52,66 +54,6 @@ vec4 getPosition(vec2 pos_screen) return pos; } -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - float ret = 1.0; - - float dist = dot(pos.xyz,pos.xyz); - - if (dist < 64.0*64.0) - { - 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 = getPosition(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); - - ret = (1.0 - (float(points != 0) * angle_hidden)); - ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); - } - - return min(ret, 1.0); -} - float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; @@ -232,7 +174,7 @@ void main() } gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + gl_FragColor[1] = 1.0; //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8051fcbcfa..862e1de685 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -547,6 +547,7 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2)); gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); + gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _2)); gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _2)); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5b7b464e91..50e5522174 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -973,10 +973,22 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + S32 level = 0; + std::string fragment; + + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { + fragment = "deferred/sunLightSSAOF.glsl"; + } + else + { + fragment = "deferred/sunLightF.glsl"; + } + 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.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 04118ad767..5cfd6c3d38 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6344,16 +6344,16 @@ void LLPipeline::renderDeferredLighting() glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); } - if (gSavedSettings.getS32("RenderShadowDetail") > 0) - { - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); - mDeferredLight[0].bindTarget(); - if (gSavedSettings.getBOOL("RenderDeferredSun")) + mDeferredLight[0].bindTarget(); + + if (gSavedSettings.getBOOL("RenderDeferredSSAO") || gSavedSettings.getS32("RenderShadowDetail") > 0) + { { //paint shadow/SSAO light map (direct lighting lightmap) LLFastTimer ftm(FTM_SUN_SHADOW); bindDeferredShader(gDeferredSunProgram, 0); @@ -6394,18 +6394,22 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredSunProgram); } - else - { - mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); - } + } + else + { + glClearColor(1,1,1,1); + mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + } - mDeferredLight[0].flush(); + mDeferredLight[0].flush(); + { //global illumination specific block (still experimental) if (gSavedSettings.getBOOL("RenderDeferredBlurLight") && - gSavedSettings.getBOOL("RenderDeferredGI")) - { + gSavedSettings.getBOOL("RenderDeferredGI")) + { LLFastTimer ftm(FTM_EDGE_DETECTION); - //get edge map + //generate edge map LLGLDisable blend(GL_BLEND); LLGLDisable test(GL_ALPHA_TEST); LLGLDepthTest depth(GL_FALSE); @@ -6502,79 +6506,79 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredPostGIProgram); } } + } - if (gSavedSettings.getBOOL("RenderDeferredBlurLight")) - { //soften direct lighting lightmap - LLFastTimer ftm(FTM_SOFTEN_SHADOW); - //blur lightmap - mDeferredLight[1].bindTarget(); + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { //soften direct lighting lightmap + LLFastTimer ftm(FTM_SOFTEN_SHADOW); + //blur lightmap + mDeferredLight[1].bindTarget(); - glClearColor(1,1,1,1); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); - - bindDeferredShader(gDeferredBlurLightProgram); + glClearColor(1,1,1,1); + mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + bindDeferredShader(gDeferredBlurLightProgram); - LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); - const U32 kern_length = 4; - F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); - F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); + LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian"); + const U32 kern_length = 4; + F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize"); + F32 dist_factor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = 0.f; + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = 0.f; - LLVector3 gauss[32]; // xweight, yweight, offset + LLVector3 gauss[32]; // xweight, yweight, offset - 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; - } + 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; + } - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - mDeferredLight[1].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); - bindDeferredShader(gDeferredBlurLightProgram, 1); - mDeferredLight[0].bindTarget(); + bindDeferredShader(gDeferredBlurLightProgram, 1); + mDeferredLight[0].bindTarget(); - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - { - LLGLDisable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - mDeferredLight[0].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); } - - stop_glerror(); - glPopMatrix(); - stop_glerror(); - glMatrixMode(GL_MODELVIEW); - stop_glerror(); - glPopMatrix(); - 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); -- cgit v1.3 From 8f9fae7815f24ca59e2a7e180b7baab3bc75e2e7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 20 Mar 2010 14:15:13 -0500 Subject: SSAO version of sunLight shaders. --- .../shaders/class1/deferred/sunLightSSAOF.glsl | 123 ++++++++++ .../shaders/class2/deferred/sunLightSSAOF.glsl | 248 +++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl create mode 100644 indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl new file mode 100644 index 0000000000..7450817ea7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -0,0 +1,123 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +//class 1 -- no shadow, SSAO only + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D noiseMap; + +uniform sampler2D lightFunc; + + +// Inputs +uniform mat4 shadow_matrix[6]; +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; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + float dist = dot(pos.xyz,pos.xyz); + + if (dist < 64.0*64.0) + { + 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 = getPosition(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); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); + } + + return min(ret, 1.0); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + + gl_FragColor[0] = 1.0; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + gl_FragColor[2] = 1.0; + gl_FragColor[3] = 1.0; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl new file mode 100644 index 0000000000..d77d17942a --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -0,0 +1,248 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +//class 2 -- shadows and SSAO + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap4; +uniform sampler2DShadow shadowMap5; +uniform sampler2D noiseMap; + +uniform sampler2D lightFunc; + +// Inputs +uniform mat4 shadow_matrix[6]; +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; + +uniform mat4 inv_proj; +uniform vec2 screen_res; +uniform vec2 shadow_res; +uniform vec2 proj_shadow_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + float dist = dot(pos.xyz,pos.xyz); + + if (dist < 64.0*64.0) + { + 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 = getPosition(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); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); + } + + return min(ret, 1.0); +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias*scl; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias*scl; + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + vec2 off = 1.5/proj_shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); + + + return shadow/5.0; + + //return shadow; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + float displace = nmap4.w; + vec3 norm = nmap4.xyz*2.0-1.0; + + /*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)); + + vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + + if (spos.z > -shadow_clip.w) + { + 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 + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 0.25); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 0.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 0.75); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.0); + } + + // 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); + + //lpos.xy /= lpos.w*32.0; + //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + //{ + // shadow = 0.0; + //} + + } + } + else + { + // more distant than the shadow map covers + shadow = 1.0; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; +} -- cgit v1.3 From eb3206fb93187efdef3dce389862ed31be516963 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Mon, 22 Mar 2010 16:10:34 +0000 Subject: screen-space reflections mk4. generally subtle. very cheap. --- .../shaders/class1/deferred/softenLightF.glsl | 47 +++++++++++++++++---- .../shaders/class2/deferred/softenLightF.glsl | 48 ++++++++++++++++++---- .../shaders/class3/deferred/softenLightF.glsl | 48 ++++++++++++++++++---- 3 files changed, 119 insertions(+), 24 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 9cf60aad48..7d57eaa13d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -56,9 +56,8 @@ vec3 vary_AtmosAttenuation; uniform mat4 inv_proj; uniform vec2 screen_res; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -69,6 +68,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -252,7 +257,8 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; @@ -272,11 +278,36 @@ void main() col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnorm, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // screen-space cheap fakey reflection map + // + // first figure out where we'll make our 2D guess from + vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // get attributes from the 2D guess point + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb; + vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point + float reflit = max(dot(refn, vary_light.xyz), 0.0); + // apply sun color to guess-point, dampen according to inappropriateness of guess + vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; + vec3 ssshiny = (refprod * spec.a); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 589a292751..c5530c5f59 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -55,9 +55,8 @@ vec3 vary_AmblitColor; vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -68,6 +67,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -251,7 +256,8 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; @@ -271,11 +277,37 @@ void main() col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnorm, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // screen-space cheap fakey reflection map + // + // first figure out where we'll make our 2D guess from + vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // get attributes from the 2D guess point + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb; + float refshad = texture2DRect(lightMap, ref2d).r; + vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point + float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad); + // apply sun color to guess-point, dampen according to inappropriateness of guess + vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; + vec3 ssshiny = (refprod * spec.a); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 96a083b522..265fb437ec 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -56,9 +56,8 @@ vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; uniform float gi_ambiance; -vec4 getPosition(vec2 pos_screen) -{ //get position in screen space (world units) given window coordinate and depth map - float depth = texture2DRect(depthMap, pos_screen.xy).a; +vec4 getPosition_d(vec2 pos_screen, float depth) +{ vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -69,6 +68,12 @@ vec4 getPosition(vec2 pos_screen) return pos; } +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -252,7 +257,8 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = getPosition(tc).xyz; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; @@ -274,11 +280,37 @@ void main() col *= diffuse.rgb; - if (spec.a > 0.0) + if (spec.a > 0.0) // specular reflection { - vec3 ref = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(ref, vary_light.xyz); - col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a; + // the old infinite-sky shiny reflection + // + vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnorm, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // screen-space cheap fakey reflection map + // + // first figure out where we'll make our 2D guess from + vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // get attributes from the 2D guess point + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb; + float refshad = texture2DRect(lightMap, ref2d).r; + vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point + float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad); + // apply sun color to guess-point, dampen according to inappropriateness of guess + vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; + vec3 ssshiny = (refprod * spec.a); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); -- cgit v1.3 From 122308205b2958b27152b9dd5375554ef76dd084 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 26 Mar 2010 09:07:08 +0000 Subject: screen-space reflections: remember to unbias the value from the depth map. don't use varying version of lightnorm for lighting the reflection-guess-point. --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 7d57eaa13d..c78d7ece7e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -288,6 +288,7 @@ void main() // screen-space cheap fakey reflection map // + depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point @@ -301,7 +302,7 @@ void main() //refapprop *= step(dot(refnorm, refn), 0.0); refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant // get appropriate light strength for guess-point - float reflit = max(dot(refn, vary_light.xyz), 0.0); + float reflit = max(dot(refn, lightnorm.xyz), 0.0); // apply sun color to guess-point, dampen according to inappropriateness of guess vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; vec3 ssshiny = (refprod * spec.a); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index c5530c5f59..9305d77ddb 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -287,6 +287,7 @@ void main() // screen-space cheap fakey reflection map // + depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point @@ -301,7 +302,7 @@ void main() //refapprop *= step(dot(refnorm, refn), 0.0); refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant // get appropriate light strength for guess-point - float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad); + float reflit = min(max(dot(refn, lightnorm.xyz), 0.0), refshad); // apply sun color to guess-point, dampen according to inappropriateness of guess vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; vec3 ssshiny = (refprod * spec.a); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 265fb437ec..262b34ede7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -290,6 +290,7 @@ void main() // screen-space cheap fakey reflection map // + depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point @@ -304,7 +305,7 @@ void main() //refapprop *= step(dot(refnorm, refn), 0.0); refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant // get appropriate light strength for guess-point - float reflit = min(max(dot(refn, vary_light.xyz), 0.0), refshad); + float reflit = min(max(dot(refn, lightnorm.xyz), 0.0), refshad); // apply sun color to guess-point, dampen according to inappropriateness of guess vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; vec3 ssshiny = (refprod * spec.a); -- cgit v1.3 From 79d2c59112213151060b928a2528c481cfde09fe Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Sun, 28 Mar 2010 21:45:32 +0100 Subject: ss reflections: make the guess less far from the source. --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 2 +- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 2 +- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index c78d7ece7e..e14869af9e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -290,7 +290,7 @@ void main() // depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from - vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 9305d77ddb..78e4c179d7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -289,7 +289,7 @@ void main() // depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from - vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 262b34ede7..9ecb0a40ff 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -292,7 +292,7 @@ void main() // depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from - vec2 ref2d = tc.xy + (0.5 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; -- cgit v1.3 From ccd5b9e2f3f1139814a63d9db03c3671c249930c Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Mon, 29 Mar 2010 11:30:08 +0100 Subject: ss reflections tweakage: + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. --- .../app_settings/shaders/class1/deferred/softenLightF.glsl | 8 ++++++++ .../app_settings/shaders/class2/deferred/softenLightF.glsl | 8 ++++++++ .../app_settings/shaders/class3/deferred/softenLightF.glsl | 8 ++++++++ 3 files changed, 24 insertions(+) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index e14869af9e..4646bd4d40 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -291,6 +291,14 @@ void main() depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 78e4c179d7..5769288a36 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -290,6 +290,14 @@ void main() depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 9ecb0a40ff..70a1c53456 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -293,6 +293,14 @@ void main() depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; -- cgit v1.3 From e3c49e617edf6dfe61389e3e90c28082e5b678ce Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Wed, 31 Mar 2010 18:27:50 +0100 Subject: debug ssreflection blur direction. minor. --- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 5769288a36..922a07c306 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -289,7 +289,7 @@ void main() // depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from - vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // Offset the guess source a little according to a trivial // checkerboard dither function and spec.a. // This is meant to be similar to sampling a blurred version @@ -298,6 +298,7 @@ void main() // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); + ref2d += tc.xy; // use as offset from destination // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 70a1c53456..ddd69befc3 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -292,7 +292,7 @@ void main() // depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from - vec2 ref2d = tc.xy + (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; // Offset the guess source a little according to a trivial // checkerboard dither function and spec.a. // This is meant to be similar to sampling a blurred version @@ -301,6 +301,7 @@ void main() // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); + ref2d += tc.xy; // use as offset from destination // get attributes from the 2D guess point float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; -- cgit v1.3 From 33fd1e26beac37701301dfce3478a145720d73c9 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 2 Apr 2010 16:03:20 +0100 Subject: apply ssreflection changes to class2 and class3 too. --- .../shaders/class2/deferred/softenLightF.glsl | 13 +++++++++---- .../shaders/class3/deferred/softenLightF.glsl | 15 ++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 922a07c306..d6fbae7b22 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -281,12 +281,13 @@ void main() { // the old infinite-sky shiny reflection // - vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(refnorm, vary_light.xyz); + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; // screen-space cheap fakey reflection map // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; @@ -311,9 +312,13 @@ void main() //refapprop *= step(dot(refnorm, refn), 0.0); refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant // get appropriate light strength for guess-point - float reflit = min(max(dot(refn, lightnorm.xyz), 0.0), refshad); + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = max(dot(refn, reflight.xyz), 0.0); // apply sun color to guess-point, dampen according to inappropriateness of guess - vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); // add the two types of shiny together diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index ddd69befc3..ecfd9bef52 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -284,12 +284,13 @@ void main() { // the old infinite-sky shiny reflection // - vec3 refnorm = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(refnorm, vary_light.xyz); + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; // screen-space cheap fakey reflection map // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); depth -= 0.5; // unbias depth // first figure out where we'll make our 2D guess from vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; @@ -313,10 +314,14 @@ void main() // darken reflections from points which face away from the reflected ray - our guess was a back-face //refapprop *= step(dot(refnorm, refn), 0.0); refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant - // get appropriate light strength for guess-point - float reflit = min(max(dot(refn, lightnorm.xyz), 0.0), refshad); + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = max(dot(refn, reflight.xyz), 0.0); // apply sun color to guess-point, dampen according to inappropriateness of guess - vec3 refprod = (vary_SunlitColor*reflit) * refcol.rgb * refapprop; + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); // add the two types of shiny together -- cgit v1.3 From a63c59be9e7df57143ddd04e44263c232f420a21 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 2 Apr 2010 16:09:31 +0100 Subject: ssreflection: restore the shadow factor I accidentally removed with the last update. --- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 2 +- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index d6fbae7b22..00a6a9dcb5 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -315,7 +315,7 @@ void main() // reflect light direction to increase the illusion that // these are reflections. vec3 reflight = reflect(lightnorm.xyz, norm.xyz); - float reflit = max(dot(refn, reflight.xyz), 0.0); + float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); // apply sun color to guess-point, dampen according to inappropriateness of guess float refmod = min(refapprop, reflit); vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index ecfd9bef52..aaa74eb7df 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -318,7 +318,7 @@ void main() // reflect light direction to increase the illusion that // these are reflections. vec3 reflight = reflect(lightnorm.xyz, norm.xyz); - float reflit = max(dot(refn, reflight.xyz), 0.0); + float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); // apply sun color to guess-point, dampen according to inappropriateness of guess float refmod = min(refapprop, reflit); vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; -- cgit v1.3 From e07937ced233513bcae55b2365f9ba5a15108faa Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Wed, 7 Apr 2010 10:31:56 +0100 Subject: apply latest ssreflections tweaks to class2 and class3. --- .../app_settings/shaders/class2/deferred/softenLightF.glsl | 13 ++++++++++--- .../app_settings/shaders/class3/deferred/softenLightF.glsl | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 00a6a9dcb5..dbccb7fb8b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -298,12 +298,19 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); + vec2 checkoffset = normalize(ref2d)*5.0*(1.0-spec.a)*(checkerboard-0.5); + ref2d += checkoffset; ref2d += tc.xy; // use as offset from destination - // get attributes from the 2D guess point + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + // --------------------- + // ^ ^ ^ ^ ^ + // a . b o c . d check=0:avg(a,b) check=1:avg(c,d) + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d).rgb + + texture2DRect(diffuseRect, ref2d + checkoffset*2.0).rgb); float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; - vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb; float refshad = texture2DRect(lightMap, ref2d).r; vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); // figure out how appropriate our guess actually was diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index aaa74eb7df..ef81ed1308 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -301,12 +301,19 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - ref2d += normalize(ref2d)*14.0*(1.0-spec.a)*(checkerboard-0.5); + vec2 checkoffset = normalize(ref2d)*5.0*(1.0-spec.a)*(checkerboard-0.5); + ref2d += checkoffset; ref2d += tc.xy; // use as offset from destination - // get attributes from the 2D guess point + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + // --------------------- + // ^ ^ ^ ^ ^ + // a . b o c . d check=0:avg(a,b) check=1:avg(c,d) + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d).rgb + + texture2DRect(diffuseRect, ref2d + checkoffset*2.0).rgb); float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; - vec3 refcol = texture2DRect(diffuseRect, ref2d).rgb; float refshad = texture2DRect(lightMap, ref2d).r; vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); // figure out how appropriate our guess actually was -- cgit v1.3 From 70aa3cf12405eb7c0deaedce4dd2ced81ca3e0c8 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 7 Apr 2010 12:41:44 -0500 Subject: Shadow aliasing fix WIP --- indra/newview/app_settings/settings.xml | 48 ++++++++++++++++++++++ .../shaders/class2/deferred/sunLightF.glsl | 32 +++++++++++++-- indra/newview/pipeline.cpp | 14 ++++++- 3 files changed, 89 insertions(+), 5 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index eef3725cd7..b0c56aea7c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6537,6 +6537,54 @@ 0.01 + RenderShadowBiasError + + Comment + Error scale for shadow bias (based on altitude). + Persist + 1 + Type + F32 + Value + 0 + + RenderShadowOffsetError + + Comment + Error scale for shadow offset (based on altitude). + Persist + 1 + Type + F32 + Value + 0 + + + RenderSpotShadowBias + + Comment + Bias value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + -0.008 + + RenderSpotShadowOffset + + Comment + Offset value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 0.01 + + + + RenderShadowResolutionScale Comment diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 04c9a4d19a..4974bbef9e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -41,6 +41,9 @@ uniform vec2 proj_shadow_res; uniform float shadow_bias; uniform float shadow_offset; +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -72,6 +75,24 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) //return shadow; } +float pcfSpotShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += spot_shadow_bias*scl; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; @@ -114,7 +135,10 @@ void main() float shadow = 1.0; float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); if (spos.z > -shadow_clip.w) { @@ -176,13 +200,15 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = 1.0; + spos.xyz = shadow_pos*offset*spot_shadow_offset; + //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; + gl_FragColor[2] = pcfSpotShadow(shadowMap4, lpos, 0.8).x; //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; + gl_FragColor[3] = pcfSpotShadow(shadowMap5, lpos, 0.8).x; //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3778cae201..2aa0210a80 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5922,8 +5922,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } +static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred"); + void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map) { + LLFastTimer t(FTM_BIND_DEFERRED); + if (noise_map == 0xFFFFFFFF) { noise_map = mNoiseMap; @@ -6261,10 +6265,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen matrix_nondiag, matrix_nondiag, matrix_diag}; shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat); + F32 shadow_offset_error = 1.f + gSavedSettings.getF32("RenderShadowOffsetError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = 1.f + gSavedSettings.getF32("RenderShadowBiasError") * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")); - shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")); + shader.uniform1f ("shadow_offset", gSavedSettings.getF32("RenderShadowOffset")*shadow_offset_error); + shader.uniform1f("shadow_bias", gSavedSettings.getF32("RenderShadowBias")*shadow_bias_error); + shader.uniform1f ("spot_shadow_offset", gSavedSettings.getF32("RenderSpotShadowOffset")); + shader.uniform1f("spot_shadow_bias", gSavedSettings.getF32("RenderSpotShadowBias")); + shader.uniform1f("lum_scale", gSavedSettings.getF32("RenderLuminanceScale")); shader.uniform1f("sun_lum_scale", gSavedSettings.getF32("RenderSunLuminanceScale")); shader.uniform1f("sun_lum_offset", gSavedSettings.getF32("RenderSunLuminanceOffset")); -- cgit v1.3 From b13af3b8baa05d20ae9f33046f100596182f6be0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 9 Apr 2010 01:42:50 -0500 Subject: Tweak bias on projectors. Fix some silly shader mistakes. --- indra/newview/app_settings/settings.xml | 2 +- .../shaders/class2/deferred/sunLightF.glsl | 29 ++++------------------ .../shaders/class2/deferred/sunLightSSAOF.glsl | 16 +++++++++--- indra/newview/lldrawpoolavatar.cpp | 5 ++++ 4 files changed, 23 insertions(+), 29 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b9647d0148..fa8dccd659 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6524,7 +6524,7 @@ Type F32 Value - -0.008 + -0.0005 RenderSpotShadowOffset diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 4974bbef9e..46db3c990c 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -75,28 +75,10 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) //return shadow; } -float pcfSpotShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) -{ - stc.xyz /= stc.w; - stc.z += spot_shadow_bias*scl; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; - float shadow = cs; - - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); - - return shadow/5.0; - - //return shadow; -} - float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += spot_shadow_bias*scl; float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -107,8 +89,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); - - + return shadow/5.0; //return shadow; @@ -200,15 +181,15 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = 1.0; - spos.xyz = shadow_pos*offset*spot_shadow_offset; + spos.xyz = shadow_pos+offset*spot_shadow_offset; //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfSpotShadow(shadowMap4, lpos, 0.8).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfSpotShadow(shadowMap5, lpos, 0.8).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index d77d17942a..a0dfc96f14 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -40,6 +40,9 @@ uniform vec2 proj_shadow_res; uniform float shadow_bias; uniform float shadow_offset; +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + vec4 getPosition(vec2 pos_screen) { float depth = texture2DRect(depthMap, pos_screen.xy).a; @@ -134,7 +137,7 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; + stc.z += spot_shadow_bias*scl; float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -173,7 +176,10 @@ void main() float shadow = 1.0; float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0); + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); if (spos.z > -shadow_clip.w) { @@ -235,13 +241,15 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + spos.xyz = shadow_pos+offset*spot_shadow_offset; + //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); //gl_FragColor.rgb = pos.xyz; //gl_FragColor.b = shadow; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9311a5f60e..23211d7090 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -314,6 +314,11 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); } -- cgit v1.3 From 14f3b77b9c4103f324d24625bd30dd106ab1817f Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 16 Apr 2010 12:19:30 +0100 Subject: strengthen the fakey blur in the fakey ssreflections. (transplanted from 940e02cbe4fa2f996d11500392e71f3a00e1cfed) --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 2 +- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 2 +- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 158eef9319..5fb86dd92d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -299,7 +299,7 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - vec2 checkoffset = normalize(ref2d)*5.0*(1.0-spec.a)*(checkerboard-0.5); + vec2 checkoffset = normalize(ref2d)*9.0*(1.0-spec.a)*(checkerboard-0.5); ref2d += checkoffset; ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index dbccb7fb8b..1fd54b5607 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -298,7 +298,7 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - vec2 checkoffset = normalize(ref2d)*5.0*(1.0-spec.a)*(checkerboard-0.5); + vec2 checkoffset = normalize(ref2d)*9.0*(1.0-spec.a)*(checkerboard-0.5); ref2d += checkoffset; ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index ef81ed1308..45d921d861 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -301,7 +301,7 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - vec2 checkoffset = normalize(ref2d)*5.0*(1.0-spec.a)*(checkerboard-0.5); + vec2 checkoffset = normalize(ref2d)*9.0*(1.0-spec.a)*(checkerboard-0.5); ref2d += checkoffset; ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. -- cgit v1.3 From e188693f126455ac1e74fbab42ddc76b63bc167b Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Wed, 21 Apr 2010 14:27:54 +0100 Subject: port class1 ssreflections tweaks to class2 and class3 (transplanted from 19036fc277d88c364e957019a66b4cdf4cce8b53) --- .../app_settings/shaders/class2/deferred/softenLightF.glsl | 11 ++++------- .../app_settings/shaders/class3/deferred/softenLightF.glsl | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 1fd54b5607..2982cd3e09 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -298,17 +298,14 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - vec2 checkoffset = normalize(ref2d)*9.0*(1.0-spec.a)*(checkerboard-0.5); - ref2d += checkoffset; + float checkoffset = 1.0 + (7.0*(1.0-spec.a))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. // We average two samples of diffuse (not of anything else) per // pixel to try to reduce aliasing some more. - // --------------------- - // ^ ^ ^ ^ ^ - // a . b o c . d check=0:avg(a,b) check=1:avg(c,d) - vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d).rgb + - texture2DRect(diffuseRect, ref2d + checkoffset*2.0).rgb); + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; float refshad = texture2DRect(lightMap, ref2d).r; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 45d921d861..e1e035411b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -301,17 +301,14 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - vec2 checkoffset = normalize(ref2d)*9.0*(1.0-spec.a)*(checkerboard-0.5); - ref2d += checkoffset; + float checkoffset = 1.0 + (7.0*(1.0-spec.a))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. // We average two samples of diffuse (not of anything else) per // pixel to try to reduce aliasing some more. - // --------------------- - // ^ ^ ^ ^ ^ - // a . b o c . d check=0:avg(a,b) check=1:avg(c,d) - vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d).rgb + - texture2DRect(diffuseRect, ref2d + checkoffset*2.0).rgb); + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; float refshad = texture2DRect(lightMap, ref2d).r; -- cgit v1.3 From 12e0a745dd97b7bd5a10ee01dec3e5d3055b515c Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 22 Apr 2010 21:33:10 +0100 Subject: ssreflections: dampen/blur ssreflections rather more. --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 01d18cdcde..bf5dd4155c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -299,7 +299,7 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - float checkoffset = 1.0 + (7.0*(1.0-spec.a))*(checkerboard-0.5); + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); ref2d += vec2(checkoffset, checkoffset); ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. @@ -324,6 +324,7 @@ void main() float refmod = min(refapprop, reflit); vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 2982cd3e09..28cfc6322e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -298,7 +298,7 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - float checkoffset = 1.0 + (7.0*(1.0-spec.a))*(checkerboard-0.5); + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); ref2d += vec2(checkoffset, checkoffset); ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. @@ -324,6 +324,7 @@ void main() float refmod = min(refapprop, reflit); vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index e1e035411b..9f94b9e8ea 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -301,7 +301,8 @@ void main() // The goal of the blur is to soften reflections in surfaces // with low shinyness, and also to disguise our lameness. float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - float checkoffset = 1.0 + (7.0*(1.0-spec.a))*(checkerboard-0.5); + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); ref2d += tc.xy; // use as offset from destination // Get attributes from the 2D guess point. @@ -327,6 +328,7 @@ void main() float refmod = min(refapprop, reflit); vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; -- cgit v1.3 From f972cc4be952abc943f9d289533c9951ce4dc839 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 23 Apr 2010 13:37:03 +0100 Subject: Restore a bit of the non-deferred renderer's sun/moon waterglow in deferred rendering. This also adds a slight pinch of glow to shiny sun-spots. So be it. (transplanted from 5a0d9e5b5cfb2ecd96685f0275ab8e999ab86263) --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 4 +++- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 4 +++- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index bf5dd4155c..65540ad6fe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -270,6 +270,7 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; + float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -285,6 +286,7 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -334,5 +336,5 @@ void main() col = scaleSoftClip(col); gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + gl_FragColor.a = glowresult; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 28cfc6322e..67ef3d5280 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -269,6 +269,7 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; + float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -284,6 +285,7 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -334,5 +336,5 @@ void main() col = scaleSoftClip(col); gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + gl_FragColor.a = glowresult; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 9f94b9e8ea..b5c6693d3b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -272,6 +272,7 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; + float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -287,6 +288,7 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -340,7 +342,7 @@ void main() gl_FragColor.rgb = col; //gl_FragColor.rgb = gi_col.rgb; - gl_FragColor.a = 0.0; + gl_FragColor.a = glowresult; //gl_FragColor.rg = scol_ambocc.rg; //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; -- cgit v1.3 From f313196363085de2eb8f3a4fd33abeb5617204c4 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Fri, 23 Apr 2010 17:35:32 +0100 Subject: Backed out changeset 90f0ce75b2d7 --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 4 +--- indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 4 +--- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 65540ad6fe..bf5dd4155c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -270,7 +270,6 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; - float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -286,7 +285,6 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; - glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -336,5 +334,5 @@ void main() col = scaleSoftClip(col); gl_FragColor.rgb = col; - gl_FragColor.a = glowresult; + gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 67ef3d5280..28cfc6322e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -269,7 +269,6 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; - float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -285,7 +284,6 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; - glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -336,5 +334,5 @@ void main() col = scaleSoftClip(col); gl_FragColor.rgb = col; - gl_FragColor.a = glowresult; + gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index b5c6693d3b..9f94b9e8ea 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -272,7 +272,6 @@ void main() vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; - float glowresult = 0.0; calcAtmospherics(pos.xyz, ambocc); @@ -288,7 +287,6 @@ void main() vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; - glowresult = 0.08 * dot(dumbshiny.rgb, spec.rgb); // screen-space cheap fakey reflection map // @@ -342,7 +340,7 @@ void main() gl_FragColor.rgb = col; //gl_FragColor.rgb = gi_col.rgb; - gl_FragColor.a = glowresult; + gl_FragColor.a = 0.0; //gl_FragColor.rg = scol_ambocc.rg; //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; -- cgit v1.3 From eb283701afc7ecbe3009a9fb75be1dcb222a383b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 4 May 2010 00:45:28 -0500 Subject: Deferred pipeline integration of rigged attachments and cleanup. --- indra/llrender/llvertexbuffer.h | 2 +- .../shaders/class1/deferred/alphaF.glsl | 5 +- .../shaders/class1/deferred/alphaV.glsl | 2 +- .../shaders/class1/deferred/avatarAlphaV.glsl | 4 +- .../shaders/class1/deferred/diffuseV.glsl | 2 +- .../shaders/class2/deferred/alphaF.glsl | 2 +- indra/newview/lldrawpoolavatar.cpp | 302 +++++++++++++++------ indra/newview/lldrawpoolavatar.h | 51 +++- indra/newview/lldrawpoolbump.cpp | 27 +- indra/newview/lldrawpoolbump.h | 7 +- indra/newview/llviewershadermgr.cpp | 36 ++- indra/newview/llviewershadermgr.h | 2 + indra/newview/llvovolume.cpp | 15 + 13 files changed, 359 insertions(+), 98 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 225237215c..d1700aa54a 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -190,7 +190,7 @@ public: U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } S32 getStride() const { return mStride; } - S32 getTypeMask() const { return mTypeMask; } + U32 getTypeMask() const { return mTypeMask; } BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } S32 getSize() const { return mNumVerts*mStride; } S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index fea2e16090..6f027de6a2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -22,7 +22,6 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; -varying vec3 vary_light; uniform mat4 inv_proj; @@ -55,8 +54,8 @@ void main() color.rgb = scaleSoftClip(color.rgb); - //gl_FragColor = gl_Color; - gl_FragColor = color; + gl_FragColor = gl_Color; + //gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); //gl_FragColor = vec4(1,0,1,1)*shadow; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 04e556c11a..43200f1b07 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -36,7 +36,7 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias); + vary_position = pos.xyz; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index 650fbcc3f5..da1dafda36 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -17,7 +17,7 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec4 vary_position; +varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; @@ -41,7 +41,7 @@ void main() norm = normalize(norm); gl_Position = gl_ProjectionMatrix * pos; - vary_position = pos; + vary_position = pos.xyz; vary_normal = norm; calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index b458842657..44468cdfa2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -13,7 +13,7 @@ void main() gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_nomral = normalize(gl_NormalMatrix * gl_Normal); + vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 665fe16b43..fa6b4e2afb 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -115,7 +115,7 @@ void main() //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1)*shadow; + //gl_FragColor = vec4(1,shadow,1,1); } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 866aea42c4..ac599caa5b 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -63,6 +63,8 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +static bool is_deferred_render = false; + extern BOOL gUseGLPick; F32 CLOTHING_GRAVITY_EFFECT = 0.7f; @@ -100,6 +102,18 @@ S32 specular_channel = -1; S32 diffuse_channel = -1; S32 cube_channel = -1; +static const U32 rigged_data_mask[] = { + LLDrawPoolAvatar::RIGGED_SIMPLE_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, + LLDrawPoolAvatar::RIGGED_SHINY_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK, + LLDrawPoolAvatar::RIGGED_GLOW_MASK, + LLDrawPoolAvatar::RIGGED_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK, +}; + static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow"); @@ -155,21 +169,17 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() //----------------------------------------------------------------------------- -S32 LLDrawPoolAvatar::getNumDeferredPasses() -{ - return getNumPasses(); -} void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); sSkipTransparent = TRUE; - + is_deferred_render = true; + if (LLPipeline::sImpostorRender) - { - beginDeferredSkinned(); - return; + { //impostor pass does not have rigid or impostor rendering + pass += 2; } switch (pass) @@ -184,7 +194,10 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) beginDeferredSkinned(); break; case 3: - beginDeferredRigged(); + beginDeferredRiggedSimple(); + break; + case 4: + beginDeferredRiggedBump(); break; } } @@ -194,11 +207,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) LLFastTimer t(FTM_RENDER_CHARACTERS); sSkipTransparent = FALSE; + is_deferred_render = false; if (LLPipeline::sImpostorRender) { - endDeferredSkinned(); - return; + pass += 2; } switch (pass) @@ -213,7 +226,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) endDeferredSkinned(); break; case 3: - endDeferredRigged(); + endDeferredRiggedSimple(); + break; + case 4: + endDeferredRiggedBump(); + break; } } @@ -224,10 +241,35 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { - return 1; + return 6; } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + beginPostDeferredAlpha(); + break; + case 1: + beginRiggedFullbright(); + break; + case 2: + beginRiggedFullbrightShiny(); + break; + case 3: + beginDeferredRiggedAlpha(); + break; + case 4: + beginRiggedFullbrightAlpha(); + break; + case 5: + beginRiggedGlow(); + break; + } +} + +void LLDrawPoolAvatar::beginPostDeferredAlpha() { sSkipOpaque = TRUE; sShaderLevel = mVertexShaderLevel; @@ -240,7 +282,49 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } +void LLDrawPoolAvatar::beginDeferredRiggedAlpha() +{ + sVertexProgram = &gDeferredSkinnedAlphaProgram; + gPipeline.bindDeferredShader(*sVertexProgram); + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::endDeferredRiggedAlpha() +{ + LLVertexBuffer::unbind(); + gPipeline.unbindDeferredShader(*sVertexProgram); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + switch (pass) + { + case 0: + endPostDeferredAlpha(); + break; + case 1: + endRiggedFullbright(); + break; + case 2: + endRiggedFullbrightShiny(); + break; + case 3: + endDeferredRiggedAlpha(); + break; + case 4: + endRiggedFullbrightAlpha(); + break; + case 5: + endRiggedGlow(); + break; + } +} + +void LLDrawPoolAvatar::endPostDeferredAlpha() { // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; @@ -254,7 +338,17 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - render(2); //pass 2 = skinned + const S32 actual_pass[] = + { //map post deferred pass numbers to what render() expects + 2, //skinned + 4, // rigged fullbright + 6, //rigged fullbright shiny + 7, //rigged alpha + 8, //rigged fullbright alpha + 9, //rigged glow + }; + + render(actual_pass[pass]); } @@ -288,6 +382,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) else { sVertexProgram = &gDeferredAttachmentShadowProgram; + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -352,7 +447,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) } else { - avatarp->renderSkinnedAttachments(); + renderRigged(avatarp, RIGGED_SIMPLE); + renderRigged(avatarp, RIGGED_ALPHA); + renderRigged(avatarp, RIGGED_FULLBRIGHT); + renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); + renderRigged(avatarp, RIGGED_SHINY); + renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); } } @@ -360,7 +460,7 @@ S32 LLDrawPoolAvatar::getNumPasses() { if (LLPipeline::sImpostorRender) { - return 1; + return 8; } else if (getVertexShaderLevel() > 0) { @@ -372,6 +472,19 @@ S32 LLDrawPoolAvatar::getNumPasses() } } +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ + if (LLPipeline::sImpostorRender) + { + return 3; + } + else + { + return 5; + } +} + + void LLDrawPoolAvatar::render(S32 pass) { LLFastTimer t(FTM_RENDER_CHARACTERS); @@ -391,9 +504,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) LLVertexBuffer::unbind(); if (LLPipeline::sImpostorRender) - { - beginSkinned(); - return; + { //impostor render does not have impostors or rigid rendering + pass += 2; } switch (pass) @@ -437,8 +549,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) if (LLPipeline::sImpostorRender) { - endSkinned(); - return; + pass += 2; } switch (pass) @@ -536,8 +647,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor() sVertexProgram = &gDeferredImpostorProgram; - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); @@ -774,18 +885,40 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny() } -void LLDrawPoolAvatar::beginDeferredRigged() +void LLDrawPoolAvatar::beginDeferredRiggedSimple() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; + diffuse_channel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endDeferredRiggedSimple() +{ + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + +void LLDrawPoolAvatar::beginDeferredRiggedBump() +{ + sVertexProgram = &gDeferredSkinnedBumpProgram; sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } -void LLDrawPoolAvatar::endDeferredRigged() +void LLDrawPoolAvatar::endDeferredRiggedBump() { LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->unbind(); LLVertexBuffer::sWeight4Loc = -1; + normal_channel = -1; + diffuse_channel = -1; sVertexProgram = NULL; } @@ -933,13 +1066,28 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 3) { - renderRiggedSimple(avatarp); + if (is_deferred_render) + { + renderDeferredRiggedSimple(avatarp); + } + else + { + renderRiggedSimple(avatarp); + } return; } if (pass == 4) { - renderRiggedFullbright(avatarp); + if (is_deferred_render) + { + renderDeferredRiggedBump(avatarp); + } + else + { + renderRiggedFullbright(avatarp); + } + return; } @@ -995,6 +1143,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) renderRiggedGlow(avatarp); gGL.setColorMask(true, false); gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; } @@ -1034,12 +1183,21 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face, U32 data_mask) +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { + U32 data_mask = 0; + for (U32 i = 0; i < face->mRiggedIndex.size(); ++i) + { + if (face->mRiggedIndex[i] > -1) + { + data_mask |= rigged_data_mask[i]; + } + } + LLVertexBuffer* buff = face->mVertexBuffer; if (!buff || - !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) || + buff->getTypeMask() != data_mask || buff->getRequestedVerts() != vol_face.mVertices.size()) { face->setGeomIndex(0); @@ -1067,7 +1225,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk } } -void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow) +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { @@ -1106,8 +1264,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data } const LLVolumeFace& vol_face = volume->getVolumeFace(te); - updateRiggedFaceVertexBuffer(face, skin, volume, vol_face, data_mask); + updateRiggedFaceVertexBuffer(face, skin, volume, vol_face); + U32 data_mask = rigged_data_mask[type]; + LLVertexBuffer* buff = face->mVertexBuffer; if (buff) @@ -1145,84 +1305,72 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data glColor4f(0,0,0,face->getTextureEntry()->getGlow()); } - gGL.getTexUnit(0)->bind(face->getTexture()); - buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + gGL.getTexUnit(diffuse_channel)->bind(face->getTexture()); + if (normal_channel > -1) + { + LLDrawPoolBump::bindBumpMap(face, normal_channel); + } + + if (face->mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + else + { + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } } } } -void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) +void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; + renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); +} - renderRigged(avatar, RIGGED_SIMPLE, data_mask); +void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_BUMP); } -void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; + renderRigged(avatar, RIGGED_SIMPLE); +} - renderRigged(avatar, RIGGED_FULLBRIGHT, data_mask); +void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT); } void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_SHINY, data_mask); + renderRigged(avatar, RIGGED_SHINY); } void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY, data_mask); + renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); } void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_NORMAL | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_ALPHA, data_mask); + renderRigged(avatar, RIGGED_ALPHA); } void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_COLOR | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA, data_mask); + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); } void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { - const U32 data_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0 | - LLVertexBuffer::MAP_WEIGHT4; - - renderRigged(avatar, RIGGED_GLOW, data_mask, true); + renderRigged(avatar, RIGGED_GLOW, true); } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 59f9cf7ddb..bab6f01480 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -103,6 +103,8 @@ public: void beginRiggedAlpha(); void beginRiggedFullbrightAlpha(); void beginRiggedGlow(); + void beginPostDeferredAlpha(); + void beginDeferredRiggedAlpha(); void endRigid(); void endImpostor(); @@ -114,24 +116,27 @@ public: void endRiggedAlpha(); void endRiggedFullbrightAlpha(); void endRiggedGlow(); + void endPostDeferredAlpha(); + void endDeferredRiggedAlpha(); void beginDeferredImpostor(); void beginDeferredRigid(); void beginDeferredSkinned(); - void beginDeferredRigged(); + void beginDeferredRiggedSimple(); + void beginDeferredRiggedBump(); void endDeferredImpostor(); void endDeferredRigid(); void endDeferredSkinned(); - void endDeferredRigged(); + void endDeferredRiggedSimple(); + void endDeferredRiggedBump(); void updateRiggedFaceVertexBuffer(LLFace* facep, const LLMeshSkinInfo* skin, LLVolume* volume, - const LLVolumeFace& vol_face, - U32 data_mask); + const LLVolumeFace& vol_face); - void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow = false); + void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); void renderRiggedSimple(LLVOAvatar* avatar); void renderRiggedAlpha(LLVOAvatar* avatar); void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); @@ -139,6 +144,8 @@ public: void renderRiggedShinySimple(LLVOAvatar* avatar); void renderRiggedFullbrightShiny(LLVOAvatar* avatar); void renderRiggedGlow(LLVOAvatar* avatar); + void renderDeferredRiggedSimple(LLVOAvatar* avatar); + void renderDeferredRiggedBump(LLVOAvatar* avatar); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -154,11 +161,43 @@ public: RIGGED_GLOW, RIGGED_ALPHA, RIGGED_FULLBRIGHT_ALPHA, + RIGGED_DEFERRED_BUMP, + RIGGED_DEFERRED_SIMPLE, NUM_RIGGED_PASSES, RIGGED_UNKNOWN, } eRiggedPass; - + typedef enum + { + RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK, + RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_BINORMAL | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + } eRiggedDataMask; + void addRiggedFace(LLFace* facep, U32 type); void removeRiggedFace(LLFace* facep); diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 2f449fa42f..906615ade8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -591,18 +591,37 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL // static BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { - LLViewerTexture* bump = NULL; - U8 bump_code = params.mBump; + return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel); +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) +{ + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + U8 bump_code = te->getBumpmap(); + return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel); + } + + return FALSE; +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel) +{ //Note: texture atlas does not support bump texture now. - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ; + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; if(!tex) { //if the texture is not a fetched texture return FALSE; } + LLViewerTexture* bump = NULL; + switch( bump_code ) { case BE_NO_BUMP: @@ -616,7 +635,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) { bump = gStandardBumpmapList[bump_code].mImage; - gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize); + gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize); } break; } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 89bbefe778..127c9efe85 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -93,7 +93,12 @@ public: /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); - BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLFace* face, S32 channel = -2); + +private: + static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel); + }; enum EBumpEffect diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index eafc52748e..e64fdfc0b4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -114,6 +114,8 @@ LLGLSLShader gDeferredEdgeProgram; LLGLSLShader gDeferredWaterProgram; LLGLSLShader gDeferredDiffuseProgram; LLGLSLShader gDeferredSkinnedDiffuseProgram; +LLGLSLShader gDeferredSkinnedBumpProgram; +LLGLSLShader gDeferredSkinnedAlphaProgram; LLGLSLShader gDeferredBumpProgram; LLGLSLShader gDeferredTerrainProgram; LLGLSLShader gDeferredTreeProgram; @@ -173,6 +175,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredLightProgram); mShaderList.push_back(&gDeferredMultiLightProgram); mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredSkinnedAlphaProgram); mShaderList.push_back(&gDeferredFullbrightProgram); mShaderList.push_back(&gDeferredPostGIProgram); mShaderList.push_back(&gDeferredEdgeProgram); @@ -591,6 +594,8 @@ void LLViewerShaderMgr::unloadShaders() gDeferredDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); mVertexShaderLevel[SHADER_LIGHTING] = 0; mVertexShaderLevel[SHADER_OBJECT] = 0; @@ -906,6 +911,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTreeProgram.unload(); gDeferredDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); + gDeferredSkinnedBumpProgram.unload(); + gDeferredSkinnedAlphaProgram.unload(); gDeferredBumpProgram.unload(); gDeferredImpostorProgram.unload(); gDeferredTerrainProgram.unload(); @@ -958,6 +965,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; + gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedBumpProgram.mShaderFiles.clear(); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; + gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; + gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); + } + if (success) { gDeferredBumpProgram.mName = "Deferred Bump Shader"; @@ -1176,7 +1210,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() 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.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index bb28cd7ec2..da16a38427 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -350,6 +350,8 @@ extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; extern LLGLSLShader gDeferredSkinnedDiffuseProgram; +extern LLGLSLShader gDeferredSkinnedBumpProgram; +extern LLGLSLShader gDeferredSkinnedAlphaProgram; extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e263f8d937..220634897e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3586,6 +3586,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } } } -- cgit v1.3 From 33c4d124ce60b2999efb73fc17dc996cb3c2a103 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Thu, 6 May 2010 13:53:52 +0100 Subject: EXT-6912 FIXED Deferred Rendering - shiny objects look like a projection instead of a reflection Disable screen-space shiny while I chew on it some more. (transplanted from bde80560117295f6b3e61f9b47f3bdea826945ca) --- indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl | 3 +++ indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 3 +++ indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 3 +++ 3 files changed, 9 insertions(+) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index bf5dd4155c..ef61491826 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -286,6 +286,7 @@ void main() float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + /* // screen-space cheap fakey reflection map // vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); @@ -325,6 +326,8 @@ void main() vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 28cfc6322e..bc84720b86 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -285,6 +285,7 @@ void main() float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + /* // screen-space cheap fakey reflection map // vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); @@ -325,6 +326,8 @@ void main() vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 9f94b9e8ea..5298079af7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -288,6 +288,7 @@ void main() float sa = dot(refnormpersp, vary_light.xyz); vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + /* // screen-space cheap fakey reflection map // vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); @@ -329,6 +330,8 @@ void main() vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; vec3 ssshiny = (refprod * spec.a); ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); // add the two types of shiny together col += (ssshiny + dumbshiny) * spec.rgb; -- cgit v1.3 From 49579bebdd274a88c2381c4cab3d09ecd393564d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 10 May 2010 13:00:36 -0500 Subject: Fix for wierd triangle shadow bug and fix for ATI hating deferred rendering. --- indra/llrender/llrender.cpp | 1 + .../shaders/class2/deferred/avatarAlphaV.glsl | 3 +- indra/newview/featuretable.txt | 1 + indra/newview/lldrawpoolavatar.cpp | 43 ++++++++++++---------- indra/newview/lldrawpoolavatar.h | 4 +- indra/newview/llviewerjointmesh.cpp | 30 ++++++++------- indra/newview/pipeline.cpp | 2 +- 7 files changed, 47 insertions(+), 37 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 43662fbb5c..2472339ec4 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -165,6 +165,7 @@ void LLTexUnit::enable(eTextureType type) if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) ) { activate(); + if (mCurrTexType != TT_NONE && !gGL.mDirty) { disable(); // Force a disable of a previous texture type if it's enabled. diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index f8dd1b7431..de423ee22a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -21,6 +21,7 @@ varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; +varying vec3 vary_fragcoord; uniform float near_clip; uniform float shadow_offset; @@ -77,7 +78,7 @@ void main() gl_FrontColor = col; gl_FogFragCoord = pos.z; - + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 1913f52499..74d14c49b0 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -57,6 +57,7 @@ RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 +RenderUseFBO 1 1 // diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index a49cf8781e..d1f4be71f5 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -62,6 +62,8 @@ static U32 sShaderLevel = 0; LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +S32 LLDrawPoolAvatar::sDiffuseChannel = 0; + static bool is_deferred_render = false; @@ -99,7 +101,6 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; -S32 diffuse_channel = -1; S32 cube_channel = -1; static const U32 rigged_data_mask[] = { @@ -279,6 +280,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha() gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } @@ -286,7 +288,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedAlpha() { sVertexProgram = &gDeferredSkinnedAlphaProgram; gPipeline.bindDeferredShader(*sVertexProgram); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); gPipeline.enableLightsDynamic(); } @@ -295,6 +297,7 @@ void LLDrawPoolAvatar::endDeferredRiggedAlpha() { LLVertexBuffer::unbind(); gPipeline.unbindDeferredShader(*sVertexProgram); + sDiffuseChannel = 0; LLVertexBuffer::sWeight4Loc = -1; sVertexProgram = NULL; } @@ -332,7 +335,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha() disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); gPipeline.unbindDeferredShader(*sVertexProgram); - + sDiffuseChannel = 0; sShaderLevel = mVertexShaderLevel; } @@ -382,7 +385,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass) else { sVertexProgram = &gDeferredAttachmentShadowProgram; - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -596,7 +599,7 @@ void LLDrawPoolAvatar::beginImpostor() } gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - diffuse_channel = 0; + sDiffuseChannel = 0; } void LLDrawPoolAvatar::endImpostor() @@ -649,7 +652,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); } @@ -772,7 +775,7 @@ void LLDrawPoolAvatar::endSkinned() void LLDrawPoolAvatar::beginRiggedSimple() { sVertexProgram = &gSkinnedObjectSimpleProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; gSkinnedObjectSimpleProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -788,7 +791,7 @@ void LLDrawPoolAvatar::endRiggedSimple() void LLDrawPoolAvatar::beginRiggedAlpha() { sVertexProgram = &gSkinnedObjectSimpleProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -805,7 +808,7 @@ void LLDrawPoolAvatar::endRiggedAlpha() void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -821,7 +824,7 @@ void LLDrawPoolAvatar::endRiggedFullbrightAlpha() void LLDrawPoolAvatar::beginRiggedGlow() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -837,7 +840,7 @@ void LLDrawPoolAvatar::endRiggedGlow() void LLDrawPoolAvatar::beginRiggedFullbright() { sVertexProgram = &gSkinnedObjectFullbrightProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; gSkinnedObjectFullbrightProgram.bind(); LLVertexBuffer::sWeight4Loc = gSkinnedObjectFullbrightProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -854,14 +857,14 @@ void LLDrawPoolAvatar::beginRiggedShinySimple() { sVertexProgram = &gSkinnedObjectShinySimpleProgram; sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedShinySimple() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); sVertexProgram->unbind(); sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; @@ -871,14 +874,14 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny() { sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; sVertexProgram->bind(); - LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } void LLDrawPoolAvatar::endRiggedFullbrightShiny() { LLVertexBuffer::unbind(); - LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, diffuse_channel, cube_channel, false); + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); sVertexProgram->unbind(); sVertexProgram = NULL; LLVertexBuffer::sWeight4Loc = -1; @@ -888,7 +891,7 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny() void LLDrawPoolAvatar::beginDeferredRiggedSimple() { sVertexProgram = &gDeferredSkinnedDiffuseProgram; - diffuse_channel = 0; + sDiffuseChannel = 0; sVertexProgram->bind(); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -906,7 +909,7 @@ void LLDrawPoolAvatar::beginDeferredRiggedBump() sVertexProgram = &gDeferredSkinnedBumpProgram; sVertexProgram->bind(); normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } @@ -918,7 +921,7 @@ void LLDrawPoolAvatar::endDeferredRiggedBump() sVertexProgram->unbind(); LLVertexBuffer::sWeight4Loc = -1; normal_channel = -1; - diffuse_channel = -1; + sDiffuseChannel = 0; sVertexProgram = NULL; } @@ -1047,7 +1050,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); + avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel); } return; } @@ -1305,7 +1308,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) glColor4f(0,0,0,face->getTextureEntry()->getGlow()); } - gGL.getTexUnit(diffuse_channel)->bind(face->getTexture()); + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index bab6f01480..4a5b009412 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -1,4 +1,4 @@ -/** + /** * @file lldrawpoolavatar.h * @brief LLDrawPoolAvatar class definition * @@ -205,6 +205,8 @@ public: static BOOL sSkipOpaque; static BOOL sSkipTransparent; + static S32 sDiffuseChannel; + static LLGLSLShader* sVertexProgram; }; diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index fb6cc8d790..deb3d8fd97 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -516,6 +516,8 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) U32 triangle_count = 0; + S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; + stop_glerror(); //---------------------------------------------------------------- @@ -541,7 +543,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); + gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); if (mIsTransparent) { @@ -550,18 +552,18 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && mLayerSet ) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(0)->bind(mLayerSet->getComposite()); + gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); } else { - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } } else @@ -571,25 +573,25 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { old_mode = mTexture->getAddressMode(); } - gGL.getTexUnit(0)->bind(mTexture.get()); - gGL.getTexUnit(0)->bind(mTexture); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(diffuse_channel)->bind(mTexture.get()); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } else { - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } if (gRenderForSelect) { if (isTransparent()) { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); + gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(diffuse_channel)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); } else { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); } } @@ -626,13 +628,13 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if (mTestImageName) { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull() && !is_dummy) { - gGL.getTexUnit(0)->bind(mTexture); - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode); } return triangle_count; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9bcec9e13d..da01ae44db 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7778,7 +7778,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector 0,1, 1,2, 2,3, - 3,1, + 3,0, 4,5, 5,6, -- cgit v1.3 From 45aa68fde1fd8c89fa5e7766e1f50b14a577638f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 11 May 2010 00:57:30 -0500 Subject: EXT-7225 Fix for busted projector shadows under certain settings. --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a2b88d17d4..623f0f3b01 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6615,7 +6615,7 @@ Type F32 Value - 0.01 + -0.01 RenderShadowResolutionScale diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 46db3c990c..413835515a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -77,6 +77,7 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { + stc.z += spot_shadow_offset; stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; @@ -181,7 +182,7 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = 1.0; - spos.xyz = shadow_pos+offset*spot_shadow_offset; + spos = vec4(shadow_pos, 1.0); //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; -- cgit v1.3 From 9950c22a5568b55ff896734185e0e1181a93fcf0 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 12 May 2010 03:59:01 -0500 Subject: Fix for fullbright bump not working in deferred render. Fix for shadow artifacts around split frusta. Tweak for shadow aliasing with projectors. Fix for crash on exit in mesh thread. --- indra/newview/app_settings/settings.xml | 6 +- .../shaders/class2/deferred/sunLightF.glsl | 3 +- indra/newview/lldrawpool.h | 1 + indra/newview/lldrawpoolbump.cpp | 44 ++- indra/newview/lldrawpoolbump.h | 8 +- indra/newview/lldrawpoolsimple.cpp | 3 +- indra/newview/llviewercontrol.cpp | 3 + indra/newview/llviewerdisplay.cpp | 8 +- indra/newview/llvovolume.cpp | 39 +- indra/newview/pipeline.cpp | 394 ++++++++++++++------- indra/newview/pipeline.h | 30 +- 11 files changed, 364 insertions(+), 175 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 623f0f3b01..4c72b03b2e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6604,7 +6604,7 @@ Type F32 Value - -0.0005 + 0.0 RenderSpotShadowOffset @@ -6615,7 +6615,7 @@ Type F32 Value - -0.01 + 0.04 RenderShadowResolutionScale @@ -6751,7 +6751,7 @@ Type F32 Value - 1 + 8 RenderDeferred diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 413835515a..794c4d2761 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -77,7 +77,6 @@ float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { - stc.z += spot_shadow_offset; stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; @@ -182,7 +181,7 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = 1.0; - spos = vec4(shadow_pos, 1.0); + spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index e46d503db3..ec870f59c6 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -133,6 +133,7 @@ public: PASS_FULLBRIGHT_SHINY, PASS_SHINY, PASS_BUMP, + PASS_POST_BUMP, PASS_GLOW, PASS_ALPHA, PASS_ALPHA_MASK, diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 906615ade8..967ce3fc5c 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -659,9 +659,9 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi } //static -void LLDrawPoolBump::beginBump() +void LLDrawPoolBump::beginBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -704,9 +704,9 @@ void LLDrawPoolBump::beginBump() } //static -void LLDrawPoolBump::renderBump() +void LLDrawPoolBump::renderBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -719,13 +719,13 @@ void LLDrawPoolBump::renderBump() /// Get rid of z-fighting with non-bump pass. LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); glPolygonOffset(-1.0f, -1.0f); - renderBump(LLRenderPass::PASS_BUMP, sVertexMask); + renderBump(pass, sVertexMask); } //static -void LLDrawPoolBump::endBump() +void LLDrawPoolBump::endBump(U32 pass) { - if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP)) + if (!gPipeline.hasRenderBatches(pass)) { return; } @@ -808,17 +808,41 @@ void LLDrawPoolBump::renderDeferred(S32 pass) void LLDrawPoolBump::beginPostDeferredPass(S32 pass) { - beginFullbrightShiny(); + switch (pass) + { + case 0: + beginFullbrightShiny(); + break; + case 1: + beginBump(LLRenderPass::PASS_POST_BUMP); + break; + } } void LLDrawPoolBump::endPostDeferredPass(S32 pass) { - endFullbrightShiny(); + switch (pass) + { + case 0: + endFullbrightShiny(); + break; + case 1: + endBump(LLRenderPass::PASS_POST_BUMP); + break; + } } void LLDrawPoolBump::renderPostDeferred(S32 pass) { - renderFullbrightShiny(); + switch (pass) + { + case 0: + renderFullbrightShiny(); + break; + case 1: + renderBump(LLRenderPass::PASS_POST_BUMP); + break; + } } //////////////////////////////////////////////////////////////// diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 127c9efe85..a75653e68e 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -76,9 +76,9 @@ public: void renderFullbrightShiny(); void endFullbrightShiny(); - void beginBump(); - void renderBump(); - void endBump(); + void beginBump(U32 pass = LLRenderPass::PASS_BUMP); + void renderBump(U32 pass = LLRenderPass::PASS_BUMP); + void endBump(U32 pass = LLRenderPass::PASS_BUMP); static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); @@ -88,7 +88,7 @@ public: /*virtual*/ void endDeferredPass(S32 pass); /*virtual*/ void renderDeferred(S32 pass); - virtual S32 getNumPostDeferredPasses() { return 1; } + virtual S32 getNumPostDeferredPasses() { return 2; } /*virtual*/ void beginPostDeferredPass(S32 pass); /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index c8e6f95ab6..91191287cd 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -151,7 +151,8 @@ void LLDrawPoolSimple::render(S32 pass) renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); if (LLPipeline::sRenderDeferred) - { + { //if deferred rendering is enabled, bump faces aren't reigstered as simple + //render bump faces here as simple so bump faces will appear under water renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask()); } } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index a8004f26ed..701df86de4 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -505,6 +505,9 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); + gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 360cee9f73..3cd7af6433 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -946,9 +946,10 @@ void render_hud_attachments() bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); //only render hud objects - U32 mask = gPipeline.getRenderTypeMask(); + gPipeline.pushRenderTypeMask(); + // turn off everything - gPipeline.setRenderTypeMask(0); + gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); // turn on HUD gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); // turn on HUD particles @@ -1002,7 +1003,8 @@ void render_hud_attachments() render_hud_elements(); //restore type mask - gPipeline.setRenderTypeMask(mask); + gPipeline.popRenderTypeMask(); + if (has_ui) { gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index aaa6e8007f..b120f5abf3 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3349,7 +3349,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, model_mat = &(drawable->getRegion()->mRenderMatrix); } - U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); + + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); @@ -4052,66 +4053,76 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: && group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD && LLPipeline::sRenderBump && te->getShiny()) - { + { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim+shiny registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (LLPipeline::sRenderDeferred) - { + { //deferred rendering if (te->getFullbright()) - { + { //register in post deferred fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } } else if (te->getBumpmap()) - { + { //register in deferred bump pass registerFace(group, facep, LLRenderPass::PASS_BUMP); } else - { + { //register in deferred simple pass (deferred simple includes shiny) llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } else if (fullbright) - { + { //not deferred, register in standard fullbright shiny pass registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); } else - { + { //not deferred or fullbright, register in standard shiny pass registerFace(group, facep, LLRenderPass::PASS_SHINY); } } else - { + { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { + { //invisiprim registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } else if (fullbright) - { + { //fullbright registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } } else { if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) - { + { //non-shiny or fullbright deferred bump registerFace(group, facep, LLRenderPass::PASS_BUMP); } else - { + { //all around simple llassert(mask & LLVertexBuffer::MAP_NORMAL); registerFace(group, facep, LLRenderPass::PASS_SIMPLE); } } + //not sure why this is here -- shiny HUD attachments maybe? -- davep 5/11/2010 if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) { registerFace(group, facep, LLRenderPass::PASS_SHINY); } } + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 if (!is_alpha && !LLPipeline::sRenderDeferred) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index da01ae44db..a066b7fc0d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -331,7 +331,6 @@ LLPipeline::LLPipeline() : mInitialized(FALSE), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), - mRenderTypeMask(0), mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), @@ -385,7 +384,11 @@ void LLPipeline::init() LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); - mRenderTypeMask = 0xffffffff; // All render types start on + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = TRUE; //all rendering types start enabled + } + mRenderDebugFeatureMask = 0xffffffff; // All debugging features on mRenderDebugMask = 0; // All debug starts off @@ -2217,14 +2220,13 @@ static LLFastTimer::DeclareTimer FTM_RESET_DRAWORDER("Reset Draw Order"); void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { - const U32 face_mask = (1 << LLPipeline::RENDER_TYPE_AVATAR) | - (1 << LLPipeline::RENDER_TYPE_GROUND) | - (1 << LLPipeline::RENDER_TYPE_TERRAIN) | - (1 << LLPipeline::RENDER_TYPE_TREE) | - (1 << LLPipeline::RENDER_TYPE_SKY) | - (1 << LLPipeline::RENDER_TYPE_WATER); - - if (mRenderTypeMask & face_mask) + if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::END_RENDER_TYPES)) { //clear faces from face pools LLFastTimer t(FTM_RESET_DRAWORDER); @@ -5072,8 +5074,7 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light) //static void LLPipeline::toggleRenderType(U32 type) { - U32 bit = (1< 0) { //mask out selected geometry based on reflection detail if (detail < 4) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_PARTICLES); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); if (detail < 3) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_AVATAR); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); if (detail < 2) { - mRenderTypeMask &= ~(1 << LLPipeline::RENDER_TYPE_VOLUME); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES); } } } @@ -7418,18 +7426,17 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) stateSort(camera, ref_result); } - ref_mask = mRenderTypeMask; - mRenderTypeMask = mask; - } - if (LLDrawPoolWater::sNeedsDistortionUpdate) - { - mRenderTypeMask = ref_mask; - if (gSavedSettings.getS32("RenderReflectionDetail") > 0) + if (LLDrawPoolWater::sNeedsDistortionUpdate) { - gPipeline.grabReferences(ref_result); - LLGLUserClipPlane clip_plane(plane, mat, projection); - renderGeom(camera); + if (gSavedSettings.getS32("RenderReflectionDetail") > 0) + { + gPipeline.grabReferences(ref_result); + LLGLUserClipPlane clip_plane(plane, mat, projection); + renderGeom(camera); + } } + + gPipeline.popRenderTypeMask(); } glCullFace(GL_BACK); glPopMatrix(); @@ -7443,18 +7450,20 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (last_update) { camera.setFar(camera_in.getFar()); - mRenderTypeMask = type_mask & (~(1<cameraUnderWater() ? FALSE : TRUE; if (LLPipeline::sUnderWaterRender) { - mRenderTypeMask &= ~((1<setup3DViewport(); - mRenderTypeMask = type_mask; + gPipeline.popRenderTypeMask(); LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd)); @@ -7951,21 +7960,22 @@ void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vectorisMuted(avatar->getID()); + pushRenderTypeMask(); + if (muted) { - mask = 1 << LLPipeline::RENDER_TYPE_AVATAR; + andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); } else { - mask = (1<endAlphaGroups(); } +BOOL LLPipeline::hasRenderType(const U32 type) const +{ + return mRenderTypeEnabled[type]; +} + +void LLPipeline::setRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = TRUE; + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + +BOOL LLPipeline::hasAnyRenderType(U32 type, ...) const +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + return TRUE; + } + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + return FALSE; +} + +void LLPipeline::pushRenderTypeMask() +{ + std::string cur_mask; + cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.push(cur_mask); +} + +void LLPipeline::popRenderTypeMask() +{ + if (mRenderTypeEnableStack.empty()) + { + llerrs << "Depleted render type stack." << llendl; + } + + memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.pop(); +} + +void LLPipeline::andRenderTypeMask(U32 type, ...) +{ + va_list args; + + BOOL tmp[NUM_RENDER_TYPES]; + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + tmp[i] = FALSE; + } + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + tmp[type] = TRUE; + } + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } + + for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = tmp[i]; + } + +} + +void LLPipeline::clearRenderTypeMask(U32 type, ...) +{ + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = FALSE; + + type = va_arg(args, U32); + } + va_end(args); + + if (type > END_RENDER_TYPES) + { + llerrs << "Invalid render type." << llendl; + } +} + diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index be878ae667..2c14b94847 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -46,6 +46,8 @@ #include "lldrawable.h" #include "llrendertarget.h" +#include + class LLViewerTexture; class LLEdge; class LLFace; @@ -279,12 +281,25 @@ public: LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); + void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); - BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< mRenderTypeEnableStack; + U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; -- cgit v1.3 From 514186eee31c4bc44e7bc021bb9c526e4138cb07 Mon Sep 17 00:00:00 2001 From: Tofu Linden Date: Sun, 9 May 2010 15:02:10 +0100 Subject: Rejig deferred normal-map packing a little, to double its accuracy for free. (transplanted from bf541483d9074c18c6d4f4bd19caf0de82013cbf) --- .../newview/app_settings/shaders/class1/deferred/avatarF.glsl | 3 ++- .../app_settings/shaders/class1/deferred/blurLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl | 3 ++- .../app_settings/shaders/class1/deferred/diffuseF.glsl | 3 ++- indra/newview/app_settings/shaders/class1/deferred/giF.glsl | 3 ++- .../shaders/class1/deferred/multiPointLightF.glsl | 3 ++- .../app_settings/shaders/class1/deferred/pointLightF.glsl | 3 ++- .../newview/app_settings/shaders/class1/deferred/postgiF.glsl | 9 +++++---- .../app_settings/shaders/class1/deferred/softenLightF.glsl | 6 ++++-- .../app_settings/shaders/class1/deferred/spotLightF.glsl | 3 ++- .../app_settings/shaders/class1/deferred/sunLightSSAOF.glsl | 3 ++- .../app_settings/shaders/class1/deferred/terrainF.glsl | 3 ++- indra/newview/app_settings/shaders/class1/deferred/treeF.glsl | 3 ++- .../newview/app_settings/shaders/class1/deferred/waterF.glsl | 2 +- .../app_settings/shaders/class2/deferred/blurLightF.glsl | 3 ++- indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl | 11 ++++++++--- .../app_settings/shaders/class2/deferred/multiSpotLightF.glsl | 3 ++- .../app_settings/shaders/class2/deferred/softenLightF.glsl | 7 +++++-- .../app_settings/shaders/class2/deferred/spotLightF.glsl | 3 ++- .../app_settings/shaders/class2/deferred/sunLightF.glsl | 3 ++- .../app_settings/shaders/class2/deferred/sunLightSSAOF.glsl | 3 ++- .../app_settings/shaders/class3/deferred/giDownsampleF.glsl | 10 ++++++---- indra/newview/app_settings/shaders/class3/deferred/giF.glsl | 3 ++- .../app_settings/shaders/class3/deferred/softenLightF.glsl | 7 +++++-- indra/newview/app_settings/shaders/class3/deferred/treeF.glsl | 3 ++- 25 files changed, 70 insertions(+), 36 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 75df388941..afbe08a579 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -20,6 +20,7 @@ void main() gl_FragData[0] = vec4(diff.rgb, 0.0); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 0fad5b4b50..d1c5d7cb19 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -37,7 +37,8 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 6e38caf5ef..2197744a37 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -24,5 +24,6 @@ void main() gl_FragData[0] = vec4(col, 0.0); gl_FragData[1] = gl_Color.aaaa; // spec //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested - gl_FragData[2] = vec4(normalize(tnorm)*0.5+0.5, 0.0); + vec3 nvn = normalize(tnorm); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 112103956d..3803119cda 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -15,5 +15,6 @@ void main() gl_FragData[0] = vec4(col, 0.0); gl_FragData[1] = gl_Color.aaaa; // spec //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl index b351eec6e5..d4b153c4af 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -159,7 +159,8 @@ void main() { vec2 pos_screen = vary_fragcoord.xy; vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm gl_FragData[0].xyz = giAmbient(pos, norm); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 797b9e9f3b..e1715eb4f9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -53,7 +53,8 @@ void main() discard; } - vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz*2.0-1.0); + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 78256e20cc..3aecbc5f23 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -55,7 +55,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float da = dot(norm, lv); if (da < 0.0) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 9612aee405..bd554c2d84 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -38,10 +38,10 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; vec2 dlt = kern_scale * delta/(1.0+norm.xy*norm.xy); dlt /= max(-pos.z*dist_factor, 1.0); @@ -51,9 +51,10 @@ void main() for (int i = 0; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz; + sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm - float d = dot(norm.xyz, sampNorm); + float d = dot(norm.xyz, sampNorm); if (d > 0.8) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index ef61491826..bef91e735d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -259,7 +259,8 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).a; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -310,7 +311,8 @@ void main() texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; - vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm // figure out how appropriate our guess actually was float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); // darken reflections from points which face away from the reflected ray - our guess was a back-face diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index f320dbb400..1b95b253c3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -68,7 +68,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index 7450817ea7..cdbed4b791 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -114,7 +114,8 @@ void main() vec4 pos = getPosition(pos_screen); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm gl_FragColor[0] = 1.0; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 3cccfb7202..fa0a60c98d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -29,6 +29,7 @@ void main() gl_FragData[0] = vec4(outColor.rgb, 0.0); gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 258acee08c..5b33ea5bfe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -14,5 +14,6 @@ void main() vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index ceb7e0fb56..361ae8dc84 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -137,5 +137,5 @@ void main() gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - gl_FragData[2] = vec4(screenspacewavef*0.5+0.5, screenspacewavef.z*0.5); // normal, displace + gl_FragData[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace } diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl index 0fad5b4b50..d1c5d7cb19 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -37,7 +37,8 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(vary_fragcoord.xy).xyz; vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl index 02beddd43b..e32e9f4b32 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -31,7 +31,8 @@ float getDepth(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float depth = getDepth(vary_fragcoord.xy); vec2 tc = vary_fragcoord.xy; @@ -46,8 +47,12 @@ void main() de = step(depth_cutoff, de); vec2 ne; - ne.x = dot(texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb*2.0-1.0, norm); - ne.y = dot(texture2DRect(normalMap, tc+vec2(sc,sc)).rgb*2.0-1.0, norm); + vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; + nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm + ne.x = dot(nexnorm, norm); + vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; + neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm + ne.y = dot(neynorm, norm); ne = 1.0-ne; diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index 5308e5bb1e..22ffb58c63 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -129,7 +129,8 @@ void main() shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index bc84720b86..fd6ae2b960 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -258,7 +258,8 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).a; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -310,7 +311,9 @@ void main() float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; float refshad = texture2DRect(lightMap, ref2d).r; - vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm + refn = normalize(refn); // figure out how appropriate our guess actually was float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); // darken reflections from points which face away from the reflected ray - our guess was a back-face diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index eeaecc157f..8a90199b7c 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -82,7 +82,8 @@ void main() discard; } - vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm norm = normalize(norm); float l_dist = -dot(lv, proj_n); diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 794c4d2761..7423347346 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -104,8 +104,9 @@ void main() vec4 pos = getPosition(pos_screen); vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm float displace = nmap4.w; - vec3 norm = nmap4.xyz*2.0-1.0; + vec3 norm = nmap4.xyz; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index a0dfc96f14..4e33a1af45 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -164,8 +164,9 @@ void main() vec4 pos = getPosition(pos_screen); vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm float displace = nmap4.w; - vec3 norm = nmap4.xyz*2.0-1.0; + vec3 norm = nmap4.xyz; /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL { diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl index 7325825d6d..66606233cd 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -44,7 +44,8 @@ float getDepth(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float depth = getDepth(vary_fragcoord.xy); vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; @@ -56,9 +57,10 @@ void main() for (int i = 0; i < kern_length; i++) { vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; - vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz*2.0-1.0; - - float d = dot(norm.xyz, sampNorm); + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz; + sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm + + float d = dot(norm.xyz, sampNorm); if (d > 0.5) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl index 939710cb56..1b8354dbd1 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -178,7 +178,8 @@ void main() float rad = gi_range*0.5; - vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float dist = max(length(pos.xyz)-rad, 0.0); float da = clamp(1.0-dist/rad, 0.0, 1.0); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 5298079af7..c88edd0a60 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -259,7 +259,8 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = texture2DRect(depthMap, tc.xy).a; vec3 pos = getPosition_d(tc, depth).xyz; - vec3 norm = texture2DRect(normalMap, tc).xyz*2.0-1.0; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); @@ -314,7 +315,9 @@ void main() float refdepth = texture2DRect(depthMap, ref2d).a; vec3 refpos = getPosition_d(ref2d, refdepth).xyz; float refshad = texture2DRect(lightMap, ref2d).r; - vec3 refn = normalize(texture2DRect(normalMap, ref2d).rgb * 2.0 - 1.0); + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm + refn = normalize(refn); // figure out how appropriate our guess actually was float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); // darken reflections from points which face away from the reflected ray - our guess was a back-face diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl index 258acee08c..5b33ea5bfe 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -14,5 +14,6 @@ void main() vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal)*0.5+0.5, 0.0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } -- cgit v1.3 From 71de5f622a7917f78823a7e7840194e1b0f8f070 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 26 Aug 2010 14:23:12 -0500 Subject: Add missing files from viewer-experimental --- indra/cmake/GLOD.cmake | 9 + indra/cmake/LLConvexDecomposition.cmake | 16 + indra/llmath/llmatrix3a.cpp | 140 + indra/llmath/llmatrix3a.h | 134 + indra/llmath/llmatrix3a.inl | 125 + indra/llmath/llmatrix4a.h | 149 + indra/llmath/llquaternion2.h | 111 + indra/llmath/llquaternion2.inl | 108 + indra/llmath/llsimdmath.h | 95 + indra/llmath/llsimdtypes.h | 130 + indra/llmath/llsimdtypes.inl | 163 + indra/llmath/llvector4a.cpp | 228 ++ indra/llmath/llvector4a.h | 331 ++ indra/llmath/llvector4a.inl | 599 ++++ indra/llmath/llvector4logical.h | 130 + indra/llmath/llvolumeoctree.cpp | 208 ++ indra/llmath/llvolumeoctree.h | 138 + indra/llprimitive/llmodel.cpp | 1695 ++++++++++ indra/llprimitive/llmodel.h | 179 ++ .../shaders/class1/avatar/objectSkinV.glsl | 30 + .../shaders/class1/deferred/alphaSkinnedV.glsl | 75 + .../shaders/class1/deferred/attachmentShadowF.glsl | 16 + .../shaders/class1/deferred/attachmentShadowV.glsl | 25 + .../shaders/class1/deferred/bumpSkinnedV.glsl | 37 + .../shaders/class1/deferred/diffuseSkinnedV.glsl | 33 + .../lighting/lightFullbrightShinyWaterF.glsl | 15 + .../class1/objects/fullbrightShinySkinnedV.glsl | 39 + .../class1/objects/fullbrightShinyWaterF.glsl | 13 + .../shaders/class1/objects/fullbrightSkinnedV.glsl | 37 + .../class1/objects/shinySimpleSkinnedV.glsl | 39 + .../shaders/class1/objects/simpleSkinnedV.glsl | 39 + .../shaders/class2/deferred/alphaSkinnedV.glsl | 84 + .../lighting/lightFullbrightShinyWaterF.glsl | 29 + indra/newview/llfloaterimportcollada.cpp | 1116 +++++++ indra/newview/llfloaterimportcollada.h | 143 + indra/newview/llfloatermodelpreview.cpp | 3382 ++++++++++++++++++++ indra/newview/llfloatermodelpreview.h | 275 ++ indra/newview/llmeshreduction.cpp | 291 ++ indra/newview/llmeshreduction.h | 59 + indra/newview/llmeshrepository.cpp | 2676 ++++++++++++++++ indra/newview/llmeshrepository.h | 471 +++ 41 files changed, 13612 insertions(+) create mode 100644 indra/cmake/GLOD.cmake create mode 100644 indra/cmake/LLConvexDecomposition.cmake create mode 100644 indra/llmath/llmatrix3a.cpp create mode 100644 indra/llmath/llmatrix3a.h create mode 100644 indra/llmath/llmatrix3a.inl create mode 100644 indra/llmath/llmatrix4a.h create mode 100644 indra/llmath/llquaternion2.h create mode 100644 indra/llmath/llquaternion2.inl create mode 100644 indra/llmath/llsimdmath.h create mode 100644 indra/llmath/llsimdtypes.h create mode 100644 indra/llmath/llsimdtypes.inl create mode 100644 indra/llmath/llvector4a.cpp create mode 100644 indra/llmath/llvector4a.h create mode 100644 indra/llmath/llvector4a.inl create mode 100644 indra/llmath/llvector4logical.h create mode 100644 indra/llmath/llvolumeoctree.cpp create mode 100644 indra/llmath/llvolumeoctree.h create mode 100644 indra/llprimitive/llmodel.cpp create mode 100644 indra/llprimitive/llmodel.h create mode 100644 indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl create mode 100644 indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl create mode 100644 indra/newview/llfloaterimportcollada.cpp create mode 100644 indra/newview/llfloaterimportcollada.h create mode 100644 indra/newview/llfloatermodelpreview.cpp create mode 100644 indra/newview/llfloatermodelpreview.h create mode 100644 indra/newview/llmeshreduction.cpp create mode 100644 indra/newview/llmeshreduction.h create mode 100644 indra/newview/llmeshrepository.cpp create mode 100644 indra/newview/llmeshrepository.h (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/cmake/GLOD.cmake b/indra/cmake/GLOD.cmake new file mode 100644 index 0000000000..77221d55ed --- /dev/null +++ b/indra/cmake/GLOD.cmake @@ -0,0 +1,9 @@ +# -*- cmake -*- +include(Prebuilt) + +if (NOT STANDALONE) + use_prebuilt_binary(GLOD) +endif (NOT STANDALONE) + +set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) +set(GLOD_LIBRARIES glod) diff --git a/indra/cmake/LLConvexDecomposition.cmake b/indra/cmake/LLConvexDecomposition.cmake new file mode 100644 index 0000000000..ae9dc3c17a --- /dev/null +++ b/indra/cmake/LLConvexDecomposition.cmake @@ -0,0 +1,16 @@ +# -*- cmake -*- +include(Prebuilt) + +set(LLCONVEXDECOMP_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) + +if (INSTALL_PROPRIETARY AND NOT STANDALONE) + use_prebuilt_binary(llconvexdecomposition) + if (WINDOWS) + set(LLCONVEXDECOMP_LIBRARY llconvexdecomposition) + else (WINDOWS) + set(LLCONVEXDECOMP_LIBRARY llconvexdecompositionstub) + endif (WINDOWS) +else (INSTALL_PROPRIETARY AND NOT STANDALONE) + use_prebuilt_binary(llconvexdecompositionstub) + set(LLCONVEXDECOMP_LIBRARY llconvexdecompositionstub) +endif (INSTALL_PROPRIETARY AND NOT STANDALONE) diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp new file mode 100644 index 0000000000..b7468f4914 --- /dev/null +++ b/indra/llmath/llmatrix3a.cpp @@ -0,0 +1,140 @@ +/** + * @file llvector4a.cpp + * @brief SIMD vector implementation + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llmath.h" + +static LL_ALIGN_16(const F32 M_IDENT_3A[12]) = + { 1.f, 0.f, 0.f, 0.f, // Column 1 + 0.f, 1.f, 0.f, 0.f, // Column 2 + 0.f, 0.f, 1.f, 0.f }; // Column 3 + +extern const LLMatrix3a LL_M3A_IDENTITY = *reinterpret_cast (M_IDENT_3A); + +void LLMatrix3a::setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ) +{ + const LLVector4a col0 = lhs.getColumn(0); + const LLVector4a col1 = lhs.getColumn(1); + const LLVector4a col2 = lhs.getColumn(2); + + for ( int i = 0; i < 3; i++ ) + { + LLVector4a xxxx = _mm_load_ss( rhs.mColumns[i].getF32ptr() ); + xxxx.splat<0>( xxxx ); + xxxx.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + xxxx.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + xxxx.add( zzzz ); + } + + xxxx.store4a( mColumns[i].getF32ptr() ); + } + +} + +/*static */void LLMatrix3a::batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ) +{ + const LLVector4a col0 = xform.getColumn(0); + const LLVector4a col1 = xform.getColumn(1); + const LLVector4a col2 = xform.getColumn(2); + const LLVector4a* maxAddr = src + numVectors; + + if ( numVectors & 0x1 ) + { + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a zzzz = _mm_load_ss( (const F32*)src + 2 ); + xxxx.splat<0>( xxxx ); + yyyy.splat<0>( yyyy ); + zzzz.splat<0>( zzzz ); + xxxx.mul( col0 ); + yyyy.mul( col1 ); + zzzz.mul( col2 ); + xxxx.add( yyyy ); + xxxx.add( zzzz ); + xxxx.store4a( (F32*)dst ); + src++; + dst++; + } + + + numVectors >>= 1; + while ( src < maxAddr ) + { + _mm_prefetch( (const char*)(src + 32 ), _MM_HINT_NTA ); + _mm_prefetch( (const char*)(dst + 32), _MM_HINT_NTA ); + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a xxxx1= _mm_load_ss( (const F32*)(src + 1) ); + + xxxx.splat<0>( xxxx ); + xxxx1.splat<0>( xxxx1 ); + xxxx.mul( col0 ); + xxxx1.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a yyyy1 = _mm_load_ss( (const F32*)(src + 1) + 1); + yyyy.splat<0>( yyyy ); + yyyy1.splat<0>( yyyy1 ); + yyyy.mul( col1 ); + yyyy1.mul( col1 ); + xxxx.add( yyyy ); + xxxx1.add( yyyy1 ); + } + + { + LLVector4a zzzz = _mm_load_ss( (const F32*)(src) + 2 ); + LLVector4a zzzz1 = _mm_load_ss( (const F32*)(++src) + 2 ); + zzzz.splat<0>( zzzz ); + zzzz1.splat<0>( zzzz1 ); + zzzz.mul( col2 ); + zzzz1.mul( col2 ); + xxxx.add( zzzz ); + xxxx1.add( zzzz1 ); + } + + xxxx.store4a(dst->getF32ptr()); + src++; + dst++; + + xxxx1.store4a((F32*)dst++); + } +} diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h new file mode 100644 index 0000000000..56327f9f6d --- /dev/null +++ b/indra/llmath/llmatrix3a.h @@ -0,0 +1,134 @@ +/** + * @file llmatrix3a.h + * @brief LLMatrix3a class header file - memory aligned and vectorized 3x3 matrix + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMATRIX3A_H +#define LL_LLMATRIX3A_H + +///////////////////////////// +// LLMatrix3a, LLRotation +///////////////////////////// +// This class stores a 3x3 (technically 4x3) matrix in column-major order +///////////////////////////// +///////////////////////////// +// These classes are intentionally minimal right now. If you need additional +// functionality, please contact someone with SSE experience (e.g., Falcon or +// Huseby). +///////////////////////////// + +// LLMatrix3a is the base class for LLRotation, which should be used instead any time you're dealing with a +// rotation matrix. +class LLMatrix3a +{ +public: + + // Utility function for quickly transforming an array of LLVector4a's + // For transforming a single LLVector4a, see LLVector4a::setRotated + static void batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ); + + // Utility function to obtain the identity matrix + static inline const LLMatrix3a& getIdentity(); + + ////////////////////////// + // Ctors + ////////////////////////// + + // Ctor + LLMatrix3a() {} + + // Ctor for setting by columns + inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ); + + ////////////////////////// + // Get/Set + ////////////////////////// + + // Loads from an LLMatrix3 + inline void loadu(const LLMatrix3& src); + + // Set rows + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2); + + // Set columns + inline void setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2); + + // Get the read-only access to a specified column. Valid columns are 0-2, but the + // function is unchecked. You've been warned. + inline const LLVector4a& getColumn(const U32 column) const; + + ///////////////////////// + // Matrix modification + ///////////////////////// + + // Set this matrix to the product of lhs and rhs ( this = lhs * rhs ) + void setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ); + + // Set this matrix to the transpose of src + inline void setTranspose(const LLMatrix3a& src); + + // Set this matrix to a*w + b*(1-w) + inline void setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w); + + ///////////////////////// + // Matrix inspection + ///////////////////////// + + // Sets all 4 elements in 'dest' to the determinant of this matrix. + // If you will be using the determinant in subsequent ops with LLVector4a, use this version + inline void getDeterminant( LLVector4a& dest ) const; + + // Returns the determinant as an LLSimdScalar. Use this if you will be using the determinant + // primary for scalar operations. + inline LLSimdScalar getDeterminant() const; + + // Returns nonzero if rows 0-2 and colums 0-2 contain no NaN or INF values. Row 3 is ignored + inline LLBool32 isFinite() const; + + // Returns true if this matrix is equal to 'rhs' up to 'tolerance' + inline bool isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + +protected: + + LLVector4a mColumns[3]; + +}; + +class LLRotation : public LLMatrix3a +{ +public: + + LLRotation() {} + + // Returns true if this rotation is orthonormal with det ~= 1 + inline bool isOkRotation() const; +}; + +#endif diff --git a/indra/llmath/llmatrix3a.inl b/indra/llmath/llmatrix3a.inl new file mode 100644 index 0000000000..65fd949f78 --- /dev/null +++ b/indra/llmath/llmatrix3a.inl @@ -0,0 +1,125 @@ +/** + * @file llmatrix3a.inl + * @brief LLMatrix3a inline definitions + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llmatrix3a.h" +#include "m3math.h" + +inline LLMatrix3a::LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ) +{ + setColumns( c0, c1, c2 ); +} + +inline void LLMatrix3a::loadu(const LLMatrix3& src) +{ + mColumns[0].load3(src.mMatrix[0]); + mColumns[1].load3(src.mMatrix[1]); + mColumns[2].load3(src.mMatrix[2]); +} + +inline void LLMatrix3a::setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) +{ + mColumns[0] = r0; + mColumns[1] = r1; + mColumns[2] = r2; + setTranspose( *this ); +} + +inline void LLMatrix3a::setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2) +{ + mColumns[0] = c0; + mColumns[1] = c1; + mColumns[2] = c2; +} + +inline void LLMatrix3a::setTranspose(const LLMatrix3a& src) +{ + const LLQuad srcCol0 = src.mColumns[0]; + const LLQuad srcCol1 = src.mColumns[1]; + const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 ); + mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] ); + mColumns[1] = _mm_shuffle_ps( _mm_movehl_ps( srcCol0, unpacklo ), src.mColumns[2], _MM_SHUFFLE(0, 1, 1, 0) ); + mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) ); +} + +inline const LLVector4a& LLMatrix3a::getColumn(const U32 column) const +{ + llassert( column < 3 ); + return mColumns[column]; +} + +inline void LLMatrix3a::setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w) +{ + mColumns[0].setLerp( a.mColumns[0], b.mColumns[0], w ); + mColumns[1].setLerp( a.mColumns[1], b.mColumns[1], w ); + mColumns[2].setLerp( a.mColumns[2], b.mColumns[2], w ); +} + +inline LLBool32 LLMatrix3a::isFinite() const +{ + return mColumns[0].isFinite3() && mColumns[1].isFinite3() && mColumns[2].isFinite3(); +} + +inline void LLMatrix3a::getDeterminant( LLVector4a& dest ) const +{ + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + dest.setAllDot3( col1xcol2, mColumns[0] ); +} + +inline LLSimdScalar LLMatrix3a::getDeterminant() const +{ + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + return col1xcol2.dot3( mColumns[0] ); +} + +inline bool LLMatrix3a::isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance /*= F_APPROXIMATELY_ZERO*/ ) const +{ + return rhs.getColumn(0).equals3(mColumns[0], tolerance) + && rhs.getColumn(1).equals3(mColumns[1], tolerance) + && rhs.getColumn(2).equals3(mColumns[2], tolerance); +} + +inline const LLMatrix3a& LLMatrix3a::getIdentity() +{ + extern const LLMatrix3a LL_M3A_IDENTITY; + return LL_M3A_IDENTITY; +} + +inline bool LLRotation::isOkRotation() const +{ + LLMatrix3a transpose; transpose.setTranspose( *this ); + LLMatrix3a product; product.setMul( *this, transpose ); + + LLSimdScalar detMinusOne = getDeterminant() - 1.f; + + return product.isApproximatelyEqual( LLMatrix3a::getIdentity() ) && (detMinusOne.getAbs() < F_APPROXIMATELY_ZERO); +} + diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h new file mode 100644 index 0000000000..0ead045d04 --- /dev/null +++ b/indra/llmath/llmatrix4a.h @@ -0,0 +1,149 @@ +/** + * @file llmatrix4a.h + * @brief LLMatrix4a class header file - memory aligned and vectorized 4x4 matrix + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMATRIX4A_H +#define LL_LLMATRIX4A_H + +#include "llvector4a.h" +#include "m4math.h" +#include "m3math.h" + +class LLMatrix4a +{ +public: + LLVector4a mMatrix[4]; + + inline void clear() + { + mMatrix[0].clear(); + mMatrix[1].clear(); + mMatrix[2].clear(); + mMatrix[3].clear(); + } + + inline void loadu(const LLMatrix4& src) + { + mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]); + mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]); + mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]); + mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]); + + } + + inline void loadu(const LLMatrix3& src) + { + mMatrix[0].load3(src.mMatrix[0]); + mMatrix[1].load3(src.mMatrix[1]); + mMatrix[2].load3(src.mMatrix[2]); + mMatrix[3].set(0,0,0,1.f); + } + + inline void add(const LLMatrix4a& rhs) + { + mMatrix[0].add(rhs.mMatrix[0]); + mMatrix[1].add(rhs.mMatrix[1]); + mMatrix[2].add(rhs.mMatrix[2]); + mMatrix[3].add(rhs.mMatrix[3]); + } + + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) + { + mMatrix[0] = r0; + mMatrix[1] = r1; + mMatrix[2] = r2; + } + + inline void setMul(const LLMatrix4a& m, const F32 s) + { + mMatrix[0].setMul(m.mMatrix[0], s); + mMatrix[1].setMul(m.mMatrix[1], s); + mMatrix[2].setMul(m.mMatrix[2], s); + mMatrix[3].setMul(m.mMatrix[3], s); + } + + inline void setLerp(const LLMatrix4a& a, const LLMatrix4a& b, F32 w) + { + LLVector4a d0,d1,d2,d3; + d0.setSub(b.mMatrix[0], a.mMatrix[0]); + d1.setSub(b.mMatrix[1], a.mMatrix[1]); + d2.setSub(b.mMatrix[2], a.mMatrix[2]); + d3.setSub(b.mMatrix[3], a.mMatrix[3]); + + // this = a + d*w + + d0.mul(w); + d1.mul(w); + d2.mul(w); + d3.mul(w); + + mMatrix[0].setAdd(a.mMatrix[0],d0); + mMatrix[1].setAdd(a.mMatrix[1],d1); + mMatrix[2].setAdd(a.mMatrix[2],d2); + mMatrix[3].setAdd(a.mMatrix[3],d3); + } + + inline void rotate(const LLVector4a& v, LLVector4a& res) + { + res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + res.mul(mMatrix[0]); + + LLVector4a y; + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + y.mul(mMatrix[1]); + + LLVector4a z; + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + z.mul(mMatrix[2]); + + res.add(y); + res.add(z); + } + + inline void affineTransform(const LLVector4a& v, LLVector4a& res) + { + LLVector4a x,y,z; + + x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + + x.mul(mMatrix[0]); + y.mul(mMatrix[1]); + z.mul(mMatrix[2]); + + x.add(y); + z.add(mMatrix[3]); + res.setAdd(x,z); + } +}; + +#endif diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h new file mode 100644 index 0000000000..dbb4afe312 --- /dev/null +++ b/indra/llmath/llquaternion2.h @@ -0,0 +1,111 @@ +/** + * @file llquaternion2.h + * @brief LLQuaternion2 class header file - SIMD-enabled quaternion class + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_QUATERNION2_H +#define LL_QUATERNION2_H + +///////////////////////////// +// LLQuaternion2 +///////////////////////////// +// This class stores a quaternion x*i + y*j + z*k + w in order +// (i.e., w in high order element of vector) +///////////////////////////// +///////////////////////////// +// These classes are intentionally minimal right now. If you need additional +// functionality, please contact someone with SSE experience (e.g., Falcon or +// Huseby). +///////////////////////////// +#include "llquaternion.h" + +class LLQuaternion2 +{ +public: + + ////////////////////////// + // Ctors + ////////////////////////// + + // Ctor + LLQuaternion2() {} + + // Ctor from LLQuaternion + explicit LLQuaternion2( const class LLQuaternion& quat ); + + ////////////////////////// + // Get/Set + ////////////////////////// + + // Load from an LLQuaternion + inline void operator=( const LLQuaternion& quat ) + { + mQ.loadua( quat.mQ ); + } + + // Return the internal LLVector4a representation of the quaternion + inline const LLVector4a& getVector4a() const; + inline LLVector4a& getVector4aRw(); + + ///////////////////////// + // Quaternion modification + ///////////////////////// + + // Set this quaternion to the conjugate of src + inline void setConjugate(const LLQuaternion2& src); + + // Renormalizes the quaternion. Assumes it has nonzero length. + inline void normalize(); + + // Quantize this quaternion to 8 bit precision + inline void quantize8(); + + // Quantize this quaternion to 16 bit precision + inline void quantize16(); + + ///////////////////////// + // Quaternion inspection + ///////////////////////// + + // Return true if this quaternion is equal to 'rhs'. + // Note! Quaternions exhibit "double-cover", so any rotation has two equally valid + // quaternion representations and they will NOT compare equal. + inline bool equals(const LLQuaternion2& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + // Return true if all components are finite and the quaternion is normalized + inline bool isOkRotation() const; + +protected: + + LLVector4a mQ; + +}; + +#endif diff --git a/indra/llmath/llquaternion2.inl b/indra/llmath/llquaternion2.inl new file mode 100644 index 0000000000..9a4274d6a4 --- /dev/null +++ b/indra/llmath/llquaternion2.inl @@ -0,0 +1,108 @@ +/** + * @file llquaternion2.inl + * @brief LLQuaternion2 inline definitions + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llquaternion2.h" + +static const LLQuad LL_V4A_PLUS_ONE = {1.f, 1.f, 1.f, 1.f}; +static const LLQuad LL_V4A_MINUS_ONE = {-1.f, -1.f, -1.f, -1.f}; + +// Ctor from LLQuaternion +inline LLQuaternion2::LLQuaternion2( const LLQuaternion& quat ) +{ + mQ.set(quat.mQ[VX], quat.mQ[VY], quat.mQ[VZ], quat.mQ[VW]); +} + +////////////////////////// +// Get/Set +////////////////////////// + +// Return the internal LLVector4a representation of the quaternion +inline const LLVector4a& LLQuaternion2::getVector4a() const +{ + return mQ; +} + +inline LLVector4a& LLQuaternion2::getVector4aRw() +{ + return mQ; +} + +///////////////////////// +// Quaternion modification +///////////////////////// + +// Set this quaternion to the conjugate of src +inline void LLQuaternion2::setConjugate(const LLQuaternion2& src) +{ + static LL_ALIGN_16( const U32 F_QUAT_INV_MASK_4A[4] ) = { 0x80000000, 0x80000000, 0x80000000, 0x00000000 }; + mQ = _mm_xor_ps(src.mQ, *reinterpret_cast(&F_QUAT_INV_MASK_4A)); +} + +// Renormalizes the quaternion. Assumes it has nonzero length. +inline void LLQuaternion2::normalize() +{ + mQ.normalize4(); +} + +// Quantize this quaternion to 8 bit precision +inline void LLQuaternion2::quantize8() +{ + mQ.quantize8( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); +} + +// Quantize this quaternion to 16 bit precision +inline void LLQuaternion2::quantize16() +{ + mQ.quantize16( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); +} + + +///////////////////////// +// Quaternion inspection +///////////////////////// + +// Return true if this quaternion is equal to 'rhs'. +// Note! Quaternions exhibit "double-cover", so any rotation has two equally valid +// quaternion representations and they will NOT compare equal. +inline bool LLQuaternion2::equals(const LLQuaternion2 &rhs, F32 tolerance/* = F_APPROXIMATELY_ZERO*/) const +{ + return mQ.equals4(rhs.mQ, tolerance); +} + +// Return true if all components are finite and the quaternion is normalized +inline bool LLQuaternion2::isOkRotation() const +{ + return mQ.isFinite4() && mQ.isNormalized4(); +} + diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h new file mode 100644 index 0000000000..9377bfdb53 --- /dev/null +++ b/indra/llmath/llsimdmath.h @@ -0,0 +1,95 @@ +/** + * @file llsimdmath.h + * @brief Common header for SIMD-based math library (llvector4a, llmatrix3a, etc.) + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_SIMD_MATH_H +#define LL_SIMD_MATH_H + +#ifndef LLMATH_H +#error "Please include llmath.h before this file." +#endif + +#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 ) ) +#error SSE2 not enabled. LLVector4a and related class will not compile. +#endif + +template T* LL_NEXT_ALIGNED_ADDRESS(T* address) +{ + return reinterpret_cast( + (reinterpret_cast(address) + 0xF) & ~0xF); +} + +template T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) +{ + return reinterpret_cast( + (reinterpret_cast(address) + 0x3F) & ~0x3F); +} + +#if LL_LINUX || LL_DARWIN + +#define LL_ALIGN_PREFIX(x) +#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x))) + +#elif LL_WINDOWS + +#define LL_ALIGN_PREFIX(x) __declspec(align(x)) +#define LL_ALIGN_POSTFIX(x) + +#else +#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" +#endif + +#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) + + + +#include +#include + +#include "llsimdtypes.h" +#include "llsimdtypes.inl" + +class LLMatrix3a; +class LLRotation; +class LLMatrix3; + +#include "llquaternion.h" + +#include "llvector4logical.h" +#include "llvector4a.h" +#include "llmatrix3a.h" +#include "llquaternion2.h" +#include "llvector4a.inl" +#include "llmatrix3a.inl" +#include "llquaternion2.inl" + + +#endif //LL_SIMD_MATH_H diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h new file mode 100644 index 0000000000..82e318c8bf --- /dev/null +++ b/indra/llmath/llsimdtypes.h @@ -0,0 +1,130 @@ +/** + * @file llsimdtypes.h + * @brief Declaration of basic SIMD math related types + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_SIMD_TYPES_H +#define LL_SIMD_TYPES_H + +#ifndef LL_SIMD_MATH_H +#error "Please include llmath.h before this file." +#endif + +typedef __m128 LLQuad; + + +#if LL_WINDOWS +#pragma warning(push) +#pragma warning( disable : 4800 3 ) // Disable warning about casting int to bool for this class. +#if defined(_MSC_VER) && (_MSC_VER < 1500) +// VC++ 2005 is missing these intrinsics +// __forceinline is MSVC specific and attempts to override compiler inlining judgment. This is so +// even in debug builds this call is a NOP. +__forceinline const __m128 _mm_castsi128_ps( const __m128i a ) { return reinterpret_cast(a); } +__forceinline const __m128i _mm_castps_si128( const __m128 a ) { return reinterpret_cast(a); } +#endif // _MSC_VER + +#endif // LL_WINDOWS + +class LLBool32 +{ +public: + inline LLBool32() {} + inline LLBool32(int rhs) : m_bool(rhs) {} + inline LLBool32(unsigned int rhs) : m_bool(rhs) {} + inline LLBool32(bool rhs) { m_bool = static_cast(rhs); } + inline LLBool32& operator= (bool rhs) { m_bool = (int)rhs; return *this; } + inline bool operator== (bool rhs) const { return static_cast(m_bool) == rhs; } + inline bool operator!= (bool rhs) const { return !operator==(rhs); } + inline operator bool() const { return static_cast(m_bool); } + +private: + int m_bool; +}; + +#if LL_WINDOWS +#pragma warning(pop) +#endif + +class LLSimdScalar +{ +public: + inline LLSimdScalar() {} + inline LLSimdScalar(LLQuad q) + { + mQ = q; + } + + inline LLSimdScalar(F32 f) + { + mQ = _mm_set_ss(f); + } + + static inline const LLSimdScalar& getZero() + { + extern const LLQuad F_ZERO_4A; + return reinterpret_cast(F_ZERO_4A); + } + + inline F32 getF32() const; + + inline LLBool32 isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance = F_APPROXIMATELY_ZERO) const; + + inline LLSimdScalar getAbs() const; + + inline void setMax( const LLSimdScalar& a, const LLSimdScalar& b ); + + inline void setMin( const LLSimdScalar& a, const LLSimdScalar& b ); + + inline LLSimdScalar& operator=(F32 rhs); + + inline LLSimdScalar& operator+=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator-=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator*=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator/=(const LLSimdScalar& rhs); + + inline operator LLQuad() const + { + return mQ; + } + + inline const LLQuad& getQuad() const + { + return mQ; + } + +private: + LLQuad mQ; +}; + +#endif //LL_SIMD_TYPES_H diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl new file mode 100644 index 0000000000..69c858e310 --- /dev/null +++ b/indra/llmath/llsimdtypes.inl @@ -0,0 +1,163 @@ +/** + * @file llsimdtypes.inl + * @brief Inlined definitions of basic SIMD math related types + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + + + +////////////////// +// LLSimdScalar +////////////////// + +inline LLSimdScalar operator+(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t += b; + return t; +} + +inline LLSimdScalar operator-(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t -= b; + return t; +} + +inline LLSimdScalar operator*(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t *= b; + return t; +} + +inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t /= b; + return t; +} + +inline LLSimdScalar operator-(const LLSimdScalar& a) +{ + static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + return _mm_xor_ps(*reinterpret_cast(signMask), a); +} + +inline LLBool32 operator==(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comieq_ss(a, b); +} + +inline LLBool32 operator!=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comineq_ss(a, b); +} + +inline LLBool32 operator<(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comilt_ss(a, b); +} + +inline LLBool32 operator<=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comile_ss(a, b); +} + +inline LLBool32 operator>(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comigt_ss(a, b); +} + +inline LLBool32 operator>=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comige_ss(a, b); +} + +inline LLBool32 LLSimdScalar::isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance /* = F_APPROXIMATELY_ZERO */) const +{ + const LLSimdScalar tol( tolerance ); + const LLSimdScalar diff = _mm_sub_ss( mQ, rhs.mQ ); + const LLSimdScalar absDiff = diff.getAbs(); + return absDiff <= tol; +} + +inline void LLSimdScalar::setMax( const LLSimdScalar& a, const LLSimdScalar& b ) +{ + mQ = _mm_max_ss( a, b ); +} + +inline void LLSimdScalar::setMin( const LLSimdScalar& a, const LLSimdScalar& b ) +{ + mQ = _mm_min_ss( a, b ); +} + +inline LLSimdScalar& LLSimdScalar::operator=(F32 rhs) +{ + mQ = _mm_set_ss(rhs); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator+=(const LLSimdScalar& rhs) +{ + mQ = _mm_add_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator-=(const LLSimdScalar& rhs) +{ + mQ = _mm_sub_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator*=(const LLSimdScalar& rhs) +{ + mQ = _mm_mul_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) +{ + mQ = _mm_div_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar LLSimdScalar::getAbs() const +{ + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + return _mm_and_ps( mQ, *reinterpret_cast(F_ABS_MASK_4A)); +} + +inline F32 LLSimdScalar::getF32() const +{ + F32 ret; + _mm_store_ss(&ret, mQ); + return ret; +} diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp new file mode 100644 index 0000000000..b62c17302f --- /dev/null +++ b/indra/llmath/llvector4a.cpp @@ -0,0 +1,228 @@ +/** + * @file llvector4a.cpp + * @brief SIMD vector implementation + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llmath.h" +#include "llquantize.h" + +extern const LLQuad F_ZERO_4A = { 0, 0, 0, 0 }; +extern const LLQuad F_APPROXIMATELY_ZERO_4A = { + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO +}; + +extern const LLVector4a LL_V4A_ZERO = reinterpret_cast ( F_ZERO_4A ); +extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F_APPROXIMATELY_ZERO_4A ); + +/*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes) +{ + assert(src != NULL); + assert(dst != NULL); + assert(bytes > 0); + assert((bytes % sizeof(F32))== 0); + + F32* end = dst + (bytes / sizeof(F32) ); + + if (bytes > 64) + { + F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); + + //at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies + F32* end_64 = end-16; + + _mm_prefetch((char*)begin_64, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); + + while (dst < begin_64) + { + copy4a(dst, src); + dst += 4; + src += 4; + } + + while (dst < end_64) + { + _mm_prefetch((char*)src + 512, _MM_HINT_NTA); + _mm_prefetch((char*)dst + 512, _MM_HINT_NTA); + copy4a(dst, src); + copy4a(dst+4, src+4); + copy4a(dst+8, src+8); + copy4a(dst+12, src+12); + + dst += 16; + src += 16; + } + } + + while (dst < end) + { + copy4a(dst, src); + dst += 4; + src += 4; + } +} + +void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) +{ + const LLVector4a col0 = rot.getColumn(0); + const LLVector4a col1 = rot.getColumn(1); + const LLVector4a col2 = rot.getColumn(2); + + LLVector4a result = _mm_load_ss( vec.getF32ptr() ); + result.splat<0>( result ); + result.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( vec.getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + result.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( vec.getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + result.add( zzzz ); + } + + *this = result; +} + +void LLVector4a::setRotated( const LLQuaternion2& quat, const LLVector4a& vec ) +{ + const LLVector4a& quatVec = quat.getVector4a(); + LLVector4a temp; temp.setCross3(quatVec, vec); + temp.add( temp ); + + const LLVector4a realPart( quatVec.getScalarAt<3>() ); + LLVector4a tempTimesReal; tempTimesReal.setMul( temp, realPart ); + + mQ = vec; + add( tempTimesReal ); + + LLVector4a imagCrossTemp; imagCrossTemp.setCross3( quatVec, temp ); + add(imagCrossTemp); +} + +void LLVector4a::quantize8( const LLVector4a& low, const LLVector4a& high ) +{ + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 8-bit quantization means we can do with just 12 bits of reciprocal accuracy + const LLVector4a oneOverDelta = _mm_rcp_ps(delta.mQ); +// { +// static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; +// LLVector4a two; two.load4a( F_TWO_4A ); +// +// // Here we use _mm_rcp_ps plus one round of newton-raphson +// // We wish to find 'x' such that x = 1/delta +// // As a first approximation, we take x0 = _mm_rcp_ps(delta) +// // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) +// // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf +// const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); +// oneOverDelta.setMul( delta, recipApprox ); +// oneOverDelta.setSub( two, oneOverDelta ); +// oneOverDelta.mul( recipApprox ); +// } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast(F_U8MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast(F_OOU8MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast(F_OOU8MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } +} + +void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) +{ + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 16-bit quantization means we need a round of Newton-Raphson + LLVector4a oneOverDelta; + { + static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + LLVector4a two; two.load4a( F_TWO_4A ); + + // Here we use _mm_rcp_ps plus one round of newton-raphson + // We wish to find 'x' such that x = 1/delta + // As a first approximation, we take x0 = _mm_rcp_ps(delta) + // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) + // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf + const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); + oneOverDelta.setMul( delta, recipApprox ); + oneOverDelta.setSub( two, oneOverDelta ); + oneOverDelta.mul( recipApprox ); + } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast(F_U16MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast(F_OOU16MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast(F_OOU16MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } +} diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h new file mode 100644 index 0000000000..76a3e999ce --- /dev/null +++ b/indra/llmath/llvector4a.h @@ -0,0 +1,331 @@ +/** + * @file llvector4a.h + * @brief LLVector4a class header file - memory aligned and vectorized 4 component vector + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVECTOR4A_H +#define LL_LLVECTOR4A_H + + +class LLRotation; + +#include +#include "llpreprocessor.h" + +/////////////////////////////////// +// FIRST TIME USERS PLEASE READ +////////////////////////////////// +// This is just the beginning of LLVector4a. There are many more useful functions +// yet to be implemented. For example, setNeg to negate a vector, rotate() to apply +// a matrix rotation, various functions to manipulate only the X, Y, and Z elements +// and many others (including a whole variety of accessors). So if you don't see a +// function here that you need, please contact Falcon or someone else with SSE +// experience (Richard, I think, has some and davep has a little as of the time +// of this writing, July 08, 2010) about getting it implemented before you resort to +// LLVector3/LLVector4. +///////////////////////////////// + +class LLVector4a +{ +public: + + /////////////////////////////////// + // STATIC METHODS + /////////////////////////////////// + + // Call initClass() at startup to avoid 15,000+ cycle penalties from denormalized numbers + static void initClass() + { + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST); + } + + // Return a vector of all zeros + static inline const LLVector4a& getZero() + { + extern const LLVector4a LL_V4A_ZERO; + return LL_V4A_ZERO; + } + + // Return a vector of all epsilon, where epsilon is a small float suitable for approximate equality checks + static inline const LLVector4a& getEpsilon() + { + extern const LLVector4a LL_V4A_EPSILON; + return LL_V4A_EPSILON; + } + + // Copy 16 bytes from src to dst. Source and destination must be 16-byte aligned + static inline void copy4a(F32* dst, const F32* src) + { + _mm_store_ps(dst, _mm_load_ps(src)); + } + + // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); + + //////////////////////////////////// + // CONSTRUCTORS + //////////////////////////////////// + + LLVector4a() + { //DO NOT INITIALIZE -- The overhead is completely unnecessary + } + + LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) + { + set(x,y,z,w); + } + + LLVector4a(F32 x) + { + splat(x); + } + + LLVector4a(const LLSimdScalar& x) + { + splat(x); + } + + LLVector4a(LLQuad q) + { + mQ = q; + } + + //////////////////////////////////// + // LOAD/STORE + //////////////////////////////////// + + // Load from 16-byte aligned src array (preferred method of loading) + inline void load4a(const F32* src); + + // Load from unaligned src array (NB: Significantly slower than load4a) + inline void loadua(const F32* src); + + // Load only three floats beginning at address 'src'. Slowest method. + inline void load3(const F32* src); + + // Store to a 16-byte aligned memory address + inline void store4a(F32* dst) const; + + //////////////////////////////////// + // BASIC GET/SET + //////////////////////////////////// + + // Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + inline F32* getF32ptr(); + + // Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + inline const F32* const getF32ptr() const; + + // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates + // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead + inline F32 operator[](const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + inline LLSimdScalar getScalarAt(const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + template LL_FORCE_INLINE LLSimdScalar getScalarAt() const; + template <> LL_FORCE_INLINE LLSimdScalar getScalarAt<0>() const; + + // Set to an x, y, z and optional w provided + inline void set(F32 x, F32 y, F32 z, F32 w = 0.f); + + // Set to all zeros. This is preferred to using ::getZero() + inline void clear(); + + // Set all elements to 'x' + inline void splat(const F32 x); + + // Set all elements to 'x' + inline void splat(const LLSimdScalar& x); + + // Set all 4 elements to element N of src, with N known at compile time + template void splat(const LLVector4a& src); + + // Set all 4 elements to element i of v, with i NOT known at compile time + inline void splat(const LLVector4a& v, U32 i); + + // Select bits from sourceIfTrue and sourceIfFalse according to bits in mask + inline void setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ); + + //////////////////////////////////// + // ALGEBRAIC + //////////////////////////////////// + + // Set this to the element-wise (a + b) + inline void setAdd(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise (a - b) + inline void setSub(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise multiply (a * b) + inline void setMul(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise quotient (a / b) + inline void setDiv(const LLVector4a& a, const LLVector4a& b); + + // Set this to the element-wise absolute value of src + inline void setAbs(const LLVector4a& src); + + // Add to each component in this vector the corresponding component in rhs + inline void add(const LLVector4a& rhs); + + // Subtract from each component in this vector the corresponding component in rhs + inline void sub(const LLVector4a& rhs); + + // Multiply each component in this vector by the corresponding component in rhs + inline void mul(const LLVector4a& rhs); + + // Divide each component in this vector by the corresponding component in rhs + inline void div(const LLVector4a& rhs); + + // Multiply this vector by x in a scalar fashion + inline void mul(const F32 x); + + // Set this to (a x b) (geometric cross-product) + inline void setCross3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, and z elements in a and b + inline void setAllDot3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, z, and w elements in a and b + inline void setAllDot4(const LLVector4a& a, const LLVector4a& b); + + // Return the 3D dot product of this vector and b + inline LLSimdScalar dot3(const LLVector4a& b) const; + + // Return the 4D dot product of this vector and b + inline LLSimdScalar dot4(const LLVector4a& b) const; + + // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3(); + + // Same as normalize3() but with respect to all 4 components + inline void normalize4(); + + // Same as normalize3(), but returns length as a SIMD scalar + inline LLSimdScalar normalize3withLength(); + + // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3fast(); + + // Return true if this vector is normalized with respect to x,y,z up to tolerance + inline LLBool32 isNormalized3( F32 tolerance = 1e-3 ) const; + + // Return true if this vector is normalized with respect to all components up to tolerance + inline LLBool32 isNormalized4( F32 tolerance = 1e-3 ) const; + + // Set all elements to the length of vector 'v' + inline void setAllLength3( const LLVector4a& v ); + + // Get this vector's length + inline LLSimdScalar getLength3() const; + + // Set the components of this vector to the minimum of the corresponding components of lhs and rhs + inline void setMin(const LLVector4a& lhs, const LLVector4a& rhs); + + // Set the components of this vector to the maximum of the corresponding components of lhs and rhs + inline void setMax(const LLVector4a& lhs, const LLVector4a& rhs); + + // Clamps this vector to be within the component-wise range low to high (inclusive) + inline void clamp( const LLVector4a& low, const LLVector4a& high ); + + // Set this to (c * lhs) + rhs * ( 1 - c) + inline void setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c); + + // Return true (nonzero) if x, y, z (and w for Finite4) are all finite floats + inline LLBool32 isFinite3() const; + inline LLBool32 isFinite4() const; + + // Set this vector to 'vec' rotated by the LLRotation or LLQuaternion2 provided + void setRotated( const LLRotation& rot, const LLVector4a& vec ); + void setRotated( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Set this vector to 'vec' rotated by the INVERSE of the LLRotation or LLQuaternion2 provided + inline void setRotatedInv( const LLRotation& rot, const LLVector4a& vec ); + inline void setRotatedInv( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Quantize this vector to 8 or 16 bit precision + void quantize8( const LLVector4a& low, const LLVector4a& high ); + void quantize16( const LLVector4a& low, const LLVector4a& high ); + + //////////////////////////////////// + // LOGICAL + //////////////////////////////////// + // The functions in this section will compare the elements in this vector + // to those in rhs and return an LLVector4Logical with all bits set in elements + // where the comparison was true and all bits unset in elements where the comparison + // was false. See llvector4logica.h + //////////////////////////////////// + // WARNING: Other than equals3 and equals4, these functions do NOT account + // for floating point tolerance. You should include the appropriate tolerance + // in the inputs. + //////////////////////////////////// + + inline LLVector4Logical greaterThan(const LLVector4a& rhs) const; + + inline LLVector4Logical lessThan(const LLVector4a& rhs) const; + + inline LLVector4Logical greaterEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical lessEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical equal(const LLVector4a& rhs) const; + + // Returns true if this and rhs are componentwise equal up to the specified absolute tolerance + inline bool equals4(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + inline bool equals3(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + //////////////////////////////////// + // OPERATORS + //////////////////////////////////// + + // Do NOT add aditional operators without consulting someone with SSE experience + inline const LLVector4a& operator= ( const LLVector4a& rhs ); + + inline const LLVector4a& operator= ( const LLQuad& rhs ); + + inline operator LLQuad() const; + +private: + LLQuad mQ; +}; + +inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) +{ + min.setMin(min, p); + max.setMax(max, p); +} + +#endif diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl new file mode 100644 index 0000000000..e52b550883 --- /dev/null +++ b/indra/llmath/llvector4a.inl @@ -0,0 +1,599 @@ +/** + * @file llvector4a.inl + * @brief LLVector4a inline function implementations + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +//////////////////////////////////// +// LOAD/STORE +//////////////////////////////////// + +// Load from 16-byte aligned src array (preferred method of loading) +inline void LLVector4a::load4a(const F32* src) +{ + mQ = _mm_load_ps(src); +} + +// Load from unaligned src array (NB: Significantly slower than load4a) +inline void LLVector4a::loadua(const F32* src) +{ + mQ = _mm_loadu_ps(src); +} + +// Load only three floats beginning at address 'src'. Slowest method. +inline void LLVector4a::load3(const F32* src) +{ + // mQ = { 0.f, src[2], src[1], src[0] } = { W, Z, Y, X } + // NB: This differs from the convention of { Z, Y, X, W } + mQ = _mm_set_ps(0.f, src[2], src[1], src[0]); +} + +// Store to a 16-byte aligned memory address +inline void LLVector4a::store4a(F32* dst) const +{ + _mm_store_ps(dst, mQ); +} + +//////////////////////////////////// +// BASIC GET/SET +//////////////////////////////////// + +// Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +F32* LLVector4a::getF32ptr() +{ + return (F32*) &mQ; +} + +// Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +const F32* const LLVector4a::getF32ptr() const +{ + return (const F32* const) &mQ; +} + +// Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates +// the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead +inline F32 LLVector4a::operator[](const S32 idx) const +{ + return ((F32*)&mQ)[idx]; +} + +// Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. +inline LLSimdScalar LLVector4a::getScalarAt(const S32 idx) const +{ + // Return appropriate LLQuad. It will be cast to LLSimdScalar automatically (should be effectively a nop) + switch (idx) + { + case 0: + return mQ; + case 1: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(1, 1, 1, 1)); + case 2: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(2, 2, 2, 2)); + case 3: + default: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(3, 3, 3, 3)); + } +} + +// Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. +template LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt() const +{ + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(N, N, N, N)); +} + +template<> LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt<0>() const +{ + return mQ; +} + +// Set to an x, y, z and optional w provided +inline void LLVector4a::set(F32 x, F32 y, F32 z, F32 w) +{ + mQ = _mm_set_ps(w, z, y, x); +} + +// Set to all zeros +inline void LLVector4a::clear() +{ + mQ = LLVector4a::getZero().mQ; +} + +inline void LLVector4a::splat(const F32 x) +{ + mQ = _mm_set1_ps(x); +} + +inline void LLVector4a::splat(const LLSimdScalar& x) +{ + mQ = _mm_shuffle_ps( x.getQuad(), x.getQuad(), _MM_SHUFFLE(0,0,0,0) ); +} + +// Set all 4 elements to element N of src, with N known at compile time +template void LLVector4a::splat(const LLVector4a& src) +{ + mQ = _mm_shuffle_ps(src.mQ, src.mQ, _MM_SHUFFLE(N, N, N, N) ); +} + +// Set all 4 elements to element i of v, with i NOT known at compile time +inline void LLVector4a::splat(const LLVector4a& v, U32 i) +{ + switch (i) + { + case 0: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(0, 0, 0, 0)); + break; + case 1: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(1, 1, 1, 1)); + break; + case 2: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(2, 2, 2, 2)); + break; + case 3: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(3, 3, 3, 3)); + break; + } +} + +// Select bits from sourceIfTrue and sourceIfFalse according to bits in mask +inline void LLVector4a::setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ) +{ + // ((( sourceIfTrue ^ sourceIfFalse ) & mask) ^ sourceIfFalse ) + // E.g., sourceIfFalse = 1010b, sourceIfTrue = 0101b, mask = 1100b + // (sourceIfTrue ^ sourceIfFalse) = 1111b --> & mask = 1100b --> ^ sourceIfFalse = 0110b, + // as expected (01 from sourceIfTrue, 10 from sourceIfFalse) + // Courtesy of Mark++, http://markplusplus.wordpress.com/2007/03/14/fast-sse-select-operation/ + mQ = _mm_xor_ps( sourceIfFalse, _mm_and_ps( mask, _mm_xor_ps( sourceIfTrue, sourceIfFalse ) ) ); +} + +//////////////////////////////////// +// ALGEBRAIC +//////////////////////////////////// + +// Set this to the element-wise (a + b) +inline void LLVector4a::setAdd(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_add_ps(a.mQ, b.mQ); +} + +// Set this to element-wise (a - b) +inline void LLVector4a::setSub(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_sub_ps(a.mQ, b.mQ); +} + +// Set this to element-wise multiply (a * b) +inline void LLVector4a::setMul(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_mul_ps(a.mQ, b.mQ); +} + +// Set this to element-wise quotient (a / b) +inline void LLVector4a::setDiv(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_div_ps( a.mQ, b.mQ ); +} + +// Set this to the element-wise absolute value of src +inline void LLVector4a::setAbs(const LLVector4a& src) +{ + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + mQ = _mm_and_ps(src.mQ, *reinterpret_cast(F_ABS_MASK_4A)); +} + +// Add to each component in this vector the corresponding component in rhs +inline void LLVector4a::add(const LLVector4a& rhs) +{ + mQ = _mm_add_ps(mQ, rhs.mQ); +} + +// Subtract from each component in this vector the corresponding component in rhs +inline void LLVector4a::sub(const LLVector4a& rhs) +{ + mQ = _mm_sub_ps(mQ, rhs.mQ); +} + +// Multiply each component in this vector by the corresponding component in rhs +inline void LLVector4a::mul(const LLVector4a& rhs) +{ + mQ = _mm_mul_ps(mQ, rhs.mQ); +} + +// Divide each component in this vector by the corresponding component in rhs +inline void LLVector4a::div(const LLVector4a& rhs) +{ + // TODO: Check accuracy, maybe add divFast + mQ = _mm_div_ps(mQ, rhs.mQ); +} + +// Multiply this vector by x in a scalar fashion +inline void LLVector4a::mul(const F32 x) +{ + LLVector4a t; + t.splat(x); + + mQ = _mm_mul_ps(mQ, t.mQ); +} + +// Set this to (a x b) (geometric cross-product) +inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b) +{ + // Vectors are stored in memory in w, z, y, x order from high to low + // Set vector1 = { a[W], a[X], a[Z], a[Y] } + const LLQuad vector1 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // Set vector2 = { b[W], b[Y], b[X], b[Z] } + const LLQuad vector2 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } + mQ = _mm_mul_ps( vector1, vector2 ); + // vector3 = { a[W], a[Y], a[X], a[Z] } + const LLQuad vector3 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // vector4 = { b[W], b[X], b[Z], b[Y] } + const LLQuad vector4 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } + mQ = _mm_sub_ps( mQ, _mm_mul_ps( vector3, vector4 )); +} + +/* This function works, but may be slightly slower than the one below on older machines + inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b) + { + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const LLQuad wzxy = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE(3, 2, 0, 1 )); + // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusY = _mm_add_ps(ab, wzxy); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); + // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } + const LLQuad zSplat = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE( 2, 2, 2, 2 )); + // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(zSplat, xPlusYSplat); + }*/ + +// Set all elements to the dot product of the x, y, and z elements in a and b +inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b) +{ + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i wzxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(3, 2, 0, 1 )); + // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusY = _mm_add_ps(ab, _mm_castsi128_ps(wzxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); + // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } + const __m128i zSplat = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE( 2, 2, 2, 2 )); + // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(_mm_castsi128_ps(zSplat), xPlusYSplat); +} + +// Set all elements to the dot product of the x, y, z, and w elements in a and b +inline void LLVector4a::setAllDot4(const LLVector4a& a, const LLVector4a& b) +{ + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i zwxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(2, 3, 0, 1 )); + // zPlusWandXplusY = { a[W]*b[W] + a[Z]*b[Z], a[Z] * b[Z] + a[W]*b[W], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad zPlusWandXplusY = _mm_add_ps(ab, _mm_castsi128_ps(zwxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(zPlusWandXplusY, zPlusWandXplusY); + const LLQuad zPlusWSplat = _mm_movehl_ps(zPlusWandXplusY, zPlusWandXplusY); + + // mQ = { a[W]*b[W] + a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(xPlusYSplat, zPlusWSplat); +} + +// Return the 3D dot product of this vector and b +inline LLSimdScalar LLVector4a::dot3(const LLVector4a& b) const +{ + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + const LLQuad splatY = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(1, 1, 1, 1) ) ); + const LLQuad splatZ = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(2, 2, 2, 2) ) ); + const LLQuad xPlusY = _mm_add_ps( ab, splatY ); + return _mm_add_ps( xPlusY, splatZ ); +} + +// Return the 4D dot product of this vector and b +inline LLSimdScalar LLVector4a::dot4(const LLVector4a& b) const +{ + // ab = { w, z, y, x } + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + // upperProdsInLowerElems = { y, x, y, x } + const LLQuad upperProdsInLowerElems = _mm_movehl_ps( ab, ab ); + // sumOfPairs = { w+y, z+x, 2y, 2x } + const LLQuad sumOfPairs = _mm_add_ps( upperProdsInLowerElems, ab ); + // shuffled = { z+x, z+x, z+x, z+x } + const LLQuad shuffled = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( sumOfPairs ), _MM_SHUFFLE(1, 1, 1, 1) ) ); + return _mm_add_ss( sumOfPairs, shuffled ); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize3() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); +} + +// Normalize this vector with respect to all components. Accurate to 22 bites of precision. +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize4() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot4( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline LLSimdScalar LLVector4a::normalize3withLength() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); + return _mm_sqrt_ss(lenSqrd); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize3fast() +{ + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + mQ = _mm_mul_ps( mQ, approxRsqrt ); +} + +// Return true if this vector is normalized with respect to x,y,z up to tolerance +inline LLBool32 LLVector4a::isNormalized3( F32 tolerance ) const +{ + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot3( *this, *this ); + lenSquared.sub( *reinterpret_cast(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); +} + +// Return true if this vector is normalized with respect to all components up to tolerance +inline LLBool32 LLVector4a::isNormalized4( F32 tolerance ) const +{ + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot4( *this, *this ); + lenSquared.sub( *reinterpret_cast(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); +} + +// Set all elements to the length of vector 'v' +inline void LLVector4a::setAllLength3( const LLVector4a& v ) +{ + LLVector4a lenSqrd; + lenSqrd.setAllDot3(v, v); + + mQ = _mm_sqrt_ps(lenSqrd.mQ); +} + +// Get this vector's length +inline LLSimdScalar LLVector4a::getLength3() const +{ + return _mm_sqrt_ss( dot3( (const LLVector4a)mQ ) ); +} + +// Set the components of this vector to the minimum of the corresponding components of lhs and rhs +inline void LLVector4a::setMin(const LLVector4a& lhs, const LLVector4a& rhs) +{ + mQ = _mm_min_ps(lhs.mQ, rhs.mQ); +} + +// Set the components of this vector to the maximum of the corresponding components of lhs and rhs +inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs) +{ + mQ = _mm_max_ps(lhs.mQ, rhs.mQ); +} + +// Set this to (c * lhs) + rhs * ( 1 - c) +inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c) +{ + LLVector4a a = lhs; + a.mul(c); + + LLVector4a b = rhs; + b.mul(1.f-c); + + setAdd(a, b); +} + +inline LLBool32 LLVector4a::isFinite3() const +{ + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + const __m128i nanOrInfMaskV = *reinterpret_cast (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZ ); +} + +inline LLBool32 LLVector4a::isFinite4() const +{ + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + const __m128i nanOrInfMaskV = *reinterpret_cast (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZW ); +} + +inline void LLVector4a::setRotatedInv( const LLRotation& rot, const LLVector4a& vec ) +{ + LLRotation inv; inv.setTranspose( rot ); + setRotated( inv, vec ); +} + +inline void LLVector4a::setRotatedInv( const LLQuaternion2& quat, const LLVector4a& vec ) +{ + LLQuaternion2 invRot; invRot.setConjugate( quat ); + setRotated(invRot, vec); +} + +inline void LLVector4a::clamp( const LLVector4a& low, const LLVector4a& high ) +{ + const LLVector4Logical highMask = greaterThan( high ); + const LLVector4Logical lowMask = lessThan( low ); + + setSelectWithMask( highMask, high, *this ); + setSelectWithMask( lowMask, low, *this ); +} + + +//////////////////////////////////// +// LOGICAL +//////////////////////////////////// +// The functions in this section will compare the elements in this vector +// to those in rhs and return an LLVector4Logical with all bits set in elements +// where the comparison was true and all bits unset in elements where the comparison +// was false. See llvector4logica.h +//////////////////////////////////// +// WARNING: Other than equals3 and equals4, these functions do NOT account +// for floating point tolerance. You should include the appropriate tolerance +// in the inputs. +//////////////////////////////////// + +inline LLVector4Logical LLVector4a::greaterThan(const LLVector4a& rhs) const +{ + return _mm_cmpgt_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::lessThan(const LLVector4a& rhs) const +{ + return _mm_cmplt_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::greaterEqual(const LLVector4a& rhs) const +{ + return _mm_cmpge_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::lessEqual(const LLVector4a& rhs) const +{ + return _mm_cmple_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::equal(const LLVector4a& rhs) const +{ + return _mm_cmpeq_ps(mQ, rhs.mQ); +} + +// Returns true if this and rhs are componentwise equal up to the specified absolute tolerance +inline bool LLVector4a::equals4(const LLVector4a& rhs, F32 tolerance ) const +{ + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad cmp = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( cmp ) & LLVector4Logical::MASK_XYZW) == LLVector4Logical::MASK_XYZW; +} + +inline bool LLVector4a::equals3(const LLVector4a& rhs, F32 tolerance ) const +{ + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad t = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( t ) & LLVector4Logical::MASK_XYZ) == LLVector4Logical::MASK_XYZ; + +} + +//////////////////////////////////// +// OPERATORS +//////////////////////////////////// + +// Do NOT add aditional operators without consulting someone with SSE experience +inline const LLVector4a& LLVector4a::operator= ( const LLVector4a& rhs ) +{ + mQ = rhs.mQ; + return *this; +} + +inline const LLVector4a& LLVector4a::operator= ( const LLQuad& rhs ) +{ + mQ = rhs; + return *this; +} + +inline LLVector4a::operator LLQuad() const +{ + return mQ; +} diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h new file mode 100644 index 0000000000..1c7ee1d79f --- /dev/null +++ b/indra/llmath/llvector4logical.h @@ -0,0 +1,130 @@ +/** + * @file llvector4logical.h + * @brief LLVector4Logical class header file - Companion class to LLVector4a for logical and bit-twiddling operations + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_VECTOR4LOGICAL_H +#define LL_VECTOR4LOGICAL_H + + +//////////////////////////// +// LLVector4Logical +//////////////////////////// +// This class is incomplete. If you need additional functionality, +// for example setting/unsetting particular elements or performing +// other boolean operations, feel free to implement. If you need +// assistance in determining the most optimal implementation, +// contact someone with SSE experience (Falcon, Richard, Davep, e.g.) +//////////////////////////// + +static LL_ALIGN_16(const U32 S_V4LOGICAL_MASK_TABLE[4*4]) = +{ + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF +}; + +class LLVector4Logical +{ +public: + + enum { + MASK_X = 1, + MASK_Y = 1 << 1, + MASK_Z = 1 << 2, + MASK_W = 1 << 3, + MASK_XYZ = MASK_X | MASK_Y | MASK_Z, + MASK_XYZW = MASK_XYZ | MASK_W + }; + + // Empty default ctor + LLVector4Logical() {} + + LLVector4Logical( const LLQuad& quad ) + { + mQ = quad; + } + + // Create and return a mask consisting of the lowest order bit of each element + inline U32 getGatheredBits() const + { + return _mm_movemask_ps(mQ); + }; + + // Invert this mask + inline LLVector4Logical& invert() + { + static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); + return *this; + } + + inline LLBool32 areAllSet( U32 mask ) const + { + return ( getGatheredBits() & mask) == mask; + } + + inline LLBool32 areAllSet() const + { + return areAllSet( MASK_XYZW ); + } + + inline LLBool32 areAnySet( U32 mask ) const + { + return getGatheredBits() & mask; + } + + inline LLBool32 areAnySet() const + { + return areAnySet( MASK_XYZW ); + } + + inline operator LLQuad() const + { + return mQ; + } + + inline void clear() + { + mQ = _mm_setzero_ps(); + } + + template void setElement() + { + mQ = _mm_or_ps( mQ, *reinterpret_cast(S_V4LOGICAL_MASK_TABLE + 4*N) ); + } + +private: + + LLQuad mQ; +}; + +#endif //LL_VECTOR4ALOGICAL_H diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp new file mode 100644 index 0000000000..194b1faf81 --- /dev/null +++ b/indra/llmath/llvolumeoctree.cpp @@ -0,0 +1,208 @@ +/** + + * @file llvolumeoctree.cpp + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llvolumeoctree.h" +#include "llvector4a.h" + +BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size) +{ + LLVector4a fAWdU; + LLVector4a dir; + LLVector4a diff; + + dir.setSub(end, start); + dir.mul(0.5f); + + diff.setAdd(end,start); + diff.mul(0.5f); + diff.sub(center); + fAWdU.setAbs(dir); + + LLVector4a rhs; + rhs.setAdd(size, fAWdU); + + LLVector4a lhs; + lhs.setAbs(diff); + + U32 grt = lhs.greaterThan(rhs).getGatheredBits(); + + if (grt & 0x7) + { + return false; + } + + LLVector4a f; + f.setCross3(dir, diff); + f.setAbs(f); + + LLVector4a v0, v1; + + v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); + lhs.setMul(v0, v1); + + v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); + rhs.setMul(v0, v1); + rhs.add(lhs); + + grt = f.greaterThan(rhs).getGatheredBits(); + + return (grt & 0x7) ? false : true; +} + + +LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode* node) +{ + node->addListener(this); + + mBounds = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*4); + mExtents = mBounds+2; +} + +LLVolumeOctreeListener::~LLVolumeOctreeListener() +{ + ll_aligned_free_16(mBounds); +} + +void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode* parent, + LLOctreeNode* child) +{ + new LLVolumeOctreeListener(child); +} + + +LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + const LLVolumeFace* face, F32* closest_t, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) + : mFace(face), + mStart(start), + mDir(dir), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mBinormal(bi_normal), + mClosestT(closest_t), + mHitFace(false) +{ + mEnd.setAdd(mStart, mDir); +} + +void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode* node) +{ + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); + + /*const F32* start = mStart.getF32(); + const F32* end = mEnd.getF32(); + const F32* center = vl->mBounds[0].getF32(); + const F32* size = vl->mBounds[1].getF32();*/ + + //if (LLLineSegmentBoxIntersect(mStart.getF32(), mEnd.getF32(), vl->mBounds[0].getF32(), vl->mBounds[1].getF32())) + if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) + { + node->accept(this); + for (S32 i = 0; i < node->getChildCount(); ++i) + { + traverse(node->getChild(i)); + } + } +} + +void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode* node) +{ + for (LLOctreeNode::const_element_iter iter = + node->getData().begin(); iter != node->getData().end(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + F32 a, b, t; + + if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], + mStart, mDir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < *mClosestT)) // and this hit is closer + { + *mClosestT = t; + mHitFace = true; + + if (mIntersection != NULL) + { + LLVector4a intersect = mDir; + intersect.mul(*mClosestT); + intersect.add(mStart); + mIntersection->set(intersect.getF32ptr()); + } + + + if (mTexCoord != NULL) + { + LLVector2* tc = (LLVector2*) mFace->mTexCoords; + *mTexCoord = ((1.f - a - b) * tc[tri->mIndex[0]] + + a * tc[tri->mIndex[1]] + + b * tc[tri->mIndex[2]]); + + } + + if (mNormal != NULL) + { + LLVector4* norm = (LLVector4*) mFace->mNormals; + + *mNormal = ((1.f - a - b) * LLVector3(norm[tri->mIndex[0]]) + + a * LLVector3(norm[tri->mIndex[1]]) + + b * LLVector3(norm[tri->mIndex[2]])); + } + + if (mBinormal != NULL) + { + LLVector4* binormal = (LLVector4*) mFace->mBinormals; + *mBinormal = ((1.f - a - b) * LLVector3(binormal[tri->mIndex[0]]) + + a * LLVector3(binormal[tri->mIndex[1]]) + + b * LLVector3(binormal[tri->mIndex[2]])); + } + } + } + } +} + +const LLVector4a& LLVolumeTriangle::getPositionGroup() const +{ + return *mPositionGroup; +} + +const F32& LLVolumeTriangle::getBinRadius() const +{ + return mRadius; +} + + diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h new file mode 100644 index 0000000000..0031626498 --- /dev/null +++ b/indra/llmath/llvolumeoctree.h @@ -0,0 +1,138 @@ +/** + * @file llvolumeoctree.h + * @brief LLVolume octree classes. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVOLUME_OCTREE_H +#define LL_LLVOLUME_OCTREE_H + +#include "linden_common.h" +#include "llmemory.h" + +#include "lloctree.h" +#include "llvolume.h" +#include "llvector4a.h" + +class LLVolumeOctreeListener : public LLOctreeListener +{ +public: + + LLVolumeOctreeListener(LLOctreeNode* node); + ~LLVolumeOctreeListener(); + + LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) + { + *this = rhs; + } + + const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + + //LISTENER FUNCTIONS + virtual void handleChildAddition(const LLOctreeNode* parent, + LLOctreeNode* child); + virtual void handleStateChange(const LLTreeNode* node) { } + virtual void handleChildRemoval(const LLOctreeNode* parent, + const LLOctreeNode* child) { } + virtual void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleDestruction(const LLTreeNode* node) { } + + +public: + LLVector4a* mBounds; // bounding box (center, size) of this node and all its children (tight fit to objects) + LLVector4a* mExtents; // extents (min, max) of this node and all its children +}; + +class LLOctreeTriangleRayIntersect : public LLOctreeTraveler +{ +public: + const LLVolumeFace* mFace; + LLVector4a mStart; + LLVector4a mDir; + LLVector4a mEnd; + LLVector3* mIntersection; + LLVector2* mTexCoord; + LLVector3* mNormal; + LLVector3* mBinormal; + F32* mClosestT; + bool mHitFace; + + LLOctreeTriangleRayIntersect() { }; + + LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + const LLVolumeFace* face, F32* closest_t, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal); + + void traverse(const LLOctreeNode* node); + + virtual void visit(const LLOctreeNode* node); +}; + +class LLVolumeTriangle : public LLRefCount +{ +public: + LLVolumeTriangle() + { + mPositionGroup = (LLVector4a*) ll_aligned_malloc_16(16); + } + + LLVolumeTriangle(const LLVolumeTriangle& rhs) + { + *this = rhs; + } + + const LLVolumeTriangle& operator=(const LLVolumeTriangle& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + + ~LLVolumeTriangle() + { + ll_aligned_free_16(mPositionGroup); + } + + const LLVector4a* mV[3]; + U16 mIndex[3]; + + LLVector4a* mPositionGroup; + + F32 mRadius; + + virtual const LLVector4a& getPositionGroup() const; + virtual const F32& getBinRadius() const; +}; + + +#endif diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp new file mode 100644 index 0000000000..82765c740f --- /dev/null +++ b/indra/llprimitive/llmodel.cpp @@ -0,0 +1,1695 @@ +/** + * @file llmodel.cpp + * @brief Model handling implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llmodel.h" +#include "llsdserialize.h" +#include "llvector4a.h" + +#include "dae.h" +#include "dae/daeErrorHandler.h" +#include "dom/domConstants.h" +#include "dom/domMesh.h" +#include "zlib/zlib.h" + +#if LL_MESH_ENABLED + +std::string model_names[] = +{ + "lowest_lod", + "low_lod", + "medium_lod", + "high_lod", + "physics_shape" +}; + +const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string); + +LLModel::LLModel(LLVolumeParams& params, F32 detail) + : LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0) +{ + +} + +void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Array& inputs, U32 min_idx, U32 max_idx) +{ + for (U32 j = 0; j < inputs.getCount(); ++j) + { + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) + { //found vertex array + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + + domInputLocal_Array& v_inp = vertices->getInput_array(); + if (inputs[j]->getOffset() != 0) + { + llerrs << "WTF?" << llendl; + } + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + const domURIFragmentType& uri = v_inp[k]->getSource(); + + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + + if (src->getTechnique_common()->getAccessor()->getStride() != 3) + { + llerrs << "WTF?" << llendl; + } + + domListOfFloats& v = src->getFloat_array()->getValue(); + + LLVector4a min; + min.set(v[min_idx], v[min_idx+1], v[min_idx+2]); + LLVector4a max = min; + + for (U32 j = min_idx; j <= max_idx; ++j) + { //copy vertex array + face.mPositions[j-min_idx].set(v[j*3+0], v[j*3+1], v[j*3+2]); + update_min_max(min, max, face.mPositions[j-min_idx]); + } + + face.mExtents[0] = min; + face.mExtents[1] = max; + } + } + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + { + //found normal array for this triangle list + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + domListOfFloats& n = src->getFloat_array()->getValue(); + + for (U32 j = min_idx; j <= max_idx; ++j) + { + LLVector4a* norm = (LLVector4a*) face.mNormals + (j-min_idx); + norm->set(n[j*3+0], n[j*3+1], n[j*3+2]); + norm->normalize3fast(); + } + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) + { //found texCoords + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + domListOfFloats& u = src->getFloat_array()->getValue(); + + for (U32 j = min_idx; j <= max_idx; ++j) + { + face.mTexCoords[j-min_idx].setVec(u[j*2+0], u[j*2+1]); + } + } + } +} + +void get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, + domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +{ + idx_stride = 0; + + for (U32 j = 0; j < inputs.getCount(); ++j) + { + idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) + { //found vertex array + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + + domInputLocal_Array& v_inp = vertices->getInput_array(); + + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + pos_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + pos_source = (domSource*) elem.cast(); + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) + { + norm_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + } + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + { + //found normal array for this triangle list + norm_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) + { //found texCoords + tc_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + tc_source = (domSource*) elem.cast(); + } + } + + idx_stride += 1; +} + +void load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri) +{ + LLVolumeFace face; + std::vector verts; + std::vector indices; + + const domInputLocalOffset_Array& inputs = tri->getInput_array(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source); + + domPRef p = tri->getP(); + domListOfUInts& idx = p->getValue(); + + domListOfFloats v; + domListOfFloats tc; + domListOfFloats n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < idx.getCount(); i += idx_stride) + { + LLVolumeFace::VertexData cv; + if (pos_source) + { + cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], + v[idx[i+pos_offset]*3+1], + v[idx[i+pos_offset]*3+2])); + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], + tc[idx[i+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], + n[idx[i+norm_offset]*3+1], + n[idx[i+norm_offset]*3+2])); + } + + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + + if (point_iter != point_map.end()) + { + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + if ((point_iter->second)[j] == cv) + { + found = TRUE; + indices.push_back((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; + } + U16 index = (U16) (verts.size()-1); + indices.push_back(index); + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + } + } + + if (indices.size()%3 == 0 && verts.size() >= 65532) + { + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + face = LLVolumeFace(); + point_map.clear(); + } + + } + + if (!verts.empty()) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + + face_list.rbegin()->fillFromLegacyData(verts, indices); + } + +} + +void load_face_from_dom_polylist(std::vector& face_list, std::vector& materials, domPolylistRef& poly) +{ + domPRef p = poly->getP(); + domListOfUInts& idx = p->getValue(); + + if (idx.getCount() == 0) + { + return; + } + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + domListOfUInts& vcount = poly->getVcount()->getValue(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source); + + LLVolumeFace face; + + std::vector indices; + std::vector verts; + + domListOfFloats v; + domListOfFloats tc; + domListOfFloats n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + U32 cur_idx = 0; + for (U32 i = 0; i < vcount.getCount(); ++i) + { //for each polygon + U32 first_index = 0; + U32 last_index = 0; + for (U32 j = 0; j < vcount[i]; ++j) + { //for each vertex + + LLVolumeFace::VertexData cv; + + if (pos_source) + { + cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], + v[idx[cur_idx+pos_offset]*3+1], + v[idx[cur_idx+pos_offset]*3+2]); + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], + tc[idx[cur_idx+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], + n[idx[cur_idx+norm_offset]*3+1], + n[idx[cur_idx+norm_offset]*3+2]); + } + + cur_idx += idx_stride; + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + LLVector3 pos3(cv.getPosition().getF32ptr()); + point_iter = point_map.find(pos3); + + if (point_iter != point_map.end()) + { + for (U32 k = 0; k < point_iter->second.size(); ++k) + { + if ((point_iter->second)[k] == cv) + { + found = TRUE; + U32 index = (point_iter->second)[k].mIndex; + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; + } + U16 index = (U16) (verts.size()-1); + + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos3].push_back(d); + } + } + + if (indices.size()%3 == 0 && indices.size() >= 65532) + { + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + face = LLVolumeFace(); + verts.clear(); + indices.clear(); + point_map.clear(); + } + } + } + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + } +} + +void load_face_from_dom_polygons(std::vector& face_list, std::vector& materials, domPolygonsRef& poly) +{ + LLVolumeFace face; + std::vector indices; + std::vector verts; + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + S32 v_offset = -1; + S32 n_offset = -1; + S32 t_offset = -1; + + domListOfFloats* v = NULL; + domListOfFloats* n = NULL; + domListOfFloats* t = NULL; + + U32 stride = 0; + for (U32 i = 0; i < inputs.getCount(); ++i) + { + stride = llmax((U32) inputs[i]->getOffset()+1, stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) + { //found vertex array + v_offset = inputs[i]->getOffset(); + + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + + domInputLocal_Array& v_inp = vertices->getInput_array(); + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + v = &(src->getFloat_array()->getValue()); + } + } + } + else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) + { + n_offset = inputs[i]->getOffset(); + //found normal array for this triangle list + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + n = &(src->getFloat_array()->getValue()); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) + { //found texCoords + t_offset = inputs[i]->getOffset(); + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + t = &(src->getFloat_array()->getValue()); + } + } + + domP_Array& ps = poly->getP_array(); + + //make a triangle list in + for (U32 i = 0; i < ps.getCount(); ++i) + { //for each polygon + domListOfUInts& idx = ps[i]->getValue(); + for (U32 j = 0; j < idx.getCount()/stride; ++j) + { //for each vertex + if (j > 2) + { + U32 size = verts.size(); + LLVolumeFace::VertexData v0 = verts[size-3]; + LLVolumeFace::VertexData v1 = verts[size-1]; + + verts.push_back(v0); + verts.push_back(v1); + } + + LLVolumeFace::VertexData vert; + + + if (v) + { + U32 v_idx = idx[j*stride+v_offset]*3; + vert.getPosition().set(v->get(v_idx), + v->get(v_idx+1), + v->get(v_idx+2)); + } + + if (n) + { + U32 n_idx = idx[j*stride+n_offset]*3; + vert.getNormal().set(n->get(n_idx), + n->get(n_idx+1), + n->get(n_idx+2)); + } + + if (t) + { + U32 t_idx = idx[j*stride+t_offset]*2; + vert.mTexCoord.setVec(t->get(t_idx), + t->get(t_idx+1)); + } + + + verts.push_back(vert); + } + } + + if (verts.empty()) + { + return; + } + + face.mExtents[0] = verts[0].getPosition(); + face.mExtents[1] = verts[0].getPosition(); + + //create a map of unique vertices to indices + std::map vert_idx; + + U32 cur_idx = 0; + for (U32 i = 0; i < verts.size(); ++i) + { + std::map::iterator iter = vert_idx.find(verts[i]); + if (iter == vert_idx.end()) + { + vert_idx[verts[i]] = cur_idx++; + } + } + + //build vertex array from map + verts.resize(vert_idx.size()); + + for (std::map::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) + { + verts[iter->second] = iter->first; + update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); + } + + //build index array from map + indices.resize(verts.size()); + + for (U32 i = 0; i < verts.size(); ++i) + { + indices[i] = vert_idx[verts[i]]; + } + + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + } +} + +void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) +{ + domTriangles_Array& tris = mesh->getTriangles_array(); + + for (U32 i = 0; i < tris.getCount(); ++i) + { + domTrianglesRef& tri = tris.get(i); + + load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); + } + + domPolylist_Array& polys = mesh->getPolylist_array(); + for (U32 i = 0; i < polys.getCount(); ++i) + { + domPolylistRef& poly = polys.get(i); + + load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); + } + + domPolygons_Array& polygons = mesh->getPolygons_array(); + for (U32 i = 0; i < polygons.getCount(); ++i) + { + domPolygonsRef& poly = polygons.get(i); + + load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); + } + +} + +BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) +{ + if (mesh) + { + mVolumeFaces.clear(); + mMaterialList.clear(); + + addVolumeFacesFromDomMesh(mesh); + + if (getNumVolumeFaces() > 0) + { + optimizeVolumeFaces(); + normalizeVolumeFaces(); + + if (getNumVolumeFaces() > 0) + { + return TRUE; + } + } + } + else + { + llwarns << "no mesh found" << llendl; + } + + return FALSE; +} + + +BOOL LLModel::createVolumeFacesFromFile(const std::string& file_name) +{ + DAE dae; + domCOLLADA* dom = dae.open(file_name); + if (dom) + { + daeDatabase* db = dae.getDatabase(); + + daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); + + mVolumeFaces.clear(); + mMaterialList.clear(); + + for (daeInt idx = 0; idx < count; ++idx) + { + domMesh* mesh = NULL; + + db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); + + if (mesh) + { + addVolumeFacesFromDomMesh(mesh); + } + } + + if (getNumVolumeFaces() > 0) + { + optimizeVolumeFaces(); + normalizeVolumeFaces(); + return TRUE; + } + } + + return FALSE; +} + + +void LLModel::optimizeVolumeFaces() +{ +#if 0 //VECTORIZE ? + for (std::vector::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ) + { + std::vector::iterator cur_iter = iter++; + LLVolumeFace& face = *cur_iter; + + for (S32 i = 0; i < (S32) face.mNumIndices; i += 3) + { //remove zero area triangles + U16 i0 = face.mIndices[i+0]; + U16 i1 = face.mIndices[i+1]; + U16 i2 = face.mIndices[i+2]; + + if (i0 == i1 || + i1 == i2 || + i0 == i2) + { //duplicate index in triangle, remove triangle + face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3); + i -= 3; + } + else + { + LLVolumeFace::VertexData& v0 = face.mVertices[i0]; + LLVolumeFace::VertexData& v1 = face.mVertices[i1]; + LLVolumeFace::VertexData& v2 = face.mVertices[i2]; + + if (v0.mPosition == v1.mPosition || + v1.mPosition == v2.mPosition || + v2.mPosition == v0.mPosition) + { //zero area triangle, delete + face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3); + i-=3; + } + } + } + + //remove unreference vertices + std::vector ref; + ref.resize(face.mNumVertices); + + for (U32 i = 0; i < ref.size(); ++i) + { + ref[i] = false; + } + + for (U32 i = 0; i < face.mNumIndices; ++i) + { + ref[face.mIndices[i]] = true; + } + + U32 unref_count = 0; + for (U32 i = 0; i < ref.size(); ++i) + { + if (!ref[i]) + { + //vertex is unreferenced + face.mVertices.erase(face.mVertices.begin()+(i-unref_count)); + U16 idx = (U16) (i-unref_count); + + for (U32 j = 0; j < face.mNumIndices; ++j) + { //decrement every index array value greater than idx + if (face.mIndices[j] > idx) + { + --face.mIndices[j]; + } + } + ++unref_count; + } + } + + if (face.mVertices.empty() || face.mIndices.empty()) + { //face is empty, remove it + iter = mVolumeFaces.erase(cur_iter); + } + } +#endif +} + +void LLModel::normalizeVolumeFaces() +{ + + // ensure we don't have too many faces + if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES) + mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES); + + if (!mVolumeFaces.empty()) + { + LLVector4a min, max; + + if (mVolumeFaces[0].mNumVertices <= 0) + { + llerrs << "WTF?" << llendl; + } + + min = mVolumeFaces[0].mExtents[0]; + max = mVolumeFaces[0].mExtents[1]; + + for (U32 i = 1; i < mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + if (face.mNumVertices <= 0) + { + llerrs << "WTF?" << llendl; + } + + update_min_max(min, max, face.mExtents[0]); + update_min_max(min, max, face.mExtents[1]); + } + + LLVector4a trans; + trans.setAdd(min, max); + trans.mul(-0.5f); + LLVector4a size; + size.setSub(max, min); + + F32 scale = 1.f/llmax(llmax(size[0], size[1]), size[2]); + + for (U32 i = 0; i < mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + face.mExtents[0].add(trans); + face.mExtents[0].mul(scale); + + face.mExtents[1].add(trans); + face.mExtents[1].mul(scale); + + LLVector4a* pos = (LLVector4a*) face.mPositions; + for (U32 j = 0; j < face.mNumVertices; ++j) + { + pos[j].add(trans); + pos[j].mul(scale); + } + } + + mNormalizedScale = LLVector3(1,1,1) / scale; + mNormalizedTranslation.set(trans.getF32ptr()); + mNormalizedTranslation *= -1.f; + } +} + +void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) +{ + scale_out = mNormalizedScale; + translation_out = mNormalizedTranslation; +} + +void LLModel::setNumVolumeFaces(S32 count) +{ + mVolumeFaces.resize(count); +} + +void LLModel::setVolumeFaceData(S32 f, + LLStrider pos, + LLStrider norm, + LLStrider tc, + LLStrider ind, + U32 num_verts, + U32 num_indices) +{ + LLVolumeFace& face = mVolumeFaces[f]; + + face.resizeVertices(num_verts); + face.resizeIndices(num_indices); + + LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); + U32 size = (num_indices*2+0xF)&~0xF; + LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size); +} + +void LLModel::appendFaces(LLModel *model, LLMatrix4 &transform, LLMatrix4& norm_mat) +{ + if (mVolumeFaces.empty()) + { + setNumVolumeFaces(1); + } + + LLVolumeFace& face = mVolumeFaces[mVolumeFaces.size()-1]; + + + for (S32 i = 0; i < model->getNumFaces(); ++i) + { + face.appendFace(model->getVolumeFace(i), transform, norm_mat); + } + +} + +void LLModel::appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat) +{ + S32 rindex = getNumVolumeFaces()-1; + if (rindex == -1 || + mVolumeFaces[rindex].mNumVertices + src_face.mNumVertices >= 65536) + { //empty or overflow will occur, append new face + LLVolumeFace cur_face; + cur_face.appendFace(src_face, mat, norm_mat); + addFace(cur_face); + mMaterialList.push_back(src_material); + } + else + { //append to existing end face + mVolumeFaces.rbegin()->appendFace(src_face, mat, norm_mat); + } +} + +void LLModel::addFace(const LLVolumeFace& face) +{ + if (face.mNumVertices == 0) + { + llerrs << "Cannot add empty face." << llendl; + } + + mVolumeFaces.push_back(face); + + if (mVolumeFaces.size() > MAX_MODEL_FACES) + { + llerrs << "Model prims cannot have more than " << MAX_MODEL_FACES << " faces!" << llendl; + } +} + + +void LLModel::smoothNormals(F32 angle_cutoff) +{ + //smooth normals for all faces by: + // 1 - Create faceted copy of face with no texture coordinates + // 2 - Weld vertices in faceted copy that are shared between triangles with less than "angle_cutoff" difference between normals + // 3 - Generate smoothed set of normals based on welding results + // 4 - Create faceted copy of face with texture coordinates + // 5 - Copy smoothed normals to faceted copy, using closest normal to triangle normal where more than one normal exists for a given position + // 6 - Remove redundant vertices from new faceted (now smooth) copy + + angle_cutoff = cosf(angle_cutoff); + for (U32 j = 0; j < mVolumeFaces.size(); ++j) + { + LLVolumeFace& vol_face = mVolumeFaces[j]; + + //create faceted copy of current face with no texture coordinates (step 1) + LLVolumeFace faceted; + + LLVector4a* src_pos = (LLVector4a*) vol_face.mPositions; + //LLVector4a* src_norm = (LLVector4a*) vol_face.mNormals; + + + //bake out triangles into temporary face, clearing normals and texture coordinates + for (U32 i = 0; i < vol_face.mNumIndices; ++i) + { + U32 idx = vol_face.mIndices[i]; + LLVolumeFace::VertexData v; + v.setPosition(src_pos[idx]); + v.getNormal().clear(); + v.mTexCoord.clear(); + faceted.pushVertex(v); + faceted.pushIndex(i); + } + + //generate normals for temporary face + for (U32 i = 0; i < faceted.mNumIndices; i += 3) + { //for each triangle + U16 i0 = faceted.mIndices[i+0]; + U16 i1 = faceted.mIndices[i+1]; + U16 i2 = faceted.mIndices[i+2]; + + LLVector4a& p0 = faceted.mPositions[i0]; + LLVector4a& p1 = faceted.mPositions[i1]; + LLVector4a& p2 = faceted.mPositions[i2]; + + LLVector4a& n0 = faceted.mNormals[i0]; + LLVector4a& n1 = faceted.mNormals[i1]; + LLVector4a& n2 = faceted.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + n0.setCross3(lhs, rhs); + n0.normalize3fast(); + n1 = n0; + n2 = n0; + } + + //weld vertices in temporary face, respecting angle_cutoff (step 2) + faceted.optimize(angle_cutoff); + + //generate normals for welded face based on new topology (step 3) + + for (U32 i = 0; i < faceted.mNumVertices; i++) + { + faceted.mNormals[i].clear(); + } + + for (U32 i = 0; i < faceted.mNumIndices; i += 3) + { //for each triangle + U16 i0 = faceted.mIndices[i+0]; + U16 i1 = faceted.mIndices[i+1]; + U16 i2 = faceted.mIndices[i+2]; + + LLVector4a& p0 = faceted.mPositions[i0]; + LLVector4a& p1 = faceted.mPositions[i1]; + LLVector4a& p2 = faceted.mPositions[i2]; + + LLVector4a& n0 = faceted.mNormals[i0]; + LLVector4a& n1 = faceted.mNormals[i1]; + LLVector4a& n2 = faceted.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + LLVector4a n; + n.setCross3(lhs, rhs); + + n0.add(n); + n1.add(n); + n2.add(n); + } + + //normalize normals and build point map + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < faceted.mNumVertices; ++i) + { + faceted.mNormals[i].normalize3fast(); + + LLVolumeFace::VertexMapData v; + v.setPosition(faceted.mPositions[i]); + v.setNormal(faceted.mNormals[i]); + + point_map[LLVector3(v.getPosition().getF32ptr())].push_back(v); + } + + //create faceted copy of current face with texture coordinates (step 4) + LLVolumeFace new_face; + + //bake out triangles into new face + for (U32 i = 0; i < vol_face.mNumIndices; ++i) + { + U32 idx = vol_face.mIndices[i]; + LLVolumeFace::VertexData v; + v.setPosition(vol_face.mPositions[idx]); + v.setNormal(vol_face.mNormals[idx]); + v.mTexCoord = vol_face.mTexCoords[idx]; + + new_face.pushVertex(v); + new_face.pushIndex(i); + } + + //generate normals for new face + for (U32 i = 0; i < new_face.mNumIndices; i += 3) + { //for each triangle + U16 i0 = new_face.mIndices[i+0]; + U16 i1 = new_face.mIndices[i+1]; + U16 i2 = new_face.mIndices[i+2]; + + LLVector4a& p0 = new_face.mPositions[i0]; + LLVector4a& p1 = new_face.mPositions[i1]; + LLVector4a& p2 = new_face.mPositions[i2]; + + LLVector4a& n0 = new_face.mNormals[i0]; + LLVector4a& n1 = new_face.mNormals[i1]; + LLVector4a& n2 = new_face.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + n0.setCross3(lhs, rhs); + n0.normalize3fast(); + n1 = n0; + n2 = n0; + } + + //swap out normals in new_face with best match from point map (step 5) + for (U32 i = 0; i < new_face.mNumVertices; ++i) + { + //LLVolumeFace::VertexData v = new_face.mVertices[i]; + + LLVector4a ref_norm = new_face.mNormals[i]; + + LLVolumeFace::VertexMapData::PointMap::iterator iter = point_map.find(LLVector3(new_face.mPositions[i].getF32ptr())); + + if (iter != point_map.end()) + { + F32 best = -2.f; + for (U32 k = 0; k < iter->second.size(); ++k) + { + LLVector4a& n = iter->second[k].getNormal(); + + if (!iter->second[k].getPosition().equals3(new_face.mPositions[i])) + { + llerrs << "WTF?" << llendl; + } + + F32 cur = n.dot3(ref_norm).getF32(); + + if (cur > best) + { + best = cur; + new_face.mNormals[i] = n; + } + } + } + } + + //remove redundant vertices from new face (step 6) + new_face.optimize(); + + mVolumeFaces[j] = new_face; + } +} + +//static +std::string LLModel::getElementLabel(daeElement *element) +{ // try to get a decent label for this element + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + if (parent) + { + // if parent has a name, use it + std::string name = parent->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if parent has an ID, use it + if (parent->getID()) + { + return std::string(parent->getID()); + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name); + } + + // if all else fails, use "object" + return std::string("object"); +} + +//static +LLModel* LLModel::loadModelFromDae(std::string filename) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* ret = new LLModel(volume_params, 0.f); + ret->createVolumeFacesFromFile(filename); + return ret; +} + +//static +LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* ret = new LLModel(volume_params, 0.f); + ret->createVolumeFacesFromDomMesh(mesh); + ret->mLabel = getElementLabel(mesh); + return ret; +} + +//static +LLSD LLModel::writeModel(std::string filename, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, BOOL nowrite) +{ + std::ofstream os(filename.c_str(), std::ofstream::out | std::ofstream::binary); + + LLSD header = writeModel(os, physics, high, medium, low, impostor, decomp, nowrite); + + os.close(); + + return header; +} + +//static +LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* impostor, LLModel::physics_shape& decomp, BOOL nowrite) +{ + LLSD mdl; + + LLModel* model[] = + { + impostor, + low, + medium, + high, + physics + }; + + bool skinning = high && !high->mSkinWeights.empty(); + + if (skinning) + { //write skinning block + if (high->mJointList.size() != high->mInvBindMatrix.size()) + { + llerrs << "WTF?" << llendl; + } + + for (U32 i = 0; i < high->mJointList.size(); ++i) + { + mdl["skin"]["joint_names"][i] = high->mJointList[i]; + + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + mdl["skin"]["inverse_bind_matrix"][i][j*4+k] = high->mInvBindMatrix[i].mMatrix[j][k]; + } + } + } + + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 4; j++) + { + mdl["skin"]["bind_shape_matrix"][i*4+j] = high->mBindShapeMatrix.mMatrix[i][j]; + } + } + } + + if (!decomp.empty()) + { + //write decomposition block + // ["decomposition"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points + // ["decomposition"]["PositionDomain"]["Min"/"Max"] + // ["decomposition"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points + + //get minimum and maximum + LLVector3 min = decomp[0][0]; + LLVector3 max = min; + + LLSD::Binary hulls(decomp.size()); + + U32 total = 0; + + for (U32 i = 0; i < decomp.size(); ++i) + { + U32 size = decomp[i].size(); + total += size; + hulls[i] = (U8) size; + + for (U32 j = 0; j < decomp[i].size(); ++j) + { + update_min_max(min, max, decomp[i][j]); + } + } + + mdl["decomposition"]["Min"] = min.getValue(); + mdl["decomposition"]["Max"] = max.getValue(); + mdl["decomposition"]["HullList"] = hulls; + + LLSD::Binary p(total*3*2); + + LLVector3 range = max-min; + + U32 vert_idx = 0; + for (U32 i = 0; i < decomp.size(); ++i) + { + for (U32 j = 0; j < decomp[i].size(); ++j) + { + for (U32 k = 0; k < 3; k++) + { + //convert to 16-bit normalized across domain + U16 val = (U16) (((decomp[i][j].mV[k]-min.mV[k])/range.mV[k])*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + p[vert_idx++] = buff[0]; + p[vert_idx++] = buff[1]; + + if (vert_idx > p.size()) + { + llerrs << "WTF?" << llendl; + } + } + } + } + + mdl["decomposition"]["Position"] = p; + } + + for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) + { + if (model[idx] && model[idx]->getNumVolumeFaces() > 0) + { + LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr()); + LLVector3 max_pos = min_pos; + + //find position domain + for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i) + { //for each face + const LLVolumeFace& face = model[idx]->getVolumeFace(i); + for (U32 j = 0; j < face.mNumVertices; ++j) + { + update_min_max(min_pos, max_pos, face.mPositions[j].getF32ptr()); + } + } + + LLVector3 pos_range = max_pos - min_pos; + + for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i) + { //for each face + const LLVolumeFace& face = model[idx]->getVolumeFace(i); + if (!face.mNumVertices) + { //don't export an empty face + continue; + } + LLSD::Binary verts(face.mNumVertices*3*2); + LLSD::Binary tc(face.mNumVertices*2*2); + LLSD::Binary normals(face.mNumVertices*3*2); + LLSD::Binary indices(face.mNumIndices*2); + + U32 vert_idx = 0; + U32 norm_idx = 0; + U32 tc_idx = 0; + + LLVector2* ftc = (LLVector2*) face.mTexCoords; + LLVector2 min_tc = ftc[0]; + LLVector2 max_tc = min_tc; + + //get texture coordinate domain + for (U32 j = 0; j < face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, ftc[j]); + } + + LLVector2 tc_range = max_tc - min_tc; + + for (U32 j = 0; j < face.mNumVertices; ++j) + { //for each vert + + F32* pos = face.mPositions[j].getF32ptr(); + F32* norm = face.mNormals[j].getF32ptr(); + + //position + normal + for (U32 k = 0; k < 3; ++k) + { //for each component + + //convert to 16-bit normalized across domain + U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + verts[vert_idx++] = buff[0]; + verts[vert_idx++] = buff[1]; + + //convert to 16-bit normalized + val = (U16) ((norm[k]+1.f)*0.5f*65535); + + //write to binary buffer + normals[norm_idx++] = buff[0]; + normals[norm_idx++] = buff[1]; + } + + F32* src_tc = (F32*) face.mTexCoords[j].mV; + + //texcoord + for (U32 k = 0; k < 2; ++k) + { //for each component + //convert to 16-bit normalized + U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + tc[tc_idx++] = buff[0]; + tc[tc_idx++] = buff[1]; + } + + } + + U32 idx_idx = 0; + for (U32 j = 0; j < face.mNumIndices; ++j) + { + U8* buff = (U8*) &(face.mIndices[j]); + indices[idx_idx++] = buff[0]; + indices[idx_idx++] = buff[1]; + } + + //write out face data + mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue(); + mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue(); + + mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue(); + mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue(); + + mdl[model_names[idx]][i]["Position"] = verts; + mdl[model_names[idx]][i]["Normal"] = normals; + mdl[model_names[idx]][i]["TexCoord0"] = tc; + mdl[model_names[idx]][i]["TriangleList"] = indices; + + if (skinning) + { + //write out skin weights + + //each influence list entry is up to 4 24-bit values + // first 8 bits is bone index + // last 16 bits is bone influence weight + // a bone index of 0xFF signifies no more influences for this vertex + + std::stringstream ostr; + + for (U32 j = 0; j < face.mNumVertices; ++j) + { + LLVector3 pos(face.mPositions[j].getF32ptr()); + + weight_list& weights = high->getJointInfluences(pos); + + if (weights.size() > 4) + { + llerrs << "WTF?" << llendl; + } + + S32 count = 0; + for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter) + { + if (iter->mJointIdx < 255 && iter->mJointIdx >= 0) + { + U8 idx = (U8) iter->mJointIdx; + ostr.write((const char*) &idx, 1); + + U16 influence = (U16) (iter->mWeight*65535); + ostr.write((const char*) &influence, 2); + + ++count; + } + } + U8 end_list = 0xFF; + if (count < 4) + { + ostr.write((const char*) &end_list, 1); + } + } + + //copy ostr to binary buffer + std::string data = ostr.str(); + const U8* buff = (U8*) data.data(); + U32 bytes = data.size(); + + LLSD::Binary w(bytes); + for (U32 j = 0; j < bytes; ++j) + { + w[j] = buff[j]; + } + + mdl[model_names[idx]][i]["Weights"] = w; + } + } + } + } + + return writeModelToStream(ostr, mdl, nowrite); +} + +LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite) +{ + U32 bytes = 0; + + std::string::size_type cur_offset = 0; + + LLSD header; + + std::string skin; + + if (mdl.has("skin")) + { //write out skin block + skin = zip_llsd(mdl["skin"]); + + U32 size = skin.size(); + if (size > 0) + { + header["skin"]["offset"] = (LLSD::Integer) cur_offset; + header["skin"]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + else + { + llerrs << "WTF?" << llendl; + } + } + + std::string decomposition; + + if (mdl.has("decomposition")) + { //write out convex decomposition + decomposition = zip_llsd(mdl["decomposition"]); + + U32 size = decomposition.size(); + if (size > 0) + { + header["decomposition"]["offset"] = (LLSD::Integer) cur_offset; + header["decomposition"]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + } + + std::string out[MODEL_NAMES_LENGTH]; + + for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) + { + if (mdl.has(model_names[i])) + { + out[i] = zip_llsd(mdl[model_names[i]]); + + U32 size = out[i].size(); + + header[model_names[i]]["offset"] = (LLSD::Integer) cur_offset; + header[model_names[i]]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + else + { + header[model_names[i]]["offset"] = -1; + header[model_names[i]]["size"] = 0; + } + } + + if (!nowrite) + { + LLSDSerialize::serialize(header, ostr, LLSDSerialize::LLSD_BINARY); + + if (!skin.empty()) + { //write skin block + ostr.write((const char*) skin.data(), header["skin"]["size"].asInteger()); + } + + if (!decomposition.empty()) + { //write decomposition block + ostr.write((const char*) decomposition.data(), header["decomposition"]["size"].asInteger()); + } + + for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) + { + if (!out[i].empty()) + { + ostr.write((const char*) out[i].data(), header[model_names[i]]["size"].asInteger()); + } + } + } + + return header; +} + +//static +LLModel* LLModel::loadModelFromAsset(std::string filename, S32 lod) +{ + return NULL; +} + +LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) +{ + weight_map::iterator iter = mSkinWeights.find(pos); + + if (iter != mSkinWeights.end()) + { + if ((iter->first - pos).magVec() > 0.1f) + { + llerrs << "WTF?" << llendl; + } + + return iter->second; + } + else + { //no exact match found, get closest point + iter = mSkinWeights.begin(); + weight_map::iterator best = iter; + + F32 min_dist = (iter->first - pos).magVecSquared(); + + while (++iter != mSkinWeights.end()) + { + F32 dist = (iter->first - pos).magVecSquared(); + if (dist < min_dist) + { + best = iter; + min_dist = dist; + } + } + + return best->second; + } +} + +#endif + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h new file mode 100644 index 0000000000..a91c80d5b7 --- /dev/null +++ b/indra/llprimitive/llmodel.h @@ -0,0 +1,179 @@ +/** + * @file llmodel.h + * @brief Model handling class definitions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMODEL_H +#define LL_LLMODEL_H + +#include "llvolume.h" +#include "v4math.h" +#include "m4math.h" + +#if LL_MESH_ENABLED + +class daeElement; +class domMesh; + +#define MAX_MODEL_FACES 8 + +class LLModel : public LLVolume +{ +public: + + enum + { + LOD_IMPOSTOR = 0, + LOD_LOW, + LOD_MEDIUM, + LOD_HIGH, + LOD_PHYSICS, + NUM_LODS + }; + + //physics shape is a vector of convex hulls + //each convex hull is a set of points + typedef std::vector > physics_shape; + + LLModel(LLVolumeParams& params, F32 detail); + static LLSD writeModel(std::string filename, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* imposotr, LLModel::physics_shape& physics_shape, BOOL nowrite = FALSE); + static LLSD writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LLModel* medium, LLModel* low, LLModel* imposotr, LLModel::physics_shape& physics_shape, BOOL nowrite = FALSE); + static LLSD writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite = FALSE); + static LLModel* loadModelFromAsset(std::string filename, S32 lod); + static LLModel* loadModelFromDae(std::string filename); + static LLModel* loadModelFromDomMesh(domMesh* mesh); + static std::string getElementLabel(daeElement* element); + + void appendFaces(LLModel* model, LLMatrix4& transform, LLMatrix4& normal_transform); + void appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat); + + void setNumVolumeFaces(S32 count); + void setVolumeFaceData(S32 f, + LLStrider pos, + LLStrider norm, + LLStrider tc, + LLStrider ind, + U32 num_verts, + U32 num_indices); + + void smoothNormals(F32 angle_cutoff); + + void addFace(const LLVolumeFace& face); + + void normalizeVolumeFaces(); + void optimizeVolumeFaces(); + + + U32 getResourceCost(); + void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); + std::vector mMaterialList; + + //data used for skin weights + class JointWeight + { + public: + S32 mJointIdx; + F32 mWeight; + + JointWeight() + { + mJointIdx = 0; + mWeight = 0.f; + } + + JointWeight(S32 idx, F32 weight) + : mJointIdx(idx), mWeight(weight) + { + } + + bool operator<(const JointWeight& rhs) const + { + if (mWeight == rhs.mWeight) + { + return mJointIdx < rhs.mJointIdx; + } + + return mWeight < rhs.mWeight; + } + + }; + + struct CompareWeightGreater + { + bool operator()(const JointWeight& lhs, const JointWeight& rhs) + { + return rhs < lhs; // strongest = first + } + }; + + //copy of position array for this model -- mPosition[idx].mV[X,Y,Z] + std::vector mPosition; + + //map of positions to skin weights --- mSkinWeights[pos].mV[0..4] == . + //joint_index corresponds to mJointList + typedef std::vector weight_list; + typedef std::map weight_map; + weight_map mSkinWeights; + + //get list of weight influences closest to given position + weight_list& getJointInfluences(const LLVector3& pos); + + //should always be true that mJointList[mJointMap["foo"]] == "foo" + + //map of joint names to joint index + std::map mJointMap; + + //list of joint names + std::vector mJointList; + + LLMatrix4 mBindShapeMatrix; + std::vector mInvBindMatrix; + + std::string mLabel; + + LLVector3 mNormalizedScale; + LLVector3 mNormalizedTranslation; + + //physics shape + physics_shape mPhysicsShape; + + LLVector3 mPhysicsCenter; + std::vector mHullCenter; + U32 mPhysicsPoints; + +protected: + void addVolumeFacesFromDomMesh(domMesh* mesh); + virtual BOOL createVolumeFacesFromFile(const std::string& file_name); + virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); +}; + + +#endif + +#endif //LL_LLMODEL_H diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl new file mode 100644 index 0000000000..eef6556fba --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -0,0 +1,30 @@ +/** + * @file objectSkinV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +attribute vec4 object_weight; + +uniform mat4 matrixPalette[64]; + +mat4 getObjectSkinnedTransform() +{ + int i; + + vec4 w = fract(object_weight); + vec4 index = floor(object_weight); + + float scale = 1.0/(w.x+w.y+w.z+w.w); + w *= scale; + + mat4 mat = matrixPalette[int(index.x)]*w.x; + mat += matrixPalette[int(index.y)]*w.y; + mat += matrixPalette[int(index.z)]*w.z; + mat += matrixPalette[int(index.w)]*w.w; + + return mat; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl new file mode 100644 index 0000000000..fde0e97713 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -0,0 +1,75 @@ +/** + * @file alphaSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getObjectSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; +varying vec3 vary_light; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getObjectSkinnedTransform(); + trans = gl_ModelViewMatrix * trans; + + pos = trans * gl_Vertex; + + norm = gl_Vertex.xyz + gl_Normal.xyz; + norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz); + + gl_Position = gl_ProjectionMatrix * pos; + + vary_position = pos.xyz; + vary_normal = norm; + + calcAtmospherics(pos.xyz); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + + vary_light = gl_LightSource[0].position.xyz; + + 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/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl new file mode 100644 index 0000000000..085ffddeec --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl @@ -0,0 +1,16 @@ +/** + * @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).a); + gl_FragColor = vec4(1,1,1,1); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl new file mode 100644 index 0000000000..1626e21cd8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl @@ -0,0 +1,25 @@ +/** + * @file diffuseSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +mat4 getObjectSkinnedTransform(); + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl new file mode 100644 index 0000000000..d884f2e4a5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file bumpV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; + +mat4 getObjectSkinnedTransform(); + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + + vec3 pos = (mat*gl_Vertex).xyz; + + + vec3 n = normalize((mat * vec4(gl_Normal.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz); + vec3 b = normalize((mat * vec4(gl_MultiTexCoord2.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.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_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl new file mode 100644 index 0000000000..9a45c03237 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl @@ -0,0 +1,33 @@ +/** + * @file diffuseSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +varying vec3 vary_normal; + +mat4 getObjectSkinnedTransform(); + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vary_normal = norm.xyz; + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl new file mode 100644 index 0000000000..4cde013eef --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl @@ -0,0 +1,15 @@ +/** + * @file lightFullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + +uniform sampler2D diffuseMap; +uniform samplerCube environmentMap; + +void fullbright_shiny_lighting_water() +{ + gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl new file mode 100644 index 0000000000..f0baeeeee5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl @@ -0,0 +1,39 @@ +/** + * @file shinySimpleSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +attribute vec4 object_weight; + +void main() +{ + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vec3 ref = reflect(pos.xyz, -norm.xyz); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl new file mode 100644 index 0000000000..5e6e4c16b7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl @@ -0,0 +1,13 @@ +/** + * @file fullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +void fullbright_shiny_lighting_water(); + +void main() +{ + fullbright_shiny_lighting_water(); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl new file mode 100644 index 0000000000..02ff3cc2a9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file fullbrightSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +attribute vec4 object_weight; + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl new file mode 100644 index 0000000000..4146646058 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl @@ -0,0 +1,39 @@ +/** + * @file shinySimpleSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +attribute vec4 object_weight; + +void main() +{ + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vec3 ref = reflect(pos.xyz, -norm.xyz); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0); + + calcAtmospherics(pos.xyz); + + vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.)); + gl_FrontColor = color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl new file mode 100644 index 0000000000..59944b8861 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl @@ -0,0 +1,39 @@ +/** + * @file simpleV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +attribute vec4 object_weight; + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + calcAtmospherics(pos.xyz); + + vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.)); + gl_FrontColor = color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl new file mode 100644 index 0000000000..dc4663677b --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -0,0 +1,84 @@ +/** + * @file alphaSkinnedV.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 calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); +mat4 getObjectSkinnedTransform(); +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; +varying vec3 vary_light; + +uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + + vec3 pos = (mat*gl_Vertex).xyz; + + gl_Position = gl_ProjectionMatrix * vec4(pos, 1.0); + + vec4 n = gl_Vertex; + n.xyz += gl_Normal.xyz; + n.xyz = (mat*n).xyz; + n.xyz = normalize(n.xyz-pos.xyz); + + vec3 norm = n.xyz; + + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); + col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); + col.rgb = scaleDownLight(col.rgb); + + // Add windlight lights + col.rgb += atmosAmbient(vec3(0.)); + + vary_light = gl_LightSource[0].position.xyz; + + 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.xyz = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl new file mode 100644 index 0000000000..eca9a567f6 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl @@ -0,0 +1,29 @@ +/** + * @file lightFullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +uniform sampler2D diffuseMap; +uniform samplerCube environmentMap; + +vec3 fullbrightShinyAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_shiny_lighting_water() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = fullbrightShinyAtmosTransport(color.rgb); + color.rgb = fullbrightScaleSoftClip(color.rgb); + color.a = max(color.a, gl_Color.a); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/llfloaterimportcollada.cpp b/indra/newview/llfloaterimportcollada.cpp new file mode 100644 index 0000000000..476c02cd46 --- /dev/null +++ b/indra/newview/llfloaterimportcollada.cpp @@ -0,0 +1,1116 @@ +/** + * @file llfloaterimportcollada.cpp + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterimportcollada.h" + +#include "dae.h" +//#include "dom.h" +#include "dom/domAsset.h" +#include "dom/domBind_material.h" +#include "dom/domConstants.h" +#include "dom/domEffect.h" +#include "dom/domGeometry.h" +#include "dom/domInstance_geometry.h" +#include "dom/domInstance_material.h" +#include "dom/domInstance_node.h" +#include "dom/domInstance_effect.h" +#include "dom/domMaterial.h" +#include "dom/domMatrix.h" +#include "dom/domNode.h" +#include "dom/domProfile_COMMON.h" +#include "dom/domRotate.h" +#include "dom/domScale.h" +#include "dom/domTranslate.h" +#include "dom/domVisual_scene.h" + +#include "llagent.h" +#include "llassetuploadresponders.h" +#include "lleconomy.h" +#include "llfloaterperms.h" +#include "llfloaterreg.h" +#include "llsdutil.h" +#include "llsdutil_math.h" +#include "llselectmgr.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llviewermenufile.h" +#include "llviewerregion.h" +#include "llvolumemessage.h" +#include "llmodel.h" +#include "llmeshreduction.h" +#include "material_codes.h" + +// +// floater +// + +#if LL_MESH_ENABLED + +LLFloaterImportCollada::LLFloaterImportCollada(const LLSD& key) + : LLFloater(key) +{ +} + + +BOOL LLFloaterImportCollada::postBuild() +{ + if (!LLFloater::postBuild()) + { + return FALSE; + } + + childSetCommitCallback("ok", LLImportCollada::onCommitOK, this); + childSetCommitCallback("cancel", LLImportCollada::onCommitCancel, this); + + setStatusIdle(); + setAssetCount(0,0); + enableOK(TRUE); + + return TRUE; +} + + +void LLFloaterImportCollada::setAssetCount(S32 mesh_count, S32 texture_count) +{ + childSetTextArg("mesh count", "[COUNT]", llformat("%d", mesh_count)); + childSetTextArg("texture count", "[COUNT]", llformat("%d", texture_count)); +} + +void LLFloaterImportCollada::setStatusAssetUploading(std::string asset_name) +{ + LLUIString uploading = getString("status_uploading"); + uploading.setArg("[NAME]", asset_name); + childSetTextArg("status", "[STATUS]", uploading.getString()); +} + +void LLFloaterImportCollada::setStatusCreatingPrim(std::string prim_name) +{ + LLUIString creating = getString("status_creating"); + creating.setArg("[NAME]", prim_name); + childSetTextArg("status", "[STATUS]", creating.getString()); +} + +void LLFloaterImportCollada::setStatusIdle() +{ + childSetTextArg("status", "[STATUS]", getString("status_idle")); +} + +void LLFloaterImportCollada::enableOK(BOOL enable) +{ + childSetEnabled("ok", enable); +} + + +// +// misc helpers +// + + +// why oh why do forbid matrix multiplication in our llmath library? +LLMatrix4 matrix_multiply(LLMatrix4 a, LLMatrix4 b) +{ + a *= b; + + return a; +} + +// why oh why does colladadom not provide such things? +daeElement* getFirstChild(daeElement* parent) +{ + daeTArray< daeSmartRef > children = parent->getChildren(); + + if (children.getCount() > 0) + { + return children[0]; + } + else + { + return NULL; + } +} + +// why oh why does colladadom not provide such things? +daeElement* getNextSibling(daeElement* child) +{ + daeElement* parent = child->getParent(); + + if (parent == NULL) + { + // must be root, root has no siblings + return NULL; + } + + daeElement* sibling = NULL; + + daeTArray< daeSmartRef > children = parent->getChildren(); + for (S32 i = 0; i < children.getCount(); i++) + { + if (child == children[i]) + { + if ((i+1) < children.getCount()) + { + sibling = children[i+1]; + } + } + } + + return sibling; +} + +// try to get a decent label for this element +std::string getElementLabel(daeElement *element) +{ + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + if (parent) + { + // if parent has a name, use it + std::string name = parent->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if parent has an ID, use it + if (parent->getID()) + { + return std::string(parent->getID()); + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name); + } + + // if all else fails, use "object" + return std::string("object"); +} + +LLColor4 getDaeColor(daeElement* element) +{ + LLColor4 value; + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(element->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + } + + return value; +} + +LLTextureEntry profileToTextureEntry(domProfile_COMMON* material) +{ + LLTextureEntry te; + + te.setID(LLUUID("5748decc-f629-461c-9a36-a35a221fe21f")); // blank texture + daeElement* diffuse = material->getDescendant("diffuse"); + if (diffuse) + { + te.setColor(LLColor3(0.1f, 0.9f, 1.0f)); + + domCommon_color_or_texture_type_complexType::domTexture* texture = + daeSafeCast(diffuse->getDescendant("texture")); + if (texture) + { + domCommon_newparam_type_Array newparams = material->getNewparam_array(); + for (S32 i = 0; i < newparams.getCount(); i++) + { + domFx_surface_common* surface = newparams[i]->getSurface(); + if (surface) + { + domFx_surface_init_common* init = surface->getFx_surface_init_common(); + if (init) + { + domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); + + if (init_from.getCount() > 0) + { + daeElement* image = init_from[0]->getValue().getElement(); + if (image) + { + LLUUID texture_asset = LLImportColladaAssetCache::getInstance()->getAssetForDaeElement(image); + + if (texture_asset.notNull()) + { + te.setID(texture_asset); + te.setColor(LLColor3(1,1,1)); + } + } + } + } + } + } + } + + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(diffuse->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + te.setColor(value); + } + } + + daeElement* emission = material->getDescendant("emission"); + if (emission) + { + LLColor4 emission_color = getDaeColor(emission); + if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) + { + te.setFullbright(TRUE); + } + } + + return te; +} + +std::vector getMaterials(LLModel* model, domInstance_geometry* instance_geo) +{ + std::vector texture_entries; + for (int i = 0; i < model->mMaterialList.size(); i++) + { + LLTextureEntry texture_entry; + + domInstance_material* instance_mat = NULL; + + domBind_material::domTechnique_common* technique = + daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); + + if (technique) + { + daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); + for (int j = 0; j < inst_materials.getCount(); j++) + { + std::string symbol(inst_materials[j]->getSymbol()); + + if (symbol == model->mMaterialList[i]) // found the binding + { + instance_mat = inst_materials[j]; + } + } + } + + if (instance_mat) + { + domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); + if (material) + { + domInstance_effect* instance_effect = + daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); + if (instance_effect) + { + domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); + if (effect) + { + domProfile_COMMON* profile = + daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); + if (profile) + { + texture_entry = profileToTextureEntry(profile); + } + } + } + } + } + + texture_entries.push_back(texture_entry); + } + + return texture_entries; +} + +LLTextureEntry instanceGeoToTextureEntry(domInstance_geometry* instance_geo) +{ + LLTextureEntry te; + domInstance_material* instance_mat = + daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domInstance_material::ID()))); + if (instance_mat) + { + } + + return te; +} + + + +// responder for asset uploads +// does all the normal stuff followed by a notification to continue importing +// WARNING - currently unused - TODO +class LLColladaNewAgentInventoryResponder : public LLNewAgentInventoryResponder +{ + LLColladaNewAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) + : LLNewAgentInventoryResponder(post_data, vfile_id, asset_type) + { + } + LLColladaNewAgentInventoryResponder(const LLSD& post_data, + const std::string& file_name, + LLAssetType::EType asset_type) + : LLNewAgentInventoryResponder(post_data, file_name, asset_type) + { + } + + virtual void uploadComplete(const LLSD& content) + { + LLNewAgentInventoryResponder::uploadComplete(content); + } + +}; + +BOOL LLImportColladaAssetCache::uploadImageAsset(domImage* image) +{ + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (!init) + { + return FALSE; + } + + std::string filename = cdom::uriToNativePath(init->getValue().str()); + + std::string name = getElementLabel(image); + + LLUUID transaction_id = upload_new_resource(filename, name, std::string(), + 0, LLFolderType::FT_TEXTURE, LLInventoryType::IT_TEXTURE, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), + LLFloaterPerms::getEveryonePerms(), + name, NULL, + LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), NULL); + + if (transaction_id.isNull()) + { + llwarns << "cannot upload " << filename << llendl; + + return FALSE; + } + + mTransactionMap[transaction_id] = image; + + LLFloaterReg::findTypedInstance("import_collada")->setStatusAssetUploading(name); + + return TRUE; +} + + + +// +// asset cache - +// uploads assets and provides a map from collada element to asset +// + + + +BOOL LLImportColladaAssetCache::uploadMeshAsset(domMesh* mesh) +{ + LLPointer model = LLModel::loadModelFromDomMesh(mesh); + + if (model->getNumVolumeFaces() == 0) + { + return FALSE; + } + + // generate LODs + + + std::vector > lods; + lods.push_back(model); + S32 triangle_count = model->getNumTriangles(); + + for (S32 i = 0; i < 4; i++) + { + LLPointer last_model = lods.back(); + + S32 triangle_target = (S32)(triangle_count / pow(3.f, i + 1)); + if (triangle_target > 16) + { + LLMeshReduction reduction; + LLPointer new_model = reduction.reduce(model, triangle_target, LLMeshReduction::TRIANGLE_BUDGET); + lods.push_back(new_model); + } + else + { + lods.push_back(last_model); + } + } + + // write model to temp file + + std::string filename = gDirUtilp->getTempFilename(); + LLModel::writeModel(filename, + lods[4], + lods[0], + lods[1], + lods[2], + lods[3], + lods[4]->mPhysicsShape); + + + // copy file to VFS + + LLTransactionID tid; + tid.generate(); + LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID()); // create asset uuid + + S32 file_size; + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + + if (infile.getFileHandle()) + { + LLVFile file(gVFS, uuid, LLAssetType::AT_MESH, LLVFile::WRITE); + + file.setMaxSize(file_size); + + const S32 buf_size = 65536; + U8 copy_buf[buf_size]; + while ((file_size = infile.read(copy_buf, buf_size))) + { + file.write(copy_buf, file_size); + } + } + + + std::string name = getElementLabel(mesh); + + upload_new_resource(tid, LLAssetType::AT_MESH, name, std::string(), 0,LLFolderType::FT_MESH, LLInventoryType::IT_MESH, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), + name, NULL, + LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), NULL); + + LLFile::remove(filename); + + mTransactionMap[uuid] = mesh; + + LLFloaterReg::findTypedInstance("import_collada")->setStatusAssetUploading(name); + + return TRUE; +} + + +// called by the mesh asset upload responder to indicate the mesh asset has been uploaded +void LLImportColladaAssetCache::assetUploaded(LLUUID transaction_uuid, LLUUID asset_uuid, BOOL success) +{ + std::map::iterator i = mTransactionMap.find(transaction_uuid); + + if (i != mTransactionMap.end()) + { + daeElement* element = i->second; + + + if (success) + { + mAssetMap[element] = asset_uuid; + } + else // failure + { + // if failed, put back on end of queue + mUploadsPending.push_back(element); + } + + mUploads--; + uploadNextAsset(); + } +} + +const S32 MAX_CONCURRENT_UPLOADS = 5; + +void LLImportColladaAssetCache::uploadNextAsset() +{ + while ((mUploadsPending.size() > 0) && (mUploads < MAX_CONCURRENT_UPLOADS)) + { + BOOL upload_started = FALSE; + + daeElement* element = mUploadsPending.back(); + mUploadsPending.pop_back(); + + domImage* image = daeSafeCast(element); + if (image) + { + upload_started = uploadImageAsset(image); + } + + domMesh* mesh = daeSafeCast(element); + if (mesh) + { + upload_started = uploadMeshAsset(mesh); + } + + if (upload_started) + { + mUploads++; + } + + } + + if ((mUploadsPending.size() == 0) && (mUploads == 0)) + { + // we're done! notify the importer + LLImportCollada::getInstance()->assetsUploaded(); + } + + updateCount(); +} + + +void LLImportColladaAssetCache::clear() +{ + mDAE = NULL; + mTransactionMap.clear(); + mAssetMap.clear(); + mUploadsPending.clear(); + mUploads = 0; +} + +void LLImportColladaAssetCache::endImport() +{ + clear(); +} + +void LLImportColladaAssetCache::updateCount() +{ + S32 mesh_count = 0; + S32 image_count = 0; + + for (S32 i = 0; i < mUploadsPending.size(); i++) + { + daeElement* element = mUploadsPending[i]; + + if (daeSafeCast(element)) + { + mesh_count++; + } + + if (daeSafeCast(element)) + { + image_count++; + } + } + + LLFloaterReg::findTypedInstance("import_collada")->setAssetCount(mesh_count, image_count); +} + +void LLImportColladaAssetCache::prepareForUpload(DAE* dae) +{ + clear(); + mDAE = dae; + + daeDatabase* db = mDAE->getDatabase(); + + S32 mesh_count = db->getElementCount(NULL, COLLADA_TYPE_MESH); + for (S32 i = 0; i < mesh_count; i++) + { + domMesh* mesh = NULL; + + db->getElement((daeElement**) &mesh, i, NULL, COLLADA_TYPE_MESH); + + mUploadsPending.push_back(mesh); + } + + + S32 image_count = db->getElementCount(NULL, COLLADA_TYPE_IMAGE); + for (S32 i = 0; i < image_count; i++) + { + domImage* image = NULL; + db->getElement((daeElement**) &image, i, NULL, COLLADA_TYPE_IMAGE); + + mUploadsPending.push_back(image); + } + + updateCount(); +} + + +void LLImportColladaAssetCache::uploadAssets() +{ + uploadNextAsset(); +} + + +LLUUID LLImportColladaAssetCache::getAssetForDaeElement(daeElement* element) +{ + LLUUID id; + + std::map::iterator i = mAssetMap.find(element); + if (i != mAssetMap.end()) + { + id = i->second; + } + + return id; +} + + +// +// importer +// + + + +LLImportCollada::LLImportCollada() +{ + mIsImporting = FALSE; +} + + + + +void LLImportCollada::appendObjectAsset(domInstance_geometry* instance_geo) +{ + domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); + if (!geo) + { + llwarns << "cannot find geometry" << llendl; + return; + } + + domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); + if (!mesh) + { + llwarns << "could not find mesh" << llendl; + return; + } + + LLUUID mesh_asset = LLImportColladaAssetCache::getInstance()->getAssetForDaeElement(mesh); + if (mesh_asset.isNull()) + { + llwarns << "no mesh asset, skipping" << llendl; + return; + } + + // load the model + LLModel* model = LLModel::loadModelFromDomMesh(mesh); + + + + + // get our local transformation + LLMatrix4 transformation = mStack.front().transformation; + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + transformation = matrix_multiply(mesh_translation, transformation); + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + transformation = matrix_multiply(mesh_scale, transformation); + + // check for reflection + BOOL reflected = (transformation.determinant() < 0); + + // compute position + LLVector3 position = LLVector3(0, 0, 0) * transformation; + + // compute scale + LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position; + LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position; + LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position; + F32 x_length = x_transformed.normalize(); + F32 y_length = y_transformed.normalize(); + F32 z_length = z_transformed.normalize(); + LLVector3 scale = LLVector3(x_length, y_length, z_length); + + // adjust for "reflected" geometry + LLVector3 x_transformed_reflected = x_transformed; + if (reflected) + { + x_transformed_reflected *= -1.0; + } + + // compute rotation + LLMatrix3 rotation_matrix; + rotation_matrix.setRows(x_transformed_reflected, y_transformed, z_transformed); + LLQuaternion quat_rotation = rotation_matrix.quaternion(); + quat_rotation.normalize(); // the rotation_matrix might not have been orthoginal. make it so here. + LLVector3 euler_rotation; + quat_rotation.getEulerAngles(&euler_rotation.mV[VX], &euler_rotation.mV[VY], &euler_rotation.mV[VZ]); + + + // + // build parameter block to construct this prim + // + + LLSD object_params; + + // create prim + + // set volume params + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + U8 sculpt_type = LL_SCULPT_TYPE_MESH; + if (reflected) + { + sculpt_type |= LL_SCULPT_FLAG_MIRROR; + } + volume_params.setSculptID(mesh_asset, sculpt_type); + object_params["shape"] = volume_params.asLLSD(); + + object_params["material"] = LL_MCODE_WOOD; + + object_params["group-id"] = gAgent.getGroupID(); + object_params["pos"] = ll_sd_from_vector3(position); + object_params["rotation"] = ll_sd_from_quaternion(quat_rotation); + object_params["scale"] = ll_sd_from_vector3(scale); + object_params["name"] = mStack.front().name; + + // load material from dae file + std::vector texture_entries = getMaterials(model, instance_geo); + object_params["facelist"] = LLSD::emptyArray(); + for (int i = 0; i < texture_entries.size(); i++) + { + object_params["facelist"][i] = texture_entries[i].asLLSD(); + } + + // set extra parameters + LLSculptParams sculpt_params; + sculpt_params.setSculptTexture(mesh_asset); + sculpt_params.setSculptType(sculpt_type); + U8 buffer[MAX_OBJECT_PARAMS_SIZE+1]; + LLDataPackerBinaryBuffer dp(buffer, MAX_OBJECT_PARAMS_SIZE); + sculpt_params.pack(dp); + std::vector v(dp.getCurrentSize()); + memcpy(&v[0], buffer, dp.getCurrentSize()); + LLSD extra_parameter; + extra_parameter["extra_parameter"] = sculpt_params.mType; + extra_parameter["param_data"] = v; + object_params["extra_parameters"].append(extra_parameter); + + mObjectList.append(object_params); + + delete model; + + LLFloaterReg::findTypedInstance("import_collada")->setStatusCreatingPrim(mStack.front().name); + + return; +} + +void LLImportCollada::uploadObjectAsset() +{ + LLSD request; + request["objects"] = mObjectList; + + std::string url = gAgent.getRegion()->getCapability("UploadObjectAsset"); + LLHTTPClient::post(url, request, new LLHTTPClient::Responder()); +} + + + +void LLImportCollada::importFile(std::string filename) +{ + if (mIsImporting) + { + llwarns << "Importer already running, import command for " << filename << " ignored" << llendl; + return; + } + + LLFloaterReg::showInstance("import_collada"); + LLFloaterReg::findTypedInstance("import_collada")->enableOK(TRUE); + + + mIsImporting = TRUE; + mDAE = new DAE; + mImportOrigin = gAgent.getPositionAgent() + LLVector3(0, 0, 2); + mSceneTransformation = LLMatrix4(); // identity + mFilename = filename; + mCreates = 0; + mObjectList = LLSD::emptyArray(); + + if (mDAE->open(mFilename) == NULL) + { + llwarns << "cannot open file " << mFilename << llendl; + endImport(); + return; + } + + LLImportColladaAssetCache::getInstance()->prepareForUpload(mDAE); + + return; +} + + +void LLImportCollada::assetsUploaded() +{ + if (!mIsImporting) + { + // weird, we got a callback while not importing. + return; + } + + daeDocument* doc = mDAE->getDoc(mFilename); + if (!doc) + { + llwarns << "can't find internal doc" << llendl; + endImport(); + } + + daeElement* root = doc->getDomRoot(); + if (!root) + { + llwarns << "document has no root" << llendl; + endImport(); + } + + domAsset::domUnit* unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); + if (unit) + { + mSceneTransformation *= unit->getMeter(); + } + + domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP + domAsset::domUp_axis* up_axis = + daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + if (up_axis) + { + up = up_axis->getValue(); + } + + if (up == UPAXISTYPE_X_UP) + { + LLMatrix4 rotation; + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + + mSceneTransformation = matrix_multiply(rotation, mSceneTransformation); + } + else if (up == UPAXISTYPE_Y_UP) + { + LLMatrix4 rotation; + rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); + + mSceneTransformation = matrix_multiply(rotation, mSceneTransformation); + } + // else Z_UP, which is our behavior + + + + daeElement* scene = root->getDescendant("visual_scene"); + if (!scene) + { + llwarns << "document has no visual_scene" << llendl; + endImport(); + } + + processElement(scene); + processNextElement(); +} + +void LLImportCollada::pushStack(daeElement* next_element, std::string name, LLMatrix4 transformation) +{ + struct StackState new_state; + + new_state.next_element = next_element; + new_state.name = name; + new_state.transformation = transformation; + + mStack.push_front(new_state); +} + + + +void LLImportCollada::popStack() +{ + mStack.pop_front(); +} + + + +BOOL LLImportCollada::processElement(daeElement* element) +{ + if (mStack.size() > 0) + { + mStack.front().next_element = getNextSibling(element); + } + + domTranslate* translate = daeSafeCast(element); + if (translate) + { + domFloat3 dom_value = translate->getValue(); + + LLMatrix4 translation; + translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + mStack.front().transformation = matrix_multiply(translation, mStack.front().transformation); + } + + domRotate* rotate = daeSafeCast(element); + if (rotate) + { + domFloat4 dom_value = rotate->getValue(); + + LLMatrix4 rotation; + rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); + + mStack.front().transformation = matrix_multiply(rotation, mStack.front().transformation); + } + + domScale* scale = daeSafeCast(element); + if (scale) + { + domFloat3 dom_value = scale->getValue(); + + LLMatrix4 scaling; + scaling.initScale(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + mStack.front().transformation = matrix_multiply(scaling, mStack.front().transformation); + } + + domMatrix* matrix = daeSafeCast(element); + if (matrix) + { + domFloat4x4 dom_value = matrix->getValue(); + + LLMatrix4 matrix_transform; + + for (int i = 0; i < 4; i++) + for(int j = 0; j < 4; j++) + { + matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; + } + + mStack.front().transformation = matrix_multiply(matrix_transform, mStack.front().transformation); + } + + domInstance_geometry* instance_geo = daeSafeCast(element); + if (instance_geo) + { + appendObjectAsset(instance_geo); + } + + domNode* node = daeSafeCast(element); + if (node) + { + pushStack(getFirstChild(element), getElementLabel(element), mStack.front().transformation); + } + + domInstance_node* instance_node = daeSafeCast(element); + if (instance_node) + { + daeElement* instance = instance_node->getUrl().getElement(); + if (instance) + { + pushStack(getFirstChild(instance), getElementLabel(instance), mStack.front().transformation); + } + } + + domVisual_scene* scene = daeSafeCast(element); + if (scene) + { + pushStack(getFirstChild(element), std::string("scene"), mSceneTransformation); + } + + return FALSE; +} + + +void LLImportCollada::processNextElement() +{ + while(1) + { + if (mStack.size() == 0) + { + uploadObjectAsset(); + endImport(); + return; + } + + daeElement *element = mStack.front().next_element; + + if (element == NULL) + { + popStack(); + } + else + { + processElement(element); + } + } +} + + +void LLImportCollada::endImport() +{ + LLFloaterReg::hideInstance("import_collada"); + + LLImportColladaAssetCache::getInstance()->endImport(); + + if (mDAE) + { + delete mDAE; + mDAE = NULL; + } + + mIsImporting = FALSE; +} + + +/* static */ +void LLImportCollada::onCommitOK(LLUICtrl*, void*) +{ + LLFloaterReg::findTypedInstance("import_collada")->enableOK(FALSE); + + LLImportColladaAssetCache::getInstance()->uploadAssets(); +} + + +/* static */ +void LLImportCollada::onCommitCancel(LLUICtrl*, void*) +{ + getInstance()->endImport(); +} + +#endif diff --git a/indra/newview/llfloaterimportcollada.h b/indra/newview/llfloaterimportcollada.h new file mode 100644 index 0000000000..818b19e403 --- /dev/null +++ b/indra/newview/llfloaterimportcollada.h @@ -0,0 +1,143 @@ +/** + * @file llfloaterimportcollada.h + * @brief The about box from Help -> About + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERIMPORTCOLLADA_H +#define LL_LLFLOATERIMPORTCOLLADA_H + +#include "llfloater.h" +#include "llvolume.h" //for LL_MESH_ENABLED + +#if LL_MESH_ENABLED + +class LLFloaterImportCollada : public LLFloater +{ +public: + LLFloaterImportCollada(const LLSD& key); + /* virtual */ BOOL postBuild(); + + void setAssetCount(S32 mesh_count, S32 texture_count); + void setStatusAssetUploading(std::string asset_name); + void setStatusCreatingPrim(std::string prim_name); + void setStatusIdle(); + void enableOK(BOOL enable); +}; + +class LLViewerObject; +class DAE; +class daeElement; +class domMesh; +class domImage; +class domInstance_geometry; +class LLModel; +class LLImportCollada; + +class LLImportColladaAssetCache : public LLSingleton +{ +public: + // called first to initialize + void prepareForUpload(DAE* dae); + + // upload the assets in this collada file + void uploadAssets(); + + // get the uploaded assets which corresponds to this element + LLUUID getAssetForDaeElement(daeElement* element); + + // stop the upload + void endImport(); + + // reset + void clear(); + + // callback for notification when an asset has been uploaded + void assetUploaded(LLUUID transaction_uuid, LLUUID asset_uuid, BOOL success); + +private: + void uploadNextAsset(); + BOOL uploadMeshAsset(domMesh* mesh); + BOOL uploadImageAsset(domImage* image); + void updateCount(); + + std::vector mUploadsPending; + std::map mTransactionMap; + std::map mAssetMap; + + DAE* mDAE; + S32 mUploads; +}; + + +class LLImportCollada +: public LLSingleton +{ +public: + LLImportCollada(); + void importFile(std::string filename); + + // callback when all assets have been uploaded + void assetsUploaded(); + + // callback when buttons pressed + static void onCommitOK(LLUICtrl*, void*); + static void onCommitCancel(LLUICtrl*, void*); + + +private: + void endImport(); + void processNextElement(); + BOOL processElement(daeElement* element); + void pushStack(daeElement* next_element, std::string name, LLMatrix4 transformation); + void popStack(); + void appendObjectAsset(domInstance_geometry* instance_geo); + void uploadObjectAsset(); + + struct StackState + { + daeElement* next_element; + std::string name; + LLMatrix4 transformation; + }; + + std::list mStack; + S32 mCreates; + LLVector3 mImportOrigin; + std::string mFilename; + BOOL mIsImporting; + DAE *mDAE; + LLSD mObjectList; + + LLMatrix4 mSceneTransformation; +}; + +#endif + +#endif // LL_LLFLOATERIMPORTCOLLADA_H diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp new file mode 100644 index 0000000000..5dd983d818 --- /dev/null +++ b/indra/newview/llfloatermodelpreview.cpp @@ -0,0 +1,3382 @@ +/** + * @file llfloatermodelpreview.cpp + * @brief LLFloaterModelPreview class implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "dae.h" +//#include "dom.h" +#include "dom/domAsset.h" +#include "dom/domBind_material.h" +#include "dom/domCOLLADA.h" +#include "dom/domConstants.h" +#include "dom/domController.h" +#include "dom/domEffect.h" +#include "dom/domGeometry.h" +#include "dom/domInstance_geometry.h" +#include "dom/domInstance_material.h" +#include "dom/domInstance_node.h" +#include "dom/domInstance_effect.h" +#include "dom/domMaterial.h" +#include "dom/domMatrix.h" +#include "dom/domNode.h" +#include "dom/domProfile_COMMON.h" +#include "dom/domRotate.h" +#include "dom/domScale.h" +#include "dom/domTranslate.h" +#include "dom/domVisual_scene.h" + +#include "llfloatermodelpreview.h" + +#include "llfilepicker.h" +#include "llimagebmp.h" +#include "llimagetga.h" +#include "llimagejpeg.h" +#include "llimagepng.h" + +#include "llagent.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "lldatapacker.h" +#include "lldrawable.h" +#include "lldrawpoolavatar.h" +#include "llrender.h" +#include "llface.h" +#include "lleconomy.h" +#include "llfocusmgr.h" +#include "llfloaterperms.h" +#include "llmatrix4a.h" +#include "llmeshrepository.h" +#include "llsdutil_math.h" +#include "lltextbox.h" +#include "lltoolmgr.h" +#include "llui.h" +#include "llvector4a.h" +#include "llviewercamera.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llvoavatarself.h" +#include "pipeline.h" +#include "lluictrlfactory.h" +#include "llviewermenufile.h" +#include "llviewerregion.h" +#include "llstring.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "llvfile.h" +#include "llvfs.h" + + +#include "glod/glod.h" + + +#if LL_MESH_ENABLED + +//static +S32 LLFloaterModelPreview::sUploadAmount = 10; +LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; + +const S32 PREVIEW_BORDER_WIDTH = 2; +const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; +const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; +const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16; +const S32 PREVIEW_TEXTURE_HEIGHT = 300; + +void drawBoxOutline(const LLVector3& pos, const LLVector3& size); + +std::string limit_name[] = +{ + "lowest limit", + "low limit", + "medium limit", + "high limit", + "physics limit", + + "I went off the end of the limit_name array. Me so smart." +}; + +std::string info_name[] = +{ + "lowest info", + "low info", + "medium info", + "high info", + "physics info", + + "I went off the end of the info_name array. Me so smart." +}; + +bool validate_face(const LLVolumeFace& face) +{ + for (U32 i = 0; i < face.mNumIndices; ++i) + { + if (face.mIndices[i] >= face.mNumVertices) + { + llwarns << "Face has invalid index." << llendl; + return false; + } + } + + return true; +} + +bool validate_model(const LLModel* mdl) +{ + if (mdl->getNumVolumeFaces() == 0) + { + llwarns << "Model has no faces!" << llendl; + return false; + } + + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + if (mdl->getVolumeFace(i).mNumVertices == 0) + { + llwarns << "Face has no vertices." << llendl; + return false; + } + + if (mdl->getVolumeFace(i).mNumIndices == 0) + { + llwarns << "Face has no indices." << llendl; + return false; + } + + if (!validate_face(mdl->getVolumeFace(i))) + { + return false; + } + } + + return true; +} + +BOOL stop_gloderror() +{ + GLuint error = glodGetError(); + + if (error != GLOD_NO_ERROR) + { + llwarns << "GLOD error detected, cannot generate LOD: " << std::hex << error << llendl; + return TRUE; + } + + return FALSE; +} + +LLPhysicsDecompFloater::LLPhysicsDecompFloater(LLSD& key) +: LLFloater(key) +{ + +} + +LLPhysicsDecompFloater::~LLPhysicsDecompFloater() +{ + if (LLFloaterModelPreview::sInstance && LLFloaterModelPreview::sInstance->mDecompFloater) + { + LLFloaterModelPreview::sInstance->mDecompFloater = NULL; + } +} + +class LLMeshFilePicker : public LLFilePickerThread +{ +public: + LLFloaterModelPreview* mFMP; + S32 mLOD; + + LLMeshFilePicker(LLFloaterModelPreview* fmp, S32 lod) + : LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA) + { + mFMP = fmp; + mLOD = lod; + } + + virtual void notify(const std::string& filename) + { + mFMP->mModelPreview->loadModel(mFile, mLOD); + } +}; + + +//----------------------------------------------------------------------------- +// LLFloaterModelPreview() +//----------------------------------------------------------------------------- +LLFloaterModelPreview::LLFloaterModelPreview(const LLSD& key) : + LLFloater(key) +{ + sInstance = this; + mLastMouseX = 0; + mLastMouseY = 0; + mGLName = 0; + mLoading = FALSE; + mDecompFloater = NULL; +} + +//----------------------------------------------------------------------------- +// postBuild() +//----------------------------------------------------------------------------- +BOOL LLFloaterModelPreview::postBuild() +{ + if (!LLFloater::postBuild()) + { + return FALSE; + } + + childSetCommitCallback("high detail combo", onHighLODCommit, this); + childSetCommitCallback("medium detail combo", onMediumLODCommit, this); + childSetCommitCallback("low detail combo", onLowLODCommit, this); + childSetCommitCallback("lowest detail combo", onLowestLODCommit, this); + childSetCommitCallback("physics detail combo", onPhysicsLODCommit, this); + + + childSetCommitCallback("high limit", onHighLimitCommit, this); + childSetCommitCallback("medium limit", onMediumLimitCommit, this); + childSetCommitCallback("low limit", onLowLimitCommit, this); + childSetCommitCallback("lowest limit", onLowestLimitCommit, this); + childSetCommitCallback("physics limit", onPhysicsLimitCommit, this); + + childSetCommitCallback("smooth normals", onSmoothNormalsCommit, this); + + childSetCommitCallback("show edges", onShowEdgesCommit, this); + childSetCommitCallback("auto fill", onAutoFillCommit, this); + + childSetCommitCallback("explode", onExplodeCommit, this); + + childSetTextArg("status", "[STATUS]", getString("status_idle")); + + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + if (lod == LLModel::LOD_PHYSICS) + { + childSetTextArg(info_name[lod], "[HULLS]", std::string("0")); + childSetTextArg(info_name[lod], "[POINTS]", std::string("0")); + } + else + { + childSetTextArg(info_name[lod], "[TRIANGLES]", std::string("0")); + childSetTextArg(info_name[lod], "[VERTICES]", std::string("0")); + childSetTextArg(info_name[lod], "[SUBMESHES]", std::string("0")); + std::string msg = getString("required"); + childSetTextArg(info_name[lod], "[MESSAGE]", msg); + } + + childSetVisible(limit_name[lod], FALSE); + } + + //childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount)); + childSetAction("ok_btn", onUpload, this); + + childSetAction("consolidate", onConsolidate, this); + childSetAction("scrub materials", onScrubMaterials, this); + + childSetAction("decompose_btn", onDecompose, this); + + childSetCommitCallback("preview_lod_combo", onPreviewLODCommit, this); + + const U32 width = 512; + const U32 height = 512; + + mPreviewRect.set(getRect().getWidth()-PREVIEW_HPAD-width, + PREVIEW_HPAD+height, + getRect().getWidth()-PREVIEW_HPAD, + PREVIEW_HPAD); + + mModelPreview = new LLModelPreview(512, 512, this); + mModelPreview->setPreviewTarget(16.f); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLFloaterModelPreview() +//----------------------------------------------------------------------------- +LLFloaterModelPreview::~LLFloaterModelPreview() +{ + sInstance = NULL; + + delete mModelPreview; + + if (mGLName) + { + LLImageGL::deleteTextures(1, &mGLName ); + } + + if (mDecompFloater) + { + mDecompFloater->closeFloater(); + mDecompFloater = NULL; + } +} + +void LLFloaterModelPreview::loadModel(S32 lod) +{ + mLoading = TRUE; + + (new LLMeshFilePicker(this, lod))->getFile(); +} + +void LLFloaterModelPreview::setLODMode(S32 lod, S32 mode) +{ + if (mode == 0) + { + loadModel(lod); + } + else if (mode != mModelPreview->mLODMode[lod]) + { + mModelPreview->mLODMode[lod] = mode; + mModelPreview->genLODs(lod); + } + + mModelPreview->setPreviewLOD(lod); + + + LLSpinCtrl* lim = getChild(limit_name[lod], TRUE); + + if (mode == 1) //triangle count + { + U32 tri_count = 0; + for (LLModelLoader::model_list::iterator iter = mModelPreview->mBaseModel.begin(); + iter != mModelPreview->mBaseModel.end(); ++iter) + { + tri_count += (*iter)->getNumTriangles(); + } + + lim->setMaxValue(tri_count); + lim->setVisible(TRUE); + } + else + { + lim->setVisible(FALSE); + } +} + +void LLFloaterModelPreview::setLimit(S32 lod, S32 limit) +{ + if (limit != mModelPreview->mLimit[lod]) + { + mModelPreview->mLimit[lod] = limit; + mModelPreview->genLODs(lod); + mModelPreview->setPreviewLOD(lod); + } +} + +void LLFloaterModelPreview::onPreviewLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; + + if (!fp->mModelPreview) + { + return; + } + + S32 which_mode = 0; + + LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface("preview_lod_combo"); + if (iface) + { + which_mode = iface->getFirstSelectedIndex(); + } + fp->mModelPreview->setPreviewLOD(which_mode); +} + +//static +void LLFloaterModelPreview::setLODMode(S32 lod, void* userdata) +{ + LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; + + if (!fp->mModelPreview) + { + return; + } + + S32 which_mode = 0; + + std::string combo_name[] = + { + "lowest detail combo", + "low detail combo", + "medium detail combo", + "high detail combo", + "physics detail combo", + + "I went off the end of the combo_name array. Me so smart." + }; + + LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface(combo_name[lod]); + if (iface) + { + which_mode = iface->getFirstSelectedIndex(); + } + + fp->setLODMode(lod, which_mode); +} + +//static +void LLFloaterModelPreview::onHighLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLODMode(3, userdata); +} + +//static +void LLFloaterModelPreview::onMediumLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLODMode(2, userdata); +} + +//static +void LLFloaterModelPreview::onLowLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLODMode(1, userdata); +} + +//static +void LLFloaterModelPreview::onLowestLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLODMode(0, userdata); +} + +//static +void LLFloaterModelPreview::onPhysicsLODCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLODMode(4, userdata); +} + +//static +void LLFloaterModelPreview::setLimit(S32 lod, void* userdata) +{ + LLFloaterModelPreview *fp =(LLFloaterModelPreview *)userdata; + + if (!fp->mModelPreview) + { + return; + } + + S32 limit = fp->childGetValue(limit_name[lod]).asInteger(); + + + fp->setLimit(lod, limit); +} + +//static +void LLFloaterModelPreview::onHighLimitCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLimit(3, userdata); +} + +//static +void LLFloaterModelPreview::onMediumLimitCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLimit(2, userdata); +} + +//static +void LLFloaterModelPreview::onLowLimitCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLimit(1, userdata); +} + +//static +void LLFloaterModelPreview::onLowestLimitCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLimit(0, userdata); +} + +//static +void LLFloaterModelPreview::onPhysicsLimitCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview::setLimit(4, userdata); +} + +//static +void LLFloaterModelPreview::onSmoothNormalsCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; + + fp->mModelPreview->smoothNormals(); +} + +//static +void LLFloaterModelPreview::onShowEdgesCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; + + fp->mModelPreview->refresh(); +} + +//static +void LLFloaterModelPreview::onExplodeCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; + + fp->mModelPreview->refresh(); +} + +//static +void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; + + fp->mModelPreview->genLODs(); +} + + +//----------------------------------------------------------------------------- +// draw() +//----------------------------------------------------------------------------- +void LLFloaterModelPreview::draw() +{ + LLFloater::draw(); + LLRect r = getRect(); + + if (!mLoading) + { + childSetTextArg("status", "[STATUS]", getString("status_idle")); + } + + childSetTextArg("description_label", "[PRIM_COST]", llformat("%d", mModelPreview->mResourceCost)); + childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); + + if (mDecompFloater) + { + mDecompFloater->childSetText("status", gMeshRepo.mDecompThread->mStatus); + } + + U32 resource_cost = mModelPreview->mResourceCost*10; + + if (childGetValue("upload_textures").asBoolean()) + { + resource_cost += mModelPreview->mTextureSet.size()*10; + } + + childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", resource_cost)); + + if (mModelPreview) + { + gGL.color3f(1.f, 1.f, 1.f); + + gGL.getTexUnit(0)->bind(mModelPreview); + + gGL.begin( LLRender::QUADS ); + { + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop); + } + gGL.end(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } +} + +//----------------------------------------------------------------------------- +// handleMouseDown() +//----------------------------------------------------------------------------- +BOOL LLFloaterModelPreview::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (mPreviewRect.pointInRect(x, y)) + { + bringToFront( x, y ); + gFocusMgr.setMouseCapture(this); + gViewerWindow->hideCursor(); + mLastMouseX = x; + mLastMouseY = y; + return TRUE; + } + + return LLFloater::handleMouseDown(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleMouseUp() +//----------------------------------------------------------------------------- +BOOL LLFloaterModelPreview::handleMouseUp(S32 x, S32 y, MASK mask) +{ + gFocusMgr.setMouseCapture(FALSE); + gViewerWindow->showCursor(); + return LLFloater::handleMouseUp(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleHover() +//----------------------------------------------------------------------------- +BOOL LLFloaterModelPreview::handleHover (S32 x, S32 y, MASK mask) +{ + MASK local_mask = mask & ~MASK_ALT; + + if (mModelPreview && hasMouseCapture()) + { + if (local_mask == MASK_PAN) + { + // pan here + mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); + } + else if (local_mask == MASK_ORBIT) + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; + + mModelPreview->rotate(yaw_radians, pitch_radians); + } + else + { + + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; + + mModelPreview->rotate(yaw_radians, 0.f); + mModelPreview->zoom(zoom_amt); + } + + + mModelPreview->refresh(); + + LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY); + } + + if (!mPreviewRect.pointInRect(x, y) || !mModelPreview) + { + return LLFloater::handleHover(x, y, mask); + } + else if (local_mask == MASK_ORBIT) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); + } + else if (local_mask == MASK_PAN) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// handleScrollWheel() +//----------------------------------------------------------------------------- +BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + if (mPreviewRect.pointInRect(x, y) && mModelPreview) + { + mModelPreview->zoom((F32)clicks * -0.2f); + mModelPreview->refresh(); + } + + return TRUE; +} + +//static +void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data) +{ + LLCDParam* param = (LLCDParam*) data; + + LLCDResult ret = LLCD_OK; + + if (LLConvexDecomposition::getInstance() == NULL) + { + llinfos << "convex decomposition tool is a stub on this platform. cannot get decomp." << llendl; + return; + } + + if (param->mType == LLCDParam::LLCD_FLOAT) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, (F32) ctrl->getValue().asReal()); + } + else if (param->mType == LLCDParam::LLCD_INTEGER || + param->mType == LLCDParam::LLCD_ENUM) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, ctrl->getValue().asInteger()); + } + else if (param->mType == LLCDParam::LLCD_BOOLEAN) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, ctrl->getValue().asBoolean()); + } + + if (ret) + { + llerrs << "WTF?" << llendl; + } +} + +//static +void LLFloaterModelPreview::onPhysicsStageExecute(LLUICtrl* ctrl, void* data) +{ + LLCDStageData* stage = (LLCDStageData*) data; + + LLModel* mdl = NULL; + + if (sInstance) + { + if (sInstance->mModelPreview) + { + if (sInstance->mDecompFloater) + { + S32 idx = sInstance->mDecompFloater->childGetValue("model").asInteger(); + if (idx >= 0 && idx < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size()) + { + mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][idx]; + } + } + } + } + + if (mdl) + { + gMeshRepo.mDecompThread->execute(stage->mName, mdl); + } +} + +//static +void LLFloaterModelPreview::onPhysicsStageCancel(LLUICtrl* ctrl, void*data) +{ + gMeshRepo.mDecompThread->cancel(); +} + +void LLFloaterModelPreview::showDecompFloater() +{ + if (!mDecompFloater) + { + LLSD key; + mDecompFloater = new LLPhysicsDecompFloater(key); + + S32 left = 20; + S32 right = 270; + + S32 cur_y = 30; + + { + //add status text + LLTextBox::Params p; + p.name("status"); + p.rect(LLRect(left, cur_y, right-80, cur_y-20)); + mDecompFloater->addChild(LLUICtrlFactory::create(p)); + } + + + { //add cancel button + LLButton::Params p; + p.name("Cancel"); + p.label("Cancel"); + p.rect(LLRect(right-80, cur_y, right, cur_y-20)); + LLButton* button = LLUICtrlFactory::create(p); + button->setCommitCallback(onPhysicsStageCancel, NULL); + mDecompFloater->addChild(button); + } + + cur_y += 30; + + + const LLCDStageData* stage; + S32 stage_count = 0; + if (LLConvexDecomposition::getInstance() != NULL) + { + stage_count = LLConvexDecomposition::getInstance()->getStages(&stage); + } + + const LLCDParam* param; + S32 param_count = 0; + if (LLConvexDecomposition::getInstance() != NULL) + { + param_count = LLConvexDecomposition::getInstance()->getParameters(¶m); + } + + for (S32 j = stage_count-1; j >= 0; --j) + { + LLButton::Params p; + p.name(stage[j].mName); + p.label(stage[j].mName); + p.rect(LLRect(left, cur_y, right, cur_y-20)); + LLButton* button = LLUICtrlFactory::create(p); + button->setCommitCallback(onPhysicsStageExecute, (void*) &stage[j]); + mDecompFloater->addChild(button); + gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j; + cur_y += 30; + // protected against stub by stage_count being 0 for stub above + LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback); + + for (S32 i = 0; i < param_count; ++i) + { + if (param[i].mStage != j) + { + continue; + } + + if (param[i].mType == LLCDParam::LLCD_FLOAT) + { + LLSliderCtrl::Params p; + p.name(param[i].mName); + p.label(param[i].mName); + p.rect(LLRect(left, cur_y, right, cur_y-20)); + p.min_value(param[i].mDetails.mRange.mLow.mFloat); + p.max_value(param[i].mDetails.mRange.mHigh.mFloat); + p.increment(param[i].mDetails.mRange.mDelta.mFloat); + p.decimal_digits(3); + p.initial_value(param[i].mDefault.mFloat); + LLSliderCtrl* slider = LLUICtrlFactory::create(p); + slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); + mDecompFloater->addChild(slider); + cur_y += 30; + } + else if (param[i].mType == LLCDParam::LLCD_INTEGER) + { + LLSliderCtrl::Params p; + p.name(param[i].mName); + p.label(param[i].mName); + p.rect(LLRect(left, cur_y, right, cur_y-20)); + p.min_value(param[i].mDetails.mRange.mLow.mIntOrEnumValue); + p.max_value(param[i].mDetails.mRange.mHigh.mIntOrEnumValue); + p.increment(param[i].mDetails.mRange.mDelta.mIntOrEnumValue); + p.initial_value(param[i].mDefault.mIntOrEnumValue); + LLSliderCtrl* slider = LLUICtrlFactory::create(p); + slider->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); + mDecompFloater->addChild(slider); + cur_y += 30; + } + else if (param[i].mType == LLCDParam::LLCD_BOOLEAN) + { + LLCheckBoxCtrl::Params p; + p.rect(LLRect(left, cur_y, right, cur_y-20)); + p.name(param[i].mName); + p.label(param[i].mName); + p.initial_value(param[i].mDefault.mBool); + LLCheckBoxCtrl* check_box = LLUICtrlFactory::create(p); + check_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); + mDecompFloater->addChild(check_box); + cur_y += 30; + } + else if (param[i].mType == LLCDParam::LLCD_ENUM) + { + LLComboBox::Params p; + p.rect(LLRect(left, cur_y, right/3, cur_y-20)); + p.name(param[i].mName); + p.label(param[i].mName); + LLComboBox* combo_box = LLUICtrlFactory::create(p); + for (S32 k = 0; k < param[i].mDetails.mEnumValues.mNumEnums; ++k) + { + combo_box->add(param[i].mDetails.mEnumValues.mEnumsArray[k].mName, + LLSD::Integer(param[i].mDetails.mEnumValues.mEnumsArray[k].mValue)); + } + combo_box->setValue(param[i].mDefault.mIntOrEnumValue); + combo_box->setCommitCallback(onPhysicsParamCommit, (void*) ¶m[i]); + mDecompFloater->addChild(combo_box); + cur_y += 30; + } + } + } + + //mesh render checkbox + { + LLCheckBoxCtrl::Params p; + p.label("Mesh: "); + p.name("render_mesh"); + p.rect(LLRect(left, cur_y, right/4, cur_y-20)); + LLCheckBoxCtrl* check = LLUICtrlFactory::create(p); + check->setValue(true); + mDecompFloater->addChild(check); + } + + //hull render checkbox + { + LLCheckBoxCtrl::Params p; + p.label("Hull: "); + p.name("render_hull"); + p.rect(LLRect(right/4, cur_y, right/2, cur_y-20)); + LLCheckBoxCtrl* check = LLUICtrlFactory::create(p); + check->setValue(true); + mDecompFloater->addChild(check); + } + + { //submesh combo box label + LLTextBox::Params p; + p.label("Model"); + p.name("model label"); + p.rect(LLRect(right/3, cur_y, right/2, cur_y-20)); + LLTextBox* text_box = LLUICtrlFactory::create(p); + text_box->setValue("Model"); + mDecompFloater->addChild(text_box); + } + { + //add submesh combo box + LLComboBox::Params p; + p.rect(LLRect(right/2, cur_y, right, cur_y-20)); + p.name("model"); + LLComboBox* combo_box = LLUICtrlFactory::create(p); + for (S32 i = 0; i < mModelPreview->mBaseModel.size(); ++i) + { + LLModel* mdl = mModelPreview->mBaseModel[i]; + combo_box->add(mdl->mLabel, i); + } + combo_box->setValue(0); + mDecompFloater->addChild(combo_box); + cur_y += 30; + } + + mDecompFloater->childSetCommitCallback("model", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); + mDecompFloater->childSetCommitCallback("render_mesh", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); + mDecompFloater->childSetCommitCallback("render_hull", LLFloaterModelPreview::refresh, LLFloaterModelPreview::sInstance); + + mDecompFloater->setRect(LLRect(10, cur_y+20, right+20, 10)); + } + + mDecompFloater->openFloater(); +} + +//----------------------------------------------------------------------------- +// onMouseCaptureLost() +//----------------------------------------------------------------------------- +// static +void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handler) +{ + gViewerWindow->showCursor(); +} + +//----------------------------------------------------------------------------- +// LLModelLoader +//----------------------------------------------------------------------------- +LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview) +: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mState(STARTING), mFirstTransform(TRUE) +{ + mJointMap["mPelvis"] = "mPelvis"; + mJointMap["mTorso"] = "mTorso"; + mJointMap["mChest"] = "mChest"; + mJointMap["mNeck"] = "mNeck"; + mJointMap["mHead"] = "mHead"; + mJointMap["mSkull"] = "mSkull"; + mJointMap["mEyeRight"] = "mEyeRight"; + mJointMap["mEyeLeft"] = "mEyeLeft"; + mJointMap["mCollarLeft"] = "mCollarLeft"; + mJointMap["mShoulderLeft"] = "mShoulderLeft"; + mJointMap["mElbowLeft"] = "mElbowLeft"; + mJointMap["mWristLeft"] = "mWristLeft"; + mJointMap["mCollarRight"] = "mCollarRight"; + mJointMap["mShoulderRight"] = "mShoulderRight"; + mJointMap["mElbowRight"] = "mElbowRight"; + mJointMap["mWristRight"] = "mWristRight"; + mJointMap["mHipRight"] = "mHipRight"; + mJointMap["mKneeRight"] = "mKneeRight"; + mJointMap["mAnkleRight"] = "mAnkleRight"; + mJointMap["mFootRight"] = "mFootRight"; + mJointMap["mToeRight"] = "mToeRight"; + mJointMap["mHipLeft"] = "mHipLeft"; + mJointMap["mKneeLeft"] = "mKneeLeft"; + mJointMap["mAnkleLeft"] = "mAnkleLeft"; + mJointMap["mFootLeft"] = "mFootLeft"; + mJointMap["mToeLeft"] = "mToeLeft"; + + mJointMap["avatar_mPelvis"] = "mPelvis"; + mJointMap["avatar_mTorso"] = "mTorso"; + mJointMap["avatar_mChest"] = "mChest"; + mJointMap["avatar_mNeck"] = "mNeck"; + mJointMap["avatar_mHead"] = "mHead"; + mJointMap["avatar_mSkull"] = "mSkull"; + mJointMap["avatar_mEyeRight"] = "mEyeRight"; + mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; + mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; + mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; + mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; + mJointMap["avatar_mWristLeft"] = "mWristLeft"; + mJointMap["avatar_mCollarRight"] = "mCollarRight"; + mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; + mJointMap["avatar_mElbowRight"] = "mElbowRight"; + mJointMap["avatar_mWristRight"] = "mWristRight"; + mJointMap["avatar_mHipRight"] = "mHipRight"; + mJointMap["avatar_mKneeRight"] = "mKneeRight"; + mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; + mJointMap["avatar_mFootRight"] = "mFootRight"; + mJointMap["avatar_mToeRight"] = "mToeRight"; + mJointMap["avatar_mHipLeft"] = "mHipLeft"; + mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; + mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; + mJointMap["avatar_mFootLeft"] = "mFootLeft"; + mJointMap["avatar_mToeLeft"] = "mToeLeft"; + + + mJointMap["hip"] = "mPelvis"; + mJointMap["abdomen"] = "mTorso"; + mJointMap["chest"] = "mChest"; + mJointMap["neck"] = "mNeck"; + mJointMap["head"] = "mHead"; + mJointMap["figureHair"] = "mSkull"; + mJointMap["lCollar"] = "mCollarLeft"; + mJointMap["lShldr"] = "mShoulderLeft"; + mJointMap["lForeArm"] = "mElbowLeft"; + mJointMap["lHand"] = "mWristLeft"; + mJointMap["rCollar"] = "mCollarRight"; + mJointMap["rShldr"] = "mShoulderRight"; + mJointMap["rForeArm"] = "mElbowRight"; + mJointMap["rHand"] = "mWristRight"; + mJointMap["rThigh"] = "mHipRight"; + mJointMap["rShin"] = "mKneeRight"; + mJointMap["rFoot"] = "mFootRight"; + mJointMap["lThigh"] = "mHipLeft"; + mJointMap["lShin"] = "mKneeLeft"; + mJointMap["lFoot"] = "mFootLeft"; +} + +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) +{ + LLVector4a box[] = + { + LLVector4a(-1, 1,-1), + LLVector4a(-1, 1, 1), + LLVector4a(-1,-1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1, 1,-1), + LLVector4a( 1, 1, 1), + LLVector4a( 1,-1,-1), + LLVector4a( 1,-1, 1), + }; + + for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) + { + const LLVolumeFace& face = model->getVolumeFace(j); + + LLVector4a center; + center.setAdd(face.mExtents[0], face.mExtents[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(face.mExtents[1],face.mExtents[0]); + size.mul(0.5f); + + for (U32 i = 0; i < 8; i++) + { + LLVector4a t; + t.setMul(size, box[i]); + t.add(center); + + LLVector4a v; + + mat.affineTransform(t, v); + + if (first_transform) + { + first_transform = FALSE; + min = max = v; + } + else + { + update_min_max(min, max, v); + } + } + } +} + +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) +{ + LLVector4a mina, maxa; + LLMatrix4a mata; + + mata.loadu(mat); + mina.load3(min.mV); + maxa.load3(max.mV); + + stretch_extents(model, mata, mina, maxa, first_transform); + + min.set(mina.getF32ptr()); + max.set(maxa.getF32ptr()); +} + +void LLModelLoader::run() +{ + DAE dae; + domCOLLADA* dom = dae.open(mFilename); + + if (dom) + { + daeDatabase* db = dae.getDatabase(); + + daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH); + + daeDocument* doc = dae.getDoc(mFilename); + if (!doc) + { + llwarns << "can't find internal doc" << llendl; + return; + } + + daeElement* root = doc->getDomRoot(); + if (!root) + { + llwarns << "document has no root" << llendl; + return; + } + + //get unit scale + mTransform.setIdentity(); + + domAsset::domUnit* unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); + + if (unit) + { + F32 meter = unit->getMeter(); + mTransform.mMatrix[0][0] = meter; + mTransform.mMatrix[1][1] = meter; + mTransform.mMatrix[2][2] = meter; + } + + //get up axis rotation + LLMatrix4 rotation; + + domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP + domAsset::domUp_axis* up_axis = + daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + + if (up_axis) + { + up = up_axis->getValue(); + } + + if (up == UPAXISTYPE_X_UP) + { + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + } + else if (up == UPAXISTYPE_Y_UP) + { + rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); + } + + rotation *= mTransform; + mTransform = rotation; + + + for (daeInt idx = 0; idx < count; ++idx) + { //build map of domEntities to LLModel + domMesh* mesh = NULL; + db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); + + if (mesh) + { + LLPointer model = LLModel::loadModelFromDomMesh(mesh); + + if (model.notNull() && validate_model(model)) + { + mModelList.push_back(model); + mModel[mesh] = model; + } + } + } + + count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); + for (daeInt idx = 0; idx < count; ++idx) + { //add skinned meshes as instances + domSkin* skin = NULL; + db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); + + if (skin) + { + domGeometry* geom = daeSafeCast(skin->getSource().getElement()); + + if (geom) + { + domMesh* mesh = geom->getMesh(); + if (mesh) + { + LLModel* model = mModel[mesh]; + if (model) + { + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 normalized_transformation; + normalized_transformation.setTranslation(mesh_translation_vector); + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= normalized_transformation; + normalized_transformation = mesh_scale; + + glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix); + inv_mat = inv_mat.inverse(); + LLMatrix4 inverse_normalized_transformation(inv_mat.m); + + domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); + + if (bind_mat) + { //get bind shape matrix + domFloat4x4& dom_value = bind_mat->getValue(); + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + model->mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + LLMatrix4 trans = normalized_transformation; + trans *= model->mBindShapeMatrix; + model->mBindShapeMatrix = trans; + + } + + /*{ + LLMatrix4 rotation; + if (up == UPAXISTYPE_X_UP) + { + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + } + else if (up == UPAXISTYPE_Z_UP) + { + rotation.initRotation(90.0f * DEG_TO_RAD, 90.0f * DEG_TO_RAD, 0.0f); + } + + rotation *= model->mBindShapeMatrix; + model->mBindShapeMatrix = rotation; + }*/ + + + domSkin::domJoints* joints = skin->getJoints(); + + domInputLocal_Array& joint_input = joints->getInput_array(); + + for (size_t i = 0; i < joint_input.getCount(); ++i) + { + domInputLocal* input = joint_input.get(i); + xsNMTOKEN semantic = input->getSemantic(); + + if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) + { //found joint source, fill model->mJointMap and model->mJointList + daeElement* elem = input->getSource().getElement(); + + domSource* source = daeSafeCast(elem); + if (source) + { + + + domName_array* names_source = source->getName_array(); + + if (names_source) + { + domListOfNames &names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j)); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mJointList.push_back(name); + model->mJointMap[name] = j; + } + } + else + { + domIDREF_array* names_source = source->getIDREF_array(); + if (names_source) + { + xsIDREFS& names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j).getID()); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mJointList.push_back(name); + model->mJointMap[name] = j; + } + } + } + } + } + else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) + { //found inv_bind_matrix array, fill model->mInvBindMatrix + domSource* source = daeSafeCast(input->getSource().getElement()); + if (source) + { + domFloat_array* t = source->getFloat_array(); + if (t) + { + domListOfFloats& transform = t->getValue(); + S32 count = transform.getCount()/16; + + for (S32 k = 0; k < count; ++k) + { + LLMatrix4 mat; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + mat.mMatrix[i][j] = transform[k*16 + i + j*4]; + } + } + + model->mInvBindMatrix.push_back(mat); + } + } + } + } + } + + + //grab raw position array + + domVertices* verts = mesh->getVertices(); + if (verts) + { + domInputLocal_Array& inputs = verts->getInput_array(); + for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) + { + domSource* pos_source = daeSafeCast(inputs[i]->getSource().getElement()); + if (pos_source) + { + domFloat_array* pos_array = pos_source->getFloat_array(); + if (pos_array) + { + domListOfFloats& pos = pos_array->getValue(); + + for (size_t j = 0; j < pos.getCount(); j += 3) + { + if (pos.getCount() <= j+2) + { + llerrs << "WTF?" << llendl; + } + + LLVector3 v(pos[j], pos[j+1], pos[j+2]); + + //transform from COLLADA space to volume space + v = v * inverse_normalized_transformation; + + model->mPosition.push_back(v); + } + } + } + } + } + } + + //grab skin weights array + domSkin::domVertex_weights* weights = skin->getVertex_weights(); + if (weights) + { + domInputLocalOffset_Array& inputs = weights->getInput_array(); + domFloat_array* vertex_weights = NULL; + for (size_t i = 0; i < inputs.getCount(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) + { + domSource* weight_source = daeSafeCast(inputs[i]->getSource().getElement()); + if (weight_source) + { + vertex_weights = weight_source->getFloat_array(); + } + } + } + + if (vertex_weights) + { + domListOfFloats& w = vertex_weights->getValue(); + domListOfUInts& vcount = weights->getVcount()->getValue(); + domListOfInts& v = weights->getV()->getValue(); + + U32 c_idx = 0; + for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) + { //for each vertex + daeUInt count = vcount[vc_idx]; + + //create list of weights that influence this vertex + LLModel::weight_list weight_list; + + for (daeUInt i = 0; i < count; ++i) + { //for each weight + daeInt joint_idx = v[c_idx++]; + daeInt weight_idx = v[c_idx++]; + + if (joint_idx == -1) + { + //ignore bindings to bind_shape_matrix + continue; + } + + F32 weight_value = w[weight_idx]; + + weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); + } + + //sort by joint weight + std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); + + std::vector wght; + + F32 total = 0.f; + + for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) + { //take up to 4 most significant weights + if (weight_list[i].mWeight > 0.f) + { + wght.push_back( weight_list[i] ); + total += weight_list[i].mWeight; + } + } + + F32 scale = 1.f/total; + if (scale != 1.f) + { //normalize weights + for (U32 i = 0; i < wght.size(); ++i) + { + wght[i].mWeight *= scale; + } + } + + model->mSkinWeights[model->mPosition[vc_idx]] = wght; + } + + //add instance to scene for this model + + LLMatrix4 transform; + std::vector materials; + materials.resize(model->getNumVolumeFaces()); + mScene[transform].push_back(LLModelInstance(model, transform, materials)); + stretch_extents(model, transform, mExtents[0], mExtents[1], mFirstTransform); + } + } + } + } + } + } + } + + daeElement* scene = root->getDescendant("visual_scene"); + if (!scene) + { + llwarns << "document has no visual_scene" << llendl; + return; + } + + processElement(scene); + + mPreview->loadModelCallback(mLod); + } +} + +void LLModelLoader::processElement(daeElement* element) +{ + LLMatrix4 saved_transform = mTransform; + + domTranslate* translate = daeSafeCast(element); + if (translate) + { + domFloat3 dom_value = translate->getValue(); + + LLMatrix4 translation; + translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + translation *= mTransform; + mTransform = translation; + } + + domRotate* rotate = daeSafeCast(element); + if (rotate) + { + domFloat4 dom_value = rotate->getValue(); + + LLMatrix4 rotation; + rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); + + rotation *= mTransform; + mTransform = rotation; + } + + domScale* scale = daeSafeCast(element); + if (scale) + { + domFloat3 dom_value = scale->getValue(); + + LLMatrix4 scaling; + scaling.initScale(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + scaling *= mTransform; + mTransform = scaling; + } + + domMatrix* matrix = daeSafeCast(element); + if (matrix) + { + domFloat4x4 dom_value = matrix->getValue(); + + LLMatrix4 matrix_transform; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + matrix_transform *= mTransform; + mTransform = matrix_transform; + } + + domInstance_geometry* instance_geo = daeSafeCast(element); + if (instance_geo) + { + domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); + if (geo) + { + domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); + if (mesh) + { + LLModel* model = mModel[mesh]; + if (model) + { + LLMatrix4 transformation = mTransform; + + std::vector materials = getMaterials(model, instance_geo); + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + mesh_translation *= transformation; + transformation = mesh_translation; + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= transformation; + transformation = mesh_scale; + + mScene[transformation].push_back(LLModelInstance(model, transformation, materials)); + + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + } + } + } + } + + domInstance_node* instance_node = daeSafeCast(element); + if (instance_node) + { + daeElement* instance = instance_node->getUrl().getElement(); + if (instance) + { + processElement(instance); + } + } + + //process children + daeTArray< daeSmartRef > children = element->getChildren(); + for (S32 i = 0; i < children.getCount(); i++) + { + processElement(children[i]); + } + + domNode* node = daeSafeCast(element); + if (node) + { //this element was a node, restore transform before processiing siblings + mTransform = saved_transform; + } +} + +std::vector LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) +{ + std::vector materials; + for (int i = 0; i < model->mMaterialList.size(); i++) + { + LLImportMaterial import_material; + + domInstance_material* instance_mat = NULL; + + domBind_material::domTechnique_common* technique = + daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); + + if (technique) + { + daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); + for (int j = 0; j < inst_materials.getCount(); j++) + { + std::string symbol(inst_materials[j]->getSymbol()); + + if (symbol == model->mMaterialList[i]) // found the binding + { + instance_mat = inst_materials[j]; + } + } + } + + if (instance_mat) + { + domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); + if (material) + { + domInstance_effect* instance_effect = + daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); + if (instance_effect) + { + domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); + if (effect) + { + domProfile_COMMON* profile = + daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); + if (profile) + { + import_material = profileToMaterial(profile); + } + } + } + } + } + + materials.push_back(import_material); + } + + return materials; +} + +LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) +{ + LLImportMaterial mat; + mat.mFullbright = FALSE; + + daeElement* diffuse = material->getDescendant("diffuse"); + if (diffuse) + { + domCommon_color_or_texture_type_complexType::domTexture* texture = + daeSafeCast(diffuse->getDescendant("texture")); + if (texture) + { + domCommon_newparam_type_Array newparams = material->getNewparam_array(); + for (S32 i = 0; i < newparams.getCount(); i++) + { + domFx_surface_common* surface = newparams[i]->getSurface(); + if (surface) + { + domFx_surface_init_common* init = surface->getFx_surface_init_common(); + if (init) + { + domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); + + if (init_from.getCount() > i) + { + domImage* image = daeSafeCast(init_from[i]->getValue().getElement()); + if (image) + { + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (init) + { + std::string filename = cdom::uriToNativePath(init->getValue().str()); + + mat.mDiffuseMap = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + filename, TRUE, LLViewerTexture::BOOST_PREVIEW); + mat.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, this->mPreview, NULL, NULL); + + mat.mDiffuseMap->forceToSaveRawImage(); + mat.mDiffuseMapFilename = filename; + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + } + } + } + + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(diffuse->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + mat.mDiffuseColor = value; + } + } + + daeElement* emission = material->getDescendant("emission"); + if (emission) + { + LLColor4 emission_color = getDaeColor(emission); + if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) + { + mat.mFullbright = TRUE; + } + } + + return mat; +} + +// try to get a decent label for this element +std::string LLModelLoader::getElementLabel(daeElement *element) +{ + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + if (parent) + { + // if parent has a name, use it + std::string name = parent->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if parent has an ID, use it + if (parent->getID()) + { + return std::string(parent->getID()); + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name); + } + + // if all else fails, use "object" + return std::string("object"); +} + +LLColor4 LLModelLoader::getDaeColor(daeElement* element) +{ + LLColor4 value; + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(element->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + } + + return value; +} + +//----------------------------------------------------------------------------- +// LLModelPreview +//----------------------------------------------------------------------------- + +LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloaterModelPreview* fmp) +: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL) +{ + mNeedsUpdate = TRUE; + mCameraDistance = 0.f; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; + mTextureName = 0; + mPreviewLOD = 3; + mModelLoader = NULL; + + mLODMode[0] = 0; + + for (U32 i = 1; i < LLModel::NUM_LODS; i++) + { + mLODMode[i] = 1; + mLimit[i] = 0; + } + + mFMP = fmp; + + glodInit(); +} + +LLModelPreview::~LLModelPreview() +{ + if (mModelLoader) + { + delete mModelLoader; + mModelLoader = NULL; + } + + //*HACK : *TODO : turn this back on when we understand why this crashes + //glodShutdown(); +} + +U32 LLModelPreview::calcResourceCost() +{ + rebuildUploadData(); + + U32 cost = 0; + std::set accounted; + U32 num_points = 0; + U32 num_hulls = 0; + + for (U32 i = 0; i < mUploadData.size(); ++i) + { + LLModelInstance& instance = mUploadData[i]; + + if (accounted.find(instance.mModel) == accounted.end()) + { + accounted.insert(instance.mModel); + + LLModel::physics_shape& physics_shape = instance.mLOD[LLModel::LOD_PHYSICS] ? instance.mLOD[LLModel::LOD_PHYSICS]->mPhysicsShape : instance.mModel->mPhysicsShape; + + LLSD ret = LLModel::writeModel("", + instance.mLOD[4], + instance.mLOD[3], + instance.mLOD[2], + instance.mLOD[1], + instance.mLOD[0], + physics_shape, + TRUE); + cost += gMeshRepo.calcResourceCost(ret); + + + num_hulls += physics_shape.size(); + for (U32 i = 0; i < physics_shape.size(); ++i) + { + num_points += physics_shape[i].size(); + } + } + } + + mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",num_hulls)); + mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",num_points)); + + updateStatusMessages(); + + return cost; +} + +void LLModelPreview::rebuildUploadData() +{ + mUploadData.clear(); + mTextureSet.clear(); + + //fill uploaddata instance vectors from scene data + + for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) + { //for each transform in scene + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { //for each instance with said transform applied + LLModelInstance& instance = *model_iter; + + LLModel* base_model = instance.mModel; + + S32 idx = 0; + for (idx = 0; idx < mBaseModel.size(); ++idx) + { //find reference instance for this model + if (mBaseModel[idx] == base_model) + { + break; + } + } + + for (U32 i = 0; i < LLModel::NUM_LODS; i++) + { //fill LOD slots based on reference model index + if (!mModel[i].empty()) + { + instance.mLOD[i] = mModel[i][idx]; + } + else + { + instance.mLOD[i] = NULL; + } + } + + mUploadData.push_back(instance); + } + } +} + + +void LLModelPreview::loadModel(std::string filename, S32 lod) +{ + LLMutexLock lock(this); + + if (mModelLoader) + { + delete mModelLoader; + mModelLoader = NULL; + } + + if (filename.empty() && mBaseModel.empty()) + { + mFMP->closeFloater(false); + return; + } + + if (lod == 3 && !mGroup.empty()) + { + for (std::map::iterator iter = mGroup.begin(); iter != mGroup.end(); ++iter) + { + glodDeleteGroup(iter->second); + stop_gloderror(); + } + + for (std::map::iterator iter = mObject.begin(); iter != mObject.end(); ++iter) + { + glodDeleteObject(iter->second); + stop_gloderror(); + } + + mGroup.clear(); + mObject.clear(); + } + + mModelLoader = new LLModelLoader(filename, lod, this); + + mModelLoader->start(); + + mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); + + if (mFMP->childGetValue("description_form").asString().empty()) + { + std::string name = gDirUtilp->getBaseFileName(filename, true); + mFMP->childSetValue("description_form", name); + } + + mFMP->openFloater(); +} + +void LLModelPreview::clearIncompatible(S32 lod) +{ + for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) + { //clear out any entries that aren't compatible with this model + if (i != lod) + { + if (mModel[i].size() != mModel[lod].size()) + { + mModel[i].clear(); + mScene[i].clear(); + mVertexBuffer[i].clear(); + + if (i == LLModel::LOD_HIGH) + { + mBaseModel = mModel[lod]; + mBaseScene = mScene[lod]; + mVertexBuffer[5].clear(); + } + } + } + } +} + +void LLModelPreview::loadModelCallback(S32 lod) +{ //NOT the main thread + LLMutexLock lock(this); + if (!mModelLoader) + { + return; + } + + mModel[lod] = mModelLoader->mModelList; + mScene[lod] = mModelLoader->mScene; + mVertexBuffer[lod].clear(); + + setPreviewLOD(lod); + + + if (lod == LLModel::LOD_HIGH) + { //save a copy of the highest LOD for automatic LOD manipulation + mBaseModel = mModel[lod]; + mBaseScene = mScene[lod]; + mVertexBuffer[5].clear(); + //mModel[lod] = NULL; + } + + clearIncompatible(lod); + + mResourceCost = calcResourceCost(); + + mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f; + mPreviewScale = (mModelLoader->mExtents[1] - mModelLoader->mExtents[0]) * 0.5f; + setPreviewTarget(mPreviewScale.magVec()*2.f); + + mFMP->mLoading = FALSE; + refresh(); +} + +void LLModelPreview::smoothNormals() +{ + S32 which_lod = mPreviewLOD; + + + if (which_lod > 4 || which_lod < 0 || + mModel[which_lod].empty()) + { + return; + } + + F32 angle_cutoff = mFMP->childGetValue("edge threshold").asReal(); + + angle_cutoff *= DEG_TO_RAD; + + if (which_lod == 3 && !mBaseModel.empty()) + { + for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + { + (*iter)->smoothNormals(angle_cutoff); + } + + mVertexBuffer[5].clear(); + } + + for (LLModelLoader::model_list::iterator iter = mModel[which_lod].begin(); iter != mModel[which_lod].end(); ++iter) + { + (*iter)->smoothNormals(angle_cutoff); + } + + mVertexBuffer[which_lod].clear(); + refresh(); + +} + +void LLModelPreview::consolidate() +{ + std::map > composite; + + LLMatrix4 identity; + + //bake out each node in current scene to composite + for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) + { //for each transform in current scene + LLMatrix4 mat = iter->first; + glh::matrix4f inv_trans = glh::matrix4f((F32*) mat.mMatrix).inverse().transpose(); + LLMatrix4 norm_mat(inv_trans.m); + + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { //for each instance with that transform + LLModelInstance& source_instance = *model_iter; + LLModel* source = source_instance.mModel; + + if (!validate_model(source)) + { + llerrs << "Invalid model found!" << llendl; + } + + for (S32 i = 0; i < source->getNumVolumeFaces(); ++i) + { //for each face in instance + const LLVolumeFace& src_face = source->getVolumeFace(i); + LLImportMaterial& source_material = source_instance.mMaterial[i]; + + //get model in composite that is composite for this material + LLModel* model = NULL; + + if (composite.find(source_material) != composite.end()) + { + model = composite[source_material].rbegin()->mModel; + if (model->getVolumeFace(0).mNumVertices + src_face.mNumVertices > 65535) + { + model = NULL; + } + } + + if (model == NULL) + { //no model found, make new model + std::vector materials; + materials.push_back(source_material); + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + model = new LLModel(volume_params, 0.f); + model->mLabel = source->mLabel; + model->setNumVolumeFaces(0); + composite[source_material].push_back(LLModelInstance(model, identity, materials)); + } + + model->appendFace(src_face, source->mMaterialList[i], mat, norm_mat); + } + } + } + + + //condense composite into as few LLModel instances as possible + LLModelLoader::model_list new_model; + std::vector instance_list; + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + std::vector empty_material; + LLModelInstance cur_instance(new LLModel(volume_params, 0.f), identity, empty_material); + cur_instance.mModel->setNumVolumeFaces(0); + + BOOL first_transform = TRUE; + + LLModelLoader::scene new_scene; + LLVector3 min,max; + + for (std::map >::iterator iter = composite.begin(); + iter != composite.end(); + ++iter) + { + std::map >::iterator next_iter = iter; ++next_iter; + + for (std::vector::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + LLModel* source = instance_iter->mModel; + + if (instance_iter->mMaterial.size() != 1) + { + llerrs << "WTF?" << llendl; + } + + if (source->getNumVolumeFaces() != 1) + { + llerrs << "WTF?" << llendl; + } + + if (source->mMaterialList.size() != 1) + { + llerrs << "WTF?" << llendl; + } + + cur_instance.mModel->addFace(source->getVolumeFace(0)); + cur_instance.mMaterial.push_back(instance_iter->mMaterial[0]); + cur_instance.mModel->mMaterialList.push_back(source->mMaterialList[0]); + + BOOL last_model = FALSE; + + std::vector::iterator next_instance = instance_iter; ++next_instance; + + if (next_iter == composite.end() && + next_instance == iter->second.end()) + { + last_model = TRUE; + } + + if (last_model || cur_instance.mModel->getNumVolumeFaces() >= MAX_MODEL_FACES) + { + cur_instance.mModel->mLabel = source->mLabel; + + cur_instance.mModel->optimizeVolumeFaces(); + cur_instance.mModel->normalizeVolumeFaces(); + + if (!validate_model(cur_instance.mModel)) + { + llerrs << "Invalid model detected." << llendl; + } + + new_model.push_back(cur_instance.mModel); + + LLMatrix4 transformation = LLMatrix4(); + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + cur_instance.mModel->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + mesh_translation *= transformation; + transformation = mesh_translation; + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= transformation; + transformation = mesh_scale; + + cur_instance.mTransform = transformation; + + new_scene[transformation].push_back(cur_instance); + stretch_extents(cur_instance.mModel, transformation, min, max, first_transform); + + if (!last_model) + { + cur_instance = LLModelInstance(new LLModel(volume_params, 0.f), identity, empty_material); + cur_instance.mModel->setNumVolumeFaces(0); + } + } + } + } + + mScene[mPreviewLOD] = new_scene; + mModel[mPreviewLOD] = new_model; + mVertexBuffer[mPreviewLOD].clear(); + + if (mPreviewLOD == LLModel::LOD_HIGH) + { + mBaseScene = new_scene; + mBaseModel = new_model; + mVertexBuffer[5].clear(); + } + + mPreviewTarget = (min+max)*0.5f; + mPreviewScale = (max-min)*0.5f; + setPreviewTarget(mPreviewScale.magVec()*2.f); + + clearIncompatible(mPreviewLOD); + + mResourceCost = calcResourceCost(); + refresh(); +} + +void LLModelPreview::scrubMaterials() +{ + for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) + { //for each transform in current scene + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { //for each instance with that transform + LLModelInstance& source_instance = *model_iter; + LLModel* source = source_instance.mModel; + + for (S32 i = 0; i < source->getNumVolumeFaces(); ++i) + { //for each face in instance + LLImportMaterial& source_material = source_instance.mMaterial[i]; + + //clear material info + source_material.mDiffuseColor = LLColor4(1,1,1,1); + source_material.mDiffuseMap = NULL; + source_material.mDiffuseMapFilename.clear(); + source_material.mDiffuseMapLabel.clear(); + source_material.mFullbright = false; + } + } + } + + + mVertexBuffer[mPreviewLOD].clear(); + + if (mPreviewLOD == LLModel::LOD_HIGH) + { + mBaseScene = mScene[mPreviewLOD]; + mBaseModel = mModel[mPreviewLOD]; + mVertexBuffer[5].clear(); + } + + mResourceCost = calcResourceCost(); + refresh(); +} + +void LLModelPreview::genLODs(S32 which_lod) +{ + if (mBaseModel.empty()) + { + return; + } + + LLVertexBuffer::unbind(); + + stop_gloderror(); + static U32 cur_name = 1; + + S32 limit = -1; + + if (which_lod != -1) + { + limit = mLimit[which_lod]; + } + + U32 triangle_count = 0; + + for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + { + LLModel* mdl = *iter; + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + triangle_count += mdl->getVolumeFace(i).mNumIndices/3; + } + } + + U32 base_triangle_count = triangle_count; + + U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; + + for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + { //build GLOD objects for each model in base model list + LLModel* mdl = *iter; + if (mGroup[mdl] == 0) + { + mGroup[mdl] = cur_name++; + mObject[mdl] = cur_name++; + + glodNewGroup(mGroup[mdl]); + stop_gloderror(); + + glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET); + stop_gloderror(); + + glodGroupParameteri(mGroup[mdl], GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR); + stop_gloderror(); + + glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f); + stop_gloderror(); + + glodNewObject(mObject[mdl], mGroup[mdl], GLOD_DISCRETE); + stop_gloderror(); + + if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty()) + { //regenerate vertex buffer for skinned models to prevent animation feedback during LOD generation + mVertexBuffer[5].clear(); + } + + if (mVertexBuffer[5].empty()) + { + genBuffers(5); + } + + U32 tri_count = 0; + for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i) + { + mVertexBuffer[5][mdl][i]->setBuffer(type_mask); + U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices(); + if (num_indices > 2) + { + glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f); + } + tri_count += num_indices/3; + stop_gloderror(); + } + + //store what percentage of total model (in terms of triangle count) this model makes up + mPercentage[mdl] = (F32) tri_count / (F32) base_triangle_count; + + //build glodobject + glodBuildObject(mObject[mdl]); + if (stop_gloderror()) + { + glodDeleteGroup(mGroup[mdl]); + stop_gloderror(); + glodDeleteObject(mObject[mdl]); + stop_gloderror(); + + mGroup[mdl] = 0; + mObject[mdl] = 0; + + if (which_lod == -1) + { + mModel[LLModel::LOD_HIGH] = mBaseModel; + } + + return; + } + + } + + if (which_lod == -1 || mLODMode[which_lod] == 1) + { + //generating LODs for all entries, or this entry has a triangle budget + glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET); + stop_gloderror(); + } + else + { + //this entry uses error mode + glodGroupParameteri(mGroup[mdl], GLOD_ADAPT_MODE, GLOD_OBJECT_SPACE_ERROR); + stop_gloderror(); + } + + if (which_lod != -1 && mLODMode[which_lod] == 2) + { + glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, llmax(limit/100.f, 0.01f)); + stop_gloderror(); + } + else + { + glodGroupParameterf(mGroup[mdl], GLOD_OBJECT_SPACE_ERROR_THRESHOLD, 0.025f); + stop_gloderror(); + } + } + + + S32 start = LLModel::LOD_HIGH; + S32 end = 0; + + BOOL error_mode = FALSE; + + if (which_lod != -1) + { + start = end = which_lod; + + if (mLODMode[which_lod] == 2) + { + error_mode = TRUE; + } + } + + + for (S32 lod = start; lod >= end; --lod) + { + if (!error_mode) + { + if (which_lod == -1) + { + if (lod < start) + { + triangle_count /= 3; + } + } + else + { + triangle_count = limit; + } + } + + mModel[lod].clear(); + mModel[lod].resize(mBaseModel.size()); + mVertexBuffer[lod].clear(); + + U32 actual_tris = 0; + U32 actual_verts = 0; + U32 submeshes = 0; + + for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx) + { + LLModel* base = mBaseModel[mdl_idx]; + + U32 target_count = U32(mPercentage[base]*triangle_count); + + if (error_mode) + { + target_count = base->getNumTriangles(); + } + + if (target_count < 4) + { + target_count = 4; + } + + if (which_lod == -1 || mLODMode[which_lod] == 1) + { + glodGroupParameteri(mGroup[base], GLOD_MAX_TRIANGLES, target_count); + stop_gloderror(); + } + + glodAdaptGroup(mGroup[base]); + stop_gloderror(); + + GLint patch_count = 0; + glodGetObjectParameteriv(mObject[base], GLOD_NUM_PATCHES, &patch_count); + stop_gloderror(); + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); + + GLint* sizes = new GLint[patch_count*2]; + glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes); + stop_gloderror(); + + GLint* names = new GLint[patch_count]; + glodGetObjectParameteriv(mObject[base], GLOD_PATCH_NAMES, names); + stop_gloderror(); + + mModel[lod][mdl_idx]->setNumVolumeFaces(patch_count); + + LLModel* target_model = mModel[lod][mdl_idx]; + + for (GLint i = 0; i < patch_count; ++i) + { + LLPointer buff = new LLVertexBuffer(type_mask, 0); + + if (sizes[i*2+1] > 0 && sizes[i*2] > 0) + { + buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true); + buff->setBuffer(type_mask); + glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer()); + stop_gloderror(); + } + else + { //this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0) + buff->allocateBuffer(1, 3, true); + memset(buff->getMappedData(), 0, buff->getSize()); + memset(buff->getIndicesPointer(), 0, buff->getIndicesSize()); + } + + buff->validateRange(0, buff->getNumVerts()-1, buff->getNumIndices(), 0); + + LLStrider pos; + LLStrider norm; + LLStrider tc; + LLStrider index; + + buff->getVertexStrider(pos); + buff->getNormalStrider(norm); + buff->getTexCoord0Strider(tc); + buff->getIndexStrider(index); + + + target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices()); + actual_tris += buff->getNumIndices()/3; + actual_verts += buff->getNumVerts(); + ++submeshes; + + if (!validate_face(target_model->getVolumeFace(names[i]))) + { + llerrs << "Invalid face generated during LOD generation." << llendl; + } + } + + //blind copy skin weights and just take closest skin weight to point on + //decimated mesh for now (auto-generating LODs with skin weights is still a bit + //of an open problem). + target_model->mPosition = base->mPosition; + target_model->mSkinWeights = base->mSkinWeights; + target_model->mJointMap = base->mJointMap; + target_model->mJointList = base->mJointList; + target_model->mInvBindMatrix = base->mInvBindMatrix; + target_model->mBindShapeMatrix = base->mBindShapeMatrix; + + if (!validate_model(target_model)) + { + llerrs << "Invalid model generated when creating LODs" << llendl; + } + + delete [] sizes; + delete [] names; + } + + //rebuild scene based on mBaseScene + mScene[lod].clear(); + mScene[lod] = mBaseScene; + + for (U32 i = 0; i < mBaseModel.size(); ++i) + { + LLModel* mdl = mBaseModel[i]; + LLModel* target = mModel[lod][i]; + if (target) + { + for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter) + { + for (U32 j = 0; j < iter->second.size(); ++j) + { + if (iter->second[j].mModel == mdl) + { + iter->second[j].mModel = target; + } + } + } + } + } + + mResourceCost = calcResourceCost(); + } +} + +void LLModelPreview::updateStatusMessages() +{ + //triangle/vertex/submesh count for each mesh asset for each lod + std::vector tris[LLModel::NUM_LODS]; + std::vector verts[LLModel::NUM_LODS]; + std::vector submeshes[LLModel::NUM_LODS]; + + //total triangle/vertex/submesh count for each lod + S32 total_tris[LLModel::NUM_LODS]; + S32 total_verts[LLModel::NUM_LODS]; + S32 total_submeshes[LLModel::NUM_LODS]; + + for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) + { + //initialize total for this lod to 0 + total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; + + for (U32 i = 0; i < mModel[lod].size(); ++i) + { //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); + + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; + } + + //add this model to the lod total + total_tris[lod] += cur_tris; + total_verts[lod] += cur_verts; + total_submeshes[lod] += cur_submeshes; + + //store this model's counts to asset data + tris[lod].push_back(cur_tris); + verts[lod].push_back(cur_verts); + submeshes[lod].push_back(cur_submeshes); + } + } + + + std::string upload_message; + + for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) + { + mFMP->childSetTextArg(info_name[lod], "[TRIANGLES]", llformat("%d", total_tris[lod])); + mFMP->childSetTextArg(info_name[lod], "[VERTICES]", llformat("%d", total_verts[lod])); + mFMP->childSetTextArg(info_name[lod], "[SUBMESHES]", llformat("%d", total_submeshes[lod])); + + std::string message = "good"; + + const U32 lod_high = LLModel::LOD_HIGH; + + if (lod != lod_high) + { + if (total_submeshes[lod] == 0) + { //no model loaded for this lod, see if one is required + for (U32 i = 0; i < verts[lod_high].size(); ++i) + { + const F32 ratio = 0.5f; + const S32 required_verts = 128; + + F32 scaler = powf(0.5f, lod_high-lod); + S32 max_verts = verts[lod_high][i]*scaler; + + if (max_verts > required_verts) + { //some model in this slot might have more than 128 vertices + + //if any model higher up the chain has more than 128 vertices, + // lod is required here + for (S32 j = lod+1; j <= LLModel::LOD_HIGH; ++j) + { + if (verts[j].size() > i && verts[j][i] > 128) + { + message = "required"; + upload_message = "missing_lod"; + } + } + } + } + } + else if (total_submeshes[lod] != total_submeshes[lod_high]) + { + message = "mesh_mismatch"; + upload_message = "bad_lod"; + } + else if (tris[lod].size() != tris[lod_high].size()) + { + message = "model_mismatch"; + upload_message = "bad_lod"; + } + else + { + for (U32 i = 0; i < verts[lod].size(); ++i) + { + const F32 ratio = 0.5f; + + F32 scaler = powf(0.5f, lod_high-lod); + S32 max_verts = verts[lod_high][i]*scaler; + + if (verts[lod][i] > max_verts) + { + message = "too_heavy"; + upload_message = "bad_lod"; + } + } + } + } + + mFMP->childSetTextArg(info_name[lod], "[MESSAGE]", mFMP->getString(message)); + } + + if (upload_message.empty()) + { + mFMP->childSetTextArg("upload_message", "[MESSAGE]", std::string("")); + mFMP->childEnable("ok_btn"); + } + else + { + mFMP->childSetTextArg("upload_message", "[MESSAGE]", mFMP->getString(upload_message)); + mFMP->childDisable("ok_btn"); + } +} + +void LLModelPreview::setPreviewTarget(F32 distance) +{ + mCameraDistance = distance; + mCameraZoom = 1.f; + mCameraPitch = 0.f; + mCameraYaw = 0.f; + mCameraOffset.clearVec(); +} + +void LLModelPreview::genBuffers(S32 lod) +{ + U32 tri_count = 0; + U32 vertex_count = 0; + U32 mesh_count = 0; + + LLModelLoader::model_list* model = NULL; + + if (lod < 0 || lod > 4) + { + model = &mBaseModel; + lod = 5; + } + else + { + model = &(mModel[lod]); + } + + if (!mVertexBuffer[lod].empty()) + { + mVertexBuffer[lod].clear(); + } + + mVertexBuffer[lod].clear(); + + LLModelLoader::model_list::iterator base_iter = mBaseModel.begin(); + + for (LLModelLoader::model_list::iterator iter = model->begin(); iter != model->end(); ++iter) + { + LLModel* mdl = *iter; + if (!mdl) + { + continue; + } + + LLModel* base_mdl = *base_iter; + base_iter++; + + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + const LLVolumeFace &vf = mdl->getVolumeFace(i); + U32 num_vertices = vf.mNumVertices; + U32 num_indices = vf.mNumIndices; + + if (!num_vertices || ! num_indices) + { + continue; + } + + LLVertexBuffer* vb = NULL; + + bool skinned = !mdl->mSkinWeights.empty(); + + U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; + + if (skinned) + { + mask |= LLVertexBuffer::MAP_WEIGHT4; + } + + vb = new LLVertexBuffer(mask, 0); + + vb->allocateBuffer(num_vertices, num_indices, TRUE); + + LLStrider vertex_strider; + LLStrider normal_strider; + LLStrider tc_strider; + LLStrider index_strider; + LLStrider weights_strider; + + vb->getVertexStrider(vertex_strider); + vb->getNormalStrider(normal_strider); + vb->getTexCoord0Strider(tc_strider); + vb->getIndexStrider(index_strider); + + if (skinned) + { + vb->getWeight4Strider(weights_strider); + } + + LLVector4a::memcpyNonAliased16((F32*) vertex_strider.get(), (F32*) vf.mPositions, num_vertices*4*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) tc_strider.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + LLVector4a::memcpyNonAliased16((F32*) normal_strider.get(), (F32*) vf.mNormals, num_vertices*4*sizeof(F32)); + + if (skinned) + { + // build vertices and normals + for (U32 i = 0; i < num_vertices; i++) + { + //find closest weight to vf.mVertices[i].mPosition + LLVector3 pos(vf.mPositions[i].getF32ptr()); + + LLModel::weight_list weight_list = base_mdl->getJointInfluences(pos); + + LLVector4 w(0,0,0,0); + if (weight_list.size() > 4) + { + llerrs << "WTF?" << llendl; + } + + for (U32 i = 0; i < weight_list.size(); ++i) + { + F32 wght = llmin(weight_list[i].mWeight, 0.999999f); + F32 joint = (F32) weight_list[i].mJointIdx; + w.mV[i] = joint + wght; + } + + *(weights_strider++) = w; + } + } + + // build indices + for (U32 i = 0; i < num_indices; i++) + { + *(index_strider++) = vf.mIndices[i]; + } + + mVertexBuffer[lod][mdl].push_back(vb); + + vertex_count += num_vertices; + tri_count += num_indices/3; + ++mesh_count; + + } + } + + if (lod == 4) + { + for (U32 i = 0; i < 4; i++) + { + LLSpinCtrl* lim = mFMP->getChild(limit_name[i], TRUE); + + lim->setMaxValue(tri_count); + } + } +} + +//----------------------------------------------------------------------------- +// render() +//----------------------------------------------------------------------------- +BOOL LLModelPreview::render() +{ + LLMutexLock lock(this); + mNeedsUpdate = FALSE; + + S32 width = getWidth(); + S32 height = getHeight(); + + LLGLSUIDefault def; + LLGLDisable no_blend(GL_BLEND); + LLGLEnable cull(GL_CULL_FACE); + LLGLDepthTest depth(GL_TRUE); + LLGLDisable fog(GL_FOG); + + glMatrixMode(GL_PROJECTION); + gGL.pushMatrix(); + glLoadIdentity(); + glOrtho(0.0f, width, 0.0f, height, -1.0f, 1.0f); + + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + glLoadIdentity(); + + gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); + + gl_rect_2d_simple( width, height ); + + bool avatar_preview = false; + for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) + { + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { + LLModelInstance& instance = *model_iter; + LLModel* model = instance.mModel; + if (!model->mSkinWeights.empty()) + { + avatar_preview = true; + } + } + } + + mFMP->childSetEnabled("consolidate", !avatar_preview); + + F32 explode = mFMP->childGetValue("explode").asReal(); + + glMatrixMode(GL_PROJECTION); + gGL.popMatrix(); + + glMatrixMode(GL_MODELVIEW); + gGL.popMatrix(); + + glClear(GL_DEPTH_BUFFER_BIT); + + LLViewerCamera::getInstance()->setAspect((F32) width / height ); + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + + LLVector3 target_pos = mPreviewTarget; + LLVector3 offset = mCameraOffset; + + F32 z_near = llmax(mCameraDistance-mPreviewScale.magVec(), 0.001f); + F32 z_far = mCameraDistance+mPreviewScale.magVec(); + + if (avatar_preview) + { + target_pos = gAgentAvatarp->getPositionAgent(); + z_near = 0.01f; + z_far = 1024.f; + mCameraDistance = 16.f; + + //render avatar previews every frame + refresh(); + } + + LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * + LLQuaternion(mCameraYaw, LLVector3::z_axis); + + LLQuaternion av_rot = camera_rot; + LLViewerCamera::getInstance()->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos); // point of interest + + + LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, width, height, FALSE, z_near, z_far); + + stop_glerror(); + + gPipeline.enableLightsAvatar(); + + gGL.pushMatrix(); + const F32 BRIGHTNESS = 0.9f; + gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + + LLGLEnable normalize(GL_NORMALIZE); + + if (!mBaseModel.empty() && mVertexBuffer[5].empty()) + { + genBuffers(-1); + genBuffers(3); + //genLODs(); + } + + bool physics = (mPreviewLOD == LLModel::LOD_PHYSICS); + + S32 physics_idx = -1; + + bool render_mesh = true; + bool render_hull = false; + + if (physics && mFMP->mDecompFloater) + { + physics_idx = mFMP->mDecompFloater->childGetValue("model").asInteger(); + render_mesh = mFMP->mDecompFloater->childGetValue("render_mesh").asBoolean(); + render_hull = mFMP->mDecompFloater->childGetValue("render_hull").asBoolean(); + } + + if (!mModel[mPreviewLOD].empty()) + { + if (mVertexBuffer[mPreviewLOD].empty()) + { + genBuffers(mPreviewLOD); + } + + if (!avatar_preview) + { + for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) + { + gGL.pushMatrix(); + LLMatrix4 mat = iter->first; + + glMultMatrixf((GLfloat*) mat.mMatrix); + + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { + LLModelInstance& instance = *model_iter; + LLModel* model = instance.mModel; + + if (instance.mTransform != mat) + { + llerrs << "WTF?" << llendl; + } + + if (render_mesh) + { + for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + if (physics) + { + if (physics_idx > -1 && model == mModel[mPreviewLOD][physics_idx]) + { + glColor4f(1,0,0,1); + } + else + { + glColor4f(0.75f, 0.75f, 0.75f, 1.f); + } + } + else + { + glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); + if (i < instance.mMaterial.size() && instance.mMaterial[i].mDiffuseMap.notNull()) + { + gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); + if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) + { + mTextureSet.insert(instance.mMaterial[i].mDiffuseMap); + } + } + } + + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + glColor3f(0.4f, 0.4f, 0.4f); + + if (mFMP->childGetValue("show edges").asBoolean()) + { + glLineWidth(3.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glLineWidth(1.f); + } + } + } + + if (render_hull) + { + LLPhysicsDecomp* decomp = gMeshRepo.mDecompThread; + if (decomp) + { + LLMutexLock(decomp->mMutex); + + std::map > >::iterator iter = + mPhysicsMesh.find(model); + if (iter != mPhysicsMesh.end()) + { + for (U32 i = 0; i < iter->second.size(); ++i) + { + if (explode > 0.f) + { + gGL.pushMatrix(); + + LLVector3 offset = model->mHullCenter[i]-model->mPhysicsCenter; + offset *= explode; + + gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); + } + + static std::vector hull_colors; + + if (i+1 >= hull_colors.size()) + { + hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 255)); + } + + LLVertexBuffer* buff = iter->second[i]; + if (buff) + { + buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL); + + glColor4ubv(hull_colors[i].mV); + buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); + + if (mFMP->childGetValue("show edges").asBoolean()) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glLineWidth(3.f); + glColor4ub(hull_colors[i].mV[0]/2, hull_colors[i].mV[1]/2, hull_colors[i].mV[2]/2, 255); + buff->drawArrays(LLRender::TRIANGLES, 0, buff->getNumVerts()); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glLineWidth(1.f); + } + } + + if (explode > 0.f) + { + gGL.popMatrix(); + } + } + } + } + + //mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[HULLS]", llformat("%d",decomp->mHulls.size())); + //mFMP->childSetTextArg(info_name[LLModel::LOD_PHYSICS], "[POINTS]", llformat("%d",decomp->mTotalPoints)); + } + } + + gGL.popMatrix(); + } + + if (physics) + { + mPreviewLOD = LLModel::LOD_PHYSICS; + } + } + else + { + LLVOAvatarSelf* avatar = gAgentAvatarp; + target_pos = avatar->getPositionAgent(); + + LLViewerCamera::getInstance()->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos); // point of interest + + avatar->renderCollisionVolumes(); + + for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter) + { + for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) + { + LLModelInstance& instance = *model_iter; + LLModel* model = instance.mModel; + + if (!model->mSkinWeights.empty()) + { + for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + + const LLVolumeFace& face = model->getVolumeFace(i); + + LLStrider position; + buffer->getVertexStrider(position); + + LLStrider weight; + buffer->getWeight4Strider(weight); + + //quick 'n dirty software vertex skinning + + //build matrix palette + LLMatrix4 mat[64]; + for (U32 j = 0; j < model->mJointList.size(); ++j) + { + LLJoint* joint = avatar->getJoint(model->mJointList[j]); + if (joint) + { + mat[j] = model->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } + + for (U32 j = 0; j < buffer->getRequestedVerts(); ++j) + { + LLMatrix4 final_mat; + final_mat.mMatrix[0][0] = final_mat.mMatrix[1][1] = final_mat.mMatrix[2][2] = final_mat.mMatrix[3][3] = 0.f; + + LLVector4 wght; + S32 idx[4]; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j].mV[k]; + + idx[k] = (S32) floorf(w); + wght.mV[k] = w - floorf(w); + scale += wght.mV[k]; + } + + wght *= 1.f/scale; + + for (U32 k = 0; k < 4; k++) + { + F32* src = (F32*) mat[idx[k]].mMatrix; + F32* dst = (F32*) final_mat.mMatrix; + + F32 w = wght.mV[k]; + + for (U32 l = 0; l < 16; l++) + { + dst[l] += src[l]*w; + } + } + + //VECTORIZE THIS + LLVector3 v(face.mPositions[j].getF32ptr()); + + v = v * model->mBindShapeMatrix; + v = v * final_mat; + + position[j] = v; + } + + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + glColor4fv(instance.mMaterial[i].mDiffuseColor.mV); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); + glColor3f(0.4f, 0.4f, 0.4f); + + if (mFMP->childGetValue("show edges").asBoolean()) + { + glLineWidth(3.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glLineWidth(1.f); + } + } + } + } + } + } + } + + gGL.popMatrix(); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// refresh() +//----------------------------------------------------------------------------- +void LLModelPreview::refresh() +{ + mNeedsUpdate = TRUE; +} + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLModelPreview::rotate(F32 yaw_radians, F32 pitch_radians) +{ + mCameraYaw = mCameraYaw + yaw_radians; + + mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); +} + +//----------------------------------------------------------------------------- +// zoom() +//----------------------------------------------------------------------------- +void LLModelPreview::zoom(F32 zoom_amt) +{ + F32 new_zoom = mCameraZoom+zoom_amt; + + mCameraZoom = llclamp(new_zoom, 1.f, 10.f); +} + +void LLModelPreview::pan(F32 right, F32 up) +{ + mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); +} + +void LLModelPreview::setPreviewLOD(S32 lod) +{ + mPreviewLOD = llclamp(lod, 0, 4); + refresh(); +} + +//static +void LLFloaterModelPreview::onBrowseHighLOD(void* data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; + mp->loadModel(3); +} + +//static +void LLFloaterModelPreview::onBrowseMediumLOD(void* data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; + mp->loadModel(2); +} + +//static +void LLFloaterModelPreview::onBrowseLowLOD(void* data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; + mp->loadModel(1); +} + +//static +void LLFloaterModelPreview::onBrowseLowestLOD(void* data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) data; + mp->loadModel(0); +} + +//static +void LLFloaterModelPreview::onUpload(void* user_data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; + + if (mp->mDecompFloater) + { + mp->mDecompFloater->closeFloater(); + } + + mp->mModelPreview->rebuildUploadData(); + + gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale, mp->childGetValue("upload_textures").asBoolean()); + + mp->closeFloater(false); +} + +//static +void LLFloaterModelPreview::onConsolidate(void* user_data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; + mp->mModelPreview->consolidate(); +} + +//static +void LLFloaterModelPreview::onScrubMaterials(void* user_data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; + mp->mModelPreview->scrubMaterials(); +} + +//static +void LLFloaterModelPreview::onDecompose(void* user_data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; + mp->showDecompFloater(); +} + +//static +void LLFloaterModelPreview::onModelDecompositionComplete(LLModel* model, std::vector >& physics_mesh) +{ + if (sInstance && sInstance->mModelPreview) + { + sInstance->mModelPreview->mPhysicsMesh[model] = physics_mesh; + + sInstance->mModelPreview->mResourceCost = sInstance->mModelPreview->calcResourceCost(); + } +} + + +//static +void LLFloaterModelPreview::refresh(LLUICtrl* ctrl, void* user_data) +{ + LLFloaterModelPreview* mp = (LLFloaterModelPreview*) user_data; + mp->mModelPreview->refresh(); +} + +void LLFloaterModelPreview::updateResourceCost() +{ + U32 cost = mModelPreview->mResourceCost; + childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",cost)); +} + +//static +void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ) +{ + LLModelPreview* preview = (LLModelPreview*) userdata; + preview->refresh(); +} + +#endif + diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h new file mode 100644 index 0000000000..1f9de2e2b9 --- /dev/null +++ b/indra/newview/llfloatermodelpreview.h @@ -0,0 +1,275 @@ +/** + * @file llfloatermodelpreview.h + * @brief LLFloaterModelPreview class definition + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERMODELPREVIEW_H +#define LL_LLFLOATERMODELPREVIEW_H + +#include "llfloaternamedesc.h" + +#include "lldynamictexture.h" +#include "llquaternion.h" +#include "llmeshrepository.h" +#include "llmodel.h" +#include "llthread.h" + +#if LL_MESH_ENABLED +class LLComboBox; +class LLJoint; +class LLViewerJointMesh; +class LLVOAvatar; +class LLTextBox; +class LLVertexBuffer; +class LLModelPreview; +class LLFloaterModelPreview; +class daeElement; +class domProfile_COMMON; +class domInstance_geometry; + +class LLPhysicsDecompFloater : public LLFloater +{ +public: + + LLPhysicsDecompFloater(LLSD& key); + ~LLPhysicsDecompFloater(); +}; + +class LLModelLoader : public LLThread +{ +public: + typedef enum + { + STARTING = 0, + READING_FILE, + CREATING_FACES, + GENERATING_VERTEX_BUFFERS, + GENERATING_LOD, + DONE, + } eLoadState; + + U32 mState; + std::string mFilename; + S32 mLod; + LLModelPreview* mPreview; + LLMatrix4 mTransform; + BOOL mFirstTransform; + LLVector3 mExtents[2]; + + std::map > mModel; + + typedef std::vector > model_list; + model_list mModelList; + + typedef std::vector model_instance_list; + + typedef std::map scene; + + scene mScene; + + LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview); + + virtual void run(); + + void processElement(daeElement* element); + std::vector getMaterials(LLModel* model, domInstance_geometry* instance_geo); + LLImportMaterial profileToMaterial(domProfile_COMMON* material); + std::string getElementLabel(daeElement *element); + LLColor4 getDaeColor(daeElement* element); + + //map of avatar joints as named in COLLADA assets to internal joint names + std::map mJointMap; +}; + +class LLModelPreview : public LLViewerDynamicTexture, public LLMutex +{ + public: + + LLModelPreview(S32 width, S32 height, LLFloaterModelPreview* fmp); + virtual ~LLModelPreview(); + + void setPreviewTarget(F32 distance); + void setTexture(U32 name) { mTextureName = name; } + + BOOL render(); + void genBuffers(S32 lod); + void refresh(); + void rotate(F32 yaw_radians, F32 pitch_radians); + void zoom(F32 zoom_amt); + void pan(F32 right, F32 up); + virtual BOOL needsRender() { return mNeedsUpdate; } + void setPreviewLOD(S32 lod); + void loadModel(std::string filename, S32 lod); + void loadModelCallback(S32 lod); + void genLODs(S32 which_lod = -1); + void smoothNormals(); + void consolidate(); + void scrubMaterials(); + U32 calcResourceCost(); + void rebuildUploadData(); + void clearIncompatible(S32 lod); + void updateStatusMessages(); + + static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); + + protected: + friend class LLFloaterModelPreview; + friend class LLPhysicsDecomp; + + LLFloaterModelPreview* mFMP; + + BOOL mNeedsUpdate; + U32 mTextureName; + F32 mCameraDistance; + F32 mCameraYaw; + F32 mCameraPitch; + F32 mCameraZoom; + LLVector3 mCameraOffset; + LLVector3 mPreviewTarget; + LLVector3 mPreviewScale; + S32 mPreviewLOD; + U32 mResourceCost; + S32 mLODMode[LLModel::NUM_LODS]; + S32 mLimit[LLModel::NUM_LODS]; + + LLModelLoader* mModelLoader; + + + LLModelLoader::scene mScene[LLModel::NUM_LODS]; + LLModelLoader::scene mBaseScene; + + LLModelLoader::model_list mModel[LLModel::NUM_LODS]; + LLModelLoader::model_list mBaseModel; + + std::map mGroup; + std::map mObject; + std::map > mPatch; + + std::map mPercentage; + std::map > > mPhysicsMesh; + + LLMeshUploadThread::instance_list mUploadData; + std::set > mTextureSet; + + //map of vertex buffers to models (one vertex buffer in vector per face in model + std::map > > mVertexBuffer[6]; +}; + +class LLFloaterModelPreview : public LLFloater +{ +public: + static LLFloaterModelPreview* sInstance; + + LLFloaterModelPreview(const LLSD& key); + virtual ~LLFloaterModelPreview(); + + virtual BOOL postBuild(); + + BOOL handleMouseDown(S32 x, S32 y, MASK mask); + BOOL handleMouseUp(S32 x, S32 y, MASK mask); + BOOL handleHover(S32 x, S32 y, MASK mask); + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + + static void onMouseCaptureLostModelPreview(LLMouseHandler*); + static void setUploadAmount(S32 amount) { sUploadAmount = amount; } + + static void onBrowseHighLOD(void* data); + static void onBrowseMediumLOD(void* data); + static void onBrowseLowLOD(void* data); + static void onBrowseLowestLOD(void* data); + + static void onUpload(void* data); + + static void onConsolidate(void* data); + static void onScrubMaterials(void* data); + static void onDecompose(void* data); + static void onModelDecompositionComplete(LLModel* model, std::vector >& physics_mesh); + + static void refresh(LLUICtrl* ctrl, void* data); + + void updateResourceCost(); + + void loadModel(S32 lod); + +protected: + friend class LLModelPreview; + friend class LLMeshFilePicker; + friend class LLPhysicsDecomp; + friend class LLPhysicsDecompFloater; + + static void onPreviewLODCommit(LLUICtrl*,void*); + + static void onHighLODCommit(LLUICtrl*,void*); + static void onMediumLODCommit(LLUICtrl*,void*); + static void onLowLODCommit(LLUICtrl*,void*); + static void onLowestLODCommit(LLUICtrl*,void*); + static void onPhysicsLODCommit(LLUICtrl*,void*); + + static void onHighLimitCommit(LLUICtrl*,void*); + static void onMediumLimitCommit(LLUICtrl*,void*); + static void onLowLimitCommit(LLUICtrl*,void*); + static void onLowestLimitCommit(LLUICtrl*,void*); + static void onPhysicsLimitCommit(LLUICtrl*,void*); + + static void onSmoothNormalsCommit(LLUICtrl*,void*); + + static void onAutoFillCommit(LLUICtrl*,void*); + static void onShowEdgesCommit(LLUICtrl*,void*); + + static void onExplodeCommit(LLUICtrl*, void*); + + static void onPhysicsParamCommit(LLUICtrl* ctrl, void* userdata); + static void onPhysicsStageExecute(LLUICtrl* ctrl, void* userdata); + static void onPhysicsStageCancel(LLUICtrl* ctrl, void* userdata); + static void onClosePhysicsFloater(LLUICtrl* ctrl, void* userdata); + + void draw(); + static void setLODMode(S32 lod, void* userdata); + void setLODMode(S32 lod, S32 which_mode); + + static void setLimit(S32 lod, void* userdata); + void setLimit(S32 lod, S32 limit); + + void showDecompFloater(); + + LLModelPreview* mModelPreview; + + LLFloater* mDecompFloater; + + S32 mLastMouseX; + S32 mLastMouseY; + LLRect mPreviewRect; + U32 mGLName; + BOOL mLoading; + static S32 sUploadAmount; +}; + +#endif + +#endif // LL_LLFLOATERMODELPREVIEW_H diff --git a/indra/newview/llmeshreduction.cpp b/indra/newview/llmeshreduction.cpp new file mode 100644 index 0000000000..e785784a32 --- /dev/null +++ b/indra/newview/llmeshreduction.cpp @@ -0,0 +1,291 @@ +/** + * @file llmeshreduction.cpp + * @brief LLMeshReduction class implementation + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmeshreduction.h" +#include "llgl.h" +#include "llvertexbuffer.h" + +#include "glod/glod.h" + +#if LL_MESH_ENABLED + +static BOOL stop_gloderror() +{ + GLuint error = glodGetError(); + + if (error != GLOD_NO_ERROR) + { + llwarns << "GLOD error detected: " << std::hex << error << llendl; + return TRUE; + } + + return FALSE; +} + + +void create_vertex_buffers_from_model(LLModel* model, std::vector >& vertex_buffers) +{ +#if 0 //VECTORIZE THIS ? + vertex_buffers.clear(); + + for (S32 i = 0; i < model->getNumVolumeFaces(); ++i) + { + const LLVolumeFace &vf = model->getVolumeFace(i); + U32 num_vertices = vf.mNumVertices; + U32 num_indices = vf.mNumIndices; + + if (!num_vertices || ! num_indices) + { + continue; + } + + LLVertexBuffer* vb = + new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0); + + vb->allocateBuffer(num_vertices, num_indices, TRUE); + + LLStrider vertex_strider; + LLStrider normal_strider; + LLStrider tc_strider; + LLStrider index_strider; + + vb->getVertexStrider(vertex_strider); + vb->getNormalStrider(normal_strider); + vb->getTexCoord0Strider(tc_strider); + + vb->getIndexStrider(index_strider); + + // build vertices and normals + for (U32 i = 0; (S32)i < num_vertices; i++) + { + *(vertex_strider++) = vf.mVertices[i].mPosition; + *(tc_strider++) = vf.mVertices[i].mTexCoord; + LLVector3 normal = vf.mVertices[i].mNormal; + normal.normalize(); + *(normal_strider++) = normal; + } + + // build indices + for (U32 i = 0; i < num_indices; i++) + { + *(index_strider++) = vf.mIndices[i]; + } + + + vertex_buffers.push_back(vb); + } +#endif +} + +void create_glod_object_from_vertex_buffers(S32 object, S32 group, std::vector >& vertex_buffers) +{ + glodNewGroup(group); + stop_gloderror(); + glodNewObject(object, group, GLOD_DISCRETE); + stop_gloderror(); + + for (U32 i = 0; i < vertex_buffers.size(); ++i) + { + vertex_buffers[i]->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + + U32 num_indices = vertex_buffers[i]->getNumIndices(); + + if (num_indices > 2) + { + glodInsertElements(object, i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, + vertex_buffers[i]->getIndicesPointer(), 0, 0.f); + } + stop_gloderror(); + } + + glodBuildObject(object); + stop_gloderror(); +} + +// extract the GLOD data into vertex buffers +void create_vertex_buffers_from_glod_object(S32 object, S32 group, std::vector >& vertex_buffers) +{ + vertex_buffers.clear(); + + GLint patch_count = 0; + glodGetObjectParameteriv(object, GLOD_NUM_PATCHES, &patch_count); + stop_gloderror(); + + GLint* sizes = new GLint[patch_count*2]; + glodGetObjectParameteriv(object, GLOD_PATCH_SIZES, sizes); + stop_gloderror(); + + GLint* names = new GLint[patch_count]; + glodGetObjectParameteriv(object, GLOD_PATCH_NAMES, names); + stop_gloderror(); + + for (S32 i = 0; i < patch_count; i++) + { + LLPointer buff = + new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0, 0); + + if (sizes[i*2+1] > 0 && sizes[i*2] > 0) + { + buff->allocateBuffer(sizes[i*2+1], sizes[i*2], true); + buff->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + glodFillElements(object, names[i], GL_UNSIGNED_SHORT, buff->getIndicesPointer()); + stop_gloderror(); + } + else + { + // this face was eliminated, create a dummy triangle (one vertex, 3 indices, all 0) + buff->allocateBuffer(1, 3, true); + } + + vertex_buffers.push_back(buff); + } + + glodDeleteObject(object); + stop_gloderror(); + glodDeleteGroup(group); + stop_gloderror(); + + delete [] sizes; + delete [] names; +} + + +LLPointer create_model_from_vertex_buffers(std::vector >& vertex_buffers) +{ + // extract the newly reduced mesh + + // create our output model + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLPointer out_model = new LLModel(volume_params, 0.f); + + out_model->setNumVolumeFaces(vertex_buffers.size()); + + // build new faces from each vertex buffer + for (GLint i = 0; i < vertex_buffers.size(); ++i) + { + LLStrider pos; + LLStrider norm; + LLStrider tc; + LLStrider index; + + vertex_buffers[i]->getVertexStrider(pos); + vertex_buffers[i]->getNormalStrider(norm); + vertex_buffers[i]->getTexCoord0Strider(tc); + vertex_buffers[i]->getIndexStrider(index); + + out_model->setVolumeFaceData(i, pos, norm, tc, index, + vertex_buffers[i]->getNumVerts(), vertex_buffers[i]->getNumIndices()); + } + + return out_model; +} + + + +LLMeshReduction::LLMeshReduction() +{ + mCounter = 1; + + glodInit(); +} + +LLMeshReduction::~LLMeshReduction() +{ + glodShutdown(); +} + + +LLPointer LLMeshReduction::reduce(LLModel* in_model, F32 limit, S32 mode) +{ + LLVertexBuffer::unbind(); + + // create vertex buffers from model + std::vector > in_vertex_buffers; + create_vertex_buffers_from_model(in_model, in_vertex_buffers); + + // create glod object from vertex buffers + stop_gloderror(); + S32 glod_group = mCounter++; + S32 glod_object = mCounter++; + create_glod_object_from_vertex_buffers(glod_object, glod_group, in_vertex_buffers); + + + // set reduction parameters + stop_gloderror(); + + if (mode == TRIANGLE_BUDGET) + { + // triangle budget mode + glodGroupParameteri(glod_group, GLOD_ADAPT_MODE, GLOD_TRIANGLE_BUDGET); + stop_gloderror(); + glodGroupParameteri(glod_group, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR); + stop_gloderror(); + S32 triangle_count = (S32)limit; + glodGroupParameteri(glod_group, GLOD_MAX_TRIANGLES, triangle_count); + stop_gloderror(); + } + else if (mode == ERROR_THRESHOLD) + { + // error threshold mode + glodGroupParameteri(glod_group, GLOD_ADAPT_MODE, GLOD_ERROR_THRESHOLD); + glodGroupParameteri(glod_group, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR); + F32 error_threshold = limit; + glodGroupParameterf(glod_group, GLOD_OBJECT_SPACE_ERROR_THRESHOLD, error_threshold); + stop_gloderror(); + } + + else + { + // not a legal mode + return NULL; + } + + + // do the reduction + glodAdaptGroup(glod_group); + stop_gloderror(); + + // convert glod object into vertex buffers + std::vector > out_vertex_buffers; + create_vertex_buffers_from_glod_object(glod_object, glod_group, out_vertex_buffers); + + // convert vertex buffers into a model + LLPointer out_model = create_model_from_vertex_buffers(out_vertex_buffers); + + + return out_model; +} + +#endif + diff --git a/indra/newview/llmeshreduction.h b/indra/newview/llmeshreduction.h new file mode 100644 index 0000000000..d86696978d --- /dev/null +++ b/indra/newview/llmeshreduction.h @@ -0,0 +1,59 @@ +/** + * @file llmeshreduction.h + * @brief LLMeshReduction class definition + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLMESHREDUCTION_H +#define LL_LLMESHREDUCTION_H + +#include "llmodel.h" + +#if LL_MESH_ENABLED + +class LLMeshReduction +{ + public: + enum EReductionMode + { + TRIANGLE_BUDGET, + ERROR_THRESHOLD + }; + + LLMeshReduction(); + ~LLMeshReduction(); + + LLPointer reduce(LLModel* in_model, F32 limit, S32 mode); + +private: + U32 mCounter; +}; + +#endif + +#endif // LL_LLMESHREDUCTION_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp new file mode 100644 index 0000000000..96a170ef07 --- /dev/null +++ b/indra/newview/llmeshrepository.cpp @@ -0,0 +1,2676 @@ +/** + * @file llmeshrepository.cpp + * @brief Mesh repository implementation. + * + * $LicenseInfo:firstyear=2005&license=viewergpl$ + * + * Copyright (c) 2005-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "apr_pools.h" +#include "apr_dso.h" + +#include "llmeshrepository.h" + +#include "llagent.h" +#include "llappviewer.h" +#include "llbufferstream.h" +#include "llcurl.h" +#include "llfasttimer.h" +#include "llfloatermodelpreview.h" +#include "llfloaterperms.h" +#include "lleconomy.h" +#include "llimagej2c.h" +#include "llhost.h" +#include "llnotificationsutil.h" +#include "llsd.h" +#include "llsdutil_math.h" +#include "llsdserialize.h" +#include "llthread.h" +#include "llvfile.h" +#include "llviewercontrol.h" +#include "llviewermenufile.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewertexturelist.h" +#include "llvolume.h" +#include "llvolumemgr.h" +#include "llvovolume.h" +#include "llworld.h" +#include "material_codes.h" +#include "pipeline.h" + + +#include + +#if LL_MESH_ENABLED + +LLFastTimer::DeclareTimer FTM_MESH_UPDATE("Mesh Update"); +LLFastTimer::DeclareTimer FTM_LOAD_MESH("Load Mesh"); + +LLMeshRepository gMeshRepo; + +const U32 MAX_MESH_REQUESTS_PER_SECOND = 100; + +U32 LLMeshRepository::sBytesReceived = 0; +U32 LLMeshRepository::sHTTPRequestCount = 0; +U32 LLMeshRepository::sHTTPRetryCount = 0; +U32 LLMeshRepository::sCacheBytesRead = 0; +U32 LLMeshRepository::sCacheBytesWritten = 0; +U32 LLMeshRepository::sPeakKbps = 0; + + +std::string header_lod[] = +{ + "lowest_lod", + "low_lod", + "medium_lod", + "high_lod" +}; + + +//get the number of bytes resident in memory for given volume +U32 get_volume_memory_size(const LLVolume* volume) +{ + U32 indices = 0; + U32 vertices = 0; + + for (U32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + indices += face.mNumIndices; + vertices += face.mNumVertices; + } + + + return indices*2+vertices*11+sizeof(LLVolume)+sizeof(LLVolumeFace)*volume->getNumVolumeFaces(); +} + +std::string scrub_host_name(std::string http_url, const LLHost& host) +{ //curl loves to abuse the DNS cache, so scrub host names out of urls where trivial to prevent DNS timeouts + std::string ip_string = host.getIPString(); + std::string host_string = host.getHostName(); + + std::string::size_type idx = http_url.find(host_string); + + if (!ip_string.empty() && !host_string.empty() && idx != std::string::npos) + { + http_url.replace(idx, host_string.length(), ip_string); + } + + return http_url; +} + +LLVertexBuffer* get_vertex_buffer_from_mesh(LLCDMeshData& mesh, F32 scale = 1.f) +{ + LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0); + buff->allocateBuffer(mesh.mNumTriangles*3, 0, true); + + LLStrider pos; + LLStrider norm; + + buff->getVertexStrider(pos); + buff->getNormalStrider(norm); + + const F32* v = mesh.mVertexBase; + + if (mesh.mIndexType == LLCDMeshData::INT_16) + { + U16* idx = (U16*) mesh.mIndexBase; + for (S32 j = 0; j < mesh.mNumTriangles; ++j) + { + F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes); + F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes); + F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes); + + idx = (U16*) (((U8*)idx)+mesh.mIndexStrideBytes); + + LLVector3 v0(mp0); + LLVector3 v1(mp1); + LLVector3 v2(mp2); + + LLVector3 n = (v1-v0)%(v2-v0); + n.normalize(); + + *pos++ = v0*scale; + *pos++ = v1*scale; + *pos++ = v2*scale; + + *norm++ = n; + *norm++ = n; + *norm++ = n; + } + } + else + { + U32* idx = (U32*) mesh.mIndexBase; + for (S32 j = 0; j < mesh.mNumTriangles; ++j) + { + F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes); + F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes); + F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes); + + idx = (U32*) (((U8*)idx)+mesh.mIndexStrideBytes); + + LLVector3 v0(mp0); + LLVector3 v1(mp1); + LLVector3 v2(mp2); + + LLVector3 n = (v1-v0)%(v2-v0); + n.normalize(); + + *(pos++) = v0*scale; + *(pos++) = v1*scale; + *(pos++) = v2*scale; + + *(norm++) = n; + *(norm++) = n; + *(norm++) = n; + } + } + + return buff; +} + +S32 LLMeshRepoThread::sActiveHeaderRequests = 0; +S32 LLMeshRepoThread::sActiveLODRequests = 0; +U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; + + +class LLTextureCostResponder : public LLCurl::Responder +{ +public: + LLTextureUploadData mData; + LLMeshUploadThread* mThread; + + LLTextureCostResponder(LLTextureUploadData data, LLMeshUploadThread* thread) + : mData(data), mThread(thread) + { + + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + mThread->mPendingConfirmations--; + if (isGoodStatus(status)) + { + mThread->priceResult(mData, content); + } + else + { + llwarns << status << ": " << reason << llendl; + llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; + + if (status == 499) + { + mThread->uploadTexture(mData); + } + else + { + llerrs << "Unhandled status " << status << llendl; + } + } + } +}; + +class LLTextureUploadResponder : public LLCurl::Responder +{ +public: + LLTextureUploadData mData; + LLMeshUploadThread* mThread; + + LLTextureUploadResponder(LLTextureUploadData data, LLMeshUploadThread* thread) + : mData(data), mThread(thread) + { + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + mThread->mPendingUploads--; + if (isGoodStatus(status)) + { + mData.mUUID = content["new_asset"].asUUID(); + gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content)); + mThread->onTextureUploaded(mData); + } + else + { + llwarns << status << ": " << reason << llendl; + llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; + + if (status == 404) + { + mThread->uploadTexture(mData); + } + else if (status == 499) + { + mThread->mConfirmedTextureQ.push(mData); + } + else + { + llerrs << "Unhandled status " << status << llendl; + } + } + } +}; + +class LLMeshCostResponder : public LLCurl::Responder +{ +public: + LLMeshUploadData mData; + LLMeshUploadThread* mThread; + + LLMeshCostResponder(LLMeshUploadData data, LLMeshUploadThread* thread) + : mData(data), mThread(thread) + { + + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + mThread->mPendingConfirmations--; + + if (isGoodStatus(status)) + { + mThread->priceResult(mData, content); + } + else + { + llwarns << status << ": " << reason << llendl; + llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; + + if (status == 499) + { + mThread->uploadModel(mData); + } + else if (status == 400) + { + llwarns << "Status 400 received from server, giving up." << llendl; + } + else + { + llerrs << "Unhandled status " << status << llendl; + } + } + } +}; + +class LLMeshUploadResponder : public LLCurl::Responder +{ +public: + LLMeshUploadData mData; + LLMeshUploadThread* mThread; + + LLMeshUploadResponder(LLMeshUploadData data, LLMeshUploadThread* thread) + : mData(data), mThread(thread) + { + } + + virtual void completed(U32 status, const std::string& reason, const LLSD& content) + { + mThread->mPendingUploads--; + if (isGoodStatus(status)) + { + mData.mUUID = content["new_asset"].asUUID(); + if (mData.mUUID.isNull()) + { + LLSD args; + std::string message = content["error"]["message"]; + std::string identifier = content["error"]["identifier"]; + std::string invalidity_identifier = content["error"]["invalidity_identifier"]; + + args["MESSAGE"] = message; + args["IDENTIFIER"] = identifier; + args["INVALIDITY_IDENTIFIER"] = invalidity_identifier; + args["LABEL"] = mData.mBaseModel->mLabel; + + gMeshRepo.uploadError(args); + } + else + { + gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content)); + mThread->onModelUploaded(mData); + } + } + else + { + llwarns << status << ": " << reason << llendl; + llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl; + + if (status == 404) + { + mThread->uploadModel(mData); + } + else if (status == 499) + { + mThread->mConfirmedQ.push(mData); + } + else if (status != 500) + { //drop internal server errors on the floor, otherwise grab + llerrs << "Unhandled status " << status << llendl; + } + } + } +}; + + +class LLMeshHeaderResponder : public LLCurl::Responder +{ +public: + LLVolumeParams mMeshParams; + + LLMeshHeaderResponder(const LLVolumeParams& mesh_params) + : mMeshParams(mesh_params) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshLODResponder : public LLCurl::Responder +{ +public: + LLVolumeParams mMeshParams; + S32 mLOD; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) + : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshSkinInfoResponder : public LLCurl::Responder +{ +public: + LLUUID mMeshID; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size) + : mMeshID(id), mRequestedBytes(size), mOffset(offset) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshDecompositionResponder : public LLCurl::Responder +{ +public: + LLUUID mMeshID; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size) + : mMeshID(id), mRequestedBytes(size), mOffset(offset) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + + +LLMeshRepoThread::LLMeshRepoThread() +: LLThread("mesh repo", NULL) +{ + mWaiting = false; + mMutex = new LLMutex(NULL); + mHeaderMutex = new LLMutex(NULL); + mSignal = new LLCondition(NULL); +} + +LLMeshRepoThread::~LLMeshRepoThread() +{ + +} + +void LLMeshRepoThread::run() +{ + mCurlRequest = new LLCurlRequest(); + LLCDResult res = LLConvexDecomposition::initThread(); + if (res != LLCD_OK) + { + llwarns << "convex decomposition unable to be loaded" << llendl; + } + + while (!LLApp::isQuitting()) + { + mWaiting = true; + mSignal->wait(); + mWaiting = false; + + if (!LLApp::isQuitting()) + { + static U32 count = 0; + + static F32 last_hundred = gFrameTimeSeconds; + + if (gFrameTimeSeconds - last_hundred > 1.f) + { //a second has gone by, clear count + last_hundred = gFrameTimeSeconds; + count = 0; + } + + // NOTE: throttling intentionally favors LOD requests over header requests + + while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests) + { + { + LLMutexLock lock(mMutex); + LODRequest req = mLODReqQ.front(); + mLODReqQ.pop(); + if (fetchMeshLOD(req.mMeshParams, req.mLOD)) + { + count++; + } + } + } + + while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests) + { + { + LLMutexLock lock(mMutex); + HeaderRequest req = mHeaderReqQ.front(); + mHeaderReqQ.pop(); + if (fetchMeshHeader(req.mMeshParams)) + { + count++; + } + } + } + + { + std::set incomplete; + for (std::set::iterator iter = mSkinRequests.begin(); iter != mSkinRequests.end(); ++iter) + { + LLUUID mesh_id = *iter; + if (!fetchMeshSkinInfo(mesh_id)) + { + incomplete.insert(mesh_id); + } + } + mSkinRequests = incomplete; + } + + { + std::set incomplete; + for (std::set::iterator iter = mDecompositionRequests.begin(); iter != mDecompositionRequests.end(); ++iter) + { + LLUUID mesh_id = *iter; + if (!fetchMeshDecomposition(mesh_id)) + { + incomplete.insert(mesh_id); + } + } + mDecompositionRequests = incomplete; + } + + + } + + mCurlRequest->process(); + } + + res = LLConvexDecomposition::quitThread(); + if (res != LLCD_OK) + { + llwarns << "convex decomposition unable to be quit" << llendl; + } + + delete mCurlRequest; + delete mMutex; +} + +void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here + mSkinRequests.insert(mesh_id); +} + +void LLMeshRepoThread::loadMeshDecomposition(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here + mDecompositionRequests.insert(mesh_id); +} + +void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //protected by mSignal, no locking needed here + + mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + if (iter != mMeshHeader.end()) + { //if we have the header, request LOD byte range + LODRequest req(mesh_params, lod); + mLODReqQ.push(req); + } + else + { + HeaderRequest req(mesh_params); + + pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); + + if (pending != mPendingLOD.end()) + { //append this lod request to existing header request + pending->second.push_back(lod); + if (pending->second.size() > 4) + { + llerrs << "WTF?" << llendl; + } + } + else + { //if no header request is pending, fetch header + mHeaderReqQ.push(req); + mPendingLOD[mesh_params].push_back(lod); + } + } +} + +//static +std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id) +{ + std::string http_url; + + if (gAgent.getRegion()) + { + http_url = gAgent.getRegion()->getCapability("GetMesh"); + scrub_host_name(http_url, gAgent.getRegionHost()); + } + + if (!http_url.empty()) + { + http_url += "/?mesh_id="; + http_url += mesh_id.asString().c_str(); + } + else + { + llwarns << "Current region does not have GetMesh capability! Cannot load " << mesh_id << ".mesh" << llendl; + } + + return http_url; +} + +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +{ //protected by mMutex + mHeaderMutex->lock(); + + if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + U32 header_size = mMeshHeaderSize[mesh_id]; + + if (header_size > 0) + { + S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger(); + S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger(); + + mHeaderMutex->unlock(); + + if (offset >= 0 && size > 0) + { + //check VFS for mesh skin info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (skinInfoReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + new LLMeshSkinInfoResponder(mesh_id, offset, size)); + } + } + } + else + { + mHeaderMutex->unlock(); + } + + //early out was not hit, effectively fetched + return true; +} + +bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) +{ //protected by mMutex + mHeaderMutex->lock(); + + if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + U32 header_size = mMeshHeaderSize[mesh_id]; + + if (header_size > 0) + { + S32 offset = header_size + mMeshHeader[mesh_id]["decomposition"]["offset"].asInteger(); + S32 size = mMeshHeader[mesh_id]["decomposition"]["size"].asInteger(); + + mHeaderMutex->unlock(); + + if (offset >= 0 && size > 0) + { + //check VFS for mesh skin info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (decompositionReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + new LLMeshDecompositionResponder(mesh_id, offset, size)); + } + } + } + else + { + mHeaderMutex->unlock(); + } + + //early out was not hit, effectively fetched + return true; +} + +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +{ + bool retval = false; + + { + //look for mesh in asset in vfs + LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); + + S32 size = file.getSize(); + + if (size > 0) + { + U8 buffer[1024]; + S32 bytes = llmin(size, 1024); + LLMeshRepository::sCacheBytesRead += bytes; + file.read(buffer, bytes); + if (headerReceived(mesh_params, buffer, bytes)) + { //did not do an HTTP request, return false + return false; + } + } + } + + //either cache entry doesn't exist or is corrupt, request header from simulator + + std::vector headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_params.getSculptID()); + if (!http_url.empty()) + { + ++sActiveHeaderRequests; + retval = true; + //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits + //within the first 4KB + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + } + + return retval; +} + +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //protected by mMutex + mHeaderMutex->lock(); + + bool retval = false; + + LLUUID mesh_id = mesh_params.getSculptID(); + + U32 header_size = mMeshHeaderSize[mesh_id]; + + if (header_size > 0) + { + S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger(); + S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger(); + mHeaderMutex->unlock(); + if (offset >= 0 && size > 0) + { + + //check VFS for mesh asset + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (lodReceived(mesh_params, lod, buffer, size)) + { + delete[] buffer; + return false; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + retval = true; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + new LLMeshLODResponder(mesh_params, lod, offset, size)); + } + else + { + mUnavailableQ.push(LODRequest(mesh_params, lod)); + } + } + else + { + mUnavailableQ.push(LODRequest(mesh_params, lod)); + } + } + else + { + mHeaderMutex->unlock(); + } + + return retval; +} + +bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size) +{ + LLSD header; + + U32 header_size = 0; + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::istringstream stream(res_str); + + if (!LLSDSerialize::deserialize(header, stream, data_size)) + { + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; + return false; + } + + header_size = stream.tellg(); + } + else + { + header["404"] = 1; + } + + { + U32 cost = gMeshRepo.calcResourceCost(header); + + LLUUID mesh_id = mesh_params.getSculptID(); + + mHeaderMutex->lock(); + mMeshHeaderSize[mesh_id] = header_size; + mMeshHeader[mesh_id] = header; + mMeshResourceCost[mesh_id] = cost; + mHeaderMutex->unlock(); + + //check for pending requests + pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); + if (iter != mPendingLOD.end()) + { + for (U32 i = 0; i < iter->second.size(); ++i) + { + LODRequest req(mesh_params, iter->second[i]); + mLODReqQ.push(req); + } + } + mPendingLOD.erase(iter); + } + + return true; +} + +bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size) +{ + LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); + std::string mesh_string((char*) data, data_size); + std::istringstream stream(mesh_string); + + if (volume->unpackVolumeFaces(stream, data_size)) + { + LoadedMesh mesh(volume, mesh_params, lod); + if (volume->getNumFaces() > 0) + { + LLMutexLock lock(mMutex); + mLoadedQ.push(mesh); + return true; + } + } + + return false; +} + +bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ + LLSD skin; + + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::istringstream stream(res_str); + + if (!unzip_llsd(skin, stream, data_size)) + { + llwarns << "Mesh skin info parse error. Not a valid mesh asset!" << llendl; + return false; + } + } + + { + LLMeshSkinInfo info; + info.mMeshID = mesh_id; + + if (skin.has("joint_names")) + { + for (U32 i = 0; i < skin["joint_names"].size(); ++i) + { + info.mJointNames.push_back(skin["joint_names"][i]); + } + } + + if (skin.has("inverse_bind_matrix")) + { + for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i) + { + LLMatrix4 mat; + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal(); + } + } + + info.mInvBindMatrix.push_back(mat); + } + } + + if (skin.has("bind_shape_matrix")) + { + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + info.mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal(); + } + } + } + + mSkinInfoQ.push(info); + } + + return true; +} + +bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ + LLSD decomp; + + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::istringstream stream(res_str); + + if (!unzip_llsd(decomp, stream, data_size)) + { + llwarns << "Mesh decomposition parse error. Not a valid mesh asset!" << llendl; + return false; + } + } + + { + LLMeshDecomposition* d = new LLMeshDecomposition(); + d->mMeshID = mesh_id; + + // updated for const-correctness. gcc is picky about this type of thing - Nyx + const LLSD::Binary& hulls = decomp["HullList"].asBinary(); + const LLSD::Binary& position = decomp["Position"].asBinary(); + + U16* p = (U16*) &position[0]; + + d->mHull.resize(hulls.size()); + + LLVector3 min; + LLVector3 max; + LLVector3 range; + + min.setValue(decomp["Min"]); + max.setValue(decomp["Max"]); + range = max-min; + + for (U32 i = 0; i < hulls.size(); ++i) + { + U8 count = hulls[i]; + + for (U32 j = 0; j < count; ++j) + { + d->mHull[i].push_back(LLVector3( + (F32) p[0]/65535.f*range.mV[0]+min.mV[0], + (F32) p[1]/65535.f*range.mV[1]+min.mV[1], + (F32) p[2]/65535.f*range.mV[2]+min.mV[2])); + p += 3; + } + + } + + //get mesh for decomposition + for (U32 i = 0; i < d->mHull.size(); ++i) + { + LLCDHull hull; + hull.mNumVertices = d->mHull[i].size(); + hull.mVertexBase = d->mHull[i][0].mV; + hull.mVertexStrideBytes = 12; + + LLCDMeshData mesh; + LLCDResult res = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh); + } + if (res != LLCD_OK) + { + llwarns << "could not get mesh from hull from convex decomposition lib." << llendl; + return false; + } + + + d->mMesh.push_back(get_vertex_buffer_from_mesh(mesh)); + } + + mDecompositionQ.push(d); + } + + return true; +} + +LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures) +: LLThread("mesh upload") +{ + mInstanceList = data; + mUploadTextures = upload_textures; + mMutex = new LLMutex(NULL); + mCurlRequest = NULL; + mPendingConfirmations = 0; + mPendingUploads = 0; + mPendingCost = 0; + mFinished = false; + mOrigin = gAgent.getPositionAgent(); + mHost = gAgent.getRegionHost(); + mUploadObjectAssetCapability = gAgent.getRegion()->getCapability("UploadObjectAsset"); + mNewInventoryCapability = gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice"); + + mOrigin += gAgent.getAtAxis() * scale.magVec(); + + scrub_host_name(mUploadObjectAssetCapability, mHost); + scrub_host_name(mNewInventoryCapability, mHost); +} + +LLMeshUploadThread::~LLMeshUploadThread() +{ + +} + +void LLMeshUploadThread::run() +{ + mCurlRequest = new LLCurlRequest(); + + //build map of LLModel refs to instances for callbacks + for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter) + { + mInstance[iter->mModel].push_back(*iter); + } + + std::set > textures; + + //populate upload queue with relevant models + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + LLModelInstance& instance = *(iter->second.begin()); + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + uploadModel(data); + + if (mUploadTextures) + { + for (std::vector::iterator material_iter = instance.mMaterial.begin(); + material_iter != instance.mMaterial.end(); ++material_iter) + { + + if (textures.find(material_iter->mDiffuseMap) == textures.end()) + { + textures.insert(material_iter->mDiffuseMap); + + LLTextureUploadData data(material_iter->mDiffuseMap, material_iter->mDiffuseMapLabel); + uploadTexture(data); + } + } + } + } + + + //upload textures + bool done = false; + do + { + if (!mTextureQ.empty()) + { + sendCostRequest(mTextureQ.front()); + mTextureQ.pop(); + } + + if (!mConfirmedTextureQ.empty()) + { + doUploadTexture(mConfirmedTextureQ.front()); + mConfirmedTextureQ.pop(); + } + + mCurlRequest->process(); + + done = mTextureQ.empty() && mConfirmedTextureQ.empty(); + } + while (!done || mCurlRequest->getQueued() > 0); + + LLSD object_asset; + object_asset["objects"] = LLSD::emptyArray(); + + done = false; + do + { + static S32 count = 0; + static F32 last_hundred = gFrameTimeSeconds; + if (gFrameTimeSeconds - last_hundred > 1.f) + { + last_hundred = gFrameTimeSeconds; + count = 0; + } + + //how many requests to push before calling process + const S32 PUSH_PER_PROCESS = 32; + + S32 tcount = llmin(count+PUSH_PER_PROCESS, 100); + + while (!mUploadQ.empty() && count < tcount) + { //send any pending upload requests + mMutex->lock(); + LLMeshUploadData data = mUploadQ.front(); + mUploadQ.pop(); + mMutex->unlock(); + sendCostRequest(data); + count++; + } + + tcount = llmin(count+PUSH_PER_PROCESS, 100); + + while (!mConfirmedQ.empty() && count < tcount) + { //process any meshes that have been confirmed for upload + LLMeshUploadData& data = mConfirmedQ.front(); + doUploadModel(data); + mConfirmedQ.pop(); + count++; + } + + tcount = llmin(count+PUSH_PER_PROCESS, 100); + + while (!mInstanceQ.empty() && count < tcount) + { //create any objects waiting for upload + count++; + object_asset["objects"].append(createObject(mInstanceQ.front())); + mInstanceQ.pop(); + } + + mCurlRequest->process(); + + done = mInstanceQ.empty() && mConfirmedQ.empty() && mUploadQ.empty(); + } + while (!done || mCurlRequest->getQueued() > 0); + + delete mCurlRequest; + mCurlRequest = NULL; + + // now upload the object asset + std::string url = mUploadObjectAssetCapability; + LLHTTPClient::post(url, object_asset, new LLHTTPClient::Responder()); + + mFinished = true; +} + +void LLMeshUploadThread::uploadModel(LLMeshUploadData& data) +{ //called from arbitrary thread + { + LLMutexLock lock(mMutex); + mUploadQ.push(data); + } +} + +void LLMeshUploadThread::uploadTexture(LLTextureUploadData& data) +{ //called from mesh upload thread + mTextureQ.push(data); +} + + +static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_LOADED("Notify Loaded"); +static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_UNAVAILABLE("Notify Unavailable"); + +void LLMeshRepoThread::notifyLoadedMeshes() +{ + while (!mLoadedQ.empty()) + { + mMutex->lock(); + LoadedMesh mesh = mLoadedQ.front(); + mLoadedQ.pop(); + mMutex->unlock(); + + if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0) + { + gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); + } + else + { + gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, + LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + } + } + + while (!mUnavailableQ.empty()) + { + mMutex->lock(); + LODRequest req = mUnavailableQ.front(); + mUnavailableQ.pop(); + mMutex->unlock(); + + gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + } + + while (!mSkinInfoQ.empty()) + { + gMeshRepo.notifySkinInfoReceived(mSkinInfoQ.front()); + mSkinInfoQ.pop(); + } + + while (!mDecompositionQ.empty()) + { + gMeshRepo.notifyDecompositionReceived(mDecompositionQ.front()); + mDecompositionQ.pop(); + } +} + +S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //only ever called from main thread + lod = llclamp(lod, 0, 3); + + LLMutexLock lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + + if (iter != mMeshHeader.end()) + { + LLSD& header = iter->second; + + if (header.has("404")) + { + return -1; + } + + if (header[header_lod[lod]]["size"].asInteger() > 0) + { + return lod; + } + + //search down to find the next available lower lod + for (S32 i = lod-1; i >= 0; --i) + { + if (header[header_lod[i]]["size"].asInteger() > 0) + { + return i; + } + } + + //search up to find then ext available higher lod + for (S32 i = lod+1; i < 4; ++i) + { + if (header[header_lod[i]]["size"].asInteger() > 0) + { + return i; + } + } + + //header exists and no good lod found, treat as 404 + header["404"] = 1; + return -1; + } + + return lod; +} + +U32 LLMeshRepoThread::getResourceCost(const LLUUID& mesh_id) +{ + LLMutexLock lock(mHeaderMutex); + + std::map::iterator iter = mMeshResourceCost.find(mesh_id); + if (iter != mMeshResourceCost.end()) + { + return iter->second; + } + + return 0; +} + +void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) +{ + mThread->mMeshHeader[data.mUUID] = header; + + // we cache the mesh for default parameters + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(data.mUUID, LL_SCULPT_TYPE_MESH); + + for (U32 i = 0; i < 4; i++) + { + if (data.mModel[i].notNull()) + { + LLPointer volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i)); + volume->copyVolumeFaces(data.mModel[i]); + } + } + +} + +void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + + LLMeshRepoThread::sActiveLODRequests--; + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + file.seek(offset); + file.write(data, size); + LLMeshRepository::sCacheBytesWritten += size; + } + } + + delete [] data; +} + +void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesWritten += size; + file.seek(offset); + file.write(data, size); + } + } + + delete [] data; +} + +void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshDecomposition(mMeshID); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesWritten += size; + file.seek(offset); + file.write(data, size); + } + } + + delete [] data; +} + +void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + LLMeshRepoThread::sActiveHeaderRequests--; + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + S32 data_size = buffer->countAfter(channels.in(), NULL); + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + LLMeshRepository::sBytesReceived += llmin(data_size, 4096); + + if (!gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size)) + { + llwarns << "Header responder failed with status: " << status << ": " << reason << llendl; + if (status == 503 || status == 499) + { //retry + LLMeshRepository::sHTTPRetryCount++; + LLMeshRepoThread::HeaderRequest req(mMeshParams); + gMeshRepo.mThread->mHeaderReqQ.push(req); + } + } + else if (data && data_size > 0) + { + //header was successfully retrieved from sim, cache in vfs + LLUUID mesh_id = mMeshParams.getSculptID(); + LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; + + std::stringstream str; + + S32 lod_bytes = 0; + + for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) + { //figure out how many bytes we'll need to reserve in the file + std::string lod_name = header_lod[i]; + lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); + } + + //just in case skin info or decomposition is at the end of the file (which it shouldn't be) + lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); + lod_bytes = llmax(lod_bytes, header["decomposition"]["offset"].asInteger() + header["decomposition"]["size"].asInteger()); + + S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; + S32 bytes = lod_bytes + header_bytes; + + + //it's possible for the remote asset to have more data than is needed for the local cache + //only allocate as much space in the VFS as is needed for the local cache + data_size = llmin(data_size, bytes); + + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); + if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) + { + LLMeshRepository::sCacheBytesWritten += data_size; + + file.write((const U8*) data, data_size); + + //zero out the rest of the file + U8 block[4096]; + memset(block, 0, 4096); + + while (bytes-file.tell() > 4096) + { + file.write(block, 4096); + } + + S32 remaining = bytes-file.tell(); + + if (remaining < 0 || remaining > 4096) + { + llerrs << "Bad padding of mesh asset cache entry." << llendl; + } + + if (remaining > 0) + { + file.write(block, remaining); + } + } + } + + delete [] data; +} + + +LLMeshRepository::LLMeshRepository() +: mMeshMutex(NULL), + mMeshThreadCount(0), + mThread(NULL) +{ + +} + +void LLMeshRepository::init() +{ + mMeshMutex = new LLMutex(NULL); + + mDecompThread = new LLPhysicsDecomp(); + mDecompThread->start(); + + while (!mDecompThread->mInited) + { //wait for physics decomp thread to init + apr_sleep(100); + } + + mThread = new LLMeshRepoThread(); + mThread->start(); +} + +void LLMeshRepository::shutdown() +{ + mThread->mSignal->signal(); + + delete mThread; + mThread = NULL; + + for (U32 i = 0; i < mUploads.size(); ++i) + { + delete mUploads[i]; + } + + mUploads.clear(); + + delete mMeshMutex; + mMeshMutex = NULL; + + if (mDecompThread) + { + mDecompThread->shutdown(); + delete mDecompThread; + mDecompThread = NULL; + } +} + + +S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail) +{ + if (detail < 0 || detail > 4) + { + return detail; + } + + LLFastTimer t(FTM_LOAD_MESH); + + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); + if (iter != mLoadingMeshes[detail].end()) + { //request pending for this mesh, append volume id to list + iter->second.insert(vobj->getID()); + } + else + { + //first request for this mesh + mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); + mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); + } + } + + //do a quick search to see if we can't display something while we wait for this mesh to load + LLVolume* volume = vobj->getVolume(); + + if (volume) + { + if (volume->getNumVolumeFaces() == 0 && !volume->isTetrahedron()) + { + volume->makeTetrahedron(); + } + + LLVolumeParams params = volume->getParams(); + + LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); + + if (group) + { + //first see what the next lowest LOD available might be + for (S32 i = detail-1; i >= 0; --i) + { + LLVolume* lod = group->refLOD(i); + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) + { + group->derefLOD(lod); + return i; + } + + group->derefLOD(lod); + } + + //no lower LOD is a available, is a higher lod available? + for (S32 i = detail+1; i < 4; ++i) + { + LLVolume* lod = group->refLOD(i); + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) + { + group->derefLOD(lod); + return i; + } + + group->derefLOD(lod); + } + } + else + { + llerrs << "WTF?" << llendl; + } + } + + return detail; +} + +static LLFastTimer::DeclareTimer FTM_START_MESH_THREAD("Start Thread"); +static LLFastTimer::DeclareTimer FTM_LOAD_MESH_LOD("Load LOD"); +static LLFastTimer::DeclareTimer FTM_MESH_LOCK1("Lock 1"); +static LLFastTimer::DeclareTimer FTM_MESH_LOCK2("Lock 2"); + +void LLMeshRepository::notifyLoadedMeshes() +{ //called from main thread + + LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests"); + + //clean up completed upload threads + for (std::vector::iterator iter = mUploads.begin(); iter != mUploads.end(); ) + { + LLMeshUploadThread* thread = *iter; + + if (thread->isStopped() && thread->finished()) + { + iter = mUploads.erase(iter); + delete thread; + } + else + { + ++iter; + } + } + + //update inventory + if (!mInventoryQ.empty()) + { + LLMutexLock lock(mMeshMutex); + while (!mInventoryQ.empty()) + { + inventory_data& data = mInventoryQ.front(); + + LLAssetType::EType asset_type = LLAssetType::lookup(data.mPostData["asset_type"].asString()); + LLInventoryType::EType inventory_type = LLInventoryType::lookup(data.mPostData["inventory_type"].asString()); + + on_new_single_inventory_upload_complete( + asset_type, + inventory_type, + data.mPostData["asset_type"].asString(), + data.mPostData["folder_id"].asUUID(), + data.mPostData["name"], + data.mPostData["description"], + data.mResponse, + 0); + + mInventoryQ.pop(); + } + } + + if (!mThread->mWaiting) + { //curl thread is churning, wait for it to go idle + return; + } + + LLFastTimer t(FTM_MESH_UPDATE); + + { + LLFastTimer t(FTM_MESH_LOCK1); + mMeshMutex->lock(); + } + + { + LLFastTimer t(FTM_MESH_LOCK2); + mThread->mMutex->lock(); + } + + //popup queued error messages from background threads + while (!mUploadErrorQ.empty()) + { + LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front()); + mUploadErrorQ.pop(); + } + + S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests); + + if (push_count > 0) + { + //calculate "score" for pending requests + + //create score map + std::map score_map; + + for (U32 i = 0; i < 4; ++i) + { + for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) + { + F32 max_score = 0.f; + for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + { + LLViewerObject* object = gObjectList.findObject(*obj_iter); + + if (object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); + max_score = llmax(max_score, cur_score); + } + } + } + + score_map[iter->first.getSculptID()] = max_score; + } + } + + //set "score" for pending requests + for (std::vector::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) + { + iter->mScore = score_map[iter->mMeshParams.getSculptID()]; + } + + //sort by "score" + std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); + + while (!mPendingRequests.empty() && push_count > 0) + { + LLFastTimer t(FTM_LOAD_MESH_LOD); + LLMeshRepoThread::LODRequest& request = mPendingRequests.front(); + mThread->loadMeshLOD(request.mMeshParams, request.mLOD); + mPendingRequests.erase(mPendingRequests.begin()); + push_count--; + } + } + + //send skin info requests + while (!mPendingSkinRequests.empty()) + { + mThread->loadMeshSkinInfo(mPendingSkinRequests.front()); + mPendingSkinRequests.pop(); + } + + //send decomposition requests + while (!mPendingDecompositionRequests.empty()) + { + mThread->loadMeshDecomposition(mPendingDecompositionRequests.front()); + mPendingDecompositionRequests.pop(); + } + + mThread->notifyLoadedMeshes(); + + mThread->mMutex->unlock(); + mMeshMutex->unlock(); + + mThread->mSignal->signal(); +} + +void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) +{ + mSkinMap[info.mMeshID] = info; + mLoadingSkins.erase(info.mMeshID); +} + +void LLMeshRepository::notifyDecompositionReceived(LLMeshDecomposition* decomp) +{ + mDecompositionMap[decomp->mMeshID] = decomp; + mLoadingDecompositions.erase(decomp->mMeshID); +} + +void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume) +{ + S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail()); + + //get list of objects waiting to be notified this mesh is loaded + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params); + + if (volume && obj_iter != mLoadingMeshes[detail].end()) + { + //make sure target volume is still valid + if (volume->getNumVolumeFaces() <= 0) + { + llwarns << "Mesh loading returned empty volume." << llendl; + volume->makeTetrahedron(); + } + + { //update system volume + LLVolume* sys_volume = LLPrimitive::getVolumeManager()->refVolume(mesh_params, detail); + if (sys_volume) + { + sys_volume->copyVolumeFaces(volume); + LLPrimitive::getVolumeManager()->unrefVolume(sys_volume); + } + else + { + llwarns << "Couldn't find system volume for given mesh." << llendl; + } + } + + //notify waiting LLVOVolume instances that their requested mesh is available + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + vobj->notifyMeshLoaded(); + } + } + + mLoadingMeshes[detail].erase(mesh_params); + } +} + +void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod) +{ + //get list of objects waiting to be notified this mesh is loaded + mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params); + + F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); + + if (obj_iter != mLoadingMeshes[lod].end()) + { + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + LLVolume* obj_volume = vobj->getVolume(); + + if (obj_volume && + obj_volume->getDetail() == detail && + obj_volume->getParams() == mesh_params) + { //should force volume to find most appropriate LOD + vobj->setVolume(obj_volume->getParams(), lod); + } + } + } + + mLoadingMeshes[lod].erase(mesh_params); + } +} + +S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ + return mThread->getActualMeshLOD(mesh_params, lod); +} + +U32 LLMeshRepository::calcResourceCost(LLSD& header) +{ + U32 bytes = 0; + + for (U32 i = 0; i < 4; i++) + { + bytes += header[header_lod[i]]["size"].asInteger(); + } + + bytes += header["skin"]["size"].asInteger(); + + return bytes/4096 + 1; +} + +U32 LLMeshRepository::getResourceCost(const LLUUID& mesh_id) +{ + return mThread->getResourceCost(mesh_id); +} + +const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id) +{ + if (mesh_id.notNull()) + { + skin_map::iterator iter = mSkinMap.find(mesh_id); + if (iter != mSkinMap.end()) + { + return &(iter->second); + } + + //no skin info known about given mesh, try to fetch it + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + std::set::iterator iter = mLoadingSkins.find(mesh_id); + if (iter == mLoadingSkins.end()) + { //no request pending for this skin info + mLoadingSkins.insert(mesh_id); + mPendingSkinRequests.push(mesh_id); + } + } + } + + return NULL; +} + +const LLMeshDecomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id) +{ + if (mesh_id.notNull()) + { + decomposition_map::iterator iter = mDecompositionMap.find(mesh_id); + if (iter != mDecompositionMap.end()) + { + return iter->second; + } + + //no skin info known about given mesh, try to fetch it + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + std::set::iterator iter = mLoadingDecompositions.find(mesh_id); + if (iter == mLoadingDecompositions.end()) + { //no request pending for this skin info + mLoadingDecompositions.insert(mesh_id); + mPendingDecompositionRequests.push(mesh_id); + } + } + } + + return NULL; +} + +void LLMeshRepository::uploadModel(std::vector& data, LLVector3& scale, bool upload_textures) +{ + LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures); + mUploads.push_back(thread); + thread->start(); +} + +void LLMeshUploadThread::sendCostRequest(LLMeshUploadData& data) +{ + //write model file to memory buffer + std::stringstream ostr; + + LLModel::physics_shape& phys_shape = data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysicsShape : + data.mBaseModel->mPhysicsShape; + + LLSD header = LLModel::writeModel(ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + phys_shape, + true); + + std::string desc = data.mBaseModel->mLabel; + + // Grab the total vertex count of the model + // along with other information for the "asset_resources" map + // to send to the server. + LLSD asset_resources = LLSD::emptyMap(); + + + std::string url = mNewInventoryCapability; + + if (!url.empty()) + { + LLSD body = generate_new_resource_upload_capability_body( + LLAssetType::AT_MESH, + desc, + desc, + LLFolderType::FT_MESH, + LLInventoryType::IT_MESH, + LLFloaterPerms::getNextOwnerPerms(), + LLFloaterPerms::getGroupPerms(), + LLFloaterPerms::getEveryonePerms()); + + body["asset_resources"] = asset_resources; + + mPendingConfirmations++; + LLCurlRequest::headers_t headers; + + data.mPostData = body; + + mCurlRequest->post(url, headers, body, new LLMeshCostResponder(data, this)); + } +} + +void LLMeshUploadThread::sendCostRequest(LLTextureUploadData& data) +{ + if (data.mTexture.notNull() && data.mTexture->getDiscardLevel() >= 0) + { + LLSD asset_resources = LLSD::emptyMap(); + + std::string url = mNewInventoryCapability; + + if (!url.empty()) + { + LLSD body = generate_new_resource_upload_capability_body( + LLAssetType::AT_TEXTURE, + data.mLabel, + data.mLabel, + LLFolderType::FT_TEXTURE, + LLInventoryType::IT_TEXTURE, + LLFloaterPerms::getNextOwnerPerms(), + LLFloaterPerms::getGroupPerms(), + LLFloaterPerms::getEveryonePerms()); + + body["asset_resources"] = asset_resources; + + mPendingConfirmations++; + LLCurlRequest::headers_t headers; + + data.mPostData = body; + mCurlRequest->post(url, headers, body, new LLTextureCostResponder(data, this)); + } + } +} + + +void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data) +{ + if (!data.mRSVP.empty()) + { + std::stringstream ostr; + + LLModel::physics_shape& phys_shape = data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysicsShape : + data.mBaseModel->mPhysicsShape; + + LLModel::writeModel(ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + phys_shape); + + data.mAssetData = ostr.str(); + + LLCurlRequest::headers_t headers; + mPendingUploads++; + + mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLMeshUploadResponder(data, this)); + } +} + +void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data) +{ + if (!data.mRSVP.empty()) + { + std::stringstream ostr; + + if (!data.mTexture->isRawImageValid()) + { + data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel()); + } + + LLPointer upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getRawImage()); + + ostr.write((const char*) upload_file->getData(), upload_file->getDataSize()); + + data.mAssetData = ostr.str(); + + LLCurlRequest::headers_t headers; + mPendingUploads++; + + mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLTextureUploadResponder(data, this)); + } +} + + +void LLMeshUploadThread::onModelUploaded(LLMeshUploadData& data) +{ + createObjects(data); +} + +void LLMeshUploadThread::onTextureUploaded(LLTextureUploadData& data) +{ + mTextureMap[data.mTexture] = data; +} + + +void LLMeshUploadThread::createObjects(LLMeshUploadData& data) +{ + instance_list& instances = mInstance[data.mBaseModel]; + + for (instance_list::iterator iter = instances.begin(); iter != instances.end(); ++iter) + { //create prims that reference given mesh + LLModelInstance& instance = *iter; + instance.mMeshID = data.mUUID; + mInstanceQ.push(instance); + } +} + +LLSD LLMeshUploadThread::createObject(LLModelInstance& instance) +{ + LLMatrix4 transformation = instance.mTransform; + + if (instance.mMeshID.isNull()) + { + llerrs << "WTF?" << llendl; + } + + // check for reflection + BOOL reflected = (transformation.determinant() < 0); + + // compute position + LLVector3 position = LLVector3(0, 0, 0) * transformation; + + // compute scale + LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position; + LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position; + LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position; + F32 x_length = x_transformed.normalize(); + F32 y_length = y_transformed.normalize(); + F32 z_length = z_transformed.normalize(); + LLVector3 scale = LLVector3(x_length, y_length, z_length); + + // adjust for "reflected" geometry + LLVector3 x_transformed_reflected = x_transformed; + if (reflected) + { + x_transformed_reflected *= -1.0; + } + + // compute rotation + LLMatrix3 rotation_matrix; + rotation_matrix.setRows(x_transformed_reflected, y_transformed, z_transformed); + LLQuaternion quat_rotation = rotation_matrix.quaternion(); + quat_rotation.normalize(); // the rotation_matrix might not have been orthoginal. make it so here. + LLVector3 euler_rotation; + quat_rotation.getEulerAngles(&euler_rotation.mV[VX], &euler_rotation.mV[VY], &euler_rotation.mV[VZ]); + + // + // build parameter block to construct this prim + // + + LLSD object_params; + + // create prim + + // set volume params + U8 sculpt_type = LL_SCULPT_TYPE_MESH; + if (reflected) + { + sculpt_type |= LL_SCULPT_FLAG_MIRROR; + } + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + volume_params.setSculptID(instance.mMeshID, sculpt_type); + object_params["shape"] = volume_params.asLLSD(); + + object_params["material"] = LL_MCODE_WOOD; + + object_params["group-id"] = gAgent.getGroupID(); + object_params["pos"] = ll_sd_from_vector3(position + mOrigin); + object_params["rotation"] = ll_sd_from_quaternion(quat_rotation); + object_params["scale"] = ll_sd_from_vector3(scale); + object_params["name"] = instance.mModel->mLabel; + + // load material from dae file + object_params["facelist"] = LLSD::emptyArray(); + for (S32 i = 0; i < instance.mMaterial.size(); i++) + { + LLTextureEntry te; + LLImportMaterial& mat = instance.mMaterial[i]; + + te.setColor(mat.mDiffuseColor); + + LLUUID diffuse_id = mTextureMap[mat.mDiffuseMap].mUUID; + + if (diffuse_id.notNull()) + { + te.setID(diffuse_id); + } + else + { + te.setID(LLUUID("5748decc-f629-461c-9a36-a35a221fe21f")); // blank texture + } + + te.setFullbright(mat.mFullbright); + + object_params["facelist"][i] = te.asLLSD(); + } + + // set extra parameters + LLSculptParams sculpt_params; + sculpt_params.setSculptTexture(instance.mMeshID); + sculpt_params.setSculptType(sculpt_type); + U8 buffer[MAX_OBJECT_PARAMS_SIZE+1]; + LLDataPackerBinaryBuffer dp(buffer, MAX_OBJECT_PARAMS_SIZE); + sculpt_params.pack(dp); + std::vector v(dp.getCurrentSize()); + memcpy(&v[0], buffer, dp.getCurrentSize()); + LLSD extra_parameter; + extra_parameter["extra_parameter"] = sculpt_params.mType; + extra_parameter["param_data"] = v; + object_params["extra_parameters"].append(extra_parameter); + + return object_params; +} + +void LLMeshUploadThread::priceResult(LLMeshUploadData& data, const LLSD& content) +{ + mPendingCost += content["upload_price"].asInteger(); + data.mRSVP = content["rsvp"].asString(); + data.mRSVP = scrub_host_name(data.mRSVP, mHost); + + mConfirmedQ.push(data); +} + +void LLMeshUploadThread::priceResult(LLTextureUploadData& data, const LLSD& content) +{ + mPendingCost += content["upload_price"].asInteger(); + data.mRSVP = content["rsvp"].asString(); + data.mRSVP = scrub_host_name(data.mRSVP, mHost); + + mConfirmedTextureQ.push(data); +} + + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + if (mDiffuseMap != rhs.mDiffuseMap) + { + return mDiffuseMap < rhs.mDiffuseMap; + } + + if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) + { + return mDiffuseMapFilename < rhs.mDiffuseMapFilename; + } + + if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) + { + return mDiffuseMapLabel < rhs.mDiffuseMapLabel; + } + + if (mDiffuseColor != rhs.mDiffuseColor) + { + return mDiffuseColor < rhs.mDiffuseColor; + } + + return mFullbright < rhs.mFullbright; +} + + +void LLMeshRepository::updateInventory(inventory_data data) +{ + LLMutexLock lock(mMeshMutex); + mInventoryQ.push(data); +} + +void LLMeshRepository::uploadError(LLSD& args) +{ + LLMutexLock lock(mMeshMutex); + mUploadErrorQ.push(args); +} + + +LLPhysicsDecomp::LLPhysicsDecomp() +: LLThread("Physics Decomp") +{ + mInited = false; + mQuitting = false; + mDone = false; + mStage = -1; + mContinue = 1; + + mSignal = new LLCondition(NULL); + mMutex = new LLMutex(NULL); + + setStatusMessage("Idle"); +} + +LLPhysicsDecomp::~LLPhysicsDecomp() +{ + shutdown(); +} + +void LLPhysicsDecomp::shutdown() +{ + if (mSignal) + { + mQuitting = true; + mContinue = 0; + mSignal->signal(); + + while (!mDone) + { + apr_sleep(100); + } + } +} + +void LLPhysicsDecomp::setStatusMessage(std::string msg) +{ + LLMutexLock lock(mMutex); + mStatus = msg; +} + +void LLPhysicsDecomp::execute(const char* stage, LLModel* mdl) +{ + LLMutexLock lock(mMutex); + + if (mModel.notNull()) + { + llwarns << "Not done processing previous model." << llendl; + return; + } + + mModel = mdl; + //load model into LLCD + if (mdl) + { + mStage = mStageID[stage]; + + U16 index_offset = 0; + + if (mStage == 0) + { + mPositions.clear(); + mIndices.clear(); + + //queue up vertex positions and indices + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = mdl->getVolumeFace(i); + if (mPositions.size() + face.mNumVertices > 65535) + { + continue; + } + + for (U32 j = 0; j < face.mNumVertices; ++j) + { + mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); + } + + for (U32 j = 0; j < face.mNumIndices; ++j) + { + mIndices.push_back(face.mIndices[j]+index_offset); + } + + index_offset += face.mNumVertices; + } + } + + //signal decomposition thread + mSignal->signal(); + } +} + +//static +S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2) +{ + LLPhysicsDecomp* comp = gMeshRepo.mDecompThread; + comp->setStatusMessage(llformat("%s: %d/%d", status, p1, p2)); + return comp->mContinue; +} + +void LLPhysicsDecomp::cancel() +{ + mContinue = 0; +} + +void LLPhysicsDecomp::run() +{ + LLConvexDecomposition::initSystem(); + mInited = true; + + while (!mQuitting) + { + mSignal->wait(); + if (!mQuitting) + { + //load data intoLLCD + if (mStage == 0) + { + mMesh.mVertexBase = mPositions[0].mV; + mMesh.mVertexStrideBytes = 12; + mMesh.mNumVertices = mPositions.size(); + + mMesh.mIndexType = LLCDMeshData::INT_16; + mMesh.mIndexBase = &(mIndices[0]); + mMesh.mIndexStrideBytes = 6; + + mMesh.mNumTriangles = mIndices.size()/3; + + LLCDResult ret = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + ret = LLConvexDecomposition::getInstance()->setMeshData(&mMesh); + } + + if (ret) + { + llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl; + } + } + + setStatusMessage("Executing."); + + mContinue = 1; + LLCDResult ret = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + ret = LLConvexDecomposition::getInstance()->executeStage(mStage); + } + + mContinue = 0; + if (ret) + { + llerrs << "Convex Decomposition thread valid but could not execute stage " << mStage << llendl; + } + + + setStatusMessage("Reading results"); + + S32 num_hulls =0; + if (LLConvexDecomposition::getInstance() != NULL) + { + num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(mStage); + } + + if (mModel.isNull()) + { + llerrs << "mModel should never be null here!" << llendl; + } + + mMutex->lock(); + mModel->mPhysicsShape.clear(); + mModel->mPhysicsShape.resize(num_hulls); + mModel->mHullCenter.clear(); + mModel->mHullCenter.resize(num_hulls); + std::vector > mesh_buffer; + mesh_buffer.resize(num_hulls); + mModel->mPhysicsCenter.clearVec(); + mModel->mPhysicsPoints = 0; + mMutex->unlock(); + + for (S32 i = 0; i < num_hulls; ++i) + { + std::vector p; + LLCDHull hull; + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + LLConvexDecomposition::getInstance()->getHullFromStage(mStage, i, &hull); + + const F32* v = hull.mVertexBase; + + LLVector3 hull_center; + + for (S32 j = 0; j < hull.mNumVertices; ++j) + { + LLVector3 vert(v[0], v[1], v[2]); + p.push_back(vert); + hull_center += vert; + v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); + } + + + hull_center *= 1.f/hull.mNumVertices; + + LLCDMeshData mesh; + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + LLConvexDecomposition::getInstance()->getMeshFromStage(mStage, i, &mesh); + + mesh_buffer[i] = get_vertex_buffer_from_mesh(mesh); + + mMutex->lock(); + mModel->mPhysicsShape[i] = p; + mModel->mHullCenter[i] = hull_center; + mModel->mPhysicsPoints += hull.mNumVertices; + mModel->mPhysicsCenter += hull_center; + + mMutex->unlock(); + } + + { + LLMutexLock lock(mMutex); + mModel->mPhysicsCenter *= 1.f/mModel->mPhysicsPoints; + + LLFloaterModelPreview::onModelDecompositionComplete(mModel, mesh_buffer); + //done updating model + mModel = NULL; + } + + setStatusMessage("Done."); + LLFloaterModelPreview::sInstance->mModelPreview->refresh(); + } + } + + LLConvexDecomposition::quitSystem(); + + //delete mSignal; + delete mMutex; + mSignal = NULL; + mMutex = NULL; + mDone = true; +} + +#endif + diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h new file mode 100644 index 0000000000..d5e21c35cc --- /dev/null +++ b/indra/newview/llmeshrepository.h @@ -0,0 +1,471 @@ +/** + * @file llmeshrepository.h + * @brief Client-side repository of mesh assets. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_MESH_REPOSITORY_H +#define LL_MESH_REPOSITORY_H + +#include "llassettype.h" +#include "llmodel.h" +#include "lluuid.h" +#include "llviewertexture.h" +#include "llvolume.h" + +#if LL_MESH_ENABLED + +#define LLCONVEXDECOMPINTER_STATIC 1 + +#include "llconvexdecomposition.h" + +class LLVOVolume; +class LLMeshResponder; +class LLCurlRequest; +class LLMutex; +class LLCondition; +class LLVFS; +class LLMeshRepository; + +class LLMeshUploadData +{ +public: + LLPointer mBaseModel; + LLPointer mModel[5]; + LLUUID mUUID; + U32 mRetries; + std::string mRSVP; + std::string mAssetData; + LLSD mPostData; + + LLMeshUploadData() + { + mRetries = 0; + } +}; + +class LLTextureUploadData +{ +public: + LLPointer mTexture; + LLUUID mUUID; + std::string mRSVP; + std::string mLabel; + U32 mRetries; + std::string mAssetData; + LLSD mPostData; + + LLTextureUploadData() + { + mRetries = 0; + } + + LLTextureUploadData(LLViewerFetchedTexture* texture, std::string& label) + : mTexture(texture), mLabel(label) + { + mRetries = 0; + } +}; + +class LLImportMaterial +{ +public: + LLPointer mDiffuseMap; + std::string mDiffuseMapFilename; + std::string mDiffuseMapLabel; + LLColor4 mDiffuseColor; + bool mFullbright; + + bool operator<(const LLImportMaterial ¶ms) const; + + LLImportMaterial() + : mFullbright(false) + { + mDiffuseColor.set(1,1,1,1); + } +}; + +class LLModelInstance +{ +public: + LLPointer mModel; + LLPointer mLOD[5]; + + LLUUID mMeshID; + + LLMatrix4 mTransform; + std::vector mMaterial; + + LLModelInstance(LLModel* model, LLMatrix4& transform, std::vector& materials) + : mModel(model), mTransform(transform), mMaterial(materials) + { + } +}; + +class LLMeshSkinInfo +{ +public: + LLUUID mMeshID; + std::vector mJointNames; + std::vector mInvBindMatrix; + LLMatrix4 mBindShapeMatrix; +}; + +class LLMeshDecomposition +{ +public: + LLMeshDecomposition() { } + + LLUUID mMeshID; + LLModel::physics_shape mHull; + + std::vector > mMesh; +}; + +class LLPhysicsDecomp : public LLThread +{ +public: + LLCondition* mSignal; + LLMutex* mMutex; + + LLCDMeshData mMesh; + + bool mInited; + bool mQuitting; + bool mDone; + + S32 mContinue; + std::string mStatus; + + std::vector mPositions; + std::vector mIndices; + + S32 mStage; + + LLPhysicsDecomp(); + ~LLPhysicsDecomp(); + + void shutdown(); + void setStatusMessage(std::string msg); + + void execute(const char* stage, LLModel* mdl); + static S32 llcdCallback(const char*, S32, S32); + void cancel(); + + virtual void run(); + + std::map mStageID; + LLPointer mModel; +}; + +class LLMeshRepoThread : public LLThread +{ +public: + + static S32 sActiveHeaderRequests; + static S32 sActiveLODRequests; + static U32 sMaxConcurrentRequests; + + LLCurlRequest* mCurlRequest; + LLMutex* mMutex; + LLMutex* mHeaderMutex; + LLCondition* mSignal; + + bool mWaiting; + + //map of known mesh headers + typedef std::map mesh_header_map; + mesh_header_map mMeshHeader; + + std::map mMeshHeaderSize; + std::map mMeshResourceCost; + + class HeaderRequest + { + public: + const LLVolumeParams mMeshParams; + + HeaderRequest(const LLVolumeParams& mesh_params) + : mMeshParams(mesh_params) + { + } + + bool operator<(const HeaderRequest& rhs) const + { + return mMeshParams < rhs.mMeshParams; + } + }; + + class LODRequest + { + public: + LLVolumeParams mMeshParams; + S32 mLOD; + F32 mScore; + + LODRequest(const LLVolumeParams& mesh_params, S32 lod) + : mMeshParams(mesh_params), mLOD(lod), mScore(0.f) + { + } + }; + + struct CompareScoreGreater + { + bool operator()(const LODRequest& lhs, const LODRequest& rhs) + { + return lhs.mScore > rhs.mScore; // greatest = first + } + }; + + + class LoadedMesh + { + public: + LLPointer mVolume; + LLVolumeParams mMeshParams; + S32 mLOD; + + LoadedMesh(LLVolume* volume, const LLVolumeParams& mesh_params, S32 lod) + : mVolume(volume), mMeshParams(mesh_params), mLOD(lod) + { + } + + }; + + //set of requested skin info + std::set mSkinRequests; + + //queue of completed skin info requests + std::queue mSkinInfoQ; + + //set of requested decompositions + std::set mDecompositionRequests; + + //queue of completed Decomposition info requests + std::queue mDecompositionQ; + + //queue of requested headers + std::queue mHeaderReqQ; + + //queue of requested LODs + std::queue mLODReqQ; + + //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) + std::queue mUnavailableQ; + + //queue of successfully loaded meshes + std::queue mLoadedQ; + + //map of pending header requests and currently desired LODs + typedef std::map > pending_lod_map; + pending_lod_map mPendingLOD; + + static std::string constructUrl(LLUUID mesh_id); + + LLMeshRepoThread(); + ~LLMeshRepoThread(); + + virtual void run(); + + void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool fetchMeshHeader(const LLVolumeParams& mesh_params); + bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size); + bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size); + bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); + bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); + + void notifyLoadedMeshes(); + S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + U32 getResourceCost(const LLUUID& mesh_params); + + void loadMeshSkinInfo(const LLUUID& mesh_id); + void loadMeshDecomposition(const LLUUID& mesh_id); + + //send request for skin info, returns true if header info exists + // (should hold onto mesh_id and try again later if header info does not exist) + bool fetchMeshSkinInfo(const LLUUID& mesh_id); + + //send request for decomposition, returns true if header info exists + // (should hold onto mesh_id and try again later if header info does not exist) + bool fetchMeshDecomposition(const LLUUID& mesh_id); +}; + +class LLMeshUploadThread : public LLThread +{ +public: + typedef std::vector instance_list; + instance_list mInstanceList; + + typedef std::map, instance_list> instance_map; + instance_map mInstance; + + LLMutex* mMutex; + LLCurlRequest* mCurlRequest; + S32 mPendingConfirmations; + S32 mPendingUploads; + S32 mPendingCost; + bool mFinished; + LLVector3 mOrigin; + bool mUploadTextures; + + LLHost mHost; + std::string mUploadObjectAssetCapability; + std::string mNewInventoryCapability; + + std::queue mUploadQ; + std::queue mConfirmedQ; + std::queue mInstanceQ; + + std::queue mTextureQ; + std::queue mConfirmedTextureQ; + + std::map, LLTextureUploadData> mTextureMap; + + LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures); + ~LLMeshUploadThread(); + + void uploadTexture(LLTextureUploadData& data); + void doUploadTexture(LLTextureUploadData& data); + void sendCostRequest(LLTextureUploadData& data); + void priceResult(LLTextureUploadData& data, const LLSD& content); + void onTextureUploaded(LLTextureUploadData& data); + + void uploadModel(LLMeshUploadData& data); + void sendCostRequest(LLMeshUploadData& data); + void doUploadModel(LLMeshUploadData& data); + void onModelUploaded(LLMeshUploadData& data); + void createObjects(LLMeshUploadData& data); + LLSD createObject(LLModelInstance& instance); + void priceResult(LLMeshUploadData& data, const LLSD& content); + + bool finished() { return mFinished; } + virtual void run(); + +}; + +class LLMeshRepository +{ +public: + + //metrics + static U32 sBytesReceived; + static U32 sHTTPRequestCount; + static U32 sHTTPRetryCount; + static U32 sCacheBytesRead; + static U32 sCacheBytesWritten; + static U32 sPeakKbps; + + + LLMeshRepository(); + + void init(); + void shutdown(); + + //mesh management functions + S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0); + + void notifyLoadedMeshes(); + void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume); + void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod); + void notifySkinInfoReceived(LLMeshSkinInfo& info); + void notifyDecompositionReceived(LLMeshDecomposition* info); + + S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + U32 calcResourceCost(LLSD& header); + U32 getResourceCost(const LLUUID& mesh_params); + const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id); + const LLMeshDecomposition* getDecomposition(const LLUUID& mesh_id); + + void uploadModel(std::vector& data, LLVector3& scale, bool upload_textures); + + + + + typedef std::map > mesh_load_map; + mesh_load_map mLoadingMeshes[4]; + + typedef std::map skin_map; + skin_map mSkinMap; + + typedef std::map decomposition_map; + decomposition_map mDecompositionMap; + + LLMutex* mMeshMutex; + + std::vector mPendingRequests; + + //list of mesh ids awaiting skin info + std::set mLoadingSkins; + + //list of mesh ids that need to send skin info fetch requests + std::queue mPendingSkinRequests; + + //list of mesh ids awaiting decompositions + std::set mLoadingDecompositions; + + //list of mesh ids that need to send decomposition fetch requests + std::queue mPendingDecompositionRequests; + + U32 mMeshThreadCount; + + void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header); + + LLMeshRepoThread* mThread; + std::vector mUploads; + + LLPhysicsDecomp* mDecompThread; + + class inventory_data + { + public: + LLSD mPostData; + LLSD mResponse; + + inventory_data(const LLSD& data, const LLSD& content) + : mPostData(data), mResponse(content) + { + } + }; + + std::queue mInventoryQ; + + std::queue mUploadErrorQ; + + void uploadError(LLSD& args); + void updateInventory(inventory_data data); + +}; + +extern LLMeshRepository gMeshRepo; + +#endif + +#endif + -- cgit v1.3 From 21b1b91c448b7d148a840c06d74deabc45af1819 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 6 Oct 2010 12:53:26 -0500 Subject: ATI compatibility pass --- indra/llrender/llglslshader.cpp | 13 +++++++++++-- .../newview/app_settings/shaders/class1/avatar/avatarF.glsl | 2 ++ .../app_settings/shaders/class1/avatar/avatarSkinV.glsl | 2 ++ .../newview/app_settings/shaders/class1/avatar/avatarV.glsl | 2 ++ .../app_settings/shaders/class1/avatar/eyeballF.glsl | 2 ++ .../app_settings/shaders/class1/avatar/eyeballV.glsl | 2 ++ .../app_settings/shaders/class1/avatar/pickAvatarF.glsl | 2 ++ .../app_settings/shaders/class1/avatar/pickAvatarV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/alphaF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/alphaSkinnedV.glsl | 10 +++++++++- .../app_settings/shaders/class1/deferred/alphaV.glsl | 2 ++ .../shaders/class1/deferred/attachmentShadowF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/avatarAlphaF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/avatarAlphaV.glsl | 12 ++++++++++-- .../app_settings/shaders/class1/deferred/avatarF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/avatarShadowF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/avatarShadowV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/avatarV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/blurLightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/blurLightV.glsl | 2 ++ .../newview/app_settings/shaders/class1/deferred/bumpF.glsl | 2 ++ .../newview/app_settings/shaders/class1/deferred/bumpV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/diffuseF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/diffuseV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/fullbrightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/fullbrightV.glsl | 2 ++ indra/newview/app_settings/shaders/class1/deferred/giF.glsl | 2 ++ indra/newview/app_settings/shaders/class1/deferred/giV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/impostorF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/impostorV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/luminanceF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/luminanceV.glsl | 3 +++ .../shaders/class1/deferred/multiPointLightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/pointLightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/pointLightV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/postDeferredF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/postDeferredV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/postgiF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/postgiV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/shadowF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/shadowV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/softenLightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/softenLightV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/sunLightF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/sunLightSSAOF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/sunLightV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/terrainF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/terrainV.glsl | 2 ++ .../newview/app_settings/shaders/class1/deferred/treeF.glsl | 2 ++ .../newview/app_settings/shaders/class1/deferred/treeV.glsl | 2 ++ .../app_settings/shaders/class1/deferred/waterF.glsl | 2 ++ .../app_settings/shaders/class1/deferred/waterV.glsl | 2 ++ .../app_settings/shaders/class1/effects/glowExtractF.glsl | 2 ++ .../app_settings/shaders/class1/effects/glowExtractV.glsl | 1 + .../newview/app_settings/shaders/class1/effects/glowF.glsl | 2 ++ .../newview/app_settings/shaders/class1/effects/glowV.glsl | 2 ++ .../app_settings/shaders/class1/environment/terrainF.glsl | 2 ++ .../app_settings/shaders/class1/environment/terrainV.glsl | 2 ++ .../shaders/class1/environment/terrainWaterF.glsl | 2 ++ .../shaders/class1/environment/underWaterF.glsl | 2 ++ .../app_settings/shaders/class1/environment/waterF.glsl | 2 ++ .../app_settings/shaders/class1/environment/waterFogF.glsl | 2 ++ .../app_settings/shaders/class1/environment/waterV.glsl | 2 ++ .../app_settings/shaders/class1/interface/highlightF.glsl | 2 ++ .../app_settings/shaders/class1/interface/highlightV.glsl | 2 ++ .../app_settings/shaders/class1/lighting/lightF.glsl | 2 ++ .../shaders/class1/lighting/lightFullbrightF.glsl | 2 ++ .../shaders/class1/lighting/lightFullbrightShinyF.glsl | 2 ++ .../shaders/class1/lighting/lightFullbrightShinyWaterF.glsl | 2 ++ .../shaders/class1/lighting/lightFullbrightWaterF.glsl | 2 ++ .../shaders/class1/lighting/lightFuncSpecularV.glsl | 2 ++ .../app_settings/shaders/class1/lighting/lightFuncV.glsl | 2 ++ .../app_settings/shaders/class1/lighting/lightShinyF.glsl | 2 ++ .../shaders/class1/lighting/lightShinyWaterF.glsl | 2 ++ .../shaders/class1/lighting/lightSpecularV.glsl | 2 ++ .../app_settings/shaders/class1/lighting/lightV.glsl | 2 ++ .../app_settings/shaders/class1/lighting/lightWaterF.glsl | 2 ++ .../shaders/class1/lighting/sumLightsSpecularV.glsl | 3 +++ .../app_settings/shaders/class1/lighting/sumLightsV.glsl | 2 ++ .../app_settings/shaders/class1/objects/fullbrightF.glsl | 2 ++ .../shaders/class1/objects/fullbrightShinyF.glsl | 2 ++ .../shaders/class1/objects/fullbrightShinyV.glsl | 2 ++ .../shaders/class1/objects/fullbrightShinyWaterF.glsl | 2 ++ .../app_settings/shaders/class1/objects/fullbrightV.glsl | 2 ++ .../shaders/class1/objects/fullbrightWaterF.glsl | 2 ++ .../newview/app_settings/shaders/class1/objects/shinyF.glsl | 2 ++ .../newview/app_settings/shaders/class1/objects/shinyV.glsl | 2 ++ .../app_settings/shaders/class1/objects/shinyWaterF.glsl | 2 ++ .../app_settings/shaders/class1/objects/simpleF.glsl | 2 ++ .../app_settings/shaders/class1/objects/simpleSkinnedV.glsl | 2 +- .../app_settings/shaders/class1/objects/simpleV.glsl | 2 ++ .../app_settings/shaders/class1/objects/simpleWaterF.glsl | 2 ++ .../shaders/class1/windlight/atmosphericsF.glsl | 2 ++ .../shaders/class1/windlight/atmosphericsHelpersV.glsl | 2 ++ .../shaders/class1/windlight/atmosphericsV.glsl | 2 ++ .../shaders/class1/windlight/atmosphericsVarsF.glsl | 2 ++ .../shaders/class1/windlight/atmosphericsVarsV.glsl | 2 ++ .../app_settings/shaders/class1/windlight/gammaF.glsl | 2 ++ .../app_settings/shaders/class1/windlight/transportF.glsl | 2 ++ .../app_settings/shaders/class2/avatar/eyeballV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/alphaF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/alphaSkinnedV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/alphaV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/avatarAlphaF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/avatarAlphaV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/blurLightF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/blurLightV.glsl | 2 ++ .../newview/app_settings/shaders/class2/deferred/edgeF.glsl | 2 ++ .../newview/app_settings/shaders/class2/deferred/edgeV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/postDeferredF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/postDeferredV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/softenLightF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/softenLightV.glsl | 2 ++ .../app_settings/shaders/class2/deferred/spotLightF.glsl | 2 +- .../app_settings/shaders/class2/deferred/sunLightF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/sunLightSSAOF.glsl | 2 ++ .../app_settings/shaders/class2/deferred/sunLightV.glsl | 2 ++ .../newview/app_settings/shaders/class2/effects/blurF.glsl | 2 ++ .../newview/app_settings/shaders/class2/effects/blurV.glsl | 2 ++ .../app_settings/shaders/class2/effects/colorFilterF.glsl | 2 ++ .../app_settings/shaders/class2/effects/drawQuadV.glsl | 2 ++ .../app_settings/shaders/class2/effects/extractF.glsl | 2 ++ .../app_settings/shaders/class2/effects/nightVisionF.glsl | 2 ++ .../app_settings/shaders/class2/effects/simpleF.glsl | 2 ++ .../app_settings/shaders/class2/environment/terrainF.glsl | 2 ++ .../app_settings/shaders/class2/environment/terrainV.glsl | 2 ++ .../shaders/class2/environment/terrainWaterF.glsl | 2 ++ .../shaders/class2/environment/underWaterF.glsl | 2 ++ .../app_settings/shaders/class2/environment/waterF.glsl | 2 ++ .../app_settings/shaders/class2/environment/waterFogF.glsl | 2 ++ .../app_settings/shaders/class2/lighting/lightF.glsl | 2 ++ .../shaders/class2/lighting/lightFullbrightF.glsl | 2 ++ .../shaders/class2/lighting/lightFullbrightShinyF.glsl | 2 ++ .../shaders/class2/lighting/lightFullbrightShinyWaterF.glsl | 2 ++ .../shaders/class2/lighting/lightFullbrightWaterF.glsl | 2 ++ .../app_settings/shaders/class2/lighting/lightShinyF.glsl | 2 ++ .../shaders/class2/lighting/lightShinyWaterF.glsl | 2 ++ .../shaders/class2/lighting/lightSpecularV.glsl | 2 ++ .../app_settings/shaders/class2/lighting/lightV.glsl | 2 ++ .../app_settings/shaders/class2/lighting/lightWaterF.glsl | 2 ++ .../shaders/class2/lighting/sumLightsSpecularV.glsl | 2 ++ .../app_settings/shaders/class2/lighting/sumLightsV.glsl | 2 ++ .../newview/app_settings/shaders/class2/objects/shinyV.glsl | 2 ++ .../shaders/class2/windlight/atmosphericsF.glsl | 2 ++ .../shaders/class2/windlight/atmosphericsHelpersV.glsl | 2 ++ .../shaders/class2/windlight/atmosphericsV.glsl | 2 ++ .../shaders/class2/windlight/atmosphericsVarsF.glsl | 2 ++ .../shaders/class2/windlight/atmosphericsVarsV.glsl | 2 ++ .../app_settings/shaders/class2/windlight/cloudsF.glsl | 2 ++ .../app_settings/shaders/class2/windlight/cloudsV.glsl | 2 ++ .../app_settings/shaders/class2/windlight/gammaF.glsl | 2 ++ .../newview/app_settings/shaders/class2/windlight/skyF.glsl | 2 ++ .../newview/app_settings/shaders/class2/windlight/skyV.glsl | 2 ++ .../app_settings/shaders/class2/windlight/transportF.glsl | 2 ++ .../newview/app_settings/shaders/class3/avatar/avatarV.glsl | 2 ++ .../app_settings/shaders/class3/deferred/giDownsampleF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/giDownsampleV.glsl | 2 ++ indra/newview/app_settings/shaders/class3/deferred/giF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/giFinalF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/giFinalV.glsl | 2 ++ indra/newview/app_settings/shaders/class3/deferred/giV.glsl | 2 ++ .../app_settings/shaders/class3/deferred/luminanceF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/luminanceV.glsl | 2 ++ .../app_settings/shaders/class3/deferred/postDeferredF.glsl | 4 +++- .../app_settings/shaders/class3/deferred/postDeferredV.glsl | 2 ++ .../app_settings/shaders/class3/deferred/postgiF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/postgiV.glsl | 2 ++ .../app_settings/shaders/class3/deferred/softenLightF.glsl | 2 ++ .../app_settings/shaders/class3/deferred/softenLightV.glsl | 2 ++ .../newview/app_settings/shaders/class3/deferred/treeF.glsl | 2 ++ .../shaders/class3/lighting/sumLightsSpecularV.glsl | 2 ++ .../app_settings/shaders/class3/lighting/sumLightsV.glsl | 2 ++ indra/newview/lldrawpoolavatar.cpp | 6 +----- indra/newview/pipeline.cpp | 3 --- 174 files changed, 369 insertions(+), 16 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index f59bac8c3c..ac56bea275 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -704,6 +704,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const string& uniform) { + GLint ret = -1; if (mProgramObject > 0) { std::map::iterator iter = mUniformMap.find(uniform); @@ -718,11 +719,19 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform) } stop_glerror(); } - return iter->second; + ret = iter->second; } } - return -1; + if (gDebugGL) + { + if (ret == -1 && ret != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform map invalid." << llendl; + } + } + + return ret; } GLint LLGLSLShader::getAttribLocation(U32 attrib) diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl index 5de9cb0790..3f6b8b3323 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index 7e9818e54a..1ad87badfe 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 attribute vec4 weight; //1 diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl index 9f06301cc7..a15846f192 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl index 0feb88535a..05fe100372 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl index 30a2f10f62..4b8a7604a1 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl index bcd710dc57..27ac59a840 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl index 299def1927..f1aa549a47 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index aad21c309b..b08c5dd295 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl index fde0e97713..4261f943fb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getObjectSkinnedTransform(); @@ -22,6 +24,9 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; varying vec3 vary_light; +varying vec3 vary_fragcoord; + +uniform float near_clip; void main() { @@ -38,7 +43,8 @@ void main() norm = gl_Vertex.xyz + gl_Normal.xyz; norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz); - gl_Position = gl_ProjectionMatrix * pos; + vec4 frag_pos = gl_ProjectionMatrix * pos; + gl_Position = frag_pos; vary_position = pos.xyz; vary_normal = norm; @@ -70,6 +76,8 @@ void main() gl_FrontColor = col; gl_FogFragCoord = pos.z; + + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 9cbc5fac73..7ac410da95 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ +#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl index 085ffddeec..164322c3a7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl @@ -5,6 +5,8 @@ * $License$ */ +#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl index 82ce6d7377..7d9d6cc0b2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ +#version 120 + uniform sampler2D diffuseMap; uniform sampler2DShadow shadowMap0; uniform sampler2DShadow shadowMap1; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index e565952c3f..5dfbb91393 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); @@ -21,6 +23,9 @@ varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; +varying vec3 vary_fragcoord; + +uniform float near_clip; void main() { @@ -40,7 +45,9 @@ void main() norm.z = dot(trans[2].xyz, gl_Normal); norm = normalize(norm); - gl_Position = gl_ProjectionMatrix * pos; + vec4 frag_pos = gl_ProjectionMatrix * pos; + gl_Position = frag_pos; + vary_position = pos.xyz; vary_normal = norm; @@ -71,7 +78,8 @@ void main() gl_FrontColor = col; gl_FogFragCoord = pos.z; - + + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index e376892e0a..9748727147 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index d88e3ecfd8..1b7ae06888 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 2af8c8f5f7..cf6579a40d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 988226fb7c..69c93799b5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 258a9b7c40..ea2df4b51a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl index b1b3f55f00..c2d05c601a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 35f334d58e..37bfaac32c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 6c8550cb5b..9b109b2db6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_mat0; varying vec3 vary_mat1; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 9bd622a506..35cfb80c93 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index bd58096317..03d3322cb6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_normal; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index f53e15c6cc..3429877397 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index dc8b2c6be4..6c38d220e2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl index e64e29a0d2..75b555e8ae 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl index 543527612e..8dc1410ea5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 7f365fedc8..7125d845d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D normalMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl index 4fc27d4412..37148b3f1a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index acb3014d18..78df54d5dc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ +#version 120 + uniform sampler2DRect diffuseMap; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl index 6368def830..0c820bfc6c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl @@ -5,6 +5,9 @@ * $/LicenseInfo$ */ +#version 120 + + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 6fca08ae6a..c5ddf31ac0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ +#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect depthMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 43da16436b..22ed9dcd40 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + + #version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index e056c3e896..8e74feb615 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ +#version 120 + varying vec4 vary_light; varying vec4 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 650e1a91a8..7e41b07f8a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl index 0ec81dcb02..12983baa94 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index e8e58f50e1..63b3c9f205 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl index e5f6217644..ae57227fe5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index 378a3295ec..6674c4a5aa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index 666f909f01..db3bddc6be 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec4 post_pos; diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 5fbeceba81..0fb26bd9a1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl index 9d187b46e2..8f0bcca76b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index d4d686bbb7..00093836a2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 //class 1, no shadow, no SSAO, should never be called diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index cdbed4b791..1e0693d19f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl index 9d092d9cea..9beb513ad8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec4 vary_light; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 9ba508a30c..0edae47918 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index 789e53b789..a6163063be 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_normal; diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 1c1725a95c..c54d9a1e3e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index 45832e350f..29689ecbaf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_normal; diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index ea531de24a..e76f598d09 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl index e002d75ebe..649e392630 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 2d40a19fa6..f2023fa5ea 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl index fe45898ed2..0ca0608b45 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl @@ -5,6 +5,7 @@ * $/LicenseInfo$ */ +#version 120 void main() { diff --git a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl index 5b4e8b3ecc..65fc2e9f99 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform float glowStrength; diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl index 97696e4719..0bd44cec90 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec2 glowDelta; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl index 3a852239fb..ac00f15b35 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D detail0; uniform sampler2D detail1; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl index 0d781fd849..1e19ee7699 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl index 99c340d91a..34f78565a5 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // this class1 shader is just a copy of terrainF diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl index 66458ec66d..0dfac84a6e 100644 --- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index 5f1fbee1df..4e9c09b1ea 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index e5eb25f3fa..a34cf23790 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 applyWaterFog(vec4 color) { diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl index 608a7a5807..161c794c68 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl index 5ac9e96601..6f821f893d 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl index c5f69c4ad4..d1c98bf70c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void main() { diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl index ad128dae8d..9c59e8c3ad 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index 1742b9fc1c..1fee99c446 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl index 68b6603b4a..fb5da21c72 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl index 4cde013eef..1bdaccf9b8 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl @@ -5,6 +5,8 @@ * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl index 693ed289f2..2e94d3bbf1 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl @@ -5,6 +5,8 @@ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl index b888e70325..714f9a2551 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l) { diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 4b6d95e177..65b45f8081 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l) diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl index b127b1f8ea..7f65ea76f7 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl index 05ad3256af..8f13e6dc04 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl index b1a7cb46ff..56f31f6a79 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl index f6afa6a3ae..64d549ff52 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl index e5e6ddc2d8..c5d084c132 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl index a0649aea88..732d246471 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,9 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl index c7d40d853f..73e1a1ec26 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl index 9da4c2c92b..afc3dc89bf 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void fullbright_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl index 1c8a9a1a30..3dc4294f67 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void fullbright_shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl index 032def63b3..02367b9439 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl index 5e6e4c16b7..5daf66fb31 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void fullbright_shiny_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index 914e417ca0..38e07dbd80 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl index df76e9e1eb..afaac4f69c 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void fullbright_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl index 6bcd44506d..2cf7a69baa 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl index 0aa313e0df..6ea83b721d 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl index 54b30573e7..e3babe2210 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void shiny_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl index 61c2ce4272..d449d37c0c 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl index 59944b8861..be38a14d52 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl @@ -1,5 +1,5 @@ /** - * @file simpleV.glsl + * @file simpleSkinnedV.glsl * * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index ced1a4be01..0d8e14e2e3 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl index 5e44212aed..68bd81e029 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void default_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl index 7a05b8c8c6..f337bde329 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec3 atmosLighting(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl index 874f2b4843..4b402a7028 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec3 atmosAmbient(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl index 7ead9ddf26..20948b1e46 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void setPositionEye(vec3 v); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl index f6032f8d41..8a2c2a7186 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl index a696ddf607..a1dd4ed5fe 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl index 4a1899798a..7aed1fd3b5 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl index b78b90545e..6780dc4d3e 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec3 atmosTransport(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl index 47300f0b39..172c2ca078 100644 --- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 553a5d2f4f..32aab152a3 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl index dc4663677b..1da3d95069 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 45f727951e..92f1cb22d6 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl index 5ecbbd2c4f..4671a54078 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 2b2d40c2ce..30954a8677 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl index 258a9b7c40..ea2df4b51a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl index b1b3f55f00..c2d05c601a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl index ff32a15c54..c9bee13b48 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl index 74f2bd9818..b3413c301f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl index 757e3e7aab..3da50eb52a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect diffuseRect; uniform sampler2DRect localLightMap; diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl index 0ec81dcb02..12983baa94 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 1067be1e6e..0160e84278 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl index 9d187b46e2..8f0bcca76b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index d0e242c2d4..50b9ef276e 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -4,7 +4,7 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ - + #version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index f565d3bdb9..26bc83e0d4 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 4e33a1af45..cc921f23d7 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl index 9d092d9cea..9beb513ad8 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec4 vary_light; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl index 4173709298..a4ad0bfa15 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect RenderTexture; uniform float bloomStrength; diff --git a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl index f66609527d..d471a6c5e5 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec2 texelSize; uniform vec2 blurDirection; diff --git a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl index df41dae757..66880b958e 100644 --- a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect RenderTexture; uniform float brightness; diff --git a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl index e836caf93f..c35c500d62 100644 --- a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void main(void) { diff --git a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl index 06d5fc9797..e77baa5bee 100644 --- a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect RenderTexture; uniform float extractLow; diff --git a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl index 0a2767ad02..8e0eec6f5e 100644 --- a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect RenderTexture; uniform sampler2D NoiseTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl index 29ad9a995b..98a50e22fc 100644 --- a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl index 32259acf1b..bbb8951f3a 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl index 2234f0bd89..84906c16bf 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl index 1650912fc8..7590c542ef 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl index 9e936a3790..900f1a6cb8 100644 --- a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl index e477107c0b..f4f6b6e90f 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl index 7bcdcf5d5b..9f3328cbf0 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec4 lightnorm; uniform vec4 waterPlane; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl index 269d11a085..342bc2ab66 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl index 9ffe3c6f4a..dad18b5883 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl index b7181dec3a..73ff81e03a 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl index eca9a567f6..9b4b584369 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl index ee38790cc4..3d46c8d874 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl index b96b5d75bc..ebe21320b4 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl index 0f5b2d6fcf..7f48e2cf1d 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl index 6400b45d9e..ad1dc4da77 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl index 89ef510d7c..a0f6e019ef 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl index 016258bd18..97eba92d7b 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl index 8cfeeb1cf9..fde32ed035 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index a512b9d6fb..8fe49e3be0 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl index c428bbb28e..4cebb06df0 100644 --- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl index 8baff24dbd..77d15fba9a 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl index 6883edc1f1..8c5b864cbe 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // Output variables vec3 getSunlitColor(); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl index f5c513bbdd..8d365c15ca 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // varying param funcs void setSunlitColor(vec3 v); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl index d0b60e918e..cf9ef30632 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl index 4b4baf50d0..398f1556a0 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl index 2a559440fc..13207997b2 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl index 865c0e9da8..267ef36d4d 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 ////////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl index ce4bd2358f..a658edd21f 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl index b69a88a45f..77ca4868a6 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl index 397db01378..03bca8f27e 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 // SKY //////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl index b30313bdc8..7f1ad4d5b4 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl index c85ba0c734..a003e2a1f1 100644 --- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl index d26b244fa3..fc370ef367 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2DRect giLightMap; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl index e5f6217644..ae57227fe5 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl index 735150a78c..951e3e97ae 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl index e0f4a3e4f5..b2f8b2c633 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl index fbf2c17370..19c4e07b8b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl index 543527612e..8dc1410ea5 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl index d9483bc6e4..5f3bf68b24 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl index 6368def830..a24eda35dc 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl index 51ab579e3c..ab99a88971 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl @@ -4,7 +4,9 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ - + +#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl index 0ec81dcb02..12983baa94 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl index 24fa07f251..f037754708 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl index e5f6217644..ae57227fe5 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index a2db247331..ce32f66000 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl index 9d187b46e2..8f0bcca76b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl index 1c1725a95c..c54d9a1e3e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl index 2b44aedd5a..04533fdce1 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 329b0c4305..73bc18b866 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -4,6 +4,8 @@ * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * $/LicenseInfo$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index e09e40671d..579af2ad38 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1506,11 +1506,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) skin->mJointNames.size(), FALSE, (GLfloat*) mat[0].mMatrix); - LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette[0]", - skin->mJointNames.size(), - FALSE, - (GLfloat*) mat[0].mMatrix); - + stop_glerror(); } else diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f11cfc738d..b771bde128 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6853,7 +6853,6 @@ void LLPipeline::renderDeferredLighting() gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); gDeferredBlurLightProgram.uniform1f("dist_factor", dist_factor); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); @@ -7179,9 +7178,7 @@ void LLPipeline::renderDeferredLighting() if (count == max_count || 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); gDeferredMultiLightProgram.uniform1f("far_z", far_z); far_z = 0.f; -- cgit v1.3 From e4b502793da09c746d3b0c13782ec9ffb90c54d2 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sun, 21 Nov 2010 02:53:33 -0600 Subject: Fake anti-aliasing for deferred rendering as an alternative to real anti-aliasing. --- .../shaders/class1/deferred/postDeferredF.glsl | 93 ++++++++++++++-------- .../shaders/class2/deferred/edgeF.glsl | 2 - .../shaders/class2/deferred/postDeferredF.glsl | 61 -------------- .../shaders/class2/deferred/postDeferredV.glsl | 19 ----- indra/newview/llviewershadermgr.cpp | 20 ++--- indra/newview/pipeline.cpp | 29 ++++--- 6 files changed, 89 insertions(+), 135 deletions(-) delete mode 100644 indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl delete mode 100644 indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 7e41b07f8a..03c2e63fb1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -10,50 +10,77 @@ #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; -uniform sampler2DRect localLightMap; -uniform sampler2DRect sunLightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D luminanceMap; -uniform sampler2DRect lightMap; +uniform sampler2DRect edgeMap; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D bloomMap; -uniform vec3 lum_quad; -uniform float lum_lod; -uniform vec4 ambient; - -uniform vec3 gi_quad; +uniform float depth_cutoff; +uniform float norm_cutoff; +uniform mat4 inv_proj; uniform vec2 screen_res; + varying vec2 vary_fragcoord; +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + void main() { + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + float depth = getDepth(vary_fragcoord.xy); + vec2 tc = vary_fragcoord.xy; - vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - float luminance = lum.r; - luminance = luminance*lum_quad.y+lum_quad.z; - - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - - float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; - - vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; - gi_col *= diff; - vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); + float sc = 0.75; + + vec2 de; + de.x = (depth-getDepth(tc+vec2(sc, sc))) + (depth-getDepth(tc+vec2(-sc, -sc))); + de.y = (depth-getDepth(tc+vec2(-sc, sc))) + (depth-getDepth(tc+vec2(sc, -sc))); + de /= depth; + de *= de; + de = step(depth_cutoff, de); + + vec2 ne; + vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; + nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm + ne.x = dot(nexnorm, norm); + vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; + neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm + ne.y = dot(neynorm, norm); + + ne = 1.0-ne; + + ne = step(norm_cutoff, ne); + + float edge_weight = clamp(dot(de,de)+dot(ne,ne), 0.0, 1.0); + //edge_weight *= 0.0; + + vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,-1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,-1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(-1,0))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(1,0))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,1))*edge_weight; + diff += texture2DRect(diffuseRect, vary_fragcoord.xy+vec2(0,-1))*edge_weight; - vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; - - - sun_col *= 1.0/min(luminance, 1.0); - gi_col *= 1.0/luminance; - - vec3 col = sun_col.rgb+gi_col+local_col; + diff /= 1.0+edge_weight*8.0; - gl_FragColor.rgb = col.rgb; - col.rgb = max(col.rgb-vec3(1.0,1.0,1.0), vec3(0.0, 0.0, 0.0)); + vec4 blur = texture2DRect(edgeMap, vary_fragcoord.xy); - gl_FragColor.a = 0.0; // max(dot(col.rgb,col.rgb)*lum_quad.x, sun_col.a); + //gl_FragColor = vec4(edge_weight,edge_weight,edge_weight, 1.0); + gl_FragColor = diff + bloom; + //gl_FragColor.r = edge_weight; - //gl_FragColor.rgb = vec3(lum_lod); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl index c9bee13b48..3155f3f929 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -12,8 +12,6 @@ uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; -uniform float gi_dist_cutoff; - varying vec2 vary_fragcoord; uniform float depth_cutoff; diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl deleted file mode 100644 index 3da50eb52a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file postDeferredF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * $/LicenseInfo$ - */ - -#version 120 - -uniform sampler2DRect diffuseRect; -uniform sampler2DRect localLightMap; -uniform sampler2DRect sunLightMap; -uniform sampler2DRect giLightMap; -uniform sampler2D luminanceMap; -uniform sampler2DRect lightMap; - -uniform vec3 gi_lum_quad; -uniform vec3 sun_lum_quad; -uniform vec3 lum_quad; -uniform float lum_lod; -uniform vec4 ambient; - -uniform vec3 gi_quad; - -uniform vec2 screen_res; -varying vec2 vary_fragcoord; - -void main() -{ - vec2 tc = vary_fragcoord.xy; - vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb; - - float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z; - - vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); - - float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g; - - vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; - gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb; - gi_col *= diff; - - vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); - - vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; - - - float sun_lum = 1.0-lum; - sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z; - - float gi_lum = lum; - gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z; - gi_col *= 1.0/gi_lum; - - vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col; - - gl_FragColor.rgb = col.rgb; - gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a); - - //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl deleted file mode 100644 index 12983baa94..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file postDeferredV.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * $/LicenseInfo$ - */ - -#version 120 - -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/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 6231822fe7..a16257940e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1225,6 +1225,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } + if (success) + { + gDeferredPostProgram.mName = "Deferred Post Shader"; + gDeferredPostProgram.mShaderFiles.clear(); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostProgram.createShader(NULL, NULL); + } + if (mVertexShaderLevel[SHADER_DEFERRED] > 1) { if (success) @@ -1240,15 +1250,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (mVertexShaderLevel[SHADER_DEFERRED] > 2) { - if (success) - { - gDeferredPostProgram.mName = "Deferred Post Shader"; - gDeferredPostProgram.mShaderFiles.clear(); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostProgram.createShader(NULL, NULL); - } + if (success) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d1a4575880..4007d9d8f3 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -693,8 +693,9 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) } - if (LLRenderTarget::sUseFBO && gGLManager.mHasFramebufferMultisample && samples > 1) - { + if (LLRenderTarget::sUseFBO && !sRenderDeferred && gGLManager.mHasFramebufferMultisample && samples > 1) + { // DON'T use multisample buffers when rendering deferred -- multisampling doesn't play nice with deferred rendering + //so a post-effect smooths edges in screen space mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); if (LLPipeline::sRenderDeferred) { @@ -6245,12 +6246,18 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) LLVertexBuffer::unbind(); - if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) + if (LLPipeline::sRenderDeferred) { + LLGLSLShader* shader = &gDeferredPostProgram; + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) + { + shader = &gDeferredGIFinalProgram; + } + LLGLDisable blend(GL_BLEND); - bindDeferredShader(gDeferredGIFinalProgram); + bindDeferredShader(*shader); - S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mScreen.bindTexture(0, channel); @@ -6268,7 +6275,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.end(); - unbindDeferredShader(gDeferredGIFinalProgram); + unbindDeferredShader(*shader); } else { @@ -6329,12 +6336,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } - if (LLRenderTarget::sUseFBO) - { //copy depth buffer from mScreen to framebuffer - LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), - 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } gGL.setSceneBlendType(LLRender::BT_ALPHA); -- cgit v1.3 From a6e8026de00248bf6be5cf608bea6c7d94c4e07c Mon Sep 17 00:00:00 2001 From: Tofu Buzzard Date: Wed, 15 Dec 2010 13:40:28 +0000 Subject: CTS-411 edge ghosting in deferred rendering (w/shadows and shadow smoothing enabled) (transplanted from c698ce37c0502597aafc75fcf9c37ff2970b7faf) (transplanted from ae92e806703a0c03ec2ab76d74906c7465285aaf) --- doc/contributions.txt | 1 + .../shaders/class1/deferred/blurLightF.glsl | 27 +++---- .../shaders/class2/deferred/blurLightF.glsl | 83 ---------------------- .../shaders/class2/deferred/blurLightV.glsl | 19 ----- 4 files changed, 15 insertions(+), 115 deletions(-) delete mode 100644 indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl delete mode 100644 indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/doc/contributions.txt b/doc/contributions.txt index 4c59e703ee..b5158b3792 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -750,6 +750,7 @@ Thraxis Epsilon tiamat bingyi CT-246 Tofu Buzzard + CTS-411 STORM-546 TraductoresAnonimos Alter CT-324 diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index ea2df4b51a..ad4d700b99 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -39,43 +39,44 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + vec2 tc = vary_fragcoord.xy; + vec3 norm = texture2DRect(normalMap, tc).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; + vec3 pos = getPosition(tc).xyz; + vec4 ccol = texture2DRect(lightMap, tc).rgba; vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); - dlt /= max(-pos.z*dist_factor, 1.0); vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' vec4 col = defined_weight.xyxx * ccol; - + + // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large + tc += ( (int(tc.x+tc.y)%2 - 0.5) * kern[1].z * dlt * 0.5 ); + for (int i = 1; i < 4; i++) { - vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; + vec2 samptc = tc + kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= 0.003) { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; defined_weight += kern[i].xy; } } for (int i = 1; i < 4; i++) { - vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; + vec2 samptc = tc - kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane if (d*d <= 0.003) { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; defined_weight += kern[i].xy; } } - - col /= defined_weight.xyxx; gl_FragColor = col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl deleted file mode 100644 index ea2df4b51a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file blurLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * $/LicenseInfo$ - */ - -#version 120 - -#extension GL_ARB_texture_rectangle : enable - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect lightMap; - -uniform float dist_factor; -uniform float blur_size; -uniform vec2 delta; -uniform vec3 kern[4]; -uniform float kern_scale; - -varying vec2 vary_fragcoord; - -uniform mat4 inv_proj; -uniform vec2 screen_res; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} - -void main() -{ - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; - norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm - vec3 pos = getPosition(vary_fragcoord.xy).xyz; - vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba; - - vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); - - dlt /= max(-pos.z*dist_factor, 1.0); - - vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec4 col = defined_weight.xyxx * ccol; - - for (int i = 1; i < 4; i++) - { - vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; - float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - if (d*d <= 0.003) - { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; - defined_weight += kern[i].xy; - } - } - for (int i = 1; i < 4; i++) - { - vec2 tc = vary_fragcoord.xy - kern[i].z*dlt; - vec3 samppos = getPosition(tc).xyz; - float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - if (d*d <= 0.003) - { - col += texture2DRect(lightMap, tc)*kern[i].xyxx; - defined_weight += kern[i].xy; - } - } - - - - col /= defined_weight.xyxx; - - gl_FragColor = col; -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl deleted file mode 100644 index c2d05c601a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file blurLightF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * $/LicenseInfo$ - */ - -#version 120 - -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; -} -- cgit v1.3 From 1426bcbae4ff6fad8383b857a6697abcbe243116 Mon Sep 17 00:00:00 2001 From: Tofu Buzzard Date: Sun, 16 Jan 2011 13:47:15 +0000 Subject: FIX VWR-24509 Fix SSAO speckling artifacts at distance, re-enable distant SSAO followup - remove the distance limiting, re-enabling distant SSAO. (transplanted from d11eafacb2609537905718fa559e81b53e6740f8) --- .../shaders/class1/deferred/sunLightSSAOF.glsl | 74 ++++++++++----------- .../shaders/class2/deferred/sunLightSSAOF.glsl | 76 ++++++++++------------ 2 files changed, 67 insertions(+), 83 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index 1e0693d19f..25ff958107 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -53,57 +53,49 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) { float ret = 1.0; - float dist = dot(pos.xyz,pos.xyz); - - if (dist < 64.0*64.0) - { - 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 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; + 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 angle_hidden = 0.0; + int points = 0; - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + 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 = getPosition(samppos_screen).xyz; + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); + 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) + // 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); + 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); - } + // '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); + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - ret = (1.0 - (float(points != 0) * angle_hidden)); - ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); - } + ret = (1.0 - (float(points != 0) * angle_hidden)); return min(ret, 1.0); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index cc921f23d7..08b16d787f 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -62,58 +62,50 @@ vec4 getPosition(vec2 pos_screen) float calcAmbientOcclusion(vec4 pos, vec3 norm) { float ret = 1.0; - - float dist = dot(pos.xyz,pos.xyz); - - if (dist < 64.0*64.0) - { - 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; + 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 angle_hidden = 0.0; + int points = 0; - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + 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 = getPosition(samppos_screen).xyz; + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); + 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) + // 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); + 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); - } + // '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); + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - ret = (1.0 - (float(points != 0) * angle_hidden)); - ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); - } + ret = (1.0 - (float(points != 0) * angle_hidden)); return min(ret, 1.0); } -- cgit v1.3 From ef0b1b1564c469b526d0a62d8e4412a26571fb4f Mon Sep 17 00:00:00 2001 From: Tofu Buzzard Date: Sat, 22 Jan 2011 00:56:18 +0000 Subject: remove some unused depth samplings. (transplanted from a38a7ea07c52aafbd4305f96d715201a35d86726) --- indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl | 3 --- indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl | 3 --- 2 files changed, 6 deletions(-) (limited to 'indra/newview/app_settings/shaders/class2') diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index b08c5dd295..28a38d4390 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -10,7 +10,6 @@ #extension GL_ARB_texture_rectangle : enable uniform sampler2D diffuseMap; -uniform sampler2D noiseMap; uniform sampler2DRect depthMap; uniform mat4 shadow_matrix[6]; @@ -45,8 +44,6 @@ void main() vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = getPosition(frag).xyz; - vec4 pos = vec4(vary_position, 1.0); vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 32aab152a3..1dd29bfc70 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -14,7 +14,6 @@ uniform sampler2DRectShadow shadowMap0; uniform sampler2DRectShadow shadowMap1; uniform sampler2DRectShadow shadowMap2; uniform sampler2DRectShadow shadowMap3; -uniform sampler2D noiseMap; uniform sampler2DRect depthMap; uniform mat4 shadow_matrix[6]; @@ -70,8 +69,6 @@ void main() vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = getPosition(frag).xyz; - float shadow = 1.0; vec4 pos = vec4(vary_position, 1.0); -- cgit v1.3