Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ OpenGL:动态更改纹理坐标_C++_Opengl_Opengl Es_Rendering_Shader - Fatal编程技术网

C++ OpenGL:动态更改纹理坐标

C++ OpenGL:动态更改纹理坐标,c++,opengl,opengl-es,rendering,shader,C++,Opengl,Opengl Es,Rendering,Shader,我目前正在尝试使用位图(想想入侵者记分板)渲染整数的值,但在游戏运行时更改纹理坐标时遇到问题 我将着色器和数据链接如下: GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord"); glEnableVertexAttribArray(texAttrib); glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2

我目前正在尝试使用位图(想想入侵者记分板)渲染整数的值,但在游戏运行时更改纹理坐标时遇到问题

我将着色器和数据链接如下:

GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(float), (void*)(2 * sizeof(float)));
在我的着色器中,我执行以下操作: 顶点着色器:

#version 150

uniform mat4 mvp;

in vec2 position;
in vec2 texcoord;

out vec2 Texcoord;


void main() {
    Texcoord = texcoord;
    gl_Position =  mvp * vec4(position, 0.0, 1.0) ;
}
碎片着色器:

#version 150 core
in vec2 Texcoord;
out vec4 outColor;

uniform sampler2D tex;
void main() {
    outColor = texture2D(tex, Texcoord);
}

我将如何更改此代码/实现一个函数来更改texcoord变量?

因此,我没有承诺此技术的效率,但这是我所做的,如果文本渲染导致我的程序变慢,我将被诅咒

我有一个专门的类来存储mesh,它由一些数据向量组成,还有一些
GLuint
s来存储指向上传数据的指针。我将数据上传到openGL,如下所示:

            glBindBuffer(GL_ARRAY_BUFFER, position);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.position.size(), &data.position[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, normal);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.normal.size(), &data.normal[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, uv);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec2) * data.uv.size(), &data.uv[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * data.index.size(), &data.index[0], GL_DYNAMIC_DRAW);
        glEnableVertexAttribArray(positionBinding);
        glBindBuffer(GL_ARRAY_BUFFER, position);
        glVertexAttribPointer(positionBinding, 3, GL_FLOAT, GL_FALSE, 0, NULL);

        glEnableVertexAttribArray(normalBinding);
        glBindBuffer(GL_ARRAY_BUFFER, normal);
        glVertexAttribPointer(normalBinding, 3, GL_FLOAT, GL_TRUE, 0, NULL);

        glEnableVertexAttribArray(uvBinding);
        glBindBuffer(GL_ARRAY_BUFFER, uv);
        glVertexAttribPointer(uvBinding, 2, GL_FLOAT, GL_FALSE, 0, NULL);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);

        glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, NULL);

        glDisableVertexAttribArray(positionBinding);
        glDisableVertexAttribArray(normalBinding);
        glDisableVertexAttribArray(uvBinding);
GLuint vboIds[2];
glGenBuffers(2, vboIds);

// Load positions.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

// Load texture coordinates.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_DYNAMIC_DRAW);
然后,我这样画:

            glBindBuffer(GL_ARRAY_BUFFER, position);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.position.size(), &data.position[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, normal);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.normal.size(), &data.normal[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, uv);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec2) * data.uv.size(), &data.uv[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * data.index.size(), &data.index[0], GL_DYNAMIC_DRAW);
        glEnableVertexAttribArray(positionBinding);
        glBindBuffer(GL_ARRAY_BUFFER, position);
        glVertexAttribPointer(positionBinding, 3, GL_FLOAT, GL_FALSE, 0, NULL);

        glEnableVertexAttribArray(normalBinding);
        glBindBuffer(GL_ARRAY_BUFFER, normal);
        glVertexAttribPointer(normalBinding, 3, GL_FLOAT, GL_TRUE, 0, NULL);

        glEnableVertexAttribArray(uvBinding);
        glBindBuffer(GL_ARRAY_BUFFER, uv);
        glVertexAttribPointer(uvBinding, 2, GL_FLOAT, GL_FALSE, 0, NULL);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);

        glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, NULL);

        glDisableVertexAttribArray(positionBinding);
        glDisableVertexAttribArray(normalBinding);
        glDisableVertexAttribArray(uvBinding);
GLuint vboIds[2];
glGenBuffers(2, vboIds);

// Load positions.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

// Load texture coordinates.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_DYNAMIC_DRAW);
这个设置是为一个成熟的3D引擎设计的,所以你可以把它调小一点。基本上,我有4个缓冲区,位置、uv、法线和索引。你可能只需要前两个,所以忽略其他的

无论如何,每次我想画一些文本时,我都会使用我显示的第一个代码块上传数据,然后使用第二个代码块来画。它很好用,而且非常优雅。这是我使用它绘制文本的代码:

