主頁 > 企業開發 > 記錄--Threejs-著色器實作一個水波紋

記錄--Threejs-著色器實作一個水波紋

2023-06-28 09:58:41 企業開發

這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

hree.js 是一個基于 WebGL 的 JavaScript 3D 庫,用于創建和渲染 3D 圖形場景,

一、 影像渲染程序

1、webGL

webGL: WebGL 是一種基于 JavaScript API 的圖形庫,它允許在瀏覽器中進行高性能的 3D 圖形渲染,webGL的渲染依賴于底層GPU的渲染能力,
通過獲取<canvas>元素獲取WebGL的背景關系,從而獲得WebGL API和GPU,
GPU 圖形處理器:處理圖形計算的硬體,GPU運行著一個著色器小程式,包含兩種型別的著色器程式,頂點著色器片元著色器

2、著色器

著色器:

3、坐標系

(1)模型空間:物體在其自身坐標系下的位置、大小、方向,
(2)世界空間:所有模型都放置在同一坐標系下的空間,每個物體都有唯一的坐標系,如three.js的AxesHelper是基于世界空間創建的坐標系,
(3)視圖空間:相機所在的坐標系,簡單來說就是以相機為原點,物體在相機眼中的位置,
(4)投影空間:將3D圖形投影到二維螢屏上的坐標系,將3D坐標轉化為2D坐標,
各個坐標系之間的轉換:通過矩陣變換來完成,例如,將物體從模型空間轉換到世界空間,可以使用模型變換矩陣將區域坐標轉換為全域坐標,將物體從世界空間轉換到視圖空間,可以使用相機變換矩陣將全域坐標變換為相機坐標,最后,將視圖空間中的坐標投影到螢屏上,可以使用投影變換矩陣將相機坐標變換為裁剪坐標,通過這些矩陣變換,可以將坐標從一個空間轉換到另一個空間,從而實作3D圖形的渲染和顯示,

4、GPU渲染程序

(1)渲染管線:就是將3D坐標轉化為螢屏像素(螢屏都是二維的,也就是二維坐標)的程序,分為以下幾個階段,
應用階段:由CPU控制,主要負責資料的準備和處理,CPU將資料發送的GPU,包括圖形的頂點坐標、紋理坐標、顏色資訊等 ,
幾何階段:運行在GPU中,將頂點坐標變換到螢屏空間中,
光柵化階段:階段運行在GPU中,光柵化階段主要將渲染圖元轉換為像素,并進行顏色插值、紋理采樣等處理,最終輸出渲染像素,

(2)GPU具體渲染程序,

 齊次裁剪空間:簡單來說就是相機視錐體的范圍,如下圖

二、著色器材質

three.js中有兩個著色器材質ShaderMaterial和原始著色器材質RawShaderMaterial,它是用著色器語言GLSL撰寫的程式,可以讓我們自定義物體的著色器程式,從而實作復雜的效果, 1、ShaderMaterial:材質接收兩個著色器,頂點著色器和片元著色器,著色器代碼需要我們自己撰寫,來實作復雜的效果,來看下如何使用,

用著色器材質實作下面這個效果:

qi.gif

搭建目錄結構和基礎看這里

1、首先搭建一個three.js場景
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>threejs_collision</title>
    <link rel="stylesheet" href="https://www.cnblogs.com/smileZAZ/archive/2023/06/27/asstes/css/style.css">
</head>
<body>
    <script src="https://www.cnblogs.com/smileZAZ/archive/2023/06/27/main/index.js" type="module"></script>
</body>
</html>
*{
    padding: 0;
    margin: 0;
}
body,html {
    background: green;
}
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 創建場景
const scene = new THREE.Scene();
// 創建相機
const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
);
// 設定相機位置
camera.position.set(0, 0, 10);
//將相機添加到
scene.add(camera);

//創建環境光,環境光會均勻的照亮場景中的所有物體,
const light = new THREE.AmbientLight(0x404040);
//將環境光添加到場景
scene.add(light);
// 創建平行光
const directionalLight = new THREE.DirectionalLight();
//設定光源位置
directionalLight.position.set(0, 5, 0);
//添加到場景
scene.add(directionalLight);
//設定光源投射陰影
directionalLight.castShadow= true

