在OpenGL中渲染精灵时的附加精灵UV

时间:2017-10-23 07:00:14

标签: c++ opengl glsl sprite

我在OpenGL的地图集渲染中精确地使用下面的代码。我的问题来自于尝试为样本添加辅助“纹理”,因此我可以做一些多纹理魔术。问题我认为第二个精灵也在一个地图集中,并且受到VAO偏移的影响所以我无法选择正确的UV来获得我需要的确切点。我已经尝试添加一些计算来对其他纹理内的精灵进行逆向工程(你可以看到我在底部的尝试),但这似乎不起作用。这样做的最佳方法是什么?

的制备:将

glm::vec4 fRect;

fRect.x = static_cast<float>(iRect.x) / textureWidth;
fRect.y = static_cast<float>(iRect.y) / textureHeight;
fRect.z = (static_cast<float>(iRect.z) / textureWidth) + fRect.x;
fRect.w = (static_cast<float>(iRect.w) / textureHeight) + fRect.y;

// Configure VAO/VBO
GLuint VBO;
GLfloat vertices[] = {
    // Pos      // Tex
    0.0f, 1.0f, fRect.x, fRect.w,
    1.0f, 0.0f, fRect.z, fRect.y,
    0.0f, 0.0f, fRect.x, fRect.y,
    0.0f, 1.0f, fRect.x, fRect.w,
    1.0f, 1.0f, fRect.z, fRect.w,
    1.0f, 0.0f, fRect.z, fRect.y
};

GLuint VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

渲染:

// Prepare transformations
glm::mat4 modelMatrix;
modelMatrix = glm::translate(modelMatrix, position);
// modelMatrix = glm::translate(modelMatrix, -glm::vec3(spriteOffset.x, spriteOffset.y, 0.0f));
modelMatrix = glm::rotate(modelMatrix, rotate.x, glm::vec3(1.0f, 0.0f, 0.0f));
// modelMatrix = glm::rotate(modelMatrix, rotate.y, glm::vec3(0.0f, 1.0f, 0.0f));
modelMatrix = glm::rotate(modelMatrix, rotate.z, glm::vec3(0.0f, 0.0f, 1.0f));
modelMatrix = glm::translate(modelMatrix, glm::vec3(-spriteOffset.x, -spriteOffset.y, 0.0f));
modelMatrix = glm::scale(modelMatrix, glm::vec3(size, 1.0f));
//(...)
glUniformMatrix4fv(modelMatrixLocation, 1, false, glm::value_ptr( modelMatrix ) );
glUniformMatrix4fv(viewMatrixLocation, 1, false, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projectionMatrixLocation, 1, false, glm::value_ptr(projectionMatrix));
ASSERT( !HasOpenGLErrors(), "OpenGL error!" );

glUniform3f(multColorLocation, multColour.x, multColour.y, multColour.z );
glUniform3f(addColorLocation, addColour.x, addColour.y, addColour.z );
ASSERT( !HasOpenGLErrors(), "OpenGL error!" );
// Bind Texture, etc
glDrawArrays(GL_TRIANGLES, 0, 6);

顶点着色器:

#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>

out vec2 TexCoords;

uniform mat4 model_matrix, view_matrix, projection_matrix;

void main()
{
    TexCoords = vec2(vertex.z, 1.0 - vertex.w);
    gl_Position = projection_matrix*view_matrix*model_matrix*vec4(vertex.xyz,1);
}

片段着色器:

#version 330 core
in vec2 TexCoords;
out vec4 color;

uniform sampler2D texture;
uniform vec3 multColour;
uniform vec3 addColour;

void main()
{
    vec4 minColour = vec4(0.0, 0.0, 0.0, 0.0);
    vec4 maxColour = vec4(1.0, 1.0, 1.0, 1.0);
    vec4 texColour = texture(texture, TexCoords);
    if(texColour.a < 0.01)
        discard;
    color = clamp(vec4(multColour, 1.0) * texColour + vec4(addColour,0.0), minColour, maxColour);
}

尝试在片段着色器中读取正确的UV时失败:

float normU = (TexCoords.x - currUVs.x) / (currUVs.z - currUVs.x);
float icU = mix(icUVs.x, icUVs.z, normU);
float normV = (TexCoords.y - currUVs.y) / (currUVs.w - currUVs.y);
float icV = mix(icUVs.y, icUVs.w, normV);

vec2 UV = vec2(icU, icV );
vec4 initial = texture(initialColor, UV);

其中currUVs是上面VAO中传递的fRect的值,而icUVs是atlas纹理中第二个精灵的UV边界(最小值和最大值)。 / p>

到目前为止,似乎所有没有应用偏移的精灵都会正确渲染,但如果我将任何类型的spriteOffset传入渲染,那么它将呈现错误。

我该如何解决这个问题?有没有办法在着色器中应用VAO rects然后才能正确获得第二个精灵?

0 个答案:

没有答案