The rendered scene is again shown in Optix 6.0

I use OpenGL to create a window interface for an Optix program, the purpose is to achieve selective display between multiple scenes。When I close my first scene through the button and open the second scene, my second scene screen shows white 。I found that my second scene was also running by calculating the rendering time, but it was not displayed on the interface I drawn。
When I close the first scene via the button, I also log out the buffer, context, and ray_gen_program.注销
When I open the second scene, I will recreate the subform I drew,But the second scene shows nothing in the subform。
How should i solve this problem?

That is really not enough information to say what’s going on.

Sounds like something is not correctly initialized with GLUT, OpenGL or OptiX or the interoperability between OptiX and OpenGL to transfer the rendered image.

If you completely destroy all OptiX resources and the GLUT window used for OpenGL display, then the second time should just do the exact same initialization steps again. Note that the OpenGL pixelformat can only be set once per lifetime of a window though.

Have you checked all OpenGL calls for errors with glGetError()?
Do you have an exception program running in your OptiX pipeline to see if the renderer worked?

You should check where the white image comes from.
If you clear the screen, change the clear color to some debug color to see if that is actually from the background or the texture blit.
If you fill in data to the OpenGL texture manually does the OpenGL display itself work?
Can you look at the rendered OptiX image manually to see if that worked?
(Map the output buffer, check what’s inside, for example in a memory window of the debugger, unmap the buffer)
Maybe let the ray generation program fill in a single color for easier debugging.
If either doesn’t work then that is your first problem.
If both work, then the mechanism you use to transfer the image to the OpenGL texture would be the next thing to debug.

thank you for your reply。
I created a main window and created its child windows in the main window。The results drawn by Optix are displayed in this sub-window。

This is the child window I drew。

void glutInitialize2()
{
	glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE);
	SubWindow = glutCreateSubWindow(MainWindow, 0, 40, 1080, 680);
    glClearColor(1.0, 0.0, 1.0, 1.0);
	glutDisplayFunc(display2);	
}

I create a button in the main window and give feedback through the glutMouseFunc function。

This is the main window code that I drew

void glutInitialize()
{
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1080, 720);
glutInitWindowPosition(100, 50);
MainWindow=glutCreateWindow(“Main Window”);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glutDisplayFunc(display);
glutMouseFunc(mouseFunc);
gluOrtho2D(0, 1080, 0, 720);
glutMainLoop();
}

The function of the button is implemented in the mouseFunc function。

This is the code of mouseFunc function

void mouseFunc(int button,int state,int x,int y)
{

	if ((button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN))
	{
			hit_x = x;
			hit_y = fabs(720-y);
		
		if ((sceneText != 0) && (gpuText != 0))
		{

			//Confirm button
			if (hit_x >= 834 && hit_x <= 900 && hit_y >= 685 && hit_y <= 710)
			{
				glutInitialize2();
				huizong();
			}
           //Cancel button
			if (hit_x>952&&hit_x<=1018&&hit_y>=685&&hit_y<=710)
			{
				buffer->destroy();
				light_buffer->destroy();
				ray_gen_program->destroy();
				exception_program->destroy();
				destroyContext();
				glutDestroyWindow(SubWindow);
		
			}
		}
	}
}

This is the code of huizong function

void huizong()
{
if (texture_path.empty())
{
texture_path = std::string(sutil::samplesDir()) + “/data”;
}
#ifndef APPLE
glewInit();
#endif
std::string out_file;
// load the ptx source associated with tutorial number
tutorial_ptx = “D:\C#\OptixTest1\x64\Debug\tutorial0.cu.ptx”;
createContext();
createGeometry2();
setupCamera();
setupLights();
context->validate();
if (out_file.empty())
{
glutRun();
}
else
{
updateCamera();
context->launch(0, width, height);
sutil::displayBufferPPM(out_file.c_str(), getOutputBuffer());
destroyContext();
}
}

This is the code of createGeometry2 function。Judge the objects drawn in each scene through sceneText

