1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16import { XMat4 } from "./XMat4.js" 17import { XShader } from "./XShader.js" 18import { Scr } from "../XDefine.js" 19import { XTexture } from "./XTexture.js" 20import { gl } from "../GLFrame.js" 21import { fAngle, iDistance } from "../XTools.js" 22 23export class X2DFast { 24 static gi() { 25 if (X2DFast.px2f == null) X2DFast.px2f = new X2DFast(); 26 return X2DFast.px2f; 27 } 28 29 constructor() { 30 this.localBuffer = gl.createBuffer(); 31 this.texSampleIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 32 33 this.vertexArray = new ArrayBuffer(1024 * 1024 * 4 * 2) 34 this.vertexFloat32 = new Float32Array(this.vertexArray) 35 this.vertexUint32 = new Uint32Array(this.vertexArray) 36 this.whiteImg = XTexture.gi().loadTextureFromImage("CUSTOM_TEXTURE_1") 37 this.whiteCut = XTexture.gi().makeCut(this.whiteImg, 0, 0, 1, 1) 38 39 XShader.gi(); 40 41 this.resetMat(); 42 } 43 resetMat() { 44 X2DFast.transform2D.unit() 45 X2DFast.transform2D.orthoMat(0, 0, Scr.logicw, Scr.logich); 46 let tm = X2DFast.transform2D.mat; 47 this.t2dExt = [ 48 tm[0][0], tm[1][0], tm[2][0], tm[3][0], 49 tm[0][1], tm[1][1], tm[2][1], tm[3][1], 50 tm[0][2], tm[1][2], tm[2][2], tm[3][2], 51 tm[0][3], tm[1][3], tm[2][3], tm[3][3] 52 ] 53 } 54 55 swapMode2D() { 56 gl.disable(gl.DEPTH_TEST) 57 58 gl.enable(gl.BLEND) 59 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) 60 } 61 62 DrawCircle(ox, oy, rw, rh, c = 0xffffffff, lw = 1) { 63 let lx = -1 64 let ly = -1 65 let i = 0 66 let gap = Math.PI * 2 / 32 67 while (i < Math.PI * 2 + 0.00001) { 68 let dx = Math.cos(i) * rw + ox 69 let dy = Math.sin(i) * rh + oy 70 if (lx != -1) { 71 this.drawLine(lx, ly, dx, dy, c, lw) 72 } 73 lx = dx 74 ly = dy 75 i += gap 76 } 77 } 78 79 fillRect(x, y, w, h, c = 0xffffffff) { 80 this.drawCut(this.whiteCut, x, y, w, h, 0, 0, 0, c) 81 } 82 83 drawLine(x1, y1, x2, y2, c = 0xffffffff, linewidth = 1) { 84 this.drawCut(this.whiteCut, x1, y1, 85 iDistance(x1 - x2, y1 - y2), linewidth, fAngle(x2 - x1, y2 - y1), 0, 0.5, c) 86 } 87 88 drawRect(x, y, w, h, c = 0xffffffff, lw = 1) { 89 this.drawLine(x - lw / 2, y, x + w + lw / 2, y, c, lw) 90 this.drawLine(x, y, x, y + h, c, lw) 91 this.drawLine(x + w, y + h, x + w, y, c, lw) 92 this.drawLine(x + w + lw / 2, y + h, x - lw / 2, y + h, c, lw) 93 } 94 95 static testTransform(x, y, sw, sh, ra, ox, oy, realw, realh) { 96 X2DFast.tmpMat.unit() 97 if (ox == -1) ox = 0 98 if (ox == -2) ox = Math.floor(realw / 2) 99 if (ox == -3) ox = realw 100 if (oy == -1) oy = 0 101 if (oy == -2) oy = Math.floor(realh / 2) 102 if (oy == -3) oy = realh 103 if (ox != 0 || oy != 0) X2DFast.tmpMat.move(-ox, -oy, 0) 104 if (sw != 1 || sh != 1) X2DFast.tmpMat.scale(sw, sh, 1) 105 if (ra != 0) X2DFast.tmpMat.rotate(0, 0, ra) 106 if (x != 0 || y != 0) X2DFast.tmpMat.move(x, y, 0) 107 } 108 clearBuffer() { 109 this.ridDict = {} 110 this.ridPoint = 0 111 this.drawCount = 0 112 } 113 swapC(c) { 114 let r = Math.floor(((c >> 16) & 0xff) * 63 / 255) 115 let g = Math.floor(((c >> 8) & 0xff) * 63 / 255) 116 let b = Math.floor((c & 0xff) * 63 / 255) 117 let a = Math.floor(((c >> 24) & 0xff) * 63 / 255) 118 return ((a * 64 + r) * 64 + g) * 64 + b 119 } 120 drawCut_(pcut, m00, m01, m10, m11, m22, m30, m31, c = 0xffffffff) { 121 if (c == -1) c = 0xffffffff 122 c = this.swapC(c) 123 this.vertexFloat32.set([0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, 124 this.ridDict[pcut.rid], c, 125 pcut.w, 0.0, 0.0, pcut.u1, pcut.v1, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 126 pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 127 0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 128 pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 129 0.0, pcut.h, 0.0, pcut.u3, pcut.v3, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c], 130 this.drawCount * 14 * 6) 131 this.drawCount += 1 132 } 133 drawCutEx(cid, tmat, c = 0xffffffff) { 134 let pcut = XTexture.pinstance_.allCuts[cid]; 135 if (!(pcut.rid in this.ridDict)) { 136 this.ridDict[pcut.rid] = this.ridPoint; 137 this.ridPoint += 1; 138 } 139 tmat = tmat.mat 140 this.drawCut(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c) 141 } 142 drawCut(cid, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) { 143 let pcut = XTexture.gi().allCuts[cid]; 144 if (pcut == null) 145 return; 146 if (!(pcut.rid in this.ridDict)) { 147 this.ridDict[pcut.rid] = this.ridPoint; 148 this.ridPoint += 1; 149 } 150 X2DFast.testTransform(x, y, sw, sh, ra, ox, oy, pcut.w, pcut.h) 151 let tmat = X2DFast.tmpMat.mat; 152 this.drawCut_(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c) 153 } 154 drawText(s, size = 18, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = 0xffffffff) { 155 if (s.length <= 0) return 0; 156 let cid = XTexture.gi().getText(s, size) 157 if (cid >= 0) 158 this.drawCut(cid, x, y, sw, sh, ra, ox, oy, c) 159 return XTexture.gi().allCuts[cid].w; 160 } 161 getTextWidth(s, size) { 162 if (s.length <= 0) return 0; 163 let cid = XTexture.gi().getText(s, size) 164 return XTexture.gi().allCuts[cid].w; 165 } 166 freshBuffer() { 167 XTexture.gi()._FreshText() 168 if (this.drawCount == 0) return 169 let ps = XShader.gi().use(XShader.ID_SHADER_FAST) 170 for (let rid in this.ridDict) { 171 gl.activeTexture(gl.TEXTURE0 + this.ridDict[rid]) 172 gl.bindTexture(gl.TEXTURE_2D, XTexture.gi().ximages[rid].tex); 173 174 gl.uniform1i(ps.tex[this.ridDict[rid]], this.ridDict[rid]); 175 } 176 177 gl.uniformMatrix4fv(ps.uMat, false, this.t2dExt) 178 179 gl.bindBuffer(gl.ARRAY_BUFFER, this.localBuffer); 180 gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW) 181 gl.vertexAttribPointer(ps.position, 3, gl.FLOAT, false, 4 * 14, 0) 182 gl.enableVertexAttribArray(ps.position) 183 gl.vertexAttribPointer(ps.aTexCoord, 2, gl.FLOAT, false, 4 * 14, 4 * 3) 184 gl.enableVertexAttribArray(ps.aTexCoord) 185 gl.vertexAttribPointer(ps.ext1, 4, gl.FLOAT, false, 4 * 14, 4 * 5) 186 gl.enableVertexAttribArray(ps.ext1) 187 gl.vertexAttribPointer(ps.ext2, 4, gl.FLOAT, false, 4 * 14, 4 * 9) 188 gl.enableVertexAttribArray(ps.ext2) 189 gl.vertexAttribPointer(ps.inColor, 1, gl.FLOAT, false, 4 * 14, 4 * 13) 190 gl.enableVertexAttribArray(ps.inColor) 191 192 gl.drawArrays(gl.TRIANGLES, 0, 6 * this.drawCount); 193 } 194} 195X2DFast.tmpMat = new XMat4(); 196X2DFast.transform2D = new XMat4(); 197 198X2DFast.px2f = null; 199 200 201