WebGL的全称为Web Graphic Library(网页图形库),主要用于交互式渲染2D图形和3D图形。目前OpenHarmony中使用的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主要帮助开发者在前端开发中完成图形图像的相关处理,比如绘制彩色图形等。
说明:
目前该功能仅支持使用兼容JS的类Web开发范式开发。
接口说明
表1 WebGL主要接口列表
接口名 | 描述 | |
---|---|---|
canvas.getContext | 获取canvas对象上下文。 | |
webgl.createBuffer(): WebGLBuffer | null | 创建与初始化WebGL数据缓冲区。 |
webgl.bindBuffer(target: GLenum, buffer: WebGLBuffer | null): void | 将WebGL数据缓冲区与目标进行绑定。 |
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 | 清空<canvas>指定的颜色。 | |
webgl.clear(mask: GLbitfield): void | 清空<canvas>。 | |
webgl.drawArrays(mode: GLenum, first:;GLint, count: GLsizei): void | 执行数据绘制。 | |
webgl.flush(): void | 刷新数据至GPU,清空缓冲区。 | |
webgl.createProgram(): WebGLProgram | null | 创建着色器程序对象。 |
开发步骤
以下分别展示无着色器绘制2D图形和着色器绘制彩色三角形的两个场景示例及开发过程。
说明: 使用WebGL开发时,为保证界面图形显示效果,请使用真机运行。
无着色器绘制2D图形
此场景为未使用WebGL绘制的2D图形(CPU绘制非GPU绘制)。开发示例如下:
- 创建页面布局。index.hml示例如下:
<div class="container">
<canvas ref="canvas1" style="width : 400px; height : 200px; background-color : lightyellow;"></canvas>
<button class="btn-button" onclick="BtnDraw2D">BtnDraw2D</button>
</div>
- 设置页面样式。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;
}
- 编辑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();
}
}
图1 点击按钮绘制2D图形的效果图
着色器绘制彩色三角形
此场景为使用WebGL绘制的彩色三角形图形(GPU绘制)。开发示例如下:
- 创建页面布局。index.hml示例如下:
<div class="container">
<canvas ref="canvas1" style="width : 400px; height : 200px; background-color : lightyellow;"></canvas>
<button class="btn-button" onclick="BtnColorTriangle">BtnColorTriangle</button>
</div>
- 设置页面样式。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;
}
- 编辑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 点击按钮绘制彩色三角形的效果图