GPU编程shader之正余弦波和幂/指数函数
先上一个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函数里面的代码:
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之正余弦波和幂/指数函数的更多相关文章
- MATLAB实现连续周期信号的频谱分析(正余弦波信号举例)
关于MATLAB实现连续信号的频谱分析,以正余弦波信号频谱分析为例分析如下: 1.含有频率f ,2f和3f的正弦波叠加信号,即: 其中,f =500Hz.试采用Matlab仿真软件对该信号进行频谱分析 ...
- MT【34】正余弦的正整数幂次快速表示成正余弦的线性组合
问题:如何快速把$cos^4xsin^3x$表示成正弦,余弦的线性组合? 分析:利用牛顿二项式展开以下表达式: 再利用欧拉公式$e^{i\theta}=cos\theta+isin\theta$ 比如 ...
- cg语言学习&&阳春白雪GPU编程入门学习
虽然所知甚少,但康大的<GPU编程与Cg编程之阳春白雪下里巴人>确实带我入了shader的门,在里面我第一次清晰地知道了“语义”的意思,非常感谢. 入门shader,我觉得可以先读3本书: ...
- GPU编程和流式多处理器(三)
GPU编程和流式多处理器(三) 3. Floating-Point Support 快速的本机浮点硬件是GPU的存在理由,并且在许多方面,它们在浮点实现方面都等于或优于CPU.全速支持异常可以根据每条 ...
- Point : GPU编程的艺术!一切的历史!
Point: 渲染渲染,神奇的渲染!! ———————————————— 只要你走的足够远,你肯定能到达某个地方. 1"GPU编程" History ————————— //由于笔 ...
- GPU 编程入门到精通(四)之 GPU 程序优化
博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...
- GPU 编程入门到精通(三)之 第一个 GPU 程序
博主因为工作其中的须要.開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程,因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...
- 使用CORDIC算法求解角度正余弦及Verilog实现
本文是用于记录在了解和学习CORDIC算法期间的收获,以供日后自己及他人参考:并且附上了使用Verilog实现CORDIC算法求解角度的正弦和余弦的代码.简单的testbench测试代码.以及在Mod ...
- GPU编程和流式多处理器(四)
GPU编程和流式多处理器(四) 3.2. 单精度(32位) 单精度浮点支持是GPU计算的主力军.GPU已经过优化,可以在此数据类型上原生提供高性能,不仅适用于核心标准IEEE操作(例如加法和乘法),还 ...
随机推荐
- kotlin函数和函数式表达式
这次的写法可能有些怪异,但是如果熟悉java8的Lambda表达式的话其实理解起来很顺其自然[参考博客:http://www.cnblogs.com/webor2006/p/7705130.html] ...
- (十二)zabbix监控redis
1)agent端配置 安装redis yum install epel-release -y yum install redis -y 配置认证密码 #vim /etc/redis.conf requ ...
- PassengerNginxdebian快速部署Rails
Passenger/Nginx/Debian快速部署Rails PassengerNginxdebian快速部署Rails 安装所需的linux包 sudo apt-get install ...
- JAVA_GET请求URL
import java.io.IOException; import net.sf.json.JSONObject; import org.apache.commons.httpclient.Defa ...
- [Spring boot] CommandLineRunner and Autowired
Previously we use Application Context to get Bean and Dependenies injection. It is actually easier t ...
- 对称加密算法DES、3DES和AES 原理总结(转载)
1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...
- Linux系统挂载存储只读改成读写
Copy from:https://blog.csdn.net/u010977122/article/details/53316671 1.mount:用于查看哪个模块输入只读,一般显示为:[root ...
- vue路由跳转push,replace,go
this.$router.replace({ path: "/subpagest" });//不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 his ...
- Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery
PyQuery:一个类似jquery的python库 学习一时爽,一直学习一直爽 Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 BeautifulSoup 美味 ...
- RabbitMQ安装遇到的问题及解决记录
提示:若是win10 请注意计算机名称不能有中文 安装Rabbit MQ 需要先安装 Erlang 这里下载版本Erlang OTP22.0 http://www.erlang.org/downloa ...