void createGeometry2()
{

	const char* box_ptx = "D:\\C#\\OptixTest1\\x64\\Debug\\box.cu.ptx";
	Program box_bounds = context->createProgramFromPTXFile(box_ptx, "box_bounds");
	Program box_intersect = context->createProgramFromPTXFile(box_ptx, "box_intersect");
	//create box
	Geometry box = context->createGeometry();
	box->setPrimitiveCount(1u);
	box->setBoundingBoxProgram(box_bounds);
	box->setIntersectionProgram(box_intersect);
	box["boxmin"]->setFloat(-2.0f, 0.0f, -2.0f);
	box["boxmax"]->setFloat(2.0f, 7.0f, 2.0f);
	//create box2
	Geometry box2 = context->createGeometry();
	box2->setPrimitiveCount(1u);
	box2->setBoundingBoxProgram(box_bounds);
	box2->setIntersectionProgram(box_intersect);
	box2["boxmin"]->setFloat(-6.0f, 0.0f, -6.0f);
	box2["boxmax"]->setFloat(-4.0f, 10.0f, -4.0f);


	//材质
	std::string box_chname;
	box_chname = "closest_hit_radiance";
	Material box_matl = context->createMaterial();
	Program box_ch = context->createProgramFromPTXFile(tutorial_ptx, box_chname.c_str());
	box_matl->setClosestHitProgram(0, box_ch);
	box_matl["Ka"]->setFloat(0.3f, 0.3f, 0.3f);
	box_matl["Kd"]->setFloat(0.6f, 0.7f, 0.8f);
	box_matl["Ks"]->setFloat(0.8f, 0.9f, 0.8f);
	box_matl["phong_exp"]->setFloat(88);
	box_matl["reflectivity_n"]->setFloat(0.2f, 0.2f, 0.2f);
	//绑定材质
	std::vector<GeometryInstance> Box_gi;
	Box_gi.push_back(context->createGeometryInstance(box, &box_matl, &box_matl + 1));

	std::vector<GeometryInstance> Box2_gi;
	Box2_gi.push_back(context->createGeometryInstance(box2, &box_matl, &box_matl + 1));
	if (sceneText==1)
	{
		GeometryGroup gp1 = context->createGeometryGroup();
		gp1->setChildCount(static_cast<unsigned int>(Box_gi.size()));
		gp1->setChild(0, Box_gi[0]);
		//gp1->setChild(1, Box_gi[1]);
		gp1->setAcceleration(context->createAcceleration("Trbvh"));
		context["top_object"]->set(gp1);
		context["top_shadower"]->set(gp1);
	}
	if (sceneText==2)
	{
		GeometryGroup gp2 = context->createGeometryGroup();
		gp2->setChildCount(static_cast<unsigned int>(Box2_gi.size()));
		gp2->setChild(0, Box2_gi[0]);
		//gp1->setChild(1, Box_gi[1]);
		gp2->setAcceleration(context->createAcceleration("Trbvh"));
		context["top_object"]->set(gp2);
		context["top_shadower"]->set(gp2);
	}
}

This is the code of destroyContext function

void destroyContext()
{
if (context)
{
context->destroy();
context = 0;
}
}

Most of the code of the program is rewritten on the basis of optixTutorial in the Optix6.0 sample

Displaying the result of Optix drawing on OpenGL is achieved by the following function

void glutDisplay()
{
if (context)
{
updateCamera();
context->launch(0, width, height);
sutil::displayBufferGL(buffer);
{
static unsigned frame_count = 0;
sutil::displayFps(frame_count++);
}
glutSwapBuffers();
}
}

glutDIsplay is called through the glutRun function

void glutRun()
{
// Initialize GL state
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, width, height);
glutShowWindow();
glutReshapeWindow(width, height);
// register glut callbacks
glutDisplayFunc(glutDisplay);
glutIdleFunc(glutDisplay);
glutReshapeFunc(glutResize);
glutKeyboardFunc(glutKeyboardPress);
glutMouseFunc(glutMousePress);
glutMotionFunc(glutMouseMotion);
registerExitHandler();
}

