美文网首页iOS技术交流收藏iOS技术文章
解决苹果开发者论坛的求助帖(Transform Feedback

解决苹果开发者论坛的求助帖(Transform Feedback

作者: 熊皮皮 | 来源:发表于2016-03-09 07:35 被阅读261次

本人已编写的有关Transform Feedback相关文档:

本文档描述了修复一份来自苹果开发者论坛的求助代码中存在的错误Transform Feedback doesn't write, crashes | Apple Developer Forums

求助代码如下所示。

// create shader
const GLchar* vertexShaderSrc = "in float inValue; out float outValue;  void main() {  outValue = sqrt(inValue); } );";

GLuint shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(shader, 1, &vertexShaderSrc, 0);
glCompileShader(shader);

GLuint program = glCreateProgram();
glAttachShader(program, shader);
const GLchar* feedbackVaryings[] = { "outValue" };
glTransformFeedbackVaryings(program, 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
glLinkProgram(program);
glUseProgram(program);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLfloat data[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };

// create input buffer
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLint inputAttrib = glGetAttribLocation(program, "inValue");
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(inputAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);

// create output buffer
GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), 0, GL_STATIC_READ);

// transform
glEnable(GL_RASTERIZER_DISCARD);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, 5);
glEndTransformFeedback();
glFlush();

// write output
GLfloat *feedback;
feedback = glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(feedback), GL_MAP_READ_BIT);
NSLog(@"%f %f %f %f %f\n", feedback[0], feedback[1], feedback[2], feedback[3], feedback[4]);

提问者说feedback返回空指针,如下所述。

The value of data[] is never changed and NSLog crashes because glMapBufferRange returns a null pointer. How do you do transform feedback

现在,分析这段代码并令其可在iPhone 6上运行。猜测为简化代码,提问者并没给出Fragment Shader代码,然而,这对于OpenGL ES 3.0是必需的,所以,这应该是个Mac软件开发者。

因此,先给出片段着色器的实现及顶点着色器的细微调整。

const GLchar* vertexShaderSrc = "#version 300 es \n in float inValue; out float outValue;  void main() {  outValue = sqrt(inValue); } );";
// 补上Fragment Shader
const GLchar* fragmentShaderSrc = "#version 300 es void main() {}";

编译并安装至program。

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, & fragmentShaderSrc, 0);
glCompileShader(fragmentShader);
///
glAttachShader(program, fragmentShader);

修复内存映射时指定的缓冲区长度错误。整段代码的核心错误就在于此

feedback = glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(feedback), GL_MAP_READ_BIT);
///////修改为
feedback = glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);

到此,此代码可在iOS上运行。下面分析存在的其它问题。

1、输出缓冲区存在内存修饰符不合理。

// create output buffer
GLuint tbo;
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), 0, GL_STATIC_READ);

GL_STATIC_READ应改为GL_STATIC_DRAW,因为整个代码只需运行一次。当然,驱动程序会忽略不合理的内存修饰符,并自动选择合适的值,但是,尽量不要依赖驱动程序的优化。

2、判断映射结果及解除内存映射

当然,这显然是段验证性代码,不应该过多要求健壮性。

if (feedback) {
    NSLog(@"%f %f %f %f %f\n", feedback[0], feedback[1], feedback[2], feedback[3], feedback[4]);
}
glUnmapBuffer(GL_ARRAY_BUFFER);

相关文章

网友评论

  • Jieqiudedede:飞雄出点iOS直播方面的,感觉网上好少:stuck_out_tongue_winking_eye:
    Micropoints:感觉配置输出Buffer会覆盖原来已上传的数据。
    Micropoints:#if 0
    // create output buffer
    GLuint tbo;
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(data), 0, GL_STREAM_DRAW);

    // transform
    glEnable(GL_RASTERIZER_DISCARD);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo);
    glBeginTransformFeedback(GL_POINTS);
    glDrawArrays(GL_POINTS, 0, 5);
    glEndTransformFeedback();
    glFlush();
    #endif
    你好,请问一下,我运行了下这个例子发现不能正常返回数据,而且打印上传的数据也都是0,但是 注释掉配置输出部分后,能打印上传的值,但是输出的值就不正确了。
    Jieqiudedede:@飞雄_82084788 期待

本文标题:解决苹果开发者论坛的求助帖(Transform Feedback

本文链接:https://www.haomeiwen.com/subject/eoizkttx.html