我目前正在尝试遵循本教程。但是有一些问题,对于初学者来说,因为我在 Mac 上,GLSL 语言的最大值为 1.5(我决定使用 1.1)并且本教程需要 3.3,本教程也使用不同的窗口系统(我正在使用他们正在使用的 GLUT GLFW在这里查看所有站点教程的完整源代码)。我目前已经重新安排了代码,让它在我的电脑上运行:
//OpenGL and GLEW
#include <GL/glew.h>
//Include GLUT
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
//Some standard libraries
#include <vector>
#include <string>
#include <stdio.h>
#include <fstream>
#include <math.h>
//For transofmations.
#include "glm.hpp"
#include "transform.hpp"
//max macro for my Mac.
#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
//Vertex data for cube. Direct copy and paste for the coordinates from the website.
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
//Color data for cube. Direct copy and paste from the site.
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
//Used to check if shaders are working. (http://content.gpwiki.org/index.php/OpenGL:Codes:Simple_GLSL_example is where I got this from)
void printLog(GLuint obj)
{
int infologLength = 0;
int maxLength;
if(glIsShader(obj))
glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
else
glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
char infoLog[maxLength];
if (glIsShader(obj))
glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog);
else
glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog);
if (infologLength > 0)
printf("%s\n",infoLog);
}
//Loads the vertex and fragment shader.
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open())
{
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if(FragmentShaderStream.is_open()){
std::string Line = "";
while(getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
printLog(VertexShaderID);
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
printLog(FragmentShaderID);
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage( max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
//Clean up.
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
void display() {
//Enable depth.
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
//Clear screen.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Create the vertexbuffer.
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
//Create the color buffer.
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
1,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
//Draw the cube. 12 triangles, 3 vertices per triangle thus 12*3.
glDrawArrays(GL_TRIANGLES, 0, 12*3);
//Clean Up.
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//Display on screen
glutSwapBuffers();
}
int main(int argc, char** argv) {
//Init stuff.
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(400, 300);
glutCreateWindow("Triangle");
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
//Create the shaders.
GLuint programID = LoadShaders("/Users/person/Programming/C++/OpenGL Cube/OpenGL Cube/v.vsh", "/Users/person/Programming/C++/OpenGL Cube/OpenGL Cube/f.fsh");
glUseProgram(programID);
//Set the camera and stuff.
glm::mat4 Projection = glm::perspective(45.0f, 4.0f/3.0f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(4.0f,3.0f,3.0f),
glm::vec3(0.0f,0.0f,0.0f),
glm::vec3(0.0f,1.0f,0.0f)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
//Get stuff to display.
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
顶点着色器代码:
#version 110
uniform mat4 MVP;
attribute vec2 position;
attribute vec3 vertexColor;
varying vec4 fragmentColor;
void main() {
gl_Position = MVP * vec4(position, 0.0, 1.0);
fragmentColor = vec4(vertexColor, 1.0);
}
片段着色器代码:
#version 110
varying vec4 fragmentColor;
void main() {
gl_FragColor = fragmentColor;
}
目前我的立方体看起来像这样:
着色器编译良好,没有错误消息。
很抱歉,如果这看起来代码太多或什么的,但我真的不知道要删减什么,如果你有什么要我特别指出的,请询问。
更新
谢谢蒂姆的建议,但我仍然遇到一些问题(尽管看起来更好)。我在显示函数中更改了以下代码行,所以我不假设哪个属性是哪个:
GLuint loc1;
loc1 = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(loc1);
printf("%d\n", loc1);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
loc1,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
GLuint loc2 = glGetAttribLocation(program, "vertexColor");
glEnableVertexAttribArray(loc2);
printf("%d\n", loc2);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
loc2,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
除了创建一个全局变量program
之外,programID
我还可以在我的显示函数中使用它的值。现在看起来像这样:
任何人有任何进一步的建议?