ThreeJS-3D教学十二:ShaderMaterial

一、首先 Shader 是做什么的
Shader 可以自定义每个顶点、每个片元/像素如何显示,而控制顶点和片元显示是通过设置 vertexShader 顶点着色器和 fragmentShader 片元着色器,这两个着色器用在 ShaderMaterial 和 RawShaderMaterial 材质上。
我们先看一个例子:
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<title>three.js webgl - raw shader</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<div id="container"></div>
<script id="vertexShader" type="x-shader/x-vertex">
	uniform mat4 modelViewMatrix;
	uniform mat4 projectionMatrix;
	attribute vec3 position;
	void main()	{
		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
	}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
	void main()	{
		gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
	}

</script>
<script type="importmap">
	{
		"imports": {
          "three": "../three-155/build/three.module.js",
          "three/addons/": "../three-155/examples/jsm/"
        }
	}
</script>

<script type="module">
  import * as THREE from 'three';
  import Stats from 'three/addons/libs/stats.module.js';
  import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  let container, stats, controls;
  let camera, scene, renderer;

  init();
  animate();
  initObject();

  function initObject() {
    // geometry
    // 第一个是生成几个三角形 
    const vertexCount = 2 * 3;
    const geometry = new THREE.BufferGeometry();
    const positions = [];
    const colors = [];

    for ( let i = 0; i < vertexCount; i ++ ) {
      // adding x,y,z
      positions.push( Math.random() - 0.5 );
      positions.push( Math.random() - 0.5 );
      positions.push( Math.random() - 0.5 );
      // adding r,g,b,a
      colors.push( Math.random() * 255 );
      colors.push( Math.random() * 255 );
      colors.push( Math.random() * 255 );
      colors.push( Math.random() * 255 );
    }

    const positionAttribute = new THREE.Float32BufferAttribute( positions, 3 );
    const colorAttribute = new THREE.Uint8BufferAttribute( colors, 4 );
    colorAttribute.normalized = true; // this will map the buffer values to 0.0f - +1.0f in the shader
    geometry.setAttribute( 'position', positionAttribute );
    geometry.setAttribute( 'color', colorAttribute );

    // material
    const material = new THREE.RawShaderMaterial({
      uniforms: {
        time: { value: 1.0 }
      },
      vertexShader: document.getElementById( 'vertexShader' ).textContent,
      fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
      side: THREE.DoubleSide,
      transparent: true
    });
    const mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );
  }

  function init() {
    container = document.getElementById( 'container' );
    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10 );
    camera.position.z = 2;
    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0x101010 );
    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );
    controls = new OrbitControls( camera, renderer.domElement );
    stats = new Stats();
    container.appendChild( stats.dom );
    window.addEventListener( 'resize', onWindowResize );

  }

  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
    controls.update();
    stats.update();
  }
  function render() {
    const time = performance.now();
    const object = scene.children[0];
    if (object) {
      // object.rotation.y = time * 0.0005;
      object.material.uniforms.time.value = time * 0.005;
    }
    renderer.render( scene, camera );
  }
</script>
</body>
</html>

以上代码 顶点着色器 我们用的是固定写法计算顶点的位置

gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
或者也可以这样:
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );

而片元着色器我们设置了一个白色
我相信大家会对 scropt 中 x-shader/x-vertex、x-shader/x-fragment 很陌生,没关系咱们学习 Shader 其实大部分就是学这里面怎么写:
它是一种类似C语言的 GLSL 语言——即 OpenGL Shading Language——,
JavaScript、C 等语言通常在 CPU 上执行,而着色器语言通常在 GPU 上执行,由 GPU 分别对每个顶点、每个片元独立执行

shader 程序可以单独写在诸如 vertex.glsl、fragment.glsl 的文件里再导入使用,也可以和示例一样写在script中,或者在 JavaScript 里用字符串格式表示(后面会介绍)

在顶点着色器里需要设置 gl_Position顶点位置,在片元着色器里需要设置 gl_FragColor 片元/像素颜色,两者都在没有返回值的 void main() {} 主函数里设置,并且 main 函数会被自动执行

