在openGL中绘制一个纹理的一部分在一个三角形的

时间:2013-02-04 02:51:54

标签: opengl geometry drawing textures

我正在尝试在三角形上绘制部分纹理。三角形由3个点定义。其中一个点将始终是图像的中心。现在我想在该三角形上绘制一部分纹理。因此,三角形将切出图像的那一部分并将其绘制在自身上。但我不希望在绘制时纹理缩放。它必须保持不变。即使三角形的基点落在图像之外。图像无法缩放。我不明白如何做到这一点。每当我使用纹理时,图像会被缩放或绘制多次。

这是一张图片:所以红色三角形的绘制方式与openGL中的完全相同。

enter image description here

1 个答案:

答案 0 :(得分:0)

在片段着色器中,检查s&您的texcoord和t上的discard值,如果小于零或大于一。

编辑:示例:

// g++ main.cpp -o main -lglut -lGLEW
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include <iostream>

using namespace std;

void CheckStatus( GLuint obj )
{
    GLint status = GL_FALSE, len = 10;
    if( glIsShader(obj) )   glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
    if( glIsProgram(obj) )  glGetProgramiv( obj, GL_LINK_STATUS, &status );
    if( status == GL_TRUE ) return;
    if( glIsShader(obj) )   glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
    if( glIsProgram(obj) )  glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
    vector< char > log( len, 'X' );
    if( glIsShader(obj) )   glGetShaderInfoLog( obj, len, NULL, &log[0] );
    if( glIsProgram(obj) )  glGetProgramInfoLog( obj, len, NULL, &log[0] );
    cerr << &log[0] << endl;
    exit( -1 );
}

GLuint LoadShader( GLenum type, const char* src )
{
    GLuint shader = glCreateShader( type );
    glShaderSource( shader, 1, &src, NULL );
    glCompileShader( shader );
    CheckStatus( shader );
    return shader;
}

GLuint LoadProgram( const char* vert, const char* geom, const char* frag )
{
    GLuint program = glCreateProgram();
    if( vert ) glAttachShader( program, LoadShader( GL_VERTEX_SHADER, vert ) );
    if( geom ) glAttachShader( program, LoadShader( GL_GEOMETRY_SHADER, geom ) );
    if( frag ) glAttachShader( program, LoadShader( GL_FRAGMENT_SHADER, frag ) );
    glLinkProgram( program );
    CheckStatus( program );
    return program;
}

#define GLSL(version, shader) "#version " #version "\n" #shader

const GLchar* vert = GLSL
(
    120,
    void main()
    {
        gl_TexCoord[0] = gl_MultiTexCoord0;
        gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    }
);

const GLchar* frag = GLSL
(
    120,
    uniform sampler2D texture;
    void main()
    {
        if( any( lessThan( gl_TexCoord[0].st, vec2( 0.0, 0.0 ) ) ) || 
            any( greaterThan( gl_TexCoord[0].st, vec2( 1.0, 1.0 ) ) ) )
        {
            gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
            //discard;
        }
        else
        {
            gl_FragColor = texture2D( texture, gl_TexCoord[0].st );
        }
    }
);

GLuint prog = 0;
GLuint tex = 0;
void init()
{
    prog = LoadProgram( vert, NULL, frag );

    unsigned char bits[ 32 * 32 * 4 ];
    for( unsigned int i = 0; i < 32*32; ++i )
    {
        bits[i*4 + 0] = rand() % 255;
        bits[i*4 + 1] = rand() % 255;
        bits[i*4 + 2] = rand() % 255;
        bits[i*4 + 3] = 255;
    }

    glGenTextures( 1, &tex );
    glBindTexture( GL_TEXTURE_2D, tex );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 
    glTexImage2D( GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits );
}

void display()
{
    glClear( GL_COLOR_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    double ar = w / h;
    glOrtho( -3 * ar, 3 * ar, -3, 3, -1, 1);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glUseProgram( prog );
    glUniform1i( glGetUniformLocation( prog, "texture" ), 0 );    
    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, tex );

    glBegin( GL_TRIANGLES );
    glTexCoord2f( 0.5, 0.5 );
    glVertex2f( 0, 0 );
    glTexCoord2f( 1.5, 0.5 );
    glVertex2f( 2, 0 );
    glTexCoord2f( 0.5, 1.5 );
    glVertex2f( 0, 2 );
    glEnd();

    glutSwapBuffers();
}

int main(int argc, char** argv)
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
    glutInitWindowSize( 640,480 );
    glutCreateWindow( "test" );
    glutDisplayFunc( display );
    glewInit();
    init();
    glutMainLoop();
    return 0;
}