17

I've been trying to find a clear answer, but it seems no one has clearly asked the question.

Can I use a 1D sampler and 1D texture in WebGL Chrome, Firefox, Safari, IE, etc?

EDIT

Understandably 1 is indeed a power of 2 (2^0=1) meaning you could effectively use a 2D sampler and texture using a height of 1 and a width of 256 or 512 etc. to replicate a 1D texture.

1D textures are not moot, they exist because they not only have a purpose, but are intended to translate into optimizations on the GPU itself (as opposed to a 2D texture). Remember that each parameter takes time to load onto the call stack, and almost all GPU programming is an art of optimizing every possible operation.

Compute shaders have frequent need for a single list of floats without the extra dimension, using a 1D texture and sampler provides the same clarity strong typing provides. Ie representing 1D data in a 1D structure, and representing 2D data in a 2D structure. It also removes extra operations required in index to row/column translations.

The questions wasn't if there is a good reason for them, it was are they supported yet.

In WebGL 1.0 based on OpenGL ES 2.0 as of 09/MAY/2014

  • There is currently no 1D texture or sampler support.
Adrian Seeley
  • 2,262
  • 2
  • 29
  • 37
  • I'd change "yet" to "WebGL 1.0" or something like that. WebGL 2 will most certainly have them. – Bartek Banachewicz May 08 '14 at 13:41
  • 1
    @BartekBanachewicz: Why would they add 1D textures? They are a completely redundant feature. They don't allow you to do anything you can't do with 2D textures. As the answers below suggest, you create a 2D texture with height 1, and have a 1D texture. In fact, if the API was created from scratch, having only 3D textures would be enough. 2D and 1D textures are just reduced cases of 3D textures. – Reto Koradi May 08 '14 at 15:20
  • 2
    @RetoKoradi: Without the [ARB_texture_non_power_of_two extension](https://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt) mipmapping and wrap modes other than GL_CLAMP_TO_EDGE are only supported for power-of-two textures, so there are legitimate use cases for 1D textures. – Jens Nolte May 08 '14 at 15:25
  • @JensNolte: Good point. I figure the next major WebGL version will be based on ES 3.0? That lifts those restrictions on NPOT textures that were in ES 2.0. – Reto Koradi May 08 '14 at 15:31
  • @RetoKoradi: Not entirely. Buffer textures are effectively fancy 1D textures that let you far exceed the storage of `GL_MAX_TEXTURE_SIZE`^2 (2D limit). But you cannot use them with anything other than 1D coords. – Andon M. Coleman May 08 '14 at 15:36
  • @JensNolte: I changed my mind on my last comment ;), but can't edit it anymore. 1 is a power of two, isn't it? It's 2^0. So as long as the width is a power of 2, I believe the "fake" 1D texture is POT. For example, a 512x1 texture would be a POT texture. – Reto Koradi May 08 '14 at 15:55
  • @RetoKoradi: Hm, the OpenGL ES 2.0 spec mentions "power of two" textures, but does not define the term. I think you are right. Also: Yes, the WebGL 2.0 draft is based on OpenGL ES 3.0, which has core NPOT support. – Jens Nolte May 09 '14 at 01:38
  • @BartekBanachewicz: WebGL 2 will NOT have them as they are not part of OpenGL ES 3.0 nor 3.1 on which WebGL 2 will be based – gman May 09 '14 at 18:43
  • @gman I am ready to open the 3.1 spec laying on my disk and humbly accept that I was wrong. – Bartek Banachewicz May 09 '14 at 18:49
  • "are intended to translate into optimizations on the GPU itself" Who says the driver/gpu can't still use specialized code/hardware for 2D textures that have one dimension set to one? – Tara Dec 05 '18 at 02:59

3 Answers3

11

Why do you need 1D textures? Just make a 2D texture N pixels wide and 1 pixel tall.

var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);

// 3x1 pixel 1d texture
var oneDTextureTexels = new Uint8Array([
    255,0,0,255, 
    0,255,0,255,
    0,0,255,255,
]);

var width = 3;
var height = 1;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
              oneDTextureTexels);

Either generatemips or set filtering so no mips are needed

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_W, gl.CLAMP_TO_EDGE);

Sample it with with 0.5 for y

uniform sampler2D u_texture;
varying float v_texcoord;

void main() {
  vec4 color = texture2D(u_texture, vec2(v_texcoord, 0.5));
  ...

Here's a sample using 1D textures. It uses the dot product of a typical lighting calculation to look up a value from a 1d ramp texture to shade the objects.

In direct answer to your question. There will be no 1D textures in WebGL because WebGL is based on OpenGL ES 2.0 and OpenGL ES 2.0 does not support 1D textures. Neither does OpenGL ES 3.0 nor 3.1. I'd be surprised if they didn't remove 1D textures completely when they merge OpenGL and OpenGL ES

gman
  • 100,619
  • 31
  • 269
  • 393
  • Hi gman. Is this a completely legitimate use of this pseudo 1d texture? If rendering stuff to buffers, does it make sense to make nx1 render target? – pailhead Dec 18 '14 at 03:46
  • I'm not sure what you're asking. If you need a nx1 render target make an nx1 render target. There's nothing wrong with an nx1 render target if that's what you need. – gman Dec 18 '14 at 03:56
  • i realized that we're limited to a certain width, so i guess at most 4096 or 8192 values? I guess i'm confused with what a real 1d texture does, and i'm trying to figure out when would one use this. I tried to walk a 2d texture (noise, or some pattern) with a linear index using mods and fracts to keep track of rows and columns. nx1 is easy to access, but can hold much less data? – pailhead Dec 18 '14 at 07:11
  • I'm not sure what you're trying to do. There's one example of a 1d texture linked in the answer. [Here's another](http://stackoverflow.com/questions/19695658/emulating-palette-based-graphics-in-webgl-v-s-canvas-2d/19719654#19719654). But anything you can do in 1d you can also do in 2d. Just change your math when addressing the 2d texture. – gman Dec 18 '14 at 09:16
  • Say i want to use textures to store a bunch of simulation stuff, tens of thousands of nodes. My experience comes from webgl, so i've never encountered 1d textures. A 1024x1024 target can hold a million nodes, but i need to do some logic to access it. A 1d texture is trivial to access, but it seems very limited. I guess i'm asking what is the purpose of a 1d texture, but i see now that these color shifts and gradients and stuff can be done with relatively few values and linear interpolation. – pailhead Dec 18 '14 at 16:39
  • 1
    Say i want to upload a bunch of random numbers to be used as seeds in some particle system or some such. Making nx1 texture puts a limitation on this, does the "real" 1d texture do the same? – pailhead Dec 18 '14 at 16:40
  • "real" 1d textures have the same size limits as 2d textures. upload your random texture in 2d, make your random function pick in 2d. I'm not understanding the problem. Ask a real question on SO so you can get a real answer instead of just tiny comments. – gman Dec 18 '14 at 22:30
7

WebGL 1.0 is based on OpenGL ES 2.0 which does not support 1D textures. The Texture Objects section in the WebGL specification reflects this by only having texImage2D and compressedTexImage2D methods.

You can use a texture with a height of one instead.

Jens Nolte
  • 509
  • 3
  • 15
0

As Jens Nolte said it's not supported in WebGL since it's based on OpenGL ES. You can use 2D textures with a unit width or height. For example (256 width and 1 height):

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, ColorMap.optimalIB);

Then in the sampler you can sample the texture by using any value for the height (since it doesn't matter).

C.d.
  • 9,932
  • 6
  • 41
  • 51