着色器语言三种变量 attribute、uniform 和 varying

  • 简单总结
    顶点着色器渲染定位顶点位置
    片段着色器为该几何体的每个可见片元(像素)进行着色
    片段着色器在顶点着色器之后执行
    在每个顶点之间会有变化的数据(如顶点的位置)称为attribute,只能在顶点着色器中使用
    顶点之间不变的数据(如网格位置或颜色)称为uniform,可以在顶点着色器和片段着色器中使用
    从顶点着色器发送到片元着色器中的插值计算数据被称为varying

看了上面的内容,我们再来看一个案例,提前说下 在这里我无意将所有 GLSL 语言的方法一一列出,我相信大家也不愿意看,毕竟网上一大堆类似文章,官网上也能看,我只是通过案例,把一些常用的知识点给到大家,能让各位对 编写Shader有个初步的认知:

let vertexShader = `
    precision mediump float;
	precision mediump int;
	uniform mat4 modelViewMatrix;
	uniform mat4 projectionMatrix;
	attribute vec3 position;
	attribute vec4 color;
	varying vec3 vPosition;
	varying vec4 vColor;
	void main()	{
		vPosition = position;
		vColor = color;
		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
	}
`;
let fragmentShader = `
    precision mediump float;
	precision mediump int;
	uniform float time;
	varying vec3 vPosition;
	varying vec4 vColor;
	void main()	{
		vec4 color = vec4( vColor );
		color.g += sin( vPosition.x * 10.0 + time ) * 0.5;
		gl_FragColor = color;
	}
`;

上面有几点知识点,先从简单的来,
1、通过 varying 可以将vPosition、vColor 从 vertexShader 到 fragmentShader
2、上面的写法是 shader 程序刚才提到的 字符串格式写法
3、precision 一个新的知识点 - 着色器运算精度设置
通过设置着色器数值的精度可以更好的配置资源,可以根据需要,在不太影响渲染效果前提下,可以尽量降低运算精度。
lowp、mediump和highp关键字 分别对应 低、中、高三个精度

1)通过precision关键字可以批量声明一些变量精度。
比如顶点着色器代码设置precision highp float;,表示顶点着色器中所有浮点数精度为高精度。

2)比如片元着色器代码设置precision lowp int;,表示片元着色器中所有整型数精度为低精度。

3)顶点和片元着色器不同类型数据默认精度
顶点着色器默认精度

数据类型默认精度
int高精度hight
float高度hight
sampler2D低精度lowp
samplerCube低精度lowp

片元着色器默认精度

数据类型默认精度
int中精度mediump
float无默认值,如果片元着色器用到浮点数,注意一定手动设置
sampler2D低精度lowp
samplerCube低精度lowp

4、我们发现有申明 modelViewMatrix、projectionMatrix、position、color变量,这是因为我们使用 RawShaderMaterial材质,这个方法没有默认的内置变量声明,与之对应的我们可以用 ShaderMaterial 材质,此时就可以这样写:

let vertexShader = `
    precision mediump float;
	precision mediump int;
	varying vec3 vPosition;
	varying vec4 vColor;
	void main()	{
		vPosition = position;
		vColor = color;
		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
	}
`;

更多的 内置变量请看这里
通过以上案例我们算是简单的了解了 Shader,发现 Shader其实就是改变 顶点位置 和 片元/像素颜色

二、图形构成的基础 三角形
我们将 geometry 换为一个球体来认识一下图形的基础构成

const geometry = new THREE.SphereGeometry( 0.5, 16, 8 );
const material = new THREE.RawShaderMaterial({

          uniforms: {
            time: { value: 1.0 }
          },
          vertexShader: document.getElementById( 'vertexShader1' ).textContent,
          fragmentShader: document.getElementById( 'fragmentShader1' ).textContent,
          side: THREE.DoubleSide,
          transparent: false,
          wireframe: true  // 将几何体渲染为线框,默认值为false(即渲染为平面多边形)。
        });

