I'm trying to draw a translucent box with opaque items inside. Something like this:
For the translucent box I have also created a texture (whitebg.jpg) I would like to apply:
So far this is what I tried:
Main function
private static void CreateItems(List<Items> packedItems)
{
Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);
Glut.glutInitWindowSize(width, height);
Glut.glutCreateWindow("pack");
Glut.glutIdleFunc(OnRenderFrame);
Glut.glutDisplayFunc(OnDisplay);
Glut.glutKeyboardFunc(OnKeyboardDown);
Glut.glutKeyboardUpFunc(OnKeyboardUp);
Glut.glutMouseWheelFunc(OnMouseWheel);
Glut.glutCloseFunc(OnClose);
Glut.glutReshapeFunc(OnReshape);
Gl.Disable(EnableCap.DepthTest);
Gl.Enable(EnableCap.Blend);
Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
program = new ShaderProgram(VertexShader, FragmentShader);
program.Use();
program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, new Vector3(0, 1, 0)));
program["light_direction"].SetValue(new Vector3(0, 0, 1));
program["enable_lighting"].SetValue(lighting);
bgTexture = new Texture("whitebg.jpg");
}
Glut.glutIdleFunc
private static void OnRenderFrame()
{
watch.Stop();
float deltaTime = (float)watch.ElapsedTicks / System.Diagnostics.Stopwatch.Frequency;
watch.Restart();
// perform rotation of the cube depending on the keyboard state
if (autoRotate)
{
xangle += deltaTime / 2;
yangle += deltaTime;
}
if (right) yangle += deltaTime;
if (left) yangle -= deltaTime;
if (up) xangle -= deltaTime;
if (down) xangle += deltaTime;
// set up the viewport and clear the previous depth and color buffers
Gl.Viewport(0, 0, width, height);
Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// make sure the shader program and texture are being used
Gl.UseProgram(program);
Gl.BindTexture(bgTexture);
// set up the model matrix and draw the cube
program["model_matrix"].SetValue(Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
program["enable_lighting"].SetValue(lighting);
for (int i = 0; i < virtual_items.Count; i++)
{
Gl.BindBufferToShaderAttribute(virtual_items[i], program, "vertexPosition");
Gl.BindBufferToShaderAttribute(virtual_items_color[i], program, "vertexColor");
Gl.BindBuffer(virtual_items_quads[i]);
Gl.DrawElements(BeginMode.Quads, virtual_items_quads[i].Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
}
Gl.BindBufferToShaderAttribute(virtual_container, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(virtual_container_normals, program, "vertexNormal");
Gl.BindBufferToShaderAttribute(virtual_container_UV, program, "vertexUV");
Gl.BindBuffer(virtual_container_Quads);
Gl.DrawElements(BeginMode.Quads, virtual_container_Quads.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
Glut.glutSwapBuffers();
}
But the result obtained is not what I'm expecting. Texture is applying at box and also at items inside. Here a sample where I have a box of (2x1x1) and two items of (1x1x1):
Is it possible to apply the texture only on the box and keep the items with their real opaque color just like in the first picture?



In your initialization method "CreateItems" you are disabling depth testing and enabling blending:
These states are not changed in the OnRenderFrame method. But if you want the items to be opaque, then you have to disable blending before drawing them. And of course renable it before drawing the translucent container.
If you want to display the translucent box only in the background, with items not being affected by it. Then you should render it with depth buffering being disabled using the command
glDepthMask(false). Afterwards you turn it back on usingglDepthMask(true).Also you need to enable depth testing, because otherwise the items might not be displayed correctly. I.e. faces further away from the camera could overlap closer ones.