我有一个程序可以在许多不同的机器上运行在Windows和Linux上。它在我尝试的任何mac上都无法正常工作(OS X 10.9和10.10的几台不同机器)。该程序基本上只是在屏幕上呈现纹理四边形。纹理格式是浮点。
在Windows和Linux上看起来像这样:
这就是Mac上的样子:
因此,纹理数据会进入GPU,但却会出现奇怪的扭曲现象。纹理包装模式设置为钳位,您可以从图片中看到它的行为方式。
这是最小的绘图代码:
void Framebuffer::initialize()
{
Settings& settings = App::getSettings();
glGenTextures(1, &imageTextureId);
glBindTexture(GL_TEXTURE_2D, imageTextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
resampleProgramId = GLHelper::buildProgram(settings.framebuffer.resampleVertexShader, settings.framebuffer.resampleFragmentShader);
resampleTextureUniformId = glGetUniformLocation(resampleProgramId, "texture0");
resampleTextureWidthUniformId = glGetUniformLocation(resampleProgramId, "textureWidth");
resampleTextureHeightUniformId = glGetUniformLocation(resampleProgramId, "textureHeight");
resampleTexelWidthUniformId = glGetUniformLocation(resampleProgramId, "texelWidth");
resampleTexelHeightUniformId = glGetUniformLocation(resampleProgramId, "texelHeight");
const GLfloat vertexData[] = {
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
};
glGenBuffers(1, &vertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glBindVertexArray(0);
resize(settings.window.width, settings.window.height);
}
void Framebuffer::resize(int width, int height)
{
image.resize(width, height);
floatPixelData.resize(width * height * sizeof(float) * 4);
// reserve the texture memory on the device
glBindTexture(GL_TEXTURE_2D, imageTextureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_FLOAT, 0);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Framebuffer::render()
{
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
glUseProgram(resampleProgramId);
glUniform1i(resampleTextureUniformId, 0);
std::vector<Color>& imagePixelData = image.getPixelData();
// convert image data from Color to float array
for (int i = 0; i < (int)imagePixelData.size(); ++i)
{
int pixelIndex = i * 4;
floatPixelData[pixelIndex] = (float)imagePixelData[i].r;
floatPixelData[pixelIndex + 1] = (float)imagePixelData[i].g;
floatPixelData[pixelIndex + 2] = (float)imagePixelData[i].b;
floatPixelData[pixelIndex + 3] = (float)imagePixelData[i].a;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, imageTextureId);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, (GLsizei)imageWidth, (GLsizei)imageHeight, GL_RGBA, GL_FLOAT, &floatPixelData[0]);
glGenerateMipmap(GL_TEXTURE_2D);
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
GLHelper::checkError("Could not render the framebuffer");
}
为了测试,所有着色器都替换为最小颜色传递版本。
这是我尝试过没有运气的事情:
glGenerateMipmap
相同的代码在Windows和Linux上运行良好。
什么可能导致这种腐败只有Mac?
答案 0 :(得分:0)
我不确定这是否是您代码中唯一的问题(如果问题完全在您的代码中),但您的mipmap生成肯定存在问题。你有这样一系列的电话:
glBindTexture(GL_TEXTURE_2D, framebufferTextureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)windowWidth, (GLsizei)windowHeight, 0, GL_RGBA, GL_FLOAT, 0);
glGenerateMipmap(GL_TEXTURE_2D);
glGenerateMipmap()
不状态设置调用,指定在纹理填充数据后您希望生成mipmap。它的作用是从调用时纹理中的数据生成mipmap 。由于您刚刚在上一次调用中分配了纹理数据,并且纹理中还没有数据,glGenerateMipmap()
将不执行任何操作。
稍后,您使用此纹理:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, framebufferTextureId);
此时,即使采样模式设置为使用mipmap,纹理也没有mipmap。
您需要做的是在纹理填充数据后生成mipmap。您可以从glGenerateMipmap()
中的当前位置移除setWindowSize()
来电,例如将其移至上方第二个编码器片段下方:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, framebufferTextureId);
glGenerateMipmap(GL_TEXTURE_2D);
答案 1 :(得分:0)
好的,我终于明白了。顶点着色器内的属性位置在Mac OS X上切换。幸运的是,它在屏幕上呈现了一些东西,其中texcoords作为顶点位置,反之亦然。
我本可以使用glBindAttribLocation
来修复它,但我将着色器更新到版本330并使用了layout(location = 0)
属性。这也很好。