Skip to content

Instantly share code, notes, and snippets.

@futurepastori
Last active January 25, 2022 11:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save futurepastori/5db4b11f72a84a6aedf57e015779571d to your computer and use it in GitHub Desktop.
Save futurepastori/5db4b11f72a84a6aedf57e015779571d to your computer and use it in GitHub Desktop.
phong
#include "application.h"
#include "utils.h"
#include "mesh.h"
#include "texture.h"
#include "light.h"
#include "volume.h"
#include "fbo.h"
#include "shader.h"
#include "input.h"
#include "animation.h"
#include "extra/hdre.h"
#include "extra/imgui/imgui.h"
#include "extra/imgui/imgui_impl_sdl.h"
#include "extra/imgui/imgui_impl_opengl3.h"
#include <cmath>
Application* Application::instance = NULL;
Camera* Application::camera = nullptr;
float cam_speed = 10;
bool render_wireframe = false;
Application::Application(int window_width, int window_height, SDL_Window* window)
{
this->window_width = window_width;
this->window_height = window_height;
this->window = window;
instance = this;
must_exit = false;
render_debug = true;
fps = 0;
frame = 0;
time = 0.0f;
elapsed_time = 0.0f;
mouse_locked = false;
// OpenGL flags
glEnable( GL_CULL_FACE ); //render both sides of every triangle
glEnable( GL_DEPTH_TEST ); //check the occlusions using the Z buffer
// Create camera
camera = new Camera();
camera->lookAt(Vector3(-5.f, 1.5f, 10.f), Vector3(0.f, 0.0f, 0.f), Vector3(0.f, 1.f, 0.f));
camera->setPerspective(45.f,window_width/(float)window_height,0.1f,10000.f); //set the projection, we want to be perspective
// Create node and add it to the scene
SceneNode * node = new SceneNode("Scene node");
node_list.push_back(node);
// Set mesh to node
Mesh* mesh = new Mesh();
mesh->createCube();
node->mesh = mesh;
// Set texture
Texture* cubemap = new Texture();
cubemap->cubemapFromImages("data/environments/city");
// Set material
StandardMaterial* material = new StandardMaterial();
material->shader = Shader::Get("data/shaders/phong.vs", "data/shaders/phong.fs");
Light* light = new Light();
material->light = light;
node->material = material;
//hide the cursor
SDL_ShowCursor(!mouse_locked); //hide or show the mouse
}
//what to do when the image has to be draw
void Application::render(void)
{
//set the clear color (the background color)
glClearColor(0, 0, 0, 1);
// Clear the window and the depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set the camera as default
camera->enable();
for (int i = 0; i < node_list.size(); i++) {
node_list[i]->render(camera);
if(render_wireframe)
node_list[i]->renderWireframe(camera);
}
//Draw the floor grid
if(render_debug)
drawGrid();
}
void Application::update(double seconds_elapsed)
{
mouse_locked = false;
float speed = seconds_elapsed * cam_speed; //the speed is defined by the seconds_elapsed so it goes constant
float orbit_speed = seconds_elapsed * 0.5f;
//camera speed modifier
if (Input::isKeyPressed(SDL_SCANCODE_LSHIFT)) speed *= 10; //move faster with left shift
float pan_speed = speed * 0.5f;
//async input to move the camera around
if (Input::isKeyPressed(SDL_SCANCODE_W) || Input::isKeyPressed(SDL_SCANCODE_UP)) camera->move(Vector3( 0.0f, 0.0f, 1.0f) * speed);
if (Input::isKeyPressed(SDL_SCANCODE_S) || Input::isKeyPressed(SDL_SCANCODE_DOWN)) camera->move(Vector3( 0.0f, 0.0f, -1.0f) * speed);
if (Input::isKeyPressed(SDL_SCANCODE_A) || Input::isKeyPressed(SDL_SCANCODE_LEFT)) camera->move(Vector3( 1.0f, 0.0f, 0.0f) * speed);
if (Input::isKeyPressed(SDL_SCANCODE_D) || Input::isKeyPressed(SDL_SCANCODE_RIGHT)) camera->move(Vector3(-1.0f, 0.0f, 0.0f) * speed);
if (!HoveringImGui())
{
//move in first person view
if (mouse_locked || Input::mouse_state & SDL_BUTTON(SDL_BUTTON_RIGHT))
{
mouse_locked = true;
camera->rotate(-Input::mouse_delta.x * orbit_speed * 0.5, Vector3(0, 1, 0));
Vector3 right = camera->getLocalVector(Vector3(1, 0, 0));
camera->rotate(-Input::mouse_delta.y * orbit_speed * 0.5, right);
}
//orbit around center
else if (Input::mouse_state & SDL_BUTTON(SDL_BUTTON_LEFT)) //is left button pressed?
{
mouse_locked = true;
camera->orbit(-Input::mouse_delta.x * orbit_speed, Input::mouse_delta.y * orbit_speed);
}
//camera panning
else if(Input::mouse_state& SDL_BUTTON(SDL_BUTTON_MIDDLE))
{
mouse_locked = true;
camera->move(Vector3(-Input::mouse_delta.x * pan_speed, 0.f, 0.f));
camera->move(Vector3(0.f, Input::mouse_delta.y * pan_speed, 0.f));
}
}
//move up or down the camera using Q and E keys
if (Input::isKeyPressed(SDL_SCANCODE_Q) || Input::isKeyPressed(SDL_SCANCODE_SPACE)) camera->moveGlobal(Vector3(0.0f, -1.0f, 0.0f) * speed);
if (Input::isKeyPressed(SDL_SCANCODE_E) || Input::isKeyPressed(SDL_SCANCODE_LCTRL)) camera->moveGlobal(Vector3(0.0f, 1.0f, 0.0f) * speed);
//to navigate with the mouse fixed in the middle
if (mouse_locked)
Input::centerMouse();
SDL_ShowCursor(!mouse_locked);
ImGui::SetMouseCursor(mouse_locked ? ImGuiMouseCursor_None : ImGuiMouseCursor_Arrow);
}
void Application::renderInMenu()
{
// Show and edit your global variables on the fly here
}
//Keyboard event handler (sync input)
void Application::onKeyDown( SDL_KeyboardEvent event )
{
switch(event.keysym.sym)
{
case SDLK_ESCAPE: must_exit = true; break; //ESC key, kill the app
case SDLK_F1: render_debug = !render_debug; break;
case SDLK_F2: render_wireframe = !render_wireframe; break;
case SDLK_F5: Shader::ReloadAll(); break;
}
}
void Application::onKeyUp(SDL_KeyboardEvent event)
{
}
void Application::onGamepadButtonDown(SDL_JoyButtonEvent event)
{
}
void Application::onGamepadButtonUp(SDL_JoyButtonEvent event)
{
}
void Application::onMouseButtonDown( SDL_MouseButtonEvent event )
{
}
void Application::onMouseButtonUp(SDL_MouseButtonEvent event)
{
}
void Application::onMouseWheel(SDL_MouseWheelEvent event)
{
bool mouse_blocked = false;
ImGuiIO& io = ImGui::GetIO();
if (!mouse_locked)
switch (event.type)
{
case SDL_MOUSEWHEEL:
{
if (event.x > 0) io.MouseWheelH += 1;
if (event.x < 0) io.MouseWheelH -= 1;
if (event.y > 0) io.MouseWheel += 1;
if (event.y < 0) io.MouseWheel -= 1;
}
}
mouse_blocked = ImGui::IsAnyWindowHovered();
if (!mouse_blocked && event.y)
{
if (mouse_locked)
cam_speed *= 1 + (event.y * 0.1);
else
camera->changeDistance(event.y * 0.5);
}
}
void Application::onResize(int width, int height)
{
std::cout << "window resized: " << width << "," << height << std::endl;
glViewport( 0,0, width, height );
camera->aspect = width / (float)height;
window_width = width;
window_height = height;
}
#include "material.h"
#include "texture.h"
#include "application.h"
StandardMaterial::StandardMaterial()
{
color = Vector4(1.f, 1.f, 1.f, 1.f);
// No canvia res independentment dels valors que posem aquí,
// en tot cas agafarà el color de la línia anterior
diffuse_k = Vector3(1.0, 1.0, 1.0);
ambient_k = Vector3(1.0, 1.0, 1.0);
ambient_k = Vector3(1.0, 1.0, 1.0);
alpha = 30.0;
}
StandardMaterial::~StandardMaterial()
{
}
void StandardMaterial::setUniforms(Camera* camera, Matrix44 model)
{
//upload node uniforms
shader->setUniform("u_viewprojection", camera->viewprojection_matrix);
shader->setUniform("u_camera_position", camera->eye);
shader->setUniform("u_model", model);
shader->setUniform("u_time", Application::instance->time);
shader->setUniform("u_color", color);
if (texture)
shader->setUniform("u_texture", texture);
if (light) {
shader->setUniform("light_position", light->position);
shader->setUniform("diffuse_i", light->diffuse_color);
shader->setUniform("specular_i", light->specular_color);
shader->setUniform("ambient_i", light->ambient_color);
shader->setUniform("diffuse_k", diffuse_k);
shader->setUniform("specular_k", specular_k);
shader->setUniform("ambient_k", ambient_k);
shader->setFloat("alpha", alpha);
}
}
void StandardMaterial::render(Mesh* mesh, Matrix44 model, Camera* camera)
{
//set flags
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
if (mesh && shader)
{
//enable shader
shader->enable();
//upload uniforms
setUniforms(camera, model);
//do the draw call
mesh->render(GL_TRIANGLES);
//disable shader
shader->disable();
}
}
void StandardMaterial::renderInMenu()
{
ImGui::ColorEdit3("Color", (float*)&color); // Edit 3 floats representing a color
}
WireframeMaterial::WireframeMaterial()
{
color = vec4(1.f, 1.f, 1.f, 1.f);
shader = Shader::Get("data/shaders/basic.vs", "data/shaders/flat.fs");
}
WireframeMaterial::~WireframeMaterial()
{
}
void WireframeMaterial::render(Mesh* mesh, Matrix44 model, Camera * camera)
{
if (shader && mesh)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//enable shader
shader->enable();
//upload material specific uniforms
setUniforms(camera, model);
//do the draw call
mesh->render(GL_TRIANGLES);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
varying vec3 v_position;
varying vec3 v_world_position;
varying vec3 v_normal;
varying vec2 v_uv;
varying vec4 v_color;
// uniforms
uniform vec3 diffuse_k;
uniform vec3 diffuse_i;
uniform float alpha;
uniform vec3 specular_k;
uniform vec3 specular_i;
uniform vec3 ambient_k;
uniform vec3 ambient_i;
uniform vec3 light_position;
uniform vec3 u_camera_position;
uniform vec4 u_color;
void main()
{
//here we set up the normal as a color to see them as a debug
//here write the computations for PHONG.
//for GOURAUD you dont need to do anything here, just pass the color from the vertex shader
vec3 N = normalize(v_normal);
vec3 L = normalize( light_position - v_world_position);
vec3 E = normalize( u_camera_position - v_world_position);
vec3 R = normalize(reflect(E, N));
float NdotL = max(0.0, dot(N,L));
float RdotL = pow(max(0.0, dot(-R,L)), alpha);
vec3 color = ambient_k * ambient_i + diffuse_k * diffuse_i * NdotL + specular_k * specular_i * RdotL;
//set the ouput color por the pixel
gl_FragColor = vec4( color, 1.0 )*u_color;
}
attribute vec3 a_vertex;
attribute vec3 a_normal;
attribute vec2 a_uv;
attribute vec4 a_color;
uniform vec3 u_camera_pos;
uniform mat4 u_model;
uniform mat4 u_viewprojection;
//this will store the color for the pixel shader
varying vec3 v_position;
varying vec3 v_world_position;
varying vec3 v_world_normal;
varying vec3 v_normal;
varying vec2 v_uv;
varying vec4 v_color;
void main()
{
//calcule the normal in camera space (the NormalMatrix is like ViewMatrix but without traslation)
v_normal = (u_model * vec4( a_normal, 0.0) ).xyz;
v_world_normal = (u_model * vec4( gl_Normal.xyz, 0.0)).xyz;
//calcule the vertex in object space
v_position = a_vertex;
v_world_position = (u_model * vec4( v_position, 1.0) ).xyz;
//store the color in the varying var to use it from the pixel shader
v_color = a_color;
//store the texture coordinates
v_uv = a_uv;
//calcule the position of the vertex using the matrices
gl_Position = u_viewprojection * vec4( v_world_position, 1.0 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment