Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Texturerender #524

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions debug/style-streets.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ var style = {
},
"building": {
"filter": {"source": "mapbox streets", "layer": "building"},
"prerender": true,
"prerender-blur": 1,
"prerender-size": 2048,
"fill": true
},
"borders": {
Expand Down
45 changes: 44 additions & 1 deletion js/render/drawfill.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
'use strict';

var PrerenderedTexture = require('./prerendered.js');
var drawRaster = require('./drawraster.js');
var glmatrix = require('../lib/glmatrix.js');
var mat4 = glmatrix.mat4;

module.exports = drawFill;

function drawFill(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, background) {

if (!background && bucket.info.prerender) {

if (!bucket.prerendered) {
bucket.prerendered = new PrerenderedTexture(gl, bucket.info);
bucket.prerendered.bindFramebuffer();

gl.clearStencil(0x80);
gl.stencilMask(0xFF);
gl.clear(gl.STENCIL_BUFFER_BIT | gl.COLOR_BUFFER_BIT);
gl.stencilMask(0x00);

gl.viewport(0, 0, bucket.prerendered.size, bucket.prerendered.size);

var matrix = mat4.create();
mat4.ortho(matrix, 0, 4096, -4096, 0, 0, 1);
mat4.translate(matrix, matrix, [0, -4096, 0]);

drawFillFromVectors(gl, painter, bucket, layerStyle, matrix, params, imageSprite, background);

if (bucket.info['prerender-blur'] > 0) {
bucket.prerendered.blur(painter, bucket.info['prerender-blur']);
}


bucket.prerendered.unbindFramebuffer();
gl.viewport(0, 0, painter.width, painter.height);
}

// drawPrendered
drawRaster(gl, painter, bucket.prerendered, {}, true);

} else {
drawFillFromVectors(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, background);
}
}

function drawFillFromVectors(gl, painter, bucket, layerStyle, posMatrix, params, imageSprite, background) {
if (typeof layerStyle['fill-color'] !== 'object') console.warn('layer style has a color');

var color = layerStyle['fill-color'];
Expand Down Expand Up @@ -141,7 +184,7 @@ function drawFill(gl, painter, bucket, layerStyle, posMatrix, params, imageSprit

} else {
// Draw filling rectangle.
gl.switchShader(painter.fillShader, painter.tile.posMatrix, painter.tile.exMatrix);
gl.switchShader(painter.fillShader, posMatrix, painter.tile.exMatrix);
gl.uniform4fv(painter.fillShader.u_color, color);
}

Expand Down
12 changes: 9 additions & 3 deletions js/render/drawraster.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
var Tile = require('../ui/tile.js');
module.exports = drawRaster;

function drawRaster(gl, painter, tile, layerStyle) {
function drawRaster(gl, painter, tile, layerStyle, noCrossFade) {

var shader = painter.rasterShader;
gl.switchShader(shader, painter.tile.posMatrix, painter.tile.exMatrix);
Expand All @@ -16,8 +16,14 @@ function drawRaster(gl, painter, tile, layerStyle) {
gl.uniform3fv(shader.u_spin_weights, spinWeights(layerStyle['raster-spin'] || 0));


var parentTile = findParent(tile);
var opacities = getOpacities(tile, parentTile);
var parentTile, opacities;
if (noCrossFade) {
parentTile = null;
opacities = [1, 0];
} else {
parentTile = findParent(tile);
opacities = getOpacities(tile, parentTile);
}
var parentScaleBy, parentTL;

gl.activeTexture(gl.TEXTURE0);
Expand Down
6 changes: 4 additions & 2 deletions js/render/painter.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ GLPainter.prototype.setup = function() {
['a_pos'],
['u_posmatrix', 'u_opacity']);

this.gaussianShader = gl.initializeShader('gaussian',
['a_pos'],
['u_posmatrix', 'u_opacity', 'u_image', 'u_offset']);

this.rasterShader = gl.initializeShader('raster',
['a_pos'],
['u_posmatrix', 'u_brightness_low', 'u_brightness_high', 'u_saturation_factor', 'u_spin_weights', 'u_contrast_factor', 'u_opacity0', 'u_opacity1', 'u_image0', 'u_image1', 'u_tl_parent', 'u_scale_parent']);
Expand Down Expand Up @@ -226,7 +230,6 @@ GLPainter.prototype.bindRenderTexture = function(name) {
var stencil = this.stencilBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, stencil);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, gl.drawingBufferWidth, gl.drawingBufferHeight);
this.stencilClippingMaskDirty = true;
}

// We create a separate texture for every level.
Expand Down Expand Up @@ -270,7 +273,6 @@ GLPainter.prototype.draw = function glPainterDraw(tile, style, layers, params) {
if (tile) {
// Draw the root clipping mask.
this.drawClippingMask();
this.stencilClippingMaskDirty = true;
}

if (!Array.isArray(layers)) console.warn('Layers is not an array');
Expand Down
101 changes: 101 additions & 0 deletions js/render/prerendered.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
'use strict';

var glmatrix = require('../lib/glmatrix.js');
var mat4 = glmatrix.mat4;

module.exports = PrerenderedTexture;

function PrerenderedTexture(gl, bucket) {
this.gl = gl;
this.size = bucket['prerender-size'] || 1024;
this.buffer = bucket['prerender-buffer'] || (1/32);

this.texture = null;
this.fbo = null;
this.fboPrevious = null;
}

PrerenderedTexture.prototype.bindFramebuffer = function() {
var gl = this.gl;
// TODO get previous fbo

if (!this.texture) {
this.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, this.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.size, this.size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
}

if (!this.fbo) {
var stencil = this.stencilBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, stencil);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, this.size, this.size);

this.fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencilBuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0);

}
};

PrerenderedTexture.prototype.unbindFramebuffer = function() {
var gl = this.gl;
gl.bindFramebuffer(gl.FRAMEBUFFER, this.fboPrevious);
gl.deleteFramebuffer(this.fbo);
};

PrerenderedTexture.prototype.bind = function() {
if (!this.texture) throw('pre-rendered texture does not exist');
var gl = this.gl;
gl.bindTexture(gl.TEXTURE_2D, this.texture);
};

PrerenderedTexture.prototype.blur = function(painter, passes) {
var gl = this.gl;
var originalTexture = this.texture;
var secondaryTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, secondaryTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.size, this.size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.bindTexture(gl.TEXTURE_2D, null);

var matrix = mat4.create();
mat4.ortho(matrix, 0, 4096, -4096, 0, 0, 1);
mat4.translate(matrix, matrix, [0, -4096, 0]);

gl.switchShader(painter.gaussianShader, matrix);
gl.activeTexture(gl.TEXTURE0);
gl.uniform1i(painter.gaussianShader.u_image, 0);
gl.uniform1f(painter.gaussianShader.u_opacity, 1);

for (var i = 0; i < passes; i++) {

// Render horizontal
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, secondaryTexture, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform2fv(painter.gaussianShader.u_offset, [1 / this.size, 0]);
gl.bindTexture(gl.TEXTURE_2D, originalTexture);
gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer);
gl.vertexAttribPointer(painter.gaussianShader.a_pos, 2, gl.SHORT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);


// Render vertical
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, originalTexture, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.uniform2fv(painter.gaussianShader.u_offset, [0, 1 / this.size]);
gl.bindTexture(gl.TEXTURE_2D, secondaryTexture);
gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer);
gl.vertexAttribPointer(painter.gaussianShader.a_pos, 2, gl.SHORT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}

gl.deleteTexture(secondaryTexture);
};
1 change: 1 addition & 0 deletions js/render/shaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var glify = require('glify');

