簡體   English   中英

如何處理WebGL GLSL着色器中的大數字?

[英]How to handle big numbers in WebGL GLSL shaders?

我如何處理GLSL中的大數字,例如下面的數字?

我提供了一個帶有Date.now()作為制服的着色器,其描述如下:

Date.now()方法返回自1970年1月1日00:00:00 UTC以來經過的毫秒數。 - MDN

例如, 1514678400000是一年中的最后一天。

將此值傳遞給我的ShaderMaterial導致不會發生太多事情,除非我將該值大幅縮減。

具體來說,這是行為似乎與我對將最后2500毫秒映射到0-1范圍內的值的期望不同的部分:

JavaScript: ( Date.now() % 2500 ) / 2500

GLSL: mod( time, 2500.0 ) / 2500.0

我寧願在GPU上進行這些計算,但我不確定如何處理這個問題?

下面是一個小場景,說明了這個問題:

 const scene = new THREE.Scene() const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) const renderer = new THREE.WebGLRenderer() renderer.setSize( window.innerWidth, window.innerHeight ) camera.position.z = 0.5 document.body.appendChild( renderer.domElement ) const checkbox = document.getElementById( "toggle" ) const geo = new THREE.PlaneGeometry( 1, 1 ) const mat = new THREE.ShaderMaterial({ vertexShader: ` void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `, fragmentShader: ` uniform bool check; uniform float time; const float TAU = 6.2831; void main() { float fColor; check ? fColor = ( sin( ( time * TAU ) ) + 1.0 ) / 2.0 : fColor = ( sin( ( ( mod( time, 2500.0 ) / 2500.0 ) * TAU ) ) + 1.0 ) / 2.0; gl_FragColor = vec4( 1.0, fColor, 1.0, 1.0 ); } `, uniforms: { "check": { value: false }, "time": { value: 1.0 }, }, }) const plane = new THREE.Mesh( geo, mat ) scene.add( plane ) const animate = function() { requestAnimationFrame( animate ) if ( checkbox.checked ) { plane.material.uniforms.check.value = true plane.material.uniforms.time.value = ( Date.now() % 2500 ) / 2500 } else { plane.material.uniforms.check.value = false plane.material.uniforms.time.value = Date.now() } renderer.render( scene, camera ) } animate() 
 body { margin: 0; } canvas { width: 100%; height: 100%; } #config { position: absolute; color: #fff; cursor: pointer; user-select: none; font: bold 1em/1.5 sans-serif; padding: 1em; } #config label, #config input { cursor: pointer; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.js"></script> <div id="config"> <input id="toggle" type="checkbox"> <label for="toggle">Use JavaScript</label> </div> 

我正在使用Date.now()提供着色器

它在着色器中產生不可預測的東西,特別是當你使用三角函數時,比如sin()cos()等。 原因是您將毫秒作為一個大整數傳遞。 這就是為什么你必須將它除以1000以使它們成為一個浮點數,即將毫秒轉換為秒。

所以,划分是一個適用。 另一個是使用THREE.Clock()及其.getDelta()方法。 看看代碼片段。

 const scene = new THREE.Scene() const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) const renderer = new THREE.WebGLRenderer() renderer.setSize( window.innerWidth, window.innerHeight ) camera.position.z = 0.5 document.body.appendChild( renderer.domElement ) const geo = new THREE.PlaneGeometry( 1, 1 ) const mat = new THREE.ShaderMaterial({ vertexShader: ` void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); } `, fragmentShader: ` uniform bool check; uniform float time; const float TAU = 6.2831; void main() { float fColor; fColor = ( sin( ( time * TAU ) ) + 1.0 ) / 2.0; gl_FragColor = vec4( 1.0, fColor, 1.0, 1.0 ); } `, uniforms: { "check": { value: false }, "time": { value: 1.0 }, }, }) const plane = new THREE.Mesh( geo, mat ) scene.add( plane ) var clock = new THREE.Clock(); var time = 0; const animate = function() { requestAnimationFrame( animate ) time += clock.getDelta(); plane.material.uniforms.time.value = time * 0.4; // make it 2.5 times slower renderer.render( scene, camera ) } animate() 
 body { margin: 0; } canvas { width: 100%; height: 100%; } #config { position: absolute; color: #fff; cursor: pointer; user-select: none; font: bold 1em/1.5 sans-serif; padding: 1em; } #config label, #config input { cursor: pointer; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.js"></script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM