鸿蒙WebGL开发入门

WebGL的全称为Web Graphic Library(网页图形库),主要用于交互式渲染2D图形和3D图形。目前HarmonyOS中使用的WebGL是基于OpenGL裁剪的OpenGL ES,可以在HTML5的canvas元素对象中使用,无需使用插件,支持跨平台。WebGL程序是由JavaScript代码组成的,其中使用的API可以利用用户设备提供的GPU硬件完成图形渲染和加速。

基本概念

着色器

可以理解为运行在显卡中的指令和数据。在WebGL中,着色器是用OpenGL ES着色语言(GLSL)编写的。

完整的着色器包括顶点着色器和片元着色器。顶点着色器和片元着色器的交互则涉及到图片光栅化。

  • 顶点着色器:最基本的任务是接收三维空间中点的坐标,将其处理为二维空间中的坐标并输出。
  • 片元着色器:最基本的任务是对需要处理的屏幕上的每个像素输出一个颜色值。
  • 图片光栅化:将顶点着色器输出的二维空间中的点坐标,转化为需要处理的像素并传递给片元着色器的过程。

缓冲区

驻存于内存中的JavaScript对象,存储着即将推送到着色器中的attribute对象。

着色器程序

将缓冲区中的数据推送到着色器中还需涉及"着色器程序",一个负责关联着色器和缓冲区的JavaScript对象。一个WebGLProgram 对象由两个编译过后的 WebGLShader 组成,即顶点着色器和片段着色器(均由 GLSL 语言所写)。

运作机制

图1 WebGL运作机制

  • 应用前端HTML5绘制界面组件。
  • Native API完成前端JavaScript与C++代码交互。
  • JavaScript engine为图形框架,为WebGL模块提供绘制对象Surface。
  • WebGL模块对外暴露OpenGL ES的GPU绘制接口。
  • 中间接口层EGL(Embedded Graphics Library)完成不同平台的适配。

WebGL快速入门

接口说明

表1 WebGL主要接口列表

接口名 描述
canvas.getContext 获取canvas对象上下文。
webgl.createBuffer(): WebGLBuffer null
webgl.bindBuffer(target: GLenum, buffer: WebGLBuffer null): void
webgl.bufferData(target: GLenum, srcData: ArrayBufferView, usage: GLenum, srcOffset: GLuint, length?: GLuint): void 创建并初始化WebGL的数据存储区。
webgl.getAttribLocation(program: WebGLProgram, name: string): GLint 从给定WebGL着色程序中获取着色器中attribute变量的地址。
webgl.vertexAttribPointer(index GLuint, size: GLint, type: GLenum, normalized: GLboolean, stride: GLsizei, offset: GLintptr): void 将缓冲区对象分配给变量。
webgl.enableVertexAttribArray(index: GLuint): void 连接变量与分配给它的缓冲区对象。
webgl.clearColor(red: GLclampf, green:GLclampf, blue: GLclampf, alpha: GLclampf): void 清空指定的颜色。
webgl.clear(mask: GLbitfield): void 清空。
webgl.drawArrays(mode: GLenum, first:;GLint, count: GLsizei): void 执行数据绘制。
webgl.flush(): void 刷新数据至GPU,清空缓冲区。
webgl.createProgram(): WebGLProgram null

开发步骤

以下分别展示无着色器绘制2D图形和着色器绘制彩色三角形的两个场景示例及开发过程。

无着色器绘制2D图形

此场景为未使用WebGL绘制的2D图形(CPU绘制非GPU绘制)。开发示例如下:

  1. 创建页面布局。index.hml示例如下:

    <canvas ref="canvas1" style="width : 400px; height : 200px; background-color : lightyellow;"></canvas> <button class="btn-button" onclick="BtnDraw2D">BtnDraw2D</button>
  2. 设置页面样式。index.css示例如下:

    .container {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    }
    .btn-button {
    margin: 1px;
    height: 40px;
    width: 220px;
    background-color: lightblue;
    font-size: 20px;
    text-color: blue;
    }

  3. 编辑JavaScript代码文件,增加2D绘制逻辑代码。index.js示例如下:

    // index.js
    export default {//NAPI交互代码
    data: {
    title: "DEMO BY TEAMOL",
    fit:"cover",
    fits: ["cover", "contain", "fill", "none", "scale-down"]
    },
    onInit() {
    this.title = this.t('strings.world'); }, BtnDraw2D(){ // 获取canvas元素 const canvas = this.refs.canvas1;
    // 获取2D上下文
    const ctx = canvas.getContext('2d');

    复制代码
         // 执行CPU绘制函数
         // Set line width
         ctx.lineWidth = 10;
         // Wall
         ctx.strokeRect(75, 140, 150, 110);
         // Door
         ctx.fillRect(130, 190, 40, 60);
         // Roof
         ctx.beginPath();
         ctx.moveTo(50, 140);
         ctx.lineTo(150, 60);
         ctx.lineTo(250, 140);
         ctx.closePath();
         ctx.stroke();
     }

    }

