samplerCube в структуре вызывает GL_INVALID_OPERATION

Да, это возможно с использованием регулярных выражений

string = string.replace(/[^a-z0-9]+|\s+/gmi, " ");
2
задан user2331095 5 March 2019 в 06:10
поделиться

1 ответ

Ваша настоящая ошибка, скорее всего, где-то еще и связана с тем, что вы не правильно связали свои текстуры или искали неправильные места или что-то еще

ПРЕДУПРЕЖДЕНИЕ О RENDER: нет текстуры, привязанной к юниту 0

Вот рабочий пример с вашей однородной структурой

const fs = `
precision mediump float;

struct PhongMaterial {
  vec4 diffuse;
  sampler2D diffuseMap;

  vec4 specular;
  sampler2D specularMap;

  float shininess;

  samplerCube environmentMap; 
};
uniform PhongMaterial material;

void main() {
  vec4 diffuse  = texture2D(material.diffuseMap, gl_PointCoord.xy);
  vec4 specular = texture2D(material.specularMap, gl_PointCoord.xy);
  vec4 cube = textureCube(
     material.environmentMap, 
     vec3(gl_PointCoord.xy, gl_PointCoord.x * gl_PointCoord.y) * 2. - 1.);
     
  // use all 3 textures so we can see they were set
  vec4 diffuseOrSpecular = mix(diffuse, specular, step(0.25, gl_PointCoord.y));
  gl_FragColor = mix(diffuseOrSpecular, cube, step(0.5, gl_PointCoord.y));
}
`
const vs = `
void main() {
  gl_Position = vec4(0, 0, 0, 1);
  gl_PointSize = 128.0;
}
`;

const gl = document.querySelector('canvas').getContext('webgl');
const prg = twgl.createProgram(gl, [vs, fs]);
const diffuseLocation = gl.getUniformLocation(prg, 'material.diffuseMap');
const specularLocation = gl.getUniformLocation(prg, 'material.specularMap');
const envmapLocation = gl.getUniformLocation(prg, 'material.environmentMap');

const texDiffuse = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texDiffuse);
{
  const level = 0;
  const format = gl.RGBA;
  const width = 1;
  const height = 1;
  const type = gl.UNSIGNED_BYTE;
  const pixel = new Uint8Array([255, 255, 0, 255]);  // yellow
  gl.texImage2D(gl.TEXTURE_2D, level, format, width, height, 0, format, type, pixel);
}

const texSpecular = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texSpecular);
{
  const level = 0;
  const format = gl.RGBA;
  const width = 1;
  const height = 1;
  const type = gl.UNSIGNED_BYTE;
  const pixel = new Uint8Array([0, 0, 255, 255]);  // blue
  gl.texImage2D(gl.TEXTURE_2D, level, format, width, height, 0, format, type, pixel);
}

const texCube = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);
for (let i = 0; i < 6; ++i) {
  const level = 0;
  const format = gl.RGBA;
  const width = 1;
  const height = 1;
  const type = gl.UNSIGNED_BYTE;
  const pixel = new Uint8Array([(i & 1) * 255, (i & 2) * 255, (i & 4) * 255, 255]);
  gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, format, width, height, 0, format, type, pixel);
}

gl.useProgram(prg);

// put the yellow diffuse texture on texture unit 0
gl.activeTexture(gl.TEXTURE0 + 0);  
gl.bindTexture(gl.TEXTURE_2D, texDiffuse);

// use texture on texture unit 0
gl.uniform1i(diffuseLocation, 0);   

// put the blue specular texture on texture unit 1
gl.activeTexture(gl.TEXTURE0 + 1);  
gl.bindTexture(gl.TEXTURE_2D, texSpecular);

// tell the specular sampler to use texture unit 1
gl.uniform1i(specularLocation, 1);  

// put the cubemap on texture unit 2
gl.activeTexture(gl.TEXTURE0 + 2);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texCube);

// tell the cubemap sampler to use texture unit 2
gl.uniform1i(envmapLocation, 2);    

// draw one 128x128 pixel point
gl.drawArrays(gl.POINTS, 0, 1);  
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>

ПРИМЕЧАНИЕ: вы должны предоставить действительную текстуру для каждого сэмплера, который, как утверждает ваш шейдер, используется независимо от того, используется ли он на самом деле.

Чтобы выяснить, утверждает ли шейдер, что он используется, вызовите

gl.getUniformLocation(program, nameOfSamplerUniform);

Если он возвращает ненулевое значение, тогда AFAIK, как и WebGL, должен предоставить корректную текстуру для этого сэмплера.

Если вам это не нужно (из-за условий или чего-то еще), оставьте текстуру в 1 пиксель для текстуры 2D или 6 пикселов, по 1 пикселю на лицо для карт куба и прикрепите эту текстуру, когда вы не не нужна конкретная текстура.

Для этих случаев я обычно держу вокруг себя белую и / или черную текстуру. Например, скажем, у меня была математика, подобная

color = diffuseMapColor * diffuseColor + envMapColor;

Если я только хочу diffuseColor, тогда я могу установить diffuseMapColor на белый и envMapColor на черный, что эффективно

color = 1 * diffuseColor + 0;
[1128 ] Точно так же, как я хочу только diffuseMapColor, я могу установить diffuseColor на белый и envMapColor на черный и получить

color = diffuseMapColor * 1 + 0;

, и если я только хочу envMapColor, тогда установка diffuseColor на 0 будет Работа

color = diffuseMapColor * 0 + envMapColor;

такая же, как

color = 0 + envMapColor;

С другой стороны, большинство 3D движков будут генерировать разные шейдеры для этих случаев. Если карта окружения не используется, они генерируют шейдер, который не включает карту окружения. Это связано с тем, что обычно выполнение меньшего количества работы в шейдере происходит быстрее, чем большее, поэтому хороший 3D-движок генерирует шейдеры для каждого случая, когда это необходимо.

0
ответ дан gman 5 March 2019 в 06:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: