OpenGL закадровый рендер

У меня есть приложение, которое создает 3D-модель и экспортирует из нее изображение. Я использую этот пример, чтобы сделать это:

#include <windows.h>
#include <GL\GL.h>
#include <GL\glu.h>
#include <GL\glut.h>
#include <opencv2\highgui.hpp>

GLfloat light_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };  /* Red diffuse light. */
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };  /* Infinite light location. */
GLfloat n[6][3] = {  /* Normals for the 6 faces of a cube. */
{ -1.0, 0.0, 0.0 },{ 0.0, 1.0, 0.0 },{ 1.0, 0.0, 0.0 },
{ 0.0, -1.0, 0.0 },{ 0.0, 0.0, 1.0 },{ 0.0, 0.0, -1.0 } };
GLint faces[6][4] = {  /* Vertex indices for the 6 faces of a cube. */
{ 0, 1, 2, 3 },{ 3, 2, 6, 7 },{ 7, 6, 5, 4 },
{ 4, 5, 1, 0 },{ 5, 6, 2, 1 },{ 7, 4, 0, 3 } };
GLfloat v[8][3];  /* Will be filled in with X,Y,Z vertexes. */

void drawBox(void)
{
int i;

for (i = 0; i < 6; i++) {
glBegin(GL_QUADS);
glNormal3fv(&n[i][0]);
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}

void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawBox();
glFlush();
}

void init(void)
{
/* Setup cube vertex data. */
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;

/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);

/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);

/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,5) */
0.0, 0.0, 0.0,      /* center is at (0,0,0) */
0.0, 1.0, 0.);      /* up is in positive Y direction */

/* Adjust cube position to be asthetic angle. */
glTranslatef(0.0, 0.0, -1.0);
glRotatef(60, 1.0, 0.0, 0.0);
glRotatef(-20, 0.0, 0.0, 1.0);
}

int main(int argc, char **argv)
{
int width = 500, height = 500;

/********* i want to remove this section ************/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("red 3D lighted cube");
/********* i want to remove this section ************/

init();
display();

BYTE* result = new BYTE[3 * width *height];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, result);
cv::Mat img(width, height, CV_8UC3);
img.data = result;
cv::flip(img, img, 0);
cv::imwrite("D:\\result_off.jpg", img);

return 0;             /* ANSI C requires main to return int. */
}

Это работает правильно, но когда я запускаю эту программу, она создает окно и показывает его, а затем удаляет.

Я пытался удалить функцию glut * и запустить мою программу, но она ничего не экспортировала при запуске. Я погуглил и обнаружил, что должен использовать Framebuffer, но не смог найти ни одного примера.

Как я могу установить, что моя программа не показывает никакого окна при рендеринге моей 3D-модели?

Примечание: я хочу запустить эту программу в Windows и Linux.

0

Решение

Я только что посмотрел на исходный код, который я сделал для Windows. Поскольку это было исследование продуктивного кода (и, следовательно, используется другой материал нашего продуктивного кода), я не могу предоставить его как есть. То, что я представляю здесь, является урезанной версией, которая должна показать, как это работает:

// standard C/C++ header:
#include <iostream>

// Windows header:
#include <Windows.h>

using namespace std;

