先上一个demo代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html, body {
margin: ;
height: %;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script src="../lib/three.min.js"></script>
<script src="../lib/stats.min.js"></script>
<script src="../lib/OrbitControl.js"></script> <!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script> <script id="fragment-shader-8" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution; void main( void ) {
float x = gl_FragCoord.x;
float y = gl_FragCoord.y;
float fy = sin(x / . + time * .) * . + .;
float opacity = 0.0;
if(y > fy){
opacity = 1.0;
}
gl_FragColor = vec4(.,.,.,opacity);
}
</script> <script type="module">
var renderer;
var clock ;
function initRender() {
clock = new THREE.Clock();
renderer = new THREE.WebGLRenderer({antialias: true,alpha:true});
renderer.setSize(window.innerWidth, window.innerHeight);
//告诉渲染器需要阴影效果
//renderer.shadowMap.enabled = true;
//renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是,没有设置的这个清晰 THREE.PCFShadowMap
renderer.setClearColor(0xffffff);
document.body.appendChild(renderer.domElement);
} var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(, window.innerWidth / window.innerHeight, 0.1, );
camera.position.set(, , );
camera.lookAt(new THREE.Vector3(, , ));
} var scene;
function initScene() {
scene = new THREE.Scene();
var bgTexture = new THREE.TextureLoader().load("../texture/starfiled.jpeg");
scene.background = bgTexture;
} function initLight() {
var hemisphereLight1 = new THREE.HemisphereLight(0xffffff, 0x444444, );
hemisphereLight1.position.set(, , );
scene.add(hemisphereLight1);
} var plane;
function addplane(){
var planeGeometry = new THREE.PlaneGeometry(,)
var meshMaterial = createMaterial("vertex-shader", "fragment-shader-8"); plane = new THREE.Mesh(planeGeometry,meshMaterial);
scene.add(plane);
} //创建ShaderMaterial纹理的函数
function createMaterial(vertexShader, fragmentShader) {
var vertShader = document.getElementById(vertexShader).innerHTML; //获取顶点着色器的代码
var fragShader = document.getElementById(fragmentShader).innerHTML; //获取片元着色器的代码
//配置着色器里面的attribute变量的值
var attributes = {};
//配置着色器里面的uniform变量的值
var uniforms = {
time: {type: 'f', value: 1.0},
scale: {type: 'f', value: 0.2},
alpha: {type: 'f', value: 0.6},
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;
} //初始化性能插件
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
} //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放
var controls;
function initControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
// 如果使用animate方法时,将此函数删除
//controls.addEventListener( 'change', render );
// 使动画循环使用时阻尼或自转 意思是否有惯性
controls.enableDamping = true;
//动态阻尼系数 就是鼠标拖拽旋转灵敏度
//controls.dampingFactor = 0.25;
//是否可以缩放
controls.enableZoom = true;
//是否自动旋转
controls.autoRotate = false;
controls.autoRotateSpeed = ;
//设置相机距离原点的最远距离
controls.minDistance = ;
//设置相机距离原点的最远距离
controls.maxDistance = ;
//是否开启右键拖拽
controls.enablePan = true;
} function render() {
var delta = clock.getDelta();
renderer.render(scene, camera);
if(plane){
plane.material.uniforms.time.value += 0.01;
}
}
//窗口变动触发的函数
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
//更新控制器
render();
//更新性能插件
stats.update();
controls.update();
requestAnimationFrame(animate);
}
function draw() {
initScene();
initCamera();
initLight();
initRender(); addplane(); initControls();
initStats();
animate();
window.onresize = onWindowResize;
}
draw(); </script> </body>
</html>

一、页面结构介绍

后续的shader代码效果,也基本上会基于上述html页面代码;

我们看到,我们是用three的一个PlaneGeometry类画了一张面板(你可以把它看作我们今后写shader的画板),然后在这个面板上应用shader材质,这个材质呈现什么样的效果全靠我们去写这个shader啦。比如说,上述代码就是写了一个正余弦波,并且利用一个递增的变量实现波的移动效果。

虽然这个shader很简单,但是还是有必要解析一下,顺便温习一下高中学的三角函数。

二、demo中着色器代码解析

<!-- 顶点着色器 -->
<script id="vertex-shader" type="x-shader/x-vertex">
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script> <!-- 片元着色器 -->
<script id="fragment-shader-8" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution; void main( void ) {
float x = gl_FragCoord.x;
float y = gl_FragCoord.y;
float fy = sin(x / . + time * .) * . + .;
float opacity = 0.0;
if(y > fy){
opacity = 1.0;
}
gl_FragColor = vec4(.,.,.,opacity);
}
</script>

顶点着色器就是把plane的顶点通过矩阵变换转成屏幕上的像素点;

然后在片元着色器中对这些顶点进行逐个着色(如果有1w个顶点,那么这个片元着色器代码就会跑1w次,因为是在GPU中并行地跑,所以很快),gl_FragCoord就是当前操作的顶点,而gl_FragColor算出来的颜色就是用来在该顶点输出到屏幕的颜色值;

所以片元着色器就是给你一个顶点gl_FragCoord(屏幕上的像素点),你来决定输出什么颜色gl_FragColor!

我们看这段main函数里面的代码:

float fy = sin(x / 100. + time * 5.) * 100. + 250.;
是不是很熟悉?

