Skip to content

狗子窝

没事就吠一下

Menu
  • 首页
  • 技术交流
    • 原创
    • WebGL教程
    • js小程序在线演示
    • 摘要总结
  • 小评论
    • 动漫短评
    • 其他短评
  • 日志/心情
    • My Piano
    • 絮絮叨叨
    • 长篇大论
  • 关于我
    • 留言板
Menu

【WebGL教程】Lesson 1

Posted on 2013 年 12 月 20 日2013 年 12 月 20 日 by wysaid

本文地址: https://wysaid.org/721.html
原创,转载请注明出处

第一话,准备工作(blog.wysaid.org)

第一步

观看本教程时,请先确保自己有一定的编程基础,我不会给你讲什么javascript的基础语法的。

但鉴于一般学编程的人不一定懂网页页面设计,我会附带少量DIV,CSS这方面必备的知识。

那么,废话不多说,开始吧。做一件事千万不能着急,磨刀不误砍柴工这个道理相信大家都懂。

做一件事之前先做充足/一定/少量是非常有必要的。比如WebGL做出来的东西肯定是显示在图形界面上的,而不是一个只有功能的控制台程序,那么我们首先应该准备的就是一个简单优雅的界面。

需要了解的知识(为了便于显示,我会给所有的div元素加上边框):div标签是网页设计里面用得非常多的,用于控制网页显示的元素。我们也将用到它来控制显示的界面,包括位置、大小以及可能会处理的鼠标事件等等。此外,我们还需要一个按钮,来点击以运行出结果。

如下:

第二步

本教程为WebGL教程,所以,现在必须引入canvas,你可能知道,从canvas里面创建名叫”2d”的上下文进行绘图。也就是大家所乐道HTML5方式,但是WebGL使用的方式为”experimental-webgl”或者”webgl”,如果后者创建不成功,那么请试试前者,本教程使用前者。

请不要用爪机观看本教程,适当的动手有助于进步。以及,你必须先安装一个支持WebGL的浏览器(IE11+,chrome,firefox,opera等)

为了便于控制,我们将canvas元素写在刚才的div里面:

也许你看不出来canvas已经写进去了,那么你可以试着多点几下上面的run,我将用html5方式在上面的canvas上画出一个红色矩形

第三步

前面说了半天,还没真正说到WebGL本身。那么经过上面两小节的描述,现在进入我们的第一个WebGL小程序:hello webgl

首先,你需要初始化webgl,以获得一个上下文,让浏览器知道你想绘图到什么地方。代码类似于这样:

1
2
3
4
5
6
7
8
var webgl = null;
function webglInit() {
    var myCanvasObject = document.getElementById("webglView");
    var myDivObject = document.getElementById("containerView");
    webgl = myCanvasObject.getContext("experimental-webgl");
    if (webgl == null) alert("你的浏览器不支持webgl");
    webgl.viewport(0, 0, myDivObject.clientWidth, myDivObject.clientHeight);
}

千万注意上面注释部分那一句,viewport设置的宽高是div的宽高,而不是canvas的,也许你想知道为什么,那么我解释一下:在设计中,你不一定想让canvas具有固定的大小,所以你可能用css控制了元素随着浏览器窗口的变化而变动,但是canvas的宽高属性是独立出来的,不受style控制,即便根据父元素改变了大小,直接获取的宽高值也不对。这里有两种解决办法,一是像上面那样写,二是使用js代码响应每一次窗口大小的变动,把canvas对象的width和height重设。后面如果涉及到复杂一点的布局的时候再讨论。

这里获取到了webgl对象,接下来就要创建Shader对象了。为了节省篇幅,后面的就不写容错代码,只写功能了:

1
2
3
4
5
6
7
8
var vertexShaderObject = null;
var fragmentShaderObject = null;
function shaderInitWithVertexAndFragmentShader(vsh, fsh) {
    webgl.shaderSource(vertexShaderObject, vsh);
    webgl.shaderSource(fragmentShaderObject, fsh);
    webgl.compileShader(vertexShaderObject);
    webgl.compileShader(fragmentShaderObject);
}

上面这一步获取到了Shader Object对象,那么,再接下来当然是ShaderProgram了,有了program可就差不多大功告成了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var programObject;
var v4PositionIndex;
function initShaderProgram(positionName) {
    programObject = webgl.createProgram();
    webgl.attachShader(programObject, vertexShaderObject);
    webgl.attachShader(programObject, fragmentShaderObject);
    webgl.bindAttribLocation(programObject, v4PositionIndex, positionName);
    webgl.linkProgram(programObject);
    if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) {
        alert(webgl.getProgramInfoLog(programObject));
        return;
    }
    webgl.useProgram(programObject);
}

是的,代码就这么简单,我们快要看到我们的第一个webgl程序了。写了一堆辅助函数,下面就要调用它们了,但是调用就要直接写吗?不,我说了,磨刀不误砍柴工。初学一样东西,把准备工作做足,后面才方便继续。因为我们的demo是随着我们的努力不断进步了。不要说学到下一章我们就把第一章的内容丢掉这样的话。我们将在此基础上不断完善,所以这个demo的功能必须写得稍微分开一点。

接下来就是一步完成绘制的函数,加上它,就相当于我们的第一个webgl程序了:

