通过顶点属性指针将颜色坐标传递到顶点着色器

Posted

技术标签:

【中文标题】通过顶点属性指针将颜色坐标传递到顶点着色器【英文标题】:Passing colour coords into a vertex shader through a vertex attrib pointer 【发布时间】:2019-03-24 16:54:49 【问题描述】:

我正在尝试将 vec3 颜色数据获取到顶点着色器(作为属性指针),然后将其传递到片段中以进行所有设置。

这一切都是从无法将纹理坐标传递到顶点着色器中开始的。我到处寻找,但找不到明确的解决方案。我可以(通过在顶点着色器中手动设置颜色),得到一个白色方块来渲染,但来自 VAO 的颜色数据似乎无法传递给它。

我还确定着色器加载系统可以正常工作。我最好的想法是信息没有被传递到顶点着色器的'layout = 1',但我很可能错了。

VAO/缓冲区/着色器设置

float vert[] = 
        //Vert Locs   Normal Coords
        -0.5f,-0.5f,  1.0f,1.0f,1.0f,  //0
         0.5f,-0.5f,  1.0f,1.0f,1.0f,  //1
         0.5f,0.5f,   1.0f,1.0f,1.0f,  //2
        -0.5f, 0.5f,  1.0f,1.0f,1.0f,  //3
    ;


    unsigned int index[] = 
        0,1,2, //Order of drawing vertices
        2,3,0
    ;

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

    unsigned int buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 5 * 4 * sizeof(float), vert, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 5 * sizeof(float), 0);
    glVertexAttribPointer(1, 3,  GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));


    glEnableVertexAttribArray(0); // vao ^^

    unsigned int ibo;
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), index, GL_STATIC_DRAW);

    Shader v("VertexN.shader", GL_VERTEX_SHADER);
    Shader f("FragmentN.shader", GL_FRAGMENT_SHADER);

    unsigned int shaders2[] = v.id, f.id;
    unsigned int program2 = Shader::getProgram(shaders2);

    glUseProgram(0);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

渲染循环

glClearColor(0, 0, 0, 1);
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

        glUseProgram(program2);
        //tex.bind(slot);
        glBindVertexArray(vao);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); //Drawing mode, Type indecies , type of index buffer , pointer to index buffer

        glfwSwapBuffers(window);

        glfwPollEvents();

        glFlush();

        glBindVertexArray(0);
        glUseProgram(0);
        glActiveTexture(0);

顶点着色器

#version 330 core

layout(location = 0)in vec2 pos;
layout(location = 1)in vec3 normals;

out vec3 normal;

void main() 

    normal = normals;

    gl_Position = vec4(pos, 0.0f, 1.0f);

;

片段着色器

#version 330 core

layout(location = 0)out vec4 colour;

in vec3 normal;

void main() 
    colour = vec4(normal, 1.0f);
;

【问题讨论】:

我在这里没有看到任何试图为顶点着色器获取颜色属性的东西。 它在 Normal Color (vert array) 中,我试图通过 glVertexAttribPointer 将该数据传递到 vertex 的布局 1 中,然后进入片段着色器。虽然我可能错了,因为我是 OpenGL 和 GLSL 的新手。 【参考方案1】:

我不知道这里的源代码注释是什么:

glEnableVertexAttribArray(0); // vao ^^

应该是这个意思。但是,我的印象是你误解了这个函数的作用。

GL 管理一组通用顶点属性(规范保证至少有 16 个,也许更多),对于每个这样的属性,数据可以来自一个数组。除了必须指定属性指针和数据格式外,您还必须单独启用每个属性的数组。当进行绘图调用时,对于每个顶点索引i,GPU 将获取i——属性数组中启用数组的每个属性的值。对于禁用数组的属性,它将在整个绘制调用中使用一个常量值。 (您可以在发出绘图调用之前通过glVertexAttrib*() familiy of functions 进行设置)。

由于您从未启用属性 1 的数组(您的 normals 着色器输入),所有顶点都将看到属性 1 的当前值 - 很可能只是 vec4(0),因为这是初始默认值,您永远不会好像改了。

解决方案当然是启用所有要从中获取的属性数组:

glEnableVertexAttribArray(1);

而且,当你这样做时:在你的渲染循环中,你有

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

这没有必要。 VAO已经存储了这些信息,不需要重新绑定绘制。

【讨论】:

非常感谢,我知道这会是某种误解,我已经研究了一段时间了。我个人认为它是在谈论启用整个 VAO 之类的。无论如何非常感谢你。

以上是关于通过顶点属性指针将颜色坐标传递到顶点着色器的主要内容,如果未能解决你的问题,请参考以下文章

Unity Shaders and Effects Cookbook (7-1) 在Surface Shader 中 访问 顶点颜色

UnityShader中的语义相关

顶点着色器的绘制操作

如何将变量(不统一)浮点值从 C++ 传递到顶点着色器 OpenGL ES 2.0

GLSL将颜色数据从片段着色器发送到顶点着色器似乎总是等于0

将无符号整数输入属性传递给顶点着色器