Jump to content

Shader Texture Arrays


Pryme8
 Share

Recommended Posts

Is this the correct way to construct an array to pass to my shader that I can then reference and use in the fragment shader?
 

var textureBank = new Array();
				var textureLocations = [
				//ZONE 1:
					"./textures/Beach_Rocks.jpg",//BASE
					"./textures/Sand_2.jpg",//Angle Zone 1
					"./textures/Sand_2.jpg",//Angle Zone 2
					"./textures/Sand_1.jpg",//Angle Zone 3
					"./textures/Rocks_2.jpg",//Angle Zone 4
				];
				
				$.each(textureLocations, function(i,e){
					textureBank.push(new BABYLON.Texture(e, scene));
					textureBank[i].wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
					textureBank[i].wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
					});
					
					
				teriableBasic = new BABYLON.ShaderMaterial("teriableBasic", scene, {
                    vertex: "teriableBasic",
                    fragment: "teriableBasic",
                	},
                    {
                        attributes: ["position", "normal", "uv"],
                        uniforms: ["world", "worldView", "worldViewProjection", "view", "projection"]
                    });
				
				teriableBasic.setTexture("textureBank", textureBank);

Now how do I reference and use it in the shader?
 "uniform sampler2D textureBank;\r\n"+

is the line im using, but before I even run it Im like 90% sure it will drop and error, because textureBank is and array...
Do I have to set texture to each of those textures in my array to sample from them?

Link to comment
Share on other sites

i will do some tests soon too, but i think, it runs much faster in the overall app, if you compile it first and then use BABYLON.USEShaderLib (..././) (i forgot the function)

https://doc.babylonjs.com/tutorials/How_to_create_a_material_for_materialsLibrary

http://www.babylonjs.com/Demos/CUSTOMSHADER/cellShading.js

Im not sure, also not tested, but i think if you call your shader inside the app, this way, you kind of creating a call stack, also blocking default shaders because of asynch in js. ...only a theory

Link to comment
Share on other sites

this sounds like what I needed, thank you so much!

If I get a chance today, I should be able to finish the texture sampling part of my advance terrain shader, from there it will be extending it to handle normal maps as well.

You can see the basic shader in effect on my TERIABLE Demo, Im trying to get a better version of the demo together today with the ability to walk around on the land your generating, new filters like terracing and smoothing, and fixes to the masking and absolute value systems.

If things go according to plan you will be able to create and infinite terrain to walk around that is complete procedural and you will have complete control over its generation. 

I wanted to have the sampled textures done for it.

Link to comment
Share on other sites

GL_TEXTURE_2D_ARRAY

" Images in this texture all are 2-dimensional. However, it contains multiple sets of 2-dimensional images, all within one texture. The array length is part of the texture's size."

Does this mean it treats and array of separate images like a single buffer?

Link to comment
Share on other sites

Correct.

Babylon.js supports texture arrays. You just need to call effect.setTextureArray: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.effect.ts#L383

Or if you are using a ShaderMaterial: material.setTextureArray: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.shaderMaterial.ts#L57

Link to comment
Share on other sites

Ok Im a little lost, I need to figure out how to pack a crap ton of textures into a single shader right now I am doing this:
 

