#define GLM_FORCE_RADIANS
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <stdlib.h>
#include <stdio.h>
#include "constants.h"
#include "allmodels.h"
#include "lodepng.h"
#include "shaderprogram.h"
using namespace glm;
float speed_x = 0; // [radiany/s]
float speed_y = 0; // [radiany/s]
//Uchwyty na shadery
ShaderProgram *shaderProgram; //Wskaźnik na obiekt reprezentujący program cieniujący.
//Uchwyty na VAO i bufory wierzchołków
GLuint vao;
GLuint vbo[3];
//Procedura obsługi błędów
void error_callback(int error, const char* description) {
fputs(description, stderr);
}
//Procedura obsługi klawiatury
void key_callback(GLFWwindow* window, int key,
int scancode, int action, int mods) {
if (action == GLFW_PRESS) {
if (key == GLFW_KEY_LEFT) speed_y = -3.14;
if (key == GLFW_KEY_RIGHT) speed_y = 3.14;
if (key == GLFW_KEY_UP) speed_x = -3.14;
if (key == GLFW_KEY_DOWN) speed_x = 3.14;
}
if (action == GLFW_RELEASE) {
if (key == GLFW_KEY_LEFT) speed_y = 0;
if (key == GLFW_KEY_RIGHT) speed_y = 0;
if (key == GLFW_KEY_UP) speed_x = 0;
if (key == GLFW_KEY_DOWN) speed_x = 0;
}
}
//Tworzy bufor VBO z tablicy
GLuint makeBuffer(void *data, int vertexCount, int vertexSize) {
GLuint handle;
glGenBuffers(1,&handle);//Wygeneruj uchwyt na Vertex Buffer Object (VBO), który będzie zawierał tablicę danych
glBindBuffer(GL_ARRAY_BUFFER,handle); //Uaktywnij wygenerowany uchwyt VBO
glBufferData(GL_ARRAY_BUFFER, vertexCount*vertexSize, data, GL_STATIC_DRAW);//Wgraj tablicę do VBO
return handle;
}
//Przypisuje bufor VBO do atrybutu
void assignVBOtoAttribute(ShaderProgram *shaderProgram,char* attributeName, GLuint bufVBO, int vertexSize) {
GLuint location=shaderProgram->getAttribLocation(attributeName); //Pobierz numery slotów dla atrybutu
glBindBuffer(GL_ARRAY_BUFFER,bufVBO); //Uaktywnij uchwyt VBO
glEnableVertexAttribArray(location); //Włącz używanie atrybutu o numerze slotu zapisanym w zmiennej location
glVertexAttribPointer(location,vertexSize,GL_FLOAT, GL_FALSE, 0, NULL); //Dane do slotu location mają być brane z aktywnego VBO
}
void InitVertexBuffer()
{
const float x0 = 1.0f;
const float y0 = 1.0f;
const float z0 = 1.0f;
const float positions[] =
{
-x0,-y0,0.0f,
x0,-y0,0.0f,
0,y0,0.0f
};
const float colors[] =
{
1,1,0,1,
1,0,1,1,
0,1,1,1
};
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(3, vbo);
GLuint position_attribute = 0;
GLuint color_attribute = 3;
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
glVertexAttribPointer(position_attribute, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(position_attribute);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer(color_attribute, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(color_attribute);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
}
//Procedura inicjująca
void initOpenGLProgram(GLFWwindow* window) {
//************Tutaj umieszczaj kod, który należy wykonać raz, na początku programu************
glClearColor(0, 0, 0, 1); //Czyść ekran na czarno
glEnable(GL_DEPTH_TEST); //Włącz używanie Z-Bufora
glfwSetKeyCallback(window, key_callback); //Zarejestruj procedurę obsługi klawiatury
InitVertexBuffer();
}
//Procedura rysująca zawartość sceny
void drawScene(GLFWwindow* window, float angle_x, float angle_y) {
//************Tutaj umieszczaj kod rysujący obraz******************l
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //Wykonaj czyszczenie bufora kolorów
glm::mat4 P = glm::perspective(50 * PI / 180, 1.0f, 1.0f, 50.0f); //Wylicz macierz rzutowania
glm::mat4 V = glm::lookAt( //Wylicz macierz widoku
glm::vec3(0.0f, 0.0f, -5.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
//Wylicz macierz modelu rysowanego obiektu
glm::mat4 M = glm::mat4(1.0f);
M = glm::rotate(M, angle_x, glm::vec3(1, 0, 0));
M = glm::rotate(M, angle_y, glm::vec3(0, 1, 0));
glDrawArrays(GL_TRIANGLES, 0, 3);
//Przerzuć tylny bufor na przedni
glfwSwapBuffers(window);
}
int main(void)
{
GLFWwindow* window; //Wskaźnik na obiekt reprezentujący okno
glfwSetErrorCallback(error_callback);//Zarejestruj procedurę obsługi błędów
if (!glfwInit()) { //Zainicjuj bibliotekę GLFW
fprintf(stderr, "Nie można zainicjować GLFW.\n");
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(500, 500, "OpenGL", NULL, NULL); //Utwórz okno 500x500 o tytule "OpenGL" i kontekst OpenGL.
if (!window) //Jeżeli okna nie udało się utworzyć, to zamknij program
{
fprintf(stderr, "Nie można utworzyć okna.\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window); //Od tego momentu kontekst okna staje się aktywny i polecenia OpenGL będą dotyczyć właśnie jego.
glfwSwapInterval(1); //Czekaj na 1 powrót plamki przed pokazaniem ukrytego bufora
if (glewInit() != GLEW_OK) { //Zainicjuj bibliotekę GLEW
fprintf(stderr, "Nie można zainicjować GLEW.\n");
exit(EXIT_FAILURE);
}
initOpenGLProgram(window); //Operacje inicjujące
float angle_x = 0; //Kąt obrotu obiektu
float angle_y = 0; //Kąt obrotu obiektu
glfwSetTime(0); //Wyzeruj licznik czasu
//Główna pętla
while (!glfwWindowShouldClose(window)) //Tak długo jak okno nie powinno zostać zamknięte
{
angle_x += speed_x*glfwGetTime(); //Zwiększ kąt o prędkość kątową razy czas jaki upłynął od poprzedniej klatki
angle_y += speed_y*glfwGetTime(); //Zwiększ kąt o prędkość kątową razy czas jaki upłynął od poprzedniej klatki
glfwSetTime(0); //Wyzeruj licznik czasu
drawScene(window,angle_x,angle_y); //Wykonaj procedurę rysującą
glfwPollEvents(); //Wykonaj procedury callback w zalezności od zdarzeń jakie zaszły.
}
glfwDestroyWindow(window); //Usuń kontekst OpenGL i okno
glfwTerminate(); //Zwolnij zasoby zajęte przez GLFW
exit(EXIT_SUCCESS);
}
Mam funkcję
void InitVertexBuffer()
która ładnie inicjuje bufory wierzchołków i kolorów, ale coś nie działa, bo wychodzi mi trójkąt, tylko że niepokolorowany (biały trójkąt na czarnym tle). Gdzie może tkwić błąd?