vbo(genTextMesh("some string")).draw(); //vbo is my mesh containing class

如果您有任何问题,请随意提问。

如果您需要经常修改纹理坐标,但其他顶点属性保持不变,则将纹理坐标保留在单独的VBO中可能会有所帮助。虽然通常最好使用交错属性,但这并不一定是最有效的解决方案

因此,您将有两个VBO,一个用于位置,一个用于纹理坐标。您的设置代码如下所示:

            glBindBuffer(GL_ARRAY_BUFFER, position);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.position.size(), &data.position[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, normal);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * data.normal.size(), &data.normal[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ARRAY_BUFFER, uv);
            glBufferData(GL_ARRAY_BUFFER, sizeof(vec2) * data.uv.size(), &data.uv[0], GL_DYNAMIC_DRAW);

            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
            glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * data.index.size(), &data.index[0], GL_DYNAMIC_DRAW);
        glEnableVertexAttribArray(positionBinding);
        glBindBuffer(GL_ARRAY_BUFFER, position);
        glVertexAttribPointer(positionBinding, 3, GL_FLOAT, GL_FALSE, 0, NULL);

        glEnableVertexAttribArray(normalBinding);
        glBindBuffer(GL_ARRAY_BUFFER, normal);
        glVertexAttribPointer(normalBinding, 3, GL_FLOAT, GL_TRUE, 0, NULL);

        glEnableVertexAttribArray(uvBinding);
        glBindBuffer(GL_ARRAY_BUFFER, uv);
        glVertexAttribPointer(uvBinding, 2, GL_FLOAT, GL_FALSE, 0, NULL);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);

        glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, NULL);

        glDisableVertexAttribArray(positionBinding);
        glDisableVertexAttribArray(normalBinding);
        glDisableVertexAttribArray(uvBinding);
GLuint vboIds[2];
glGenBuffers(2, vboIds);

// Load positions.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

// Load texture coordinates.
glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_DYNAMIC_DRAW);
请注意
glBufferData()
的不同最后一个参数,这是一个用法提示
GL\u STATIC\u DRAW
建议OpenGL实现不会定期修改数据,而
GL\u DYNAMIC\u DRAW
建议经常修改数据

然后,只要纹理数据发生更改,就可以使用
glBufferSubData()
对其进行修改:

当然,如果其中只有一部分发生了变化,那么您只会对发生变化的部分进行调用

您没有指定纹理坐标的确切变化方式。如果只是简单的变换,那么在着色器代码中应用该变换将比修改原始纹理坐标更有效

例如,假设您只想移动纹理坐标。可以为顶点着色器中的偏移使用统一变量,然后将其添加到传入纹理坐标属性:

uniform vec2 TexCoordShift;
in vec2 TexCoord;
out vec2 FragTexCoord;
...
    FragTexCoord = TexCoord + TexCoordShift;

然后在C++代码中:

// Once during setup, after linking program.
TexCoordShiftLoc = glGetUniformLocation(program, "TexCoordShift");

// To change transformation, after glUseProgram(), before glDraw*().
glUniform2f(TexCoordShiftLoc, xShift, yShift);

我使用统一的
vec2
将纹理偏移传递到顶点着色器中

我不知道这有多有效,但是如果你的纹理坐标是相同的形状,并且只是四处移动,那么这是一个选项

#version 150

uniform mat4 mvp;
uniform vec2 texOffset;

in vec2 position;
in vec2 texcoord;

out vec2 Texcoord;


void main() {
    Texcoord = texcoord + texOffset;
    gl_Position =  mvp * vec4(position, 0.0, 1.0) ;
}

创建一个函数以生成UV坐标设置在正确位置的网格。这不是在公园里散步,但也不太难。@BWG我不太清楚“UV坐标设置在正确的位置”是什么意思。为了澄清,我最初尝试渲染字母/数字,但我使用纹理图集通过更改纹理坐标来更改字母/数字。当你说“像这样链接着色器和数据”时,你不应该这样做。只需设置一次着色器,但每次绘制新角色时都需要更新网格的数据。或者你可以将着色器传递给你的整数,并在那里生成纹理坐标。@BWG对了,我明白了,谢谢!这是否意味着我必须将变量类型更改为类似布局限定符的类型?我个人使用布局限定符,但我使用的是OpenGL 3.3。我会给你写一个更深入的回答。现在已经很晚了,所以我要睡觉了。我明天要试试看。谢谢你的努力。我的错我没有提到,但事实确实如此。你介意教我怎么翻译吗?我猜是偏移量的另一个着色器变量,但除了上面的方法之外,我不知道在需要更改时如何更改它。我在答案的末尾添加了。