前端3D技术起源与发展

1. 3D技术是什么

3D,是three dimensional的缩写,其实就是三维,三个维度。我们的真实世界是三维的(忽略时间),那我们在计算机里,也想能创造类似现实的三维空间,这就促成了计算机三维技术的出现。

2. SGI(硅谷图形公司)与OpenGL

上世纪九十年代初,SGI(硅谷图形公司)崭露头角,专攻3D图形领域,下图是他们当年的logo,代表着当时其先进而卓越的3D技术。
在这里插入图片描述
而这个领域在当年就像现在的虚拟现实技术一样,各个大厂都争先空后的研发,Sun、惠普、IBM都在搞自己的技术和标准,以寻求成为行业领导者。

越来越多的竞争,让SGI市场份额锐减,公司做了一个大胆的决定,将自己公司的3D技术标准IRIS GL转变为开放标准,OpenGL从此诞生。

从企业标准到开放标准的转变,并不是那么容易,一些API的功能,需要交由硬件制造商或操作系统开发商来做,这就导致了IRIS GLOpenGL并不兼容,为了维护客户,SGI必须两套标准一起维护。

问题并没有改变SGI开放标准的决心,1992年,SGI领导创建架构评审委员会(OpenGL ARB),制订和规范OpenGL标准。1995年,微软发布Direct3D,成为新的行业搅局者,1997年,SGI与微软携手合作,旨在统一OpenGLDirect3D标准,一年后,3C巨头惠普也加入进来,但最后无疾而终。

时间最终磨平了一切,OpenGL标准在多轮竞争整最后存活了下来,但SGI公司,却逐渐没落了,2006年3月,SGI公司宣布破产,同年7月,OpenGL架构评审委员会决定讲OpenGL API标准的控制权交给Khronos Group(科纳斯组织),从此,3D标准领域的巨头组织扬帆起航。
在这里插入图片描述

OpenGL官网地址:https://www.opengl.org/

3. Khronos Group(科纳斯组织)

官网地址:https://www.khronos.org/

国内介绍Khronos这个组织的资料不多,这是一个由行业内巨头公司共同组建的免版税开放标准维护组织,旨在指定和规范3D图形化、虚拟现实、并行计算、机器学习等领域的开放标准。组织成员都是行业巨头,见下图。
在这里插入图片描述
经过多年的发展,组织的开放标准已经不再只是OpenGL,分类见下图。
在这里插入图片描述
其实,只要你玩过3D游戏,看过3D动画,都绕不开这些标准。

4. WebGL

在这里插入图片描述

WebGL官网地址:https://www.khronos.org/webgl/

当3D模型技术盛行于客户端开发时,新的尝试开始了,有没有可能在浏览器中使用OpenGL技术,使我们最常用的浏览器支持三维模型的展示,甚至3D游戏的运行。

该标准的API基于OpenGL ES,在前端领域,通过HTML5的Canvas元素承载,暴露符合ECMAScript标准(JavaScript语言的标准)的API。结果就是,我们可以在浏览器里,用js程序载入或创建3D空间,这个场景会创建到一个Canvas元素上运行,大大增加了浏览器程序的能力。

WebGL API接口参考:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

终于到了浏览器,有MDN的文档可以查了,年轻的前端工程师默默撸起了袖子,准备大干一场。但可能马上就会让你失望,『傻孩子们,快跑啊』,这并不是前端领域!

WebGL只是提供了OpenGL的浏览器接口,但核心技术的实现还是依托于OpenGL。看一段MDN上简单的WebGL程序:

MDN上WebGL的Demo源码:https://github.com/mdn/webgl-examples

const canvas = document.querySelector("#glcanvas")
// 初始化WebGL上下文
const gl = canvas.getContext("webgl")
// 创建着色器的方法
function createShader (gl, sourceCode, type) {
  var shader = gl.createShader( type );
  gl.shaderSource( shader, sourceCode );
  gl.compileShader( shader );

  if ( !gl.getShaderParameter(shader, gl.COMPILE_STATUS) ) {
    var info = gl.getShaderInfoLog( shader );
    throw "Could not compile WebGL program. \n\n" + info;
  }
  return shader;
}

var vertexShaderSource =
  "attribute vec4 position;\n"+
  "void main() {\n"+
  "  gl_Position = position;\n"+
  "}\n";

//从上面例子使用 createShader 函数。
var vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER)

var fragmentShaderSource =
  "void main() {\n"+
  "  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"+
  "}\n";

//从上面例子使用 createShader 函数。
var fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER)

前面几行还好理解,获取canvas元素,拿到gl上下文。后面的功能是创建着色器,这是WebGL的核心功能,图像都是用着色器渲染出来的。注意看vertexShaderSourcefragmentShaderSource两个变量,这分别是定点着色器和片段着色器的实际代码,可以看到是一段程序,但是以字符串的形式定义,这明显不是js的语法,这其实是GLSL(OpenGL ES 着色语言),已经不是前端领域了。

GLSL官方文档:https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language

为了证明这一点,我翻阅了three.js的源码,可以看到在three.js里也定义了很多着色器,都是GLSL语法。

three.js源码中的着色器部分: https://github.com/mrdoob/three.js/tree/dev/src/renderers/shaders/ShaderChunk

在这里插入图片描述
所以,想要直接用WebGL开发3D应用是很难的,不是主流前端工程师做的任务,大部分项目还是基于three.js这种库去做的,除非你是在做跟three.js同级别的库,那就要去好好学学GLSL、OpenGL和计算机图形学的相关东西了。

5. three.js