对应的运行效果如下:

着色器绘制彩色三角形

此场景为使用WebGL绘制的彩色三角形图形(GPU绘制)。开发示例如下:

  1. 创建页面布局。index.hml示例如下:

    <canvas ref="canvas1" style="width : 400px; height : 200px; background-color : lightyellow;"></canvas> <button class="btn-button" onclick="BtnColorTriangle">BtnColorTriangle</button>

2,设置页面样式。index.css示例如下:

复制代码
.container {
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
.btn-button {
    margin: 1px;
    height: 40px;
    width: 220px;
    background-color: lightblue;
    font-size: 20px;
    text-color: blue;
}

3,编辑JavaScript代码文件,增加彩色三角形绘制逻辑代码。index.js示例如下:

复制代码
// index.js

// WebGL相关预定义
var gl = {
    DEPTH_BUFFER_BIT: 0x00000100,
    STENCIL_BUFFER_BIT: 0x00000400,
    COLOR_BUFFER_BIT: 0x00004000,
    POINTS: 0x0000,
    LINES: 0x0001,
    LINE_LOOP: 0x0002,
    LINE_STRIP: 0x0003,
    TRIANGLES: 0x0004,
    TRIANGLE_STRIP: 0x0005,
    TRIANGLE_FAN: 0x0006,
    ZERO: 0,
    ONE: 1,
    SRC_COLOR: 0x0300,
    ONE_MINUS_SRC_COLOR: 0x0301,
    SRC_ALPHA: 0x0302,
    ONE_MINUS_SRC_ALPHA: 0x0303,
    DST_ALPHA: 0x0304,
    ONE_MINUS_DST_ALPHA: 0x0305,
    DST_COLOR: 0x0306,
    ONE_MINUS_DST_COLOR: 0x0307,
    SRC_ALPHA_SATURATE: 0x0308,
    FUNC_ADD: 0x8006,
    BLEND_EQUATION: 0x8009,
    BLEND_EQUATION_RGB: 0x8009,
    BLEND_EQUATION_ALPHA: 0x883D,
    FUNC_SUBTRACT: 0x800A,
    FUNC_REVERSE_SUBTRACT: 0x800B,
    BLEND_DST_RGB: 0x80C8,
    BLEND_SRC_RGB: 0x80C9,
    BLEND_DST_ALPHA: 0x80CA,
    BLEND_SRC_ALPHA: 0x80CB,
    CONSTANT_COLOR: 0x8001,
    ONE_MINUS_CONSTANT_COLOR: 0x8002,
    CONSTANT_ALPHA: 0x8003,
    ONE_MINUS_CONSTANT_ALPHA: 0x8004,
    BLEND_COLOR: 0x8005,
    ARRAY_BUFFER: 0x8892,
    ELEMENT_ARRAY_BUFFER: 0x8893,
    ARRAY_BUFFER_BINDING: 0x8894,
    ELEMENT_ARRAY_BUFFER_BINDING: 0x8895,
    STREAM_DRAW: 0x88E0,
    STATIC_DRAW: 0x88E4,
    DYNAMIC_DRAW: 0x88E8,
    BUFFER_SIZE: 0x8764,
    BUFFER_USAGE: 0x8765,
    CURRENT_VERTEX_ATTRIB: 0x8626,
    FRONT: 0x0404,
    BACK: 0x0405,
    FRONT_AND_BACK: 0x0408,
    CULL_FACE: 0x0B44,
    BLEND: 0x0BE2,
    DITHER: 0x0BD0,
    STENCIL_TEST: 0x0B90,
    DEPTH_TEST: 0x0B71,
    SCISSOR_TEST: 0x0C11,
    POLYGON_OFFSET_FILL: 0x8037,
    SAMPLE_ALPHA_TO_COVERAGE: 0x809E,
    SAMPLE_COVERAGE: 0x80A0,
    NO_ERROR: 0,
    INVALID_ENUM: 0x0500,
    INVALID_VALUE: 0x0501,
    INVALID_OPERATION: 0x0502,
    OUT_OF_MEMORY: 0x0505,
    CW: 0x0900,
    CCW: 0x0901,
    LINE_WIDTH: 0x0B21,
    ALIASED_POINT_SIZE_RANGE: 0x846D,
    ALIASED_LINE_WIDTH_RANGE: 0x846E,
    CULL_FACE_MODE: 0x0B45,
    FRONT_FACE: 0x0B46,
    DEPTH_RANGE: 0x0B70,
    DEPTH_WRITEMASK: 0x0B72,
    DEPTH_CLEAR_VALUE: 0x0B73,
    DEPTH_FUNC: 0x0B74,
    STENCIL_CLEAR_VALUE: 0x0B91,
    STENCIL_FUNC: 0x0B92,
    STENCIL_FAIL: 0x0B94,
    STENCIL_PASS_DEPTH_FAIL: 0x0B95,
    STENCIL_PASS_DEPTH_PASS: 0x0B96,
    STENCIL_REF: 0x0B97,
    STENCIL_VALUE_MASK: 0x0B93,
    STENCIL_WRITEMASK: 0x0B98,
    STENCIL_BACK_FUNC: 0x8800,
    STENCIL_BACK_FAIL: 0x8801,
    STENCIL_BACK_PASS_DEPTH_FAIL: 0x8802,
    STENCIL_BACK_PASS_DEPTH_PASS: 0x8803,
    STENCIL_BACK_REF: 0x8CA3,
    STENCIL_BACK_VALUE_MASK: 0x8CA4,
    STENCIL_BACK_WRITEMASK: 0x8CA5,
    VIEWPORT: 0x0BA2,
    SCISSOR_BOX: 0x0C10,
    COLOR_CLEAR_VALUE: 0x0C22,
    COLOR_WRITEMASK: 0x0C23,
    UNPACK_ALIGNMENT: 0x0CF5,
    PACK_ALIGNMENT: 0x0D05,
    MAX_TEXTURE_SIZE: 0x0D33,
    MAX_VIEWPORT_DIMS: 0x0D3A,
    SUBPIXEL_BITS: 0x0D50,
    RED_BITS: 0x0D52,
    GREEN_BITS: 0x0D53,
    BLUE_BITS: 0x0D54,
    ALPHA_BITS: 0x0D55,
    DEPTH_BITS: 0x0D56,
    STENCIL_BITS: 0x0D57,
    POLYGON_OFFSET_UNITS: 0x2A00,
    POLYGON_OFFSET_FACTOR: 0x8038,
    TEXTURE_BINDING_2D: 0x8069,
    SAMPLE_BUFFERS: 0x80A8,
    SAMPLES: 0x80A9,
    RGBA8: 0x8058,
    SAMPLE_COVERAGE_VALUE: 0x80AA,
    SAMPLE_COVERAGE_INVERT: 0x80AB,
    COMPRESSED_TEXTURE_FORMATS: 0x86A3,
    DONT_CARE: 0x1100,
    FASTEST: 0x1101,
    NICEST: 0x1102,
    GENERATE_MIPMAP_HINT: 0x8192,
    BYTE: 0x1400,
    UNSIGNED_BYTE: 0x1401,
    SHORT: 0x1402,
    UNSIGNED_SHORT: 0x1403,
    INT: 0x1404,
    UNSIGNED_INT: 0x1405,
    FLOAT: 0x1406,
    DEPTH_COMPONENT: 0x1902,
    ALPHA: 0x1906,
    RGB: 0x1907,
    RGBA: 0x1908,
    LUMINANCE: 0x1909,
    LUMINANCE_ALPHA: 0x190A,
    UNSIGNED_SHORT_4_4_4_4: 0x8033,
    UNSIGNED_SHORT_5_5_5_1: 0x8034,
    UNSIGNED_SHORT_5_6_5: 0x8363,
    FRAGMENT_SHADER: 0x8B30,
    VERTEX_SHADER: 0x8B31,
    MAX_VERTEX_ATTRIBS: 0x8869,
    MAX_VERTEX_UNIFORM_VECTORS: 0x8DFB,
    MAX_VARYING_VECTORS: 0x8DFC,
    MAX_COMBINED_TEXTURE_IMAGE_UNITS: 0x8B4D,
    MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8B4C,
    MAX_TEXTURE_IMAGE_UNITS: 0x8872,
    MAX_FRAGMENT_UNIFORM_VECTORS: 0x8DFD,
    SHADER_TYPE: 0x8B4F,
    DELETE_STATUS: 0x8B80,
    LINK_STATUS: 0x8B82,
    VALIDATE_STATUS: 0x8B83,
    ATTACHED_SHADERS: 0x8B85,
    ACTIVE_UNIFORMS: 0x8B86,
    ACTIVE_ATTRIBUTES: 0x8B89,
    SHADING_LANGUAGE_VERSION: 0x8B8C,
    CURRENT_PROGRAM: 0x8B8D,
    NEVER: 0x0200,
    LESS: 0x0201,
    EQUAL: 0x0202,
    LEQUAL: 0x0203,
    GREATER: 0x0204,
    NOTEQUAL: 0x0205,
    GEQUAL: 0x0206,
    ALWAYS: 0x0207,
    KEEP: 0x1E00,
    REPLACE: 0x1E01,
    INCR: 0x1E02,
    DECR: 0x1E03,
    INVERT: 0x150A,
    INCR_WRAP: 0x8507,
    DECR_WRAP: 0x8508,
    VENDOR: 0x1F00,
    RENDERER: 0x1F01,
    VERSION: 0x1F02,
    NEAREST: 0x2600,
    LINEAR: 0x2601,
    NEAREST_MIPMAP_NEAREST: 0x2700,
    LINEAR_MIPMAP_NEAREST: 0x2701,
    NEAREST_MIPMAP_LINEAR: 0x2702,
    LINEAR_MIPMAP_LINEAR: 0x2703,
    TEXTURE_MAG_FILTER: 0x2800,
    TEXTURE_MIN_FILTER: 0x2801,
    TEXTURE_WRAP_S: 0x2802,
    TEXTURE_WRAP_T: 0x2803,
    TEXTURE_2D: 0x0DE1,
    TEXTURE: 0x1702,
    TEXTURE_CUBE_MAP: 0x8513,
    TEXTURE_BINDING_CUBE_MAP: 0x8514,
    TEXTURE_CUBE_MAP_POSITIVE_X: 0x8515,
    TEXTURE_CUBE_MAP_NEGATIVE_X: 0x8516,
    TEXTURE_CUBE_MAP_POSITIVE_Y: 0x8517,
    TEXTURE_CUBE_MAP_NEGATIVE_Y: 0x8518,
    TEXTURE_CUBE_MAP_POSITIVE_Z: 0x8519,
    TEXTURE_CUBE_MAP_NEGATIVE_Z: 0x851A,
    MAX_CUBE_MAP_TEXTURE_SIZE: 0x851C,
    TEXTURE0: 0x84C0,
    TEXTURE1: 0x84C1,
    TEXTURE2: 0x84C2,
    TEXTURE3: 0x84C3,
    TEXTURE4: 0x84C4,
    TEXTURE5: 0x84C5,
    TEXTURE6: 0x84C6,
    TEXTURE7: 0x84C7,
    TEXTURE8: 0x84C8,
    TEXTURE9: 0x84C9,
    TEXTURE10: 0x84CA,
    TEXTURE11: 0x84CB,
    TEXTURE12: 0x84CC,
    TEXTURE13: 0x84CD,
    TEXTURE14: 0x84CE,
    TEXTURE15: 0x84CF,
    TEXTURE16: 0x84D0,
    TEXTURE17: 0x84D1,
    TEXTURE18: 0x84D2,
    TEXTURE19: 0x84D3,
    TEXTURE20: 0x84D4,
    TEXTURE21: 0x84D5,
    TEXTURE22: 0x84D6,
    TEXTURE23: 0x84D7,
    TEXTURE24: 0x84D8,
    TEXTURE25: 0x84D9,
    TEXTURE26: 0x84DA,
    TEXTURE27: 0x84DB,
    TEXTURE28: 0x84DC,
    TEXTURE29: 0x84DD,
    TEXTURE30: 0x84DE,
    TEXTURE31: 0x84DF,
    ACTIVE_TEXTURE: 0x84E0,
    REPEAT: 0x2901,
    CLAMP_TO_EDGE: 0x812F,
    MIRRORED_REPEAT: 0x8370,
    FLOAT_VEC2: 0x8B50,
    FLOAT_VEC3: 0x8B51,
    FLOAT_VEC4: 0x8B52,
    INT_VEC2: 0x8B53,
    INT_VEC3: 0x8B54,
    INT_VEC4: 0x8B55,
    BOOL: 0x8B56,
    BOOL_VEC2: 0x8B57,
    BOOL_VEC3: 0x8B58,
    BOOL_VEC4: 0x8B59,
    FLOAT_MAT2: 0x8B5A,
    FLOAT_MAT3: 0x8B5B,
    FLOAT_MAT4: 0x8B5C,
    SAMPLER_2D: 0x8B5E,
    SAMPLER_CUBE: 0x8B60,
    VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622,
    VERTEX_ATTRIB_ARRAY_SIZE: 0x8623,
    VERTEX_ATTRIB_ARRAY_STRIDE: 0x8624,
    VERTEX_ATTRIB_ARRAY_TYPE: 0x8625,
    VERTEX_ATTRIB_ARRAY_NORMALIZED: 0x886A,
    VERTEX_ATTRIB_ARRAY_POINTER: 0x8645,
    VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 0x889F,
    IMPLEMENTATION_COLOR_READ_TYPE: 0x8B9A,
    IMPLEMENTATION_COLOR_READ_FORMAT: 0x8B9B,
    COMPILE_STATUS: 0x8B81,
    LOW_FLOAT: 0x8DF0,
    MEDIUM_FLOAT: 0x8DF1,
    HIGH_FLOAT: 0x8DF2,
    LOW_INT: 0x8DF3,
    MEDIUM_INT: 0x8DF4,
    HIGH_INT: 0x8DF5,
    FRAMEBUFFER: 0x8D40,
    RENDERBUFFER: 0x8D41,
    RGBA4: 0x8056,
    RGB5_A1: 0x8057,
    RGB565: 0x8D62,
    DEPTH_COMPONENT16: 0x81A5,
    STENCIL_INDEX8: 0x8D48,
    DEPTH_STENCIL: 0x84F9,
    RENDERBUFFER_WIDTH: 0x8D42,
    RENDERBUFFER_HEIGHT: 0x8D43,
    RENDERBUFFER_INTERNAL_FORMAT: 0x8D44,
    RENDERBUFFER_RED_SIZE: 0x8D50,
    RENDERBUFFER_GREEN_SIZE: 0x8D51,
    RENDERBUFFER_BLUE_SIZE: 0x8D52,
    RENDERBUFFER_ALPHA_SIZE: 0x8D53,
    RENDERBUFFER_DEPTH_SIZE: 0x8D54,
    RENDERBUFFER_STENCIL_SIZE: 0x8D55,
    FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 0x8CD0,
    FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 0x8CD1,
    FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 0x8CD2,
    FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 0x8CD3,
    COLOR_ATTACHMENT0: 0x8CE0,
    DEPTH_ATTACHMENT: 0x8D00,
    STENCIL_ATTACHMENT: 0x8D20,
    DEPTH_STENCIL_ATTACHMENT: 0x821A,
    NONE: 0,
    FRAMEBUFFER_COMPLETE: 0x8CD5,
    FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 0x8CD6,
    FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 0x8CD7,
    FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 0x8CD9,
    FRAMEBUFFER_UNSUPPORTED: 0x8CDD,
    FRAMEBUFFER_BINDING: 0x8CA6,
    RENDERBUFFER_BINDING: 0x8CA7,
    MAX_RENDERBUFFER_SIZE: 0x84E8,
    INVALID_FRAMEBUFFER_OPERATION: 0x0506,
    UNPACK_FLIP_Y_WEBGL: 0x9240,
    UNPACK_PREMULTIPLY_ALPHA_WEBGL: 0x9241,
    CONTEXT_LOST_WEBGL: 0x9242,
    UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243,
    BROWSER_DEFAULT_WEBGL: 0x9244,
    TEXTURE_MAX_LOD: 0x813B,
    TEXTURE_BASE_LEVEL: 0x813C,
    TEXTURE_IMMUTABLE_FORMAT: 0x912F,
    UNIFORM_BLOCK_BINDING: 0x8A3F,
    UNIFORM_BLOCK_DATA_SIZE: 0x8A40,
    UNIFORM_BLOCK_ACTIVE_UNIFORMS: 0x8A42,
    UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 0x8A43,
    UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 0x8A44,
    UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 0x8A46,
    RED: 0x1903,
    PIXEL_UNPACK_BUFFER: 0x88EC,
    RGB8: 0x8051,
    R16F: 0x822D,
    COPY_WRITE_BUFFER: 0x8F37,
    TEXTURE_3D: 0x806F,
    COMPRESSED_R11_EAC: 0x9270,
    COPY_READ_BUFFER: 0x8F36,
    TRANSFORM_FEEDBACK_BUFFER: 0x8C8E,
    TRANSFORM_FEEDBACK_BUFFER_BINDING: 0x8C8F,
    TRANSFORM_FEEDBACK_BUFFER_SIZE: 0x8C85,
    TRANSFORM_FEEDBACK_BUFFER_START: 0x8C84,
    UNIFORM_BUFFER_BINDING: 0x8A28,
    UNIFORM_BUFFER_SIZE: 0x8A2A,
    UNIFORM_BUFFER_START: 0x8A29,
    DYNAMIC_READ: 0x88E9,
    READ_FRAMEBUFFER: 0x8CA8,
    COLOR_ATTACHMENT1: 0x8CE1,
    INTERLEAVED_ATTRIBS: 0x8C8C,
    UNIFORM_OFFSET: 0x8A3B,
    UNIFORM_TYPE: 0x8A37,
    UNIFORM_SIZE: 0x8A38,
    UNIFORM_BLOCK_INDEX: 0x8A3A,
    UNIFORM_ARRAY_STRIDE: 0x8A3C,
    UNIFORM_MATRIX_STRIDE: 0x8A3D,
    UNIFORM_IS_ROW_MAJOR: 0x8A3E,
    TEXTURE_MAX_ANISOTROPY_EXT: 0x84FE
}

// 顶点着色器程序
var VSHADER_SOURCE =
    'attribute vec4 a_Position;\n' + // attribute variable
    'attribute vec4 a_Color;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_Position = a_Position;\n' + // Set the vertex coordinates of the point
    '  v_Color = a_Color;\n' +
    '}\n';

// 片元着色器程序
var FSHADER_SOURCE =
    'precision mediump float;\n' +
    'varying vec4 v_Color;\n' +
    'void main() {\n' +
    '  gl_FragColor = v_Color;\n' +
    '}\n';

function initVertexBuffers(gl) {
    // 顶点坐标和颜色
    var verticesColors = new Float32Array([
        0.0, -0.5, 1.0, 0.0, 0.0,
        -0.5, -0.8, 0.0, 1.0, 0.0,
        0.5, -0.8, 0.0, 0.0, 1.0,
    ]);

    var n = 3; // 点的个数
    var FSIZE = verticesColors.BYTES_PER_ELEMENT; //数组中每个元素的字节数

    // 创建缓冲区对象
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
        console.log('Failed to create the buffer object');
        return -1;
    }

    // 将缓冲区对象绑定到目标
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    // 向缓冲区对象写入数据
    gl.bufferData(gl.ARRAY_BUFFER, verticesColors.buffer, gl.STATIC_DRAW);


    // 获取着色器中attribute变量a_Position的地址
    var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if (a_Position < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }
    // 将缓冲区对象分配给a_Position变量
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 5 * FSIZE, 0);

    // 连接a_Position变量与分配给它的缓冲区对象
    gl.enableVertexAttribArray(a_Position);

    // 获取着色器中attribute变量a_Color的地址
    var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
    if (a_Color < 0) {
        console.log('Failed to get the storage location of a_Color');
        return -1;
    }
    // 将缓冲区对象分配给a_Color变量
    gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2);

    // 连接a_Color变量与分配给它的缓冲区对象
    gl.enableVertexAttribArray(a_Color);

    // 解除绑定
    gl.bindBuffer(gl.ARRAY_BUFFER, null);

    return n;
}

