Skip to content

Commit

Permalink
Render one sphere as a light source (sun)
Browse files Browse the repository at this point in the history
  • Loading branch information
joelvaz0x01 committed Dec 21, 2023
1 parent 32370a9 commit b4c37f5
Show file tree
Hide file tree
Showing 19 changed files with 473 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@
# Build files
cmake-*/
build/
bin/
51 changes: 46 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.5)
project(solar_system VERSION 1.0)

# set output directory to ${CMAKE_SOURCE_DIR}/bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

find_package(OpenGL REQUIRED)

set(SOLAR_SYSTEM solar_system.out)
Expand All @@ -22,13 +25,51 @@ set(ALL_LIBS
GLAD
)

file(GLOB SHADERS
"src/shaders/*.glsl"
)

file(GLOB SRC_SOLAR_SYSTEM
"src/main.cpp"
"src/*.h"
"src/*.cpp"
${SHADERS}
)

add_executable(${SOLAR_SYSTEM} ${SRC_SOLAR_SYSTEM})
target_link_libraries(${SOLAR_SYSTEM} ${ALL_LIBS})

add_custom_command(
TARGET ${SOLAR_SYSTEM} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${SOLAR_SYSTEM}${CMAKE_EXECUTABLE_SUFFIX}" "${CMAKE_CURRENT_SOURCE_DIR}/bin/"
)
# create directory for shaders on ${CMAKE_SOURCE_DIR}/bin
if(WIN32)
add_custom_command(TARGET ${SOLAR_SYSTEM} PRE_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${SOLAR_SYSTEM}>/shaders)
elseif(UNIX AND NOT APPLE)
file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/shaders)
elseif(APPLE)
file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/shaders)
endif(WIN32)

# copy shaders to ${CMAKE_SOURCE_DIR}/bin/shaders directory
foreach(SHADER ${SHADERS})
if(WIN32)
add_custom_command(
TARGET ${SOLAR_SYSTEM} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${SHADER} $<TARGET_FILE_DIR:${SOLAR_SYSTEM}>/shaders
)
elseif(UNIX AND NOT APPLE)
file(COPY ${SHADER} DESTINATION ${CMAKE_SOURCE_DIR}/bin/)
elseif(APPLE)
get_filename_component(SHADER_NAME ${SHADER} NAME)
makeLink(${SHADER} ${CMAKE_SOURCE_DIR}/bin/${SHADER_NAME} ${SOLAR_SYSTEM})
endif(WIN32)
endforeach(SHADER)

