OpenGL实现立方体半部分水效填色及上下浮动动画的技术问询
实现带浮动水效果的线框立方体
我来帮你搞定这个需求!要在不覆盖白色边线的前提下给立方体一半填色,还要实现水的浮动动画,核心在于调整绘制顺序和利用OpenGL的混合模式+定时器动画,下面是完整的解决方案:
核心思路
- 分层绘制:先画半透明的水(填充模式),再画立方体的白色线框(线模式),这样线框会叠加在水的上方,不会被覆盖。
- 水的建模:把水做成一个高度动态变化的长方体,和立方体共享底面,顶面高度随时间浮动。
- 平滑动画:利用GLUT的定时器和正弦函数,让水位在立方体的上下限之间做周期性浮动。
完整可运行代码
#include <GL/glut.h> #include <math.h> // 全局变量:当前水位,范围在-1.0到1.0之间 float waterHeight = 0.0f; void initGL() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 开启混合模式,实现水的半透明效果 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } // 更新水位动画的函数 void update(int value) { // 用正弦函数实现平滑的上下浮动,周期约1秒(500ms为半周期) waterHeight = sin(glutGet(GLUT_ELAPSED_TIME) / 500.0f); // 重新绘制画面 glutPostRedisplay(); // 每16ms调用一次update,约60帧/秒 glutTimerFunc(16, update, 0); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(-3.0f, 0.0f, -9.0f); // -------------------------- // 第一步:绘制半透明的水 // -------------------------- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 设置半透明蓝色(RGBA,最后一个值是透明度) glColor4f(0.2f, 0.5f, 1.0f, 0.7f); glBegin(GL_QUADS); // 水的顶面 glVertex3f(-1.0f, waterHeight, -1.0f); glVertex3f(1.0f, waterHeight, -1.0f); glVertex3f(1.0f, waterHeight, 1.0f); glVertex3f(-1.0f, waterHeight, 1.0f); // 水的前面(z=-1) glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(1.0f, -1.0f, -1.0f); glVertex3f(1.0f, waterHeight, -1.0f); glVertex3f(-1.0f, waterHeight, -1.0f); // 水的后面(z=1) glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(1.0f, waterHeight, 1.0f); glVertex3f(-1.0f, waterHeight, 1.0f); // 水的左面(x=-1) glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, waterHeight, 1.0f); glVertex3f(-1.0f, waterHeight, -1.0f); // 水的右面(x=1) glVertex3f(1.0f, -1.0f, -1.0f); glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(1.0f, waterHeight, 1.0f); glVertex3f(1.0f, waterHeight, -1.0f); glEnd(); // -------------------------- // 第二步:绘制立方体的白色线框 // -------------------------- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_QUADS); // 顶面 glVertex3f(1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // 底面 glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // 前面(z=1) glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); // 后面(z=-1) glVertex3f(1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // 左面(x=-1) glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // 右面(x=1) glVertex3f(1.0f, 1.0f, -1.0f); glVertex3f(1.0f, 1.0f, 1.0f); glVertex3f(1.0f, -1.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); glEnd(); glutSwapBuffers(); } void reshape(int width, int height) { if (height == 0) height = 1; float aspect = (float)width / height; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, aspect, 0.1f, 100.0f); glViewport(0, 0, width, height); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 600); glutInitWindowPosition(100, 100); glutCreateWindow("Cube with Floating Water"); initGL(); glutDisplayFunc(display); glutReshapeFunc(reshape); // 启动动画定时器 glutTimerFunc(0, update, 0); glutMainLoop(); return 0; }
关键细节解释
- 绘制顺序的重要性:先画水(填充模式)再画线框(线模式),因为OpenGL是按绘制顺序叠加画面的,后画的内容会覆盖先画的,这样白色线框就会始终在水的上方,不会被遮挡。
- 半透明效果:通过
glEnable(GL_BLEND)开启混合模式,用glColor4f设置alpha值(最后一个参数),让水看起来有通透感,更接近真实的液体效果。 - 动画实现:
update函数利用glutGet(GLUT_ELAPSED_TIME)获取程序运行的毫秒数,通过正弦函数计算水位,实现平滑的上下浮动;glutTimerFunc每16ms调用一次update,保证动画的流畅性(约60帧/秒)。 - 修正原代码的错误:你原来的代码里在
glBegin(GL_QUADS)后直接调用glBegin(GL_LINES),这违反了OpenGL的规范(glBegin必须和glEnd配对),我改用GL_QUADS绘制立方体的六个面,在GL_LINE模式下会自动生成边线,代码更简洁规范。
内容的提问来源于stack exchange,提问作者Sergiu Tonț
相关产品推荐
相关产品推荐

