顶点/片段着色器中的坐标

时间:2013-12-06 15:32:22

标签: opengl opengl-es fragment-shader vertex-shader

我想在网格的每个实例上执行逐像素操作。我发现了一个名为gl_FragCoord的变量,但似乎它的坐标是SCREEN坐标。我想访问LOCAL坐标,以便我可以进行独立影响每个网格的更改。我想有坐标,例如(0.0,0.0)坐标是片段的左上角,(1.0,1.0)是右下角的坐标。

3 个答案:

答案 0 :(得分:1)

您可以将视口作为制服传递,并通过视口W划分您的frag coord X,并通过视口H划分Y frag coord

答案 1 :(得分:0)

使用barycentric coordinates和其他顶点属性构建三角形局部坐标系:

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <vector>
using namespace std;

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp> 
#include <glm/gtx/transform.hpp>
using namespace glm;

void CheckStatus( GLuint obj )
{
    GLint status = GL_FALSE;
    if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
    if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
    if( status == GL_TRUE ) return;
    GLchar log[ 1 << 16 ] = { 0 };
    if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
    if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
    std::cerr << log << std::endl;
    exit( -1 );
}

void AttachShader( GLuint program, GLenum type, const char* src )
{
    GLuint shader = glCreateShader( type );
    glShaderSource( shader, 1, &src, NULL );
    glCompileShader( shader );
    CheckStatus( shader );
    glAttachShader( program, shader );
    glDeleteShader( shader );
}

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

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

const char* vert = GLSL
(
    120,
    uniform mat4 u_projection;
    uniform mat4 u_modelview;

    attribute vec3 a_pos;
    attribute vec3 a_bc;

    varying vec3 v_bc;

    void main()
    {
        v_bc = a_bc;
        gl_Position = u_projection * u_modelview * vec4( a_pos, 1.0 );
    }
);

const char* frag = GLSL
(
    120,
    varying vec3 v_bc;
    void main()
    {
        gl_FragColor = vec4( v_bc, 1.0 );
    }
);

struct Vertex
{
    Vertex( const vec3& pos, const vec3& bc )
        : pos( pos )
        , bc( bc )
    {}
    vec3 pos;
    vec3 bc;
};

void AddTriangle( const vec3& p1, const vec3& p2, const vec3& p3, vector< Vertex >& verts )
{
    verts.push_back( Vertex( p1, vec3( 1, 0, 0 ) ) );
    verts.push_back( Vertex( p2, vec3( 0, 1, 0 ) ) );
    verts.push_back( Vertex( p3, vec3( 0, 0, 1 ) ) );
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    double ar = w / h;
    mat4 projection = glm::ortho< float >( -2 * ar, 2 * ar, -2.0, 2.0, -1.0, 1.0 );

    mat4 modelview = mat4( 1.0 );

    // prepare to render
    static GLuint prog = LoadProgram( vert, NULL, frag );
    glUseProgram( prog );

    GLint proj = glGetUniformLocation( prog, "u_projection" );
    glUniformMatrix4fv( proj, 1, GL_FALSE, glm::value_ptr( projection ) );

    GLint model = glGetUniformLocation( prog, "u_modelview" );
    glUniformMatrix4fv( model, 1, GL_FALSE, glm::value_ptr( modelview) );

    vector< Vertex > verts;
    AddTriangle
        (
        vec3( 0, 0, 0 ),
        vec3( 1, 0, 0 ),
        vec3( 1, 1, 0 ),
        verts
        );

    GLint pos = glGetAttribLocation( prog, "a_pos" );
    glVertexAttribPointer( pos, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), &verts[0].pos );
    glEnableVertexAttribArray( pos );

    GLint bc = glGetAttribLocation( prog, "a_bc" );
    glVertexAttribPointer( bc, 3, GL_FLOAT, GL_FALSE, sizeof( Vertex ), &verts[0].bc );
    glEnableVertexAttribArray( bc );

    glDrawArrays( GL_TRIANGLES, 0, verts.size() );

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    glutInit( &argc, argv );
    glutSetOption( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 600, 600 );
    glutCreateWindow( "GLUT" );
    glewInit();

    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}

如果v_bc == (1,0,0),则您的片段位于第一个顶点。

如果v_bc == (0,1,0),则您的片段位于第二个顶点。

如果v_bc == (0,0,1),则您的片段位于第三个顶点。

答案 2 :(得分:0)

感谢您的支持和想法,我需要的是通过顶点着色器将顶点的LOCAL位置传递给片段着色器。我们可以在没有任何额外计算的情况下完成它,因为它是顶点着色器已知的值。我仍然没有在开始时我想要的东西,但现在我知道如何使用片段着色器来做我想要的效果:)。