whs.js icon indicating copy to clipboard operation
whs.js copied to clipboard

DataTextureModule

Open thejmazz opened this issue 7 years ago • 7 comments

I have a module for data textures from whs v1. I think either a DataTextureModule and TextureModule (see #213) can exist, or there can be one generic one. Here is the code for reference, I will make a v2 version soon. Also included some utils I used, but probably would not want those in the module. But maybe the data texture module could have some param options which are callback functions used to construct the texture. Something that gives you (x,y) of current position, and you return a [r, g, b, a], etc.

class DataTexture {
  static defaults = {
    data: undefined,
    width: DEFAULT_WIDTH,
    height: DEFAULT_HEIGHT,
    mapping: THREE.UVMapping,
    format: THREE.RGBFormat,
    wrapS: THREE.ClampToEdgeWrapping,
    wrapT: THREE.ClampToEdgeWrapping,
    minFilter: THREE.LinearFilter, // NearestFilter,
    magFilter: THREE.LinearFilter,
    type: THREE.UnsignedByteType,
    anisotropy: 1, // see renderer.getMaxAnisotropy()
    needsUpdate: false, // flag this when modifying texture (e.g. wrap, encoding)
    encoding: THREE.LinearEncoding, // sRGB, RGBE, RGBM, RGBD, LogLuv and Gamma
    onUpdate: () => {}
  }

  constructor (params = {}) {
    params = Object.assign({}, DataTexture.defaults, params)

    const dataTexture = new THREE.DataTexture(
      params.data,
      params.width, params.height,
      params.format,
      params.type,
      params.mapping,
      params.wrapS, params.wrapT,
      params.magFilter, params.minFilter,
      params.anisotropy
    )

    dataTexture.needsUpdate = true

    this.dataTexture = dataTexture

    return this.dataTexture
  }
}

// Utils
export const generateTextureArray = ({
  width = DEFAULT_WIDTH,
  height = DEFAULT_HEIGHT,
  format = 'rgba'
} = {}) => {
  if (typeof(width) !== 'number' || typeof(height) !== 'number') {
    throw new Error('width and height must be numbers')
  }

  if (typeof(format.length) !== 'number') {
    throw new Error('format.length must be a number')
  }

  return new Uint8Array(width * height * format.length)
}

export const dataMaker = ({
  width = DEFAULT_WIDTH,
  height = DEFAULT_HEIGHT,
  format = 'rgba',
  cb = function (i) {
    const val = Math.random() * 255
    const opacity = 1

    return [val, val, val, opacity]
  }
} = {}) => {
  const data = generateTextureArray({ width, height, format })

  for (let i = 0; i < data.length; i += format.length) {
    // cb receives i and should return an array of same length as format
    const datum = cb(i)

    for (let j = 0; j < format.length; j++) {
      data[i + j] = datum[j]
    }
  }

  return data
}

export default DataTexture
Version:
  • [x] v2.x.x
  • [ ] v1.x.x
Issue type:
  • [ ] Bug
  • [x] Proposal/Enhancement
  • [ ] Question

Tested on:
Desktop
  • [ ] Chrome
  • [ ] Chrome Canary
  • [ ] Chrome dev-channel
  • [ ] Firefox
  • [ ] Opera
  • [ ] Microsoft IE
  • [ ] Microsoft Edge
Android
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Opera
IOS
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Opera

thejmazz avatar Mar 22 '17 15:03 thejmazz

@thejmazz Is there a three.js example that explains DataTexture ? /ping @hirako2000

sasha240100 avatar Mar 22 '17 15:03 sasha240100

There is not much to explain - works the same as a normal texture except you construct the array buffer yourself (thats why need to set encoding, e.g. rgb vs rgba).

It can be used to create height map textures on CPU for example - or use Math.random() to make noise textures rather than using a shader and texture render target.

thejmazz avatar Mar 22 '17 15:03 thejmazz

  • Let's have generateTextureArray and dataMaker as static methods of DataTextureModules because it's better to keep module as one exported (default) class

  • defaults seems a bit complicated (yep, those are not required) but there we just copy three.js params. I think THREE.DataTexture should already handle undefined params.

  • module should not return this.dataTexture because this way it is not a module (will not work)

sasha240100 avatar Mar 22 '17 16:03 sasha240100

who creates/loads texture from (bytes?) arrays? What is the benefit?

hirako2000 avatar Mar 22 '17 19:03 hirako2000

@hirako2000 for cpu generative textures like this https://jmazz.me/codevember/2016/19/

source: https://github.com/thejmazz/threejs-starter-pack/blob/e60ad6f66a11f60c928b20ee70bd9ce869d5d502/src/index.js#L142

Useful to use CPU based random functions since there are some quirks with GPU implementations of PRNG. But for simplex/perlin noise, GPU is a lot faster (and then you need to use render target to texture).

You could also imagine storing a heightmap in a buffer like that.

Also just realized that demo could be a good one to port to WHS and for the demo for this module

@sasha240100 you can assign this issue to me

thejmazz avatar Mar 22 '17 19:03 thejmazz

@thejmazz I'd like to see an example with it. How about making a fractal? could you make a simple one?

image

sasha240100 avatar Mar 22 '17 19:03 sasha240100

https://medium.com/dailyjs/the-mandelwat-set-c3037204bf83

thejmazz avatar Mar 30 '17 19:03 thejmazz