在OpenGL ES 2.0中透视梯形的正确纹理 [英] Perspective correct texturing of trapezoid in OpenGL ES 2.0

查看:213
本文介绍了在OpenGL ES 2.0中透视梯形的正确纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我绘制了一个纹理梯形,但是结果却没有达到我的预期.

I have drawn a textured trapezoid, however the result does not appear as I had intended.

不连续性不是出现为单个完整的四边形,而是在对角线上出现了不连续性,该对角线的两个三角形组成相交.

Instead of appearing as a single unbroken quadrilateral, a discontinuity occurs at the diagonal line where its two comprising triangles meet.

此图演示了该问题:

(请注意:最后一张图片并不是要100%忠实地表示,但是应该可以理解这一点.)

This illustration demonstrates the issue:

(Note: the last image is not intended to be a 100% faithful representation, but it should get the point across.)

梯形是在OpenGL ES 2.0(在iPhone上)中使用GL_TRIANGLE_STRIP绘制的.它是完全面向屏幕绘制的,并且没有倾斜(即您看到的不是3D草图!)

The trapezoid is being drawn using GL_TRIANGLE_STRIP in OpenGL ES 2.0 (on an iPhone). It's being drawn completely facing the screen, and is not being tilted (i.e. that's not a 3D sketch you're seeing!)

我已经了解到我大概需要在我的顶点和/或片段着色器中执行透视校正",但是我不清楚如何执行此操作.

I have come to understand that I need to perform "perspective correction," presumably in my vertex and/or fragment shaders, but I am unclear how to do this.

我的代码包括一些简单的模型/视图/投影"矩阵数学运算,但是目前它们都不影响我的纹理坐标值. 更新:根据用户实际的评论,上一条陈述是不正确的.

My code includes some simple Model/View/Projection matrix math, but none of it currently influences my texture coordinate values. Update: The previous statement is incorrect, according to comment by user infact.

此外,我在ES 2.0规范中发现了这个花絮,但不了解其含义:

Furthermore, I have found this tidbit in the ES 2.0 spec, but do not understand what it means:

由于 OpenGL,不支持PERSPECTIVE CORRECTION HINT ES 2.0要求对所有属性进行透视插值.

The PERSPECTIVE CORRECTION HINT is not supported because OpenGL ES 2.0 requires that all attributes be perspectively interpolated.

如何正确绘制纹理?

在下面添加了代码:

// Vertex shader
attribute vec4 position;
attribute vec2 textureCoordinate;

varying vec2 texCoord;

uniform mat4 modelViewProjectionMatrix;

void main()
{
    gl_Position = modelViewProjectionMatrix * position;
    texCoord = textureCoordinate;
}


// Fragment shader
uniform sampler2D texture;
varying mediump vec2 texCoord;

void main()
{
    gl_FragColor = texture2D(texture, texCoord);
}


// Update and Drawing code (uses GLKit helpers from iOS)

- (void)update
{
    float fov = GLKMathDegreesToRadians(65.0f);
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    projectionMatrix = GLKMatrix4MakePerspective(fov, aspect, 0.1f, 50.0f);
    viewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); // zoom out
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(shaders[SHADER_DEFAULT]);

    GLKMatrix4 modelMatrix = GLKMatrix4MakeScale(0.795, 0.795, 0.795); // arbitrary scale

    GLKMatrix4 modelViewMatrix = GLKMatrix4Multiply(viewMatrix, modelMatrix);

    GLKMatrix4 modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, GL_FALSE, modelViewProjectionMatrix.m);

    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_WALLS]);
    glUniform1i(uniforms[UNIFORM_TEXTURE], 0);

    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, wall.vertexArray);
    glVertexAttribPointer(ATTRIB_TEXTURE_COORDINATE, 2, GL_FLOAT, GL_FALSE, 0, wall.texCoords);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, wall.vertexCount);

}

推荐答案

(我在这里打个平角,因为您的图片没有完全显示出我对梯形纹理的期望,所以也许还有其他东西在您的情况下发生-但普遍存在的问题是众所周知的)

(I'm taking a bit of a punt here, because your picture does not show exactly what I would expect from texturing a trapezoid, so perhaps something else is happening in your case - but the general problem is well known)

纹理(默认情况下)不会在梯形上正确插值.将该形状进行三角剖分以进行绘制时,将选择对角线之一作为边缘,而该边缘笔直穿过纹理的中间,而不是穿过梯形的中间(请参见沿对角线划分的形状-这两个三角形几乎不相等.

Textures will not (by default) interpolate correctly across a trapezoid. When the shape is triangulated for drawing, one of the diagonals will be chosen as an edge, and while that edge is straight through the middle of the texture, it is not through the middle of the trapezoid (picture the shape divided along a diagonal - the two triangles are very much not equal).

您需要提供2D以上的纹理坐标才能完成此工作-您需要提供3D(或更确切地说,投影的)纹理坐标,并在片段着色器中进行透视划分,后插值(或其他方法)纹理查找功能,将执行相同的操作.)

You need to provide more than a 2D texture coordinate to make this work - you need to provide a 3D (or rather, projective) texture coordinate, and perform the perspective divide in the fragment shader, post-interpolation (or else use a texture lookup function which will do the same).

以下内容显示了如何使用老式的GL功能(梯形图为演示目的而易于阅读)为梯形提供纹理坐标.注释掉的线是2d纹理坐标,我已将其替换为投影坐标以获得正确的插值.

The following shows how to provide texture coordinates for a trapezoid using old-school GL functions (which are a little easier to read for demonstration purposes). The commented-out lines are the 2d texture coordinates, which I have replaced with projective coordinates to get the correct interpolation.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,640,0,480,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

const float trap_wide = 600;
const float trap_narrow = 300;
const float mid = 320;

glBegin(GL_TRIANGLE_STRIP);
glColor3f(1,1,1);

//  glTexCoord4f(0,0,0,1);
glTexCoord4f(0,0,0,trap_wide);
glVertex3f(mid - trap_wide/2,10,-10);

//  glTexCoord4f(1,0,0,1);
glTexCoord4f(trap_narrow,0,0,trap_narrow);
glVertex3f(mid - trap_narrow/2,470,-10);

//  glTexCoord4f(0,1,0,1);
glTexCoord4f(0,trap_wide,0,trap_wide);
glVertex3f(mid + trap_wide/2,10,-10);

//  glTexCoord4f(1,1,0,1);
glTexCoord4f(trap_narrow,trap_narrow,0,trap_narrow);
glVertex3f(mid + trap_narrow/2,470,-10);

glEnd();

此处未使用第三个坐标,因为我们仅使用2D纹理.插值后,第四个坐标将除以另外两个坐标,从而提供投影.显然,如果在顶点处进行分割,则会看到原始的纹理坐标.

The third coordinate is unused here as we're just using a 2D texture. The fourth coordinate will divide the other two after interpolation, providing the projection. Obviously if you divide it through at the vertices, you'll see you get the original texture coordinates.

这是两个渲染图的样子:

Here's what the two renderings look like:

如果梯形实际上是变换四边形的结果,那么使用GL绘制该四边形可能会更容易/更好,而不是通过软件对其进行变换并将2D形状输入到GL中.

If your trapezoid is actually the result of transforming a quad, it might be easier/better to just draw that quad using GL, rather than transforming it in software and feeding 2D shapes to GL...

这篇关于在OpenGL ES 2.0中透视梯形的正确纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