teriableBasic.setTexture("z1b[0]", textureBank[0]);
		 		teriableBasic.setTexture("z1b[1]", textureBank[1]);
				teriableBasic.setTexture("z1b[2]", textureBank[2]);
				teriableBasic.setTexture("z1a0[0]", textureBank[3]);
		 		teriableBasic.setTexture("z1a0[1]", textureBank[4]);
				teriableBasic.setTexture("z1a0[2]", textureBank[5]);
				teriableBasic.setTexture("z1a1[0]", textureBank[6]);
		 		teriableBasic.setTexture("z1a1[1]", textureBank[7]);
				teriableBasic.setTexture("z1a1[2]", textureBank[8]);
				teriableBasic.setTexture("z1a2[0]", textureBank[9]);
		 		teriableBasic.setTexture("z1a2[1]", textureBank[10]);
				teriableBasic.setTexture("z1a2[2]", textureBank[11]);
				teriableBasic.setTexture("z1a3[0]", textureBank[12]);
		 		teriableBasic.setTexture("z1a3[1]", textureBank[13]);
				teriableBasic.setTexture("z1a3[2]", textureBank[14]);
				
				teriableBasic.setTexture("z2b[0]", textureBank[15]);
		 		teriableBasic.setTexture("z2b[1]", textureBank[16]);
				teriableBasic.setTexture("z2b[2]", textureBank[17]);
				teriableBasic.setTexture("z2a0[0]", textureBank[18]);
		 		teriableBasic.setTexture("z2a0[1]", textureBank[19]);
				teriableBasic.setTexture("z2a0[2]", textureBank[20]);
				teriableBasic.setTexture("z2a1[0]", textureBank[21]);
		 		teriableBasic.setTexture("z2a1[1]", textureBank[22]);
				teriableBasic.setTexture("z2a1[2]", textureBank[23]);
				teriableBasic.setTexture("z2a2[0]", textureBank[24]);
		 		teriableBasic.setTexture("z2a2[1]", textureBank[25]);
				teriableBasic.setTexture("z2a2[2]", textureBank[26]);
				teriableBasic.setTexture("z2a3[0]", textureBank[27]);
		 		teriableBasic.setTexture("z2a3[1]", textureBank[28]);
				teriableBasic.setTexture("z2a3[2]", textureBank[29]);

which exceeds a limit of 16, is there a way to get all of this to the shader easier?
 

"// Refs\r\n"+
"uniform sampler2D z1b[3];\r\n"+
"uniform sampler2D z1a0[3];\r\n"+
"uniform sampler2D z1a1[3];\r\n"+
"uniform sampler2D z1a2[3];\r\n"+
"uniform sampler2D z1a3[3];\r\n"+
"uniform sampler2D z2b[3];\r\n"+
"uniform sampler2D z2a0[3];\r\n"+
"uniform sampler2D z2a1[3];\r\n"+
"uniform sampler2D z2a2[3];\r\n"+
"uniform sampler2D z2a3[3];\r\n"+	

I think thats what :

public setTextureArray(channel: string, textures: BaseTexture[]): void {
            if (this._samplers.indexOf(channel + "Ex") === -1) {
                var initialPos = this._samplers.indexOf(channel);
                for (var index = 1; index < textures.length; index++) {
                    this._samplers.splice(initialPos + index, 0, channel + "Ex");
                }
}
 

is for, but I dont quite understand how to implement it.


And then how would I pass a x and y size with each texture so that I can reference it later to scale each one independently?

Link to comment
Share on other sites

I was doing that this morning ^_^
I figured Im gonna limit Zones to 4 sets of 4 atlases that makes 16 textures and should bind fine.

 

also thanks to your help and experimenting I was able to pass arrays easy, and it seems like the setTextureArray function does not work but just setting the texture to ('textureBank', textureBank), when my initial bank is already an array it automatically sets it i think, as long as in the glsl part of the script the const sampler2D textureBank[x]; has the correct x value set.

Link to comment
Share on other sites

  • 7 months later...
On 8/16/2016 at 6:26 AM, Deltakosh said:

Correct.

Babylon.js supports texture arrays. You just need to call effect.setTextureArray: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.effect.ts#L383

Or if you are using a ShaderMaterial: material.setTextureArray: https://github.com/BabylonJS/Babylon.js/blob/master/src/Materials/babylon.shaderMaterial.ts#L57

Does this implementation of texture array count against the MAX_TEXTURE_IMAGE_UNITS  or is using the MAX_COMBINED_TEXTURE_IMAGE_UNITS you gen from glsl texture array... i think is was something like uniform 'sampler2DArray varname' as apposed to our babylon uses 'uniform sampler2D varname[x]'

Link to comment
Share on other sites

On 8/17/2016 at 7:58 AM, Pryme8 said:

I was doing that this morning ^_^
I figured Im gonna limit Zones to 4 sets of 4 atlases that makes 16 textures and should bind fine.

 

also thanks to your help and experimenting I was able to pass arrays easy, and it seems like the setTextureArray function does not work but just setting the texture to ('textureBank', textureBank), when my initial bank is already an array it automatically sets it i think, as long as in the glsl part of the script the const sampler2D textureBank[x]; has the correct x value set.

Yo @Pryme8 Did you ever get this going with more than the 16 texture limit ???

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...