为什么 OpenGL 位置(聚光)光会与 MacOS 上的非位置光发生干扰

问题描述 投票:0回答:1

我有一个旧版 OpenGL 固定管道应用程序,已从 Windows(32 位)移植到 MacOS 64 位。

问题是,如果我有一个带有非位置光的场景,一切都会很好。如果我添加位置聚光灯,两个灯光会相互作用,并且会得到不正确的结果。

这是“正常”情况:聚光灯在右侧:

Spotlight to right

在这里,我将聚光灯向下移动(Y = 1)。注意立方体上的黑色区域。这是不正确

Spotlight right, but low

现在,我通过注释掉聚光灯(灯 6)的“makeALight”调用来关闭聚光灯。现在,立方体被均匀照亮。

Spotlight off! 这是我用来生成灯光的测试代码。您需要使用brew 安装glfw 来构建它。

#define GL_SILENCE_DEPRECATION 1 #include <OpenGL/gl.h> #include <OpenGL/glu.h> #include <GLFW/glfw3.h> #include <iostream> #define STB_IMAGE_IMPLEMENTATION // Function to generate a checkerboard texture GLuint generateCheckerboardTexture(int width, int height) { int checkerSize = 8; // Size of each square in the checkerboard GLubyte *data = new GLubyte[width * height * 3]; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int checkerX = x / checkerSize; int checkerY = y / checkerSize; bool isWhite = (checkerX + checkerY) % 2 == 0; GLubyte color = isWhite ? 255 : 0; data[(y * width + x) * 3 + 0] = color; // Red data[(y * width + x) * 3 + 1] = color; // Green data[(y * width + x) * 3 + 2] = color; // Blue } } GLuint textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); // Set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Upload the texture data glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); // Clean up delete[] data; return textureID; } // Function to create and configure a light source void makeALight(int index, bool positional, GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat dirX, GLfloat dirY, GLfloat dirZ, GLfloat ambR, GLfloat ambG, GLfloat ambB, GLfloat ambA, GLfloat diffR, GLfloat diffG, GLfloat diffB, GLfloat diffA, GLfloat specR, GLfloat specG, GLfloat specB, GLfloat specA, float beamWidth, float constantA, float linearA, float quadA) { GLenum glLightIndex = GL_LIGHT0 + index; glEnable(glLightIndex); GLfloat ambColor[] = {ambR, ambG, ambB, ambA}; GLfloat diffColor[] = {diffR, diffG, diffB, diffA}; GLfloat specColor[] = {specR, specG, specB, specA}; glLightfv(glLightIndex, GL_AMBIENT, ambColor); glLightfv(glLightIndex, GL_DIFFUSE, diffColor); glLightfv(glLightIndex, GL_SPECULAR, specColor); glLightf(glLightIndex, GL_CONSTANT_ATTENUATION, constantA); glLightf(glLightIndex, GL_LINEAR_ATTENUATION, linearA); glLightf(glLightIndex, GL_QUADRATIC_ATTENUATION, quadA); if (positional) { GLfloat pos[] = {posX, posY, posZ, 1.0f}; glLightfv(glLightIndex, GL_POSITION, pos); if (beamWidth != 180.0f) { glLightf(glLightIndex, GL_SPOT_CUTOFF, beamWidth); GLfloat direction[] = {dirX, dirY, dirZ}; glLightfv(glLightIndex, GL_SPOT_DIRECTION, direction); } else { glLightf(glLightIndex, GL_SPOT_CUTOFF, 180.0f); } } else { GLfloat pos[] = {dirX, dirY, dirZ, 0.0f}; glLightfv(glLightIndex, GL_POSITION, pos); } } // Function to render a textured cube void renderTexturedCube(GLuint textureID) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureID); glBegin(GL_QUADS); // Front Face glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glNormal3f(0.0f, 0.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Face glNormal3f(0.0f, 1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Bottom Face glNormal3f(0.0f, -1.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right face glNormal3f(1.0f, 0.0f, 0.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Left Face glNormal3f(-1.0f, 0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); glDisable(GL_TEXTURE_2D); } // Function to render a cube with explicit material properties // Function to render a cube with explicit metallic material properties void renderCube() { // Define metallic material properties GLfloat materialAmbient[] = {0.25f, 0.25f, 0.25f, 1.0f}; // Low ambient reflection GLfloat materialDiffuse[] = {0.4f, 0.4f, 0.4f, 1.0f}; // Slightly higher diffuse reflection GLfloat materialSpecular[] = {0.77f, 0.77f, 0.77f, 1.0f}; // High specular reflection GLfloat materialShininess = 76.8f; // High shininess for a metallic look // Apply the material properties to the cube glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient); glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular); glMaterialf(GL_FRONT, GL_SHININESS, materialShininess); glBegin(GL_QUADS); // Front Face glNormal3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Back Face glNormal3f(0.0f, 0.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Top Face glNormal3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Bottom Face glNormal3f(0.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(1.0f, -1.0f, -1.0f); glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Right Face glNormal3f(1.0f, 0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); glVertex3f(1.0f, 1.0f, -1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Left Face glNormal3f(-1.0f, 0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glEnd(); } int main() { // Initialize GLFW if (!glfwInit()) { std::cerr << "Failed to initialize GLFW" << std::endl; return -1; } // Create a windowed mode window and its OpenGL context // Set the OpenGL version to 2.1 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Lighting Test", nullptr, nullptr); if (!window) { std::cerr << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } // Make the window's context current glfwMakeContextCurrent(window); // Set viewport glViewport(0, 0, 800, 600); // Set up projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f); // Set up modelview matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0f, 0.0f, 5.0f, // Eye position 0.0f, 0.0f, 0.0f, // Look-at point 0.0f, 1.0f, 0.0f); // Up vector // Enable depth testing glEnable(GL_DEPTH_TEST); GLuint textureID = generateCheckerboardTexture(256, 256); // Enable lighting glEnable(GL_LIGHTING); // Set shading model to smooth glShadeModel(GL_SMOOTH); // float amb[] = { 0.70, 0.70, 0.70, 1 }; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb ); // Set up the lights using the provided makeALight calls makeALight(6, true, 7.0f, 5.0f, 0.0f, // Position 0.0f, -1.0f, 0.0f, // Direction 1.0f, 0.00f, 0.00f, 1.0f, // Ambient 1.0f, 0.0f, 0.0f, 1.00f, // Diffuse 1.0f, 0.00f, 0.00f, 1.00f, // Specular 55.0f, // Angle 0.0f, 0.09f, 0.0f); // Constant, Linear, Quad makeALight(0, false, 0.0f, 0.0f, 0.0f, // Position 0.00f, 0.00f, -1.00f, // Direction 0.0f, 1.0f, 0.0f, 1.00f, // Ambient 0.0f, 1.0f, 0.0f, 1.00f, // Diffuse 0.0f, 1.0f, 0.0f, 1.00f, // Specular 180.0f, // Angle 1.0f, 0.0f, 0.0f); // Constant, Linear, Quad // Main loop while (!glfwWindowShouldClose(window)) { // Render here glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Rotate the cube over time glPushMatrix(); glRotatef((float)glfwGetTime() * 50.0f, 1.0f, 1.0f, 0.0f); // renderCube(); renderTexturedCube(textureID); glPopMatrix(); // Swap front and back buffers glfwSwapBuffers(window); // Poll for and process events glfwPollEvents(); } // Clean up and exit glDeleteTextures(1, &textureID); glfwDestroyWindow(window); glfwTerminate(); return 0; }

