我正在关注learnopengl.com上的教程,但我遇到了一些问题。我用C而不是C ++编写我的程序,并使用linmath库进行矩阵转换,我有shader.c和texture.c文件。我认为问题在于我的矩阵转换,但我无法弄清楚我哪里出错了。程序运行并编译,创建窗口并且背景颜色正确但是对象不显示。
以下是来源:
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "linmath.h"
#include "shader.h"
#include "texture.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main(){
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL){
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD");
return -1;
}
Shader ourShader;
ourShader.ID = loadShader("3.3.shader.vs", "3.3.shader.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Texture tex1 = loadTexture("container.jpg");
Texture tex2 = loadTexture("awesomeface.png");
// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
useShader(ourShader.ID);
setIntShader("texture1", 0, ourShader.ID);
setIntShader("texture2", 1, ourShader.ID);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind textures on corresponding texture units
bindTexture(tex1, GL_TEXTURE0);
bindTexture(tex2, GL_TEXTURE1);
// activate shader
useShader(ourShader.ID);
// create transformations
mat4x4 model;
mat4x4 m;
mat4x4 view;
mat4x4 projection;
mat4x4_rotate(model, m, 1.0f, 0.0f, 0.0f, -0.95993f);
mat4x4_translate(view, 0.0f, 0.0f, -3.0f);
mat4x4_perspective(projection, 0.785f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// pass them to the shaders
setMat4Shader("model", model, ourShader.ID);
setMat4Shader("view", view, ourShader.ID);
setMat4Shader("projection", projection, ourShader.ID);
// render container
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
shader.c
#include "shader.h"
GLuint loadShader(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
char* VertexShaderCode;
FILE * vertexFile = fopen(vertex_file_path, "r");
if( vertexFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long vertex_file_size;
fseek(vertexFile, 0, SEEK_END);
vertex_file_size = ftell(vertexFile);
rewind(vertexFile);
VertexShaderCode = malloc((vertex_file_size + 1) * (sizeof(char)));
fread(VertexShaderCode, sizeof(char), vertex_file_size, vertexFile);
fclose(vertexFile);
VertexShaderCode[vertex_file_size] = 0;
// Read the Fragment Shader code from the file
char* FragmentShaderCode;
FILE * fragmentFile = fopen(fragment_file_path, "r");
if( fragmentFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long fragment_file_size;
fseek(fragmentFile, 0, SEEK_END);
fragment_file_size = ftell(fragmentFile);
rewind(fragmentFile);
FragmentShaderCode = malloc((fragment_file_size + 1) * (sizeof(char)));
fread(FragmentShaderCode, sizeof(char), fragment_file_size, fragmentFile);
fclose(fragmentFile);
FragmentShaderCode[fragment_file_size] = 0;
const char* vsCode = VertexShaderCode;
const char* fsCode = FragmentShaderCode;
// 2. compile shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vsCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fsCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
GLuint ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
return ID;
}
void useShader(unsigned int ID){
glUseProgram(ID);
}
void setBoolShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setIntShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setFloatShader(const char * name, float value, unsigned int ID)
{
glUniform1f(glGetUniformLocation(ID, name), value);
}
void setMat4Shader(const char * name, mat4x4 mat, unsigned int ID)
{
glUniformMatrix4fv(glGetUniformLocation(ID, name), 1, GL_FALSE, *mat);
}
void checkCompileErrors(GLuint shader, char type[])
{
GLint success;
GLchar infoLog[1024];
if(strncmp(type, "PROGRAM", 7) != 0)
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
}
texture.c
#include "texture.h"
Texture loadTexture(const char* path){
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
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);
//load texture
int width, height, nrChannels;
unsigned char *data = SOIL_load_image(path, &width, &height, &nrChannels, SOIL_LOAD_RGB);
if(data){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else{
printf("Failed to load Image");
}
SOIL_free_image_data(data);
Texture t;
t.ID = texture;
t.path = path;
return t;
}
void bindTexture(Texture texture, GLenum unit){
// bind textures on corresponding texture units
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, texture.ID);
}
顶点着色器
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
// linearly interpolate between both textures (80% container, 20% awesomeface)
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}