1
2
3
4
5
6
7
8
9
10
11
12
13
function renderWebGL(vertices, vSize, vLen, vsh, fsh, positionName) {
    webglInit();
    shaderInitWithVertexAndFragmentShader(vsh, fsh);
    initShaderProgram(positionName);
    var buffer = webgl.createBuffer();
    webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer);
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);
    webgl.enableVertexAttribArray(v4PositionIndex);
    webgl.vertexAttribPointer(v4PositionIndex, vSize, webgl.FLOAT, false, 0, 0);
    webgl.clearColor(0.0, 0.0, 0.0, 1.0);
    webgl.clear(webgl.COLOR_BUFFER_BIT);
    webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, vLen);
}

第四步

虽然我说我们的第一个WebGL程序已经写完了,但是不是还感觉少了写什么?对,那就是显示。上面所有的代码相当于对WebGL的一个简单封装,我们要让它显示点什么东西出来才对。让我们的应用我们的封装吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//使用上面封装的函数在绘制一个渐变色三角形, 由于前面封装的功劳,我们现在可以绘制很多东西而只需要提供shader文本代码和顶点就行了。
function renderTriangle()
{
var vertices =
[
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5,
];
var vsh =
"precision mediump float;" +
"attribute vec4 position;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" gl_Position = position;" +
" textureCoordinate = position.xy + 0.5;" +
"}";
var fsh =
"precision mediump float;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" gl_FragColor = vec4(textureCoordinate, 0.0, 1.0);" +
"}";
renderWebGL(vertices, 2, 3, vsh, fsh, "position");
}
 
function renderRectangle()
{
var vertices =
[
0.5, 0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, -0.5
];
var vsh =
"precision mediump float;" +
"attribute vec4 position;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" gl_Position = position;" +
" textureCoordinate = position.xy + 0.5;" +
"}";
var fsh =
"precision mediump float;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" gl_FragColor = vec4(textureCoordinate, 0.0, 1.0);" +
"}";
renderWebGL(vertices, 2, 4, vsh, fsh, "position");
}
 
function renderCircle()
{
var vertices =
[
1.0, 1.0,
1.0, -1.0,
-1.0, 1.0,
-1.0, -1.0
];
var vsh =
"precision mediump float;" +
"attribute vec4 position;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" gl_Position = position;" +
" textureCoordinate = position.xy;" +
"}";
var fsh =
"precision mediump float;" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{" +
" if(length(textureCoordinate) < 0.5)" +
" gl_FragColor = vec4(textureCoordinate + 0.5, 0.0, 1.0);" +
" else gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);" +
"}";
renderWebGL(vertices, 2, 4, vsh, fsh, "position");
}

好的,第一期教程到此为止,请关注lesson 2。系列教程地址:webgl-lesson.wysaid.org

10 thoughts on “【WebGL教程】Lesson 1”

  1. PWvyy说道:
    2016 年 12 月 26 日 下午 5:41

    这个更刺c激,准备好手纸哦 A 片。。 288d.pw

  2. yamakasiluke说道:
    2015 年 12 月 19 日 上午 11:37

    出问题的同学,不要用给出的代码,要用源码

  3. 你猜我是谁说道:
    2014 年 3 月 26 日 下午 10:58

    我晕。。。
    就是我在canvas外面加了div了还是不得行

    1. wysaid说道:
      2014 年 3 月 27 日 下午 9:51

      你把你没弄成功的页面发给我看看吧。也许弄知道什么原因

  4. 你猜我是谁说道:
    2014 年 3 月 26 日 下午 10:56

    <!–
    Your browser doesn’t support the HTML5 element canvas.

    –!>

  5. 你猜我是谁说道:
    2014 年 3 月 26 日 下午 10:54

    Your browser doesn’t support the HTML5 element canvas.

    这个样子还是不得行呢?

  6. 你猜我是谁说道:
    2014 年 3 月 25 日 上午 10:51

    大师兄,你是如何在文章里使用canvas元素的?我使用它,浏览器会无法识别?
    但是单独的页面就可以。

    1. wysaid说道:
      2014 年 3 月 26 日 下午 3:11

      给canvas元素外面加上一个div框起来哈

  7. AntiMoron说道:
    2013 年 12 月 26 日 下午 1:35

    大师兄,我照着你写的。
    http://codepad.org/4zviSmWz

    总是提示vertexShaderCompile Error
    fragmentShaderCompileError.
    告诉missing shaders.

    能帮我看下是怎么回事吗?里面的封装基本都是你的。

    1. wysaid说道:
      2013 年 12 月 26 日 下午 1:38

      直接看这篇文章的下一篇lesson 2,开头我给出了这一篇用到的代码,你好好对比一下~

Comments are closed.


转载本Blog文章请注明出处:
wysaid.org

2025 年 5 月
日 一 二 三 四 五 六
 123
45678910
11121314151617
18192021222324
25262728293031
« 2 月    

评论

  • 翔鱼 发表在《关于我》
  • luo.la 发表在《使用OpenAL打开麦克风录音并实时回放(类似K歌效果)》
  • 罗拉 发表在《使用OpenAL打开麦克风录音并实时回放(类似K歌效果)》
  • 大喜 发表在《使用OpenAL打开麦克风录音并实时回放(类似K歌效果)》
  • 罗拉套图网 发表在《使用OpenAL打开麦克风录音并实时回放(类似K歌效果)》

归档

分类

TAG

Android c C++ domain EGE host iOS JavaScript NDK OpenAL OpenGL Slideshow WebGL教程 WGE 人脸识别 作文 分形 动漫 在线演示 小程序 常识 数学 游戏 源代码 滤镜 算法 老文翻新 表白 视频 评论 谷歌娘 酸腐文章 钢琴 音乐
© 2025 狗子窝 | Powered by Superbs Personal Blog theme