Skip to content

大师兄的博客

专注无聊20年,数过的小羊连起来可以绕地球两圈

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

2023年 3月
日 一 二 三 四 五 六
 1234
567891011
12131415161718
19202122232425
262728293031  
« 7月    

评论

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

归档

分类

TAG

Android c C++ domain EGE host iOS JavaScript NDK OpenAL OpenGL Slideshow WebGL教程 WGE 人脸识别 分形 动漫 在线演示 小程序 常识 数学 游戏 源代码 滤镜 算法 表白 视频 评论 谷歌娘 钢琴 音乐
© 2023 大师兄的博客 | Powered by Superbs Personal Blog theme