我目前正在尝试学习OpenGL。我已成功地将彩虹三角形渲染到屏幕上,并且我已成功地将它们移动到屏幕上。 但是,我似乎无法正确地将纹理渲染为两个三角形。
每当我运行这个程序时,我都会看到一个没有任何渲染的黑屏。我已经检查了,图像文件肯定在正确的目录中(否则不会运行!)
define STB_IMAGE_IMPLEMENTATION
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <stb/stb_image.h>
int main()
{
//Initialize glfw
if (!glfwInit())
{
fprintf(stderr, "ERROR: Could not start GLFW3.\n");
return 1;
}
//Create the rendering context
GLFWwindow* window = glfwCreateWindow(480, 600, "Hello Rendering",
nullptr, nullptr);
if(!window)
{
fprintf(stderr, "ERROR: Could not create a rendering context with "
"GLFW3.\n");
return 1;
}
glfwMakeContextCurrent(window);
//Start GLEW
glewExperimental=GL_TRUE;
GLenum err=glewInit();
if(err!=GLEW_OK)
{
//Problem: glewInit failed, something is seriously wrong.
std::cout<<"glewInit failed, aborting."<<std::endl;
}
////////////////////////
//Loading PNG
////////////////////////
int x = 0;
int y = 0;
int n = 0;
int force_channels = 4;
unsigned char* image_data = stbi_load("spooky.png", &x, &y, &n,
force_channels);
if(!image_data)
{
fprintf(stderr, "ERROR: Could not load spooky.png\n.");
return 1;
}
//NPOT Check
if((x & (x - 1)) != 0 || (y & (y - 1)) != 0)
{
fprintf(stderr, "ERROR: Image is not a power of 2.\n");
fprintf(stderr, "h: %d w: %d", y, x);
return 1;
}
//Flip the image
int width_in_bytes = x * 4;
unsigned char* top = nullptr;
unsigned char* bottom = nullptr;
unsigned char temp = 0;
int half_height = y / 2;
for(int row = 0; row < half_height; row++)
{
top = image_data + row * width_in_bytes;
bottom = image_data + (y - row - 1) * width_in_bytes;
for(int col = 0; col < width_in_bytes; col++)
{
temp = *top;
*top = *bottom;
*bottom = temp;
top++;
bottom++;
}
}
GLuint tex = 0;
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA,
GL_UNSIGNED_BYTE, image_data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//////////////////////////////////
//Vertex shader
//////////////////////////////////
const char* vertShader =
"#version 330 core"
"layout(location = 0) in vec3 vertexPosition_modelspace;"
"layout(location = 1) in vec2 vt;"
"out vec2 texture_coordinates;"
"void main() {"
" texture_coordinates = vt;"
" gl_Position.xyz = vertexPosition_modelspace;"
" gl_Position.w = 1.0;"
"}";
///////////////////////////////////
//Frag shader
///////////////////////////////////
const char* fragShader =
"#version 330 core"
"uniform sampler2D basic_texture;"
"out vec4 frag_color;"
"void main() {"
" vec4 texel = texture(basic_texture, texture_coordinates);"
" frag_color = texel;"
"}";
////////////////////////////////////
//Create shader program
///////////////////////////////////
GLuint vsp = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vsp, 1, &vertShader, nullptr);
glCompileShader(vsp);
GLuint fsp = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fsp, 1, &fragShader, nullptr);
glCompileShader(fsp);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fsp);
glAttachShader(shader_program, vsp);
glLinkProgram(shader_program);
glUseProgram(shader_program);
////////////////////////////////////
//Texture coordinates
////////////////////////////////////
GLfloat texcoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
GLuint vt_vbo;
glGenBuffers(1, &vt_vbo);
glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof( texcoords), texcoords,
GL_STATIC_DRAW);
GLuint vao;;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
int dimensions = 2;
glVertexAttribPointer(1, dimensions, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Use the shader
glUseProgram(shader_program);
//Draw the two triangles (6 points)
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwPollEvents();
glfwSwapBuffers(window);
if(GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE))
{
glfwSetWindowShouldClose(window, 1);
}
}
std::cout << "Hello, World!" << std::endl;
return 0;
}
答案 0 :(得分:1)
首先,您应该在编译和链接着色器时检索错误消息:
GLint status = GL_TRUE;
char error_msg[1024];
GLsizei read;
GLuint vsp = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vsp, 1, &vertShader, nullptr);
glCompileShader(vsp);
glGetShaderiv( vsp, GL_COMPILE_STATUS, &status );
if ( status != GL_TRUE )
{
glGetShaderInfoLog( vsp, 1024, &read, error_msg );
std::cout << "compile error:" << std::endl << error_msg << std::endl;
}
GLuint fsp = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fsp, 1, &fragShader, nullptr);
glCompileShader(fsp);
glGetShaderiv( fsp, GL_COMPILE_STATUS, &status );
if ( status != GL_TRUE )
{
glGetShaderInfoLog( fsp, 1024, &read, error_msg );
std::cout << "compile error:" << std::endl << error_msg << std::endl;
}
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fsp);
glAttachShader(shader_program, vsp);
glLinkProgram(shader_program);
glGetProgramiv( shader_program, GL_LINK_STATUS, &status );
if ( status != GL_TRUE )
{
glGetProgramInfoLog( shader_program, 1024, &read, error_msg );
std::cout << "compile error:" << std::endl << error_msg << std::endl;
}
您将收到的第一条错误消息是这样的:
0(1):错误C0205:无效的配置文件“corelayout”
0(1):错误C0206:版本行中的令牌“”无效
这是因为您没有在着色器代码的第一行("\n"
)之后写下结束"#version 330 core"
的行。
当您修复此问题时,您会收到下一条错误消息:
0(2):错误C1008:未定义变量“texture_coordinates”
您必须将in
变量texture_coordinates
的声明添加到片段着色器。
in vec2 texture_coordinates;
最终代码如下:
const char* vertShader =
"#version 330 core\n"
"layout(location = 0) in vec3 vertexPosition_modelspace;"
"layout(location = 1) in vec2 vt;"
"out vec2 texture_coordinates;"
"void main() {"
" texture_coordinates = vt;"
" gl_Position.xyz = vertexPosition_modelspace;"
" gl_Position.w = 1.0;"
"}";
const char* fragShader =
"#version 330 core\n"
"uniform sampler2D basic_texture;"
"out vec4 frag_color;"
"in vec2 texture_coordinates;"
"void main() {"
" vec4 texel = texture(basic_texture, texture_coordinates);"
" frag_color = texel;"
"}";
当然,您必须为顶点属性vertexPosition_modelspace
提供顶点数据:
GLfloat texcoords[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
GLfloat vertex[] = {
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
};
GLuint vert_vbo;
glGenBuffers(1, &vert_vbo);
glBindBuffer(GL_ARRAY_BUFFER, vert_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof( vertex ), vertex, GL_STATIC_DRAW);
GLuint vt_vbo;
glGenBuffers(1, &vt_vbo);
glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof( texcoords ), texcoords, GL_STATIC_DRAW);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vert_vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vt_vbo);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(1);
最后,您应该将纹理单元的索引(纹理绑定到的)设置为纹理采样器统一变量basic_texture
:
int texture_unit_index = 0;
GLuint tex = 0;
glGenTextures(1, &tex);
glActiveTexture(GL_TEXTURE0 + texture_unit_index );
glBindTexture(GL_TEXTURE_2D, tex);
.....
// to do after glLinkProgram(shader_program);
int tex_sampler_loc = glGetUniformLocation( shader_program, "basic_texture" );
.....
// to do after glUseProgram(shader_program);
glUniform1i( tex_sampler_loc, texture_unit_index );