SimplexPerlin3D queryable in JS

Hi! I have a question about noise that I’m not sure is in scope for this forum but here goes.

I’d like to be able to query the exact SimplexPerlin3D noise algorithm shown here in NME (like noise.getValue(x,z)) and get the value at that point as a float between 0 and 1. I know that it’s not possible to query the material from the CPU, but is there a way to run the exact same algorithm in the CPU so I have some data structure with the same data just for querying? I’d like the performance of the shader in my rendering, but i’d also like to have some way to access the data about the resulting shape, and that doesn’t have to be super performant.
Specifically:

  1. how do I get the worldPos seed so my output is guaranteed to be the same?
  2. is there already a JS version of this algorithm? if not, would it be possible for me to write one or is there some obstacle I’m not considering?

Thanks!
-George

I use this but I don’t know if the algorithm is exactly the same josephg/noisejs: Javascript 2D Perlin & Simplex noise functions (github.com)

What about generating a procedural texture by using the SimplexPerlin3D block and applying this texture on your mesh instead? You could then read back this texture into the CPU to get the values you want.

I don’t think you will be able to do things the way you would like, worldPos is coming from the geometry (those are the vertices of your geometry), and is interpolated by your GPU for each pixel. You would need to implement this same interpolation and in exactly the same way to be sure to get the exact same values. Also, the computations are probably not done in 64 bits by the GPU, which is the precision you would have in javascript because a number is 64 bits. So you would end up with numbers being different just because of that.

yeah that could work! how do i read the texture back into the CPU?

Texture.readPixels will do it.

will check it out, thanks!

Ok so I’m trying to get pixel data out a procedural texture but all I’m getting is a bunch of 0s.

https://playground.babylonjs.com/#K9GLE6#50

What am I doing wrong? I’ve also tried reading the buffer into an array but it’s still all 0s

The texture is all black at start, try to get it a bit later:

https://playground.babylonjs.com/#K9GLE6#52

thanks!

i’m still hitting issues though:

https://playground.babylonjs.com/#L8IJYI#6

this is closer to what i actually want to do where i get a node material’s perlin values, but it’s just returning a (51, 51, 76, 255) on repeat.

do you know what i’m doing wrong?

Is it the right PG? You simply dump the buffer as in my PG above.

yeah it’s the right PG–my issue is the dumped buffer doesn’t appear to have any relation to the perlin noise. every pixel in the dumped buffer has rgba value (51, 51, 76, 255) whereas the noise has variation and is grayscale so 51,51,76 appears nowhere on it.

That’s because you are using the mesh position in your shader but when generating a procedural texture with nodeMaterial.createProceduralTexture(256) there’s no mesh rendering taking place. So mesh position is (0,0,0) during the texture generation.

Your node material will only work when applied to a mesh, not to create a procedural texture.

ahh okay that makes sense. how do i generate the procedural texture using the block as you suggest here?

What about generating a procedural texture by using the SimplexPerlin3D block and applying this texture on your mesh instead? You could then read back this texture into the CPU to get the values you want.

is there a way to pass the mesh in when i call createProceduralTexture?

No, you can’t pass the mesh in createProceduralTexture. You should create a procedure texture in the NME without using the mesh data, only screen.position, something like:

https://nme.babylonjs.com/#2EHBK9

@george Here is the demo how to calc perlin noise in texture (ProceduralTexture) and read values from it with readPixels and then use it in your JS code

https://playground.babylonjs.com/#3SSUAB#2

I hope it should help you

awesome massive thanks both! will give it a shot

@avin I’m getting this error from your code

Babylon.js v4.2.0 - WebGL2 - Parallel shader compilation
webRequest.ts:135 GET http://127.0.0.1:5500/textures/environment.dds 404 (Not Found)
./Misc/webRequest.ts.WebRequest.send @ webRequest.ts:135
retryLoop @ fileTools.ts:422
requestFile @ fileTools.ts:425
./Misc/fileTools.ts.FileTools.RequestFile @ fileTools.ts:461
./Misc/fileTools.ts.FileTools.LoadFile @ fileTools.ts:317
./Engines/thinEngine.ts.ThinEngine.loadFile @ thinEngine.ts:4281
./Engines/Extensions/engine.cubeTexture.ts.Engines_thinEngine__WEBPACK_IMPORTED_MODULE_1
.ThinEngine.createCubeTexture @ engine.cubeTexture.ts:286
./Misc/dds.ts.Engines_thinEngine__WEBPACK_IMPORTED_MODULE_8_.ThinEngine.createPrefilteredCubeTexture @ dds.ts:795
CubeTexture @ cubeTexture.ts:234
./Materials/Textures/cubeTexture.ts.CubeTexture.CreateFromPrefilteredData @ cubeTexture.ts:135
createScene @ proceduralNoise.js:29
(anonymous) @ proceduralNoise.js:232
proceduralNoise.js:91 Uncaught TypeError: noiseTexture.readPixels(…).then is not a function
at updateBoxesScale (proceduralNoise.js:91)
at Observer.callback (proceduralNoise.js:168)
at Observable…/Misc/observable.ts.Observable.notifyObservers (observable.ts:336)
at Scene…/scene.ts.Scene.render (scene.ts:4028)
at proceduralNoise.js:234
at Engine…/Engines/engine.ts.Engine._renderFrame (engine.ts:1187)
at Engine…/Engines/engine.ts.Engine._renderLoop (engine.ts:1205)

Texture.readPixels is a feature of babylon 5.0.
4.2 do not have this or there is another API for it

Texture.readPixels does exist in 4.2 but it does not return a Promise but the buffer directly.