/**
 * 创建并使能一个program对象
 * @param gl 表示 WebGL上下文对
 * @param vshader 表示顶点着色器
 * @param fshader 表示片段着色器
 * @return 如果WebGLProgram对象被创建并成功作为当前对象,则返回true;否则返回false 
 */
function initShaders(gl, vshader, fshader) {
    var program = createProgram(gl, vshader, fshader);
    console.log("======createProgram program: " + program);
    if (!program) {
        console.log('Failed to create program');
        return false;
    }
    gl.useProgram(program);
    gl.program = program;
    return true;
}
/**
 * 创建一个linked program对象
 * @param gl 表示 WebGL上下文对象
 * @param vshader 表示顶点着色器
 * @param fshader 表示片段着色器
 * @return 如果创建program成功,则返回创建的program;否则返回null
 */
function createProgram(gl, vshader, fshader) {
    console.log("======createProgram start======");
    // 创建shader对象
    var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshader);
    console.log("======vertexShader: " + vertexShader);
    var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshader);
    if (!vertexShader || !fragmentShader) {
        return null;
    }
    // 创建program对象
    var program = gl.createProgram();
    console.log("======createProgram program: " + program);
    if (!program) {
        return null;
    }
    // 将着色器附加到对象
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    // 连接程序对象
    gl.linkProgram(program);
    // 检查连接对象的结果
    var linked = gl.getProgramParameter(program, 0x8B82);
    console.log("======getProgramParameter linked: " + linked);
    if (!linked) {
        var error = gl.getProgramInfoLog(program);
        console.log('Failed to link the program: ' + error);
        gl.deleteProgram(program);
        gl.deleteShader(fragmentShader);
        gl.deleteShader(vertexShader);
        return null;
    }
    return program;
}
/**
  * 创建一个shader对象
  * @param gl 表示 WebGL上下文对象
  * @param type 表示shader类型
  * @param source 表示shader的源码 
  * @return 如果操作成功,返回创建的着色器对象;否则返回false
  */ 
