Fixed heissenbug caused by quat initialization and added sound server.
This commit is contained in:
+3
-1
@@ -6,6 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
include(FindPkgConfig)
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(SDL2 REQUIRED)
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
|
||||
include_directories("src/")
|
||||
include_directories("gl/include")
|
||||
@@ -30,4 +32,4 @@ set(SOURCE
|
||||
)
|
||||
|
||||
add_executable(demo main.cpp gl/src/glad.c ${SOURCE} lib/easyloggingpp/src/easylogging++.cc)
|
||||
target_link_libraries(demo glfw OpenGL::GL)
|
||||
target_link_libraries(demo glfw OpenGL::GL ${SDL2_LIBRARIES})
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <memory>
|
||||
#include <iterator>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
@@ -7,6 +8,8 @@
|
||||
#include "peripherals_glfw.h"
|
||||
#include "demo/demo_engine.h"
|
||||
#include "timer.h"
|
||||
#include "audio/sound_server.h"
|
||||
#include <bitset>
|
||||
|
||||
using namespace acidrain;
|
||||
using namespace std;
|
||||
@@ -15,30 +18,30 @@ INITIALIZE_EASYLOGGINGPP
|
||||
|
||||
int main() {
|
||||
acidrain::peripherals_glfw peripherals;
|
||||
peripherals.init();
|
||||
peripherals.init(demo_data::screen_width, demo_data::screen_height, "acidrain", false);
|
||||
LOG(INFO) << "peripherals initialized";
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
const float DEMO_LENGTH_IN_SECONDS = 100;
|
||||
const float DEMO_LENGTH_IN_SECONDS = 1000;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Load resources
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
acidrain::texture_generator tg(256, 256);
|
||||
tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
|
||||
// tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
|
||||
// tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
|
||||
tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
|
||||
|
||||
shared_ptr<mesh> affectedSphere = mesh_generator::sphere(50, 50);
|
||||
map_transform(affectedSphere, tg, 0, 0, 0.2f);
|
||||
calculate_normals(*affectedSphere.get());
|
||||
shared_ptr<mesh> affected_sphere = mesh_generator::sphere(50, 50);
|
||||
map_transform(affected_sphere, tg, 0, 0, 0.2f);
|
||||
calculate_normals(*affected_sphere);
|
||||
|
||||
// affectedSphere = mesh_generator::cog(0.2, 0.5, 50, 4, 0.1, 0.2, 0.2, 0.1);
|
||||
|
||||
demo_data::meshes.push_back(affectedSphere);
|
||||
demo_data::meshes.push_back(affected_sphere);
|
||||
demo_data::meshes.push_back(mesh_generator::sphere(3, 3));
|
||||
demo_data::meshes.push_back(mesh_generator::grid(30, 30));
|
||||
demo_data::meshes.push_back(mesh_generator::grid(1, 1));
|
||||
demo_data::meshes.push_back(mesh_generator::cube());
|
||||
|
||||
auto mat = std::make_shared<material>();
|
||||
@@ -49,21 +52,21 @@ int main() {
|
||||
mat->shininess = 200;
|
||||
mat->cast_shadows = true;
|
||||
|
||||
auto *textureGenerator1 = new texture_generator(256, 256);
|
||||
// mat->textures[texture_role::diffuse] = textureGenerator1->checker_board(0, 20,
|
||||
// colour(1, 1, 1, 1),
|
||||
// colour(0, 0.5, 0.2, 1)).get_texture(0);
|
||||
mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
|
||||
50, 20,
|
||||
4,
|
||||
colour(0.3, 0.1, 0, 1),
|
||||
colour(1, 0.3, 0, 1)).get_texture(0);
|
||||
auto *texgen = new texture_generator(256, 256);
|
||||
mat->textures[texture_role::diffuse] = texgen->checker_board(0, 20,
|
||||
colour(1, 1, 1, 1),
|
||||
colour(0, 0.5, 0.2, 1)).get_texture(0);
|
||||
// mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
|
||||
// 50, 20,
|
||||
// 4,
|
||||
// colour(0.3, 0.1, 0, 1),
|
||||
// colour(1, 0.3, 0, 1)).get_texture(0);
|
||||
|
||||
demo_data::materials.push_back(mat);
|
||||
|
||||
auto material2 = make_shared<material>();
|
||||
material2->ambient = glm::vec4(0, 0, 0.15, 1);
|
||||
material2->textures[texture_role::diffuse] = textureGenerator1->get_texture(0);
|
||||
material2->textures[texture_role::diffuse] = texgen->get_texture(0);
|
||||
// material2->diffuse = glm::vec4(0.2, 1.0, 0.7, 1);
|
||||
material2->diffuse = glm::vec4(1, 1, 1, 1);
|
||||
material2->specular = glm::vec4(0.3, 0.3, 0.3, 1);
|
||||
@@ -102,14 +105,14 @@ int main() {
|
||||
// Set up demo parts
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
DemoPartClear demoPartClear;
|
||||
demoPartClear.startTime = 0;
|
||||
demoPartClear.endTime = DEMO_LENGTH_IN_SECONDS;
|
||||
demo_part_clear demoPartClear;
|
||||
demoPartClear.start_time = 0;
|
||||
demoPartClear.end_time = DEMO_LENGTH_IN_SECONDS;
|
||||
demoPartClear.color = glm::vec4(0.1f, 0.1f, 0.3f, 1.0f);
|
||||
|
||||
DemoPartScene demoPartScene;
|
||||
demoPartScene.startTime = 0;
|
||||
demoPartScene.endTime = DEMO_LENGTH_IN_SECONDS;
|
||||
demo_part_scene demoPartScene;
|
||||
demoPartScene.start_time = 0;
|
||||
demoPartScene.end_time = DEMO_LENGTH_IN_SECONDS;
|
||||
demoPartScene.cameraName = "cam1";
|
||||
demoPartScene.lightName = "light1";
|
||||
|
||||
@@ -135,21 +138,21 @@ int main() {
|
||||
back_plane->material_ = demo_data::materials[1];
|
||||
back_plane->position = glm::vec3(0, 5, -5);
|
||||
back_plane->scale = glm::vec3(10);
|
||||
back_plane->rotation = angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
back_plane->rotation = glm::angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
|
||||
auto left_plane = std::make_shared<mesh_node>("left plane");
|
||||
left_plane->mesh_ = demo_data::meshes[2];
|
||||
left_plane->material_ = demo_data::materials[1];
|
||||
left_plane->position = glm::vec3(-5, 5, 0);
|
||||
left_plane->scale = glm::vec3(10);
|
||||
left_plane->rotation = angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
left_plane->rotation = glm::angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
auto right_plane = std::make_shared<mesh_node>("right plane");
|
||||
right_plane->mesh_ = demo_data::meshes[2];
|
||||
right_plane->material_ = demo_data::materials[1];
|
||||
right_plane->position = glm::vec3(5, 5, 0);
|
||||
right_plane->scale = glm::vec3(10);
|
||||
right_plane->rotation = angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
right_plane->rotation = glm::angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
auto bigSphere = make_shared<mesh_node>("big sphere");
|
||||
bigSphere->mesh_ = demo_data::meshes[0];
|
||||
@@ -178,7 +181,7 @@ int main() {
|
||||
lightNode->spot_cutoff = 50.0f;
|
||||
lightNode->spot_exponent = 16.0f;
|
||||
lightNode->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
||||
lightNode->diffuse = glm::vec4(0.5, 1.0, 1.0, 1.0);
|
||||
lightNode->diffuse = glm::vec4(0.1, 0.3, 1.0, 1.0);
|
||||
lightNode->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
|
||||
|
||||
auto lightNode2 = make_shared<light_node>(light_type::spot);
|
||||
@@ -188,8 +191,8 @@ int main() {
|
||||
lightNode2->spot_cutoff = 50.0f;
|
||||
lightNode2->spot_exponent = 16.0f;
|
||||
lightNode2->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
|
||||
lightNode2->diffuse = glm::vec4(1.0, 0.5, 1.0, 1.0);
|
||||
lightNode2->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
|
||||
lightNode2->diffuse = glm::vec4(1.0, 0.5, 0.3, 1.0);
|
||||
lightNode2->specular = glm::vec4(1.0, 0.8, 0.1, 1.0);
|
||||
|
||||
scene1->tree->add(ground_plane);
|
||||
scene1->tree->add(back_plane);
|
||||
@@ -213,14 +216,15 @@ int main() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw*)&peripherals)->get_window(), true);
|
||||
ImGui_ImplOpenGL3_Init("#version 150");
|
||||
// IMGUI_CHECKVERSION();
|
||||
// ImGui::CreateContext();
|
||||
// ImGuiIO& io = ImGui::GetIO();
|
||||
// (void) io;
|
||||
// ImGui::StyleColorsDark();
|
||||
//
|
||||
// // Setup Platform/Renderer backends
|
||||
// ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw *) &peripherals)->get_window(), true);
|
||||
// ImGui_ImplOpenGL3_Init("#version 150");
|
||||
|
||||
timer timer1;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
@@ -228,56 +232,57 @@ int main() {
|
||||
bool show_another_window = false;
|
||||
|
||||
while (!peripherals.should_close() && timer1.seconds_since_start() < DEMO_LENGTH_IN_SECONDS) {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
// ImGui_ImplOpenGL3_NewFrame();
|
||||
// ImGui_ImplGlfw_NewFrame();
|
||||
// ImGui::NewFrame();
|
||||
//
|
||||
// {
|
||||
// static float f = 0.0f;
|
||||
// static int counter = 0;
|
||||
//
|
||||
// ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
//
|
||||
// ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
// ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
// ImGui::Checkbox("Another Window", &show_another_window);
|
||||
//
|
||||
// ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
// ImGui::ColorEdit3("clear color", (float *) &clear_color); // Edit 3 floats representing a color
|
||||
//
|
||||
// if (ImGui::Button(
|
||||
// "Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
// counter++;
|
||||
// ImGui::SameLine();
|
||||
// ImGui::Text("counter = %d", counter);
|
||||
//
|
||||
// ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
// ImGui::End();
|
||||
// }
|
||||
|
||||
|
||||
double elapsedSeconds = timer1.seconds_since_start();
|
||||
auto elapsed_seconds = timer1.seconds_since_start();
|
||||
bigSphere->mesh_ = mesh_generator::extrude(mesh_generator::sphere(50, 50), {200, 201, 100, 101, 400, 401}, 0.05,
|
||||
(int) ((sin(elapsedSeconds) + 0.5) * 40));
|
||||
(int) ((sinf(elapsed_seconds) + 0.5f) * 40));
|
||||
|
||||
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsedSeconds) * 2.0 + 0.5, 0);
|
||||
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsed_seconds) * 2.0 + 0.5, 0);
|
||||
// meshNode->position = glm::vec3(0, 0.001, 0);
|
||||
// camNode->target = glm::vec3(0, 0.0001, 0);
|
||||
// camNode->position = glm::vec3(0, 5, -10);
|
||||
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsedSeconds), 2,
|
||||
5 * cos(2 * M_PI * 0.05 * elapsedSeconds));
|
||||
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsedSeconds), 2,
|
||||
5 * sin(2 * M_PI * 0.75 * elapsedSeconds));
|
||||
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsed_seconds), 2,
|
||||
5 * cos(2 * M_PI * 0.05 * elapsed_seconds));
|
||||
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsed_seconds), 2,
|
||||
5 * sin(2 * M_PI * 0.75 * elapsed_seconds));
|
||||
|
||||
lightMeshNode->position = lightNode2->position;
|
||||
|
||||
bigSphere->rotation *= angleAxis((float) (M_PI / 4.0 * timer1.lap()), normalize(glm::vec3(0.2, 0.5, 0.3)));
|
||||
|
||||
|
||||
demoPartClear.process(demoPartClear.normalizeTime(elapsedSeconds));
|
||||
demoPartScene.process(demoPartScene.normalizeTime(elapsedSeconds));
|
||||
demoPartClear.process(demoPartClear.normalize_time(elapsed_seconds));
|
||||
demoPartScene.process(demoPartScene.normalize_time(elapsed_seconds));
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
// ImGui::Render();
|
||||
// ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
peripherals.swap_buffers();
|
||||
peripherals.poll_events();
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
Midi events delta time
|
||||
|
||||
https://sites.uci.edu/camp2014/2014/05/19/timing-in-midi-files/
|
||||
http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html#BM2_3
|
||||
|
||||
- Delta-time is in some fraction of a beat (or a second, for recording a track with SMPTE times), as specified in the header chunk.
|
||||
- nardis header track:
|
||||
Format: 1
|
||||
tracks: 10
|
||||
division : 480
|
||||
The third word, <division>, specifies the meaning of the delta-times.
|
||||
It has two formats, one for metrical time, and one for time-code-based time:
|
||||
|
||||
bit 15 bits 14 thru 8 bits 7 thru 0
|
||||
======|===============================|==============
|
||||
0 | ticks per quarter-note
|
||||
1 | negative SMPTE format | ticks per frame
|
||||
|
||||
If bit 15 of <division> is zero, the bits 14 thru 0 represent the number of delta time "ticks" which make up a quarter-note.
|
||||
For instance, if division is 96, then a time interval of an eighth-note between two events in the file would be 48.
|
||||
|
||||
nardis division == 480 => bit 15 is zero, so we have 480 ticks per quarter note.
|
||||
default tempo is 120, if not specified by a meta event
|
||||
default time signature is 4/4 if not specified by a meta event
|
||||
nardis has 4/4 time signature and tempo of 300000 microseconds per quarter note
|
||||
|
||||
|
||||
MIDI header track gives division, which is PPQ (parts per quarter or ticks per quarter note). Nardis = 480 => delta time of 480 means a quarter note.
|
||||
But how long is a quarter note? that is given by the tempo.
|
||||
|
||||
|
||||
|
||||
PITCH bending
|
||||
https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/
|
||||
- we get a 14bit value, [0..16383]
|
||||
- map this to [-1..1], meaning that 16383/2 means no bend
|
||||
- the float is the relative amount of bending, we should multiply it by a synth setting which says what is the bending range (+/- 2 semitones for example)
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
set(HEADERS
|
||||
${HEADERS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
|
||||
@@ -10,13 +11,15 @@ set(HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/particles.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/perlin.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shader_program.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/texture.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h
|
||||
@@ -27,6 +30,7 @@ set(HEADERS
|
||||
|
||||
set(SOURCE
|
||||
${SOURCE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/demo_data.cpp
|
||||
@@ -36,7 +40,9 @@ set(SOURCE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/particles.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/perlin.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.cpp
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "sound_server.h"
|
||||
#include <iostream>
|
||||
#include <SDL.h>
|
||||
|
||||
void audio_callback(void *param, uint8_t *stream, int len) {
|
||||
auto producer = reinterpret_cast<sound_producer *>(param);
|
||||
uint16_t samples = len >> 2; // 4 bytes per F32
|
||||
uint16_t frames = samples >> 1; // 2 channels, left and right
|
||||
producer->render(reinterpret_cast<float *>(stream), frames);
|
||||
}
|
||||
|
||||
sound_server::sound_server(uint16_t samplerate, sound_producer& producer) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
std::cerr << "Init failed" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_AudioSpec spec;
|
||||
spec.freq = samplerate;
|
||||
spec.format = AUDIO_F32;
|
||||
spec.samples = 256;
|
||||
spec.callback = audio_callback;
|
||||
spec.userdata = reinterpret_cast<void *>(&producer);
|
||||
spec.channels = 2;
|
||||
|
||||
if (SDL_OpenAudio(&spec, nullptr) < 0) {
|
||||
std::cerr << "Unable to open audio" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
|
||||
sound_server::~sound_server() {
|
||||
SDL_Quit();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct sound_producer {
|
||||
// interleaved samples, LR
|
||||
virtual void render(float *buffer, uint16_t frames) = 0;
|
||||
};
|
||||
|
||||
struct sound_server {
|
||||
sound_server(uint16_t samplerate, sound_producer& producer);
|
||||
~sound_server();
|
||||
};
|
||||
@@ -1,9 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <easylogging++.h>
|
||||
|
||||
#define BEGIN_NAMESPACE namespace acidrain {
|
||||
#define END_NAMESPACE };
|
||||
|
||||
inline int rand_int(int x, int y) { return rand() % (y - x + 1) + x; }
|
||||
|
||||
inline double rand_float() { return ((rand()) / (RAND_MAX + 1.0)); }
|
||||
|
||||
inline double rand_in_range(double x, double y) {
|
||||
return x + rand_float() * (y - x);
|
||||
}
|
||||
|
||||
//static int SCREEN_WIDTH = 800;
|
||||
//static int SCREEN_HEIGHT = 600;
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
struct DemoPart {
|
||||
float startTime; // absolute time, since demo starts
|
||||
float endTime; // absolute time, since demo starts
|
||||
struct demo_part {
|
||||
float start_time; // absolute time, since demo starts
|
||||
float end_time; // absolute time, since demo starts
|
||||
|
||||
float normalizeTime(float absoluteTimeInSeconds) {
|
||||
return (absoluteTimeInSeconds - startTime) / static_cast<float>(endTime - startTime);
|
||||
float normalize_time(float absolute_time_in_seconds) {
|
||||
return (absolute_time_in_seconds - start_time) / static_cast<float>(end_time - start_time);
|
||||
}
|
||||
|
||||
virtual void process(float normalizedTime) = 0;
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
void DemoPartClear::process(float normalizedTime) {
|
||||
void demo_part_clear::process(float normalized_time) {
|
||||
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
|
||||
GLbitfield mask = 0;
|
||||
if (clearDepth)
|
||||
if (do_clear_depth)
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
if (clearColor)
|
||||
if (do_clear_color)
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (clearStencil)
|
||||
if (do_clear_stencil)
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
glClear(mask);
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
struct DemoPartClear : DemoPart {
|
||||
struct demo_part_clear : demo_part {
|
||||
|
||||
glm::vec4 color = glm::vec4(0, 0, 0, 0);
|
||||
|
||||
bool clearDepth = true;
|
||||
bool clearColor = true;
|
||||
bool clearStencil = true;
|
||||
bool do_clear_depth = true;
|
||||
bool do_clear_color = true;
|
||||
bool do_clear_stencil = true;
|
||||
|
||||
void process(float normalizedTime) override;
|
||||
void process(float normalized_time) override;
|
||||
};
|
||||
|
||||
END_NAMESPACE
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh) {
|
||||
demo_part_marching_cubes::demo_part_marching_cubes(std::shared_ptr<mesh> affectedMesh) {
|
||||
mesh_ = affectedMesh;
|
||||
|
||||
field.emitters.push_back(glm::vec4(0, 0.7, 0, 1));
|
||||
@@ -15,36 +15,36 @@ DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh)
|
||||
// field.emitters.push_back(glm::vec4(-0.5, 0.7, -0.3, 1));
|
||||
}
|
||||
|
||||
void DemoPartMarchingCubes::process(float normalizedTime) {
|
||||
void demo_part_marching_cubes::process(float normalized_time) {
|
||||
|
||||
field.emitters[0].x = sin(normalizedTime * 2 * M_PI * 4);
|
||||
field.emitters[0].z = cos(normalizedTime * 2 * M_PI * 4);
|
||||
field.emitters[0].y = 0.7 * cos(normalizedTime * 2 * M_PI * 2);
|
||||
field.emitters[0].x = sin(normalized_time * 2 * M_PI * 4);
|
||||
field.emitters[0].z = cos(normalized_time * 2 * M_PI * 4);
|
||||
field.emitters[0].y = 0.7 * cos(normalized_time * 2 * M_PI * 2);
|
||||
|
||||
field.emitters[1].x = sin(normalizedTime * 2 * M_PI * 7);
|
||||
field.emitters[1].z = cos(normalizedTime * 2 * M_PI * 3.5);
|
||||
field.emitters[1].x = sin(normalized_time * 2 * M_PI * 7);
|
||||
field.emitters[1].z = cos(normalized_time * 2 * M_PI * 3.5);
|
||||
|
||||
field.emitters[2].y = 0.5 * sin(normalizedTime * 2 * M_PI * 4);
|
||||
field.emitters[2].z = 0.8 * cos(normalizedTime * 2 * M_PI * 2);
|
||||
field.emitters[2].y = 0.5 * sin(normalized_time * 2 * M_PI * 4);
|
||||
field.emitters[2].z = 0.8 * cos(normalized_time * 2 * M_PI * 2);
|
||||
|
||||
// field.emitters[3].y = 0.8 * cos(normalizedTime * 2 * M_PI * 3);
|
||||
// field.emitters[3].z = 0.2 * sin(normalizedTime * 2 * M_PI * 8);
|
||||
|
||||
grid.evaluateForces(field);
|
||||
grid.triangulate(*mesh_.get(), minFieldValue);
|
||||
grid.evaluate_forces(field);
|
||||
grid.triangulate(*mesh_.get(), min_field_value);
|
||||
|
||||
for (auto &v: mesh_->vertices)
|
||||
v.normal = field.getFieldNormalAt(v.position);
|
||||
v.normal = field.get_field_normal_at(v.position);
|
||||
|
||||
// calculateNormals(*mesh.get());
|
||||
}
|
||||
|
||||
void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
||||
void marching_cubes_grid::evaluate_forces(force_field &field) {
|
||||
|
||||
// Make sure we have enough space preallocated.
|
||||
// We use resize because we want it also logically allocated with defaults
|
||||
// so we can simply access an item at certain index with no issues
|
||||
gridVertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
|
||||
grid_vertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
|
||||
|
||||
glm::vec3 stepSize(
|
||||
(xMax - xMin) / static_cast<float>(xCells),
|
||||
@@ -64,11 +64,11 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
||||
|
||||
for (int x = 0; x <= xCells; x++) {
|
||||
gridVertex.x = xMin + x * stepSize.x;
|
||||
gridVertex.w = field.getFieldValueAt(glm::vec3(gridVertex));
|
||||
gridVertex.w = field.get_field_value_at(glm::vec3(gridVertex));
|
||||
|
||||
// std::cout << std::setprecision(5) << std::fixed << "(x: " << gridVertex.x << ", y: " << gridVertex.y << ", z: " << gridVertex.z << ", val: " << gridVertex.w << ")" << std::endl;
|
||||
|
||||
gridVertices[cellIndex] = gridVertex;
|
||||
grid_vertices[cellIndex] = gridVertex;
|
||||
|
||||
cellIndex++;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
|
||||
}
|
||||
|
||||
|
||||
void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
|
||||
void marching_cubes_grid::triangulate(mesh &m, float minFieldValue) {
|
||||
|
||||
m.vertices.clear();
|
||||
m.facets.clear();
|
||||
@@ -87,20 +87,20 @@ void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
|
||||
for (int y = 0; y < yCells; y++) {
|
||||
for (int x = 0; x < xCells; x++) {
|
||||
|
||||
calculateCellVertices(x, y, z);
|
||||
calculate_cell_vertices(x, y, z);
|
||||
|
||||
int cellType = classifyCell(minFieldValue);
|
||||
int cellType = classify_cell(minFieldValue);
|
||||
if (!edgeTable[cellType]) continue;
|
||||
|
||||
calculateIntersectionVertices(cellType, minFieldValue);
|
||||
addResultingFacets(m, cellType);
|
||||
calculate_intersection_vertices(cellType, minFieldValue);
|
||||
add_resulting_facets(m, cellType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
|
||||
void marching_cubes_grid::calculate_cell_vertices(int x, int y, int z) {
|
||||
// TODO: optimize these out. they are constant for a given grid size.
|
||||
int xVerts = xCells + 1;
|
||||
int yVerts = yCells + 1;
|
||||
@@ -109,61 +109,61 @@ void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
|
||||
int leftTopFarthestIndex = z * vertsInXYPlane + x + y * xCells;
|
||||
|
||||
// see http://paulbourke.net/geometry/polygonise/polygonise1.gif
|
||||
cubeVertexIndices[0] = leftTopFarthestIndex + xVerts;
|
||||
cubeVertexIndices[1] = leftTopFarthestIndex + xVerts + 1;
|
||||
cubeVertexIndices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
|
||||
cubeVertexIndices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
|
||||
cube_vertex_indices[0] = leftTopFarthestIndex + xVerts;
|
||||
cube_vertex_indices[1] = leftTopFarthestIndex + xVerts + 1;
|
||||
cube_vertex_indices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
|
||||
cube_vertex_indices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
|
||||
|
||||
cubeVertexIndices[4] = leftTopFarthestIndex;
|
||||
cubeVertexIndices[5] = leftTopFarthestIndex + 1;
|
||||
cubeVertexIndices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
|
||||
cubeVertexIndices[7] = leftTopFarthestIndex + vertsInXYPlane;
|
||||
cube_vertex_indices[4] = leftTopFarthestIndex;
|
||||
cube_vertex_indices[5] = leftTopFarthestIndex + 1;
|
||||
cube_vertex_indices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
|
||||
cube_vertex_indices[7] = leftTopFarthestIndex + vertsInXYPlane;
|
||||
}
|
||||
|
||||
|
||||
int MarchingCubesGrid::classifyCell(float minFieldValue) {
|
||||
int marching_cubes_grid::classify_cell(float minFieldValue) {
|
||||
int result = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (gridVertices[cubeVertexIndices[i]].w <= minFieldValue)
|
||||
if (grid_vertices[cube_vertex_indices[i]].w <= minFieldValue)
|
||||
result |= 1 << i;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void MarchingCubesGrid::calculateIntersectionVertices(int cellType, float minFieldValue) {
|
||||
void marching_cubes_grid::calculate_intersection_vertices(int cellType, float minFieldValue) {
|
||||
|
||||
if (edgeTable[cellType] & 1)
|
||||
intersectionVertices[0] = intersection(cubeVertexIndices[0], cubeVertexIndices[1], minFieldValue);
|
||||
intersection_vertices[0] = intersection(cube_vertex_indices[0], cube_vertex_indices[1], minFieldValue);
|
||||
if (edgeTable[cellType] & 2)
|
||||
intersectionVertices[1] = intersection(cubeVertexIndices[1], cubeVertexIndices[2], minFieldValue);
|
||||
intersection_vertices[1] = intersection(cube_vertex_indices[1], cube_vertex_indices[2], minFieldValue);
|
||||
if (edgeTable[cellType] & 4)
|
||||
intersectionVertices[2] = intersection(cubeVertexIndices[2], cubeVertexIndices[3], minFieldValue);
|
||||
intersection_vertices[2] = intersection(cube_vertex_indices[2], cube_vertex_indices[3], minFieldValue);
|
||||
if (edgeTable[cellType] & 8)
|
||||
intersectionVertices[3] = intersection(cubeVertexIndices[3], cubeVertexIndices[0], minFieldValue);
|
||||
intersection_vertices[3] = intersection(cube_vertex_indices[3], cube_vertex_indices[0], minFieldValue);
|
||||
if (edgeTable[cellType] & 16)
|
||||
intersectionVertices[4] = intersection(cubeVertexIndices[4], cubeVertexIndices[5], minFieldValue);
|
||||
intersection_vertices[4] = intersection(cube_vertex_indices[4], cube_vertex_indices[5], minFieldValue);
|
||||
if (edgeTable[cellType] & 32)
|
||||
intersectionVertices[5] = intersection(cubeVertexIndices[5], cubeVertexIndices[6], minFieldValue);
|
||||
intersection_vertices[5] = intersection(cube_vertex_indices[5], cube_vertex_indices[6], minFieldValue);
|
||||
if (edgeTable[cellType] & 64)
|
||||
intersectionVertices[6] = intersection(cubeVertexIndices[6], cubeVertexIndices[7], minFieldValue);
|
||||
intersection_vertices[6] = intersection(cube_vertex_indices[6], cube_vertex_indices[7], minFieldValue);
|
||||
if (edgeTable[cellType] & 128)
|
||||
intersectionVertices[7] = intersection(cubeVertexIndices[7], cubeVertexIndices[4], minFieldValue);
|
||||
intersection_vertices[7] = intersection(cube_vertex_indices[7], cube_vertex_indices[4], minFieldValue);
|
||||
if (edgeTable[cellType] & 256)
|
||||
intersectionVertices[8] = intersection(cubeVertexIndices[0], cubeVertexIndices[4], minFieldValue);
|
||||
intersection_vertices[8] = intersection(cube_vertex_indices[0], cube_vertex_indices[4], minFieldValue);
|
||||
if (edgeTable[cellType] & 512)
|
||||
intersectionVertices[9] = intersection(cubeVertexIndices[1], cubeVertexIndices[5], minFieldValue);
|
||||
intersection_vertices[9] = intersection(cube_vertex_indices[1], cube_vertex_indices[5], minFieldValue);
|
||||
if (edgeTable[cellType] & 1024)
|
||||
intersectionVertices[10] = intersection(cubeVertexIndices[2], cubeVertexIndices[6], minFieldValue);
|
||||
intersection_vertices[10] = intersection(cube_vertex_indices[2], cube_vertex_indices[6], minFieldValue);
|
||||
if (edgeTable[cellType] & 2048)
|
||||
intersectionVertices[11] = intersection(cubeVertexIndices[3], cubeVertexIndices[7], minFieldValue);
|
||||
intersection_vertices[11] = intersection(cube_vertex_indices[3], cube_vertex_indices[7], minFieldValue);
|
||||
|
||||
}
|
||||
|
||||
glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFieldValue) {
|
||||
glm::vec4 &a = gridVertices[v1Index];
|
||||
glm::vec4 &b = gridVertices[v2Index];
|
||||
glm::vec3 marching_cubes_grid::intersection(int v1Index, int v2Index, float minFieldValue) {
|
||||
glm::vec4 &a = grid_vertices[v1Index];
|
||||
glm::vec4 &b = grid_vertices[v2Index];
|
||||
|
||||
if (a.w != b.w) {
|
||||
float alpha = (minFieldValue - a.w) / (b.w - a.w);
|
||||
@@ -174,7 +174,7 @@ glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFie
|
||||
}
|
||||
|
||||
|
||||
void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
||||
void marching_cubes_grid::add_resulting_facets(mesh &m, int cellType) {
|
||||
facet f{};
|
||||
vertex v{};
|
||||
int vertexOffset = m.vertices.size();
|
||||
@@ -182,7 +182,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
||||
for (int n = 0; triTable[cellType][n] != -1; n += 3) {
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
v.position = intersectionVertices[triTable[cellType][n + 2 - i]];
|
||||
v.position = intersection_vertices[triTable[cellType][n + 2 - i]];
|
||||
m.vertices.push_back(v);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
|
||||
}
|
||||
|
||||
|
||||
float ForceField::getFieldValueAt(const glm::vec3 &position) const {
|
||||
float force_field::get_field_value_at(const glm::vec3 &position) const {
|
||||
float result = 0;
|
||||
|
||||
for (auto &e: emitters) {
|
||||
@@ -206,7 +206,7 @@ float ForceField::getFieldValueAt(const glm::vec3 &position) const {
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 ForceField::getFieldNormalAt(const glm::vec3 &position) const {
|
||||
glm::vec3 force_field::get_field_normal_at(const glm::vec3 &position) const {
|
||||
// Hello blackpawn! http://www.blackpawn.com/texts/metanormals/default.html
|
||||
glm::vec3 normal = glm::vec3(0);
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
struct ForceField {
|
||||
float getFieldValueAt(const glm::vec3 &position) const;
|
||||
glm::vec3 getFieldNormalAt(const glm::vec3 &position) const;
|
||||
struct force_field {
|
||||
float get_field_value_at(const glm::vec3& position) const;
|
||||
glm::vec3 get_field_normal_at(const glm::vec3& position) const;
|
||||
|
||||
std::vector<glm::vec4> emitters; // vec4 = position + strength
|
||||
};
|
||||
|
||||
struct MarchingCubesGrid {
|
||||
struct marching_cubes_grid {
|
||||
int xCells = 60;
|
||||
int yCells = 60;
|
||||
int zCells = 60;
|
||||
@@ -28,31 +28,31 @@ struct MarchingCubesGrid {
|
||||
float zMax = 2;
|
||||
|
||||
// .w will hold field value for code size optimisation purposes
|
||||
std::vector<glm::vec4> gridVertices;
|
||||
std::vector<glm::vec4> grid_vertices;
|
||||
|
||||
void evaluateForces(ForceField &field);
|
||||
void evaluate_forces(force_field& field);
|
||||
void triangulate(mesh& m, float minFieldValue);
|
||||
|
||||
private:
|
||||
void calculateCellVertices(int x, int y, int z);
|
||||
int classifyCell(float minFieldValue);
|
||||
void calculateIntersectionVertices(int cellType, float minFieldValue);
|
||||
void addResultingFacets(mesh &m, int cellType);
|
||||
void calculate_cell_vertices(int x, int y, int z);
|
||||
int classify_cell(float minFieldValue);
|
||||
void calculate_intersection_vertices(int cellType, float minFieldValue);
|
||||
void add_resulting_facets(mesh& m, int cellType);
|
||||
glm::vec3 intersection(int v1Index, int v2Index, float minFieldValue);
|
||||
|
||||
int cubeVertexIndices[8];
|
||||
glm::vec3 intersectionVertices[12];
|
||||
int cube_vertex_indices[8];
|
||||
glm::vec3 intersection_vertices[12];
|
||||
|
||||
};
|
||||
|
||||
struct DemoPartMarchingCubes : DemoPart {
|
||||
DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh);
|
||||
struct demo_part_marching_cubes : demo_part {
|
||||
explicit demo_part_marching_cubes(std::shared_ptr<mesh> affected_mesh);
|
||||
|
||||
void process(float normalizedTime) override;
|
||||
void process(float normalized_time) override;
|
||||
|
||||
MarchingCubesGrid grid;
|
||||
ForceField field;
|
||||
float minFieldValue = 2.6;
|
||||
marching_cubes_grid grid;
|
||||
force_field field;
|
||||
float min_field_value = 2.6;
|
||||
std::shared_ptr<mesh> mesh_;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
DemoPartRenderToTexture::DemoPartRenderToTexture(int s, RenderToTextureAction a)
|
||||
demo_part_render_to_texture::demo_part_render_to_texture(int s, render_to_texture_action a)
|
||||
: slot(s), action(a) {
|
||||
}
|
||||
|
||||
void DemoPartRenderToTexture::process(float normalizedTime) {
|
||||
if (action == RenderToTextureAction::Start)
|
||||
void demo_part_render_to_texture::process(float normalizedTime) {
|
||||
if (action == render_to_texture_action::start)
|
||||
demo_data::fbos[slot]->use();
|
||||
else
|
||||
demo_data::fbos[slot]->unuse();
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
enum class RenderToTextureAction {
|
||||
Start,
|
||||
Stop
|
||||
enum class render_to_texture_action {
|
||||
start,
|
||||
stop
|
||||
};
|
||||
|
||||
struct DemoPartRenderToTexture : DemoPart {
|
||||
struct demo_part_render_to_texture : demo_part {
|
||||
demo_part_render_to_texture(int slot, render_to_texture_action action);
|
||||
|
||||
DemoPartRenderToTexture(int slot, RenderToTextureAction action);
|
||||
|
||||
void process(float normalizedTime) override;
|
||||
void process(float normalized_time) override;
|
||||
|
||||
int slot;
|
||||
RenderToTextureAction action;
|
||||
render_to_texture_action action;
|
||||
};
|
||||
|
||||
END_NAMESPACE
|
||||
@@ -7,16 +7,13 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
DemoPartScene::DemoPartScene() {
|
||||
demo_part_scene::demo_part_scene() {
|
||||
renderer = std::make_shared<scene_renderer>();
|
||||
}
|
||||
|
||||
DemoPartScene::~DemoPartScene() {
|
||||
}
|
||||
|
||||
void DemoPartScene::process(float normalizedTime) {
|
||||
void demo_part_scene::process(float normalized_time) {
|
||||
if (scene_->animation)
|
||||
scene_->animation->set_at_time(normalizedTime);
|
||||
scene_->animation->set_at_time(normalized_time);
|
||||
|
||||
if (scene_->tree) {
|
||||
scene_->tree->transform();
|
||||
|
||||
+12
-11
@@ -9,27 +9,28 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
struct DemoPartScene : DemoPart {
|
||||
struct demo_part_scene : demo_part {
|
||||
|
||||
DemoPartScene();
|
||||
virtual ~DemoPartScene();
|
||||
demo_part_scene();
|
||||
~demo_part_scene() = default;
|
||||
|
||||
void process(float normalized_time) override;
|
||||
|
||||
std::shared_ptr<scene_renderer> renderer;
|
||||
std::shared_ptr<scene> scene_;
|
||||
std::string cameraName;
|
||||
std::string lightName;
|
||||
float animationStartTime; // normalized time, [0-1]
|
||||
float animationEndTime; // normalized time, [0-1]
|
||||
float animationStartTime = 0; // normalized time, [0-1]
|
||||
|
||||
float animationEndTime = 1.0; // normalized time, [0-1]
|
||||
GLuint fboID = 0;
|
||||
GLuint shadowMapTexID = 0;
|
||||
std::shared_ptr<shader_program> firstPassShadowShader;
|
||||
|
||||
GLuint fboID;
|
||||
GLuint shadowMapTexID;
|
||||
std::shared_ptr<shader> firstPassShadowShader;
|
||||
std::shared_ptr<material> firstPassShadowMaterial;
|
||||
std::shared_ptr<shader_program> secondPassShadowShader;
|
||||
|
||||
std::shared_ptr<shader> secondPassShadowShader;
|
||||
std::shared_ptr<material> secondPassShadowMaterial;
|
||||
|
||||
void process(float normalizedTime) override;
|
||||
};
|
||||
|
||||
END_NAMESPACE
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "glm/gtx/transform.hpp"
|
||||
#include "glm/gtc/matrix_transform.hpp"
|
||||
|
||||
#include "shader.h"
|
||||
#include "shader_program.h"
|
||||
#include "texture.h"
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -3,12 +3,12 @@
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
std::vector<std::shared_ptr<texture>> demo_data::textures;
|
||||
std::vector<std::shared_ptr<shader>> demo_data::shaders;
|
||||
std::vector<std::shared_ptr<shader_program>> demo_data::shaders;
|
||||
std::vector<std::shared_ptr<material>> demo_data::materials;
|
||||
std::vector<std::shared_ptr<mesh>> demo_data::meshes;
|
||||
std::vector<std::shared_ptr<fbo>> demo_data::fbos;
|
||||
|
||||
int demo_data::screen_width = 1024;
|
||||
int demo_data::screen_height = 768;
|
||||
int demo_data::screen_width = 1024 * 2;
|
||||
int demo_data::screen_height = 768 * 2;
|
||||
|
||||
END_NAMESPACE
|
||||
+1
-1
@@ -10,7 +10,7 @@ BEGIN_NAMESPACE
|
||||
struct demo_data {
|
||||
|
||||
static std::vector<std::shared_ptr<texture>> textures;
|
||||
static std::vector<std::shared_ptr<shader>> shaders;
|
||||
static std::vector<std::shared_ptr<shader_program>> shaders;
|
||||
static std::vector<std::shared_ptr<material>> materials;
|
||||
static std::vector<std::shared_ptr<mesh>> meshes;
|
||||
static std::vector<std::shared_ptr<fbo>> fbos;
|
||||
|
||||
+2
-3
@@ -24,8 +24,7 @@ fbo::fbo(int w, int h)
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id,
|
||||
0);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id, 0);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer_id);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
@@ -52,7 +51,7 @@ void fbo::use() {
|
||||
old_width = demo_data::screen_width;
|
||||
old_height = demo_data::screen_height;
|
||||
|
||||
demo_data::screen_height = width;
|
||||
demo_data::screen_width = width;
|
||||
demo_data::screen_height = height;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_id);
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ enum class light_type {
|
||||
};
|
||||
|
||||
struct light_node : scene_node {
|
||||
light_node(light_type type);
|
||||
explicit light_node(light_type type);
|
||||
|
||||
void calculate_local_transform() override;
|
||||
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ GLenum to_gl(const blending_constant &c) {
|
||||
void set_material(std::shared_ptr<material> &mat) {
|
||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
mat->shader_->use();
|
||||
mat->shader->bind();
|
||||
|
||||
// if (material->textures[TextureRole::Diffuse]) {
|
||||
// std::cout << "CAN has diffuse texture!!!!!!!!!11" << std::endl;
|
||||
@@ -86,7 +86,7 @@ void unset_material(std::shared_ptr<material> &mat) {
|
||||
// textureUnit++;
|
||||
// }
|
||||
|
||||
mat->shader_->unuse();
|
||||
mat->shader->unbind();
|
||||
|
||||
if (mat->transparent)
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include "texture.h"
|
||||
#include "shader.h"
|
||||
#include "shader_program.h"
|
||||
#include "glm/glm.hpp"
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
@@ -52,7 +52,7 @@ struct material {
|
||||
blending_constant blend_dst_fact = blending_constant::one_minus_src_alpha;
|
||||
|
||||
fill_mode_type fill_mode = fill_mode_type::solid;
|
||||
std::shared_ptr<shader> shader_;
|
||||
std::shared_ptr<shader_program> shader;
|
||||
texture_map textures;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ BEGIN_NAMESPACE
|
||||
|
||||
struct mesh_node : scene_node {
|
||||
mesh_node();
|
||||
mesh_node(std::string name);
|
||||
explicit mesh_node(std::string name);
|
||||
|
||||
std::shared_ptr<mesh> mesh_;
|
||||
std::shared_ptr<material> material_;
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "particles.h"
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
particle_emitter::particle_emitter() {
|
||||
to_spawn = 0;
|
||||
start_size = 1.0f;
|
||||
end_size = 1.0f;
|
||||
}
|
||||
|
||||
particle *particle_emitter::new_particle() {
|
||||
particle *p;
|
||||
if (dead_particles.empty()) {
|
||||
p = new particle{};
|
||||
} else {
|
||||
p = dead_particles.back();
|
||||
dead_particles.pop_back();
|
||||
}
|
||||
|
||||
particles.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
void particle_emitter::update(float elapsed_ms) {
|
||||
float factor = elapsed_ms / 1000.0f;
|
||||
|
||||
for (auto p : particles) {
|
||||
p->old_pos = p->position;
|
||||
p->position += p->velocity * factor;
|
||||
p->life -= life_decay * factor;
|
||||
p->color = glm::mix(start_colour, end_colour, p->life);
|
||||
p->size = glm::mix(start_size, end_size, p->life);
|
||||
}
|
||||
|
||||
// move dead particles to the dead list
|
||||
auto pit = particles.begin();
|
||||
while (pit != particles.end()) {
|
||||
if ((*pit)->life <= 0.0) {
|
||||
dead_particles.push_back(*pit);
|
||||
pit = particles.erase(pit);
|
||||
} else {
|
||||
++pit;
|
||||
}
|
||||
}
|
||||
|
||||
// spawn if needed
|
||||
to_spawn += factor * emission_rate;
|
||||
auto new_particles = static_cast<int>(to_spawn);
|
||||
|
||||
for (auto i = 0; i < new_particles; i++) {
|
||||
particle *p = new_particle();
|
||||
spawn(p);
|
||||
}
|
||||
to_spawn -= static_cast<float>(new_particles);
|
||||
}
|
||||
|
||||
|
||||
void particle_system::update(float elapsed_ms) {
|
||||
particles.clear();
|
||||
|
||||
for (auto& emitter: emitters) {
|
||||
emitter->update(elapsed_ms);
|
||||
std::copy(emitter->particles.begin(), emitter->particles.end(), std::back_inserter(particles));
|
||||
}
|
||||
|
||||
for (auto& modifier: modifiers) {
|
||||
for (auto& particle: particles) {
|
||||
modifier->affect_particle(particle, elapsed_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void particle_system::render() {
|
||||
|
||||
// draw trail
|
||||
// draw head
|
||||
|
||||
// Matrix mat;
|
||||
// mat.fromGL(GL_MODELVIEW_MATRIX);
|
||||
//
|
||||
// Vector3D a(mat._mat[0], mat._mat[4], mat._mat[8]);
|
||||
// Vector3D b(mat._mat[1], mat._mat[5], mat._mat[9]);
|
||||
//
|
||||
// Vector3D pos[4];
|
||||
// pos[0] = (-a - b);
|
||||
// pos[1] = (a - b);
|
||||
// pos[2] = (a + b);
|
||||
// pos[3] = (-a + b);
|
||||
//
|
||||
//
|
||||
// glEnable(GL_COLOR_MATERIAL);
|
||||
// glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
|
||||
//
|
||||
// glBegin(GL_QUADS);
|
||||
//
|
||||
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
|
||||
// Particle *p = (*it);
|
||||
//
|
||||
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
|
||||
//
|
||||
// glTexCoord2f(1.0f, 1.0f);
|
||||
// glVertex3d(pos[0].x * p->size + p->position.x, pos[0].y * p->size + p->position.y, pos[0].z * p->size + p->position.z);
|
||||
//
|
||||
// glTexCoord2f(0.0f, 1.0f);
|
||||
// glVertex3d(pos[1].x * p->size + p->position.x, pos[1].y * p->size + p->position.y, pos[1].z * p->size + p->position.z);
|
||||
//
|
||||
// glTexCoord2f(0.0f, 0.0f);
|
||||
// glVertex3d(pos[2].x * p->size + p->position.x, pos[2].y * p->size + p->position.y, pos[2].z * p->size + p->position.z);
|
||||
//
|
||||
// glTexCoord2f(1.0f, 0.0f);
|
||||
// glVertex3d(pos[3].x * p->size + p->position.x, pos[3].y * p->size + p->position.y, pos[3].z * p->size + p->position.z);
|
||||
// }
|
||||
//
|
||||
// glEnd();
|
||||
//
|
||||
// //
|
||||
//
|
||||
// glDisable(GL_TEXTURE_2D);
|
||||
// glBegin(GL_LINES);
|
||||
//
|
||||
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
|
||||
// Particle *p = (*it);
|
||||
//
|
||||
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
|
||||
//
|
||||
// glVertex3d(p->previousPosition.x, p->previousPosition.y, p->previousPosition.z);
|
||||
// glVertex3d(p->position.x, p->position.y, p->position.z);
|
||||
// }
|
||||
//
|
||||
// glEnd();
|
||||
//
|
||||
//
|
||||
// glDisable(GL_COLOR_MATERIAL);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
|
||||
|
||||
// This is how will our point sprite's size will be modified by
|
||||
// distance from the viewer
|
||||
float quadratic[] = { 1.0f, 0.0f, 0.01f };
|
||||
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
|
||||
|
||||
// Query for the max point size supported by the hardware
|
||||
float maxSize = 0.0f;
|
||||
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
|
||||
|
||||
// Clamp size to 100.0f or the sprites could get a little too big on some
|
||||
// of the newer graphic cards. My ATI card at home supports a max point
|
||||
// size of 1024.0f!
|
||||
maxSize = min( maxSize, 100.0f );
|
||||
glPointSize( maxSize );
|
||||
|
||||
// The alpha of a point is calculated to allow the fading of points
|
||||
// instead of shrinking them past a defined threshold size. The threshold
|
||||
// is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
|
||||
// the minimum and maximum point sizes.
|
||||
glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
|
||||
|
||||
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f );
|
||||
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
|
||||
|
||||
// Specify point sprite texture coordinate replacement mode for each
|
||||
// texture unit
|
||||
glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
|
||||
|
||||
glEnable( GL_POINT_SPRITE_ARB );
|
||||
|
||||
|
||||
glBegin( GL_POINTS );
|
||||
for ( ParticleList::iterator it = particles.begin(); it != particles.end(); it++ ) {
|
||||
Particle *p = (*it);
|
||||
glColor4d( p->color.r, p->color.g, p->color.b, p->color.a );
|
||||
glVertex3d( p->position.x, p->position.y, p->position.z );
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glDisable( GL_POINT_SPRITE_ARB );
|
||||
glDisable( GL_BLEND );
|
||||
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
*/
|
||||
}
|
||||
|
||||
dot_particle_emitter::dot_particle_emitter() {
|
||||
emission_rate = 30.0f;
|
||||
life_decay = 0.1;
|
||||
}
|
||||
|
||||
void dot_particle_emitter::spawn(acidrain::particle *p) {
|
||||
if (nullptr == p) {
|
||||
return;
|
||||
}
|
||||
p->position = {0, 0, 0};
|
||||
p->color = {rand_in_range(0, 1), rand_in_range(0, 1), rand_in_range(0, 1), 1.0};
|
||||
p->velocity = glm::normalize(glm::vec3(rand_in_range(-1, 1), rand_in_range(-1, 1), rand_in_range(-1, 1)));
|
||||
// p->velocity *= 10;
|
||||
|
||||
p->life = 1.0;
|
||||
}
|
||||
|
||||
END_NAMESPACE
|
||||
|
||||
void acidrain::particle_attractor::init(glm::vec3& center, float s) {
|
||||
attractor_center = center;
|
||||
strength = s;
|
||||
}
|
||||
|
||||
void acidrain::particle_attractor::affect_particle(acidrain::particle *p, float elapsed_ms) {
|
||||
float factor = elapsed_ms / 1000.0f;
|
||||
|
||||
glm::vec3 attract_direction = attractor_center - p->position;
|
||||
float distance_to_center = glm::length(attract_direction);
|
||||
|
||||
float amount = 1.0f / (distance_to_center * distance_to_center) * strength;
|
||||
p->velocity += attract_direction * amount * factor;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include "colour.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
struct particle;
|
||||
struct particle_emitter;
|
||||
struct particle_modifier;
|
||||
|
||||
using particle_list = std::vector<particle *>;
|
||||
using particle_emitter_list = std::vector<particle_emitter *>;
|
||||
using particle_modifier_list = std::vector<particle_modifier *>;
|
||||
|
||||
struct particle {
|
||||
glm::vec3 position;
|
||||
glm::vec3 old_pos;
|
||||
glm::vec3 velocity;
|
||||
colour color;
|
||||
float life;
|
||||
float size;
|
||||
};
|
||||
|
||||
struct particle_emitter {
|
||||
particle_emitter();
|
||||
virtual ~particle_emitter() = default;
|
||||
|
||||
particle *new_particle();
|
||||
void update(float elapsed_ms);
|
||||
|
||||
virtual void spawn(particle *p) = 0;
|
||||
|
||||
particle_list particles;
|
||||
particle_list dead_particles;
|
||||
|
||||
glm::vec3 position{};
|
||||
float emission_rate{}; // particles per second
|
||||
float to_spawn;
|
||||
float life_decay{};
|
||||
colour start_colour{};
|
||||
colour end_colour{};
|
||||
float start_size;
|
||||
float end_size;
|
||||
};
|
||||
|
||||
struct particle_modifier {
|
||||
virtual void affect_particle(particle *p, float elapsed_ms) = 0;
|
||||
};
|
||||
|
||||
struct particle_system {
|
||||
void update(float elapsed_ms);
|
||||
void render();
|
||||
|
||||
particle_list particles;
|
||||
particle_emitter_list emitters;
|
||||
particle_modifier_list modifiers;
|
||||
};
|
||||
|
||||
struct dot_particle_emitter : particle_emitter {
|
||||
dot_particle_emitter();
|
||||
void spawn(particle *p) override;
|
||||
};
|
||||
|
||||
|
||||
struct particle_attractor : particle_modifier {
|
||||
void init(glm::vec3& center, float strength_);
|
||||
void affect_particle(particle *p, float elapsed_ms) override;
|
||||
|
||||
glm::vec3 attractor_center;
|
||||
float strength;
|
||||
};
|
||||
|
||||
END_NAMESPACE
|
||||
+1
-1
@@ -5,7 +5,7 @@ BEGIN_NAMESPACE
|
||||
|
||||
class peripherals {
|
||||
public:
|
||||
virtual bool init() = 0;
|
||||
virtual bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) = 0;
|
||||
virtual void swap_buffers() = 0;
|
||||
virtual void poll_events() = 0;
|
||||
virtual bool should_close() = 0;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "peripherals_glfw.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include "demo_data.h"
|
||||
#include "defines.h"
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
@@ -20,7 +19,7 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action,
|
||||
}
|
||||
}
|
||||
|
||||
bool peripherals_glfw::init() {
|
||||
bool peripherals_glfw::init(uint16_t width, uint16_t height, const char *title, bool fullscreen) {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
@@ -31,10 +30,9 @@ bool peripherals_glfw::init() {
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
|
||||
bool fullscreen = false;
|
||||
window = glfwCreateWindow(demo_data::screen_width,
|
||||
demo_data::screen_height,
|
||||
"Demo",
|
||||
window = glfwCreateWindow(width,
|
||||
height,
|
||||
title,
|
||||
fullscreen ? glfwGetPrimaryMonitor() : nullptr,
|
||||
nullptr);
|
||||
if (window == nullptr) {
|
||||
|
||||
@@ -9,7 +9,7 @@ BEGIN_NAMESPACE
|
||||
class peripherals_glfw : public peripherals {
|
||||
public:
|
||||
|
||||
bool init() override;
|
||||
bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) override;
|
||||
void swap_buffers() override;
|
||||
void poll_events() override;
|
||||
bool should_close() override;
|
||||
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
#include "perlin.h"
|
||||
#include <cmath>
|
||||
|
||||
// Thank you, Ken Perlin
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
namespace perlin {
|
||||
|
||||
#define B 0x100
|
||||
#define BM 0xff
|
||||
#define N 0x1000
|
||||
#define NP 12 /* 2^N */
|
||||
#define NM 0xfff
|
||||
|
||||
#define s_curve(t) ( t * t * (3. - 2. * t) )
|
||||
#define lerp(t, a, b) ( a + t * (b - a) )
|
||||
#define setup(i, b0, b1, r0, r1)\
|
||||
t = vec[i] + N;\
|
||||
b0 = ((int)t) & BM;\
|
||||
b1 = (b0+1) & BM;\
|
||||
r0 = t - (int)t;\
|
||||
r1 = r0 - 1.;
|
||||
#define at2(rx, ry) ( rx * q[0] + ry * q[1] )
|
||||
#define at3(rx, ry, rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
|
||||
|
||||
|
||||
/* Coherent noise function over 1, 2 or 3 dimensions */
|
||||
/* (copyright Ken Perlin) */
|
||||
|
||||
static int p[B + B + 2];
|
||||
static double g3[B + B + 2][3];
|
||||
static double g2[B + B + 2][2];
|
||||
static double g1[B + B + 2];
|
||||
static int start = 1;
|
||||
|
||||
double noise1(double arg) {
|
||||
int bx0, bx1;
|
||||
double rx0, rx1, sx, t, u, v, vec[1];
|
||||
|
||||
vec[0] = arg;
|
||||
if (start) {
|
||||
start = 0;
|
||||
init();
|
||||
}
|
||||
|
||||
setup(0, bx0, bx1, rx0, rx1);
|
||||
|
||||
sx = s_curve(rx0);
|
||||
u = rx0 * g1[p[bx0]];
|
||||
v = rx1 * g1[p[bx1]];
|
||||
|
||||
return (lerp(sx, u, v));
|
||||
}
|
||||
|
||||
double noise2(double vec[2]) {
|
||||
int bx0, bx1, by0, by1, b00, b10, b01, b11;
|
||||
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
|
||||
int i, j;
|
||||
|
||||
if (start) {
|
||||
start = 0;
|
||||
init();
|
||||
}
|
||||
|
||||
setup(0, bx0, bx1, rx0, rx1);
|
||||
setup(1, by0, by1, ry0, ry1);
|
||||
|
||||
i = p[bx0];
|
||||
j = p[bx1];
|
||||
|
||||
b00 = p[i + by0];
|
||||
b10 = p[j + by0];
|
||||
b01 = p[i + by1];
|
||||
b11 = p[j + by1];
|
||||
|
||||
sx = s_curve(rx0);
|
||||
sy = s_curve(ry0);
|
||||
|
||||
q = g2[b00];
|
||||
u = at2(rx0, ry0);
|
||||
q = g2[b10];
|
||||
v = at2(rx1, ry0);
|
||||
a = lerp(sx, u, v);
|
||||
|
||||
q = g2[b01];
|
||||
u = at2(rx0, ry1);
|
||||
q = g2[b11];
|
||||
v = at2(rx1, ry1);
|
||||
b = lerp(sx, u, v);
|
||||
|
||||
return lerp(sy, a, b);
|
||||
}
|
||||
|
||||
double noise3(double vec[3]) {
|
||||
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
|
||||
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
|
||||
int i, j;
|
||||
|
||||
if (start) {
|
||||
start = 0;
|
||||
init();
|
||||
}
|
||||
|
||||
setup(0, bx0, bx1, rx0, rx1);
|
||||
setup(1, by0, by1, ry0, ry1);
|
||||
setup(2, bz0, bz1, rz0, rz1);
|
||||
|
||||
i = p[bx0];
|
||||
j = p[bx1];
|
||||
|
||||
b00 = p[i + by0];
|
||||
b10 = p[j + by0];
|
||||
b01 = p[i + by1];
|
||||
b11 = p[j + by1];
|
||||
|
||||
t = s_curve(rx0);
|
||||
sy = s_curve(ry0);
|
||||
sz = s_curve(rz0);
|
||||
|
||||
q = g3[b00 + bz0];
|
||||
u = at3(rx0, ry0, rz0);
|
||||
q = g3[b10 + bz0];
|
||||
v = at3(rx1, ry0, rz0);
|
||||
a = lerp(t, u, v);
|
||||
|
||||
q = g3[b01 + bz0];
|
||||
u = at3(rx0, ry1, rz0);
|
||||
q = g3[b11 + bz0];
|
||||
v = at3(rx1, ry1, rz0);
|
||||
b = lerp(t, u, v);
|
||||
|
||||
c = lerp(sy, a, b);
|
||||
|
||||
q = g3[b00 + bz1];
|
||||
u = at3(rx0, ry0, rz1);
|
||||
q = g3[b10 + bz1];
|
||||
v = at3(rx1, ry0, rz1);
|
||||
a = lerp(t, u, v);
|
||||
|
||||
q = g3[b01 + bz1];
|
||||
u = at3(rx0, ry1, rz1);
|
||||
q = g3[b11 + bz1];
|
||||
v = at3(rx1, ry1, rz1);
|
||||
b = lerp(t, u, v);
|
||||
|
||||
d = lerp(sy, a, b);
|
||||
|
||||
return lerp(sz, c, d);
|
||||
}
|
||||
|
||||
void normalize2(double v[2]) {
|
||||
double s;
|
||||
|
||||
s = sqrt(v[0] * v[0] + v[1] * v[1]);
|
||||
v[0] = v[0] / s;
|
||||
v[1] = v[1] / s;
|
||||
}
|
||||
|
||||
void normalize3(double v[3]) {
|
||||
double s;
|
||||
|
||||
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||
v[0] = v[0] / s;
|
||||
v[1] = v[1] / s;
|
||||
v[2] = v[2] / s;
|
||||
}
|
||||
|
||||
/* --- My harmonic summing functions - PDB --------------------------*/
|
||||
|
||||
/*
|
||||
In what follows "alpha" is the weight when the sum is formed.
|
||||
Typically it is 2, As this approaches 1 the function is noisier.
|
||||
"beta" is the harmonic scaling/spacing, typically 2.
|
||||
*/
|
||||
|
||||
double noise1D(double x, double alpha, double beta, int n) {
|
||||
int i;
|
||||
double val, sum = 0;
|
||||
double p, scale = 1;
|
||||
|
||||
p = x;
|
||||
for (i = 0; i < n; i++) {
|
||||
val = noise1(p);
|
||||
sum += val / scale;
|
||||
scale *= alpha;
|
||||
p *= beta;
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
double noise2D(double x, double y, double alpha, double beta, int n) {
|
||||
int i;
|
||||
double val, sum = 0;
|
||||
double p[2], scale = 1;
|
||||
|
||||
p[0] = x;
|
||||
p[1] = y;
|
||||
for (i = 0; i < n; i++) {
|
||||
val = noise2(p);
|
||||
sum += val / scale;
|
||||
scale *= alpha;
|
||||
p[0] *= beta;
|
||||
p[1] *= beta;
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
double noise3D(double x, double y, double z, double alpha, double beta, int n) {
|
||||
int i;
|
||||
double val, sum = 0;
|
||||
double p[3], scale = 1;
|
||||
|
||||
p[0] = x;
|
||||
p[1] = y;
|
||||
p[2] = z;
|
||||
for (i = 0; i < n; i++) {
|
||||
val = noise3(p);
|
||||
sum += val / scale;
|
||||
scale *= alpha;
|
||||
p[0] *= beta;
|
||||
p[1] *= beta;
|
||||
p[2] *= beta;
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
void init() {
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < B; i++) {
|
||||
p[i] = i;
|
||||
g1[i] = (double) ((rand() % (B + B)) - B) / B;
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
g2[i][j] = (double) ((rand() % (B + B)) - B) / B;
|
||||
normalize2(g2[i]);
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
g3[i][j] = (double) ((rand() % (B + B)) - B) / B;
|
||||
normalize3(g3[i]);
|
||||
}
|
||||
|
||||
while (--i) {
|
||||
k = p[i];
|
||||
p[i] = p[j = rand() % B];
|
||||
p[j] = k;
|
||||
}
|
||||
|
||||
for (i = 0; i < B + 2; i++) {
|
||||
p[B + i] = p[i];
|
||||
g1[B + i] = g1[i];
|
||||
for (j = 0; j < 2; j++)
|
||||
g2[B + i][j] = g2[i][j];
|
||||
for (j = 0; j < 3; j++)
|
||||
g3[B + i][j] = g3[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
END_NAMESPACE
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
namespace perlin {
|
||||
|
||||
void init();
|
||||
|
||||
double noise1D(double x, double alpha, double beta, int n);
|
||||
double noise2D(double x, double y, double alpha, double beta, int n);
|
||||
double noise3D(double x, double y, double z, double alpha, double beta, int n);
|
||||
}
|
||||
END_NAMESPACE
|
||||
@@ -35,4 +35,11 @@ camera_node &scene_node::as_camera_node() {
|
||||
return *static_cast<camera_node *>(this);
|
||||
}
|
||||
|
||||
static size_t current_id = 0;
|
||||
|
||||
scene_node::scene_node() {
|
||||
id = current_id++;
|
||||
rotation = glm::angleAxis(0.0f, glm::vec3(1, 0, 0));
|
||||
}
|
||||
|
||||
END_NAMESPACE
|
||||
|
||||
+3
-1
@@ -21,6 +21,8 @@ struct light_node;
|
||||
struct camera_node;
|
||||
|
||||
struct scene_node {
|
||||
scene_node();
|
||||
|
||||
virtual void calculate_local_transform();
|
||||
void apply_parent_transform(const glm::mat4& parent_transform);
|
||||
|
||||
@@ -28,7 +30,7 @@ struct scene_node {
|
||||
light_node& as_light_node();
|
||||
camera_node& as_camera_node();
|
||||
|
||||
int id;
|
||||
size_t id;
|
||||
std::string name;
|
||||
scene_node_type type; // We rely on type comparison instead of dynamic casting because comparing types is much faster
|
||||
|
||||
|
||||
+73
-54
@@ -1,6 +1,6 @@
|
||||
#include "scene_renderer.h"
|
||||
#include "light_node.h"
|
||||
#include "shader.h"
|
||||
#include "shader_program.h"
|
||||
#include "material.h"
|
||||
#include "mesh_node.h"
|
||||
#include "demo_data.h"
|
||||
@@ -277,20 +277,20 @@ scene_renderer::scene_renderer()
|
||||
|
||||
glGenFramebuffers(1, &fbo_id);
|
||||
|
||||
first_pass_shadow_shader = std::make_shared<shader>(vs, ps);
|
||||
first_pass_shadow_shader = std::make_shared<shader_program>(vs, ps);
|
||||
|
||||
first_pass_shadow_material = std::make_shared<material>();
|
||||
first_pass_shadow_material->shader_ = first_pass_shadow_shader;
|
||||
first_pass_shadow_material->shader = first_pass_shadow_shader;
|
||||
first_pass_shadow_material->zbuffer_write = true;
|
||||
first_pass_shadow_material->zbuffer_test = true;
|
||||
first_pass_shadow_material->transparent = false;
|
||||
first_pass_shadow_material->cull_faces = true;
|
||||
first_pass_shadow_material->cull_front_faces = false;
|
||||
|
||||
second_pass_shadow_shader = std::make_shared<shader>(vs3, ps3);
|
||||
second_pass_shadow_shader = std::make_shared<shader_program>(vs3, ps3);
|
||||
|
||||
second_pass_shadow_material = std::make_shared<material>();
|
||||
second_pass_shadow_material->shader_ = second_pass_shadow_shader;
|
||||
second_pass_shadow_material->shader = second_pass_shadow_shader;
|
||||
second_pass_shadow_material->diffuse = glm::vec4(1, 0, 0, 1);
|
||||
second_pass_shadow_material->zbuffer_write = true;
|
||||
second_pass_shadow_material->zbuffer_test = true;
|
||||
@@ -305,15 +305,28 @@ void scene_renderer::attach_depth_texture(texture &text) const {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void scene_renderer::render(const scene_tree &tree, const std::string &cameraName) {
|
||||
// for (auto &node: scene.lights) {
|
||||
// light_node &light = node->as_light_node();
|
||||
// glActiveTexture(GL_TEXTURE0);
|
||||
// render_shadow_map(scene, light);
|
||||
// }
|
||||
|
||||
std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, scene_node_type::camera);
|
||||
camera_node &camera = camNode->as_camera_node();
|
||||
std::string to_string(const glm::vec3& v) {
|
||||
std::stringstream ss;
|
||||
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << "}";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_string(const glm::quat& v) {
|
||||
std::stringstream ss;
|
||||
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << ", w:" << v.w << "}";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void scene_renderer::render(const scene_tree& tree, const std::string& cam_name) {
|
||||
for (auto& node: tree.lights) {
|
||||
light_node& light = node->as_light_node();
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
render_shadow_map(tree, light);
|
||||
}
|
||||
|
||||
std::shared_ptr<scene_node> cam_node = tree.node_by_name_and_type(cam_name, scene_node_type::camera);
|
||||
camera_node& camera = cam_node->as_camera_node();
|
||||
|
||||
shader_consts.set(uniforms::ViewMatrix, camera.view_matrix);
|
||||
shader_consts.set(uniforms::ProjectionMatrix, camera.projection_matrix);
|
||||
@@ -323,74 +336,80 @@ std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, sce
|
||||
|
||||
set_material(second_pass_shadow_material);
|
||||
|
||||
int lightIndex = 0;
|
||||
int light_index = 0;
|
||||
for (auto& node: tree.lights) {
|
||||
light_node& light = node->as_light_node();
|
||||
|
||||
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], lightIndex);
|
||||
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], lightIndex);
|
||||
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], lightIndex);
|
||||
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], light_index);
|
||||
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], light_index);
|
||||
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], light_index);
|
||||
shader_consts.set(uniforms::ShadowBiasMatrix, light.shadow_map_bias_matrix);
|
||||
|
||||
glm::vec3 lightPositionInEyeSpace = light.position - camera.position;
|
||||
shader_consts.set(uniforms::LightPosition, lightPositionInEyeSpace, lightIndex);
|
||||
glm::vec3 light_pos_in_eye_space = light.position - camera.position;
|
||||
shader_consts.set(uniforms::LightPosition, light_pos_in_eye_space, light_index);
|
||||
|
||||
glm::vec3 lightTargetInEyeSpace = light.spot_target - camera.position;
|
||||
shader_consts.set(uniforms::LightTarget, lightTargetInEyeSpace, lightIndex);
|
||||
glm::vec3 light_target_in_eye_space = light.spot_target - camera.position;
|
||||
shader_consts.set(uniforms::LightTarget, light_target_in_eye_space, light_index);
|
||||
|
||||
shader_consts.set(uniforms::LightAmbient, light.ambient, lightIndex);
|
||||
shader_consts.set(uniforms::LightDiffuse, light.diffuse, lightIndex);
|
||||
shader_consts.set(uniforms::LightSpecular, light.specular, lightIndex);
|
||||
shader_consts.set(uniforms::LightAmbient, light.ambient, light_index);
|
||||
shader_consts.set(uniforms::LightDiffuse, light.diffuse, light_index);
|
||||
shader_consts.set(uniforms::LightSpecular, light.specular, light_index);
|
||||
|
||||
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, lightIndex);
|
||||
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, lightIndex);
|
||||
shader_consts.set(uniforms::LightAttenuation, light.attenuation, lightIndex);
|
||||
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, light_index);
|
||||
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, light_index);
|
||||
shader_consts.set(uniforms::LightAttenuation, light.attenuation, light_index);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 4 + lightIndex);
|
||||
glActiveTexture(GL_TEXTURE0 + 4 + light_index);
|
||||
glBindTexture(GL_TEXTURE_2D, light.shadow_map[0]->get_id());
|
||||
|
||||
if (lightIndex == 0) {
|
||||
shader_consts.set(uniforms::ShadowMap1, lightIndex + 4);
|
||||
} else if (lightIndex == 1) {
|
||||
shader_consts.set(uniforms::ShadowMap2, lightIndex + 4);
|
||||
} else if (lightIndex == 2) {
|
||||
shader_consts.set(uniforms::ShadowMap3, lightIndex + 4);
|
||||
} else if (lightIndex == 3) {
|
||||
shader_consts.set(uniforms::ShadowMap4, lightIndex + 4);
|
||||
if (light_index == 0) {
|
||||
shader_consts.set(uniforms::ShadowMap1, light_index + 4);
|
||||
} else if (light_index == 1) {
|
||||
shader_consts.set(uniforms::ShadowMap2, light_index + 4);
|
||||
} else if (light_index == 2) {
|
||||
shader_consts.set(uniforms::ShadowMap3, light_index + 4);
|
||||
} else if (light_index == 3) {
|
||||
shader_consts.set(uniforms::ShadowMap4, light_index + 4);
|
||||
}
|
||||
|
||||
lightIndex++;
|
||||
light_index++;
|
||||
}
|
||||
|
||||
// draw opaque nodes
|
||||
for (auto& node: tree.nodes) {
|
||||
if (node->type == scene_node_type::mesh) {
|
||||
mesh_node &meshNode = node->as_mesh_node();
|
||||
mesh_node& mesh_node = node->as_mesh_node();
|
||||
|
||||
glm::mat3 normalMatrix = glm::inverseTranspose(
|
||||
glm::mat3(camera.view_matrix * meshNode.model_to_world_space_matrix));
|
||||
// if (node->name == "light mesh") {
|
||||
// LOG(INFO) << "rendering light mesh. position: " << to_string(mesh_node.position)
|
||||
// << ", scale: " << to_string(mesh_node.scale)
|
||||
// << ", rotation: " << to_string(mesh_node.rotation);
|
||||
// }
|
||||
|
||||
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
|
||||
shader_consts.set(uniforms::NormalMatrix, normalMatrix);
|
||||
shader_consts.set(uniforms::MaterialAmbientColor, meshNode.material_->ambient);
|
||||
shader_consts.set(uniforms::MaterialDiffuseColor, meshNode.material_->diffuse);
|
||||
shader_consts.set(uniforms::MaterialSpecularColor, meshNode.material_->specular);
|
||||
shader_consts.set(uniforms::MaterialShininess, meshNode.material_->shininess);
|
||||
glm::mat3 normal_mat = glm::inverseTranspose(
|
||||
glm::mat3(camera.view_matrix * mesh_node.model_to_world_space_matrix));
|
||||
|
||||
shader_consts.apply_to(*second_pass_shadow_material->shader_);
|
||||
shader_consts.set(uniforms::ModelToWorldMatrix, mesh_node.model_to_world_space_matrix);
|
||||
shader_consts.set(uniforms::NormalMatrix, normal_mat);
|
||||
shader_consts.set(uniforms::MaterialAmbientColor, mesh_node.material_->ambient);
|
||||
shader_consts.set(uniforms::MaterialDiffuseColor, mesh_node.material_->diffuse);
|
||||
shader_consts.set(uniforms::MaterialSpecularColor, mesh_node.material_->specular);
|
||||
shader_consts.set(uniforms::MaterialShininess, mesh_node.material_->shininess);
|
||||
|
||||
if (meshNode.material_->textures[texture_role::diffuse]) {
|
||||
int textureUnit = 0;
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
meshNode.material_->textures[texture_role::diffuse]->use();
|
||||
shader_consts.apply_to(*second_pass_shadow_material->shader);
|
||||
|
||||
second_pass_shadow_material->shader_->setIntUniform(textureUnit, "diffuseMap");
|
||||
if (mesh_node.material_->textures[texture_role::diffuse]) {
|
||||
int texture_unit = 0;
|
||||
glActiveTexture(GL_TEXTURE0 + texture_unit);
|
||||
mesh_node.material_->textures[texture_role::diffuse]->use();
|
||||
|
||||
second_pass_shadow_material->shader->set_int(texture_unit, "diffuseMap");
|
||||
} else {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
meshNode.mesh_->render(second_pass_shadow_material->flat_shaded);
|
||||
mesh_node.mesh_->render(second_pass_shadow_material->flat_shaded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +441,7 @@ void scene_renderer::render_shadow_map(const scene_tree &scene, light_node &ligh
|
||||
if (!meshNode.material_->transparent && meshNode.material_->cast_shadows) {
|
||||
|
||||
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
|
||||
shader_consts.apply_to(*first_pass_shadow_material->shader_);
|
||||
shader_consts.apply_to(*first_pass_shadow_material->shader);
|
||||
|
||||
meshNode.mesh_->render(first_pass_shadow_material->flat_shaded);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
class shader;
|
||||
class shader_program;
|
||||
|
||||
class material;
|
||||
|
||||
@@ -17,16 +17,16 @@ public:
|
||||
|
||||
scene_renderer();
|
||||
|
||||
void render(const scene_tree &tree, const std::string &cameraName);
|
||||
void render(const scene_tree &tree, const std::string &cam_name);
|
||||
|
||||
private:
|
||||
void attach_depth_texture(texture &text) const;
|
||||
void render_shadow_map(const scene_tree &scene, light_node &light);
|
||||
|
||||
std::shared_ptr<shader> first_pass_shadow_shader;
|
||||
std::shared_ptr<shader_program> first_pass_shadow_shader;
|
||||
std::shared_ptr<material> first_pass_shadow_material;
|
||||
|
||||
std::shared_ptr<shader> second_pass_shadow_shader;
|
||||
std::shared_ptr<shader_program> second_pass_shadow_shader;
|
||||
std::shared_ptr<material> second_pass_shadow_material;
|
||||
|
||||
shader_constants shader_consts;
|
||||
|
||||
+8
-6
@@ -1,29 +1,31 @@
|
||||
#include "scene_tree.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
std::shared_ptr<scene_node> scene_tree::nodeById(int id) const {
|
||||
std::shared_ptr<scene_node> scene_tree::node_by_id(size_t id) const {
|
||||
for (auto& node : nodes)
|
||||
if (node->id == id)
|
||||
return node;
|
||||
|
||||
return std::shared_ptr<scene_node>(nullptr);
|
||||
return {nullptr};
|
||||
}
|
||||
|
||||
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(std::string name, scene_node_type type) const {
|
||||
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(const std::string& name, scene_node_type type) const {
|
||||
for (auto& node : nodes)
|
||||
if (node->name == name && node->type == type)
|
||||
return node;
|
||||
|
||||
return std::shared_ptr<scene_node>(nullptr);
|
||||
return {nullptr};
|
||||
}
|
||||
|
||||
|
||||
void scene_tree::add(std::shared_ptr<scene_node> node) {
|
||||
add(node, std::shared_ptr<scene_node>(nullptr));
|
||||
add(std::move(node), std::shared_ptr<scene_node>(nullptr));
|
||||
}
|
||||
|
||||
void scene_tree::add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent) {
|
||||
void scene_tree::add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent) {
|
||||
nodes.push_back(node);
|
||||
node->parent = parent;
|
||||
|
||||
|
||||
+3
-3
@@ -8,11 +8,11 @@ BEGIN_NAMESPACE
|
||||
class scene_tree {
|
||||
public:
|
||||
|
||||
std::shared_ptr<scene_node> nodeById(int id) const;
|
||||
std::shared_ptr<scene_node> node_by_name_and_type(std::string name, scene_node_type type) const;
|
||||
std::shared_ptr<scene_node> node_by_id(size_t id) const;
|
||||
std::shared_ptr<scene_node> node_by_name_and_type(const std::string& name, scene_node_type type) const;
|
||||
|
||||
void add(std::shared_ptr<scene_node> node);
|
||||
void add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent);
|
||||
void add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent);
|
||||
|
||||
void transform();
|
||||
|
||||
|
||||
+21
-21
@@ -1,4 +1,4 @@
|
||||
#include "shader.h"
|
||||
#include "shader_program.h"
|
||||
#include <iostream>
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
@@ -47,7 +47,7 @@ void check_link_error(GLuint program_id) {
|
||||
}
|
||||
}
|
||||
|
||||
shader::shader(const char *vs_content, const char *ps_content)
|
||||
shader_program::shader_program(const char *vs_content, const char *ps_content)
|
||||
: shader_ids{0, 0},
|
||||
program_id{0} {
|
||||
|
||||
@@ -117,7 +117,7 @@ shader::shader(const char *vs_content, const char *ps_content)
|
||||
// glUseProgram(program_id);
|
||||
}
|
||||
|
||||
shader::~shader() {
|
||||
shader_program::~shader_program() {
|
||||
glDetachShader(program_id, shader_ids[0]);
|
||||
glDetachShader(program_id, shader_ids[1]);
|
||||
|
||||
@@ -127,53 +127,53 @@ shader::~shader() {
|
||||
glDeleteProgram(program_id);
|
||||
}
|
||||
|
||||
void shader::use() const {
|
||||
void shader_program::bind() const {
|
||||
glUseProgram(program_id);
|
||||
}
|
||||
|
||||
void shader::unuse() const {
|
||||
void shader_program::unbind() {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
int shader::getUniform(const char *uniformName) {
|
||||
if (uniform_cache.count(uniformName) == 0) {
|
||||
uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName);
|
||||
int shader_program::get_uniform(const char *name) {
|
||||
if (uniform_cache.count(name) == 0) {
|
||||
uniform_cache[name] = glGetUniformLocation(program_id, name);
|
||||
}
|
||||
return uniform_cache[uniformName];
|
||||
return uniform_cache[name];
|
||||
}
|
||||
|
||||
void shader::setMatrix3Uniform(float *matrix, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_mat3(float *matrix, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniformMatrix3fv(location, 1, false, matrix);
|
||||
}
|
||||
|
||||
void shader::setMatrix4Uniform(float *matrix, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_mat4(float *matrix, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniformMatrix4fv(location, 1, false, matrix);
|
||||
}
|
||||
|
||||
void shader::setVec3Uniform(float *value, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_vec3(float *value, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniform3fv(location, 1, value);
|
||||
}
|
||||
|
||||
void shader::setVec4Uniform(float *value, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_vec4(float *value, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniform4fv(location, 1, value);
|
||||
}
|
||||
|
||||
void shader::setIntUniform(int value, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_int(int value, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniform1i(location, value);
|
||||
}
|
||||
|
||||
void shader::setFloatUniform(float value, const char *uniformName) {
|
||||
GLint location = getUniform(uniformName);
|
||||
void shader_program::set_float(float value, const char *uniform_name) {
|
||||
GLint location = get_uniform(uniform_name);
|
||||
if (location != -1)
|
||||
glUniform1f(location, value);
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <map>
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
class shader {
|
||||
public:
|
||||
shader(const char *vs_content, const char *ps_content);
|
||||
virtual ~shader();
|
||||
|
||||
void use() const;
|
||||
void unuse() const;
|
||||
|
||||
GLuint getId() const { return program_id; }
|
||||
int getUniform(const char *uniformName);
|
||||
|
||||
void setMatrix3Uniform(float *value, const char *uniformName);
|
||||
void setMatrix4Uniform(float *value, const char *uniformName);
|
||||
void setVec3Uniform(float *value, const char *uniformName);
|
||||
void setVec4Uniform(float *value, const char *uniformName);
|
||||
void setFloatUniform(float value, const char *uniformName);
|
||||
void setIntUniform(int value, const char *uniformName);
|
||||
|
||||
private:
|
||||
GLuint program_id;
|
||||
GLuint shader_ids[2];
|
||||
std::map<const char *, int> uniform_cache;
|
||||
};
|
||||
|
||||
|
||||
END_NAMESPACE
|
||||
+48
-49
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include "shader.h"
|
||||
#include "shader_program.h"
|
||||
#include "texture.h"
|
||||
#include <map>
|
||||
#include "material.h"
|
||||
@@ -16,8 +16,7 @@ struct uniform_descriptor {
|
||||
std::string member_name;
|
||||
|
||||
// TODO: implement memoization of uniform name calculation
|
||||
|
||||
uniform_descriptor(const char *member) {
|
||||
explicit uniform_descriptor(const char *member) {
|
||||
structure_name = "";
|
||||
member_name = member;
|
||||
}
|
||||
@@ -27,7 +26,7 @@ struct uniform_descriptor {
|
||||
member_name = member;
|
||||
}
|
||||
|
||||
std::string get_name() {
|
||||
std::string get_name() const {
|
||||
if (structure_name.empty())
|
||||
return member_name;
|
||||
|
||||
@@ -36,7 +35,7 @@ struct uniform_descriptor {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string get_name(int index) {
|
||||
std::string get_name(int index) const {
|
||||
std::stringstream ss;
|
||||
if (structure_name.empty()) {
|
||||
ss << member_name << "[" << index << "]";
|
||||
@@ -93,72 +92,72 @@ public:
|
||||
|
||||
shader_constant_type type;
|
||||
|
||||
glm::vec3 vec3Val{};
|
||||
glm::vec4 vec4Val{};
|
||||
glm::mat3 mat3Val{};
|
||||
glm::mat4 mat4Val{};
|
||||
int intVal{};
|
||||
float floatVal{};
|
||||
glm::vec3 vec3_val{};
|
||||
glm::vec4 vec4_val{};
|
||||
glm::mat3 mat3_val{};
|
||||
glm::mat4 mat4_val{};
|
||||
int int_val{};
|
||||
float float_val{};
|
||||
|
||||
shader_constant_value(const shader_constant_value& rhs) {
|
||||
type = rhs.type;
|
||||
vec3Val = rhs.vec3Val;
|
||||
vec4Val = rhs.vec4Val;
|
||||
mat3Val = rhs.mat3Val;
|
||||
mat4Val = rhs.mat4Val;
|
||||
intVal = rhs.intVal;
|
||||
floatVal = rhs.floatVal;
|
||||
vec3_val = rhs.vec3_val;
|
||||
vec4_val = rhs.vec4_val;
|
||||
mat3_val = rhs.mat3_val;
|
||||
mat4_val = rhs.mat4_val;
|
||||
int_val = rhs.int_val;
|
||||
float_val = rhs.float_val;
|
||||
}
|
||||
|
||||
shader_constant_value(glm::vec3 &value) {
|
||||
vec3Val = value;
|
||||
explicit shader_constant_value(glm::vec3& value) {
|
||||
vec3_val = value;
|
||||
type = shader_constant_type::vec3;
|
||||
}
|
||||
|
||||
shader_constant_value(glm::vec4 &value) {
|
||||
vec4Val = value;
|
||||
explicit shader_constant_value(glm::vec4& value) {
|
||||
vec4_val = value;
|
||||
type = shader_constant_type::vec4;
|
||||
}
|
||||
|
||||
shader_constant_value(glm::mat3 &value) {
|
||||
mat3Val = value;
|
||||
explicit shader_constant_value(glm::mat3& value) {
|
||||
mat3_val = value;
|
||||
type = shader_constant_type::mat3;
|
||||
}
|
||||
|
||||
shader_constant_value(glm::mat4 &value) {
|
||||
mat4Val = value;
|
||||
explicit shader_constant_value(glm::mat4& value) {
|
||||
mat4_val = value;
|
||||
type = shader_constant_type::mat4;
|
||||
}
|
||||
|
||||
shader_constant_value(int value) {
|
||||
intVal = value;
|
||||
explicit shader_constant_value(int value) {
|
||||
int_val = value;
|
||||
type = shader_constant_type::integer;
|
||||
}
|
||||
|
||||
shader_constant_value(float value) {
|
||||
floatVal = value;
|
||||
explicit shader_constant_value(float value) {
|
||||
float_val = value;
|
||||
type = shader_constant_type::decimal;
|
||||
}
|
||||
|
||||
void apply_to(shader &sh, const char *uniform_name) {
|
||||
void apply_to(shader_program& sh, const char *uniform_name) {
|
||||
switch (type) {
|
||||
case shader_constant_type::vec3:
|
||||
sh.setVec3Uniform(glm::value_ptr(vec3Val), uniform_name);
|
||||
sh.set_vec3(glm::value_ptr(vec3_val), uniform_name);
|
||||
break;
|
||||
case shader_constant_type::vec4:
|
||||
sh.setVec4Uniform(glm::value_ptr(vec4Val), uniform_name);
|
||||
sh.set_vec4(glm::value_ptr(vec4_val), uniform_name);
|
||||
break;
|
||||
case shader_constant_type::mat3:
|
||||
sh.setMatrix3Uniform(glm::value_ptr(mat3Val), uniform_name);
|
||||
sh.set_mat3(glm::value_ptr(mat3_val), uniform_name);
|
||||
break;
|
||||
case shader_constant_type::mat4:
|
||||
sh.setMatrix4Uniform(glm::value_ptr(mat4Val), uniform_name);
|
||||
sh.set_mat4(glm::value_ptr(mat4_val), uniform_name);
|
||||
break;
|
||||
case shader_constant_type::integer:
|
||||
sh.setIntUniform(intVal, uniform_name);
|
||||
sh.set_int(int_val, uniform_name);
|
||||
break;
|
||||
case shader_constant_type::decimal:
|
||||
sh.setFloatUniform(floatVal, uniform_name);
|
||||
sh.set_float(float_val, uniform_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -168,55 +167,55 @@ public:
|
||||
class shader_constants {
|
||||
public:
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::mat3 value) {
|
||||
void set(const uniform_descriptor& descriptor, glm::mat3 value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::mat3 value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, glm::mat3 value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::mat4 value) {
|
||||
void set(const uniform_descriptor& descriptor, glm::mat4 value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::mat4 value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, glm::mat4 value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::vec3 value) {
|
||||
void set(const uniform_descriptor& descriptor, glm::vec3 value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::vec3 value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, glm::vec3 value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::vec4 value) {
|
||||
void set(const uniform_descriptor& descriptor, glm::vec4 value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, glm::vec4 value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, glm::vec4 value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, int value) {
|
||||
void set(const uniform_descriptor& descriptor, int value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, int value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, int value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, float value) {
|
||||
void set(const uniform_descriptor& descriptor, float value) {
|
||||
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void set(uniform_descriptor descriptor, float value, int index) {
|
||||
void set(const uniform_descriptor& descriptor, float value, int index) {
|
||||
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
|
||||
}
|
||||
|
||||
void apply_to(shader &shd) {
|
||||
void apply_to(shader_program& shd) {
|
||||
for (auto& kv: constants)
|
||||
kv.second->apply_to(shd, kv.first.c_str());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "defines.h"
|
||||
#include <map>
|
||||
|
||||
BEGIN_NAMESPACE
|
||||
|
||||
class shader_program {
|
||||
public:
|
||||
shader_program(const char *vs_content, const char *ps_content);
|
||||
virtual ~shader_program();
|
||||
|
||||
void bind() const;
|
||||
static void unbind() ;
|
||||
|
||||
GLuint get_id() const { return program_id; }
|
||||
|
||||
int get_uniform(const char *name);
|
||||
|
||||
void set_mat3(float *value, const char *uniform_name);
|
||||
void set_mat4(float *value, const char *uniform_name);
|
||||
void set_vec3(float *value, const char *uniform_name);
|
||||
void set_vec4(float *value, const char *uniform_name);
|
||||
void set_float(float value, const char *uniform_name);
|
||||
void set_int(int value, const char *uniform_name);
|
||||
|
||||
private:
|
||||
GLuint program_id;
|
||||
GLuint shader_ids[2];
|
||||
std::map<const char *, int> uniform_cache;
|
||||
};
|
||||
|
||||
END_NAMESPACE
|
||||
+4
-4
@@ -7,15 +7,15 @@ timer::timer() {
|
||||
last_lap_time = start_time;
|
||||
}
|
||||
|
||||
double timer::seconds_since_start() {
|
||||
float timer::seconds_since_start() {
|
||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
std::chrono::duration<double> elapsed_seconds = now - start_time;
|
||||
std::chrono::duration<float> elapsed_seconds = now - start_time;
|
||||
return elapsed_seconds.count();
|
||||
}
|
||||
|
||||
double timer::lap() {
|
||||
float timer::lap() {
|
||||
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
|
||||
std::chrono::duration<double> elapsed_seconds = now - last_lap_time;
|
||||
std::chrono::duration<float> elapsed_seconds = now - last_lap_time;
|
||||
last_lap_time = now;
|
||||
return elapsed_seconds.count();
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ class timer {
|
||||
public:
|
||||
timer();
|
||||
|
||||
double seconds_since_start();
|
||||
double lap();
|
||||
float seconds_since_start();
|
||||
float lap();
|
||||
|
||||
private:
|
||||
std::chrono::time_point<std::chrono::system_clock> start_time;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
intro:
|
||||
- benzene elements come together and form the symbol
|
||||
- they slowly come into place and rotate
|
||||
- either explode into particles or fade away
|
||||
|
||||
scenes:
|
||||
- camera flyby trhough a sci-fi tunnel composed of metalic pipe systems and awkward light
|
||||
- walk through a forest made with L-systems
|
||||
- heightmap
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user