int main(int argc, char **argv)
{
if (argc < 3) {
cerr << "USAGE: " << argv[0]
<< " FILE [FILES...] IMG_FILE" << endl;
return -1;
}
// Import Scene Graph
// excluded: initialize importers
// excluded: import 3d files
#ifdef _WIN32
// Window Setup
// set window properties
enum { Width = 1024, Height = 768 };
WNDCLASSEX wndClass; memset(&wndClass, 0, sizeof wndClass);
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wndClass.lpfnWndProc = &DefWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = 0;
wndClass.hIcon = 0;
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = 0;
wndClass.lpszClassName = "WndClass";
wndClass.hIconSm = 0;
RegisterClassEx(&wndClass);
// style the window and remove the caption bar (WS_POPUP)
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
// Create the window. Position and size it.
HWND hwnd = CreateWindowEx(0,
"WndClass",
"",
style,
CW_USEDEFAULT, CW_USEDEFAULT, Width, Height,
0, 0, 0, 0);
HDC hdc = GetDC(hwnd);
// Windows OpenGL Setup
PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof pfd);
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 16;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
// get the best available match of pixel format for the device context
int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
// make that the pixel format of the device context
SetPixelFormat(hdc, iPixelFormat, &pfd);
// create the context
HGLRC hGLRC = wglCreateContext(hdc);
wglMakeCurrent(hdc, hGLRC);
#endif // _WIN32
// OpenGL Rendering Setup
/* excluded: init our private OpenGL binding as
* the Microsoft API for OpenGL is stuck <= OpenGL 2.0
*/
// create Render Buffer Object (RBO) for colors
GLuint rboColor = 0;
glGenRenderbuffers(1, &rboColor);
glBindRenderbuffer(GL_RENDERBUFFER, rboColor);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create Render Buffer Object (RBO) for depth
GLuint rboDepth = 0;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create Frame Buffer Object (FBO)
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// attach RBO to FBO
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, rboColor);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, rboDepth);
// GL Rendering Setup
// excluded: prepare our GL renderer
glViewport(0, 0, Width, Height);
glClearColor(0.525f, 0.733f, 0.851f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
/* compute projection matrix from
* - field of view (property fov)
* - aspect ratio of view
* - near/far clip distance (properties dNear and dFar).
*/
const DegreeD fov(30.0);
const double dNear = 0.1, dFar = 100.0;
const double ar = (float)Width / Height;
const double d = ::tan(fov / 2.0) * 2.0 * dNear;
// excluded: construct a projection matrix for perspective view
// excluded: determine bounding sphere of 3D scene
// excluded: compute camera and view matrix from the bounding sphere of scene
// excluded: OpenGL rendering of 3d scene
// read image from render buffer
// excluded: prepare image object to store read-back
//Image::Object img(4, Image::BottomToTop);
//img.set(Width, Height, Image::RGB24);
//const size_t bytesPerLine = (3 * Width * 4 + 3) / 4;
//glReadPixels(0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, img.getData());
// store image
const string filePath = argv[argc - 1];
// excluded: export image in a supported image file format
// clean-up
// excluded: clean-up of 3D scene (incl. OpenGL rendering add-ons)
glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rboColor);
glDeleteRenderbuffers(1, &rboDepth);
#ifdef _WIN32
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hGLRC);
#endif // _WIN32
// done
return 0;
}

Я не проверял, компилируется ли это вообще (как указано выше). Он вырезан из кода, который компилируется и запускается на Windows 10 на моей стороне.


Примечание об OpenGL и Windows:

Я сделал привязку GL самостоятельно, потому что Microsoft Windows OpenGL API не поддерживает OpenGL 3.0 или выше. (Я мог бы использовать библиотеку как glfw вместо этого.) Это означает, что я должен назначить адреса функций указателям на функции (чтобы исправить прототипы функций), чтобы я мог правильно вызывать функции OpenGL, используя вызовы функций C.

Доступность функций предоставляется если У меня есть соответствующие H / W и соответствующие драйверы. (Есть возможность проверить, предоставляет ли драйвер определенные функции.)

В случае сбоя такого вызова связанной функции (например, из-за ошибки сегментации) возможными причинами могут быть:

  1. Подпись вызываемой функции неверна. (Я использовал заголовки, загруженные с сайта khronos.org, для предоставления правильных прототипов. Надеюсь, поставщик драйверов также сделал это.)

  2. Функция не существует в драйвере. (Я использую функции, которые являются частью стандарта OpenGL, который поддерживается установленным драйвером. Драйвер поддерживает OpenGL 4.x, но мне нужен только OpenGL 3.x (по крайней мере, до сих пор).)

  3. Указатели на функции должны быть инициализированы, прежде чем я их использую. (Я написал инициализацию, которая не раскрывается в коде. Здесь я разместил комментарий /* excluded: init our private OpenGL binding as the Microsoft API for OpenGL is stuck <= OpenGL 2.0 */,

Чтобы проиллюстрировать это, некоторые примеры кода:

В моей функции инициализации OpenGL я делаю:

  glGenFramebuffers
= (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress(
"glGenFramebuffers");

и заголовок обеспечивает:

extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;

PFNGLGENFRAMEBUFFERSPROC обеспечивается glext.h Я скачал с kronos.org:

typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);

wglGetProcAddress() предоставляется Microsoft Windows API.

Примечание об OpenGL и Linux:

Если H / W и установленный драйвер поддерживают требуемый стандарт OpenGL, функции могут использоваться как обычно:

  1. включая необходимые заголовки (например, #include <GL/gl.h>)

  2. связывание необходимых библиотек (например, -lGL -lGLU).


Дерхасс прокомментировал:

Нет абсолютно никакой гарантии, что функции GL 3.x будут экспортированы любым libGL.so один использует, и даже если они экспортируются, нет никакой гарантии, что функция поддерживается (т. е. mesa использует одну и ту же библиотеку внешнего интерфейса для всех бэкэндов драйверов, но каждый драйвер может поддерживать только подмножество функций). Вы должны использовать механизм расширения на обеих платформах.

Я не могу дать простую рекомендацию, как справиться с этим, и у меня нет ценного практического опыта в этом. Итак, я хочу предоставить по крайней мере эти ссылки (с khronos.org), которые я нашел в поиске Google:

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]