因为只是想分享ghcjs和webgl的使用经验,所以很多地方说的很粗,因为涉及的知识确实很多, 推荐两本书,一本haskell基础的 learn you a haskell for great good,中文翻译为haskell趣学, 网上有在线版.一本webgl入门的 webgl programming guide 中文翻译webgl编程指南.

我想写一个系列的文章,在写了一定数量后会在github创个项目分享配套的代码.

关于webgl

现阶段的webgl是opengl ES2.0,后者在移动设备上取得了很大的成功,而在web上还在与flash争地盘. 我没用过flash,我用过opengl,感觉太过程式了,像历史遗留产物(据说vulkan很不错,目标也是取代opengl). 但是平常写应用很少直接使用这么底层的Api,都是用的别人写好的框架,像基于webgl的three.js就是很不错的, 几何图形,灯光什么的都封装好了,只需打个响指,pia,阳光就洒落在了一个球体上,有如上帝一般.

但是了解底层一点的东西总是很有必要的,这是突破框架限制和跳出框架思维必须的知识.

上篇文章中我们代码已经写到获取gl::WebGLRenderingContextBase了,而这就是我们webgl世界的起点. 先看代码

  let vertShaderSource = decodeUtf8 $(embedFile "shader/graph.vert")
fragShaderSource = decodeUtf8 $(embedFile "shader/graph.frag")
frg <- createShader gl FRAGMENT_SHADER
shaderSource gl frg fragShaderSource
compileShader gl frg vert <- createShader gl VERTEX_SHADER
shaderSource gl vert vertShaderSource
compileShader gl vert prog <- createProgram gl
attachShader gl prog frg
attachShader gl prog vert
linkProgram gl prog
useProgram gl prog

所谓的“现代”的opengl程序都是基于着色器的,以前是用的绘制指令来绘制线段和三角形,由此组成图形, “现代”的opengl把这些指令的脏活累活交给了着色器.

在webgl中我们用的是顶点着色器(vertex shader)和片元着色器(fragment shader).着色器是用着色器语言写成 的,在程序的运行时加载的代码.在我们的程序中,我们把他们写在两个文件下面,shader/graph.vert和 shader/graph.frag.其代码如下

shader/graph.vert

void main() {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
gl_PointSize = 10.0;
}

shader/graph.frag

大专栏  montagyrceCode c">void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

着色器语言是门类C语言,在这里不细说.我们的目标是haskell.

在let语句中我们用embedFile在编译时将文件读取为bytestring,再用decodeUtf8得到Text,这与我们直接 将shader文件里的内容写成string是等价的.如果用js来解释的话,那么

var vertShaderSource =
'void main(){n' +
'gl_Position = vec4(0.0, 0.0, 0.0, 1.0);n' +
'gl_PointSize = 10.0;n' +
'}n';

紧接着我们创建着色器对象(createShader), 将着色器资源载入这个对象(shaderSource),最后编译这个载有着色器的对象(compileShader). 这是一个完全过程式的代码,这就是opengl在运行时所做的事情,一步一步的怎么操作,你都要告诉它.后面我们还会看到 很多类似这样的操作.

我们根据顶点和片段这两个着色器创建了两个编译好的着色器对象,然后我们创建一个program对象来组装这两者, 通过attachShader和linkProgram后,我们就可以使用(useProgram)了.这时我们的着色器工作就做完了.

着色器所做的工作都是程序在运行时GPU所做的工作,现在我们回到CPU里面来,下面我们控制CPU给GPU发送命令, 来完成我们最简单的webgl程序.

clearColor gl 0.0 0.0 0.0 1.0
clear gl COLOR_BUFFER_BIT
drawArrays gl POINTS 0 1

clearColor 是设置背景色,后面的四个数字参数是rgba.我们这里设置的是黑色. clear是清空现在画布上的缓存内容,这是准备绘制的一个过程.参数COLOR_BUFFER_BIT表示我们清空了颜色缓冲区. 最后drawArrays就是我们的绘制程序了,这里是绘制了一个POINTS.

我们这个最简单的ghcjs-webgl程序就这么结束了,当编译完后,启动一个web服务器,根目录指向./dist/build/example/example.jsexe ,然后在浏览器打开,就能看到一个400X400的黑框里有个红色的小方块.

后记

上面我们的着色器program在CPU中并没有用到,下篇我会讲讲如何与着色器交互.

montagy的更多相关文章

随机推荐

  1. share团队冲刺6

    团队冲刺第六天 昨天:进行各种原件的自定义样式,进行界面布局 登陆界面: 今天:进行后台的代码编写,实现各种按钮的功能 问题:在不同的型号手机上,界面会发生不兼容的问题.

  2. 记一次Java面试问题点总结

    引言 昨日接了一个阿里外包的电话面试,问了一些技术问题感觉到自己是真的菜,接触Java开发已经也有一段时间,技术方面说来惭愧,一直以来只是局限于框架工具的用法,也没有进行了解其实现的原理,更重要的是一 ...

  3. IOC 本质是为了实现 AOP|火影鸣人

    @JFinal 波总在 JFinal 4.8 发布新闻的评论 中给出了下面的表述: IOC 本质是为了实现 AOP 我有点吃惊, 没想到 Java 界的大佬对这两个概念有和我完全不一致的认识. 所以写 ...

  4. 【PXC】关于限流的参数,状态值说明

    一.什么是流控(FC)?如何工作? 节点接收写集并把它们按照全局顺序组织起来,节点将接收到的未应用和提交的事务保存在接收队列中,当这个接收队列达到一定的大小,将触发限流:此时节点将暂停复制,节点会先处 ...

  5. cifar数据集下载

    https://www.cs.toronto.edu/~kriz/cifar.html Version Size md5sum CIFAR-10 python version 163 MB c58f3 ...

  6. tmp == emg.经典+47

    zw.Y3s3{ttqtf**9q+{xx//up qm+Y3#9t%sfsfqtf+&* hh-Y@15zq&zf51"qt3+x>y ====== 城隍庙 经典景点 ...

  7. logstash kafka的版本兼容问题

    项目细节也就不说了 kafka + spark streaming >> kafka版本1.0,spark streaming也是依照kafka1.0开发的 这个kfk集群叫kfk_1.0 ...

  8. Flink(三) —— 运行架构

    Flink运行时组件 JobManager 作业管理器 TaskManager 任务管理器 ResourceManager 资源管理器 Dispatcher 分发器 任务提交流程 任务调度原理 Job ...

  9. springboot多数据源+jta事务管理配置

    1.创建一个maven项目,导入相关配置: <?xml version="1.0" encoding="UTF-8"?> <project x ...

  10. java中多线程入门有趣介绍

    我们在网上可以看到所有有关于java的线程的基本概念的很多解释,不乏有很多详细经典的解释和代码解说.但是我们的很多初学者看完不能有一个直观的印象,特别是一些没有编程基础的学习者,很多时候要花很多时间去 ...