一个最简单的WebGL编程范例
0 55

WebGL(Web Graphics Library)是HTML5规范中的一部分,可以用来渲染三维场景。
WebGL源自OpenGL ES(OpenGL for Embedded Systems 是OpenGL三维图形API的子集)。

示例代码

// 创建canvas
function createCanvas(width, height) {
    var canvas = document.createElement("canvas");
    canvas.width = width || 300;
    canvas.height = height || 300;
    return canvas;
}

// 创建着色器
function createShader(webGL, source, type) {
    var shader = webGL.createShader(type);
    webGL.shaderSource(shader, source);
    webGL.compileShader(shader);
    return shader;
}
// 初始化webGL
function initWebGL(canvas) {
    var webGL = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
    if (!webGL) {
        console.log("当前浏览器不支持WebGL,请切换到支持WebGL的浏览器,比如Chrome");
        return null;
    } else {
        return webGL;
    }
}

// 创建矩形
function drawRect(webGL, program) {
    var buffer = webGL.createBuffer();
    webGL.bindBuffer(webGL.ARRAY_BUFFER, buffer);
    webGL.bufferData(
        webGL.ARRAY_BUFFER,
        new Float32Array([-1.0, -1.0,
            1.0, -1.0, -1.0, 1.0, -1.0, 1.0,
            1.0, -1.0,
            1.0, 1.0
        ]),
        webGL.STATIC_DRAW
    );

    // vertex data
    var positionLocation = webGL.getAttribLocation(program, "a_position");
    webGL.enableVertexAttribArray(positionLocation);
    webGL.vertexAttribPointer(positionLocation, 2, webGL.FLOAT, false, 0, 0);
}
// 入口函数
function init() {
    var canvas = createCanvas(),
        VER_SHADER_SRC = "attribute vec4 a_position;\n" +
        "void main() {\n" +
          "gl_Position = a_position;\n" +
        "}",
        FRAG_SHADER_SRC = "precision mediump float;\n" +
        "void main() {\n" +
          "gl_FragColor = vec4(1, 0, 0.5, 1);\n" +
        "}";
    document.body.appendChild(canvas);
    var webGL = initWebGL(canvas);
    if (webGL) {
        webGL.clearColor(0.0, 0.0, 0.0, 1.0);
        webGL.clear(webGL.COLOR_BUFFER_BIT | webGL.DEPTH_BUFFER_BIT);
        var vertex = createShader(webGL, VER_SHADER_SRC, webGL.VERTEX_SHADER),
            frag = createShader(webGL, FRAG_SHADER_SRC, webGL.FRAGMENT_SHADER);
        var program = webGL.createProgram();
        webGL.attachShader(program, vertex);
        webGL.attachShader(program, frag);
        webGL.linkProgram(program);
        webGL.useProgram(program);
        drawRect(webGL, program);
        webGL.drawArrays(webGL.TRIANGLES, 0, 6);
    }
}

代码说明

WebGLShader(WebGL着色器),WebGL只关心两件事:位置坐标与颜色,所有WebGL程序都是基于这两个元件来构造的,常用的方法是使用两个着色器来实现:

  • 顶点着色器(vertex shader):返回位置坐标

  • 像素着色器(fragment shader):返回颜色

vec4()构造函数用于生成颜色,示例代码中vec4(1, 0, 0.5, 1)的数字的含义:

  • 第一个1:代表红色

  • 0:代表绿色

  • 0.5: 代表蓝色

  • 第二个1:代表alpha

在WebGL中颜色的取值范围是0到1.

具体方法:

  • createShader:生成相应类型的WebGLShader

  • shaderSource:生成GLSL的回调函数

  • compileShader:编译着色器

WebGLProgram(WebGL环境)着色器编译完后,需要将着色器链接到WebGLProgram:

  • createProgram:创建一个WebGL环境

  • attachShader:附加着色器

  • linkProgram:将着色器连接到WebGL环境中

