Почему камера не меняет направление? | OpenGL
Я попробовал написать программу для изменения направления камеры, чтобы использовать пользовательскую мышь, но она не работает. Руководство: https://ravesli.com/urok-9-kamera-v-opengl
Есть три основных момента:
- Данные для
lookAt
— глобальные переменные. Рисование выполняет методdraw
, каждый раз обновляя матрицу вида. - Метод
updateCamera
принимает позицию мыши и определяет новое направление камеры. - Программа пока не обрабатывает мышь, но есть простой тест, который через каждый кадр (30мс) двигает камеру на 10 юнитов вправо (главный цикл).
#include <iostream>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <chrono>
#include <thread>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
GLuint shaderProgram;
glm::vec3 camPos(0, 0, 3);
glm::vec3 camFront(0, 0, -1);
glm::vec3 camUp(0, 1, 0);
float lastX = -1;
float lastY = -1;
float yaw = -90.0f;
float pitch = 0.0f;
void updateCamera(float mouseX, float mouseY)
{
if (lastX == -1 && lastY == -1)
{
lastX = mouseX;
lastY = mouseY;
return;
}
float xOffset = mouseX - lastX;
float yOffset = lastY - mouseY;
lastX = mouseX;
lastY = mouseY;
float sensitivity = 0.1;
xOffset *= sensitivity;
yOffset *= sensitivity;
glm::vec3 direction;
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
direction.y = sin(glm::radians(pitch));
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
camFront = glm::normalize(direction);
}
void draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
camPos,
camPos + camFront,
camUp
);
glm::mat4 Model = glm::mat4(1.0f);
GLuint mvpId = glGetUniformLocation(shaderProgram, "mvp");
glm::mat4 mvp = Projection * View * Model;
glUniformMatrix4fv(mvpId, 1, GL_FALSE, &mvp[0][0]);
GLuint modelId = glGetUniformLocation(shaderProgram, "model");
glUniformMatrix4fv(modelId, 1, GL_FALSE, &Model[0][0]);
GLuint lightPosId = glGetUniformLocation(shaderProgram, "lightPos");
GLfloat lightPos[] = { 1.0f, 2.0f, 2.0f };
glUniform3fv(lightPosId, 1, lightPos);
glEnable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLES, 0, 12);
glDisable(GL_DEPTH_TEST);
}
int main()
{
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_Window* window = SDL_CreateWindow("OpenGL Draw", 100, 100, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(window);
glewExperimental = GL_TRUE;
glewInit();
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
float vertices[] =
{ // position | color | normal
-0.5f, -0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f, // front face
-0.5f, 0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1, 1, 0, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f, // right face
0.5f, 0.5f, 0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1, 1, 0, 1.0f, 0.0f, 0.0f,
};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
unsigned int indices[] =
{
0, 1, 2,
2, 3, 0
};
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
const char* vertexSource = R"glsl(
#version 150 core
in vec3 position;
in vec3 color;
in vec3 normal;
out vec3 Color;
out vec3 Normal;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 mvp;
void main()
{
Color = color;
Normal = mat3(transpose(inverse(model))) * normal;
FragPos = vec3(model * vec4(position, 1.0));
gl_Position = mvp * vec4(position, 1.0);
}
)glsl";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
const char* fragmentSource = R"glsl(
#version 150 core
in vec3 Color;
in vec3 Normal;
in vec3 FragPos;
out vec4 outColor;
uniform vec3 lightPos;
void main()
{
vec3 lightColor = vec3(1.0, 1.0, 1.0);
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
vec3 result = (ambient + diffuse) * Color;
outColor = vec4(result, 1.0);
}
)glsl";
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GL_FLOAT), 0);
glEnableVertexAttribArray(posAttrib);
GLint colorAttrib = glGetAttribLocation(shaderProgram, "color");
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(colorAttrib);
GLint normalAttrib = glGetAttribLocation(shaderProgram, "normal");
glVertexAttribPointer(normalAttrib, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GL_FLOAT), (void*)(6 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(normalAttrib);
float x = 0;
SDL_Event windowEvent;
while (true)
{
if (SDL_PollEvent(&windowEvent))
{
if (windowEvent.type == SDL_QUIT) break;
}
else
{
updateCamera(x, 0);
x += 10;
draw();
SDL_GL_SwapWindow(window);
std::this_thread::sleep_for(std::chrono::milliseconds(30));
std::cout << "1"; // 1111111 - цикл выполняется
}
}
SDL_GL_DeleteContext(context);
SDL_Quit();
return 0;
}
Источник: Stack Overflow на русском