# copy resources to ${CMAKE_SOURCE_DIR}/bin/resources directory
if(WIN32)
add_custom_command(
TARGET ${SOLAR_SYSTEM} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/resources $<TARGET_FILE_DIR:${SOLAR_SYSTEM}>/resources
)
elseif(UNIX AND NOT APPLE)
file(COPY ${CMAKE_SOURCE_DIR}/resources DESTINATION ${CMAKE_SOURCE_DIR}/bin/)
elseif(APPLE)
makeLink(${CMAKE_SOURCE_DIR}/resources ${CMAKE_SOURCE_DIR}/bin/resources ${SOLAR_SYSTEM})
endif(WIN32)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# computer-graphics-project
# Solar system made with OpenGL
Binary file added resources/textures/earth.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/earth_clouds.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/jupiter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/mars.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/mercury.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/moon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/neptune.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/saturn.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/saturn_ring.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/sun.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/uranus.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/textures/venus.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
222 changes: 219 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
/**
* @file main.cpp
* @brief
* @details
* @brief Solar System made with OpenGL
*
* Controls:
* - W, A, S and D keys: move the camera
* - Q key: move the camera down
* - E key: move the camera up
* - Mouse: look around
* - Mouse scroll-wheel: zoom in and out
* - ESC key: close the window
*
* @author joelvaz0x01
* @author BrunoFG1
Expand All @@ -27,6 +34,16 @@
#define WIDTH 1920 /// width of the screen
#define HEIGHT 1080 /// height of the screen

Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); /// camera position
double lastX = WIDTH / 2.0f; /// last x position of the mouse
double lastY = HEIGHT / 2.0f; /// last y position of the mouse

double deltaTime = 0.0f; /// time between current frame and last frame
double lastFrame = 0.0f; /// time of last frame

unsigned int sphereVAO = 0; /// vertex array object for sphere
GLsizei indexCount; /// number of indices for sphere

int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
Expand Down Expand Up @@ -60,12 +77,63 @@ int main() {
// per-sample processing operation performed after the Fragment Shader
glEnable(GL_DEPTH_TEST);

// compile shaders
Shader shader("shaders/vertexShader.glsl", "shaders/fragmentShader.glsl");

shader.use();
shader.setInt("albedoMap", 0);
shader.setInt("normalMap", 1);
shader.setInt("metallicMap", 2);
shader.setInt("roughnessMap", 3);
shader.setInt("aoMap", 4);

// load planet textures
unsigned int sunTexture = loadTexture("resources/textures/sun.jpg");

// light properties
glm::vec3 lightPositions[] = {glm::vec3(0.0f, 0.0f, 0.0f),};
glm::vec3 lightColors[] = {glm::vec3(10.0f, 10.0f, 10.0f),};

// projection matrix
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float) WIDTH / (float) HEIGHT, 0.1f, 100.0f);
shader.use();
shader.setMat4("projection", projection);

while (!glfwWindowShouldClose(window)) {
double currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;

processInput(window);

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

shader.use();
glm::mat4 view = camera.GetViewMatrix();
shader.setMat4("view", view);
shader.setVec3("camPos", camera.Position);

// bind textures
bindTexture(sunTexture, 0);

glm::mat4 model = glm::mat4(1.0f);

// render the light source (sun)
unsigned int lightPositionSize = sizeof(lightPositions) / sizeof(lightPositions[0]);
for (unsigned int i = 0; i < lightPositionSize; ++i) {
glm::vec3 newPos = lightPositions[i] + glm::vec3(sin(glfwGetTime() * 5.0) * 5.0, 0.0, 0.0);
newPos = lightPositions[i];
shader.setVec3("lightPositions[" + std::to_string(i) + "]", newPos);
shader.setVec3("lightColors[" + std::to_string(i) + "]", lightColors[i]);

model = glm::mat4(1.0f);
model = glm::translate(model, newPos);
shader.setMat4("model", model);
shader.setMat3("normalMatrix", glm::transpose(glm::inverse(glm::mat3(model))));
renderSphere();
}

// swap buffers and poll IO events
glfwSwapBuffers(window);
glfwPollEvents();
Expand All @@ -82,6 +150,13 @@ int main() {
*/
void processInput(GLFWwindow *window) {
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true);

if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) camera.ProcessKeyboard(FORWARD, (float) deltaTime);
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) camera.ProcessKeyboard(BACKWARD, (float) deltaTime);
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) camera.ProcessKeyboard(LEFT, (float) deltaTime);
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) camera.ProcessKeyboard(RIGHT, (float) deltaTime);
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) camera.ProcessKeyboard(UPWARD, (float) deltaTime);
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) camera.ProcessKeyboard(DOWNWARD, (float) deltaTime);
}

/** Function to resize window size if changed (by OS or user resize)
Expand All @@ -92,7 +167,6 @@ void processInput(GLFWwindow *window) {
* @return nullptr
*/
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {

glViewport(0, 0, width, height);
}

Expand All @@ -104,6 +178,13 @@ void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
* @return nullptr
*/
void mouse_callback(GLFWwindow *window, double x_pos, double y_pos) {
double x_offset = x_pos - lastX;
double y_offset = lastY - y_pos; // reversed since y-coordinates go from bottom to top

lastX = x_pos;
lastY = y_pos;

camera.ProcessMouseMovement((float) x_offset, (float) y_offset);
}

/**
Expand All @@ -115,6 +196,136 @@ void mouse_callback(GLFWwindow *window, double x_pos, double y_pos) {
* @return nullptr
*/
void scroll_callback(GLFWwindow *window, double x_offset, double y_offset) {
camera.ProcessMouseScroll(static_cast<float>(y_offset));
}

