3

我正在尝试使用着色器运行程序。在我提出的另一个问题中,我发现我正在将固定管道功能与较新的东西(来自 OpenGL 2.0)混合,所以我试图删除所有像 glMatrixMode 这样的“旧东西”,但我不确定我是否正确地做。毫无疑问,我还删除了 glLightfv 之类的调用,如果我使用可编程管道,我不确定它们是否被允许。

这是主要代码:

#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include <vector>
#include "utility.hpp"
#include "program.hpp"

GLfloat width=600, height=800;
Program* program_ref;

void init()
{   
    glewInit();
    Shader vertex_shader= Shader("vertex_shader",GL_VERTEX_SHADER);
    // This just reads the file "vertex_shader", creates the shader and compiles it
    Shader geometry_shader= Shader(); // This means that the shader is empty
    // So the program class will be enough smart to recognize it and don't attach it
    Shader fragment_shader= Shader("fragment_shader",GL_FRAGMENT_SHADER);
    program_ref= new Program(vertex_shader,geometry_shader,fragment_shader);
    // This creates a program, attaches the shaders to it, links and uses it
}

void display()
{
    vector<GLfloat> quad{-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5};
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2,GL_FLOAT,0,quad.data());
    glDrawArrays(GL_QUADS,0,4);
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
    cout << glGetError() << endl;
}

void reshape(int w, int h)
{
    width=w;
    height=h;
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(500,500);
    glutCreateWindow("test");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    init();
    glewInit();
    glutMainLoop();
    return 0;
}

要查看的可选类,在我写的评论中,程序和着色器的行为如何)

着色器.hpp:

#ifndef shader_hpp
#define shader_hpp

#include "utility.hpp"
#include "shader.hpp"
#include <fstream>

#define MAX_SIZE (size_t)1.0e5


class Shader
{
private:
    GLuint id;
    GLenum type;
    bool null;
public:
    Shader()
    {
        id=-1;
        type= -1;
        null= true;
    }
    Shader(const string& filename,GLenum type)
    {
        GLchar* data= new GLchar[MAX_SIZE];
        streamsize count;
        this->type= type;
        ifstream is;
        is.open(filename);
        is.read(data,MAX_SIZE);
        count= is.gcount();
        is.close();
        id=glCreateShader(type);
        glShaderSource(id,1,(const GLchar**)&data,&count);
        glCompileShader(id);
        delete[] data;
        null= false;
    }
    GLuint getId() const
    {
        return id;
    }
    GLenum getType() const
    {
        return type;
    }
    bool isNull() const
    {
        return null;
    }
};

#endif

程序.hpp:

#ifndef program_hpp
#define program_hpp

#include "utility.hpp"
#include "shader.hpp"

class Program
{
private:
    GLuint id;
public:
    Program(const Shader& vertex_shader, const Shader& geometry_shader, const Shader& fragment_shader)
    {
    id= glCreateProgram();
    if(!vertex_shader.isNull())
    {
        glAttachShader(id,vertex_shader.getId());
    }
    if(!geometry_shader.isNull())
    {
        glAttachShader(id,geometry_shader.getId());
    }
    if(!fragment_shader.isNull())
    {
        glAttachShader(id,fragment_shader.getId());
    }
    glLinkProgram(id);
    glUseProgram(id);
    }
    GLuint getId()
    {
    return id;
    }
};

#endif

当使用glew编译着色器并将它们附加到程序时,有两个类只是为了简化一切。

问题如下:如果我只附加顶点着色器而不是片段着色器,一切都很好,我看到用正确的颜色绘制的四边形(红色,因为在下面的顶点着色器中我将颜色设置为红色) . 相反,如果我还附加了片段着色器,我会看到四边形是白色的。我也试着看看哪里不对,我打印了 glGetError() 的结果。如果我包含片段着色器,我会收到错误 1282,如果我不包含它,我不会收到任何错误 (0)。

顶点着色器:

void main()
{
    gl_Position    = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_FrontColor  = vec4(1,0,0,1);
    // The only relevant thing I do is to set the color to red
    // I see the quad red if I attach only the vertex shader and not the fragment shader
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

片段着色器:

void main()
{
    gl_fragColor= gl_Color;
}
4

1 回答 1

5

试一试:

#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_Position    = gl_ModelViewProjectionMatrix * gl_Vertex;
        gl_FrontColor  = vec4(1.0,0.0,0.0,1.0);
        // The only relevant thing I do is to set the color to red
        // I see the quad red if I attach only the vertex shader and not the fragment shader
        gl_TexCoord[0] = gl_MultiTexCoord0;
    }
);

const GLchar* frag = GLSL
(
    120,
    void main()
    {
        gl_FragColor= gl_Color;
    }
);

void display()
{
    glClearColor(0,0,0,0);
    glClear(GL_COLOR_BUFFER_BIT);

    static GLuint prog = LoadProgram( vert, NULL, frag );
    glUseProgram( prog );
    glEnableClientState(GL_VERTEX_ARRAY);
    GLfloat quad[] = {-0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,0.5};
    glVertexPointer(2,GL_FLOAT,0,quad);
    glDrawArrays(GL_QUADS,0,4);
    glDisableClientState(GL_VERTEX_ARRAY);
    glutSwapBuffers();
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInitWindowPosition(100,100);
    glutInitWindowSize(500,500);
    glutCreateWindow("test");
    glutDisplayFunc(display);
    glewInit();
    glutMainLoop();
    return 0;
}

正如安东尼布洛姆指出的gl_fragColor那样gl_FragColor。小写字母f阻塞了我系统上的 GLSL 编译器。

于 2013-01-29T19:19:37.070 回答