function loadShader(gl, type, source) {
    console.log("======into loadShader====");
    // 创建shader对象
    var shader = gl.createShader(type);
    if (shader == null) {
        console.log('Failed to create the shader.');
        return null;
    }

    // 设置shader program
    gl.shaderSource(shader, source);

    // 编译shader
    gl.compileShader(shader);

    // 检查shader编译结果
    var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (!compiled) {
        var error = gl.getShaderInfoLog(shader);
        console.log('Failed to compile the shader: ' + error);
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}
export default {
    data: {
        title: "DEMO BY TEAMOL",
        fit:"cover",
        fits: ["cover", "contain", "fill", "none", "scale-down"]
    }
    ,onInit() {
        this.title = this.$t('strings.world');
    }
    ,BtnColorTriangle() {
        // 获取canvas元素
        const el = this.$refs.canvas1;
        // 获取webgl上下文
        var gl = el.getContext('webgl');

        if (!gl) {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }

        // 初始化着色器
        if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
            console.log('Failed to initialize shaders.');
            return;
        }

        // 设置顶点位置
        var n = initVertexBuffers(gl);
        if (n < 0) {
            console.log('Failed to set the positions of the vertices');
            return;
        }

        // 指定清空<canvas>的颜色
        gl.clearColor(0.0, 0.0, 0.0, 1.0);

        // 清空<canvas>
        gl.clear(gl.COLOR_BUFFER_BIT);

        // 绘制三角形
        gl.drawArrays(gl.TRIANGLES, 0, n);


        // 清buffer
        gl.flush();
    }
}

对应的运行效果如下:

相关推荐
晚秋大魔王2 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
Modify_QmQ2 小时前
WebGL图形编程实战【6】:性能优化 × 调试工具与技巧精讲
性能优化·webgl·webgl-lint·webgl-inspector
python算法(魔法师版)5 小时前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc7 小时前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹48 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
ax一号街阿楠9 小时前
华为FAT AP配置 真机
网络·华为·智能路由器
吗喽对你问好10 小时前
华为5.7机考第一题充电桩问题Java代码实现
java·华为·排序
乱世刀疤12 小时前
深度 |国产操作系统“破茧而出”:鸿蒙电脑填补自主生态空白
华为·harmonyos
博睿谷IT99_17 小时前
华为HCIP-AI认证考试版本更新通知
人工智能·华为
连续讨伐17 小时前
ensp的华为小实验
华为