在这里插入图片描述
通过这个球体 可以很好的理解 图形的构成,其实就是一个个的三角形,三角形越是多,图形效果越好 当然对电脑性能要求越高,

const geometry = new THREE.SphereGeometry( 0.5, 128, 64);

在这里插入图片描述
可以看到 这个球体就很完美了,通过这个案例也能更好的帮大家理解
顶点着色器渲染顶点位置的顶点 是哪些点、从哪来的点
片段着色器为该几何体的每个可见片元(像素)进行着色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/760870.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web后端开发之前后端交互

http协议 http ● 超文本传输协议 &#xff08;HyperText Transfer Protocol&#xff09;服务器传输超文本到本地浏览器的传送协议 是互联网上应用最为流行的一种网络协议,用于定义客户端浏览器和服务器之间交换数据的过程。 HTTP是一个基于TCP/IP通信协议来传递数据. HTT…

HTML5文旅文化旅游网站模板源码

文章目录 1.设计来源文旅宣传1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 文旅之行界面演示1.5 文旅之行文章内容界面演示1.6 关于我们界面演示1.7 文旅博客界面演示1.8 文旅博客文章内容界面演示1.9 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目…

Oracle、MySQL、PostGreSQL中的多版本读取一致性

multi-version read consistency in Oracle、MySQL、PostGreSQL 在多人同时访问与修改数据时&#xff0c; 最大的难题之一是&#xff1a;一方面要力争最大的并发访问&#xff0c;与此同时还要确保每个用户能以一致的方式读取和修改数据。 ANSI/ISO SQL 标准定义了4 种事务隔离…

“吃饭大学”!中国大学食堂排行TOP10(含西电)

同学们们&#xff0c;考研择校考虑的因素除了学术&#xff0c;地理位置等方面&#xff0c;你们还会考虑哪些因素呢&#xff1f;小研作为一个吃货&#xff0c;必定会考虑的一个因素当然是大学的食堂美食啊~ 那中国超级好吃的大学食堂在哪&#xff1f;一起来看看有没有你的目标院…

input调用手机摄像头实现拍照功能vue

项目需要一个拍照功能&#xff0c;实现功能如下图所示:若使用浏览器则可以直接上传图片&#xff0c;若使用手机则调用手机摄像头拍照。 1.代码结构 <!--input标签--> <input ref"photoRef"type"file"accept"image/*"capture"envir…

4-数据提取方法2(xpath和lxml)(6节课学会爬虫)

4-数据提取方法2&#xff08;xpath和lxml&#xff09;&#xff08;6节课学会爬虫&#xff09; 1&#xff0c;Xpath语法&#xff1a;&#xff08;1&#xff09;选择节点&#xff08;标签&#xff09;&#xff08;2&#xff09;“//”:能从任意节点开始选择&#xff08;3&#xf…

业务链SFC简介

目录 业务链&#xff08;SFC&#xff09;简介什么是业务链&#xff1f;业务链的体系架构业务链的基本工作流程PBRPBR实现的SFC工作流程 NSHNSH报文NSH实现的SFC工作流程 区别 业务链的应用 配置指南 业务链&#xff08;SFC&#xff09;简介 业务链是网络功能虚拟化&#xff08…

华为DCN网络之:VXLAN

VXLAN RFC定义了VLAN扩展方案VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;。VXLAN采用MAC in UDP封装方式&#xff0c;是NVO3&#xff08;Network Virtualization over Layer 3&#xff09;中的一种网络虚拟化技术。 VXLAN…

【前端】从零开始学习编写HTML

目录 一、什么是前端 二、什么是HTML 三、HTML文件的基本结构 四、HTML常见标签 4.1 注释标签 4.2 标题标签 4.3 段落标签 4.4 换行标签 4.5 格式化标签 4.6 图片标签 4.7 超链接标签 4.8 表格标签 4.9 列表标签 4.10 表单标签 &#xff08;1&#xff09;form标…