ok,到这里,正弦波就算出来了,但是颜色呢?因为根据每个x,我们算出对应正弦波上的y值,对应屏幕上每个x来说,都有n个y与之对应,那么上面的做法是,在正弦波上面的这些点的颜色的透明通道值为1.0,在下面的这些点的颜色的透明通道值为0,然后再加上横轴的偏移量θ,这里是变量time,由于time是变化的,所以就出现了上图所示的效果。

以此类推,我们还能写出指数函数、幂函数等的图像

二、幂函数

顶点着色器共用的,就不贴了

<!-- 片元着色器 -->
<script id="fragment-shader-8" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution; void main( void ) {
float x = gl_FragCoord.x;
float y = gl_FragCoord.y;
float fy = pow((x - time * .)/.,2.0) + .;
float opacity = 0.0;
if(y > fy){
opacity = 1.0;
}
gl_FragColor = vec4(.,.,.,opacity);
}
</script>

其余的曲线方程如果你有兴趣可以自己试着写写看

GPU编程shader之正余弦波和幂/指数函数的更多相关文章

  1. MATLAB实现连续周期信号的频谱分析(正余弦波信号举例)

    关于MATLAB实现连续信号的频谱分析,以正余弦波信号频谱分析为例分析如下: 1.含有频率f ,2f和3f的正弦波叠加信号,即: 其中,f =500Hz.试采用Matlab仿真软件对该信号进行频谱分析 ...

  2. MT【34】正余弦的正整数幂次快速表示成正余弦的线性组合

    问题:如何快速把$cos^4xsin^3x$表示成正弦,余弦的线性组合? 分析:利用牛顿二项式展开以下表达式: 再利用欧拉公式$e^{i\theta}=cos\theta+isin\theta$ 比如 ...

  3. cg语言学习&&阳春白雪GPU编程入门学习

    虽然所知甚少,但康大的<GPU编程与Cg编程之阳春白雪下里巴人>确实带我入了shader的门,在里面我第一次清晰地知道了“语义”的意思,非常感谢. 入门shader,我觉得可以先读3本书: ...

  4. GPU编程和流式多处理器(三)

    GPU编程和流式多处理器(三) 3. Floating-Point Support 快速的本机浮点硬件是GPU的存在理由,并且在许多方面,它们在浮点实现方面都等于或优于CPU.全速支持异常可以根据每条 ...

  5. Point : GPU编程的艺术!一切的历史!

    Point: 渲染渲染,神奇的渲染!! ———————————————— 只要你走的足够远,你肯定能到达某个地方. 1"GPU编程" History ————————— //由于笔 ...

  6. GPU 编程入门到精通(四)之 GPU 程序优化

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  7. GPU 编程入门到精通(三)之 第一个 GPU 程序

    博主因为工作其中的须要.開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程,因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  8. 使用CORDIC算法求解角度正余弦及Verilog实现

    本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考:并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码.简单的testbench测试代码.以及在Mod ...

  9. GPU编程和流式多处理器(四)

    GPU编程和流式多处理器(四) 3.2. 单精度(32位) 单精度浮点支持是GPU计算的主力军.GPU已经过优化,可以在此数据类型上原生提供高性能,不仅适用于核心标准IEEE操作(例如加法和乘法),还 ...

随机推荐

  1. zencart后台管理中选项名称和选项内容和属性控制页面出错解决办法 WARNING: An Error occurred, please refresh the page and try again

    后台管理中选项名称和选项内容和属性控制出现以下错误的解决办法WARNING: An Error occurred, please refresh the page and try again zen ...

  2. 博弈论BOSS

    基础博弈的小结:http://blog.csdn.net/acm_cxlove/article/details/7854530 经典翻硬币游戏小结:http://blog.csdn.net/acm_c ...

  3. 安装theano遇到的问题

    嗯,听说keras虽然说有TensorFlow有backend就够了,在TensorFlow和theano之间来回切换还是会有用的,然后又补安装了theano 之前解了权限了,所以不需要sudo 直接 ...

  4. TCP协议(包括TCP的连接过程,数据分段,TCP有关服务器优化)

    Transmission Control Protocol/Internet Protocol 传输控制协议/因特网互联协议 TCP/IP是一个Protocol Stack(协议栈),包括TCP.IP ...

  5. programble blending --frame buffer fetch

    https://developer.arm.com/-/media/Files/pdf/graphics-and-multimedia/Efficient%20Rendering%20with%20T ...

  6. java.io.WinNTFileSystem

    Unicode-aware FileSystem for Windows NT/2000. Since: 1.4 Author: Konstantin Kladko

  7. 32. ClustrixDB License管理

    一.许可的概述 ClustrixDB必须拥有有效的许可证才能运行.本授权指定: 集群中允许的最大节点数 ClustrixDB将使用的最大核数 在裸金属系统上,ClustrixDB将尝试启用与已授权的物 ...

  8. join on 和group

                       左边的表是article文章表,右边的是comment文章回复表. 今天mysql查询的时候,遇到了有趣的事,任务是查询数据库需要得到以下格式的文章标题列表,并按 ...

  9. CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)D

    题面 一开始想到一个 O(N^2) 做法,先把x排序,然后顺次枚举x最大的点,看向前最多可以保留多少点 (也就是先不管正方形的上下长度限制,先考虑左右的限制).然后再对这些点做一遍类似的..(等等这么 ...

  10. Codevs 1851 越狱 2008年湖南省队选拔赛

    1851 越狱 2008年湖南省队选拔赛 时间限制: 10 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 监狱有连续编号为1-N的N个房间,每 ...