OpenGL:动态改变纹理坐标

use*_*904 6 c++ opengl shader rendering opengl-es

我目前正在尝试使用位图渲染整数的值(考虑入侵者的记分板),但是在游戏运行时我无法更改纹理坐标.

我链接着色器和数据,如下所示:

GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(float), (void*)(2 * sizeof(float)));
Run Code Online (Sandbox Code Playgroud)

在我的着色器中,我执行以下操作:顶点着色器:

#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) ;
}
Run Code Online (Sandbox Code Playgroud)

FragmentShader:

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

uniform sampler2D tex;
void main() {
    outColor = texture2D(tex, Texcoord);
}
Run Code Online (Sandbox Code Playgroud)

如何更改此代码/实现一个能够更改texcoord变量的函数?

Ret*_*adi 6

如果需要频繁修改纹理坐标,但其他顶点属性保持不变,将纹理坐标保持在单独的VBO中会很有用.虽然通常最好使用交错属性,但这种情况并不一定是最有效的解决方案.

所以你会有两个VBO,一个用于位置,一个用于纹理坐标.您的设置代码如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

注意不同的最后一个参数glBufferData(),这是一个用法提示.GL_STATIC_DRAW建议OpenGL实现不会定期修改数据,同时GL_DYNAMIC_DRAW建议经常修改数据.

然后,只要您的纹理数据发生变化,您就可以使用以下方法修改它glBufferSubData():

glBindBuffer(GL_ARRAY_BUFFER, vboIds[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texCoords), texCoords);
Run Code Online (Sandbox Code Playgroud)

当然,如果只有部分内容发生变化,那么您只需要调用更改的部分.

您没有指定纹理坐标的精确变化.如果它只是一个简单的变换,那么在着色器代码中应用该变换会更有效,而不是修改原始纹理坐标.

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

uniform vec2 TexCoordShift;
in vec2 TexCoord;
out vec2 FragTexCoord;
...
    FragTexCoord = TexCoord + TexCoordShift;
Run Code Online (Sandbox Code Playgroud)

然后在你的C++代码中:

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

// To change transformation, after glUseProgram(), before glDraw*().
glUniform2f(TexCoordShiftLoc, xShift, yShift);
Run Code Online (Sandbox Code Playgroud)