OpenGL向曲面细分着色器传递float数组崩溃问题求助
问题核心原因
你的崩溃问题根本上来自顶点属性配置不符合OpenGL规范,属于典型的未定义行为触发崩溃:
- OpenGL的
glVertexAttribPointer接口的第二个参数size,仅支持传入1/2/3/4四个有效值,代表单顶点属性的分量数,你直接传6本身就是非法调用,即便驱动没有在编译/链接阶段抛出错误,运行时访问也会出现内存越界。 - 顶点着色器中声明的
layout (location = 2) in float f[SIZE];数组属性,会连续占用SIZE个location位置(这里就是2、3、4、5、6、7共6个location),你仅启用了location 2,剩下的5个location对应的顶点属性没有配置、也没有启用,访问时会读取非法显存地址。
解决步骤
1. 修正顶点输入配置
你可以选择两种常用方案传递6个float的数组:
方案A:拆分为两个vec3传递(推荐,代码量少)
着色器端修改:
顶点着色器输入部分改为:
#define SIZE 6 layout (location = 0) in vec2 x; layout (location = 1) in vec2 h; layout (location = 2) in vec3 f_low; layout (location = 3) in vec3 f_high; out TC_DATA { vec2 x; vec2 h; float f[SIZE]; } tc_out; void main() { tc_out.x = x; tc_out.h = h; // 手动组装为数组 tc_out.f = float[6](f_low.x, f_low.y, f_low.z, f_high.x, f_high.y, f_high.z); }
C++端顶点属性配置修改:
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, x)); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, h)); // 前3个float对应f_low,占location2 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, f)); // 后3个float对应f_high,占location3,偏移为3个float的长度 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(offsetof(Vertex, f) + 3 * sizeof(float))); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnableVertexAttribArray(2); glEnableVertexAttribArray(3); // 新增启用location3
方案B:拆分为6个独立float传递
顶点着色器声明6个连续location的float输入,手动组装为数组,C++端对应配置6个glVertexAttribPointer、启用6个location即可,逻辑和方案A一致。
2. 补充曲面细分求值着色器的输入块
你当前的曲面细分求值着色器(TES)没有接收TCS输出的TE_DATA块,即便驱动可能会优化掉未使用的输出,也建议补充对应声明避免兼容性问题:
// tess evaluation 着色器新增输入块 in TE_DATA { vec2 x; vec2 h; float f[SIZE]; } te_in[];
3. 可选排查手段
如果修改后仍有问题,可开启OpenGL调试上下文,注册调试回调函数,运行时可以拿到驱动输出的详细错误信息,快速定位非法调用位置。
内容的提问来源于stack exchange,提问作者Saitama10000
相关产品推荐
相关产品推荐

