【问题标题】:qt opengl shader texture coordinatesqt opengl 着色器纹理坐标
【发布时间】:2016-01-10 18:38:51
【问题描述】:

我使用 OpenGL 着色器对图像应用中值过滤器。我复制到 in_fbo 缓冲区的输入图像。一切正常。

QGLFramebufferObject *in_fbo, *out_fbo;
painter.begin(in_fbo); //Copy QImage to  QGLFramebufferObject
painter.drawImage(0,0,image_in,0,0,width,height);
painter.end();

out_fbo->bind();
glViewport( 0, 0, nWidth, nHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho( 0.0, nWidth, 0.0, nHeight, -1.0, 1.0 );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );

glEnable( GL_TEXTURE_2D );

out_fbo->drawTexture( QPointF(0.0,0.0), in_fbo->texture( ), GL_TEXTURE_2D );

但在着色器代码中,我需要将顶点的位置除以图像的宽度和高度,因为纹理坐标被标准化为 0 到 1 之间的范围。

如何正确计算纹理坐标?

//vertex shader
varying vec2 pos;
void main( void )
{
    pos = gl_Vertex.xy;
    gl_Position = ftransform( );
}
//fragment shader
#extension GL_ARB_texture_rectangle : enable

uniform sampler2D texture0;
uniform int imgWidth;
uniform int imgHeight;
uniform int len;
varying vec2 pos;

#define MAX_LEN (100)

void main(){
    float v[ MAX_LEN ];

    for (int i = 0; i < len; i++) {
         vec2 posi = pos + float(i);
         posi.x = posi.x / float( imgWidth );
         posi.y = posi.y / float( imgHeight );
         v[i] = texture2D(texture0, posi).r;
    }
    //
    //.... Calculating new value
    //

    gl_FragColor = vec4( m, m, m, 1.0 );
}

在我使用 OpenFrameworks 之前。但是 OF 中的纹理着色器不适用于 Qt 中的纹理。我想是因为 OF​​ 使用 textureTarget = GL_TEXTURE_RECTANGLE_ARB 创建纹理。现在上面应用着色器的结果是不正确的。它与旧着色器的结果不同(很少有不同颜色的像素)。我不知道如何修改上面的着色器:(。

旧着色器:

//vertex
#version 120
#extension GL_ARB_texture_rectangle : enable

void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_FrontColor = gl_Color;
}


//fragment
#version 120
#extension GL_ARB_texture_rectangle : enable

uniform sampler2D texture0;
uniform int len; 

void main(){
    vec2 pos = gl_TexCoord[0].xy;

    pos.x = int( pos.x );       
    pos.y = int( pos.y );

    float v[ MAX_LEN ];

    for (int i=0; i<len; i++) {
        vec2 posi = pos +  i;       
        posi.x = int( posi.x + 0.5 ) + 0.5;
        posi.y = int( posi.y + 0.5 ) + 0.5;
        v[i] = texture2D(texture0, posi).r;
    }
    //
    //.... Calculating new value
    //       
    gl_FragColor = vec4( m, m, m, 1.0 );
}

OpenFrameworks 库中的 OpenGL 代码

texData.width = w;
texData.height = h;

texData.tex_w = w;
texData.tex_h = h;
texData.textureTarget = GL_TEXTURE_RECTANGLE_ARB;

texData.bFlipTexture = true;
texData.glType = GL_RGBA;

// create & setup FBO
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

// Create the render buffer for depth
glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, texData.tex_w, texData.tex_h);

// create & setup texture
glGenTextures(1, (GLuint *)(&texData.textureID));   // could be more then one, but for now, just one
glBindTexture(texData.textureTarget, (GLuint)(texData.textureID));
glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(texData.textureTarget, 0, texData.glType, texData.tex_w, texData.tex_h, 0, texData.glType, GL_UNSIGNED_BYTE, 0);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

// attach it to the FBO so we can render to it
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, texData.textureTarget, (GLuint)texData.textureID, 0);

【问题讨论】:

    标签: qt opengl shader


    【解决方案1】:

    我认为您实际上并不想使用纹理的尺寸来执行此操作。从事物的声音来看,这是一个简单的全屏图像过滤器,您实际上只是希望将片段坐标映射到范围 [0.0,1.0] 中。如果是这种情况,那么gl_FragCoord.xy / viewport.xy,其中视口是定义视口宽度和高度的 2D 制服,应该适用于您的纹理坐标(在片段着色器中)。

    vec2 texCoord = vec2 (transformed_pos.x, transformed_pos.y) / transformed_pos.w * vec2 (0.5, 0.5) + vec2 (1.0, 1.0) 也可以使用相同的原理工作——剪辑空间坐标转换为 NDC,然后映射到纹理空间。这种方法不能正确考虑纹素中心((0.5, 0.5) 而不是(0.0, 0.0)),但是当启用纹理过滤并且包裹模式不是GL_CLAMP_TO_EDGE 时会出现问题。

    【讨论】:

    • 感谢您的回答,gl_FragCoord.xy / viewport.xy 与 pos.x = pos.x / imgWidth 相同 :) 我更新我的问题...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 2020-03-03
    相关资源
    最近更新 更多