在 OpenGL 中使用 SOIL 向三角形添加纹理的问题
Problem with adding texture to triangle using SOIL in OpenGL
这是在尝试加载纹理时出现的错误:
这是我的工作目录:
下面是我的纹理图像的位置
我尝试向三角形添加纹理,但似乎出了点问题。当尝试 运行 调试时,没有错误也没有警告,但是它显示灰色 window,没有三角形,也没有任何纹理。这是我的部分代码,有什么问题吗?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f,0.0f
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f,0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] =
{
0,1,2,
1,2,3
};
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
//initializeaza buffer-ele de culoare si adancime inainte de a rasteriza cadrul curent
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//defineste culoarea de fundal
glClearColor(0.8, 0.8, 0.8, 1.0);
//specifica locatia si dimensiunea ferestrei
glViewport(0, 0, retina_width, retina_height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
//activeaza program shader-ul; apeluri ulterioare de rasterizare vor utiliza acest program
glUseProgram(shaderProgram); /**/
//activeaza VAO
glBindVertexArray(triangleVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//specifica tipul primitiei, indicele de inceput si numarul de indici utilizati pentru rasterizare
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawArrays(GL_TRIANGLES, 0, 3); /**/
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile(vertexShaderFileName);
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile(fragmentShaderFileName);
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glActiveTexture(GL_TEXTURE0);
glfwPollEvents();
renderScene();
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
glBindVertexArray(triangleVAO);
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
这是片段着色器
#version 400
in vec3 colour;
in vec2 passTexture;
out vec4 fragmentColour;
uniform sampler2D dif;
void main() {
fragmentColour = texture(dif, passTexture);
}
这是顶点着色器:
#version 400
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 textcoord;
out vec3 colour;
out vec2 passTexture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
colour = vertexNormal;
passTexture = textcoord;
gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
您需要在绑定索引缓冲区之前绑定顶点数组对象,因此您需要交换它。
编辑:顶点数组绑定需要高于
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
还有。
默认情况下,顶点着色器中矩阵的所有字段都由 0.0 初始化。
要生成代码 运行,您必须跳过矩阵:
gl_Position = vec4(vertexPosition, 1.0);
或者通过renderScene
中的Identity matrix初始化它们:
GLint model_loc = glGetUniformLocation(shaderProgram, "model");
GLint view_loc = glGetUniformLocation(shaderProgram, "view");
GLint proj_loc = glGetUniformLocation(shaderProgram, "projection");
GLint tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
注意,制服必须在glUseProgram
安装程序后设置。
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
由于Index buffers
is stated in the Vertex Array Object,必须先绑定VAO,然后才能绑定索引缓冲区:
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
在执行绘制调用之前,设置所有必要的状态,并绑定必要的对象。
viewport rectangle 和 clear color 应该设置在 glClear
.
之前
纹理应该在绘制网格之前绑定。
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
glUseProgram(shaderProgram);
// set the uniforms as described above
// [...]
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
此外,顶点数组属性数组的第 2 行缺少一个逗号 (,
),并且索引未形成四边形。更改它:
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
最后,如果你想使用mipmaping,那么纹理缩小过滤器必须是GL_NEAREST_MIPMAP_NEAREST
、GL_LINEAR_MIPMAP_NEAREST
、GL_NEAREST_MIPMAP_LINEAR
或[=26=之一].
完整代码:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
GLuint texture;
GLint model_loc, view_loc, proj_loc, tex_loc;
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile( vertexShaderFileName );
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile( fragmentShaderFileName );
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
model_loc = glGetUniformLocation(shaderProgram, "model");
view_loc = glGetUniformLocation(shaderProgram, "view");
proj_loc = glGetUniformLocation(shaderProgram, "projection");
tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("SOIL2/res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
这是在尝试加载纹理时出现的错误:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f,0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f,0.0f
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f,0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] =
{
0,1,2,
1,2,3
};
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
//initializeaza buffer-ele de culoare si adancime inainte de a rasteriza cadrul curent
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//defineste culoarea de fundal
glClearColor(0.8, 0.8, 0.8, 1.0);
//specifica locatia si dimensiunea ferestrei
glViewport(0, 0, retina_width, retina_height);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
//activeaza program shader-ul; apeluri ulterioare de rasterizare vor utiliza acest program
glUseProgram(shaderProgram); /**/
//activeaza VAO
glBindVertexArray(triangleVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
//specifica tipul primitiei, indicele de inceput si numarul de indici utilizati pentru rasterizare
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawArrays(GL_TRIANGLES, 0, 3); /**/
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile(vertexShaderFileName);
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile(fragmentShaderFileName);
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glActiveTexture(GL_TEXTURE0);
glfwPollEvents();
renderScene();
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "diffuseTexture"), 0);
glBindVertexArray(triangleVAO);
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}
这是片段着色器
#version 400
in vec3 colour;
in vec2 passTexture;
out vec4 fragmentColour;
uniform sampler2D dif;
void main() {
fragmentColour = texture(dif, passTexture);
}
这是顶点着色器:
#version 400
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 textcoord;
out vec3 colour;
out vec2 passTexture;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
colour = vertexNormal;
passTexture = textcoord;
gl_Position = projection * view * model * vec4(vertexPosition, 1.0);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindVertexArray(triangleVAO);
您需要在绑定索引缓冲区之前绑定顶点数组对象,因此您需要交换它。
编辑:顶点数组绑定需要高于
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
还有。
默认情况下,顶点着色器中矩阵的所有字段都由 0.0 初始化。
要生成代码 运行,您必须跳过矩阵:
gl_Position = vec4(vertexPosition, 1.0);
或者通过renderScene
中的Identity matrix初始化它们:
GLint model_loc = glGetUniformLocation(shaderProgram, "model");
GLint view_loc = glGetUniformLocation(shaderProgram, "view");
GLint proj_loc = glGetUniformLocation(shaderProgram, "projection");
GLint tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
注意,制服必须在glUseProgram
安装程序后设置。
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
由于Index buffers
is stated in the Vertex Array Object,必须先绑定VAO,然后才能绑定索引缓冲区:
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
在执行绘制调用之前,设置所有必要的状态,并绑定必要的对象。
viewport rectangle 和 clear color 应该设置在 glClear
.
之前
纹理应该在绘制网格之前绑定。
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
glUseProgram(shaderProgram);
// set the uniforms as described above
// [...]
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
此外,顶点数组属性数组的第 2 行缺少一个逗号 (,
),并且索引未形成四边形。更改它:
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
最后,如果你想使用mipmaping,那么纹理缩小过滤器必须是GL_NEAREST_MIPMAP_NEAREST
、GL_LINEAR_MIPMAP_NEAREST
、GL_NEAREST_MIPMAP_LINEAR
或[=26=之一].
完整代码:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "SOIL2/SOIL2.h"
int glWindowWidth = 640;
int glWindowHeight = 480;
int retina_width, retina_height;
GLFWwindow* glWindow = NULL;
GLfloat vertexCoordinates[] = {
//position //color //texture
0.5f, 0.5f,0.0f, 1.0f,0.0f,0.0f, 1.0f ,1.0f,
0.5f,-0.5f,0.0f, 1.0f,1.0f,1.0f, 1.0f ,0.0f,
-0.5f,-0.5f,0.0f, 1.0f,0.0f,0.0f, 0.0f ,0.0f,
-0.5f, 0.5f,0.0f, 1.0f,0.0f,1.0f, 0.0f ,1.0f,
};
GLuint indices[] = { 0,1,2, 0,2,3 };
GLuint verticesVBO;
GLuint triangleVAO;
GLuint EBO;
GLuint triangleVAO2;
GLuint verticesVBO2;
GLuint shaderProgram;
GLuint shaderProgram2;
GLuint texture;
GLint model_loc, view_loc, proj_loc, tex_loc;
float identity_matrix[] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
void windowResizeCallback(GLFWwindow* window, int width, int height)
{
fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height);
//TODO
}
void initObjects()
{
//genereaza un ID unic pentru verticesVBO
glGenBuffers(1, &verticesVBO);
glGenBuffers(1, &EBO);
glGenVertexArrays(1, &triangleVAO);
glBindVertexArray(triangleVAO);
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//genereaza un ID unic, care corespunde obiectului triangleVAO
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
//seteaza pointer-ul atributelor de varf
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(0);
//color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//de-selecteaza obiectul triangleVAO
glBindVertexArray(0);
}
bool initOpenGLWindow()
{
if (!glfwInit()) {
fprintf(stderr, "ERROR: could not start GLFW3\n");
return false;
}
//for Mac OS X
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL);
if (!glWindow) {
fprintf(stderr, "ERROR: could not open window with GLFW3\n");
glfwTerminate();
return false;
}
glfwSetWindowSizeCallback(glWindow, windowResizeCallback);
glfwMakeContextCurrent(glWindow);
glfwWindowHint(GLFW_SAMPLES, 4);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
//for RETINA display
glfwGetFramebufferSize(glWindow, &retina_width, &retina_height);
return true;
}
void renderScene()
{
glViewport(0, 0, retina_width, retina_height);
glClearColor(0.8, 0.8, 0.8, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(triangleVAO);
if (glfwGetKey(glWindow, GLFW_KEY_D)) {
//TODO
}
glUseProgram(shaderProgram);
glUniformMatrix4fv(model_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(view_loc, 1, GL_FALSE, identity_matrix);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, identity_matrix);
glUniform1i(tex_loc, 0); // unnecessary, because 0 is default.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
std::string readShaderFile(std::string fileName)
{
std::ifstream shaderFile;
std::string shaderString;
//open shader file
shaderFile.open(fileName);
std::stringstream shaderStringStream;
//read shader content into stream
shaderStringStream << shaderFile.rdbuf();
//close shader file
shaderFile.close();
//convert stream into GLchar array
shaderString = shaderStringStream.str();
return shaderString;
}
void shaderCompileLog(GLuint shaderId)
{
GLint success;
GLchar infoLog[512];
//check compilation info
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shaderId, 512, NULL, infoLog);
std::cout << "Shader compilation error\n" << infoLog << std::endl;
}
}
void shaderLinkLog(GLuint shaderProgramId)
{
GLint success;
GLchar infoLog[512];
//check linking info
glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "Shader linking error\n" << infoLog << std::endl;
}
}
GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName, GLuint shaderProgram)
{
//read, parse and compile the vertex shader
std::string v = readShaderFile( vertexShaderFileName );
const GLchar* vertexShaderString = v.c_str();
GLuint vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderString, NULL);
glCompileShader(vertexShader);
//check compilation status
shaderCompileLog(vertexShader);
//read, parse and compile the vertex shader
std::string f = readShaderFile( fragmentShaderFileName );
const GLchar* fragmentShaderString = f.c_str();
GLuint fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL);
glCompileShader(fragmentShader);
//check compilation status
shaderCompileLog(fragmentShader);
//attach and link the shader programs
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//check linking info
shaderLinkLog(shaderProgram);
return shaderProgram;
}
int main(int argc, const char * argv[]) {
initOpenGLWindow();
initObjects();
shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag",shaderProgram);
model_loc = glGetUniformLocation(shaderProgram, "model");
view_loc = glGetUniformLocation(shaderProgram, "view");
proj_loc = glGetUniformLocation(shaderProgram, "projection");
tex_loc = glGetUniformLocation(shaderProgram, "diffuseTexture");
shaderProgram2 = initBasicShader("shaders/shader2.vert", "shaders/shader2.frag",shaderProgram2);
int width, height;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
unsigned char* image = SOIL_load_image("SOIL2/res/images/image1.jpg", &width, &height, 0, SOIL_LOAD_RGBA);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glGenerateMipmap(GL_TEXTURE_2D);
SOIL_free_image_data(image);
glBindTexture(GL_TEXTURE_2D, 0);
while (!glfwWindowShouldClose(glWindow)) {
glfwPollEvents();
renderScene();
glfwSwapBuffers(glWindow);
}
//close GL context and any other GLFW resources
glfwTerminate();
return 0;
}