Pytanie WebGL - Jak przekazywać niepodpisane wartości kolorów atrybutu vertex bajtów?


Moje wierzchołki składają się z tablicy o tej strukturze:

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

Przekazywanie pozycji wierzchołków nie stanowi problemu:

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

Ale nie mogę zrozumieć, jak mogę przekazać kolory do modułu cieniującego. Niestety, nie można używać liczb całkowitych w module cieniującym glsl, więc muszę używać pływaków. Jak mogę uzyskać wartość koloru niepodpisanego bajtu w wartości koloru ruchomego glsl? Próbowałem tego tak dla r, g i b osobno, ale kolory są pomieszane:

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);
} 

17
2017-08-26 08:17


pochodzenie


Pomijając twój problem, pomyślałeś o przekazaniu attribu jako 3-elementowego wektora? Oszczędza to kod i czas. - Nobody
@ Nikt nie jest tym, co pierwotnie zrobiłem. Przełączyłem się tylko na przekazywanie ich osobno, aby upewnić się, że tablica nie stanowiła problemu. - Markus


Odpowiedzi:


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

Twój krok powinien wynosić 16, a nie 15 i na pewno nie 4.

Ponadto każdy indywidualny kolor nie musi być osobnym atrybutem. Cztery bajty mogą być wejściami vec4. Aha, i twoje kolory powinny być znormalizowany, niepodpisane bajty. Oznacza to, że wartości w zakresie [0, 255] powinny zostać przeskalowane do [0, 1], gdy moduł cieniowania je pobierze. Dlatego właśnie chcesz:

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

Och, i atrybuty są nie materiały. Nie powinieneś ich tak nazywać.


27
2017-08-26 08:31



Dziękuję Ci. Nie zdałem sobie sprawy z tego, że jest to luka między jednym zestawem danych a drugim. Próbowałem wcześniej normalizować kolory, ale tym, czego mi brakowało, był typ UNSIGNED_BYTE. Materiał jest obiektem zawierającym moduł cieniujący, jego atrybuty i niektóre ustawienia materiałowe, więc uważam, że słusznie nazywa się to materiałem. Działa teraz. - Markus


GLfloat red=(GLfloat)red/255;

Mam nadzieję, że właśnie tego szukasz ^^


1
2017-08-26 08:20



Dzięki, ale już próbowałem. Po prostu przyciemnia punkty. gebackene-ente.at/nudelsalat/sonstiges/webgl_01.png  gebackene-ente.at/nudelsalat/sonstiges/webgl_02.png - Markus
To dziwne, ponieważ używam tego w C ++ i działa całkiem nieźle, czy jesteś pewien, że twój float ma wystarczającą precyzję? - Whiskas
Zobacz odpowiedź Nicola Bolasa na rozwiązanie. Mijałem gl.BYTE zamiast gl.UNISGNED_BYTE i mam zły krok. - Markus