/** Function to render sphere
*
* @return nullptr
*/
void renderSphere() {
if (sphereVAO == 0) { // first time initializing sphere
glGenVertexArrays(1, &sphereVAO);

// vertex buffer object, element buffer object
unsigned int vbo, ebo;
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);

std::vector<glm::vec3> positions;
std::vector<glm::vec2> uv;
std::vector<glm::vec3> normals;
std::vector<unsigned int> indices;

const unsigned int STEP = 64; // increase to improve shape quality
const float PI = 3.14159265359f;
const float distance = 1.0f; // distance from center (0,0)

// create sphere
for (unsigned int x = 0; x <= STEP; ++x) {
for (unsigned int y = 0; y <= STEP; ++y) {
// calculate the UV coordinates (two-dimensional texture coordinates)
float xSegment = (float) x / (float) STEP; // u coordinate (horizontal)
float ySegment = (float) y / (float) STEP; // v coordinate (vertical)

// calculate the position of each vertex (same for normals)
// see more at: https://mathinsight.org/spherical_coordinates
float xPos = distance * std::sin(ySegment * PI) * std::cos(xSegment * 2.0f * PI);
float yPos = distance * std::sin(ySegment * PI) * std::sin(xSegment * 2.0f * PI);
float zPos = distance * std::cos(ySegment * PI);

// add the elements to the end of each vector
positions.emplace_back(xPos, yPos, zPos);
uv.emplace_back(xSegment, ySegment);
normals.emplace_back(xPos, yPos, zPos);
}
}

// generate indices
// see more at: https://opentk.net/learn/chapter1/3-element-buffer-objects.html
bool oddRow = false;
for (unsigned int y = 0; y < STEP; ++y) {
if (!oddRow) {
// even rows move left to right
for (unsigned int x = 0; x <= STEP; ++x) {
indices.push_back(y * (STEP + 1) + x);
indices.push_back((y + 1) * (STEP + 1) + x);
}
} else {
// odd rows move right to left
for (int x = STEP; x >= 0; --x) {
indices.push_back((y + 1) * (STEP + 1) + x);
indices.push_back(y * (STEP + 1) + x);
}
}
oddRow = !oddRow;
}

// calculate the number of indices (size of indices vector)
indexCount = static_cast<GLsizei>(indices.size());

// store all the data in one vector (positions, normals and uv)
std::vector<float> data;
for (unsigned int i = 0; i < positions.size(); ++i) {
data.push_back(positions[i].x);
data.push_back(positions[i].y);
data.push_back(positions[i].z);
if (!normals.empty()) {
data.push_back(normals[i].x);
data.push_back(normals[i].y);
data.push_back(normals[i].z);
}
if (!uv.empty()) {
data.push_back(uv[i].x);
data.push_back(uv[i].y);
}
}
glBindVertexArray(sphereVAO);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
GLsizei stride = (3 + 2 + 3) * sizeof(float); // 3 for position, 2 for uv, 3 for normal

// vertex attribute
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
stride, // stride
(void *) nullptr // array buffer offset
);
glEnableVertexAttribArray(0);

// normal attribute
glVertexAttribPointer(
1, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
stride, // stride
(void *) (3 * sizeof(float)) // array buffer offset
);
glEnableVertexAttribArray(1);

// texture attribute
glVertexAttribPointer(
2, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
stride, // stride
(void *) (6 * sizeof(float)) // array buffer offset
);
glEnableVertexAttribArray(2);
}

glBindVertexArray(sphereVAO);

// GL_TRIANGLE_STRIP is to ensure that the triangles are all drawn with the same orientation
// see more at: https://www.khronos.org/opengl/wiki/Primitive#Triangle_primitives
glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, nullptr);
}

/** Function to load 2D texture from file
Expand Down Expand Up @@ -154,3 +365,8 @@ unsigned int loadTexture(char const *path) {
}
return textureID;
}

void bindTexture(unsigned int texture, unsigned int textureUnit) {
glActiveTexture(GL_TEXTURE + textureUnit);
glBindTexture(GL_TEXTURE_2D, texture);
}
4 changes: 4 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ void scroll_callback(GLFWwindow *window, double x_offset, double y_offset);
void processInput(GLFWwindow *window);

unsigned int loadTexture(const char *path);

void renderSphere();

void bindTexture(unsigned int texture, unsigned int textureUnit);
Loading

0 comments on commit b4c37f5

Please sign in to comment.