# 和得物技术一起走进Web3D的世界(1) 画个立方体吧

GLSL github.com/wshxbqq/GLS…

# 最终效果

## step1:建立webgl渲染上下文

``const canvasDom = document.getElementById('canvas')gl = canvasDom.getContext('webgl')//开启深度检测``gl.enable(gl.DEPTH_TEST)``

## step2:创建顶点着色器与片元着色器

• 顶点着色器确定了画布上点的位置

• 3d世界中基础的几何图形是三角形，片元着色器代表了区域的表现形式

``const Vertex = `attribute vec3 vPosition;void main() {gl_PointSize = 1.0;gl_Position =  mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)*mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)*vec4(vPosition, 1);}`````

vec3 vPosition 定义了一个3维向量

mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)是一个齐次矩阵 表示绕y轴旋转45度

mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)表示绕z轴旋转45度

``const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, Vertex);``gl.compileShader(vertexShader);``

``const Fragment = `#ifdef GL_ESprecision highp float;#endifvoid main() {gl_FragColor = vec4(1.0,0,0,1.0);}`````

``const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, Fragment);``gl.compileShader(fragmentShader);``

## step3:创建一个程序

``const program = gl.createProgram();``

## step4:链接程序与着色器

``gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);``gl.useProgram(program);``

## step5:建立缓冲数据

cube是用来获取顶点坐标

``//cube是用来获取顶点坐标function cube(size = 1.0) {const h = 0.5 * size;const vertices = [[-h, -h, -h],[-h, h, -h],[h, h, -h],[h, -h, -h],[-h, -h, h],[-h, h, h],[h, h, h],[h, -h, h],];const positions = [];function quad(a, b, c, d, e, f, g, h) {[a, b, c, d, e, f, g, h].forEach((i) => {positions.push(vertices[i]);});}quad(0, 1, 1, 2, 2, 3, 3, 0);quad(4, 5, 5, 6, 6, 7, 7, 4);quad(1, 2, 2, 6, 6, 5, 5, 1);quad(0, 3, 3, 7, 7, 4, 4, 0);quad(0, 1, 1, 5, 5, 4, 4, 0);quad(3, 7, 7, 6, 6, 2, 2, 3);return { positions};}const geometry = cube(1.0);console.log(geometry)const points = new Float32Array(geometry.positions.flat());const bufferId = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);``gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);``

## step6渲染

``const Position = gl.getAttribLocation(program, 'vPosition');//获取顶点着色器中的position变量的地址gl.vertexAttribPointer(Position, 3, gl.FLOAT, false, 0, 0);//给变量设置长度和类型gl.enableVertexAttribArray(Position);//激活这个变量gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)``gl.drawArrays(gl.LINES, 0, 48)``

gl.drawArrays(gl.LINES, 0, 48)就是渲染的api

webgl中有7种图元 (表示怎么画)

gl.POINTS 孤立点 绘制一系列点

gl.LINES 绘制一系列单独线段。每两个点作为端点，线段之间不连接

gl.LINE_STRIP 连续线段 绘制一个线条。即，绘制一系列线段，上一点连接下一点

gl.LINE_LOOP 连续线圈 绘制一个线圈。即，绘制一系列线段，上一点连接下一点，并且最后一点与第一个点相连

gl.TRIANGLES 孤立三角形

gl.TRIANGLE_STRIP 三角带

gl.TRIANGLE_FAN 三角扇

0，48表示从0取48个点绘制

# 完整的代码