The glutDIsplay 、 glutRun and destroyContext functions are included in the sample。

I have created a single color to be displayed on the screen with rays. When I click it at the beginning, the color I set will appear. When I click the logout button and then click the generate button, the screen is still white.

Please don’t post incomplete code excerpts as text. The forum allows attaching files with the respective full source code which would make understanding what else you did easier.

As far as I know, each GLUT sub-window holds its own OpenGL context. You assigned a different display function to the sub-window with glutDisplayFunc(display2) without showing what that does.

I would not expect that the sutil::displayBufferGL(buffer) helper function knows about different OpenGL contexts.
Depending on when and how you created the buffer you want to display, that might not have the correct OpenGL resources assigned, but from another OpenGL context and then textures will be incomplete and not show anything but white with the default color and default modulate mode for textures.

So far this looks like you didn’t manage OpenGL correctly.

thank you for your reply。
test1.cpp (18.7 KB)
sorry,I wanted to upload my entire source program, but I can’t upload it. I can upload my .cpp file. Can you help me find the errors in it?

You’re creating the OptiX output buffer with an OpenGL pixel buffer object as backing store (OpenGL interop with OptiX, rendering directly into the PBO) because use_pbo = true.

If it works when setting that to false (then the buffer will be copied through the host which is slower) then something is wrong with the OpenGL context handling.

That is all yours to figure out then. Maybe download the freeglut sources and build it yourself, then step through all your GLUT code inside the debugger. Put a breakpoint in wglMakeCurrent to see if the same OpenGL context is current when creating the buffer and displaying it. If not, that’s the issue.

I’ve not seen GLUT example code calling glutInitDisplayMode() more than once. That defines the OpenGL pixel format and I wouldn’t change that per sub-window. Just use glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DEPTH | GLUT_DOUBLE) once in main().

There wouldn’t actually be a need to destroy the OptiX context when just switching scenes. It would be enough to destroy everything else except for the context and then just rebuild the render graph again.

If it’s not the OpenGL context mismatch then I can’t say from that source what else could have gone wrong.

Thank you for your reply.

I tested my program,I set use_pbo=false,I found it to work.But I set use_pbo=false in the sample optixTutorial, and found that it can also run normally.

I do not use the windows API, so I cannot use wglMakeCurrent to test。No context is set for OpenGL, the context used by the program is created by Optix::Context。

The configuration I use is:window 10。VS2019。Optix 6.0。

Most of the functions I use are freeglut. The buttons are formed by drawing rectangles.

Yes, I have seen what your program does.

What I said is that if you look into or debug through the freeglut sources, you will find that it is calling wglMakeCurrent internally when using sub-windows. All callback functions per window need to set the current OpenGL context when entering them.

Again, if this works when disabling OpenGL interop via the pixel-buffer-object, then the failing case most likely created the OptiX output buffer with a PBO in a different OpenGL context as is active when trying to copy it to the final display texture. Means the names of the these OpenGL objects do not exist in the same context and result in no data transfer and maybe even an OpenGL error.

This is not an OptiX issue then. I can’t help with this further. I’m not using GLUT or OptiX 6 anymore.

The freeglut 3.2.1 sources contain a demo dedicated to sub-windows. Maybe that helps getting the right structure into your application.

BTW, when using OptiX versions below 7, please at least update to the newest available version. I wouldn’t use OptiX 6.0.0 for new developments when there is OptiX 6.5.0 available, or even more future proof, switch to OptiX 7 which uses a completely different and more modern explicit API where resources are managed with native CUDA code.
The SDK examples and other OptiX 7 examples found on this forum inside the sticky posts use GLFW as windowing framework.
Always read the OptiX Release Notes for each version before setting up a development environment. It describes the required minimum display drivers and compatible CUDA toolkits.

Thank you for your reply.
If I can’t debug the old version, I try to create it with the new version。
Thank you for your help。