WebGL - How to pass unsigned byte vertex attribute colour values?

13,611

Solution 1

gl.vertexAttribPointer(this.material.aVertexPosition, 3, gl.FLOAT, false, 4, 0);
gl.vertexAttribPointer(this.material.aR, 1, gl.BYTE, false, 15, 12);

Your stride should be 16, not 15 and certainly not 4.

Also, each individual color does not need to be a separate attribute. The four bytes can be a vec4 input. Oh, and your colors should be normalized, unsigned bytes. That is, the values on the range [0, 255] should be scaled to [0, 1] when the shader gets them. Therefore, what you want is:

gl.vertexAttribPointer(this.material.aVertexPosition, 3, gl.FLOAT, false, 16, 0);
gl.vertexAttribPointer(this.material.color, 4, gl.UNSIGNED_BYTE, true, 16, 12);

Oh, and attributes are not materials. You shouldn't call them that.

Solution 2

GLfloat red=(GLfloat)red/255;

I hope that's what you are looking for ^^

Share:
13,611

Related videos on Youtube

Markus
Author by

Markus

Updated on June 04, 2022

Comments

  • Markus
    Markus almost 2 years

    My vertices are made up of an array with this structure:

    [     Position      ][        colour        ]
    [float][float][float][byte][byte][byte][byte]
    

    Passing the vertex position is no problem:

    gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
    gl.vertexAttribPointer(this.material.aVertexPosition, 3, gl.FLOAT, false, 4, 0);
    

    But I can't figure out how I can pass the colours to the shader. Unfortunately, it's not possible to use integers inside the glsl shader so I have to use floats. How can I get my unsigned byte colour value into the glsl float colour value? I tried it like this for r, g and b sepperately but the colours are all messed up:

    gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
    gl.vertexAttribPointer(this.material.aR, 1, gl.BYTE, false, 15, 12);
    

    Vertex Shader (colouredPoint.vs)

    precision highp float;
    
    attribute vec3 aVertexPosition;
    attribute float aR;
    attribute float aG;
    attribute float aB;
    
    uniform mat4 world;
    uniform mat4 view;
    uniform mat4 proj;
    
    varying vec3 vVertexColour;
    
    void main(void){
        gl_PointSize = 4.0;  
        gl_Position = proj * view * world * vec4(aVertexPosition, 1.0);
        vVertexColour = vec3(aR, aG, aB);
    } 
    

    Pixel Shader (colouredPoint.fs)

    precision highp float;
    
    varying vec3 vVertexColour;
    
    void main(void){
        gl_FragColor = vec4(vVertexColour, 1);
    } 
    
  • Markus
    Markus over 12 years
  • Markus
    Markus over 12 years
    Thank you. I missunderstood the stride to be the gap between one set of data to the next. I tried to normalize colours before but what I was missing was the UNSIGNED_BYTE type. Material is an object that contains the shader, its attributes and some material settings so I think its just right to call it material. Works now.
  • Whiskas
    Whiskas over 12 years
    That's weird because I'm using this in C++ and it works pretty well, are you sure that your float have enough precision ?
  • Markus
    Markus over 12 years
    See Nicol Bolas answer for the solution. I was passing gl.BYTE instead of gl.UNISGNED_BYTE and I've got the stride wrong.