增加首屏图片(bg.jpg)
web-mobile类型打包
//index.html脚本
<div id="myDiv_1111"style="background: url(./bg.jpg) 50% 50%/ 100% auto no-repeat ; width:100%;height:100%;position:absolute;"></div>
//游戏内脚本
var div = document.getElementById("myDiv_1111");setTimeout(function (){//销毁div,即移除其从DoM中div.parentNode.removeChild(div);},700);
wechat类型打包
修改首屏文件(first-screen.js)
const VS_LOGO = `
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {gl_Position = a_Position; v_TexCoord = a_TexCoord;
}`;const FS_LOGO = `
precision mediump float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main() {gl_FragColor = texture2D(u_Sampler, v_TexCoord);
}`;const VS_BG = `
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {gl_Position = a_Position; v_TexCoord = a_TexCoord;
}`;const FS_BG = `
precision mediump float;
uniform sampler2D u_Sampler;
uniform float u_flip;
varying vec2 v_TexCoord;
void main() {vec2 texCoord = v_TexCoord;if(u_flip > 0.5) {texCoord.y = 1.0 - texCoord.y;}gl_FragColor = texture2D(u_Sampler, texCoord);
}`;const VS_PROGRESSBAR = `
precision mediump float;
attribute vec4 a_Position;
attribute float a_Progress;
varying float v_Progress;
void main() {gl_Position = a_Position; v_Progress = a_Progress;
}`;const FS_PROGRESSBAR = `
precision mediump float;
uniform float u_CurrentProgress;
varying float v_Progress;
uniform vec4 u_ProgressBarColor;
uniform vec4 u_ProgressBackground;
void main() {gl_FragColor = v_Progress <= u_CurrentProgress ? u_ProgressBarColor : u_ProgressBackground;
}`;const options = {alpha: false,antialias: true,depth: true,stencil: true,premultipliedAlpha: false,preserveDrawingBuffer: false,powerPreference: 'default',failIfMajorPerformanceCaveat: false,
};let gl = null;
let image = null;
let slogan = null;
let bg = null;
let program = null;
let programBg = null;
let programProgress = null;
let rafHandle = null;
let logoTexture = null;
let sloganTexture = null;
let bgTexture = null;
let vertexBuffer = null;
let sloganVertexBuffer = null;
let bgVertexBuffer = null;
let vertexBufferProgress = null;
let progress = 0.0;
let progressBarColor = [61 / 255, 197 / 255, 222 / 255, 1];
let progressBackground = [100 / 255, 111 / 255, 118 / 255, 1];
let afterTick = null;
let backgroundFilp = 1.0; // set 0 to not flip
let displayRatio = 1;
let bgColor = [0, 0, 0, 1];
let useCustomBg = true;
let useLogo = false;
let useDefaultLogo = false;
let logoName = 'bg.jpg';
let bgName = 'bg.jpg';function initShaders(vshader, fshader) {return createProgram(vshader, fshader);
}function createProgram(vshader, fshader) {var vertexShader = loadShader(gl.VERTEX_SHADER, vshader);var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fshader);var program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);var linked = gl.getProgramParameter(program, gl.LINK_STATUS);if (!linked) {var error = gl.getProgramInfoLog(program);console.log('Failed to link program: ' + error);gl.deleteProgram(program);program = null;}gl.deleteShader(fragmentShader);gl.deleteShader(vertexShader);return program;
}function loadShader(type, source) {var shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);if (!compiled) {var error = gl.getShaderInfoLog(shader);console.log('Failed to compile shader: ' + error);gl.deleteShader(shader);return null;}return shader;
}function initVertexBuffer() {const widthRatio = 2 / canvas.width;const heightRatio = 2 / canvas.height;const heightOffset = 0.225;const vertices = new Float32Array([widthRatio, heightRatio + heightOffset, 1.0, 1.0,widthRatio, heightRatio + heightOffset, 1.0, 0.0,-widthRatio, heightRatio + heightOffset, 0.0, 1.0,-widthRatio, heightRatio + heightOffset, 0.0, 0.0,]);vertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function initSloganVertexBuffer() {const widthRatio = 2 / canvas.width;const heightRatio = 2 / canvas.height;const vertices = new Float32Array([widthRatio, heightRatio, 1.0, 1.0,widthRatio, heightRatio, 1.0, 0.0,-widthRatio, heightRatio, 0.0, 1.0,-widthRatio, heightRatio, 0.0, 0.0,]);sloganVertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, sloganVertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function initBgVertexBuffer() {const vertices = new Float32Array([1.0, 1.0, 1.0, 1.0,1.0, 0.0, 1.0, 0.0,0.0, 1.0, 0.0, 1.0,0.0, 0.0, 0.0, 0.0,]);bgVertexBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, bgVertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function initProgressVertexBuffer() {// the ratio value may be adjusted according to the image pixelsconst widthRatio = 0.5;const heightRatio = (window.devicePixelRatio >= 2 ? 6 : 3) / canvas.height * 1.35;const heightOffset = -0.8;const vertices = new Float32Array([widthRatio, heightOffset - heightRatio, 1,widthRatio, heightOffset + heightRatio, 1,-widthRatio, heightOffset - heightRatio, 0,-widthRatio, heightOffset + heightRatio, 0,]);vertexBufferProgress = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, vertexBufferProgress);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function updateVertexBuffer() {// By default, maintain aspect ratio by constraining display at 200px heightconst defaultRatio = 200 / image.height;const widthRatio = image.width / canvas.width * 1.35 * defaultRatio * displayRatio;const heightRatio = image.height / canvas.height * 1.35 * defaultRatio * displayRatio;const heightOffset = 1 / 6; // canvas:(-1,1) -> (button, top); heightOffset = (5/12) * (-2) + 1 = 1/6const vertices = new Float32Array([widthRatio, heightOffset - heightRatio, 1.0, 1.0,widthRatio, heightOffset + heightRatio, 1.0, 0.0,-widthRatio, heightOffset - heightRatio, 0.0, 1.0,-widthRatio, heightOffset + heightRatio, 0.0, 0.0,]);gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function updateSloganVertexBuffer() {// the ratio value may be adjusted according to the image pixelsconst widthRatio = slogan.width / canvas.width * 0.75;const heightRatio = slogan.height / canvas.height * 0.75;const logoHeightRatio = image.height / canvas.height * 1.35 * displayRatio;const heightOffset = (5 / 12 + logoHeightRatio * 1 / 2 + heightRatio * 3 / 2) * (-2) + 1; // 5/12 is ui design layout for logoconst vertices = new Float32Array([widthRatio, heightOffset - heightRatio, 1.0, 1.0,widthRatio, heightOffset + heightRatio, 1.0, 0.0,-widthRatio, heightOffset - heightRatio, 0.0, 1.0,-widthRatio, heightOffset + heightRatio, 0.0, 0.0,]);gl.bindBuffer(gl.ARRAY_BUFFER, sloganVertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function updateBgVertexBuffer() {const vertices = new Float32Array([1.0, 1.0, 1.0, 1.0,1.0, -1.0, 1.0, 0.0,-1.0, 1.0, 0.0, 1.0,-1.0, -1.0, 0.0, 0.0,]);gl.bindBuffer(gl.ARRAY_BUFFER, bgVertexBuffer);gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
}function loadBackground(bgPath) {return new Promise((resolve, reject) => {bg = new Image();bg.premultiplyAlpha = false;bg.onload = function () {resolve(bg);};bg.onerror = function (err) {reject(err);};bg.src = bgPath.replace('#', '%23');});
}function loadImage(imgPath) {return new Promise((resolve, reject) => {image = new Image();image.premultiplyAlpha = false;image.onload = function () {resolve(image);};image.onerror = function (err) {reject(err);};image.src = imgPath.replace('#', '%23');});
}function loadSlogan(sloganPath) {return new Promise((resolve, reject) => {slogan = new Image();slogan.premultiplyAlpha = false;slogan.onload = function () {resolve(slogan);};slogan.onerror = function (err) {reject(err);};slogan.src = sloganPath.replace('#', '%23');});
}function initLogoTexture() {logoTexture = gl.createTexture();gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, logoTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]));
}function initSloganTexture() {sloganTexture = gl.createTexture();gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, sloganTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]));
}function initBgTexture() {bgTexture = gl.createTexture();gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, bgTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]));
}function updateLogoTexture() {gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, logoTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}function updateSloganTexture() {gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, sloganTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, slogan);
}function updateBgTexture() {gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, bgTexture);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bg);
}function drawTexture(gl, program, texture, vertexBuffer, vertexFormatLength) {gl.useProgram(program);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, texture);var uSampler = gl.getUniformLocation(program, 'u_Sampler');gl.uniform1i(uSampler, 0);var uFlip = gl.getUniformLocation(program, 'u_flip');gl.uniform1f(uFlip, backgroundFilp);gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);var aPosition = gl.getAttribLocation(program, 'a_Position');gl.enableVertexAttribArray(aPosition);gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, vertexFormatLength * 4, 0);var aTexCoord = gl.getAttribLocation(program, 'a_TexCoord');gl.enableVertexAttribArray(aTexCoord);gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, vertexFormatLength * 4, vertexFormatLength * 2);gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}function drawProgressBar(gl, program, vertexBuffer, vertexFormatLength, progress, progressBarColor, progressBackground) {gl.useProgram(program);var uCurrentProgress = gl.getUniformLocation(program, 'u_CurrentProgress');gl.uniform1f(uCurrentProgress, progress);var uProgressBarColor = gl.getUniformLocation(program, 'u_ProgressBarColor');gl.uniform4fv(uProgressBarColor, progressBarColor);var uProgressBackground = gl.getUniformLocation(program, 'u_ProgressBackground');gl.uniform4fv(uProgressBackground, progressBackground);gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);var aPosition = gl.getAttribLocation(program, 'a_Position');gl.enableVertexAttribArray(aPosition);var vertexFormatLength = 4;gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, vertexFormatLength * 3, 0);var aProgress = gl.getAttribLocation(program, 'a_Progress');gl.enableVertexAttribArray(aProgress);gl.vertexAttribPointer(aProgress, 1, gl.FLOAT, false, vertexFormatLength * 3, vertexFormatLength * 2);gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}function draw() {gl.enable(gl.BLEND);gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);gl.clearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]);gl.clear(gl.COLOR_BUFFER_BIT);// draw backgrounduseCustomBg && drawTexture(gl, programBg, bgTexture, bgVertexBuffer, 4);// draw logouseLogo && drawTexture(gl, program, logoTexture, vertexBuffer, 4);// draw sloganuseLogo && useDefaultLogo && drawTexture(gl, program, sloganTexture, sloganVertexBuffer, 4);// draw progress bardrawProgressBar(gl, programProgress, vertexBufferProgress, 3, progress, progressBarColor, progressBackground);
}function tick() {rafHandle = requestAnimationFrame(() => {draw();tick();if (afterTick) {afterTick();afterTick = null;}});
}function end() {return setProgress(1).then(() => {cancelAnimationFrame(rafHandle);gl.useProgram(null);gl.bindTexture(gl.TEXTURE_2D, null);gl.bindBuffer(gl.ARRAY_BUFFER, null);useLogo && gl.deleteTexture(logoTexture);useLogo && useDefaultLogo && gl.deleteTexture(sloganTexture);useCustomBg && gl.deleteTexture(bgTexture);gl.deleteBuffer(vertexBuffer);useCustomBg && gl.deleteBuffer(bgVertexBuffer);useLogo && useDefaultLogo && gl.deleteBuffer(sloganVertexBuffer);gl.deleteBuffer(vertexBufferProgress);gl.deleteProgram(program);gl.deleteProgram(programBg);gl.deleteProgram(programProgress);});
}function setProgress(val) {progress = val;return new Promise((resolve, reject) => {afterTick = () => {resolve();};});
}function start(alpha, antialias, useWebgl2) {options.alpha = alpha === 'true' ? true : false;options.antialias = antialias === 'false' ? false : true;if (useWebgl2 === 'true') {gl = window.canvas.getContext("webgl2", options);}// TODO: this is a hack method to detect whether WebGL2RenderingContext is supportedif (gl) {window.WebGL2RenderingContext = true;} else {window.WebGL2RenderingContext = false;gl = window.canvas.getContext("webgl", options);}initVertexBuffer();useCustomBg && initBgVertexBuffer();useLogo && useDefaultLogo && initSloganVertexBuffer();initProgressVertexBuffer();initLogoTexture();useCustomBg && initBgTexture();useLogo && useDefaultLogo && initSloganTexture();if (useLogo) {program = initShaders(VS_LOGO, FS_LOGO);}if (useCustomBg) {programBg = initShaders(VS_BG, FS_BG);}programProgress = initShaders(VS_PROGRESSBAR, FS_PROGRESSBAR);tick();return Promise.all([//logo should be loaded earlier than sloganuseLogo && loadImage(logoName).then(() => {updateVertexBuffer();updateLogoTexture();}).then(() => {return useLogo && useDefaultLogo && loadSlogan('slogan.png').then(() => {updateSloganVertexBuffer();updateSloganTexture();});}),useCustomBg && loadBackground(bgName).then(() => {updateBgVertexBuffer();updateBgTexture();})]).then(() => {return setProgress(0);});
}
module.exports = { start, end, setProgress };