OpenGL - 内部有不透明物品的半透明盒子

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

我正在尝试画一个半透明的盒子,里面有不透明的物品。像这样的东西:

对于半透明框,我还创建了一个纹理(whitebg.jpg)我想应用:

到目前为止,这就是我尝试过的:

主要功能

 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();

}

但是得到的结果并不是我所期望的。纹理适用于盒子以及里面的物品。这是一个示例,其中我有一盒 (2x1x1) 和两件 (1x1x1):

是否可以仅在盒子上应用纹理并保持物品真实的不透明颜色,就像第一张图片中一样?

c# opengl glut
1个回答
0
投票

在初始化方法“CreateItems”中,您将禁用深度测试并启用混合:

  Gl.Disable(EnableCap.DepthTest);
  Gl.Enable(EnableCap.Blend);
  Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

这些状态在OnRenderFrame方法中不会改变。但如果您希望这些项目不透明,那么您必须在绘制它们之前禁用混合。当然,在绘制半透明容器之前要重新启用它。

如果您只想在背景中显示半透明框,而项目不受其影响。然后,您应该使用命令

glDepthMask(false)
禁用深度缓冲来渲染它。然后,您可以使用
glDepthMask(true)
将其重新打开。

您还需要启用深度测试,否则项目可能无法正确显示。 IE。离相机较远的面孔可能会与较近的面孔重叠。

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