其实在3D引擎/库的帮助下,我们做webgl开发的难度已经很大大地降低了,熟悉相关API的话,开发一个简单的3D程序可以说是很轻松的事情。

在我看来,webgl的核心就是着色器(顶点着色器、片元着色器),这两者决定了如何在屏幕上绘制出我们想要的效果。所以,无论你是刚入门的3D开发者(我也是刚刚探索3D领域)还是该领域的资深老鸟,对着色器的了解都是至关重要的。

我们一般的软件开发(例如一些管理系统、商城小程序),诸如这些业务逻辑性非常强的程序,都是依靠CPU的高速运算,而做WebGL(3D开发),我们写的程序代码是要跑在GPU上的,因为对于绘图能力来说,GPU是远远高于CPU的,所以,我们做的就是GPU编程了。

今天,就以一个demo来体会一下,three.js中如何编写自定义的着色器并运用到mesh材质上的。

(首先默认大家都已经学会three.js的一些基本操作,例如将一个three.js内置的面板PlaneGeometry放到场景中)

一、添加plane

    function addplane(){
var planeGeometry = new THREE.PlaneGeometry(,)
var meshMaterial = new THREE.MeshPhongMaterial({
color: 0xfff000 * Math.random()
});
var plane = new THREE.Mesh(planeGeometry,meshMaterial);
scene.add(plane);
}

这个函数将会往场景中添加一个Plane,效果如下:

ok,这就是一个plane了。

二、着色器代码

<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
} </script>
<!-- 顶点着色器 -->
<script id="fragment-shader-3" type="x-shader/x-fragment">
uniform vec2 resolution;
      uniform float scale;

    vec2 rand(vec2 pos){
return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
}
vec2 rand2(vec2 pos){
return rand(rand(pos));
} float softnoise(vec2 pos, float scale){
vec2 smplpos = pos * scale;
float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x; vec2 a = fract(smplpos);
return mix(
mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
smoothstep(0.0, 1.0, a.y)
);
} void main(void){
vec2 pos = gl_FragCoord.xy / resolution.y;
pos.x += time * 0.1;
float color = 0.0;
float s = 1.0;
for(int i = ; i < ; i++){
color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
s *= 2.0;
}
gl_FragColor = vec4(color);
} </script>

顶点着色器中,进行了一系列的矩阵变换,将图形的顶点转换为屏幕上的像素点;

模型矩阵: 将顶点从局部坐标系转换到世界坐标系中;

视图矩阵: 将顶点从世界坐标转化到视图坐标系下;

投影矩阵: 将顶点从视图坐标系转换到规范立方体中(即屏幕中);

局部坐标系(模型/物体本身)----->世界坐标系----->视图坐标系----->屏幕。

片元着色器中,因为片元着色器是针对顶点着色器输出的顶点数据 (gl_Position)进行逐点绘制的,所以该着色器就是对每个点赋予一个颜色值,针对上面的片元着色器,他接受外界赋予的变量(uniform类型)。

三、着色器材质

下面我们就用两种着色器来生成一个材质。

    //创建ShaderMaterial纹理的函数
function createMaterial(vertexShader, fragmentShader) {
var vertShader = document.getElementById(vertexShader).innerHTML; //获取顶点着色器的代码
var fragShader = document.getElementById(fragmentShader).innerHTML; //获取片元着色器的代码 //配置着色器里面的attribute变量的值
var attributes = {};
//配置着色器里面的uniform变量的值
var uniforms = {
scale: {type: 'f', value: },
resolution: {type: "v2", value: new THREE.Vector2(window.innerWidth, window.innerHeight)}
};
var meshMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
defaultAttributeValues : attributes,
vertexShader: vertShader,
fragmentShader: fragShader,
transparent: true
});
return meshMaterial;
}

四、利用shader材质重新绘制plane

    function addplane(){
var planeGeometry = new THREE.PlaneGeometry(,)
var meshMaterial = createMaterial("vertex-shader", "fragment-shader-3");
var plane = new THREE.Mesh(planeGeometry,meshMaterial);
scene.add(plane);
}

效果:

五、其他着色器效果示例

