You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开启深度测试后未生效?附相关OpenGL/Cocos2d-x代码片段

深度测试没生效?来一步步排查修复!

嘿,看你给出的代码片段,首先最明显的问题是完全没看到开启深度测试的关键代码,这大概率就是根源。下面我给你拆解几个必须检查的点,结合你的代码来补全:

1. 先把深度测试开关打开!

OpenGL默认是关闭深度测试的,你得在初始化阶段(比如启动渲染前)加上这句:

glEnable(GL_DEPTH_TEST);

另外,每帧渲染前一定要记得同时清除颜色缓冲和深度缓冲,不然上一帧的深度数据会干扰当前帧:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

要是只清颜色不清深度,深度测试的结果肯定乱套。

2. 确认帧缓冲区有深度附件(针对Cocos2d-x)

从你用Director来看,应该是在Cocos2d-x环境下。默认帧缓冲区一般会带深度缓冲,但保险起见,初始化GLView的时候可以明确设置:

GLViewImpl* glView = GLViewImpl::createWithRect("GLDemo", Rect(0, 0, 800, 600));
glView->setDepthBufferFormat(GL_DEPTH_COMPONENT24); // 指定24位深度缓冲格式
Director::getInstance()->setOpenGLView(glView);

如果是自定义FBO的话,那必须手动绑定深度纹理/渲染缓冲作为附件,这个得额外注意。

3. 检查Shader里的Z坐标处理

你的顶点数据里有Z值(比如0.5、0.8),但得确保顶点着色器把Z坐标正确转换到裁剪空间啊!比如必须用MVP矩阵(模型视图投影矩阵)来变换顶点位置,不然Z值的范围不符合OpenGL的要求(裁剪空间Z是[-1,1]),深度测试根本没法正确判断。举个顶点着色器的例子:

attribute vec3 a_position;
uniform mat4 u_MVPMatrix; // 这个矩阵要在代码里传进去

void main() {
    gl_Position = u_MVPMatrix * vec4(a_position, 1.0);
}

要是你直接把顶点位置赋值给gl_Position,没做投影变换,那Z值等于白给。

4. 顶点数据绑定要完整

你的代码里创建了VAO和VBO,但没看到设置顶点属性指针的代码!比如glVertexAttribPointer和glEnableVertexAttribArray这俩关键调用。如果Z坐标的属性没正确绑定到着色器,那着色器拿到的Z值可能是默认值,深度测试自然失效。给你补一段:

// 先把顶点数据传入VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// 获取着色器中a_position的属性位置
GLint posLoc = m_Program->getAttribLocation("a_position");
// 设置顶点属性指针:每个顶点3个float,步长是3*sizeof(float)
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
// 启用这个属性数组
glEnableVertexAttribArray(posLoc);

5. 深度测试函数的设置(可选)

默认的深度测试函数是GL_LESS(新像素Z值小于缓冲区里的就通过),一般够用。但如果你之前改过这个设置,可以重置回默认:

glDepthFunc(GL_LESS);

给你的代码补全示例

把这些步骤整合到你的代码里,大概是这样:

// 初始化阶段先开深度测试
glEnable(GL_DEPTH_TEST);
glClearDepthf(1.0f); // 深度缓冲清除值默认是1.0,可省略

m_Program = new GLProgram; 
m_Program->initWithFilenames("shader/gldemo.vsh", "shader/gldemo.fsh"); 
m_Program->link(); 
m_Program->updateUniforms(); 

glGenVertexArrays(1, &vao); 
glBindVertexArray(vao); 

// 创建VBO并传入顶点数据
glGenBuffers(1, &vertexVBO); 
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); 
auto size = Director::getInstance()->getVisibleSize(); 
float vertices[] = { 
    0,0,0.5, // first point 
    -1, 1,0.5, 
    -1, -1,0.5, 
    -0.3,0,0.8, 
    1, 1,0.8, 
    1, -1,0.8
};
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// 绑定顶点属性
GLint posLoc = m_Program->getAttribLocation("a_position");
glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(posLoc);

// 解绑VAO和VBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

然后每帧渲染的时候:

// 先清除缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 使用着色器程序
m_Program->use();
// 计算并设置MVP矩阵(关键!根据你的相机来)
Mat4 projMat = Director::getInstance()->getMatrix(MATRIX_STACK_PROJECTION);
Mat4 modelViewMat = Director::getInstance()->getMatrix(MATRIX_STACK_MODELVIEW);
Mat4 mvp = projMat * modelViewMat;
m_Program->setUniformMatrix4fv("u_MVPMatrix", 1, GL_FALSE, mvp.m);

// 绑定VAO并绘制
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6); // 画两个三角形(6个顶点)
glBindVertexArray(0);

按照这些步骤调整后,深度测试应该就能正常工作了~


内容的提问来源于stack exchange,提问作者jerryln

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:34:32