先上一个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. vue-cli 引入 axios 并全局配置axios

    步骤一:vue add axios (向项目添加axios) 步骤二:在main.js 中 修改 如图 步骤三:在组件使用时,直接 this.$http.get().then() 即可......

  2. Python 读写XML文件

    Python 生成XML文件 from xml.dom import minidom # 生成XML文件方式 def generateXml(): impl = minidom.getDOMImple ...

  3. 根据传入url请求,返回json字符串

    /** * 根据传入url请求,返回json字符串 * @param url * @return * @throws UnsupportedEncodingException */ public st ...

  4. BZOJ 2243: [SDOI2011]染色 (树剖+线段树)

    树链剖分后两个区间合并的时候就判一下相交颜色是否相同来算颜色段数就行了. CODE #include <vector> #include <queue> #include &l ...

  5. Mybatis 向oracle批量插入与更新数据

    插入 <insert id="batchSave" parameterType="java.util.List"> INSERT INTO T_UP ...

  6. django之表多对多建立方式、form组件、钩子函数 08

    目录 多对多三种创建方式 1.全自动(用ManyToManyField创建第三张表) 2.纯手写 3.半自动 form组件 引入 form组件的使用 forms组件渲染标签 form表单展示信息 fo ...

  7. Solr full improt时遇到的问题

    安装和配置solr转载于:https://blog.csdn.net/u010510107/article/details/81051795jdk1.8 solr7.2 mysql8.0.17-bin ...

  8. HDU - 6183 暴力,线段树动态开点,cdq分治

    B - Color itHDU - 6183 题目大意:有三种操作,0是清空所有点,1是给点(x,y)涂上颜色c,2是查询满足1<=a<=x,y1<=b<=y2的(a,b)点一 ...

  9. P1121 环状最大两段子段和(DP)

    P1121 环状最大两段子段和 难度 提高+/省选- 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件 ...

  10. AcWing:173. 矩阵距离(bfs)

    给定一个N行M列的01矩阵A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为: dist(A[i][j],A[k][l])=|i−k|+|j−l|dist(A[i][j],A[k][l]) ...