Войти
ПрограммированиеФорумГрафика

GLSL WEBGL getProgramParameter Получил а чем заполнить?

#0
0:33, 2 авг. 2020

Всем привет.
Из программы я получаю все uniform'ы

class Uniforms {

    getUniforms (program) {
        let n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
        for ( let i = 0; i < n; ++ i ) {
          let info = gl.getActiveUniform( program, i );
          let type = info.type;
          let name = info.name;
          let setUniform = this.getSetterUniform(type);
         this[name] = setUniform;
        }
        return this;
    }
    
    getSetterUniform (type) {
        switch (type) {
          case 5126: return (u,v) => { gl.uniform1f(u,v); };
          case 35678: return (u,v) => { gl.uniform1i(u,0); };
          case 35665: return (u,v) => { gl.uniform3fv(u,v); };
          case 35676: return (u,v) => { gl.uniformMatrix4fv(u,false,v); };
      }
    }

}

Отлично получил.

При отрисовке мне нужно пройтись по полученным юниформам и передать в них значения.

И вот тут у меня сложности )).

Есть класс Камеры, у него свои юниформы (вид,проекция)
Есть класс Геометрии, у него свои юниформы (матрица модели, матрица нормалей)
Есть класс Материала у него свои юниформы (цвет...)
Есть класс Освещения у него свои юниформы

И вот дело дошло до отрисовки, я получил все активные юниформы, прохлажусь по ним, например 4 юниформы (с освещением больше получается):
uMatrixModel
uBaseColor
uCameraView
UCameraProj

Для каждой мне нужно передать значение. А от куда? Из камеры? Из Геометрии?

Сейчас, мне кажется я делаю что-то очень страшное, объединяю все юниформы в один массив, потом перебираю активные юниформы и проставляю им значение. А посещение может быть не одно по все источники перебираю отдельно:

draw (scene,camera) {
    
    scene.mesh.forEach((mesh) => {

        gl.useProgram(mesh.shader.program);  

        let allUniforms = {...mesh.geometry.uniforms, ...mesh.material.uniforms, ...camera.uniforms};
        for (let uniform in mesh.shader.uniforms) {
            let t = allUniforms[uniform];
            if (t == undefined) continue;
            let u = gl.getUniformLocation(mesh.shader.program, uniform);
            let v = allUniforms[uniform].get();
            if (t instanceof Texture) {
                gl.bindTexture(gl.TEXTURE_2D, v);
            }
            mesh.shader.uniforms[uniform](u,v);
        }

  scene.light.forEach(function(item){
    for (let uniform in item.uniforms) {
      let u = gl.getUniformLocation(mesh.shader.program, uniform);
      let v = item.uniforms[uniform];
      if (u) mesh.shader.uniforms[uniform](u,v);
    }
  });

        gl.bindVertexArray(mesh.vao);
        gl.drawElements(gl.TRIANGLES, mesh.geometry.indices.length, gl.UNSIGNED_SHORT, 0);  
        gl.bindVertexArray(null);
        gl.bindTexture(gl.TEXTURE_2D, null);
    });

}

Все работает )) Но мне кажется что это какой-то костыль. Или так и нужно? ))
Я пытался посмотреть как делает движок threejs, что-то похожее есть, но разобраться до конца не смог. ((

Может кто сможет объяснить, как вообще это лучше реализовать.
Надеюсь изложил понятно свой вопрос.


#1
10:57, 2 авг. 2020

Если ты хранишь список юниформов, то почему сразу location не записываешь? Каждый кадр вызывать glGetUniformLocation это так себе.

#2
11:15, 2 авг. 2020

Dimich
Спасибо. А я думаю что это у меня 2000 объектов и 15-20 fps. Видимо дело в этом. Переделаю.

Можете что-то подсказать по вопросу темы? Верно ли я делаю что храню в каждом объекте свои юниформы, потом объединяю их чтобы получить их? Или после увиденного кто-нибудь захочет выколоть глаза? ))

#3
11:33, 2 авг. 2020

SkyWeb
> А я думаю что это у меня 2000 объектов и 15-20 fps. Видимо дело в этом.
Это вряд ли, профайлером смотрел?

По теме, обычно юниформами рулит какой-нибудь менеджер материалов или его заменяющий. Всё-таки работа с шейдерами, по хорошему, не должна торчать наружу движка или что там у тебя. А внутри должен быть быть какой-то свой стандарт, чтоб менеджер точно знал какие данные брать у объектов, и как их пихать в шейдер. Но это вкусовщина, кто-нибудь точно скажет, что я несу хрень.

#4
11:37, 2 авг. 2020

Dimich
Смотрел, но там ничего для меня не понятно. )) В поисках нормальной информации как профилировать webgl. Нашел видео от яндекса, не успел посмотреть.

ПрограммированиеФорумГрафика