Странное поведение с унифицированными буферами OpenGL в OSX - PullRequest
0 голосов
/ 02 июля 2018

У меня странное поведение с одинаковыми буферами в моем хобби движке OpenGL4.1.

В Windows все работает нормально (как на графических процессорах Intel, так и на видеокартах Nvidia), но на моем MacBook (также на Intel) это не работает.

Итак, чтобы объяснить, что происходит в OSX: если я жестко закодирую все свои переменные Uniform Buffer в фактическом фрагментном коде шейдера, тогда я смогу отрендериться отлично, но если я верну их обратно в переменные - я ничего не получу.

Я посмотрел на состояние OpenGL с помощью apitrace, и все значения переменных идеальны, поэтому я немного смущен тем, что здесь происходит.

Я надеюсь, что это просто ошибка кода, а не какая-то основная проблема с драйверами.

Ниже приведен фрагмент кода шейдера, где, если я жестко закодирую все переменные DirectionLight, все будет работать нормально.

#version 410

struct DirectionalLightData
{
  vec4 Colour;
  vec3 Direction;
  float Intensity;
};

layout(std140) uniform ObjectBuffer
{
  mat4 Model;
};

layout(std140) uniform FrameBuffer
{
  mat4 Projection;
  mat4 View;  
  DirectionalLightData DirectionalLight;
  vec3 ViewPos;
};

uniform sampler2D PositionMap;
uniform sampler2D NormalMap;
uniform sampler2D AlbedoSpecMap;

layout(location = 0) in vec2 TexCoord;

out vec4 FinalColour;

float CalcDiffuseContribution(vec3 lightDir, vec3 normal)
{
  return max(dot(normal, -lightDir), 0.0f);
}

float CalcSpecularContribution(vec3 lightDir, vec3 viewDir, vec3 normal, float specularExponent)
{
  vec3 reflectDir = reflect(lightDir, normal);
  vec3 halfwayDir = normalize(lightDir + viewDir);
  return pow(max(dot(normal, halfwayDir), 0.0f), specularExponent);
}


float CalcDirectionLightFactor(vec3 viewDir, vec3 lightDir, vec3 normal)
{
  float diffuseFactor = CalcDiffuseContribution(lightDir, normal);
  float specularFactor = CalcSpecularContribution(normal, viewDir, normal, 1.0f);
  return diffuseFactor * specularFactor;
}


void main()
{
  vec3 position = texture(PositionMap, TexCoord).rgb;
  vec3 normal = texture(NormalMap, TexCoord).rgb;
  vec3 albedo = texture(AlbedoSpecMap, TexCoord).rgb;

  vec3 viewDir = normalize(ViewPos - position);
  float directionLightFactor = CalcDirectionLightFactor(viewDir, DirectionalLight.Direction, normal) * DirectionalLight.Intensity;

  FinalColour.rgb = albedo * directionLightFactor * DirectionalLight.Colour.rgb;
  FinalColour.a = 1.0f * DirectionalLight.Colour.a;
}

Вот порядок, в котором я обновляю и связываю UBO (я извлек их из apitrace, так как здесь слишком много кода, чтобы скопировать вставку):

glGetActiveUniformBlockName(5, 0, 255, NULL, FrameBuffer);
glGetUniformBlockIndex(5, FrameBuffer) = 0;
glGetActiveUniformBlockName(5, 1, 255, NULL, ObjectBuffer);
glGetUniformBlockIndex(5, ObjectBuffer) = 1;

glBindBuffer(GL_UNIFORM_BUFFER, 1);
glMapBufferRange(GL_UNIFORM_BUFFER, 0, 172,GL_MAP_WRITE_BIT);
memcpy(0x10b9f8000, [binary data, size = 172 bytes], 172);
glUnmapBuffer(GL_UNIFORM_BUFFER);

glBindBufferBase(GL_UNIFORM_BUFFER, 0, 2);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, 1);

glBindBuffer(GL_UNIFORM_BUFFER, 2);
glMapBufferRange(GL_UNIFORM_BUFFER, 0, 64, GL_MAP_WRITE_BIT);
memcpy(0x10b9f9000, [binary data, size = 64 bytes], 64);
glUnmapBuffer(GL_UNIFORM_BUFFER);

glUniformBlockBinding(5, 1, 0);
glUniformBlockBinding(5, 0, 1);

glDrawArrays(GL_TRIANGLES, 0, 6);

Обратите внимание, что UBO FrameBuffer имеет идентификатор 1, а UBO ObjectBuffer имеет идентификатор 2

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

После нескольких дней копания я, кажется, нашел проблему.

Я не вызывал glBindBufferBase () после привязки другой шейдерной программы.

Такая глупая ошибка причинила мне столько горя.

Спасибо всем за помощь.

0 голосов
/ 02 июля 2018

Я думаю, что когда вы используете макет std140, ваши элементы данных должны быть выровнены по байту, чтобы вы не могли смешивать vec4 и vec3 или float, сохраняя все переменные mat4 и vec4, иначе не используйте компоновку std140 и на стороне приложения рассчитайте выравнивание ubo и смещения ваших переменных на UBO и установить значения. Смотрите использование GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. В качестве эксперимента измените все переменные на mat4 и vec4 и увидите, что ваша проблема должна исчезнуть.

Если вы не использовали макет std140 для блока, вам потребуется запросить смещение в байтах для каждой униформы в блоке. Спецификация OpenGL объясняет хранение каждого из основных типов, но не выравнивание между типами. Члены структуры, как и обычные формы, имеют отдельное смещение, которое необходимо запрашивать индивидуально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...