Github地址:https://github.com/mrdoob/three.js

three.js目前在github的star数有81k,已经超过了angular,比它star多的前端包没几个了,大多是框架级别的库。作者是Mr.doob,一个比较传奇的人物,设计师下场写代码。

在这里插入图片描述

ubuntu关于Mr.doob的专访(2011年):https://ubuntu.com/blog/interview-with-mr-doob

three.js的功劳在于,它把WebGL通过JS进行了系统性的封装,提供了很多类与方法,可以直接使用,常用的类有Scene(场景)、Camera(相机)、Mesh(网格体)、Light(灯光)等等。前端工程师不需要陷入WebGL本身的细节当中,而专注于3D应用的功能实现,这大大提高了工作效率、降低了工作难度。

看一个最简单的例子

// 场景
const scene = new THREE.Scene();
// 相机
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// 几何体
const geometry = new THREE.BoxGeometry();
// 材质
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// 网格体
const cube = new THREE.Mesh( geometry, material );
// 加入到模型
scene.add( cube );
// 相机定位
camera.position.z = 5;

这段代码就包括了创建3D空间的大部分要素,这里我们不再需要关系WebGL的底层细节,只要理解场景、相机、渲染器、几何体、材质等等的这些概念,就可以完成代码的编写。使3D技术真正进入了『浏览器时代』!

three.js更具体细节,之后写文章具体讨论。

6. react-three-fiber

Github地址:https://github.com/pmndrs/react-three-fiber

如果当你能熟练使用three.js之后,就会面临一个新问题,如何让three.js与前端开发框架结合,当然这并不是必须的,你用任何前端框架,都可以使用three.js直接进行开发。

问题的关键依然是开发效率可维护性的问题,three.js虽然封装了WebGL的细节,但暴露的API依然是比较基础的,真正做一个比较大型的3D应用,这也是远远不够的,还需要很多生态库去配合,才可以完成日常的大部分需求。

React,毋庸置疑,是目前最先进的前端框架之一,优势在于开发交互和逻辑都较为复杂的前端应用,3D应用本身就具有这种属性,比较适合应用React来开发,但three.js和React之前并没有任何联系,这就给开发带来了割裂行,你会发现在开发过程中无法用到React Hook这些非常好用的功能。

react-three-fiber的出现,就很好的解决了这个问题。如果将一个已经可以熟练使用three.jsReact的前端开发者比作武林高手『金毛狮王谢逊』,那react-three-fiber就是谢逊手里的『屠龙宝刀』,它是前端3D开发领域的一把利器,有了它,你就可以在前端3D领域『大杀四方』了。

官网的酷炫Demo:https://docs.pmnd.rs/react-three-fiber/getting-started/examples

react-three-fiber的主要能力,是充分的利用了React框架的能力,将three.js的功能封装成符合JSX语法的React组件或一些React Hook,很大限度的又放大了three.js的能力。

看一下官网的例子,可以看到,代码又『升维了』,甚至看不到three.js的原生方法了,这里充分利用了hook和jsx,React会自动监听各个属性的变化,不需要我们在手动调用three.js的方法执行。

import { createRoot } from 'react-dom/client'
import React, { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

function Box(props) {
  // This reference will give us direct access to the mesh
  const mesh = useRef()
  // Set up state for the hovered and active state
  const [hovered, setHover] = useState(false)
  const [active, setActive] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (mesh.current.rotation.x += 0.01))
  // Return view, these are regular three.js elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={mesh}
      scale={active ? 1.5 : 1}
      onClick={(event) => setActive(!active)}
      onPointerOver={(event) => setHover(true)}
      onPointerOut={(event) => setHover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

createRoot(document.getElementById('root')).render(
  <Canvas>
    <ambientLight />
    <pointLight position={[10, 10, 10]} />
    <Box position={[-1.2, 0, 0]} />
    <Box position={[1.2, 0, 0]} />
  </Canvas>,
)

7. pmndrs

Github主页:https://opencollective.com/pmndrs

最后,我们介绍下pmndrs这个开源组织,他是react-three-fiber项目的所有者,但它并非只有react-three-fiber,在React和three.js领域,这个组织做了大量工作,基于react-three-fiber,已经做成了一个生态,用于开发炫酷的3D应用。

开发文档首页:https://docs.pmnd.rs/

在这里插入图片描述
除了主库@react-three/fiber以外,下边介绍几个常用的库,一些库我也正在学习中,这里是个挺大的世界,这些库的用法需要花时间需学习和探索。

@react-three/drei

这是@react-three/fiber的辅助类库,里边封装了three.js核心以外的大量工具,包括控制器、加载器、一些帮助方法等等。

react-spring

这是一个react的弹簧动画库,可以用它来控制变量生成各种各样的动画。

@react-three/cannon

物理碰撞检测引擎,让你可以实现类似游戏一样的墙体或者障碍物效果。

8. 结语

到这里,我们基本厘清了前端3D技术的发展脉络,这一块技术其实涉及的知识比较复杂,往底层探究,可能要接触到计算机图形学、GPU性能等一系列基础问题,往顶层探索,可能要涉及3D建模的知识,甚至3DMAX这些软件的使用。很多知识体系其实已经超出了传统前端的范畴。不过,你不卷别人,就是被人卷,多了解点也没坏处。

本篇作为一个开篇,只是介绍了一些脉络,之后有时间的话,希望自己也能把这块好好整理下,做个记录,毕竟目前自己的工作涉及这块。

好了,这篇就写到这里了,该去写bug了,干巴爹!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

量化投资技术

支持一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值