// 創建渲染器
const renderer = new THREE.WebGLRenderer();
// 設定渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
//開啟渲染器陰影計算
renderer.shadowMap.enabled = true
//將canvas添加到body中
document.body.appendChild(renderer.domElement);

// 軌道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 軌道控制器的阻尼感
controls.enableDamping = true;
//輔助坐標軸
const axesHelp = new THREE.AxesHelper();
scene.add(axesHelp);


const clock = new THREE.Clock()
//渲染函式
function render() {
    //阻尼
    controls.update()
    let time = clock.getDelta();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
// 初始化渲染函式
render();
// 監聽瀏覽器視窗尺寸變化
window.addEventListener('resize',() => {
    //重新設定相機寬高比
    camera.aspect = window.innerWidth / window.innerHeight;
    //更新相機投影矩陣
    camera.updateProjectionMatrix();
    //重新設定渲染器尺寸
    renderer.setSize(window.innerWidth,window.innerHeight);
    //設定設備像素比
    renderer.setPixelRatio(window.devicePixelRatio)
})
2、創建著色器材質

從上面動圖可以看出,是一個平面貼了一張圖,然后給這個平面加了wave的效果,
所以,先創建一個平面,

const planeGeometry = new THREE.PlaneGeometry(1,1,64,64);
引入貼圖
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(
    require('../asstes/img/texture/xx.jpeg')
)

創建一個shader檔案夾存放著色器代碼,新建一個兩個.glsl檔案,來寫頂點著色器和片元著色器代碼,如下:

image.png
在js檔案中引入這兩個著色器:

import vertexShaderText from '../shader/basic/vertex.glsl'
import fragmentShaderText from '../shader/basic/fragment.glsl'
創建著色器材質
const material = new THREE.ShaderMaterial({
    // 頂點著色器
    vertexShader:vertexShaderText,
    // 片元著色器
    fragmentShader:fragmentShaderText,
    // 設定兩面可見,默認只能看見一面
    side:THREE.DoubleSide,
})
3、撰寫著色器代碼

頂點著色器 使用的是著色器語言(GLSL),不會也沒事,知道怎么接收引數,在哪寫邏輯就夠了,首先要有一個入口點,也就是下面的void main函式,對資料的處理就寫在這里面,
shader中有三種型別的變數: uniforms, attributes, 和 varyings
uniforms:從應用程式(CPU)傳到著色器的變數(GPU),頂點著色器和片元著色器都能訪問,比如我們可以在ShaderMaterial傳遞uniforms,在著色器程式中接收,用法:接收:uniform float uTime;
attributes:與每個頂點關聯的變數,例如,頂點位置,法線和頂點顏色都是存盤在attributes中的資料,attributes  可以在頂點著色器中訪問,用法:attribute vec3 position
Varyings:在頂點著色器和片元著色器中傳遞資料,可以將頂點著色器處理過的資料通過varyings傳給片元著色器,用法:varying vec2 vUv;

// 高精度浮點數
precision highp float;
void main(){
    // vec4 四維向量
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    // projectionMatrix 投影矩陣;viewMatrix 視圖矩陣;modelMatrix 模型矩陣;跟上面提到的坐標系對應,這些都是內置的uniform,使用ShaderMaterial會自動到GLSL shader代碼中,使用RawShaderMaterial不會自動添加,需要手動接收,
    //gl_Position是一個內置變數,它表示經過投影、視圖和模型變換后的頂點位置,
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
片元著色器:
// 中等精度浮點數
precision mediump float;
void main(){
    // gl_FragColor內置物件,片元的顏色值 vec4是個思維變數這里代表了紅色分量、綠色分量、藍色分量和透明度分量,
    gl_FragColor = vec4(1.0,1.0,0.0,1.0);    
}

效果:注意這個平面的顏色是片元著色器里gl_FragColor物件決定的,現在是寫死的(當然也可以寫活),

image.png

接下來給這個平面添加wave的效果:這個平面在X、y軸,通過改變Z軸的坐標來使平面有上下波動的效果,這個波動的效果像不像正弦余弦曲線,可以通過sin,cos實作這個效果,可以通過Uniforms變數將資料傳給頂點著色器和片元著色器,

const clock = new THREE.Clock()
//渲染函式
function render() {
    let time = clock.getElapsedTime()
    material.uniforms.uTime.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/time;
}

const material = new THREE.ShaderMaterial({
    uniforms:{
        uTime:{
            value:0
        },
        // 貼圖
        uTexture:{
            value: texture
        }
    }
})
頂點著色器程式:
precision mediump float;
uniform float uTime;
//varying:從頂點著色器傳遞到片元著色器的變數, 將uv傳遞到片元著色器,uv是二維坐標,是物體頂點在紋理上的映射位置(相當于將一個3維物體展開后的對應的二維位置),傳遞給片元著色器可以讀取該坐標處的顏色,賦值給gl_FragColor,實作貼圖效果,
varying vec2 vUv;
void main(){
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    modelPosition.z = sin((modelPosition.x + uTime) * 10.0) * 0.05;
    modelPosition.z += sin((modelPosition.y + uTime) * 10.0) * 0.05;
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
片元著色器程式:
precision mediump float;
// sampler2D型別的紋理變數
uniform sampler2D uTexture;
// 接收頂點著色器傳來的uv
varying vec2 vUv;
void main(){
     // texture2D是用于讀取紋理顏色值的函式
    vec4 textureColor = texture2D(uTexture,vUv);
    gl_FragColor = textureColor;
    
}

這樣就是實作了以上效果,
image.png

如果是RawShaderMaterial材質,內置的uniform需要手動去接收,以上代碼改成:
頂點著色器程式:

precision mediump float;
// 定義頂點
attribute vec3 position;
//定義位置引數
attribute vec2 uv;
// 傳入投影矩陣
uniform mat4 projectionMatrix;
// 傳入視圖矩陣
uniform mat4 viewMatrix;
// 傳入模型矩陣
uniform mat4 modelMatrix;
//接收著色器材質傳遞的時間引數
uniform float uTime;
// uv傳遞到片元著色器 varying是從頂點著色器傳遞到片元著色器的變數
varying vec2 vUv;
void main(){
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4(position,1.0);
    modelPosition.z = sin((modelPosition.x + uTime) * 10.0) * 0.05;
    modelPosition.z += sin((modelPosition.y + uTime) * 10.0) * 0.05;
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

三、著色器實作一個水波紋

水波紋相對于上面旗幟飄動的效果,多了些隨機性,如水波的高度是變化的,波浪的起伏是隨機的,高處和低處的顏色不一樣,水波波動的大小、頻率等,這里用到了一些隨機函式,將這些隨機性添加給波浪的高度來達到更真實的效果,下面定義了很多引數,這些引數可以自己去調節看看它們是什么作用,

const material = new THREE.ShaderMaterial({
    vertexShader:vertexShaderText,
    fragmentShader:fragmentShaderText,
    side:THREE.DoubleSide,
    uniforms:{
        uTime:{
            value:0
        },
        uWaresFrequency:{
            value:params.uWaresFrequency
        },
        uScale:{
            value:params.uScale
        },
        uNoiseFrequency:{
            value:params.uNoiseFrequency
        },
        uNoiseScale:{
            value: params.uNoiseScale
        },
        uXzScale:{
            value: params.uXzScale
        },
        uLowColor:{
            value:new THREE.Color(params.uLowColor)
        },
        uHighColor: {
            value:new THREE.Color(params.uHighColor)
        },
        uOpacity:{
            value:params.uOpacity
        }
    },
    transparent: true
})

const plane = new THREE.Mesh(planeGeometry,material)
plane.rotation.x = -Math.PI / 2
scene.add(plane)

// 將這些uniforms變數添加到gui在,方便看效果,找到最合適的值,
gui.add(params,'uWaresFrequency').min(1).max(50).step(0.1).onChange(val => {
    material.uniforms.uWaresFrequency.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
});
gui.add(params,'uScale').min(0).max(0.2).step(0.01).onChange(val => {
    material.uniforms.uScale.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
});
gui.add(params,'uNoiseFrequency').min(0).max(100).step(0.1).onChange(val => {
    material.uniforms.uNoiseFrequency.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
});
gui.add(params,'uNoiseScale').min(0).max(5).step(0.01).onChange(val => {
    material.uniforms.uNoiseScale.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
});
gui.add(params,'uXzScale').min(1).max(5).step(0.01).onChange(val => {
    material.uniforms.uXzScale.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
});
gui.addColor(params,'uLowColor').onFinishChange(val => {
    material.uniforms.uLowColor.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/new THREE.Color(val)
})
gui.addColor(params,'uHighColor').onFinishChange(val => {
    material.uniforms.uHighColor.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/new THREE.Color(val)
})
gui.add(params,'uOpacity').min(0).max(1).onChange(val => {
    material.uniforms.uOpacity.value = https://www.cnblogs.com/smileZAZ/archive/2023/06/27/val;
})
頂點著色器程式:里面的函式都是從這本書里抄的
uniform float uTime;
uniform float uWaresFrequency;
uniform float uScale;
uniform float uNoiseFrequency;
uniform float uNoiseScale;
uniform float uXzScale;
varying float vElevation;

float random (vec2 st) {
    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}
// 旋轉函式
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{
    return vec2(
    cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
    cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
    );
}

// 2d噪聲函式 
float noise (in vec2 st) {
    vec2 i = floor(st);
    vec2 f = fract(st);
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));
    vec2 u = f*f*(3.0-2.0*f);
    return mix(a, b, u.x) +
    (c - a)* u.y * (1.0 - u.x) +
    (d - b) * u.x * u.y;
}
// 隨機函式
vec4 permute(vec4 x)
{
    return mod(((x*34.0)+1.0)*x, 289.0);
}
vec2 fade(vec2 t)
{
    return t*t*t*(t*(t*6.0-15.0)+10.0);
}
float cnoise(vec2 P)
{
    vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
    vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
    Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
    vec4 ix = Pi.xzxz;
    vec4 iy = Pi.yyww;
    vec4 fx = Pf.xzxz;
    vec4 fy = Pf.yyww;
    vec4 i = permute(permute(ix) + iy);
    vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
    vec4 gy = abs(gx) - 0.5;
    vec4 tx = floor(gx + 0.5);
    gx = gx - tx;
    vec2 g00 = vec2(gx.x,gy.x);
    vec2 g10 = vec2(gx.y,gy.y);
    vec2 g01 = vec2(gx.z,gy.z);
    vec2 g11 = vec2(gx.w,gy.w);
    vec4 norm = 1.79284291400159 - 0.85373472095314 * vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
    g00 *= norm.x;
    g01 *= norm.y;
    g10 *= norm.z;
    g11 *= norm.w;
    float n00 = dot(g00, vec2(fx.x, fy.x));
    float n10 = dot(g10, vec2(fx.y, fy.y));
    float n01 = dot(g01, vec2(fx.z, fy.z));
    float n11 = dot(g11, vec2(fx.w, fy.w));
    vec2 fade_xy = fade(Pf.xy);
    vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
    float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
    return 2.3 * n_xy;
}

void main() {
    vec4 modelPosition = modelMatrix * vec4(position,1.0);
    // 波浪高度
    float elevation = sin(modelPosition.x * uWaresFrequency) * sin(modelPosition.z * uWaresFrequency * uXzScale);
    elevation += cnoise(vec2(modelPosition.xz*uNoiseFrequency+uTime))
    *uNoiseScale;
    elevation *= uScale;
    // 傳到片元著色器
    vElevation = elevation;
    modelPosition.y += elevation;
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
片元著色器程式:
varying float vElevation;
uniform vec3 uLowColor;
uniform vec3 uHighColor;
uniform float uOpacity;
void main(){
    float a = (vElevation + 1.0) / 2.0;
    // 混合顏色
    vec3 color = mix(uLowColor,uHighColor,a);
    gl_FragColor = vec4(color,uOpacity);
}
最終效果(效果可以調節引數,調到自己滿意的效果): waterWave.gif

本文轉載于:

https://juejin.cn/post/7248982532728864825

如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556154.html

標籤:其他

上一篇:CSS實作根據子元素數量應用不同樣式

下一篇:返回列表

標籤雲
其他(161754) Python(38255) JavaScript(25515) Java(18266) C(15238) 區塊鏈(8273) C#(7972) AI(7469) 爪哇(7425) MySQL(7270) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4607) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2437) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1976) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 記錄--Threejs-著色器實作一個水波紋

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 hree.js 是一個基于 WebGL 的 JavaScript 3D 庫,用于創建和渲染 3D 圖形場景。 一、 影像渲染程序 1、webGL webGL: WebGL 是一種基于 JavaScript API 的圖形庫,它允許在瀏覽器 ......

    uj5u.com 2023-06-28 09:58:41 more
  • CSS實作根據子元素數量應用不同樣式

    theme: condensed-night-purple highlight: atelier-cave-light 在前端的頁面布局中經常會出現在子元素個數使用不同的樣式的需求,比如文章串列,在較少內容下單串列現,而在元素內容較多時使用雙串列現。再比如在頁面排版上,可以根據元素內容的多少來修改內 ......

    uj5u.com 2023-06-28 09:57:34 more
  • 618技術揭秘:探究競速榜頁面核心前端技術

    本文將探究京東競速榜H5頁面的核心前端技術,包括影片、樣式配置化、皮膚切換、海報技術、除錯技巧等方面,希望能夠為廣大前端開發者提供一些有用的參考和思路。 ......

    uj5u.com 2023-06-28 09:57:04 more
  • CSS實作根據子元素數量應用不同樣式

    theme: condensed-night-purple highlight: atelier-cave-light 在前端的頁面布局中經常會出現在子元素個數使用不同的樣式的需求,比如文章串列,在較少內容下單串列現,而在元素內容較多時使用雙串列現。再比如在頁面排版上,可以根據元素內容的多少來修改內 ......

    uj5u.com 2023-06-28 09:56:39 more
  • 前端Vue自定義加載中loading加載結束end組件 可用于分頁展示 頁

    #### 前端Vue自定義加載中loading加載結束end組件 可用于分頁展示 頁面加載請求, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13219 #### 效果圖如下: ![](https://p3-juejin.byteimg. ......

    uj5u.com 2023-06-27 10:04:55 more
  • 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼

    #### 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼登錄模版 密碼登錄模版, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13221 #### 效果圖如下: #### ![](https://p3-juejin. ......

    uj5u.com 2023-06-27 10:04:49 more
  • 前端Vue自定義發送短信驗證碼彈框popup 實作剩余秒數計數 重發短

    前端Vue自定義發送短信驗證碼彈框popup 實作剩余秒數計數 重發短信驗證碼, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13207 效果圖如下: ![](https://p3-juejin.byteimg.com/tos-cn-i- ......

    uj5u.com 2023-06-27 10:04:45 more
  • 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼

    #### 前端Vue自定義驗證碼密碼登錄切換tabs選項卡標簽欄標題欄 驗證碼登錄模版 密碼登錄模版, 請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13221 #### 效果圖如下: #### ![](https://p3-juejin. ......

    uj5u.com 2023-06-27 10:04:15 more
  • 驅動開發:內核讀寫記憶體多級偏移

    讓我們繼續在`《內核讀寫記憶體浮點數》`的基礎之上做一個簡單的延申,如何實作多級偏移讀寫,其實很簡單,讀寫函式無需改變,只是在讀寫之前提前做好計算作業,以此來得到一個記憶體偏移值,并通過呼叫記憶體寫入原函式實作寫出資料的目的。以讀取偏移記憶體為例,如下代碼同樣來源于本人的`LyMemory`讀寫驅動專案,其... ......

    uj5u.com 2023-06-27 09:58:39 more
  • 驅動開發:內核讀寫記憶體多級偏移

    讓我們繼續在`《內核讀寫記憶體浮點數》`的基礎之上做一個簡單的延申,如何實作多級偏移讀寫,其實很簡單,讀寫函式無需改變,只是在讀寫之前提前做好計算作業,以此來得到一個記憶體偏移值,并通過呼叫記憶體寫入原函式實作寫出資料的目的。以讀取偏移記憶體為例,如下代碼同樣來源于本人的`LyMemory`讀寫驅動專案,其... ......

    uj5u.com 2023-06-27 09:56:17 more