module.exports = {
"composite": glify('../../shaders/composite.*.glsl'),
"gaussian": glify('../../shaders/gaussian.*.glsl'),
"debug": glify('../../shaders/debug.*.glsl'),
"dot": glify('../../shaders/dot.*.glsl'),
"fill": glify('../../shaders/fill.*.glsl'),
Expand Down
16 changes: 16 additions & 0 deletions shaders/gaussian.fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
precision mediump float;

uniform sampler2D u_image;
uniform float u_opacity;

varying vec2 v_pos;
varying vec2 v_coords[3];

void main() {
vec4 sum = vec4(0.0);
sum += texture2D(u_image, v_coords[0]) * 0.40261994689424746;
sum += texture2D(u_image, v_coords[1]) * 0.2986900265528763;
sum += texture2D(u_image, v_coords[2]) * 0.2986900265528763;
gl_FragColor = sum;

}
15 changes: 15 additions & 0 deletions shaders/gaussian.vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
attribute vec2 a_pos;

uniform mat4 u_posmatrix;
uniform vec2 u_offset;
varying vec2 v_pos;
varying vec2 v_coords[3];

void main() {
gl_Position = u_posmatrix * vec4(a_pos, 0, 1);
vec2 tex = gl_Position.xy / 2.0 + 0.5;

v_coords[0] = tex;
v_coords[1] = tex + u_offset * 1.1824255238063563;
v_coords[2] = tex - u_offset * 1.1824255238063563;
}