更新

所以我拿到了一台 Intel Mac(失败案例是在 Apple Silicon Mac 上),并且问题

没有发生

。这些图像显示了不同的场景,但它们说明了问题。 X86 Mac 中的红色箭头显示位置灯处于打开状态,其照明锥体外部的纹理显示得很好,而在 Apple Silicon 外壳中,它们是深色/黑色的。 所以这意味着问题是:

我的 Rosetta 应用程序在苹果硅 Mac 上运行时出现数学问题。
  1. Apple Silicon 和 Intel Mac 之间 Open Gl 驱动程序的差异。
  2. 也许这条线索可以帮助解决这个问题!

苹果硅胶壳(失败)Apple Silicon Mac

英特尔 X86 机箱(有效!)Intel X86 Mac ** 更新 2 **

我创建了我的测试程序(立方体)的纯 ARM64 版本并对其进行了测试。它

失败了。 这消除了上面的选项 #1 - 问题可能

不是

是由 Rosetta 将 X86-64 转换为 ARM64 引起的。 因此,这要么是我的代码触发的 Apple Silicon OpenGL 驱动程序行为,要么是片上 Apple Silicon 显卡的行为。

c++ macos opengl lighting apple-silicon
1个回答
0
投票

查看驱动程序,Intel Mac 使用 AppleIntelKBLGraphicsGLDriver,这是旧版 OGL 驱动程序。

但是,M1 Mac 使用 AppleMetalOpenGLRenderer,根据名称我认为它是 Metal API 的包装器。

由于这些是不同的驱动程序实现,我只能猜测您发现了一个错误。 如果您还没有向 Apple 报告,我建议您向 Apple 报告。

https://developer.apple.com/bug-reporting/

也许在测试代码中添加注释,以便他们知道如何重现问题。

makeALight(6, true, #if 0 7.0f, 5.0f, 0.0f, // Position (Normal light) #else 7.0f, 1.0f, 0.0f, // Position (BUG: Incorrect shading with AppleMetalOpenGLRenderer) #endif 0.0f, -1.0f, 0.0f, // Direction 1.0f, 0.00f, 0.00f, 1.0f, // Ambient 1.0f, 0.0f, 0.0f, 1.00f, // Diffuse 1.0f, 0.00f, 0.00f, 1.00f, // Specular 55.0f, // Angle 0.0f, 0.09f, 0.0f); // Constant, Linear, Quad

	
© www.soinside.com 2019 - 2024. All rights reserved.