Я должен использовать расширения Haskell GHC или нет?

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

ПРЕДУПРЕЖДЕНИЕ О 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-движок генерирует шейдеры для каждого случая, когда это необходимо.

78
задан sastanin 29 April 2009 в 10:39
поделиться

3 ответа

Есть некоторые расширения GHC, без которых слишком хорошо жить. Среди моих любимых

  • классы многопараметрических типов
  • переменные типа Scoped
  • типы более высокого ранга
  • Обобщенные алгебраические типы данных (GADT)

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

Некоторые расширения GHC очень умозрительны и экспериментальны, и вы можете использовать их с осторожностью. Хороший способ определить стабильное и доверенное расширение - посмотреть, планируется ли его включить в Haskell Prime , который, как ожидается, станет преемником Haskell 98.

I второй Дон Стюарт ' Предполагается, что каждое расширение должно быть помечено с использованием прагмы LANGUAGE в исходном файле. Не включать расширения с использованием параметров командной строки.

70
ответ дан 24 November 2019 в 10:35
поделиться

Да, используйте соответствующие расширения.

Но обязательно включите их намеренно - только когда вы решите, что они вам нужны. Сделайте это для каждого модуля через {- # LANGUAGE Rank2Types # -} (например).

51
ответ дан 24 November 2019 в 10:35
поделиться

Вообще говоря, люди используют расширения GHC довольно интенсивно, потому что они очень полезны, а Haskell 98 довольно стар. Как только появится более современный стандарт, люди могут приложить больше усилий, чтобы придерживаться его.

Статус предложений по следующему стандарту можно найти здесь .

19
ответ дан 24 November 2019 в 10:35
поделиться
Другие вопросы по тегам:

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