提供数据:

  • getAttribLocation:从当前环境中寻找定义的属性,即查找示例中初始化顶点着色器时定义的a_position。

  • createBuffer:创建buffer(缓存区)

  • bindBuffer:声明变量,并指向上一步创建的buffer

  • bufferData:赋值数据到指定变量,比如示例中的ARRAY_BUFFER

清空canvas:

  • clearColor:

  • clear:

使用创建的WebGL环境:将当前的WebGL环境告知GPU程序

  • useProgram:

告知WebGL从buffer中获取数据的方式:

  • enableVertexArribArray:激活属性

  • vertexAtrribPointer:获取数据

绘制图形:WebGL执行GLSL程序

  • drawArrays:这是WebGL提供的一个渲染函数

效果

0 55
() 全部评论
所有回复 (0)

热门

最新

  • Web3D编程 2 0 1 发布

    点击查看例子

    代码效果


    源码

    <!DOCTYPE html> <html> <head> <title>材质和光源</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="LapBin-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> // 加载所有内容后,我们将运行Three.js function init() { // 创建一个场景,该场景将包含所有元素,例如对象、摄影机和灯光。 var scene = new THREE.Scene(); // 创建一个摄像头,它定义了我们要看的范围。 var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.2, 1000); // 创建渲染并设置大小 var renderer = new THREE.WebGLRenderer(); renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0)); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMapEnabled = true; // 创建平面 var planeGeometry = new THREE.PlaneGeometry(60, 30); var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // 旋转并定位平面 plane.rotation.x = -0.5 * Math.PI; plane.position.x = 10; plane.position.y = 0; plane.position.z = -10; // 将平面添加到场景中 scene.add(plane); // 创建一个立方体 var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000}); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // 定位立方体 cube.position.x = -4; cube.position.y = 3; cube.position.z = -10; // 将立方体添加到场景中 scene.add(cube); // 创建一个球体 var sphereGeometry = new THREE.SphereGeometry(4, 20, 20); var sphereMaterial = new THREE.MeshLambertMaterial({color: 0xdd77ff}); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // 定位球体 sphere.position.x = 20; sphere.position.y = 4; sphere.position.z = -10; sphere.castShadow = true; // 将球体添加到场景中 scene.add(sphere); // 将摄影机定位并指向场景的中心 camera.position.x = -30; camera.position.y = 40; camera.position.z = 30; camera.lookAt(scene.position); // 为阴影添加聚光灯 var spotLight = new THREE.SpotLight(0xffffff); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; scene.add(spotLight); // 将渲染器的输出添加到html元素 document.getElementById("LapBin-output").appendChild(renderer.domElement); // 渲染场景 renderer.render(scene, camera); } window.onload = init; </script> </body> </html>
  • LapBin(ThreeJS) 6 0 1 发布
  • 点击查看例子

    代码效果




    天空盒使用源码

    <!DOCTYPE html> <html lang="en">     <head>         <title>three.js - skybox</title>         <meta charset="utf-8">         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">         <link type="text/css" rel="stylesheet" href="main.css">     </head>     <body>         <div id="container"></div>         <script type="module">             import * as THREE from '../build/three.module.js';             import { OrbitControls } from './jsm/controls/OrbitControls.js';             var scene, camera , renderer;             init();             animate();             function init() {                 // scene                 scene = new THREE.Scene();                 // camera                 camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );                 camera.position.set( - 15, 7, 15 );                 camera.lookAt( scene.position );                              // skybox                 var cubeTextureLoader = new THREE.CubeTextureLoader();                 cubeTextureLoader.setPath( 'textures/cube/Park2/' ); //天空盒图片文件路径                 var cubeTexture = new THREE.CubeTextureLoader.load( [                     "posx.jpg", "negx.jpg", //图片 http://www.cglap.com/assets/lapbin/textures/cube/Park2/negx.jpg                     "posy.jpg", "negy.jpg", // http://www.cglap.com/assets/lapbin/textures/cube/Park2/negy.jpg                     "posz.jpg", "negz.jpg" //http://www.cglap.com/assets/lapbin/textures/cube/Park2/negz.jpg                 ] );                 scene.background = cubeTexture;                 // light                 var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );                 scene.add( ambientLight );                 var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.6 );                 directionalLight.position.set( - 1, 1, 1 );                 scene.add( directionalLight );                 // renderer                 renderer = new THREE.WebGLRenderer( { antialias: true } );                 renderer.setSize( window.innerWidth, window.innerHeight );                 renderer.setPixelRatio( window.devicePixelRatio );                 document.body.appendChild( renderer.domElement );                 // 鼠标控制旋转                 var controls = new OrbitControls( camera, renderer.domElement );                 controls.minDistance = 5;                 controls.maxDistance = 50;                              //                 window.addEventListener( 'resize', onResize, false );             }             function onResize() {                 camera.aspect = window.innerWidth / window.innerHeight;                 camera.updateProjectionMatrix();                 renderer.setSize( window.innerWidth, window.innerHeight );             }             function animate() {                 requestAnimationFrame( animate );                 render();             }             function render() {                 renderer.render( scene, camera );             }         </script> </body> </html>
  • 例子查看链接gui

    为了能够快速地搭建three.js的交互ui,官方提供了一个GUI组件,通过简单的语法学习就能够使用。

    下面我们就来学习如何使用

    用法一

    首先声明一个对象,这个对象设置获取一个交互.

       var params = {                 color: '#ffffff',                 scale: 4,                 flowX: 1,                 flowY: 1 , states:"Walking"             };

    然后就就可以使用GUI来进行生成交互UI组件

    生成一个panel组件版,然后将组件的对象添加到这个组件版,完成之后就能够生成一个交互界面了。

     // dat.gui

    颜色选择器                var gui = new GUI();                 gui.addColor( params, 'color' ).onChange( function ( value ) {                    // do something                 } );


    拉动条
    不仅可以生成按钮,也可以生成拉动条。 gui.add( params, 'scale', 1, 10 ).onChange( function ( value ) { // do something  } );


    gui.add( params, 'flowX', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                   // do something } );


     gui.add( params, 'flowY', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                   // do something                 } );


    下拉表
     //选项 var states = [ 'Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing' ];  // 添加  gui.add( params, 'states' ).options( states ).onChange( function ( value ) {              // do something } );
    效果图


    全部代码

    <!DOCTYPE html> <html lang="en">     <head>         <title>three.js - gui</title>         <meta charset="utf-8">         <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">         <link type="text/css" rel="stylesheet" href="main.css">     </head>     <body>         <div id="container"></div>         <script type="module">             import * as THREE from '../build/three.module.js';             import { GUI } from './jsm/libs/dat.gui.module.js';             var scene, camera, renderer;             var params = {                 color: '#ffffff',                 scale: 4,                 flowX: 1,                 flowY: 1,                 states:"Walking"             };             init();             animate();             function init() {                 // scene                 scene = new THREE.Scene();                 // camera                 camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 200 );                 camera.position.set( - 15, 7, 15 );                 camera.lookAt( scene.position );                 // renderer                 renderer = new THREE.WebGLRenderer( { antialias: true } );                 renderer.setSize( window.innerWidth, window.innerHeight );                 renderer.setPixelRatio( window.devicePixelRatio );                 document.body.appendChild( renderer.domElement );                 // dat.gui                 var gui = new GUI();                 gui.addColor( params, 'color' ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'scale', 1, 10 ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'flowX', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                     //do something                 } );                 gui.add( params, 'flowY', - 1, 1 ).step( 0.01 ).onChange( function ( value ) {                     //do something                 } );                 //选项                 var states = [ 'Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing' ];                  gui.add( params, 'states' ).options( states ).onChange( function ( value ) { //do something                 } );;                              gui.open();                 window.addEventListener( 'resize', onResize, false );             }             function onResize() {                 camera.aspect = window.innerWidth / window.innerHeight;                 camera.updateProjectionMatrix();                 renderer.setSize( window.innerWidth, window.innerHeight );             }             function animate() {                 requestAnimationFrame( animate );                 render();             }             function render() {                 renderer.render( scene, camera );             }         </script> </body> </html>
  • LapBin(ThreeJS) 12 0 1 发布