three中的着色器示例的更多相关文章

  1. OpenGl中使用着色器的基本步骤及GLSL渲染简单示例

    OpenGL着色语言(OpenGL Shading Language,GLSL)是用来在OpenGL中着色编程的语言,是一种具有C/C++风格的高级过程语言,同样也以main函数开始,只不过执行过程是 ...

  2. 在CG/HLSL中访问着色器属性(Properties)

    在CG/HLSL中访问着色器属性 Shader在Properties块中访问材质属性.如果你想在一个着色程序中访问一些属性,你需要声明一个Cg/HLSL具有相同的名称和一个匹配的类型的变量. Prop ...

  3. 在CG/HLSL中访问着色器的内容

    着色器在Properties代码块中声明 材质球的各种特性.如果你想要在着色器程序中使用这些特性,你需要在CG/HLSL中声明一个变量,这个变量需要与你要使用的特性拥有同样的名字和对的上号的类型.比如 ...

  4. BGFX 渲染引擎中着色器代码的调试方法

    在实时渲染的图形开发中,着色器代码(Shader)越来越复杂,于是单纯的靠经验和不断试错的开发和调试方法早已不能满足实际需求.使用调试工具进行调试,成为开发中重要的方法.Bgfx 是一款跨平台.抽象封 ...

  5. OpenGL学习脚印: uniform blocks在着色器中的使用 转自https://blog.csdn.net/wangdingqiaoit/article/details/52717963

    写在前面 目前,我们在着色器中要传递多个uniform变量时,总是使用多个uniform,然后在主程序中设置这些变量的值:同时如果要在多个shader之间共享变量,例如投影矩阵projection和视 ...

  6. unity中使用的着色器语言

    在unity中,着色器编程使用了一列列的HLSL语言变种(也叫作Cg,但是大部分实际上两者都是一样的). 目前,为了在不同平台下保持最好的跨平台性, 取样贴图时,最好使用DX9风格 的HLSL. 着色 ...

  7. Direct3D 11 Tutorial 3: Shaders and Effect System_Direct3D 11 教程3:着色器和效果系统

    概述 在上一个教程中,我们设置了一个顶点缓冲区并将一个三角形传递给GPU. 现在,我们将逐步完成图形管道并查看每个阶段的工作原理. 将解释着色器和效果系统的概念. 请注意,本教程与前一个源代码共享相同 ...

  8. Unity 几何着色器

    Unity 几何着色器 shaderGeometry Shader几何着色器 Unity 几何着色器 如果学习不能带来价值,那将毫无意义 简介     在顶点和片段着色器之间有一个可选的着色器,叫做几 ...

  9. WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码

    原文:WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码 HLSL,High Level Shader Language,高级着色器语言,是 Di ...

随机推荐

  1. Python中关于txt的简单读写模式与操作

    Python中关于txt的简单读写操作 常用的集中读写模式: 1.r 打开只读文件,该文件必须存在. 2.r+ 打开可读写的文件,该文件必须存在. 3.w 打开只写文件,若文件存在则文件长度清为0,即 ...

  2. 使用dsoframer演示ppt

    优点: (1)不用直接打开PowerPoint (2)可以嵌入到Form中,那种先打开ppt然后将ppt嵌入到Form中的方式,会先打开PowerPoint 缺点: 很早就停止更新了....  但是没 ...

  3. u-boot DM初始化流程

    initr_dm dm_init_and_scan dm_init  ((1)创建根设备root的udevice,存放在gd->dm_root中 (2)初始化uclass链表gd->ucl ...

  4. slices = [dicom.read_file(path + '/' + s) for s in os.listdir(path)] FileNotFoundError: [WinError 3] 系统找不到指定的路径。

    最近跟着kaggle做一个医疗项目,加载路径总是出错. 将下面箭头处: 改为: path = os.path.join(data_dir, patient)问题迎刃而解 上面的路径拼接方法可能是ipy ...

  5. AMD 异步模块定义

    1.解决模块加载过慢 2.核心:define函数

  6. 学习如何写一个vue插件【入门篇】

    #### 疑答 1.市面上已经有那么多插件可用,为什么还要造轮子?学习.借鉴思想.应用到开发 2.能否在项目中使用?与网上插件使用相同   更新维护问题怎么解决? 自身动力,使用者反馈等 #### 准 ...

  7. hive优化方式总结

    1. 多表join优化代码结构: select .. from JOINTABLES (A,B,C) WITH KEYS (A.key, B.key, C.key) where .... 关联条件相同 ...

  8. Java之正则表达式来判断字符串中是否包含字母

    /** * 使用正则表达式来判断字符串中是否包含字母 * @param str 待检验的字符串 * @return 返回是否包含 * true: 包含字母 ;false 不包含字母 */ public ...

  9. 前端 OSS 自动化部署脚本

    部署脚本 (deploy.js 自己命名) const co = require('co') const OSS = require('ali-oss') const path = require(' ...

  10. 【Python之路】特别篇--Redis

    NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库 随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发 ...