``<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>3D立方体</title></head><body><canvas id='canvas' width="800" height="800"></canvas></body><script>// 第一步 创建webgl上下文const canvasDom = document.getElementById('canvas')gl = canvasDom.getContext('webgl')//开启深度检测gl.enable(gl.DEPTH_TEST)console.log(gl)// 第二步 创建顶点着色器与片元着色器const Vertex = `attribute vec3 vPosition;void main() {gl_PointSize = 1.0;gl_Position =  mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)*mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)*vec4(vPosition, 1);}`const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, Vertex);gl.compileShader(vertexShader);const Fragment = `#ifdef GL_ESprecision highp float;#endifvoid main() {gl_FragColor = vec4(1.0,0,0,1.0);}`const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, Fragment);gl.compileShader(fragmentShader);//第三步 创建程序对象const program = gl.createProgram();// 第四步 链接程序与着色器gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);//第五步 建立缓冲数据function cube(size = 1.0) {const h = 0.5 * size;const vertices = [[-h, -h, -h],[-h, h, -h],[h, h, -h],[h, -h, -h],[-h, -h, h],[-h, h, h],[h, h, h],[h, -h, h],];const positions = [];function quad(a, b, c, d, e, f, g, h) {[a, b, c, d, e, f, g, h].forEach((i) => {positions.push(vertices[i]);});}quad(0, 1, 1, 2, 2, 3, 3, 0);quad(4, 5, 5, 6, 6, 7, 7, 4);quad(1, 2, 2, 6, 6, 5, 5, 1);quad(0, 3, 3, 7, 7, 4, 4, 0);quad(0, 1, 1, 5, 5, 4, 4, 0);quad(3, 7, 7, 6, 6, 2, 2, 3);return { positions};}const geometry = cube(1.0);console.log(geometry)const points = new Float32Array(geometry.positions.flat());const bufferId = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);// 第六步 渲染const Position = gl.getAttribLocation(program, 'vPosition');//获取顶点着色器中的position变量的地址gl.vertexAttribPointer(Position, 3, gl.FLOAT, false, 0, 0);//给变量设置长度和类型gl.enableVertexAttribArray(Position);//激活这个变量gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)gl.drawArrays(gl.LINES, 0, 48)</script>``</html>``

##### 得物技术

31 声望

4 粉丝

0 条评论

GLSL github.com/wshxbqq/GLS…

# 最终效果

## step1:建立webgl渲染上下文

``const canvasDom = document.getElementById('canvas')gl = canvasDom.getContext('webgl')//开启深度检测``gl.enable(gl.DEPTH_TEST)``

## step2:创建顶点着色器与片元着色器

• 顶点着色器确定了画布上点的位置

• 3d世界中基础的几何图形是三角形，片元着色器代表了区域的表现形式

``const Vertex = `attribute vec3 vPosition;void main() {gl_PointSize = 1.0;gl_Position =  mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)*mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)*vec4(vPosition, 1);}`````

vec3 vPosition 定义了一个3维向量

mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)是一个齐次矩阵 表示绕y轴旋转45度

mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)表示绕z轴旋转45度

``const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, Vertex);``gl.compileShader(vertexShader);``

``const Fragment = `#ifdef GL_ESprecision highp float;#endifvoid main() {gl_FragColor = vec4(1.0,0,0,1.0);}`````

``const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, Fragment);``gl.compileShader(fragmentShader);``

## step3:创建一个程序

``const program = gl.createProgram();``

## step4:链接程序与着色器

``gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);``gl.useProgram(program);``

## step5:建立缓冲数据

cube是用来获取顶点坐标

``//cube是用来获取顶点坐标function cube(size = 1.0) {const h = 0.5 * size;const vertices = [[-h, -h, -h],[-h, h, -h],[h, h, -h],[h, -h, -h],[-h, -h, h],[-h, h, h],[h, h, h],[h, -h, h],];const positions = [];function quad(a, b, c, d, e, f, g, h) {[a, b, c, d, e, f, g, h].forEach((i) => {positions.push(vertices[i]);});}quad(0, 1, 1, 2, 2, 3, 3, 0);quad(4, 5, 5, 6, 6, 7, 7, 4);quad(1, 2, 2, 6, 6, 5, 5, 1);quad(0, 3, 3, 7, 7, 4, 4, 0);quad(0, 1, 1, 5, 5, 4, 4, 0);quad(3, 7, 7, 6, 6, 2, 2, 3);return { positions};}const geometry = cube(1.0);console.log(geometry)const points = new Float32Array(geometry.positions.flat());const bufferId = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);``gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);``