介绍两个压测工具pgbench\sysbench,可视化监控工具NMON

性能评估做不好&#xff0c;开会又领导点名叼了。/(ㄒoㄒ)/~~ /(ㄒoㄒ)/~~ /(ㄒoㄒ)/~~ 挨叼了&#xff0c;也要写文章&#xff0c;记录下我的笔记。 写篇文章 对数据库、OS性能的性能评估&#xff0c;需要选择合适的压测工具&#xff0c;给找出数据库的运行瓶颈 pgbench 这是…

Redis 集群模式

一、集群模式概述 Redis 中哨兵模式虽然提高了系统的可用性&#xff0c;但是真正存储数据的还是主节点和从节点&#xff0c;并且每个节点都存储了全量的数据&#xff0c;此时&#xff0c;如果数据量过大&#xff0c;接近或超出了 主节点 / 从节点机器的物理内存&#xff0c;就…

【每日刷题】Day78

【每日刷题】Day78 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1608. 特殊数组的特征值 - 力扣&#xff08;LeetCode&#xff09; 2. 1385. 两个数组间的距离值 - …

实现胶囊神经网络,识别手写MNIST数据集,谈谈实现及理解。

&#x1f3c6;本文收录于《CSDN问答解答》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

在安装HDFS过程中遇见Permission denied

HDFS Shell命令权限不足问题解决 问题 想必有同学在实战Shell的时候&#xff0c;遇到了&#xff1a; Permission denied: userroot, accessWRITE, inode"/":hadoop:supergroup:drwxr-xr-x 这种类似的问题。 问题的原因就是没有权限&#xff0c;那么为什么呢&#…

C# OpenCvSharp 实现Reinhard颜色迁移算法

C# OpenCvSharp 实现Reinhard颜色迁移算法 目录 效果 项目 代码 下载 效果 项目 Reinhard颜色迁移算法的步骤&#xff1a; 1、将参考图片和目标图片转换到LAB空间下 2、得到参考图片和目标图片的均值和标准差 3、对目标图片的每一个像素值&#xff0c;减去目标图像均值然后…

【数据结构(邓俊辉)学习笔记】二叉搜索树04——AVL树

文章目录 1.重平衡1.1 AVL BBST1.2 平衡因子1.3 适度平衡1.4 接口1.5 失衡 复衡 2. 插入2.1 单旋2.2 双旋2.3 实现 3. 删除3.1 单旋3.2 双旋3.3 实现 4. &#xff08;3 4&#xff09;-重构4.1 "34"重构4.2 "34"实现4.3 rotateAt4.4 综合评价 1.重平衡 1…

自动雪深传感器的类型

TH-XL2随着科技的飞速发展&#xff0c;气象监测技术也在不断进步。在降雪天气频发的冬季&#xff0c;雪深数据对于保障道路交通、农业生产和电力供应等具有至关重要的作用。自动雪深传感器作为气象监测的重要工具&#xff0c;其类型多样、功能各异&#xff0c;为气象数据的准确…

让GNSSRTK不再难【第17讲 RTK定位技术原理-站间单差浮点解--第1部分】

第17讲 RTK定位技术原理-站间单差浮点解 RTK技术其实就是在RTD技术的基础上增加载波观测值的使用。由于伪距的误差在分米量级&#xff0c;即使我们通过站间单差消除掉绝大部分的伪距误差&#xff0c;但受限于伪距的精度&#xff0c;我们也只能达到分米量级的定位水平。 但载波…

.NET 矩阵6月红队工具和资源集合

01外网入口打点 1.1 Sharp4WbemScripting 1.2 ASP4Eval 1.3 Sharp4Web.config 1.4 Sharp4AddScript 02安全防御绕过 2.1 Sharp4DefenderStop 03搭建代理隧道 3.1 Sharp4suo5 04混淆加密防护 4.1 Obfuscar混淆器 4.2 Sharp4BatchGuard 05安全技术文档 5.1 .NET 通过Junction Fol…