diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..79d9af3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + // ... 其他配置 + ignorePatterns: ['**/*.d.ts'], + env: { + es6: true + } +}; \ No newline at end of file diff --git a/src/hook/types/index.d.ts b/src/hook/types/index.d.ts new file mode 100644 index 0000000..72881f9 --- /dev/null +++ b/src/hook/types/index.d.ts @@ -0,0 +1,47 @@ +export interface RenderElements { + grid: HTMLDivElement + view: HTMLDivElement + values: HTMLDivElement +} + +export interface ChangoItem { + kind: string + wave: Array + lineVao: WebGLVertexArrayObject + maskVao: WebGLVertexArrayObject +} + +export interface WireInfoItem { + kind: string + link: string + name: string + size: number + parent: WireInfoItem + type: string +} + +export interface Pstate { + width: number + height: number + xScale: number + xOffset: number + yOffset: number + yStep: number + yDuty: number +} + +export interface WebGLLocation { + colors: WebGLUniformLocation + shifts: WebGLUniformLocation + scale: WebGLUniformLocation + offset: WebGLUniformLocation + pos: number + widthShifts: WebGLUniformLocation + gl: WebGL2RenderingContext +} + +export interface PerspectivePoint { + x: number + y: number + color: number +} \ No newline at end of file diff --git a/src/hook/types/index.js b/src/hook/types/index.js new file mode 100644 index 0000000..3ded390 --- /dev/null +++ b/src/hook/types/index.js @@ -0,0 +1 @@ +module.Render = {}; \ No newline at end of file diff --git a/src/hook/wave-view/gen-render-waves-gl.js b/src/hook/wave-view/gen-render-waves-gl.js index 8a09552..3a22d1f 100644 --- a/src/hook/wave-view/gen-render-waves-gl.js +++ b/src/hook/wave-view/gen-render-waves-gl.js @@ -1,115 +1,9 @@ 'use strict'; -// 控制颜色 -const gl_Colors = new Float32Array([ - 0, 0, 0, 0, // 0: 空 - - 0, 0, 1, 1, // 1: 高阻态 Z - 0.2, 0.847, 0.1, 1, // 2: value = 0 用于 width = 1 的信号 - 0.2, 0.847, 0.1, 1, // 3: value = 1 用于 width = 1 的信号 - 0.9, 0.2, 0.2, 1, // 4: 未知态 X - .5, 1, 1, 1, // 5: vec 用于 width > 1 的信号 - - 1, 1, 0, 1, // 6: yellow - 1, 0, 1, 1, // 7: strange purple - - 0, 1, 0, .5, // 8: (l L) weak 0 - 0, 1, 1, .5, // 9: (h H) weak 1 - 1, 0, 0, .5, // 10: (w W) weak unknown - - 0, 0, 1, 0.1, // 11: 高阻态 Z 遮罩 - 0.2, 0.847, 0.1, 0.1, // 12: value = 0 遮罩 - 0.2, 0.847, 0.1, 0.1, // 13: value = 1 遮罩 - 0.9, 0.2, 0.2, 0.1, // 14: 未知态 X 遮罩 - .5, 1, 1, 0.1 // 15: vec 遮罩 -]); - - -// 控制方向 -const gl_Shifts = new Float32Array([ // 14 - 0, 0, // 0 - 1, -1, // 1 - 1, 0, // 2 - 1, 1, // 3 - -1, -1, // 4 - -1, 0, // 5 - -1, 1 // 6 -]); - -const gl_Shifts_map = new Map(); -gl_Shifts_map.set(-1, 4); -gl_Shifts_map.set(0, 0); -gl_Shifts_map.set(1, 1); - -const lineWidth = 0.004; // 不能写为 0.0045 这样会因为插值造成不同线段的宽度不一致的问题 -const widthShift = lineWidth / 2; -const gl_WidthShifts = new Float32Array([ - 0, widthShift, // 0 - - widthShift, widthShift, // 1 - - widthShift, 0, // 2 - - widthShift, - widthShift, // 3 - 0, - widthShift, // 4 - widthShift, - widthShift, // 5 - widthShift, 0, // 6 - widthShift, widthShift // 7 -]); - - -class ShaderMaker { - /** - * - * @param {'VERTEX_SHADER' | 'FRAGMENT_SHADER'} type - * @param {string} source - */ - constructor(type, source) { - this.type = type; - this.source = source; - } - - /** - * @param {WebGL2RenderingContext} gl - * @return {WebGLShader} - */ - make(gl) { - const shader = gl.createShader(gl[this.type]); - gl.shaderSource(shader, this.source); - gl.compileShader(shader); - const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS); - if (!ok) { - console.log('创建类型为 ' + type + ' 的着色器失败!'); - } - return shader; - } -} - -const vertexShaderScalar = new ShaderMaker('VERTEX_SHADER', `#version 300 es -in uvec4 pos; -out vec4 v_color; -uniform vec2 scale; -uniform vec2 offset; -uniform vec4 colors[16]; -uniform vec2 shifts[7]; // 基础八位图偏移量,为了性能,pos 只传入整数,需要的坐标负数由该值提供 -uniform vec2 widthShifts[8]; // 用于构造线宽的偏移 - -void main() { - v_color = colors[pos.z]; - vec2 shift = shifts[pos.y]; - vec2 widthShift = widthShifts[pos.w]; - gl_Position = vec4( - float(pos.x) * scale.x + offset.x + float(widthShift.x), - float(shift.x) * scale.y + offset.y + float(widthShift.y), - 1, 1 - ); -}`); - -const fragmentShader = new ShaderMaker('FRAGMENT_SHADER', `#version 300 es -precision mediump float; -in vec4 v_color; -out vec4 outColor; -void main() { - outColor = v_color; -}`); +const { gl_Colors, gl_Shifts, gl_Shifts_map, gl_WidthShifts } = require('./render-utils.js'); +const { vertexShader, fragmentShader } = require('./render-shader.js'); +// const { ChangoItem } = require('./types.d.ts'); class WebGL2WaveRender { /** @@ -188,7 +82,7 @@ class WebGL2WaveRender { */ initProgram(gl) { const program = gl.createProgram(); - gl.attachShader(program, vertexShaderScalar.make(gl)); + gl.attachShader(program, vertexShader.make(gl)); gl.attachShader(program, fragmentShader.make(gl)); gl.linkProgram(program); gl.useProgram(program); @@ -289,6 +183,27 @@ class WebGL2WaveRender { } } + /** + * + * @param {number} x1 + * @param {number} y1 + * @param {number} x2 + * @param {number} y2 + * @param {number} color + * @param {number} wsIndex + * @returns {number[]} + */ + makeRectangleVertices(x1, y1, x2, y2, color, wsIndex = 0) { + const r1 = [x1, gl_Shifts_map.get(y2), color, wsIndex]; + const r2 = [x1, gl_Shifts_map.get(y1), color, wsIndex]; + const r3 = [x2, gl_Shifts_map.get(y1), color, wsIndex]; + const r4 = [x2, gl_Shifts_map.get(y2), color, wsIndex]; + return [ + ...r1, ...r2, ...r3, + ...r1, ...r3, ...r4, + ] + } + /** * * @param {Array} wave @@ -383,23 +298,33 @@ class WebGL2WaveRender { // 制作 maskVertices for (let i = 0; i < pointNum; ++ i) { const p1 = perspectivePoints[i]; + + // 开头就有一条线 + if (i === 0 && p1.y === 1) { + while (perspectivePoints[++ i] && perspectivePoints[i].y === 1); + // 回退 + if (-- i > 0) { + // 四元组: (x, yshift_index, color_index, width_shift_index) + const rectangleVertices = this.makeRectangleVertices(p1.x, 1, perspectivePoints[i].x, -1, p1.color + 10, 4); + // 三角图元画矩形 + maskVertices.push(...rectangleVertices); + continue; + } + } + + // 上升沿才使用 const p2 = perspectivePoints[i + 1]; const p3 = perspectivePoints[i + 2]; + if (p1 === undefined || p2 === undefined || p3 === undefined) { continue; } if (p2.y > p1.y) { // 矩形的四个点 // 四元组: (x, yshift_index, color_index, width_shift_index) - const r1 = [p1.x, gl_Shifts_map.get(p1.y), p2.color + 10, 4]; - const r2 = [p2.x, gl_Shifts_map.get(p2.y), p2.color + 10, 4]; - const r3 = [p3.x, gl_Shifts_map.get(p3.y), p2.color + 10, 4]; - const r4 = [p3.x, gl_Shifts_map.get(p1.y), p2.color + 10, 4]; + const rectangleVertices = this.makeRectangleVertices(p2.x, p2.y, p3.x, p1.y, p2.color + 10, 4); // 三角图元画矩形 - maskVertices.push( - ...r1, ...r2, ...r3, - ...r1, ...r3, ...r4, - ); + maskVertices.push(...rectangleVertices); } } diff --git a/src/hook/wave-view/render-shader.js b/src/hook/wave-view/render-shader.js new file mode 100644 index 0000000..ae3282e --- /dev/null +++ b/src/hook/wave-view/render-shader.js @@ -0,0 +1,61 @@ + +class ShaderMaker { + /** + * + * @param {'VERTEX_SHADER' | 'FRAGMENT_SHADER'} type + * @param {string} source + */ + constructor(type, source) { + this.type = type; + this.source = source; + } + + /** + * @param {WebGL2RenderingContext} gl + * @return {WebGLShader} + */ + make(gl) { + const shader = gl.createShader(gl[this.type]); + gl.shaderSource(shader, this.source); + gl.compileShader(shader); + const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (!ok) { + console.log('创建类型为 ' + type + ' 的着色器失败!'); + } + return shader; + } +} + +const vertexShader = new ShaderMaker('VERTEX_SHADER', `#version 300 es +in uvec4 pos; +out vec4 v_color; +uniform vec2 scale; +uniform vec2 offset; +uniform vec4 colors[16]; +uniform vec2 shifts[7]; // 基础八位图偏移量,为了性能,pos 只传入整数,需要的坐标负数由该值提供 +uniform vec2 widthShifts[8]; // 用于构造线宽的偏移 + +void main() { + v_color = colors[pos.z]; + vec2 shift = shifts[pos.y]; + vec2 widthShift = widthShifts[pos.w]; + gl_Position = vec4( + float(pos.x) * scale.x + offset.x + float(widthShift.x), + float(shift.x) * scale.y + offset.y + float(widthShift.y), + 1, 1 + ); +}`); + +const fragmentShader = new ShaderMaker('FRAGMENT_SHADER', `#version 300 es +precision mediump float; +in vec4 v_color; +out vec4 outColor; +void main() { + outColor = v_color; +}`); + + +export { + vertexShader, + fragmentShader +} \ No newline at end of file diff --git a/src/hook/wave-view/render-utils.js b/src/hook/wave-view/render-utils.js new file mode 100644 index 0000000..cd868db --- /dev/null +++ b/src/hook/wave-view/render-utils.js @@ -0,0 +1,92 @@ +function getRatio() { + var ratio=0; + var screen=window.screen; + var ua=navigator.userAgent.toLowerCase(); + if(window.devicePixelRatio !== undefined) { + ratio=window.devicePixelRatio; + } + else if(~ua.indexOf('msie')) { + if(screen.deviceXDPI && screen.logicalXDPI) { + ratio=screen.deviceXDPI/screen.logicalXDPI; + } + + } + else if(window.outerWidth !== undefined && window.innerWidth !== undefined) { + ratio=window.outerWidth/window.innerWidth; + } + + if(ratio) { + ratio=Math.round(ratio*100); + } + return ratio; +} + +const screenHeightPixel = window.screen.height * getRatio() / 100; +const screenWidthPixel = window.screen.width * getRatio() / 100; + +// 控制颜色 +const gl_Colors = new Float32Array([ + 0, 0, 0, 0, // 0: 空 + + 0, 0, 1, 1, // 1: 高阻态 Z + 0.2, 0.847, 0.1, 1, // 2: value = 0 用于 width = 1 的信号 + 0.2, 0.847, 0.1, 1, // 3: value = 1 用于 width = 1 的信号 + 0.9, 0.2, 0.2, 1, // 4: 未知态 X + .5, 1, 1, 1, // 5: vec 用于 width > 1 的信号 + + 1, 1, 0, 1, // 6: yellow + 1, 0, 1, 1, // 7: strange purple + + 0, 1, 0, .5, // 8: (l L) weak 0 + 0, 1, 1, .5, // 9: (h H) weak 1 + 1, 0, 0, .5, // 10: (w W) weak unknown + + 0, 0, 1, 0.1, // 11: 高阻态 Z 遮罩 + 0.2, 0.847, 0.1, 0.1, // 12: value = 0 遮罩 + 0.2, 0.847, 0.1, 0.1, // 13: value = 1 遮罩 + 0.9, 0.2, 0.2, 0.1, // 14: 未知态 X 遮罩 + .5, 1, 1, 0.1 // 15: vec 遮罩 +]); + + +// 控制方向 +const gl_Shifts = new Float32Array([ // 14 + 0, 0, // 0 + 1, -1, // 1 + 1, 0, // 2 + 1, 1, // 3 + -1, -1, // 4 + -1, 0, // 5 + -1, 1 // 6 +]); + +const gl_Shifts_map = new Map(); +gl_Shifts_map.set(-1, 4); +gl_Shifts_map.set(0, 0); +gl_Shifts_map.set(1, 1); + +const lineWidth = 0.004 * 3800 / screenWidthPixel; // 不能写为 0.0045 这样会因为插值造成不同线段的宽度不一致的问题 +const widthShift = lineWidth / 2; +const gl_WidthShifts = new Float32Array([ + 0, widthShift, // 0 + - widthShift, widthShift, // 1 + - widthShift, 0, // 2 + - widthShift, - widthShift, // 3 + 0, - widthShift, // 4 + widthShift, - widthShift, // 5 + widthShift, 0, // 6 + widthShift, widthShift // 7 +]); + + +export { + getRatio, + gl_Colors, + gl_Shifts, + lineWidth, + widthShift, + gl_WidthShifts, + gl_Shifts_map, + screenWidthPixel, + screenHeightPixel +}; \ No newline at end of file diff --git a/test/render-line/webgl.drawio b/test/render-line/webgl.drawio index 11e7f20..87294c2 100644 --- a/test/render-line/webgl.drawio +++ b/test/render-line/webgl.drawio @@ -1,13 +1,13 @@ - + - + - + @@ -148,424 +148,538 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +