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操作(例如加法和乘法),还 ...
随机推荐
- zencart设置默认货币三种方法
zencart设置默认货币为USD 方法一:mysql UPDATE configuration SET configuration_value = 'USD' WHERE configuration ...
- 网络协议相关面试问题-https加密算法相关面试问题
密钥: 密钥是一种参数,它是在使用密码cipher算法过程中输入的参数,同一个明文在相同的密码算法和不同的密钥计算下会产生不同的密文.所以说算法既使公开了但是密钥参数不同其结果也是不同的,其中关于明文 ...
- kubernetes(K8S)快速安装与配置集群搭建图文教程
kubernetes(K8S)快速安装与配置集群搭建图文教程 作者: admin 分类: K8S 发布时间: 2018-09-16 12:20 Kubernetes是什么? 首先,它是一个全新的基于容 ...
- 服务器syns to listen sockets drop导致创建socket失败
在一次测试执行过程中,发现服务器TCP发送队列较长,执行netstat -s | grep LISTEN,发现有SYNs包被丢弃,但是没有times the listen queue of a soc ...
- SSH框架整合报错org.springframework.web.context.ContextLoaderListener
是因为在导入的jar包中缺少了一个 org.springframework.web_3.1.4.release.jar 在网上下载即可 下载地址: http://www.java2s.com/Code ...
- AJAX增删查
数据库 CREATE DATABASE crmweb; CREATE TABLE `customerstatus` ( `id` bigint(20) NOT NULL AUTO_INCREMENT ...
- beeline启动时,错误 User: root is not allowed to impersonate root
错误: beeline>!connect jdbc:hive2://192.168.33.01:10000 root rootConnecting to jdbc:hive2://192.168 ...
- git回退错误的提交
提交代码导致冲突,执行merge后,冲掉其他人的提交.需要reset,并新建分支进行恢复 解决方法: 1.找到最后一次提交到master分支的版本号,即[merge前的版本号] 2.会退到某个版本号 ...
- 修改jupyter notebook的字体等样式
方法一 /lib/site-packages/notebook/static/custom/ 里面有个custom.css文件,你只要修改这个文件就可以了. /* jupyter notebook中显 ...
- Okhttp源码分析--基本使用流程分析
Okhttp源码分析--基本使用流程分析 一. 使用 同步请求 OkHttpClient okHttpClient=new OkHttpClient(); Request request=new Re ...