我正在尝试画一个半透明的盒子,里面有不透明的物品。像这样的东西:
对于半透明框,我还创建了一个纹理(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):
是否可以仅在盒子上应用纹理并保持物品真实的不透明颜色,就像第一张图片中一样?
在初始化方法“CreateItems”中,您将禁用深度测试并启用混合:
Gl.Disable(EnableCap.DepthTest);
Gl.Enable(EnableCap.Blend);
Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
这些状态在OnRenderFrame方法中不会改变。但如果您希望这些项目不透明,那么您必须在绘制它们之前禁用混合。当然,在绘制半透明容器之前要重新启用它。
如果您只想在背景中显示半透明框,而项目不受其影响。然后,您应该使用命令
glDepthMask(false)
禁用深度缓冲来渲染它。然后,您可以使用 glDepthMask(true)
将其重新打开。
您还需要启用深度测试,否则项目可能无法正确显示。 IE。离相机较远的面孔可能会与较近的面孔重叠。