c++ - Visual Studio 2012 和 2010 中基于 Opengl Sierpinski Shader 的 C 代码

标签 c++ opengl shader fragment-shader vertex-shader

我正在进行 OpenGl Shader 基础编程和计算机图形学的第一步。我正在尝试以下示例,但是当我尝试编译项目时出现以下错误:

片段着色器链接失败。顶点着色器无法链接。 错误:并非所有着色器都具有有效的对象代码

我尝试在 Visual Studio 2012 和 2010 中运行该程序。glut 库版本为 3.7,glew 库版本为 1.10.0。问题是什么?

.cpp程序

#include <stdio.h>
#include <stdlib.h>
#include <glew.h>
#include <glut.h>
#include <gl.h>


#pragma comment(lib,"glew32.lib")
#define NoP 50000

GLuint InitShader(char *, char *);
void mydisplay();


struct points
{   GLfloat x,y,z;
};
void init();
void Sierpinski(points Num[]);

int main(int argc, char** argv)
    {
    glutInit(&argc,  argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE|GLUT_DEPTH);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0,0);
    glutCreateWindow("Sierpinski 3D");
    glewInit();
    init();
    glEnable(GL_DEPTH_TEST);
    glutDisplayFunc(mydisplay);
    glutMainLoop();
}

void init()
{
    points  Num[NoP];
    Sierpinski(Num);

    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);//set the color for clearing the display
    glPointSize(2); // set the point size
    // Creating a program object containing shader files
    GLuint program;
    program = InitShader("vshader.glsl","fshader.glsl");
    glUseProgram(program);

    //Creating a buffer object containing Sirepinski verteces data
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Num), Num, GL_STATIC_DRAW);

    //Make a conncetion between data in object buffer and "vPosition in vertex shader
    GLuint location = glGetAttribLocation(program, "vPosition");
    glEnableVertexAttribArray ( location );
    glVertexAttribPointer( location, 3, GL_FLOAT, GL_FALSE,0, 0);//BUFFER_OFFSET(0));
}
void mydisplay()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //the clear call will affect the color buffer
    glDrawArrays(GL_POINTS,0,NoP);//Rendering verteces data
    glFlush();  //Empty all commands buffer, causing all issued commands to be executed as quickly as they are accepted by the actual rendering engine
}

static char * ReadShaderSource(char * ShaderFile)
{
    FILE *fp;
    fp = fopen(ShaderFile,"rt");
    if (!fp) return NULL;
    long size=0;
    while (!feof(fp))
    {
      fgetc (fp);
      size++;
    }
    size--;//EOF should not be counted
    fseek(fp, 0, SEEK_SET);
    char * buf= new char[size + 1];
    fread(buf, 1, size,fp);
    buf[size]=0;// string is NULL terminated
    fclose(fp);
    return buf;
}
GLuint InitShader(char * vShaderFile, char * fShaderFile)
{ 
    char * svs, * sfs; 
    GLuint program, VertexShader, FragmentShader;
    program = glCreateProgram();
    VertexShader =  glCreateShader(GL_VERTEX_SHADER);
    svs=ReadShaderSource(vShaderFile);
    glShaderSource(VertexShader,1,(const GLchar **)&svs,NULL);
    glCompileShader(VertexShader);

    // reading GLSL compiler error messages for vertex shader
    GLint compiled;
    glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &compiled);
    if(!compiled)
    {   printf("/n failed to compile");
        GLint logSize;
        glGetShaderiv(VertexShader, GL_INFO_LOG_LENGTH,&logSize);
        char * logMsg = new char[logSize];
        glGetShaderInfoLog(VertexShader, logSize, NULL, logMsg);
        printf("\n  %s",logMsg);
        delete [] logMsg;
        getchar();
        exit(EXIT_FAILURE);
    }

    FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    sfs = ReadShaderSource(fShaderFile);
    glShaderSource(FragmentShader, 1, (const GLchar **)&sfs, NULL);
    glCompileShader(FragmentShader);

    // reading GLSL compiler error messages for fragment shader
    glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &compiled);
    if(!compiled) 
    {   printf("\n failed to compile");
        GLint logSize2;
        glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH,&logSize2);
        char * logMsg2 = new char[logSize2];
        glGetShaderInfoLog(FragmentShader, logSize2, NULL, logMsg2);
        printf("\n  %s",logMsg2);
        delete [] logMsg2;
        getchar();
        exit(EXIT_FAILURE);
    }
    glAttachShader(program,VertexShader);
    glAttachShader(program, FragmentShader);
    glLinkProgram(program);
    // reading GLSL linker error messages for program object
    GLint linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if(!linked)
    {   printf("/n failed to link");
        GLint logSize;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH,&logSize);
        char * logMsg = new char[logSize];
        glGetProgramInfoLog(program, logSize, NULL, logMsg);
        printf("\n  %s",logMsg);
        delete [] logMsg;
        getchar();
        exit(EXIT_FAILURE);
    }

    glUseProgram(program);
    return program;
}
void Sierpinski(points Num[])
{
    int j;
    points  Vertices[4]={{-1.0,-1.0, -1.0},{1.0,-1.0,-1.0},{0.0,1.0,-1.0},{0.0,0.0,1.0}};
    Num[0].x = 0;
    Num[0].y = 0;
    Num[0].z = 0;
    for(int i=1;i<NoP;i++)
    {
        j = rand()  % 4;
        Num[i].x = (Vertices[j].x + Num[i - 1].x)/2;
        Num[i].y = (Vertices[j].y + Num[i - 1].y)/2;
        Num[i].z = (Vertices[j].z + Num[i - 1].z)/2;
    }

}

