Обратите внимание, что рисование с помощью glBegin
/ glEnd
последовательностей и стека конвейерной матрицы с фиксированной функцией устарело с десятилетий.Прочтите о конвейере с фиксированными функциями и посмотрите Спецификация вершин и Шейдер для современного способа рендеринга.
Если вы хотите использоватьустаревший способ рисования, тогда вы должны использовать контекст профиля совместимости вместо основного профиля профиля (см. Контекст OpenGL ):
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
Также обратите внимание, что glm::lookAt
и glm::perspective
не устанавливают состояния OpenGL или даже фиксированные матрицы функций. glm - математика OpenGL - это математическая библиотека для расчетов, связанных с OpenGL.Обе функции возвращают матрицу 4 * 4.
Вы можете использовать glLoadMatrixf
для загрузки возврата матрицы с помощью функции glm в стек матриц конвейера фиксированной функции OpenGL:
#include <glm/glm.hpp>
#include "glm/gtc/matrix_transform.hpp"
#include <glm/gtc/type_ptr.hpp>
void Calculate()
{
float radius = 2.0f;
float camX = sin(SDL_GetTicks()*0.001) * radius;
float camZ = cos(SDL_GetTicks()*0.001) * radius;
glm::mat4 perspecive_mat = glm::perspective(
45.0f, 1.0f / 1.0f, 0.1f, 100.0f );
glm::mat4 view_mat = glm::lookAt(
glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0) );
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(glm::value_ptr(perspecive_mat));
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(glm::value_ptr(view_mat));
}
Если вы хотите использовать базовый профиль, вам нужно создать простую Shader программу:
#include <string>
std::string sh_vert = R"(
#version 150 core
in vec3 v_pos;
in vec4 v_col;
out vec4 color;
uniform mat4 projection;
uniform mat4 view;
void main()
{
color = v_col;
gl_Position = projection * view * vec4(v_pos, 1.0);
}
)";
std::string sh_frag = R"(
#version 150 core
in vec4 color;
void main()
{
gl_FragColor = color;
}
)";
Скомпилируйте и свяжите программу:
#include <vector>
GLuint CreateShader(GLenum type, const char *code)
{
GLuint shaderObj = glCreateShader(type);
glShaderSource(shaderObj, 1, &code, nullptr);
glCompileShader(shaderObj);
GLint status = GL_TRUE;
glGetShaderiv(shaderObj, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
GLint logLen;
glGetShaderiv(shaderObj, GL_INFO_LOG_LENGTH, &logLen);
std::vector< char >log(logLen);
GLsizei written;
glGetShaderInfoLog(shaderObj, logLen, &written, log.data());
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
return shaderObj;
}
GLuint CreateProgram()
{
GLuint vShObj = CreateShader(GL_VERTEX_SHADER, sh_vert.c_str());
GLuint fShObj = CreateShader(GL_FRAGMENT_SHADER, sh_frag.c_str());
GLuint progObj = glCreateProgram();
glAttachShader(progObj, vShObj);
glAttachShader(progObj, fShObj);
glLinkProgram(progObj);
GLint status = GL_TRUE;
glGetProgramiv(progObj, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint logLen;
glGetProgramiv(progObj, GL_INFO_LOG_LENGTH, &logLen);
std::vector< char >log(logLen);
GLsizei written;
glGetProgramInfoLog(progObj, logLen, &written, log.data());
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
return progObj;
}
Получите атрибут и единообразные местоположения:
GLuint prog;
GLint pos_attr, col_attr, proj_loc, view_loc;
void Init()
{
prog = CreateProgram();
pos_attr = glGetAttribLocation(prog, "v_pos");
col_attr = glGetAttribLocation(prog, "v_col");
proj_loc = glGetUniformLocation(prog, "projection");
view_loc = glGetUniformLocation(prog, "view");
// ....
}
Создайте Объект массива вершин :
GLuint vao;
void Init()
{
// ....
const std::vector<float> varray
{
// x y z red green blue
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f
};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, varray.size()*sizeof(float), varray.data(), GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(pos_attr, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), 0);
glEnableVertexAttribArray(pos_attr);
glVertexAttribPointer(col_attr, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(col_attr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Устанавливает программный объект как часть текущего состояния рендеринга и устанавливает единообразные переменные:
void Calculate()
{
float radius = 2.0f;
float camX = sin(SDL_GetTicks()*0.001) * radius;
float camZ = cos(SDL_GetTicks()*0.001) * radius;
glm::mat4 perspecive_mat = glm::perspective(
45.0f, 1.0f / 1.0f, 0.1f, 100.0f );
glm::mat4 view_mat = glm::lookAt(
glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0) );
glUseProgram(prog);
glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(perspecive_mat));
glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(view_mat));
}
Наконец, нарисуйте треугольник:
void Render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
SDL_GL_SwapWindow(mainWindow);
}
bool Loop()
{
Init();
while (true) {
// ....
Calculate();
Render();
}
}