Last active
November 21, 2021 17:59
-
-
Save lucasdamianjohnson/e7190f7cf9cf49e760e6eb975f3fa85f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Helper class to use a 2D texture array in Babylon.Js | |
*/ | |
export class 2DTextureArrayMaterial { | |
material: BABYLON.ShaderMaterial; | |
context: CanvasRenderingContext2D; | |
scene: BABYLON.Scene; | |
constructor() {} | |
setScene(scene: BABYLON.Scene) { | |
this.scene = scene; | |
} | |
/**# Set Up Image Creation | |
* --- | |
* Creates the html canvas and gl 2d context for getting the image data. | |
*/ | |
setUpImageCreation() { | |
const TwoDcanvas = document.createElement("canvas"); | |
const context = TwoDcanvas.getContext("2d"); | |
if (!context) { | |
throw new Error("Context did not load for texture creation."); | |
} | |
this.context = context; | |
} | |
/**# Create Material Texture | |
* --- | |
* Create a RawTexture2DArray from a series of images. | |
* Just a supply the path to each image. | |
* Each image must be the same size. | |
*/ | |
async createMaterialTexture( | |
images: string[], | |
width: number = 16, | |
height: number = 16 | |
) { | |
const resolvedImages: Uint8ClampedArray[] = []; | |
for (const image of images) { | |
const data = await this._loadImages(image, width, height); | |
resolvedImages.push(data); | |
} | |
const combinedImages = this._combineImageData(resolvedImages); | |
const _2DTextureArray = new BABYLON.RawTexture2DArray( | |
combinedImages, | |
width, | |
height, | |
images.length, | |
BABYLON.Engine.TEXTUREFORMAT_RGBA, | |
this.scene, | |
false, | |
false, | |
BABYLON.Texture.NEAREST_SAMPLINGMODE | |
); | |
return _2DTextureArray; | |
} | |
_loadImages( | |
imgPath: string, | |
width: number, | |
height: number | |
): Promise<Uint8ClampedArray> { | |
const self = this; | |
const prom: Promise<Uint8ClampedArray> = new Promise((resolve) => { | |
const loadedImage = new Image(); | |
loadedImage.src = imgPath; | |
loadedImage.onload = function () { | |
self.context.drawImage(loadedImage, 0, 0, width, height); | |
const imgData = self.context.getImageData(0, 0, width, height); | |
resolve(imgData.data); | |
}; | |
}); | |
return prom; | |
} | |
_combineImageData(arrays: Uint8ClampedArray[]) { | |
let totalLength = 0; | |
for (const array of arrays) { | |
totalLength += array.length; | |
} | |
const combinedImagedata = new Uint8ClampedArray(totalLength); | |
combinedImagedata.set(arrays[0]); | |
for (let i = 1; i < arrays.length; i++) { | |
const array = arrays[i]; | |
const previousArrayIndex = arrays[i - 1].length; | |
combinedImagedata.set(array, previousArrayIndex); | |
} | |
return combinedImagedata; | |
} | |
/** # Get Material | |
*--- | |
* Get the shader material. The shader is pretty basic. It also takes into account fog set by Babylon. | |
*/ | |
getMaterial( | |
texture: BABYLON.RawTexture2DArray | |
): BABYLON.ShaderMaterial { | |
BABYLON.Effect.ShadersStore["aVertexShader"] = ` | |
precision highp float; | |
// Attributes | |
attribute vec3 position; | |
attribute vec3 normal; | |
attribute vec3 myuvs; | |
attribute vec4 colors; | |
// Uniforms | |
uniform mat4 worldViewProjection; | |
uniform mat4 world; | |
uniform mat4 view; | |
uniform mat4 viewProjection; | |
varying vec2 vUV2; | |
// Varying | |
varying vec3 vUV; | |
varying vec3 vNormal; | |
varying vec4 vColors; | |
varying float fFogDistance; | |
void main(void) { | |
vec4 worldPosition = world * vec4(position, 1.0); | |
fFogDistance = (view * worldPosition).z; | |
gl_Position = worldViewProjection * vec4(position, 1.0); | |
vUV = myuvs; | |
vColors = colors; | |
vNormal = normal; | |
} | |
`; | |
BABYLON.Effect.ShadersStore["aFragmentShader"] = ` | |
#define FOGMODE_NONE 0. | |
#define FOGMODE_EXP 1. | |
#define FOGMODE_EXP2 2. | |
#define FOGMODE_LINEAR 3. | |
#define E 2.71828 | |
precision highp float; | |
precision highp sampler2DArray; | |
uniform vec4 vFogInfos; | |
uniform vec3 vFogColor; | |
varying float fFogDistance; | |
varying vec3 vUV; | |
varying vec4 vColors; | |
varying vec3 vNormal; | |
uniform sampler2DArray arrayTex; | |
uniform int layerIndex; | |
float CalcFogFactor() | |
{ | |
float fogCoeff = 1.0; | |
float fogStart = vFogInfos.y; | |
float fogEnd = vFogInfos.z; | |
float fogDensity = vFogInfos.w; | |
if (FOGMODE_LINEAR == vFogInfos.x) | |
{ | |
fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart); | |
} | |
else if (FOGMODE_EXP == vFogInfos.x) | |
{ | |
fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity); | |
} | |
else if (FOGMODE_EXP2 == vFogInfos.x) | |
{ | |
fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity); | |
} | |
return clamp(fogCoeff, 0.0, 1.0); | |
} | |
void main(void) { | |
vec4 lightIntensity = vec4(.5,.5,.5,1); | |
vec4 rgb = texture(arrayTex, vec3(vUV)) ; | |
//mix with supplied vertex colors | |
vec4 mixVertex = mix(rgb, vColors , 1.0); | |
//apply to texture color | |
vec4 newBase = rgb * mixVertex; | |
vec4 mixLight = newBase * lightIntensity; | |
float fog = CalcFogFactor(); | |
vec3 finalColor = fog * mixLight.rgb + (1.0 - fog) * vFogColor; | |
//gl_FragColor = vec4(finalColor.rgb,mixLight.w ); | |
gl_FragColor = vec4(finalColor.rgb , mixLight.w ); | |
} | |
`; | |
const shaderMaterial = new BABYLON.ShaderMaterial("a", this.scene, "a", { | |
attributes: ["position", "normal", "myuvs", "colors"], | |
uniforms: [ | |
"world","view","viewProjection", | |
"worldView", | |
"worldViewProjection", | |
"vFogInfos", "vFogColor", | |
"projection", | |
"layerIndex", | |
"arrayTex", | |
], | |
needAlphaBlending: true, | |
}); | |
shaderMaterial.fogEnabled = true; | |
shaderMaterial.setTexture("arrayTex", texture); | |
shaderMaterial.needDepthPrePass = true; | |
shaderMaterial.separateCullingPass = true; | |
shaderMaterial.onBind = (mesh) => { | |
var effect = shaderMaterial.getEffect(); | |
if(!effect)return; | |
effect.setFloat4("vFogInfos", this.scene.fogMode, this.scene.fogStart, this.scene.fogEnd, this.scene.fogDensity); | |
effect.setColor3("vFogColor", this.scene.fogColor); | |
} | |
this.material = shaderMaterial; | |
return this.material; | |
} | |
} |
This is broken sir
Try This First:
https://www.babylonjs-playground.com/#SSMQRA#2
You probably can't just plug and play the script. You may need to adjust it.
Ok
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is broken sir