added shading to objects

This commit is contained in:
kavan 2025-07-30 20:35:22 -04:00 committed by GitHub
parent 1a8b15b408
commit aa99620986
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -26,6 +26,7 @@ int framesCount = 0;
double c = 299792458.0;
double G = 6.67430e-11;
struct Ray;
bool Gravity = false;
struct Camera {
// Center the camera orbit on the black hole at (0, 0, 0)
@ -42,6 +43,7 @@ struct Camera {
bool dragging = false;
bool panning = false;
bool moving = false; // For compute shader optimization
double lastX = 0.0, lastY = 0.0;
// Calculate camera position in world space
@ -57,6 +59,11 @@ struct Camera {
void update() {
// Always keep target at black hole center
target = vec3(0.0f, 0.0f, 0.0f);
if(dragging | panning) {
moving = true;
} else {
moving = false;
}
}
void processMouseMove(double x, double y) {
@ -92,9 +99,9 @@ struct Camera {
}
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
if (action == GLFW_PRESS) {
panning = true;
Gravity = true;
} else if (action == GLFW_RELEASE) {
panning = false;
Gravity = false;
}
}
}
@ -103,6 +110,12 @@ struct Camera {
radius = clamp(radius, minRadius, maxRadius);
update();
}
void processKey(int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS && key == GLFW_KEY_G) {
Gravity = !Gravity;
cout << "[INFO] Gravity turned " << (Gravity ? "ON" : "OFF") << endl;
}
}
};
Camera camera;
@ -126,11 +139,12 @@ struct ObjectData {
vec4 posRadius; // xyz = position, w = radius
vec4 color; // rgb = color, a = unused
float mass;
vec3 velocity = vec3(0.0f, 0.0f, 0.0f); // Initial velocity
};
vector<ObjectData> objects = {
{ vec4(4e11f, 0.0f, 0.0f, 4e10f) ,vec4(1,1,0,1), 1.98892e30 },
{ vec4(0.0f, 0.0f, 4e11f, 4e10f) ,vec4(1,0,0,1), 1.98892e30 },
{ vec4(0.0f, 0.0f, 0.0f, SagA.r_s) ,vec4(0,0,0,1), SagA.mass },
{ vec4(4e11f, 0.0f, 0.0f, 4e10f) , vec4(1,1,0,1), 1.98892e30 },
{ vec4(0.0f, 0.0f, 4e11f, 4e10f) , vec4(1,0,0,1), 1.98892e30 },
{ vec4(0.0f, 0.0f, 0.0f, SagA.r_s) , vec4(0,0,0,1), SagA.mass },
//{ vec4(6e10f, 0.0f, 0.0f, 5e10f), vec4(0,1,0,1) }
};
@ -154,8 +168,8 @@ struct Engine {
int WIDTH = 800; // Window width
int HEIGHT = 600; // Window height
int COMPUTE_WIDTH = 400; // Compute resolution width
int COMPUTE_HEIGHT = 300; // Compute resolution height
int COMPUTE_WIDTH = 200; // Compute resolution width
int COMPUTE_HEIGHT = 150; // Compute resolution height
float width = 100000000000.0f; // Width of the viewport in meters
float height = 75000000000.0f; // Height of the viewport in meters
@ -213,8 +227,8 @@ struct Engine {
this->texture = result[1];
}
void generateGrid(const vector<ObjectData>& objects) {
const int gridSize = 100;
const float spacing = 2e10f; // tweak this
const int gridSize = 25;
const float spacing = 1e10f; // tweak this
vector<vec3> vertices;
vector<GLuint> indices;
@ -448,24 +462,36 @@ struct Engine {
return prog;
}
void dispatchCompute(const Camera& cam) {
// 1) bind your compute pipeline
// determine target computeres
int cw = cam.moving ? COMPUTE_WIDTH : 200;
int ch = cam.moving ? COMPUTE_HEIGHT : 150;
// 1) reallocate the texture if needed
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D,
0, // mip
GL_RGBA8, // internal format
cw, // width
ch, // height
0, GL_RGBA,
GL_UNSIGNED_BYTE,
nullptr);
// 2) bind compute program & UBOs
glUseProgram(computeProgram);
uploadCameraUBO(cam);
uploadDiskUBO();
// object
uploadObjectsUBO(objects);
// 3) bind your rendertexture as image unit 0
// 3) bind it as image unit 0
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
// 4) launch the compute grid (16×16 workgroups)
GLuint groupsX = (GLuint)std::ceil(static_cast<float>(COMPUTE_WIDTH) / 16.0f);
GLuint groupsY = (GLuint)std::ceil(static_cast<float>(COMPUTE_HEIGHT) / 16.0f);
// 4) dispatch grid
GLuint groupsX = (GLuint)std::ceil(cw / 16.0f);
GLuint groupsY = (GLuint)std::ceil(ch / 16.0f);
glDispatchCompute(groupsX, groupsY, 1);
// 5) make sure writes are visible to the rendering pipeline
// 5) sync
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
}
void uploadCameraUBO(const Camera& cam) {
@ -520,7 +546,7 @@ struct Engine {
void uploadDiskUBO() {
// disk
float r1 = SagA.r_s * 2.2f; // inner radius just outside the event horizon
float r2 = SagA.r_s * 4.2f; // outer radius of the disk
float r2 = SagA.r_s * 5.2f; // outer radius of the disk
float num = 2.0; // number of rays
float thickness = 1e9f; // padding for std140 alignment
float diskData[4] = { r1, r2, num, thickness };
@ -586,7 +612,7 @@ struct Engine {
};
Engine engine;
void setupCameraCallbacks(GLFWwindow* window) {
glfwSetWindowUserPointer(window, &camera); // So callbacks can access the camera
glfwSetWindowUserPointer(window, &camera);
glfwSetMouseButtonCallback(window, [](GLFWwindow* win, int button, int action, int mods) {
Camera* cam = (Camera*)glfwGetWindowUserPointer(win);
@ -602,8 +628,14 @@ void setupCameraCallbacks(GLFWwindow* window) {
Camera* cam = (Camera*)glfwGetWindowUserPointer(win);
cam->processScroll(xoffset, yoffset);
});
glfwSetKeyCallback(window, [](GLFWwindow* win, int key, int scancode, int action, int mods) {
Camera* cam = (Camera*)glfwGetWindowUserPointer(win);
cam->processKey(key, scancode, action, mods);
});
}
// -- MAIN -- //
int main() {
setupCameraCallbacks(engine.window);
@ -612,30 +644,59 @@ int main() {
auto t0 = Clock::now();
lastPrintTime = chrono::duration<double>(t0.time_since_epoch()).count();
double lastTime = glfwGetTime();
int renderW = 800, renderH = 600, numSteps = 80000;
while (!glfwWindowShouldClose(engine.window)) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // optional, but good practice
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1) adjust computetexture size if camera is dragging
// glBindTexture(GL_TEXTURE_2D, engine.texture);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
// engine.COMPUTE_WIDTH,
// engine.COMPUTE_HEIGHT,
// 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
double now = glfwGetTime();
double dt = now - lastTime; // seconds since last frame
lastTime = now;
// Gravity
for (auto& obj : objects) {
for (auto& obj2 : objects) {
if (&obj == &obj2) continue; // skip self-interaction
float dx = obj2.posRadius.x - obj.posRadius.x;
float dy = obj2.posRadius.y - obj.posRadius.y;
float dz = obj2.posRadius.z - obj.posRadius.z;
float distance = sqrt(dx * dx + dy * dy + dz * dz);
if (distance > 0) {
vector<double> direction = {dx / distance, dy / distance, dz / distance};
//distance *= 1000;
double Gforce = (G * obj.mass * obj2.mass) / (distance * distance);
double acc1 = Gforce / obj.mass;
std::vector<double> acc = {direction[0] * acc1, direction[1] * acc1, direction[2] * acc1};
if (Gravity) {
obj.velocity.x += acc[0];
obj.velocity.y += acc[1];
obj.velocity.z += acc[2];
obj.posRadius.x += obj.velocity.x;
obj.posRadius.y += obj.velocity.y;
obj.posRadius.z += obj.velocity.z;
cout << "velocity: " <<obj.velocity.x<<", " <<obj.velocity.y<<", " <<obj.velocity.z<<endl;
}
}
}
}
// ---------- GRID ------------- //
// 2) rebuild grid mesh on CPU
engine.generateGrid(objects);
// 5) overlay the bent grid
mat4 view = lookAt(camera.position(), camera.target, vec3(0,1,0));
mat4 proj = perspective(radians(60.0f), float(engine.COMPUTE_WIDTH)/engine.COMPUTE_HEIGHT, 1e9f, 1e14f);
mat4 viewProj = proj * view;
engine.drawGrid(viewProj);
// 3) update UBOs & run the raytracer
// ---------- RUN RAYTRACER ------------- //
glViewport(0, 0, engine.WIDTH, engine.HEIGHT);
engine.dispatchCompute(camera);
// 4) draw the raytraced image
engine.drawFullScreenQuad();
// 6) present to screen