vshader.glsl

#version 130
in vec4 vPosition;
out vec4 color;
void main()
{  

    gl_Position = vPosition;
    color = vPosition;
}

fshader.glsl

#version 130
in vec4 color;
void main()
{
    gl_FragColor = vec4((1.0 + color.xyz)/2.0,1.0);
}

最佳答案

似乎工作正常:

triangle

#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>

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 << 17 ] = { 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
(
    130,
    in vec4 vPosition;
    out vec4 color;
    void main()
    {  
        gl_Position = vPosition;
        color = vPosition;
    }
);

const char* frag = GLSL
(
    130,
    precision mediump float;
    in vec4 color;
    void main()
    {
        gl_FragColor = vec4((1.0 + color.xyz)/2.0,1.0);
    }
);


#define NoP 50000

struct points
{   
    GLfloat x,y,z;
};

void Sierpinski(points Num[])
{
    int j;
    points  Vertices[4]={{-1.0,-1.0, -1.0},{1.0,-1.0,-1.0},{0.0,1.0,-1.0},{0.0,0.0,1.0}};
    Num[0].x = 0;
    Num[0].y = 0;
    Num[0].z = 0;
    for(int i=1;i<NoP;i++)
    {
        j = rand()  % 4;
        Num[i].x = (Vertices[j].x + Num[i - 1].x)/2;
        Num[i].y = (Vertices[j].y + Num[i - 1].y)/2;
        Num[i].z = (Vertices[j].z + Num[i - 1].z)/2;
    }
}

void init()
{
    points  Num[NoP];
    Sierpinski(Num);

    GLuint program = LoadProgram( vert, NULL, frag );
    glUseProgram(program);

    //Creating a buffer object containing Sirepinski verteces data
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Num), Num, GL_STATIC_DRAW);

    //Make a conncetion between data in object buffer and "vPosition in vertex shader
    GLuint location = glGetAttribLocation(program, "vPosition");
    glEnableVertexAttribArray ( location );
    glVertexAttribPointer( location, 3, GL_FLOAT, GL_FALSE,0, 0);//BUFFER_OFFSET(0));
}

void mydisplay()
{
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);//set the color for clearing the display
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //the clear call will affect the color buffer

    glPointSize(2); // set the point size
    glDrawArrays(GL_POINTS,0,NoP);//Rendering verteces data

    glutSwapBuffers();
}

int main(int argc, char** argv)
{
    glutInit(&argc,  argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE|GLUT_DEPTH);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(0,0);
    glutCreateWindow("Sierpinski 3D");
    glewInit();
    init();
    glEnable(GL_DEPTH_TEST);
    glutDisplayFunc(mydisplay);
    glutMainLoop();
}

确保使用 FreeGLUT , Nate's GLUT太老了。

关于c++ - Visual Studio 2012 和 2010 中基于 Opengl Sierpinski Shader 的 C 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20343539/

相关文章:

c++ - 在 C++ 中从 .mat 文件读取变量

opengl - OpenGL 的硬件要求

c++ - 编译 OpenGL 着色器导致语法错误

python - 为什么纹理索引 31 在 Moderngl 中被覆盖?

opengl - glCompileShader 是可选的吗?

c++ - SDL 1.3 : How to render video with out displaying it?

c++ - 将不同类型的参数传递给函数模板

c++ - 注册到 Linux 的 DeviceManager

c++ - 为什么 C++ 虚拟调用并不比非虚拟调用慢多少?

c - 打开和关闭 GLFW 窗口后无法获取控制台输入