Visual Studio 2012 和 2010 中基于 Opengl Sierpinski Shader 的 C 代码
Posted
技术标签:
【中文标题】Visual Studio 2012 和 2010 中基于 Opengl Sierpinski Shader 的 C 代码【英文标题】:Opengl Sierpinski Shader based C code in Visual Studio2012 & 2010 【发布时间】:2013-12-03 05:25:01 【问题描述】:我正在 OpenGL 着色器基础编程和计算机图形学方面迈出第一步。我正在尝试以下示例,但是当我尝试编译项目时出现以下错误:
片段着色器链接失败。顶点着色器无法链接。 错误:并非所有着色器都有有效的对象代码
我尝试在 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);
【问题讨论】:
您知道有更简单的方法可以获取着色器的文件大小,对吧?fseek (fp, 0, SEEK_END)
, ftell (fp)
, frewind (fp)
... 因为着色器文件的长度不太可能超过 4 GiB,所以这样做非常安全:P 通常你会考虑 ftello (...)
(Linux/OSX/BSD)/@ 987654328@(Windows)或fstat (...)
(远不那么便携,因为它是POSIX而不是std.C)如果你有更大的文件来获取文件大小。但是在任何情况下,您实际上都不需要像现在这样遍历文件,这是非常低效的。
@AndonM.Coleman:或者更好,使用fstat()
。
@kusma:这样更好吗?这会降低可移植性,并且着色器永远不会大于 4 GiB。
因为在 Windows 上,它只查询文件系统的目录项,而不是更大、更昂贵的文件项。实际上,它不会以任何方式影响可移植性,因为它在 POSIX 和 Windows 中都是如此。
【参考方案1】:
似乎工作正常:
#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 太老了。
【讨论】:
谢谢。我尝试运行您的代码,还下载了您提到的 FreeGlut 版本并使用了它。但我遇到了几个错误,例如:error LNK2001: unresolved external symbol __imp____glewAttachShader 你链接到glew32.lib
了吗?
谢谢。我链接了它,错误消失了。但是现在当我运行项目时,我在 cmd 处收到此消息并退出:Fragment Shader 无法编译并出现以下错误:声明必须包含精度限定符,或者必须事先声明默认精度。
你的GL_VERSION
、GL_SHADING_LANGUAGE_VERSION
和GL_VENDOR
是什么?
打印出glGetString(GL_VERSION)
、glGetString(GL_VENDOR)
等在glewInit()
之后的值。以上是关于Visual Studio 2012 和 2010 中基于 Opengl Sierpinski Shader 的 C 代码的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 2010 和 Visual Studio 2012 中,带有 col、colgroup、tbody 和 thead 的 HTML 表格标记引发编译错误
Visual Studio 2012 与 Visual Studio 2010 (delta) [关闭]
Visual Studio 2010 和 2012 和 2013 连接到 Team Server Foundation 2008
我可以使用 Visual Studio 2012 安装 Visual Studio 2010 SP1 SDK 吗?
用于区分 Visual Studio 2012 和 2010 的 C# 预处理器指令或条件?
我需要用于 .NET 4.5 的 Visual Studio 2012 还是 Visual Studio 2010 适合 4.5?