diff --git a/package.json b/package.json index 316192b7..c12f586d 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vts-browser-js", - "version": "2.15.7", + "version": "2.15.8", "description": "JavaScript WebGL 3D maps rendering engine", "main": "src/browser/index.js", "scripts": { diff --git a/src/core/core.js b/src/core/core.js index bd2e6d5f..317cb0bf 100755 --- a/src/core/core.js +++ b/src/core/core.js @@ -69,6 +69,7 @@ var Core = function(element, config, coreInterface) { mapFog : true, mapNoTextures: false, mapMetricUnits : !(lang == 'en' || lang.indexOf('en-') == 0), + rendererAnisotropic : 0, rendererAntialiasing : true, rendererAllowScreenshots : false, inspector : true, @@ -471,6 +472,7 @@ Core.prototype.getConfigParam = function(key) { Core.prototype.setRendererConfigParam = function(key, value) { switch (key) { + case 'rendererAnisotropic': this.config.rendererAnisotropic = utils.validateNumber(value, -1, 2048, 0); break; case 'rendererAntialiasing': this.config.rendererAntialiasing = utils.validateBool(value, true); break; case 'rendererAllowScreenshots': this.config.rendererAllowScreenshots = utils.validateBool(value, false); break; } @@ -479,6 +481,7 @@ Core.prototype.setRendererConfigParam = function(key, value) { Core.prototype.getRendererConfigParam = function(key) { switch (key) { + case 'rendererAnisotropic': return this.config.rendererAnisotropic; case 'rendererAntialiasing': return this.config.rendererAntialiasing; case 'rendererAllowScreenshots': return this.config.rendererAllowScreenshots; } @@ -491,7 +494,7 @@ string getCoreVersion() */ function getCoreVersion(full) { - return (full ? 'Core: ' : '') + '2.15.7'; + return (full ? 'Core: ' : '') + '2.15.8'; } diff --git a/src/core/map/draw-tiles.js b/src/core/map/draw-tiles.js index 274455d1..7c5e156d 100755 --- a/src/core/map/draw-tiles.js +++ b/src/core/map/draw-tiles.js @@ -52,6 +52,8 @@ MapDrawTiles.prototype.drawSurfaceTile = function(tile, node, cameraPos, pixelSi } return true; } + + //tile.renderHappen = false; if (!preventRedener) { this.stats.renderedLods[tile.id[0]]++; @@ -116,7 +118,7 @@ MapDrawTiles.prototype.drawSurfaceTile = function(tile, node, cameraPos, pixelSi } else { if (!preventRedener && tile.lastRenderState) { var channel = this.draw.drawChannel; - this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); + this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); this.map.applyCredits(tile); return true; } @@ -141,35 +143,37 @@ MapDrawTiles.prototype.drawMeshTile = function(tile, node, cameraPos, pixelSize, var channel = draw.drawChannel; var ret = false; + //we have commnad so we can draw them if (tile.drawCommands[channel].length > 0 && this.draw.areDrawCommandsReady(tile.drawCommands[channel], priority, preventLoad, doNotCheckGpu)) { if (!preventRedener) { - draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority); + draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority, null, tile); this.map.applyCredits(tile); } tile.lastRenderState = null; return true; - } else if (tile.lastRenderState){ + } else if (tile.lastRenderState){ //we do not have cammnds or command are not redy yet, so we can draw last state if present and ready - if (tile.surfaceMesh.isReady(true, priority, doNotCheckGpu)) { - if (tile.drawCommands[channel].length > 0) { + if (tile.surfaceMesh.isReady(true, priority, doNotCheckGpu) && tile.drawCommands[channel].length > 0) { + if (this.draw.areDrawCommandsReady(tile.lastRenderState.drawCommands[channel], priority, preventLoad, doNotCheckGpu)) { if (!preventRedener) { - draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); + draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); this.map.applyCredits(tile); } - return true; - } + return true; // commands are generated so we can return from function here + } // else ret = false } else { - if (!preventRedener) { - draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); - this.map.applyCredits(tile); + if (this.draw.areDrawCommandsReady(tile.lastRenderState.drawCommands[channel], priority, preventLoad, doNotCheckGpu)) { + if (!preventRedener) { + draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); + this.map.applyCredits(tile); + } + ret = true; } - ret = true; } } - - if (tile.drawCommands[channel].length > 0) { + + if (tile.drawCommands[channel].length > 0) { //command are generated but not ready, we can return from the function if (this.config.mapHeightfiledWhenUnloaded && !preventRedener) { - //node.drawPlane(cameraPos, tile); tile.drawGrid(cameraPos); return false; } else { @@ -177,6 +181,8 @@ MapDrawTiles.prototype.drawMeshTile = function(tile, node, cameraPos, pixelSize, } } + // information about support for extarnal or internal textures are present in the mesh, + // so we have to wait until is mesh ready and then we can generate commands if (tile.surfaceMesh.isReady(preventLoad, priority, doNotCheckGpu) && !preventLoad) { var submeshes = tile.surfaceMesh.submeshes; @@ -447,6 +453,20 @@ MapDrawTiles.prototype.drawMeshTile = function(tile, node, cameraPos, pixelSize, } + if (surface.pipeline > VTS_PIPELINE_BASIC) { + this.updateTileHmap(tile, node); + + for (j = 0; j < 2; j++) { + var commands = tile.drawCommands[j]; + for (i = 0, li = commands.length; i < li; i++) { + if (commands[i].type == VTS_DRAWCOMMAND_SUBMESH) { + commands[i].pipeline = surface.pipeline; + commands[i].hmap = tile.hmap; + } + } + } + } + if (tile.resetDrawCommands) { return false; } @@ -458,18 +478,20 @@ MapDrawTiles.prototype.drawMeshTile = function(tile, node, cameraPos, pixelSize, } if (!preventRedener) { - draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority); + draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority, null, tile); this.map.applyCredits(tile); } tile.lastRenderState = null; ret = true; } else if (tile.lastRenderState) { - if (!preventRedener) { - draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); - this.map.applyCredits(tile); - } - ret = true; + if (this.draw.areDrawCommandsReady(tile.lastRenderState.drawCommands[channel], priority, preventLoad, doNotCheckGpu)) { + if (!preventRedener) { + draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); + this.map.applyCredits(tile); + } + ret = true; + } //else ret = false } else { if (this.config.mapHeightfiledWhenUnloaded && !preventRedener) { //node.drawPlane(cameraPos, tile); @@ -480,12 +502,11 @@ MapDrawTiles.prototype.drawMeshTile = function(tile, node, cameraPos, pixelSize, } else { - if (this.config.mapHeightfiledWhenUnloaded && !preventRedener) { + if (!tile.lastRenderState && this.config.mapHeightfiledWhenUnloaded && !preventRedener) { //node.drawPlane(cameraPos, tile); tile.drawGrid(cameraPos); ret = !(tile.drawCommands[channel].length > 0); - } - + } } return ret; @@ -539,7 +560,7 @@ MapDrawTiles.prototype.drawGeodataTile = function(tile, node, cameraPos, pixelSi if (tile.drawCommands[channel].length > 0 && this.draw.areDrawCommandsReady(tile.drawCommands[channel], priority, preventLoad, doNotCheckGpu)) { if (!preventRedener) { - this.draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority); + this.draw.processDrawCommands(cameraPos, tile.drawCommands[channel], priority, null, tile); this.map.applyCredits(tile); } tile.lastRenderState = null; @@ -551,14 +572,14 @@ MapDrawTiles.prototype.drawGeodataTile = function(tile, node, cameraPos, pixelSi if (tile.surfaceGeodata.isReady(true, priority, doNotCheckGpu) { if (tile.drawCommands[channel].length > 0) { if (!preventRedener) { - this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); + this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); this.applyCredits(tile); } return; } } else { if (!preventRedener) { - this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true); + this.draw.processDrawCommands(cameraPos, tile.lastRenderState.drawCommands[channel], priority, true, tile); this.applyCredits(tile); } } @@ -594,12 +615,14 @@ MapDrawTiles.prototype.drawGeodataTile = function(tile, node, cameraPos, pixelSi }; - -/*MapDrawTiles.prototype.updateTileBoundsDirectly = function(preventLoad, priority) { - if (tile.surfaceMesh.isReady(preventLoad, priority) && !preventLoad) { - this.updateTileBounds(tile, tile.surfaceMesh.submeshes); +MapDrawTiles.prototype.updateTileHmap = function(tile, node) { + if (node && node.hasNavtile() && tile.surface) { + var path = tile.surface.getNavUrl(tile.id); + this.hmap = tile.resources.getTexture(path, null, null, null, tile, true); + } else { + this.hmap = this.renderer.blackTexture; } -};*/ +}; MapDrawTiles.prototype.updateTileBounds = function(tile, submeshes) { diff --git a/src/core/map/draw.js b/src/core/map/draw.js index 4e02a786..ad1af338 100755 --- a/src/core/map/draw.js +++ b/src/core/map/draw.js @@ -610,11 +610,11 @@ MapDraw.prototype.areDrawCommandsReady = function(commands, priority, doNotLoad, }; -MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, doNotLoad) { +MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, doNotLoad, tile) { if (commands.length > 0) { this.drawTileCounter++; } - + for (var i = 0, li = commands.length; i < li; i++) { var command = commands[i]; @@ -625,7 +625,7 @@ MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, case VTS_DRAWCOMMAND_SUBMESH: var mesh = command.mesh; - var texture = command.texture; + var texture = command.texture, hmap; var meshReady = (mesh && mesh.isReady(doNotLoad, priority)), textureReady; @@ -633,7 +633,17 @@ MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, textureReady = true; texture = null; } else { - textureReady = (!texture || (texture && texture.isReady(doNotLoad, priority))); + textureReady = (!texture || (texture && texture.isReady(doNotLoad, priority))); + } + + var pipeline = command.pipeline; + + if (pipeline) { + //hmap = command.hmap; + //textureReady = (textureReady && (hmap && hmap.isReady(doNotLoad, priority))); + + tile.drawHmapTile(cameraPos, null, null, pipeline); + return; } if (meshReady && textureReady) { @@ -653,12 +663,10 @@ MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, } mesh.drawSubmesh(cameraPos, command.submesh, texture, material, command.alpha); } else { + //tile.renderHappen = true; mesh.drawSubmesh(cameraPos, command.submesh, texture, command.material, command.alpha); } - } else { - //i = i; - //this should not happen } break; @@ -666,6 +674,7 @@ MapDraw.prototype.processDrawCommands = function(cameraPos, commands, priority, case VTS_DRAWCOMMAND_GEODATA: var geodataView = command.geodataView; + //tile.renderHappen = true; if (geodataView && geodataView.isReady(doNotLoad, priority, true)) { geodataView.draw(cameraPos); diff --git a/src/core/map/surface-tile.js b/src/core/map/surface-tile.js index 436d9d27..29dd8fa2 100755 --- a/src/core/map/surface-tile.js +++ b/src/core/map/surface-tile.js @@ -63,6 +63,7 @@ var MapSurfaceTile = function(map, parent, id) { this.boundTextures = {}; this.updateBounds = true; + this.hmap = null; this.heightMap = null; this.drawCommands = [[], [], []]; this.imageryCredits = {}; @@ -138,6 +139,7 @@ MapSurfaceTile.prototype.kill = function() { this.lastState = null; this.lastRenderState = null; + this.hmap = null; this.heightMap = null; this.drawCommands = [[], [], []]; this.imageryCredits = {}; @@ -289,10 +291,6 @@ MapSurfaceTile.prototype.isMetanodeReady = function(tree, priority, preventLoad) this.viewSwitched(); this.viewCoutner = this.map.viewCounter; this.map.markDirty(); - - if (this.lastRenderState) { - this.lastRenderState = this.lastRenderState; //debug - } } if (!preventLoad) { @@ -1354,6 +1352,239 @@ MapSurfaceTile.prototype.drawGrid = function(cameraPos, divNode, angle) { }; +MapSurfaceTile.prototype.drawHmapTile = function(cameraPos, divNode, angle, pipeline) { + if ((this.texelSize == Number.POSITIVE_INFINITY || this.texelSize > 4.4) && this.metanode && this.metanode.hasChildren()) { + return; + } + + if (!this.metanode) { + return; + } + + var map = this.map, node, ll, ur, res; + + if (divNode) { + node = divNode[0]; + ll = divNode[1][0]; + ur = divNode[1][1]; + } else { + res = map.measure.getSpatialDivisionNodeAndExtents(this.id); + node = res[0]; + ll = res[1][0]; + ur = res[1][1]; + } + + var middle = [(ur[0] + ll[0])* 0.5, (ur[1] + ll[1])* 0.5]; + var hasPoles = map.referenceFrame.hasPoles; + angle = angle || this.metanode.diskAngle2; + + if ((hasPoles && !node.isPole) && Math.acos(angle) > Math.PI*0.1) { + angle = Math.cos(Math.acos(angle) * 0.5); + + this.drawHmapTile(cameraPos, [node, [ [ll[0], ll[1]], [middle[0], middle[1]] ] ], angle); + this.drawHmapTile(cameraPos, [node, [ [middle[0], ll[1]], [ur[0], middle[1]] ] ], angle); + + this.drawHmapTile(cameraPos, [node, [ [ll[0], middle[1]], [middle[0], ur[1]] ] ], angle); + this.drawHmapTile(cameraPos, [node, [ [middle[0], middle[1]], [ur[0], ur[1]] ] ], angle); + + return; + } + + var desiredSamplesPerViewExtent = 5; + var nodeExtent = node.extents.ur[1] - node.extents.ll[1]; + var viewExtent = this.distance ;//* 0.1; + var lod = Math.log((desiredSamplesPerViewExtent * nodeExtent) / viewExtent) / map.log2; + lod = Math.max(0,lod - 8 + node.id[0]); + + var h, factor, prog, draw = map.draw; + + var sx = cameraPos[0]; + var sx = cameraPos[0]; + var sy = cameraPos[1]; + var sz = cameraPos[2]; + var buffer = draw.planeBuffer; + var gridPoints = this.gridPoints; + var useSurrogatez = map.config.mapGridSurrogatez; + + if (!gridPoints) { + + h = this.metanode.minZ; + var n1 = node.getPhysicalCoords([ur[0], ur[1], h], true); + var n2 = node.getPhysicalCoords([ur[0], ll[1], h], true); + var n3 = node.getPhysicalCoords([ll[0], ll[1], h], true); + var n4 = node.getPhysicalCoords([ll[0], ur[1], h], true); + var mtop = node.getPhysicalCoords([middle[0], ur[1], h], true); + var mbottom = node.getPhysicalCoords([middle[0], ll[1], h], true); + var mleft = node.getPhysicalCoords([ll[0], middle[1], h], true); + var mright = node.getPhysicalCoords([ur[0], middle[1], h], true); + + middle[2] = h; + middle = node.getPhysicalCoords(middle, true); + + if (!divNode) { + + var gridPoints = [ + n4[0], n4[1], n4[2], + mtop[0], mtop[1], mtop[2], + n1[0], n1[1], n1[2], + + mleft[0], mleft[1], mleft[2], + middle[0], middle[1], middle[2], + mright[0], mright[1], mright[2], + + n3[0], n3[1], n3[2], + mbottom[0], mbottom[1], mbottom[2], + n2[0], n2[1], n2[2] + ]; + + this.gridPoints = gridPoints; + + } else { + buffer[0] = n4[0] - sx; + buffer[1] = n4[1] - sy; + buffer[2] = n4[2] - sz; + + buffer[3] = mtop[0] - sx; + buffer[4] = mtop[1] - sy; + buffer[5] = mtop[2] - sz; + + buffer[6] = n1[0] - sx; + buffer[7] = n1[1] - sy; + buffer[8] = n1[2] - sz; + + buffer[9] = mleft[0] - sx; + buffer[10] = mleft[1] - sy; + buffer[11] = mleft[2] - sz; + + buffer[12] = middle[0] - sx; + buffer[13] = middle[1] - sy; + buffer[14] = middle[2] - sz; + + buffer[15] = mright[0] - sx; + buffer[16] = mright[1] - sy; + buffer[17] = mright[2] - sz; + + buffer[18] = n3[0] - sx; + buffer[19] = n3[1] - sy; + buffer[20] = n3[2] - sz; + + buffer[21] = mbottom[0] - sx; + buffer[22] = mbottom[1] - sy; + buffer[23] = mbottom[2] - sz; + + buffer[24] = n2[0] - sx; + buffer[25] = n2[1] - sy; + buffer[26] = n2[2] - sz; + } + } + + var renderer = map.renderer; + var mv = renderer.camera.getModelviewMatrix(); + var proj = renderer.camera.getProjectionMatrix(); + + if (gridPoints) { + buffer[0] = gridPoints[0] - sx; + buffer[1] = gridPoints[1] - sy; + buffer[2] = gridPoints[2] - sz; + + buffer[3] = gridPoints[3] - sx; + buffer[4] = gridPoints[4] - sy; + buffer[5] = gridPoints[5] - sz; + + buffer[6] = gridPoints[6] - sx; + buffer[7] = gridPoints[7] - sy; + buffer[8] = gridPoints[8] - sz; + + buffer[9] = gridPoints[9] - sx; + buffer[10] = gridPoints[10] - sy; + buffer[11] = gridPoints[11] - sz; + + buffer[12] = gridPoints[12] - sx; + buffer[13] = gridPoints[13] - sy; + buffer[14] = gridPoints[14] - sz; + + buffer[15] = gridPoints[15] - sx; + buffer[16] = gridPoints[16] - sy; + buffer[17] = gridPoints[17] - sz; + + buffer[18] = gridPoints[18] - sx; + buffer[19] = gridPoints[19] - sy; + buffer[20] = gridPoints[20] - sz; + + buffer[21] = gridPoints[21] - sx; + buffer[22] = gridPoints[22] - sy; + buffer[23] = gridPoints[23] - sz; + + buffer[24] = gridPoints[24] - sx; + buffer[25] = gridPoints[25] - sy; + buffer[26] = gridPoints[26] - sz; + } + + if (hasPoles && !map.poleRadius && node.id[0] == 1 && !node.isPole) { + var p = node.getPhysicalCoords([node.extents.ur[0], node.extents.ur[1], 0]); + map.poleRadius = Math.sqrt(p[0]*p[0]+p[1]*p[1]); + map.poleRadiusFactor = 8 * Math.pow(2.0, 552058 / map.poleRadius); + } + + factor = 1; + + if (hasPoles && node.isPole) { + factor = map.poleRadiusFactor; + prog = renderer.progPlane2; + renderer.gpu.useProgram(prog, ['aPosition', 'aTexCoord']); + prog.setVec4('uParams4', [-sx, -sy, map.poleRadius, 0]); + } else { + prog = renderer.progHmapPlane; + renderer.gpu.useProgram(prog, ['aPosition', 'aTexCoord']); + } + + prog.setMat4('uMV', mv); + prog.setMat4('uProj', proj); + prog.setFloatArray('uPoints', buffer); + + /* + var lx = (ur[0] - ll[0]); + var ly = (ll[1] - ur[1]); + var px = (ll[0] - node.extents.ll[0]) / lx; + var py = (ur[1] - node.extents.ll[1]) / ly; + + var llx = (node.extents.ur[0] - node.extents.ll[0]) / lx; + var lly = (node.extents.ur[1] - node.extents.ll[1]) / ly; + + px = px / llx; + py = py / lly; + llx = 1.0/llx; + lly = 1.0/lly; + + llx *= step1; + lly *= step1; + px *= step1; + py *= step1; + */ + + var step1 = node.gridStep1 * factor; + + var lx = 1.0 / (ur[0] - ll[0]); + var ly = 1.0 / (ll[1] - ur[1]); + var llx = step1 / ((node.extents.ur[0] - node.extents.ll[0]) * lx); + var lly = step1 / ((node.extents.ur[1] - node.extents.ll[1]) * ly); + var px = (ll[0] - node.extents.ll[0]) * lx * llx; + var py = (ur[1] - node.extents.ll[1]) * ly * lly; + + prog.setVec4('uParams', [step1 * factor, draw.fogDensity, 1/15, node.gridStep2 * factor]); + prog.setVec4('uParams3', [(py - Math.floor(py)), (px - Math.floor(px)), lly, llx]); + prog.setVec4('uParams2', [0, 0, node.gridBlend, 0]); + prog.setVec4('uFogColor', draw.atmoColor); + + renderer.gpu.bindTexture(renderer.heightmapTexture); + + //draw bbox + renderer.planeMesh.draw(prog, 'aPosition', 'aTexCoord'); + + this.map.stats.drawnFaces += renderer.planeMesh.polygons; +}; + + export default MapSurfaceTile; diff --git a/src/core/map/surface.js b/src/core/map/surface.js index 9d16e24b..d24acd8e 100755 --- a/src/core/map/surface.js +++ b/src/core/map/surface.js @@ -85,6 +85,10 @@ MapSurface.prototype.parseJson = function(json) { this.metaBinaryOrder = json['metaBinaryOrder'] || 1; this.metaUrl = this.processUrl(json['metaUrl'], ''); this.navUrl = this.processUrl(json['navUrl'], ''); + this.hmapUrl = this.processUrl(json['hmapUrl'], json['navUrl']); + //this.cmapUrl = this.processUrl(json['cmapUrl'], ''); + //this.pipeline = json['pipeline'] || VTS_PIPELINE_HMAP;//VTS_PIPELINE_BASIC; + this.pipeline = json['pipeline'] || VTS_PIPELINE_BASIC; this.navDelta = json['navDelta'] || 1; this.meshUrl = this.processUrl(json['meshUrl'], ''); this.textureUrl = this.processUrl(json['textureUrl'], ''); diff --git a/src/core/renderer/gpu/device.js b/src/core/renderer/gpu/device.js index 48edf9cd..995144cd 100755 --- a/src/core/renderer/gpu/device.js +++ b/src/core/renderer/gpu/device.js @@ -1,6 +1,6 @@ -var GpuDevice = function(renderer, div, size, keepFrameBuffer, antialias) { +var GpuDevice = function(renderer, div, size, keepFrameBuffer, antialias, aniso) { this.renderer = renderer; this.div = div; this.canvas = null; @@ -18,50 +18,78 @@ var GpuDevice = function(renderer, div, size, keepFrameBuffer, antialias) { this.keepFrameBuffer = (keepFrameBuffer == null) ? false : keepFrameBuffer; this.antialias = antialias ? true : false; + this.anisoLevel = aniso; }; GpuDevice.prototype.init = function() { - this.canvas = document.createElement('canvas'); + var canvas = document.createElement('canvas'); - if (this.canvas == null) { + if (canvas == null) { //canvas not supported return; } - this.canvas.width = this.curSize[0]; - this.canvas.height = this.curSize[1]; - this.canvas.style.display = 'block'; + this.canvas = canvas; - if (this.canvas.getContext == null) { + canvas.width = this.curSize[0]; + canvas.height = this.curSize[1]; + canvas.style.display = 'block'; + + if (canvas.getContext == null) { //canvas not supported return; } + var gl; + try { - this.gl = this.canvas.getContext('webgl', {preserveDrawingBuffer: this.keepFrameBuffer, antialias: this.antialias, stencil: true}) || this.canvas.getContext('experimental-webgl', {preserveDrawingBuffer: this.keepFrameBuffer}); + gl = canvas.getContext('webgl', {preserveDrawingBuffer: this.keepFrameBuffer, antialias: this.antialias, stencil: true}) || canvas.getContext('experimental-webgl', {preserveDrawingBuffer: this.keepFrameBuffer}); } catch(e) { //webgl not supported } - if (!this.gl) { + if (!gl) { //webgl not supported return; } - this.gl.getExtension('OES_standard_derivatives'); + this.gl = gl; - this.div.appendChild(this.canvas); + gl.getExtension('OES_standard_derivatives'); - this.gl.viewportWidth = this.canvas.width; - this.gl.viewportHeight = this.canvas.height; + this.anisoExt = ( + gl.getExtension('EXT_texture_filter_anisotropic') || + gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || + gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') + ); - this.gl.clearColor(0.0, 0.0, 0.0, 1.0); - this.gl.enable(this.gl.DEPTH_TEST); + if (this.anisoExt) { + this.maxAniso = gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); + + if (this.anisoLevel) { + if (this.anisoLevel == -1) { + this.anisoLevel = this.maxAniso; + } else { + this.anisoLevel = Math.min(this.anisoLevel, this.maxAniso); + } + } + } else { + this.maxAniso = 0; + this.anisoLevel = 0; + } + + this.div.appendChild(canvas); + + gl.viewportWidth = canvas.width; + gl.viewportHeight = canvas.height; + + gl.clearColor(0.0, 0.0, 0.0, 1.0); + gl.enable(gl.DEPTH_TEST); //clear screen - this.gl.viewport(0, 0, this.gl.viewportWidth, this.gl.viewportHeight); - this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); + gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); }; @@ -74,15 +102,16 @@ GpuDevice.prototype.kill = function() { GpuDevice.prototype.resize = function(size, skipCanvas) { this.curSize = size; + var canvas = this.canvas, gl = this.gl; - if (this.canvas != null && skipCanvas !== true) { - this.canvas.width = this.curSize[0]; - this.canvas.height = this.curSize[1]; + if (canvas != null && skipCanvas !== true) { + canvas.width = this.curSize[0]; + canvas.height = this.curSize[1]; } - if (this.gl != null) { - this.gl.viewportWidth = this.canvas.width; - this.gl.viewportHeight = this.canvas.height; + if (gl != null) { + gl.viewportWidth = canvas.width; + gl.viewportHeight = canvas.height; } }; diff --git a/src/core/renderer/gpu/shaders.js b/src/core/renderer/gpu/shaders.js index 64b31aef..ce59d975 100755 --- a/src/core/renderer/gpu/shaders.js +++ b/src/core/renderer/gpu/shaders.js @@ -656,7 +656,16 @@ GpuShaders.heightmapDepthFragmentShader = 'precision mediump float;\n'+ 'gl_FragColor = fract(vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0) * vDepth) + (-0.5/255.0);\n'+ '}'; - +GpuShaders.quadPoint = + 'vec3 quadPoint(int i1, int i2, int i3, float t, float t2) {\n'+ + 'float p1x = uPoints[i1], p1y = uPoints[i1+1], p1z = uPoints[i1+2];\n'+ + 'float p3x = uPoints[i3], p3y = uPoints[i3+1], p3z = uPoints[i3+2];\n'+ + 'float p2x = 2.0*uPoints[i2]-p1x*0.5-p3x*0.5;\n'+ + 'float p2y = 2.0*uPoints[i2+1]-p1y*0.5-p3y*0.5;\n'+ + 'float p2z = 2.0*uPoints[i2+2]-p1z*0.5-p3z*0.5;\n'+ + 'return vec3(t2*t2*p1x+2.0*t2*t*p2x+t*t*p3x, t2*t2*p1y+2.0*t2*t*p2y+t*t*p3y, t2*t2*p1z+2.0*t2*t*p2z+t*t*p3z); }\n'; + + GpuShaders.planeVertexShader = 'attribute vec3 aPosition;\n'+ 'attribute vec2 aTexCoord;\n'+ @@ -666,14 +675,7 @@ GpuShaders.planeVertexShader = 'uniform float uPoints[9*3];\n'+ 'varying vec2 vTexCoord;\n'+ 'varying vec2 vTexCoord2;\n'+ - 'varying float vFogFactor;\n'+ - 'vec3 quadPoint(int i1, int i2, int i3, float t, float t2) {\n'+ - 'float p1x = uPoints[i1], p1y = uPoints[i1+1], p1z = uPoints[i1+2];\n'+ - 'float p3x = uPoints[i3], p3y = uPoints[i3+1], p3z = uPoints[i3+2];\n'+ - 'float p2x = 2.0*uPoints[i2]-p1x*0.5-p3x*0.5;\n'+ - 'float p2y = 2.0*uPoints[i2+1]-p1y*0.5-p3y*0.5;\n'+ - 'float p2z = 2.0*uPoints[i2+2]-p1z*0.5-p3z*0.5;\n'+ - 'return vec3(t2*t2*p1x+2.0*t2*t*p2x+t*t*p3x, t2*t2*p1y+2.0*t2*t*p2y+t*t*p3y, t2*t2*p1z+2.0*t2*t*p2z+t*t*p3z); }\n'+ + 'varying float vFogFactor;\n'+ GpuShaders.quadPoint + 'void main() {\n'+ 'vec3 indices = aPosition;\n'+ 'float t = aPosition.y * uParams[2];\n'+ //vertical index @@ -719,14 +721,7 @@ GpuShaders.planeVertex2Shader = 'uniform float uPoints[9*3];\n'+ 'varying vec2 vTexCoord;\n'+ 'varying vec2 vTexCoord2;\n'+ - 'varying float vFogFactor;\n'+ - 'vec3 quadPoint(int i1, int i2, int i3, float t, float t2) {\n'+ - 'float p1x = uPoints[i1], p1y = uPoints[i1+1], p1z = uPoints[i1+2];\n'+ - 'float p3x = uPoints[i3], p3y = uPoints[i3+1], p3z = uPoints[i3+2];\n'+ - 'float p2x = 2.0*uPoints[i2]-p1x*0.5-p3x*0.5;\n'+ - 'float p2y = 2.0*uPoints[i2+1]-p1y*0.5-p3y*0.5;\n'+ - 'float p2z = 2.0*uPoints[i2+2]-p1z*0.5-p3z*0.5;\n'+ - 'return vec3(t2*t2*p1x+2.0*t2*t*p2x+t*t*p3x, t2*t2*p1y+2.0*t2*t*p2y+t*t*p3y, t2*t2*p1z+2.0*t2*t*p2z+t*t*p3z); }\n'+ + 'varying float vFogFactor;\n'+ GpuShaders.quadPoint + 'void main() {\n'+ 'vec3 indices = aPosition;\n'+ 'float t = aPosition.y * uParams[2];\n'+ //vertical index @@ -777,14 +772,7 @@ GpuShaders.planeVertex3Shader = 'uniform float uHeights[9];\n'+ 'varying vec2 vTexCoord;\n'+ 'varying vec2 vTexCoord2;\n'+ - 'varying float vFogFactor;\n'+ - 'vec3 quadPoint(int i1, int i2, int i3, float t, float t2) {\n'+ - 'float p1x = uPoints[i1], p1y = uPoints[i1+1], p1z = uPoints[i1+2];\n'+ - 'float p3x = uPoints[i3], p3y = uPoints[i3+1], p3z = uPoints[i3+2];\n'+ - 'float p2x = 2.0*uPoints[i2]-p1x*0.5-p3x*0.5;\n'+ - 'float p2y = 2.0*uPoints[i2+1]-p1y*0.5-p3y*0.5;\n'+ - 'float p2z = 2.0*uPoints[i2+2]-p1z*0.5-p3z*0.5;\n'+ - 'return vec3(t2*t2*p1x+2.0*t2*t*p2x+t*t*p3x, t2*t2*p1y+2.0*t2*t*p2y+t*t*p3y, t2*t2*p1z+2.0*t2*t*p2z+t*t*p3z); }\n'+ + 'varying float vFogFactor;\n'+ GpuShaders.quadPoint + 'float linearHeight(float x, float y) {\n'+ 'int ix = int(x);\n'+ 'int iy = int(y);\n'+ @@ -822,7 +810,45 @@ GpuShaders.planeVertex3Shader = 'vTexCoord = uv;\n'+ '}'; - +GpuShaders.planeVertex4Shader = + 'uniform sampler2D uSampler2;\n'+ + 'attribute vec3 aPosition;\n'+ + 'attribute vec2 aTexCoord;\n'+ + 'uniform mat4 uMV, uProj;\n'+ + 'uniform vec4 uParams;\n'+ //[uGridStep1, fogDensity, indexFactor, uGridStep2] + 'uniform vec4 uParams3;\n'+ //[px, py, sx, sy] + 'uniform float uPoints[9*3];\n'+ + 'uniform vec3 uVector;\n'+ + 'uniform vec2 uHeights;\n'+ //[hmin, hmax] + 'varying vec2 vTexCoord;\n'+ + 'varying vec2 vTexCoord2;\n'+ + 'varying float vFogFactor;\n'+ GpuShaders.quadPoint + + 'void main() {\n'+ + 'vec3 indices = aPosition;\n'+ + 'float t = aPosition.y * uParams[2];\n'+ //vertical index + 'float tt = t;\n'+ + 'float t2 = (1.0-t);\n'+ + 'vec3 p1 = quadPoint(0, 3, 6, t, t2);\n'+ + 'vec3 p2 = quadPoint(9, 9+3, 9+6, t, t2);\n'+ + 'vec3 p3 = quadPoint(18, 18+3, 18+6, t, t2);\n'+ + 't = aPosition.x * uParams[2];\n'+ //horizontal index + 'float tt2 = t;\n'+ + 't2 = (1.0-t);\n'+ + 'float p2x = 2.0*p2.x-p1.x*0.5-p3.x*0.5;\n'+ + 'float p2y = 2.0*p2.y-p1.y*0.5-p3.y*0.5;\n'+ + 'float p2z = 2.0*p2.z-p1.z*0.5-p3.z*0.5;\n'+ + 'vec4 p = vec4(t2*t2*p1.x+2.0*t2*t*p2x+t*t*p3.x, t2*t2*p1.y+2.0*t2*t*p2y+t*t*p3.y, t2*t2*p1.z+2.0*t2*t*p2z+t*t*p3.z, 1);\n'+ + 'p.xyz += uVector * (uHeights[0] + (uHeights[1]-uHeights[0])*texture2D(uSampler2, vec2(tt, tt2)).x);\n'+ + 'vec4 camSpacePos = uMV * p;\n'+ + 'gl_Position = uProj * camSpacePos;\n'+ + 'float camDist = length(camSpacePos.xyz);\n'+ + 'vFogFactor = exp(uParams[1] * camDist);\n'+ + 'vec2 uv = aTexCoord;\n'+ + 'uv.x = uv.x * uParams3[2] + uParams3[0];\n'+ + 'uv.y = uv.y * uParams3[3] + uParams3[1];\n'+ + 'vTexCoord = uv;\n'+ + '}'; + //textured tile mesh GpuShaders.tileVertexShader = 'attribute vec3 aPosition;\n'+ diff --git a/src/core/renderer/gpu/texture.js b/src/core/renderer/gpu/texture.js index f3763538..6feb521a 100755 --- a/src/core/renderer/gpu/texture.js +++ b/src/core/renderer/gpu/texture.js @@ -87,7 +87,7 @@ GpuTexture.prototype.createFromData = function(lx, ly, data, filter, repeat) { this.loaded = true; }; -GpuTexture.prototype.createFromImage = function(image, filter, repeat) { +GpuTexture.prototype.createFromImage = function(image, filter, repeat, aniso) { var gl = this.gl; //utils.isPowerOfTwo = (function(value) { @@ -139,7 +139,13 @@ GpuTexture.prototype.createFromImage = function(image, filter, repeat) { data = canvas; } - if (this.gpu.noTextures !== true) { + var gpu = this.gpu; + + if (gpu.anisoLevel) { + gl.texParameterf(gl.TEXTURE_2D, gpu.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, gpu.anisoLevel); + } + + if (gpu.noTextures !== true) { //why is it here and not at the beginig of the code? gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data); if (mipmaps) { diff --git a/src/core/renderer/init.js b/src/core/renderer/init.js index f76ddfb2..1f4ccf55 100755 --- a/src/core/renderer/init.js +++ b/src/core/renderer/init.js @@ -58,9 +58,13 @@ RendererInit.prototype.initShaders = function() { renderer.progWireframeTile3 = new GpuProgram(gpu, shaders.tileWireframe3VertexShader, shaders.tileWireframeFragmentShader); renderer.progFlatShadeTile = new GpuProgram(gpu, shaders.tileFlatShadeVertexShader, shaders.tileFlatShadeFragmentShader); renderer.progHeightmap = new GpuProgram(gpu, shaders.heightmapVertexShader, shaders.heightmapFragmentShader); - renderer.progPlane = new GpuProgram(gpu, shaders.planeVertexShader, shaders.planeFragmentShader); - renderer.progPlane2 = new GpuProgram(gpu, shaders.planeVertex2Shader, shaders.planeFragment2Shader); - renderer.progPlane3 = new GpuProgram(gpu, shaders.planeVertex3Shader, shaders.planeFragmentShader); + renderer.progPlane = new GpuProgram(gpu, shaders.planeVertexShader, shaders.planeFragmentShader); //flat + renderer.progPlane2 = new GpuProgram(gpu, shaders.planeVertex2Shader, shaders.planeFragment2Shader); //poles + renderer.progPlane3 = new GpuProgram(gpu, shaders.planeVertex3Shader, shaders.planeFragmentShader); // grid + + renderer.progHmapPlane = new GpuProgram(gpu, shaders.planeVertex4Shader, shaders.planeFragmentShader); + + renderer.progSkydome = new GpuProgram(gpu, shaders.skydomeVertexShader, shaders.skydomeFragmentShader); renderer.progStardome = new GpuProgram(gpu, shaders.skydomeVertexShader, shaders.stardomeFragmentShader); diff --git a/src/core/renderer/renderer.js b/src/core/renderer/renderer.js index d98ba84a..0febc515 100755 --- a/src/core/renderer/renderer.js +++ b/src/core/renderer/renderer.js @@ -62,7 +62,7 @@ var Renderer = function(core, div, onUpdate, onResize, config) { this.cameraVector = [0,1,0]; //this.texelSizeLimit = this.core.mapConfig.texelSize * texelSizeFactor; - this.gpu = new GpuDevice(this, div, this.curSize, this.config.rendererAllowScreenshots, this.config.rendererAntialiasing); + this.gpu = new GpuDevice(this, div, this.curSize, this.config.rendererAllowScreenshots, this.config.rendererAntialiasing, this.config.rendererAnisotropic); this.camera = new Camera(this, 45, 2, 1200000.0); //reduce garbage collection diff --git a/webpack.config.js b/webpack.config.js index ae1ddbf7..d0324bb1 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -42,9 +42,13 @@ plugins.push( 'VTS_MATERIAL_FOG': 3, 'VTS_MATERIAL_INTERNAL' : 4, 'VTS_MATERIAL_INTERNAL_NOFOG': 5, - 'VTS_MATERIAL_EXTERNAL' : 6, + 'VTS_MATERIAL_EXTERNAL': 6, 'VTS_MATERIAL_EXTERNAL_NOFOG': 7, + 'VTS_PIPELINE_BASIC': 0, + 'VTS_PIPELINE_HMAP': 1, + 'VTS_PIPELINE_PROCEDURAL': 2, + 'VTS_DRAWCOMMAND_STATE' : 1, 'VTS_DRAWCOMMAND_SUBMESH' : 2, 'VTS_DRAWCOMMAND_GEODATA' : 3,