## step6渲染

``const Position = gl.getAttribLocation(program, 'vPosition');//获取顶点着色器中的position变量的地址gl.vertexAttribPointer(Position, 3, gl.FLOAT, false, 0, 0);//给变量设置长度和类型gl.enableVertexAttribArray(Position);//激活这个变量gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)``gl.drawArrays(gl.LINES, 0, 48)``

gl.drawArrays(gl.LINES, 0, 48)就是渲染的api

webgl中有7种图元 (表示怎么画)

gl.POINTS 孤立点 绘制一系列点

gl.LINES 绘制一系列单独线段。每两个点作为端点，线段之间不连接

gl.LINE_STRIP 连续线段 绘制一个线条。即，绘制一系列线段，上一点连接下一点

gl.LINE_LOOP 连续线圈 绘制一个线圈。即，绘制一系列线段，上一点连接下一点，并且最后一点与第一个点相连

gl.TRIANGLES 孤立三角形

gl.TRIANGLE_STRIP 三角带

gl.TRIANGLE_FAN 三角扇

0，48表示从0取48个点绘制

# 完整的代码

``<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>3D立方体</title></head><body><canvas id='canvas' width="800" height="800"></canvas></body><script>// 第一步 创建webgl上下文const canvasDom = document.getElementById('canvas')gl = canvasDom.getContext('webgl')//开启深度检测gl.enable(gl.DEPTH_TEST)console.log(gl)// 第二步 创建顶点着色器与片元着色器const Vertex = `attribute vec3 vPosition;void main() {gl_PointSize = 1.0;gl_Position =  mat4(1,0, 0, 0 ,0, 0.52, -0.85, 0, 0, 0.85, 0.52, 0, 0, 0, 0,1)*mat4(0.52,0, 0.85, 0 ,0, 1, 0, 0, -0.85, 0, 0.52, 0, 0, 0, 0,1)*vec4(vPosition, 1);}`const vertexShader = gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vertexShader, Vertex);gl.compileShader(vertexShader);const Fragment = `#ifdef GL_ESprecision highp float;#endifvoid main() {gl_FragColor = vec4(1.0,0,0,1.0);}`const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fragmentShader, Fragment);gl.compileShader(fragmentShader);//第三步 创建程序对象const program = gl.createProgram();// 第四步 链接程序与着色器gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);gl.useProgram(program);//第五步 建立缓冲数据function cube(size = 1.0) {const h = 0.5 * size;const vertices = [[-h, -h, -h],[-h, h, -h],[h, h, -h],[h, -h, -h],[-h, -h, h],[-h, h, h],[h, h, h],[h, -h, h],];const positions = [];function quad(a, b, c, d, e, f, g, h) {[a, b, c, d, e, f, g, h].forEach((i) => {positions.push(vertices[i]);});}quad(0, 1, 1, 2, 2, 3, 3, 0);quad(4, 5, 5, 6, 6, 7, 7, 4);quad(1, 2, 2, 6, 6, 5, 5, 1);quad(0, 3, 3, 7, 7, 4, 4, 0);quad(0, 1, 1, 5, 5, 4, 4, 0);quad(3, 7, 7, 6, 6, 2, 2, 3);return { positions};}const geometry = cube(1.0);console.log(geometry)const points = new Float32Array(geometry.positions.flat());const bufferId = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);// 第六步 渲染const Position = gl.getAttribLocation(program, 'vPosition');//获取顶点着色器中的position变量的地址gl.vertexAttribPointer(Position, 3, gl.FLOAT, false, 0, 0);//给变量设置长度和类型gl.enableVertexAttribArray(Position);//激活这个变量gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)gl.drawArrays(gl.LINES, 0, 48)</script>``</html>``