3dexperiments/src/engine/mesh/material.js

95 lines
2.9 KiB
JavaScript

import Resource from '../resource'
class Texture {
static async fromFile (gl, file, flip, filtering, repeat) {
const image = await Resource.loadImage(file)
return Texture.createTexture2D(gl, image, flip, filtering, repeat)
}
static createTexture2D (gl, img, flip = false, filtering, repeat = gl.REPEAT) {
const tex = gl.createTexture()
gl.bindTexture(gl.TEXTURE_2D, tex)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip)
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, repeat)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, repeat)
if (filtering) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filtering)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filtering)
} else {
gl.generateMipmap(gl.TEXTURE_2D)
}
gl.bindTexture(gl.TEXTURE_2D, null)
const oTex = new Texture()
oTex.type = gl.TEXTURE_2D
oTex.id = tex
return oTex
}
static createTextureCubeMap (gl, img) {
if (!img || img.length !== 6) throw new Error('createTextureCubeMap() requires six images!')
const tex = gl.createTexture()
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex)
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false)
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[0])
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[1])
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[2])
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[3])
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[4])
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img[5])
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null)
const oTex = new Texture()
oTex.type = gl.TEXTURE_CUBE_MAP
oTex.id = tex
return oTex
}
}
class Material {
constructor (textures) {
this.textures = textures
}
async loadTextures (gl) {
if (this.textures) {
for (const ti in this.textures) {
const tex = this.textures[ti]
if (!(tex instanceof Texture)) {
const result = await Texture.fromFile(gl, tex, true)
this.textures[ti] = result
}
}
}
}
apply (gl, shader) {
// TODO: lighting related things
// Load textures
if (!this.textures || !this.textures.length) return
for (const i in this.textures) {
const tex = this.textures[i]
if (tex && tex instanceof Texture) {
gl.activeTexture(gl.TEXTURE0 + parseInt(i))
gl.bindTexture(tex.type, tex.id)
}
}
}
}
export { Texture, Material }