diff --git a/Source/Scene/GroundPolylinePrimitive.js b/Source/Scene/GroundPolylinePrimitive.js index 40b844fb24f5..a595d4a65529 100644 --- a/Source/Scene/GroundPolylinePrimitive.js +++ b/Source/Scene/GroundPolylinePrimitive.js @@ -405,10 +405,10 @@ define([ // Check for use of v_width and v_polylineAngle in material shader // to determine whether these varyings should be active in the vertex shader. - if (materialShaderSource.search(/varying\s+float\s+v_polylineAngle;/g) === -1) { + if (materialShaderSource.search(/varying\s+float\s+v_polylineAngle;/g) !== -1) { vsDefines.push('ANGLE_VARYING'); } - if (materialShaderSource.search(/varying\s+float\s+v_width;/g) === -1) { + if (materialShaderSource.search(/varying\s+float\s+v_width;/g) !== -1) { vsDefines.push('WIDTH_VARYING'); } } else { @@ -455,7 +455,7 @@ define([ var colorProgramMorph = context.shaderCache.getDerivedShaderProgram(groundPolylinePrimitive._sp, 'MorphColor'); if (!defined(colorProgramMorph)) { var vsColorMorph = new ShaderSource({ - defines : vsDefines, + defines : vsDefines.concat(['MAX_TERRAIN_HEIGHT ' + ApproximateTerrainHeights._defaultMaxTerrainHeight.toFixed(1)]), sources : [vsMorph] }); diff --git a/Source/Shaders/PolylineShadowVolumeFS.glsl b/Source/Shaders/PolylineShadowVolumeFS.glsl index ce583d3da4cd..6ef10480d863 100644 --- a/Source/Shaders/PolylineShadowVolumeFS.glsl +++ b/Source/Shaders/PolylineShadowVolumeFS.glsl @@ -10,7 +10,7 @@ varying vec4 v_color; void main(void) { - float logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)); + float logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw))); vec3 ecStart = vec3(v_endEcAndStartEcX.w, v_texcoordNormalizationAndStartEcYZ.zw); // Discard for sky diff --git a/Source/Shaders/PolylineShadowVolumeMorphVS.glsl b/Source/Shaders/PolylineShadowVolumeMorphVS.glsl index f3fd713fefff..29e82a6b73bf 100644 --- a/Source/Shaders/PolylineShadowVolumeMorphVS.glsl +++ b/Source/Shaders/PolylineShadowVolumeMorphVS.glsl @@ -42,56 +42,64 @@ void main() vec4 posRelativeToEye2D = czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw)); vec4 posRelativeToEye3D = czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz); vec4 posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime); - vec3 ecPos2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz; - vec3 ecPos3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz; - vec3 ecStart = (czm_modelViewRelativeToEye * posRelativeToEye).xyz; + vec3 posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz; + vec3 posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz; + vec3 startEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz; // Start plane vec4 startPlane2D; vec4 startPlane3D; startPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy); startPlane3D.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz; - startPlane2D.w = -dot(startPlane2D.xyz, ecPos2D); - startPlane3D.w = -dot(startPlane3D.xyz, ecPos3D); + startPlane2D.w = -dot(startPlane2D.xyz, posEc2D); + startPlane3D.w = -dot(startPlane3D.xyz, posEc3D); // Right plane vec4 rightPlane2D; vec4 rightPlane3D; rightPlane2D.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw); rightPlane3D.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz; - rightPlane2D.w = -dot(rightPlane2D.xyz, ecPos2D); - rightPlane3D.w = -dot(rightPlane3D.xyz, ecPos3D); + rightPlane2D.w = -dot(rightPlane2D.xyz, posEc2D); + rightPlane3D.w = -dot(rightPlane3D.xyz, posEc3D); // End position posRelativeToEye2D = posRelativeToEye2D + vec4(0.0, offsetAndRight2D.xy, 0.0); posRelativeToEye3D = posRelativeToEye3D + vec4(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w, 0.0); posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime); - ecPos2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz; - ecPos3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz; - vec3 ecEnd = (czm_modelViewRelativeToEye * posRelativeToEye).xyz; + posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz; + posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz; + vec3 endEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz; + vec3 forwardEc3D = czm_normal * normalize(vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w)); + vec3 forwardEc2D = czm_normal * normalize(vec3(0.0, offsetAndRight2D.xy)); // End plane vec4 endPlane2D; vec4 endPlane3D; endPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw); endPlane3D.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz; - endPlane2D.w = -dot(endPlane2D.xyz, ecPos2D); - endPlane3D.w = -dot(endPlane3D.xyz, ecPos3D); + endPlane2D.w = -dot(endPlane2D.xyz, posEc2D); + endPlane3D.w = -dot(endPlane3D.xyz, posEc3D); // Forward direction - v_forwardDirectionEC = normalize(ecEnd - ecStart); + v_forwardDirectionEC = normalize(endEC - startEC); - v_texcoordNormalization_and_halfWidth.xy = mix( - vec2(abs(texcoordNormalization2D.x), texcoordNormalization2D.y), - vec2(abs(endNormalAndTextureCoordinateNormalizationX.w), rightNormalAndTextureCoordinateNormalizationY.w), czm_morphTime); + vec2 cleanTexcoordNormalization2D; + cleanTexcoordNormalization2D.x = abs(texcoordNormalization2D.x); + cleanTexcoordNormalization2D.y = czm_branchFreeTernary(texcoordNormalization2D.y > 1.0, 0.0, abs(texcoordNormalization2D.y)); + vec2 cleanTexcoordNormalization3D; + cleanTexcoordNormalization3D.x = abs(endNormalAndTextureCoordinateNormalizationX.w); + cleanTexcoordNormalization3D.y = rightNormalAndTextureCoordinateNormalizationY.w; + cleanTexcoordNormalization3D.y = czm_branchFreeTernary(cleanTexcoordNormalization3D.y > 1.0, 0.0, abs(cleanTexcoordNormalization3D.y)); + + v_texcoordNormalization_and_halfWidth.xy = mix(cleanTexcoordNormalization2D, cleanTexcoordNormalization3D, czm_morphTime); #ifdef PER_INSTANCE_COLOR v_color = czm_batchTable_color(batchId); #else // PER_INSTANCE_COLOR // For computing texture coordinates - v_alignedPlaneDistances.x = -dot(v_forwardDirectionEC, ecStart); - v_alignedPlaneDistances.y = -dot(-v_forwardDirectionEC, ecEnd); + v_alignedPlaneDistances.x = -dot(v_forwardDirectionEC, startEC); + v_alignedPlaneDistances.y = -dot(-v_forwardDirectionEC, endEC); #endif // PER_INSTANCE_COLOR #ifdef WIDTH_VARYING @@ -111,29 +119,41 @@ void main() // ****** 3D ****** // Check distance to the end plane and start plane, pick the plane that is closer - vec4 positionEC3D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position3DHigh, position3DLow); // w = 1.0, see czm_computePosition - float absStartPlaneDistance = abs(czm_planeDistance(startPlane3D, positionEC3D.xyz)); - float absEndPlaneDistance = abs(czm_planeDistance(endPlane3D, positionEC3D.xyz)); + vec4 positionEc3D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position3DHigh, position3DLow); // w = 1.0, see czm_computePosition + float absStartPlaneDistance = abs(czm_planeDistance(startPlane3D, positionEc3D.xyz)); + float absEndPlaneDistance = abs(czm_planeDistance(endPlane3D, positionEc3D.xyz)); vec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane3D.xyz, endPlane3D.xyz); vec3 upOrDown = normalize(cross(rightPlane3D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane. vec3 normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too. + // Nudge the top vertex upwards to prevent flickering + vec3 geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc3D)); + geodeticSurfaceNormal *= float(0.0 <= rightNormalAndTextureCoordinateNormalizationY.w && rightNormalAndTextureCoordinateNormalizationY.w <= 1.0); + geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT; + positionEc3D.xyz += geodeticSurfaceNormal; + // Determine if this vertex is on the "left" or "right" normalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w); // A "perfect" implementation would push along normals according to the angle against forward. // In practice, just pushing the normal out by halfWidth is sufficient for morph views. - positionEC3D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEC3D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera) + positionEc3D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc3D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera) // ****** 2D ****** // Check distance to the end plane and start plane, pick the plane that is closer - vec4 positionEC2D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); // w = 1.0, see czm_computePosition - absStartPlaneDistance = abs(czm_planeDistance(startPlane2D, positionEC2D.xyz)); - absEndPlaneDistance = abs(czm_planeDistance(endPlane2D, positionEC2D.xyz)); + vec4 positionEc2D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy); // w = 1.0, see czm_computePosition + absStartPlaneDistance = abs(czm_planeDistance(startPlane2D, positionEc2D.xyz)); + absEndPlaneDistance = abs(czm_planeDistance(endPlane2D, positionEc2D.xyz)); planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane2D.xyz, endPlane2D.xyz); upOrDown = normalize(cross(rightPlane2D.xyz, planeDirection)); // Points "up" for start plane, "down" at end plane. normalEC = normalize(cross(planeDirection, upOrDown)); // In practice, the opposite seems to work too. + // Nudge the top vertex upwards to prevent flickering + geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc2D)); + geodeticSurfaceNormal *= float(0.0 <= texcoordNormalization2D.y && texcoordNormalization2D.y <= 1.0); + geodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT; + positionEc2D.xyz += geodeticSurfaceNormal; + // Determine if this vertex is on the "left" or "right" normalEC *= sign(texcoordNormalization2D.x); #ifndef PER_INSTANCE_COLOR @@ -143,11 +163,10 @@ void main() // A "perfect" implementation would push along normals according to the angle against forward. // In practice, just pushing the normal out by halfWidth is sufficient for morph views. - positionEC2D.xyz -= normalEC; // undo the unit length push - positionEC2D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEC2D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera) + positionEc2D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc2D)) * normalEC; // prevent artifacts when czm_metersPerPixel is negative (behind camera) // Blend for actual position - gl_Position = czm_projection * mix(positionEC2D, positionEC3D, czm_morphTime); + gl_Position = czm_projection * mix(positionEc2D, positionEc3D, czm_morphTime); #ifdef ANGLE_VARYING // Approximate relative screen space direction of the line.