我正在尝试创建我的第一个OpenGL着色器,但在尝试将纹理添加到Cube对象时遇到了困难。
是否有人目光敏锐地发现错误?代码可能有很多错误,如果有人指出它们,我很感激,但我最感兴趣的是为什么我的旋转立方体是灰色而不是彩色。
(我已跳过所有错误处理以保持较低的源代码大小,对不起)
* *编辑发现我错过了一些UV设置,但仍然是灰色的立方体......
#include <windows.h>
#include <SDL.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <math.h>
#include <string>
using namespace std;
void initAll();
void setupBox();
void mainloop();
unsigned int generateTexture();
void handle_inputs();
void updateScreen();
void clean_up();
int scrWidth, scrHeight, flags;
bool bQuit = false;
float angle = 0.0f;
GLuint tex_Box, tex_Norm;
std::string vertex_source, fragment_source;
GLuint shader_program, vertex_shader, fragment_shader;
// vao and vbo handle
GLuint vao, vbo;
const char *source;
int length;
struct sVert
{
float x;
float y;
float z;
};
class cPolygon
{
public:
int v[4];
void fillverts(int v1, int v2, int v3, int v4) {
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
}
} p[6];
sVert pv[8];
int main(int argc, char *argv[])
{
initAll();
mainloop();
clean_up();
return 0;
}
void initAll()
{
scrWidth = 800;
scrHeight = 600;
vertex_source =
"#version 330\n"
"layout (location = 0) in vec3 Position;\n"
"layout (location = 1) in vec2 TexCoord;\n"
"void main() {\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"}\n";
fragment_source =
"#version 330\n"
"uniform sampler2D tex;\n"
"void main() {\n"
" FragColor = texture2D(tex, gl_TexCoord[0].st);\n"
"}\n";
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
flags = SDL_OPENGL | SDL_ANYFORMAT ;
SDL_SetVideoMode(scrWidth, scrHeight, 16, flags);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0f, (GLfloat)scrWidth/(GLfloat)scrHeight, 1.0f, 500.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
SDL_WM_SetCaption( "Texture Shader", NULL );
glewInit();
// Vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
source = vertex_source.c_str();
length = vertex_source.size();
glShaderSource(vertex_shader, 1, &source, &length);
glCompileShader(vertex_shader);
// Fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
source = fragment_source.c_str();
length = fragment_source.size();
glShaderSource(fragment_shader, 1, &source, &length);
glCompileShader(fragment_shader);
// create program
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
setupBox();
GLfloat vd[6*5*6];
for(int pi=0; pi<6; pi++)
{
vd[pi*30+ 0] = pv[ p[pi].v[0] ].x;
vd[pi*30+ 1] = pv[ p[pi].v[0] ].y;
vd[pi*30+ 2] = pv[ p[pi].v[0] ].z;
vd[pi*30+ 3] = 0.0;
vd[pi*30+ 4] = 1.0;
vd[pi*30+ 5] = pv[ p[pi].v[1] ].x;
vd[pi*30+ 6] = pv[ p[pi].v[1] ].y;
vd[pi*30+ 7] = pv[ p[pi].v[1] ].z;
vd[pi*30+ 8] = 0.0;
vd[pi*30+ 9] = 0.0;
vd[pi*30+10] = pv[ p[pi].v[2] ].x;
vd[pi*30+11] = pv[ p[pi].v[2] ].y;
vd[pi*30+12] = pv[ p[pi].v[2] ].z;
vd[pi*30+13] = 1.0;
vd[pi*30+14] = 0.0;
vd[pi*30+15] = pv[ p[pi].v[0] ].x;
vd[pi*30+16] = pv[ p[pi].v[0] ].y;
vd[pi*30+17] = pv[ p[pi].v[0] ].z;
vd[pi*30+18] = 0.0;
vd[pi*30+19] = 1.0;
vd[pi*30+20] = pv[ p[pi].v[2] ].x;
vd[pi*30+21] = pv[ p[pi].v[2] ].y;
vd[pi*30+22] = pv[ p[pi].v[2] ].z;
vd[pi*30+23] = 1.0;
vd[pi*30+24] = 0.0;
vd[pi*30+25] = pv[ p[pi].v[3] ].x;
vd[pi*30+26] = pv[ p[pi].v[3] ].y;
vd[pi*30+27] = pv[ p[pi].v[3] ].z;
vd[pi*30+28] = 1.0;
vd[pi*30+29] = 1.0;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*5*6, vd, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
tex_Box = generateTexture();
tex_Norm = generateTexture();
}
void setupBox()
{
for (int z=0;z<2;z++)
for (int y=0;y<2;y++)
for (int x=0;x<2;x++)
{
pv[x+y*2+z*4].x = -1.0+x;
pv[x+y*2+z*4].y = -1.0+y;
pv[x+y*2+z*4].z = -1.0+z;
}
p[0].fillverts (0, 1, 3, 2); // above
p[1].fillverts (4, 5, 1, 0); // behind
p[2].fillverts (6, 7, 3, 2); // in front
p[3].fillverts (5, 7, 3, 1); // right
p[4].fillverts (0, 2, 6, 4); // left
p[5].fillverts (7, 6, 4, 5); // below
}
unsigned int generateTexture()
{
BYTE data[128*128*3];
unsigned int id;
for (int x=0;x<128;x++)
for (int y=0;y<128;y++)
{
data[y*128*3+x*3+0] = x; // Red
data[y*128*3+x*3+1] = y; // Green
data[y*128*3+x*3+2] = 128-(abs(64-x)+abs(64-y)); // Blue
}
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}
void mainloop()
{
while(bQuit == false)
{
handle_inputs();
updateScreen();
angle += 1.5f;
Sleep(50);
}
}
void handle_inputs()
{
SDL_PumpEvents();
Uint8 * keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_ESCAPE]) bQuit = true;
}
void updateScreen()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt (2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glUseProgram(shader_program);
glBindVertexArray(vao);
glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis
glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis
glActiveTexture(GL_TEXTURE0);
int loc = glGetUniformLocation(shader_program, "tex");
glUniform1i(loc, 0);
glBindTexture(GL_TEXTURE_2D, tex_Box);
glDrawArrays(GL_TRIANGLES, 0, 6*6);
//glutSolidTeapot(2.0);
glUseProgram(0);
SDL_GL_SwapBuffers();
}
void clean_up()
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDetachShader(shader_program, vertex_shader);
glDetachShader(shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDeleteProgram(shader_program);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
glDeleteTextures(1, &tex_Box);
glDeleteTextures(1, &tex_Norm);
SDL_Quit();
}
* *编辑2 以下是遵循 derhass 接受答案中的建议的固定版本。如果你愿意的话,可以选择他的答案,而不是这个。
#include <windows.h>
#include <SDL.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <string>
using namespace std;
#define LOG_SIZE 10000
void initAll();
void setupBox();
void mainloop();
unsigned int generateTexture();
void handle_inputs();
void updateScreen();
void clean_up();
void dbpf(int, const char *, ...);
int scrWidth, scrHeight, flags;
bool bQuit = false;
float angle = 0.0f;
va_list m;
int db_threashold = 0;
GLint status;
GLchar elog[LOG_SIZE];
GLint rLength = 0;
GLuint tex_Box, tex_Norm;
std::string vertex_source, fragment_source;
GLuint shader_program, vertex_shader, fragment_shader;
GLuint vao, vbo;
const char *source;
int length;
struct sVert
{
float x;
float y;
float z;
};
class cPolygon
{
public:
int v[4];
void fillverts(int v1, int v2, int v3, int v4) {
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
}
} p[6];
sVert pv[8];
int main(int argc, char *argv[])
{
initAll();
mainloop();
clean_up();
return 0;
}
void initAll()
{
scrWidth = 800;
scrHeight = 600;
vertex_source =
"#version 330\n"
"in vec3 Position;\n"
"in vec2 TexCoord;\n"
"out vec3 oColor;"
"out vec2 oTexcoord;"
"void main() {\n"
" oTexcoord = TexCoord;\n"
" gl_Position = gl_ModelViewProjectionMatrix*vec4(Position, 1.0);\n"
"}\n";
fragment_source =
"#version 330\n"
"in vec2 oTexcoord;"
"out vec4 oColor;"
"uniform sampler2D tex;\n"
"void main() {\n"
" oColor = texture2D(tex, oTexcoord);\n"
"}\n";
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
flags = SDL_OPENGL | SDL_ANYFORMAT ;
SDL_SetVideoMode(scrWidth, scrHeight, 16, flags);
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective( 45.0f, (GLfloat)scrWidth/(GLfloat)scrHeight, 1.0f, 500.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
SDL_WM_SetCaption( "Texture Shader", NULL );
glewInit();
// create and compiler vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
source = vertex_source.c_str();
length = vertex_source.size();
glShaderSource(vertex_shader, 1, &source, &length);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(vertex_shader, LOG_SIZE, &rLength, elog);
dbpf(10, "Compile vertex log: \n %s \n", elog);
// create and compiler fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
source = fragment_source.c_str();
length = fragment_source.size();
glShaderSource(fragment_shader, 1, &source, &length);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &status);
glGetShaderInfoLog(fragment_shader, LOG_SIZE, &rLength, elog);
dbpf(10, "Compile fragment log: \n %s \n", elog);
// create program
shader_program = glCreateProgram();
// attach shaders
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
// link the program and check for errors
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &status);
glGetProgramInfoLog(shader_program, LOG_SIZE, &rLength, elog);
dbpf(10, "Link log: \n %s \n", elog);
// generate and bind the vao
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// generate and bind the buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
setupBox();
GLfloat vd[6*5*6];
for(int pi=0; pi<6; pi++)
{
vd[pi*30+ 0] = pv[ p[pi].v[0] ].x;
vd[pi*30+ 1] = pv[ p[pi].v[0] ].y;
vd[pi*30+ 2] = pv[ p[pi].v[0] ].z;
vd[pi*30+ 3] = 0.0;
vd[pi*30+ 4] = 1.0;
vd[pi*30+ 5] = pv[ p[pi].v[1] ].x;
vd[pi*30+ 6] = pv[ p[pi].v[1] ].y;
vd[pi*30+ 7] = pv[ p[pi].v[1] ].z;
vd[pi*30+ 8] = 0.0;
vd[pi*30+ 9] = 0.0;
vd[pi*30+10] = pv[ p[pi].v[2] ].x;
vd[pi*30+11] = pv[ p[pi].v[2] ].y;
vd[pi*30+12] = pv[ p[pi].v[2] ].z;
vd[pi*30+13] = 1.0;
vd[pi*30+14] = 0.0;
vd[pi*30+15] = pv[ p[pi].v[0] ].x;
vd[pi*30+16] = pv[ p[pi].v[0] ].y;
vd[pi*30+17] = pv[ p[pi].v[0] ].z;
vd[pi*30+18] = 0.0;
vd[pi*30+19] = 1.0;
vd[pi*30+20] = pv[ p[pi].v[2] ].x;
vd[pi*30+21] = pv[ p[pi].v[2] ].y;
vd[pi*30+22] = pv[ p[pi].v[2] ].z;
vd[pi*30+23] = 1.0;
vd[pi*30+24] = 0.0;
vd[pi*30+25] = pv[ p[pi].v[3] ].x;
vd[pi*30+26] = pv[ p[pi].v[3] ].y;
vd[pi*30+27] = pv[ p[pi].v[3] ].z;
vd[pi*30+28] = 1.0;
vd[pi*30+29] = 1.0;
}
// fill with data
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*5*6, vd, GL_STATIC_DRAW);
// set up generic attrib pointers
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
tex_Box = generateTexture();
tex_Norm = generateTexture();
}
void setupBox()
{
for (int z=0;z<2;z++)
for (int y=0;y<2;y++)
for (int x=0;x<2;x++)
{
pv[x+y*2+z*4].x = -1.0+x;
pv[x+y*2+z*4].y = -1.0+y;
pv[x+y*2+z*4].z = -1.0+z;
}
p[0].fillverts (0, 1, 3, 2); // above
p[1].fillverts (4, 5, 1, 0); // behind
p[2].fillverts (6, 7, 3, 2); // in front
p[3].fillverts (5, 7, 3, 1); // right
p[4].fillverts (0, 2, 6, 4); // left
p[5].fillverts (7, 6, 4, 5); // below
}
unsigned int generateTexture()
{
BYTE data[128*128*3];
unsigned int id;
for (int x=0;x<128;x++)
for (int y=0;y<128;y++)
{
data[y*128*3+x*3+0] = x; // Red
data[y*128*3+x*3+1] = y; // Green
data[y*128*3+x*3+2] = 128-(abs(64-x)+abs(64-y)); // Blue
}
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
return id;
}
void mainloop()
{
while(bQuit == false)
{
handle_inputs();
updateScreen();
angle += 1.5f;
Sleep(50);
}
}
void handle_inputs()
{
SDL_PumpEvents();
Uint8 * keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_ESCAPE]) bQuit = true;
}
void updateScreen()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt (2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// use the shader program
glUseProgram(shader_program);
// bind the vao
glBindVertexArray(vao);
// rotation
glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis
glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis
// bind texture
glActiveTexture(GL_TEXTURE0);
int loc = glGetUniformLocation(shader_program, "tex");
glUniform1i(loc, 0);
glBindTexture(GL_TEXTURE_2D, tex_Box);
// draw
glDrawArrays(GL_TRIANGLES, 0, 6*6);
glUseProgram(0);
SDL_GL_SwapBuffers();
}
void clean_up()
{
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDetachShader(shader_program, vertex_shader);
glDetachShader(shader_program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
glDeleteProgram(shader_program);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
glDeleteTextures(1, &tex_Box);
glDeleteTextures(1, &tex_Norm);
SDL_Quit();
}
void dbpf(int t, const char * msg, ...)
{
va_start(m, msg);
if (t >= db_threashold) vfprintf(stderr, msg, m);
va_end(m);
}
答案 0 :(得分:2)
您的片段着色器甚至不应该编译。您正在写一个未删除的变量&#39; FragColor&#39;。您应首先添加代码以检查编译和链接状态,并查询编译和链接日志,以便获得GLSL编译器/链接器检测到的所有错误和警告。你可以使用类似的东西:
GLint status;
GLubyte log[LOG_SIZE];
// compile shader here
...
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
// compile error
...
}
glGetShaderInfoLog(shader, LOG_SIZE, 0, log);
// print the log
...
// link the program here
// ...
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
// error
...
}
glGetProgramInfoLog(program, LOG_SIZE, 0, log);
// print the log
也许您只想在错误情况下打印信息日志,但即使在成功的情况下也可能会有一些警告/提示,所以我建议打印它,至少在调试/开发构建中。
我还建议您停止使用现代用户定义的属性,输入和输出来混合旧的,已弃用的内置函数,如gl_TexCoord[0]
,gl_MultiTexCoord0
等。目前,您没有使用您声明的TexCoord
属性。