Anonymous
Почему позиционный (точечный) свет OpenGL мешает непозиционному освещению в MacOS
Сообщение
Anonymous » 17 окт 2024, 02:56
У меня есть устаревшее приложение с фиксированным конвейером OpenGL, которое было перенесено из Windows (32-разрядной версии) в 64-разрядную версию MacOS.
Проблема в том, что если у меня есть сцена с непозиционный свет, все работает отлично. Если я добавлю позиционный прожектор, два источника света будут взаимодействовать, и я получу неправильные результаты.
Вот «нормальный» случай: прожектор находится справа:
Здесь я переместил прожектор вниз (Y = 1). Обратите внимание на черные области на кубе. Это
неправильно .
Теперь я выключаю прожектор, закомментировав вызов "makeALight" для прожектора (свет 6). Теперь куб равномерно освещен.
Вот тестовый код, который я использую для генерации источников света. Для его сборки вам нужно будет установить glfw с Brew.
Код: Выделить всё
#define GL_SILENCE_DEPRECATION 1
#include
#include
#include
#include
#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
Подробнее здесь: [url]https://stackoverflow.com/questions/78928346/why-is-an-opengl-positional-spot-light-interfering-with-non-positional-light-o[/url]
1729123000
Anonymous
У меня есть устаревшее приложение с фиксированным конвейером OpenGL, которое было перенесено из Windows (32-разрядной версии) в 64-разрядную версию MacOS. Проблема в том, что если у меня есть сцена с непозиционный свет, все работает отлично. Если я добавлю позиционный прожектор, два источника света будут взаимодействовать, и я получу неправильные результаты. Вот «нормальный» случай: прожектор находится справа: [img]https://i.sstatic.net/JdkjWj2C.png[/img] Здесь я переместил прожектор вниз (Y = 1). Обратите внимание на черные области на кубе. Это [b]неправильно[/b]. [img]https://i.sstatic.net/jXNmMcFd.png[/img] Теперь я выключаю прожектор, закомментировав вызов "makeALight" для прожектора (свет 6). Теперь куб равномерно освещен. [img]https://i.sstatic.net/pBx68U9f.png[/img] Вот тестовый код, который я использую для генерации источников света. Для его сборки вам нужно будет установить glfw с Brew. [code]#define GL_SILENCE_DEPRECATION 1 #include #include #include #include #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 Подробнее здесь: [url]https://stackoverflow.com/questions/78928346/why-is-an-opengl-positional-spot-light-interfering-with-non-positional-light-o[/url]