在OpenGL ES 2.0梯形的透视正确纹理(Perspective correct textur

2019-07-21 02:27发布

我得出一个纹理梯形,不过我本来打算结果不会出现。

代替显示为一个单一的完整的四边形的,不连续发生在其中它的两个三角形,其包括满足所述对角线。

该图演示了问题:

(注:最后的图像不打算成为一个100%的忠实代表,但它应该传达出点)。

梯形正在使用吸入GL_TRIANGLE_STRIP在OpenGL ES 2.0(在iPhone)。 这是正在制定完全对着屏幕,并没有倾斜(即这不是一个3D草图你看到的!)

我已经明白,我需要进行“透视校正”,想必在我的顶点和/或片段着色器,但我不清楚如何做到这一点。

我的代码包含了一些简单的模型/视图/投影矩阵数学,但没有它目前影响我的纹理坐标值。 更新:以前的说法是不正确,根据用户INFACT发表评论。

此外,我发现这个珍闻在ES 2.0规范,但不明白这是什么意思:

不支持透视校正提示,因为OpenGL ES 2.0的要求,所有的属性来透视插值。

我怎样才能让纹理正确绘制?


编辑:下面添加的代码:

// 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);

}

Answer 1:

(我正在一点平底船在这里,因为你的图片没有显示正是我所期待的纹理呈梯形,因此,或许别的东西,你的情况正在发生 - 但总的问题是众所周知的)

纹理不会(默认)正确地插穿过梯形。 当形状是三角为图中,对角线中的一个将被选择作为边缘,并且当该边缘是直的通过纹理的中间,它不是通过梯形的中间(图像形状沿着对角线分割 - 两个三角形都非常不相等)。

您需要提供超过2D纹理坐标,使这项工作 - 你需要提供3D(或者更确切地说,投影)纹理坐标,并在片段着色器,后插值进行透视分割(或者使用一个纹理查找功能,也将这样做)。

下面介绍如何提供纹理坐标使用老派GL功能(这是一个小更易于读取,演示)梯形。 被注释掉的线是2D纹理坐标,这是我与投影坐标替换,以获得正确的插值。

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纹理。 第四坐标将分另两个内插后,设置突起。 显然,如果你在顶点划分事情的经过,你会看到你的原始纹理坐标。

下面是两个效果图如下所示:

如果您的梯形实际上是转化四的结果,可能更容易/最好只画使用GL是四,而不是软件转化和饲养2D形状GL ...



Answer 2:

你试图在这里是歪斜的质感。 样品片段着色器如下:

precision mediump float;
varying vec4 vtexCoords;
uniform sampler2D sampler;

void main()
{
   gl_FragColor = texture2DProj(sampler,vtexCoords);
}

两件事情看起来应该是不同的:

1)我们使用varying vec4 vtexCoords; 。 纹理坐标是4维的。 2) texture2DProj()被用于代替texture2D()

根据您的梯形要分配的纹理坐标大大小小的边长。 以下网址可以帮助: http://www.xyzw.us/~cass/qcoord/



Answer 3:

该接受的答案给出了正确的答案和解释,但对于那些寻找了OpenGL(ES)2.0管道多一点帮助...

const GLfloat L = 2.0;
const GLfloat Z = -2.0;
const GLfloat W0 = 0.01;
const GLfloat W1 = 0.10;

/** Trapezoid shape as two triangles. */
static const GLKVector3 VERTEX_DATA[] = {
    {{-W0,    0,  Z}},
    {{+W0,    0,  Z}},
    {{-W1,    L,  Z}},

    {{+W0,    0,  Z}},
    {{+W1,    L,  Z}},
    {{-W1,    L,  Z}},
};

/** Add a 3rd coord to your texture data.  This is the perspective divisor needed in frag shader */
static const GLKVector3 TEXTURE_DATA[] = {
    {{0, 0, 0}},
    {{W0, 0, W0}},
    {{0, W1, W1}},

    {{W0, 0, W0}},
    {{W1, W1, W1}},
    {{0, W1, W1}},
};

////////////////////////////////////////////////////////////////////////////////////

// frag.glsl

varying vec3 v_texPos;
uniform sampler2D u_texture;

void main(void) 
{
    // Divide the 2D texture coords by the third projection divisor
    gl_FragColor = texture2D(u_texture, v_texPos.st / v_texPos.p);
}

另外,在着色器,按@ maverick9888的回答,您可以使用texture2Dproj虽然适用于iOS / OpenGLES2它仍然只支持vec3输入...

void main(void) 
{
    gl_FragColor = texture2DProj(u_texture, v_texPos);
}

我真的没有基准它正常,但我非常简单的例子(一维纹理真的)分割的版本似乎有点迅捷。



文章来源: Perspective correct texturing of trapezoid in OpenGL ES 2.0