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

查看:36
本文介绍了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.

我的代码包含一些简单的模型/视图/投影矩阵数学,但目前它们都不会影响我的纹理坐标值.更新:根据用户infact的评论,之前的说法是不正确的.

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:

不支持透视校正提示,因为 OpenGLES 2.0 要求对所有属性进行透视插值.

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

如何才能正确绘制纹理?

How can I make the texture draw correctly?

添加以下代码:

// 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天全站免登陆