working ray_tracing.cpp
1. working ray-tracing for spheres adding nav rn
This commit is contained in:
parent
5ab597aabb
commit
ee2af4d83f
1 changed files with 246 additions and 281 deletions
527
ray_tracing.cpp
527
ray_tracing.cpp
|
|
@ -8,208 +8,60 @@
|
|||
#include <cmath>
|
||||
using namespace glm;
|
||||
|
||||
// vars
|
||||
// global vars
|
||||
const int WIDTH = 800;
|
||||
const int HEIGHT = 600;
|
||||
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
float lastX = 400.0, lastY = 300.0;
|
||||
float cameraYaw = -90;
|
||||
float cameraPitch = 0.0;
|
||||
float deltaTime = 0.0;
|
||||
float lastFrame = 0.0;
|
||||
|
||||
// functions
|
||||
GLFWwindow* StartGLU();
|
||||
GLuint CreateShaderProgram();
|
||||
GLuint setupQuad();
|
||||
void renderScene(GLFWwindow* &window, GLuint &quadVAO, GLuint &texture, GLuint &shaderProgram, std::vector<unsigned char> &pixels);
|
||||
GLuint loadTexture();
|
||||
|
||||
void UpdateCam(GLuint shaderProgram, glm::vec3 cameraPos);
|
||||
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
|
||||
|
||||
// structures and classes :D
|
||||
struct Ray{
|
||||
vec3 direction;
|
||||
vec3 origin;
|
||||
Ray(vec3 direction, vec3 origin) : direction(direction), origin(origin){}
|
||||
};
|
||||
struct Object{
|
||||
vec3 centre;
|
||||
float radius;
|
||||
vec3 color;
|
||||
Object(vec3 centre, float radius, vec3 color) : centre(centre), radius(radius), color(color){}
|
||||
bool intersect(const Ray &ray, float& t){
|
||||
vec3 oc = ray.origin - centre;
|
||||
double a = dot(ray.direction, ray.direction);
|
||||
double b = 2.0 * dot(oc, ray.direction);
|
||||
double c = dot(oc, oc) - radius * radius;
|
||||
|
||||
double discriminant = b*b - 4 * a * c;
|
||||
if (discriminant < 0) return false;
|
||||
|
||||
float temp = (-b - sqrt(discriminant)) / (2.0f*a);
|
||||
if (temp < 0) {
|
||||
temp = (-b + sqrt(discriminant)) / (2.0f*a);
|
||||
if (temp < 0) return false;
|
||||
}
|
||||
t = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
vec3 getNormal(const glm::vec3& point) const {
|
||||
return normalize(point - centre);
|
||||
}
|
||||
};
|
||||
class Scene{
|
||||
class Engine{
|
||||
public:
|
||||
std::vector<Object> objs;
|
||||
vec3 lightPos;
|
||||
Scene() : lightPos(5.0f, 5.0f, 5.0f) {}
|
||||
// -- Quad & Texture render
|
||||
GLFWwindow* window;
|
||||
GLuint quadVAO;
|
||||
GLuint texture;
|
||||
GLuint shaderProgram;
|
||||
|
||||
vec3 trace(const Ray& ray) const{
|
||||
float closest = INFINITY;
|
||||
const Object* hitObject = nullptr;
|
||||
for(const auto& obj : objs){
|
||||
float t; // distance to intersection
|
||||
// Create non-const copy to call intersect
|
||||
Object mutableObj = obj;
|
||||
if(mutableObj.intersect(ray, t)) {
|
||||
if(t < closest) {
|
||||
closest = t;
|
||||
hitObject = &obj;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (hitObject) {
|
||||
vec3 hitPoint = ray.origin + ray.direction * closest;
|
||||
vec3 normal = hitObject->getNormal(hitPoint);
|
||||
vec3 lightDir = normalize(lightPos - hitPoint);
|
||||
|
||||
float diff = std::max(glm::dot(normal, lightDir), 0.0f);
|
||||
Ray shadowRay(lightDir, hitPoint + normal * 0.001f);
|
||||
bool inShadow = false;
|
||||
for (const auto& obj : objs) {
|
||||
float t;
|
||||
Object mutableObj = obj; // Create non-const copy
|
||||
if(mutableObj.intersect(shadowRay, t)) {
|
||||
inShadow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 color = hitObject->color;
|
||||
float ambient = 0.1f;
|
||||
|
||||
if (inShadow) {
|
||||
return color * ambient;
|
||||
}
|
||||
|
||||
return color * (ambient + diff * 0.9f);
|
||||
}
|
||||
return vec3(0.0f);
|
||||
Engine(){
|
||||
this->window = StartGLFW();
|
||||
this->shaderProgram = CreateShaderProgram();
|
||||
|
||||
auto result = QuadVAO();
|
||||
this->quadVAO = result[0];
|
||||
this->texture = result[1];
|
||||
}
|
||||
};
|
||||
GLFWwindow* StartGLFW(){
|
||||
if(!glfwInit()){
|
||||
std::cerr<<"glfw failed init, PANIC PANIC!"<<std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// --------- main --------- //
|
||||
int main() {
|
||||
// setup
|
||||
GLFWwindow* window = StartGLU();
|
||||
Scene scene;
|
||||
GLuint shaderProgram = CreateShaderProgram(); // compile shader program
|
||||
GLuint quadVAO = setupQuad(); // create quad background
|
||||
GLuint texture = loadTexture();
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetCursorPosCallback(window, mouse_callback);
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "ray tracer", NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GLEW_OK) {
|
||||
std::cerr << "Failed to initialize GLEW." << std::endl;
|
||||
glfwTerminate();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> pixels(WIDTH * HEIGHT * 3);
|
||||
scene.objs = {
|
||||
Object(glm::vec3(-1.0f, 0.0f, -5.0f), 1.0f, vec3(1.0f, 0.0, 0.0)),
|
||||
Object(glm::vec3(2.0f, 0.0f, -6.0f), 1.0f, vec3(0.0f, 1.0, 1.0))
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
return window;
|
||||
};
|
||||
|
||||
while(!glfwWindowShouldClose(window)){
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
UpdateCam(shaderProgram, cameraPos);
|
||||
GLuint CreateShaderProgram(){
|
||||
const char* vertexShaderSource = R"(
|
||||
#version 330 core
|
||||
layout (location = 0) in vec2 aPos; // Changed to vec2
|
||||
layout (location = 1) in vec2 aTexCoord;
|
||||
out vec2 TexCoord;
|
||||
void main() {
|
||||
gl_Position = vec4(aPos, 0.0, 1.0); // Explicit z=0
|
||||
TexCoord = aTexCoord;
|
||||
})";
|
||||
|
||||
// ray tracing
|
||||
for(int y = 0; y < HEIGHT; ++y){
|
||||
for(int x = 0; x < WIDTH; ++x){
|
||||
float u = float(x) / float(WIDTH); // normalize 0-1
|
||||
float v = float(y) / float(HEIGHT); // normalize 0-1
|
||||
vec3 cameraRight = normalize(cross(cameraFront, cameraUp));
|
||||
|
||||
float aspectRatio = float(WIDTH) / float(HEIGHT);
|
||||
float fov = 45.0f;
|
||||
float halfHeight = tan(radians(fov / 2.0f));
|
||||
float halfWidth = aspectRatio * halfHeight;
|
||||
|
||||
vec3 direction = normalize(
|
||||
cameraFront
|
||||
+ (2.0f * u - 1.0f) * halfWidth * cameraRight
|
||||
+ (1.0f - 2.0f * v) * halfHeight * cameraUp
|
||||
);
|
||||
|
||||
Ray ray(glm::normalize(direction), cameraPos);
|
||||
vec3 color = scene.trace(ray);
|
||||
|
||||
int index = (y * WIDTH + x) * 3;
|
||||
pixels[index + 0] = static_cast<unsigned char>(color.r * 255);
|
||||
pixels[index + 1] = static_cast<unsigned char>(color.g * 255);
|
||||
pixels[index + 2] = static_cast<unsigned char>(color.b * 255);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// actualize scene
|
||||
renderScene(window, quadVAO, texture, shaderProgram, pixels);
|
||||
|
||||
}
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
// function declarations
|
||||
GLFWwindow* StartGLU() {
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "Failed to initialize GLFW" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "RAY_TRACING", nullptr, nullptr);
|
||||
if (!window) {
|
||||
std::cerr << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return nullptr;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
glewExperimental = GL_TRUE;
|
||||
if (glewInit() != GLEW_OK) {
|
||||
std::cerr << "Failed to initialize GLEW." << std::endl;
|
||||
glfwTerminate();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
return window;
|
||||
}
|
||||
GLuint CreateShaderProgram(){
|
||||
|
||||
const char* vertexShaderSource = R"(
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec2 aTexCoord;
|
||||
out vec2 TexCoord;
|
||||
void main() {
|
||||
gl_Position = vec4(aPos, 1.0);
|
||||
TexCoord = aTexCoord;
|
||||
})";
|
||||
|
||||
const char* fragmentShaderSource = R"(
|
||||
const char* fragmentShaderSource = R"(
|
||||
#version 330 core
|
||||
in vec2 TexCoord;
|
||||
out vec4 FragColor;
|
||||
|
|
@ -218,110 +70,223 @@ GLuint CreateShaderProgram(){
|
|||
FragColor = texture(screenTexture, TexCoord);
|
||||
})";
|
||||
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
// vertex shader
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
// fragment shader
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
return shaderProgram;
|
||||
}
|
||||
GLuint setupQuad() {
|
||||
float quadVertices[] = {
|
||||
// positions // texCoords
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 1.0f, 0.0f,
|
||||
-1.0f, 1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f
|
||||
return shaderProgram;
|
||||
};
|
||||
|
||||
GLuint VAO, VBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
std::vector<GLuint> QuadVAO(){
|
||||
float quadVertices[] = {
|
||||
// positions // texCoords
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, // top left
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, // bottom left
|
||||
1.0f, -1.0f, 1.0f, 0.0f, // bottom right
|
||||
|
||||
return VAO;
|
||||
}
|
||||
GLuint loadTexture(){
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
return texture;
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, // top left
|
||||
1.0f, -1.0f, 1.0f, 0.0f, // bottom right
|
||||
1.0f, 1.0f, 1.0f, 1.0f // top right
|
||||
|
||||
};
|
||||
|
||||
GLuint VAO, VBO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
std::vector<GLuint> VAOtexture = {VAO, texture};
|
||||
return VAOtexture;
|
||||
}
|
||||
void renderScene(std::vector<unsigned char> pixels) {
|
||||
// update texture w/ ray-tracing results
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, pixels.data());
|
||||
|
||||
// clear screen and draw textured quad
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
GLint textureLocation = glGetUniformLocation(shaderProgram, "screenTexture");
|
||||
glUniform1i(textureLocation, 0);
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
};
|
||||
};
|
||||
void renderScene(GLFWwindow* &window, GLuint &quadVAO, GLuint &texture, GLuint &shaderProgram, std::vector<unsigned char> &pixels){
|
||||
// Update texture with ray traced result
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WIDTH, HEIGHT, 0, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, pixels.data());
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
struct Ray{
|
||||
vec3 direction;
|
||||
vec3 origin;
|
||||
Ray(vec3 o, vec3 d) : origin(o), direction(normalize(d)){}
|
||||
};
|
||||
struct Material{
|
||||
vec3 color;
|
||||
float specular;
|
||||
float emission;
|
||||
Material(vec3 c, float s, float e) : color(c), specular(s), emission(e) {}
|
||||
};
|
||||
struct Object{
|
||||
vec3 centre;
|
||||
float radius;
|
||||
Material material;
|
||||
|
||||
Object(vec3 c, float r, Material m) : centre(c), radius(r), material(m) {}
|
||||
|
||||
bool Intersect(Ray &ray, float &t){
|
||||
vec3 oc = ray.origin - centre;
|
||||
float a = glm::dot(ray.direction, ray.direction); // ray direction scale by t
|
||||
float b = 2.0f * glm::dot(oc, ray.direction); //
|
||||
float c = glm::dot(oc, oc) - radius * radius; // adjustment by sphere radius
|
||||
double discriminant = b*b - 4*a*c;
|
||||
if(discriminant < 0){return false;} // no intersection with sphere
|
||||
|
||||
float intercept = (-b - sqrt(discriminant)) / (2.0f*a);
|
||||
if(intercept < 0){
|
||||
intercept = (-b + sqrt(discriminant)) / (2.0f*a);
|
||||
if(intercept<0){return false;} // intersection is behind origin
|
||||
}
|
||||
t = intercept;
|
||||
return true;
|
||||
};
|
||||
|
||||
vec3 getNormal(vec3 &point) const{
|
||||
return normalize(point - centre);
|
||||
}
|
||||
};
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
std::vector<Object> objs;
|
||||
vec3 lightPos;
|
||||
Scene() : lightPos(5.0f, 5.0f, 5.0f) {}
|
||||
|
||||
vec3 trace(Ray &ray){
|
||||
float closest = INFINITY;
|
||||
const Object* hitObj = nullptr;
|
||||
|
||||
for(auto& obj : objs){
|
||||
float t; // distance to intersection
|
||||
if(obj.Intersect(ray, t)){
|
||||
if(t < closest) {
|
||||
closest = t;
|
||||
hitObj = &obj;
|
||||
}
|
||||
}
|
||||
};
|
||||
if(hitObj){
|
||||
vec3 hitPoint = ray.origin + ray.direction * closest; // point on obj hit by ray
|
||||
vec3 normal = hitObj->getNormal(hitPoint);
|
||||
vec3 lightDir = normalize(lightPos - hitPoint); // direction light to hitpoint
|
||||
|
||||
float diff = std::max(glm::dot(normal, lightDir), 0.0f); // diffuse lighting
|
||||
|
||||
Ray shadowRay(hitPoint + normal * 0.001f, lightDir); // slightly up to avoid errors ;P
|
||||
// check if is in shadow
|
||||
bool inShadow = false;
|
||||
|
||||
// Actually check for shadows by testing if any object blocks light
|
||||
for(auto& obj : objs) {
|
||||
float t;
|
||||
if(obj.Intersect(shadowRay, t)) {
|
||||
inShadow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 color = hitObj->material.color;
|
||||
float ambient = 0.1f; // minimum light level
|
||||
|
||||
if (inShadow) {
|
||||
return color * ambient;
|
||||
}
|
||||
|
||||
return color * (ambient + diff * 0.9f);
|
||||
}
|
||||
|
||||
return vec3(0.0f, 0.0f, 0.1f);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// --- main loop ---- //
|
||||
int main(){
|
||||
Engine engine;
|
||||
Scene scene;
|
||||
|
||||
scene.objs = {
|
||||
Object(vec3(0.0f, 0.0f, -5.0f), 2.0f, Material(vec3(1.0f, 0.2f, 0.2f), 0.5f, 0.0f)), // Moved further back and made bigger
|
||||
Object(vec3(3.0f, 0.0f, -7.0f), 1.5f, Material(vec3(0.2f, 1.0f, 0.2f), 0.5f, 0.0f)) // Adjusted position and size
|
||||
};
|
||||
// -- loop -- //
|
||||
std::vector<unsigned char> pixels(WIDTH * HEIGHT * 3);
|
||||
while(!glfwWindowShouldClose(engine.window)){
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// render texture (pxl by pxl)
|
||||
for(int y = 0; y < HEIGHT; ++y){
|
||||
for(int x = 0; x < WIDTH; ++x){
|
||||
float aspectRatio = float(WIDTH) / float(HEIGHT);
|
||||
float u = float(x) / float(WIDTH);
|
||||
float v = float(y) / float(HEIGHT);
|
||||
|
||||
// direction of ray threw camera
|
||||
vec3 direction(
|
||||
(2.0f * u - 1.0f) * aspectRatio,
|
||||
-(2.0f * v - 1.0f), // Flipped to correct orientation
|
||||
-1.0f // Forward direction (negative z)
|
||||
);
|
||||
Ray ray(vec3(0.0f, 0.0f, 0.0f), normalize(direction));
|
||||
vec3 color = scene.trace(ray);
|
||||
|
||||
int index = (y * WIDTH + x) * 3;
|
||||
pixels[index + 0] = static_cast<unsigned char>(color.r * 255);
|
||||
pixels[index + 1] = static_cast<unsigned char>(color.g * 255);
|
||||
pixels[index + 2] = static_cast<unsigned char>(color.b * 255);
|
||||
}
|
||||
}
|
||||
|
||||
engine.renderScene(pixels);
|
||||
}
|
||||
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void UpdateCam(GLuint shaderProgram, glm::vec3 cameraPos) {
|
||||
// Calculate current frame time for smooth movement
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
}
|
||||
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
float cameraSpeed = 1.0f * deltaTime;
|
||||
|
||||
if (key == GLFW_KEY_W && (action == GLFW_PRESS || action == GLFW_REPEAT))
|
||||
cameraPos += cameraSpeed * cameraFront;
|
||||
if (key == GLFW_KEY_S && (action == GLFW_PRESS || action == GLFW_REPEAT))
|
||||
cameraPos -= cameraSpeed * cameraFront;
|
||||
if (key == GLFW_KEY_A && (action == GLFW_PRESS || action == GLFW_REPEAT))
|
||||
cameraPos -= normalize(cross(cameraFront, cameraUp)) * cameraSpeed;
|
||||
if (key == GLFW_KEY_D && (action == GLFW_PRESS || action == GLFW_REPEAT))
|
||||
cameraPos += normalize(cross(cameraFront, cameraUp)) * cameraSpeed;
|
||||
if (key == GLFW_KEY_Q && action == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
}
|
||||
void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
|
||||
|
||||
float xoffset = xpos - lastX;
|
||||
float yoffset = lastY - ypos;
|
||||
lastX = xpos;
|
||||
lastY = ypos;
|
||||
// func dec's
|
||||
|
||||
|
||||
float sensitivity = 0.1f;
|
||||
xoffset *= sensitivity;
|
||||
yoffset *= sensitivity;
|
||||
|
||||
cameraYaw += xoffset;
|
||||
cameraPitch += -yoffset;
|
||||
|
||||
if(cameraPitch > 89.0f) cameraPitch = 89.0f;
|
||||
if(cameraPitch < -89.0f) cameraPitch = -89.0f;
|
||||
|
||||
glm::vec3 front;
|
||||
front.x = cos(glm::radians(cameraYaw)) * cos(glm::radians(cameraPitch));
|
||||
front.y = sin(glm::radians(cameraPitch));
|
||||
front.z = sin(glm::radians(cameraYaw)) * cos(glm::radians(cameraPitch));
|
||||
cameraFront = glm::normalize(front);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue