aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt41
-rw-r--r--resources/shaders/square.glsl29
-rw-r--r--src/opengl/renderer.cpp88
-rw-r--r--src/opengl/renderer.hpp54
-rw-r--r--src/opengl/shaders.cpp149
-rw-r--r--src/opengl/shaders.hpp21
-rw-r--r--src/rms.cpp45
-rwxr-xr-xtools/shader_watcher.sh50
8 files changed, 477 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..2032208
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.17)
+project(rms)
+set(CMAKE_BUILD_TYPE Debug)
+
+# SFML (window system)
+find_package(SFML 2.5 COMPONENTS window)
+link_libraries(sfml-window)
+
+# GLEW (OpenglGL dependecies manager)
+find_package(GLEW REQUIRED)
+include_directories(${GLEW_INCLUDE_DIRS})
+link_libraries(${GLEW_LIBRARIES})
+
+# OpenGL
+find_package(OpenGL REQUIRED)
+include_directories( ${OPENGL_INCLUDE_DIRS})
+link_libraries(${OPENGL_LIBRARIES})
+
+# GLM for mathematics
+find_package(glm 0.9 REQUIRED)
+include_directories( ${GLM_INCLUDE_DIRS})
+
+# Source files
+file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS src/*.cpp src/*.hpp)
+file(GLOB_RECURSE SHADERS_SRC_FILES CONFIGURE_DEPENDS resources/shaders/*)
+
+# Build
+include_directories(${CMAKE_SOURCE_DIR}/src/)
+add_executable(rms ${SRC_FILES})
+
+
+# Shaders
+add_custom_target(shaders
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_SOURCE_DIR}/resources/shaders ${CMAKE_BINARY_DIR}/resources/shaders
+ SOURCES ${SHADERS_SRC_FILES})
+
+# Build shaders each time we build rms
+add_dependencies(rms shaders)
+
+
diff --git a/resources/shaders/square.glsl b/resources/shaders/square.glsl
new file mode 100644
index 0000000..200215c
--- /dev/null
+++ b/resources/shaders/square.glsl
@@ -0,0 +1,29 @@
+// ----- Vertex Shader -----
+#version 330 core
+
+layout(location = 0) in vec3 position;
+uniform mat4 projection;
+uniform mat4 model;
+
+
+void main(){
+
+ gl_Position = projection * model * vec4(position,1);
+
+}
+
+// ----- Fragment Shader -----
+
+#version 330 core
+
+uniform vec2 resolution;
+uniform float time;
+
+out vec3 color;
+
+void main(){
+ vec2 coord=gl_FragCoord.xy/resolution;
+ coord-=0.5;
+ float d=length(coord);
+ color=vec3(d,1,1);
+}
diff --git a/src/opengl/renderer.cpp b/src/opengl/renderer.cpp
new file mode 100644
index 0000000..1898753
--- /dev/null
+++ b/src/opengl/renderer.cpp
@@ -0,0 +1,88 @@
+#include "renderer.hpp"
+#include <iostream>
+
+
+void GLAPIENTRY MessageCallback( GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const void* userParam )
+{
+ std::cerr << "GL CALLBACK" <<
+ (type == GL_DEBUG_TYPE_ERROR ? "(ERROR):" : "(UNKNOWN):") <<
+ " type="<< std::showbase << std::hex << type <<
+ " severity="<< severity << " message=" << message << std::endl;
+
+
+}
+
+Renderer::Renderer(short width,short height): Width(width),Height(height), ClockStart(steady_clock::now()){
+ // Init OpenGl
+ glewInit();
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+ glEnable ( GL_DEBUG_OUTPUT );
+ glDebugMessageCallback( MessageCallback, 0 );
+
+ // Create screen quad
+ glGenVertexArrays(1,&VAO);
+ glBindVertexArray(VAO);
+ GLuint vertexbuffer;
+ glGenBuffers(1, &vertexbuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
+ float square[]{
+ -1,1,0,
+ 1,1,0,
+ -1,-1,0,
+
+ -1,-1,0,
+ 1,1,0,
+ 1,-1,0
+
+ };
+ glBufferData(GL_ARRAY_BUFFER, 6*3*sizeof(float), square, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
+ glBindVertexArray(0);
+ LoadShader("square.glsl");
+}
+
+void Renderer::Render(){
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glUseProgram(RayMarchingShader);
+ MProjection=glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.f,100.0f);
+ MModel=glm::scale(glm::mat4(1.0f),glm::vec3(10,10,1));
+ glUniformMatrix4fv(UProjection, 1, GL_FALSE, &MProjection[0][0]);
+ glUniformMatrix4fv(UModel, 1, GL_FALSE, &MModel[0][0]);
+ ClockCurrent = std::chrono::steady_clock::now();
+ duration<double> time_span = duration_cast<duration<double>>(ClockCurrent - ClockStart);
+ glUniform1f(UTime, time_span.count());
+
+ glUniform2f(UResolution,Width,Height);
+ glBindVertexArray(VAO);
+ glDrawArrays(GL_TRIANGLES,0,6);
+ glBindVertexArray(0);
+ glUseProgram(0);
+}
+
+void Renderer::UpdateShader(std::string name){
+ glDeleteProgram(RayMarchingShader);
+ LoadShader(name);
+}
+
+void Renderer::LoadShader(std::string name){
+ RayMarchingShader = CompileShader("square.glsl");
+ RayMarchingShader = CompileShader("square.glsl");
+ UProjection = glGetUniformLocation(RayMarchingShader, "projection");
+ UModel = glGetUniformLocation(RayMarchingShader, "model");
+ UResolution = glGetUniformLocation(RayMarchingShader, "resolution");
+ UTime = glGetUniformLocation(RayMarchingShader, "time");
+}
+
+void Renderer::AjustViewport(short width,short height){
+ glViewport(0, 0, width,height);
+ this->Width=width;
+ this->Height=height;
+}
diff --git a/src/opengl/renderer.hpp b/src/opengl/renderer.hpp
new file mode 100644
index 0000000..157ceb3
--- /dev/null
+++ b/src/opengl/renderer.hpp
@@ -0,0 +1,54 @@
+#pragma once
+#include <GL/glew.h>
+#include "shaders.hpp"
+#include <glm/glm.hpp>
+#include <chrono>
+#include "glm/gtc/matrix_transform.hpp"
+
+using namespace std::chrono;
+
+/**
+ * Bind this fonction with the following for debugging:
+ * glEnable ( GL_DEBUG_OUTPUT );
+ * glDebugMessageCallback( MessageCallback, 0 );
+ * @param source
+ * @param type
+ * @param id
+ * @param severity
+ * @param length
+ * @param message
+ * @param userParam
+ */
+void GLAPIENTRY MessageCallback( GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const void* userParam);
+
+/**
+ * Main renderer class
+ */
+class Renderer {
+private:
+ GLuint VAO;
+ GLuint RayMarchingShader;
+ GLuint UProjection;
+ GLuint UResolution;
+ GLuint UModel;
+ GLuint UTime;
+ glm::mat4 MProjection;
+ glm::mat4 MModel;
+ short Width,Height;
+ steady_clock::time_point ClockStart;
+ steady_clock::time_point ClockCurrent;
+
+ void LoadShader(std::string name);
+
+public:
+ Renderer(short width,short height);
+ void Render();
+ void AjustViewport(short with,short height);
+ void UpdateShader(std::string name);
+};
diff --git a/src/opengl/shaders.cpp b/src/opengl/shaders.cpp
new file mode 100644
index 0000000..34d4e8f
--- /dev/null
+++ b/src/opengl/shaders.cpp
@@ -0,0 +1,149 @@
+#include "shaders.hpp"
+
+GLuint CompileShader(std::string shader_name){
+ std::ifstream shader_file;
+ shader_file.open(std::string(SHADERS_RESOURCES) + "/" + shader_name);
+ if(!shader_file.is_open()) {
+ std::cout << "Failed to open: " << shader_name << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ std::string line;
+ char type='\0';
+ std::stringstream ss[2];
+ while(getline(shader_file, line)) {
+ if(line.find("- Vertex Shader -") != std::string::npos){
+ type='v';
+ } else if(line.find("- Fragment Shader -") != std::string::npos){
+ type='f';
+ }
+
+ if(type=='v')
+ ss[0] << line << std::endl;
+ else if(type=='f')
+ ss[1] << line << std::endl;
+ }
+
+ // Create ids
+ GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
+ GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
+
+ // Compile vertex shader
+ std::string vsrc=ss[0].str();
+ char const * vsrc_c = vsrc.c_str();
+ glShaderSource(VertexShaderID, 1, &vsrc_c, NULL);
+ glCompileShader(VertexShaderID);
+
+ // Compile fragment shader
+ std::string fsrc=ss[1].str();
+ char const * fsrc_c = fsrc.c_str();
+ glShaderSource(FragmentShaderID, 1, &fsrc_c, NULL);
+ glCompileShader(FragmentShaderID);
+
+ // Link programs
+ GLuint ProgramID = glCreateProgram();
+ glAttachShader(ProgramID, VertexShaderID);
+ glAttachShader(ProgramID, FragmentShaderID);
+ glLinkProgram(ProgramID);
+
+ // Cleaning
+ glDetachShader(ProgramID, VertexShaderID);
+ glDetachShader(ProgramID, FragmentShaderID);
+ glDeleteShader(VertexShaderID);
+ glDeleteShader(FragmentShaderID);
+
+ return ProgramID;
+}
+
+
+GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
+
+ // Create the shaders
+ GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
+ GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
+
+ // Read the Vertex Shader code from the file
+ std::string VertexShaderCode;
+ std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
+ if(VertexShaderStream.is_open()){
+ std::stringstream sstr;
+ sstr << VertexShaderStream.rdbuf();
+ VertexShaderCode = sstr.str();
+ VertexShaderStream.close();
+ }else{
+ printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
+ getchar();
+ return 0;
+ }
+
+ // Read the Fragment Shader code from the file
+ std::string FragmentShaderCode;
+ std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
+ if(FragmentShaderStream.is_open()){
+ std::stringstream sstr;
+ sstr << FragmentShaderStream.rdbuf();
+ FragmentShaderCode = sstr.str();
+ FragmentShaderStream.close();
+ }
+
+ GLint Result = GL_FALSE;
+ int InfoLogLength;
+
+
+ // Compile Vertex Shader
+ printf("Compiling shader : %s\n", vertex_file_path);
+ char const * VertexSourcePointer = VertexShaderCode.c_str();
+ glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
+ glCompileShader(VertexShaderID);
+
+ // Check Vertex Shader
+ glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
+ glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ){
+ std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
+ glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
+ printf("%s\n", &VertexShaderErrorMessage[0]);
+ }
+
+
+
+ // Compile Fragment Shader
+ printf("Compiling shader : %s\n", fragment_file_path);
+ char const * FragmentSourcePointer = FragmentShaderCode.c_str();
+ glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
+ glCompileShader(FragmentShaderID);
+
+ // Check Fragment Shader
+ glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
+ glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ){
+ std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
+ glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
+ printf("%s\n", &FragmentShaderErrorMessage[0]);
+ }
+
+ // Link the program
+ printf("Linking program\n");
+ GLuint ProgramID = glCreateProgram();
+ glAttachShader(ProgramID, VertexShaderID);
+ glAttachShader(ProgramID, FragmentShaderID);
+ glLinkProgram(ProgramID);
+
+ // Check the program
+ glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
+ glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+ if ( InfoLogLength > 0 ){
+ std::vector<char> ProgramErrorMessage(InfoLogLength+1);
+ glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
+ printf("%s\n", &ProgramErrorMessage[0]);
+ }
+
+
+ glDetachShader(ProgramID, VertexShaderID);
+ glDetachShader(ProgramID, FragmentShaderID);
+
+ glDeleteShader(VertexShaderID);
+ glDeleteShader(FragmentShaderID);
+
+ return ProgramID;
+}
diff --git a/src/opengl/shaders.hpp b/src/opengl/shaders.hpp
new file mode 100644
index 0000000..ba7da09
--- /dev/null
+++ b/src/opengl/shaders.hpp
@@ -0,0 +1,21 @@
+#include <GL/glew.h>
+#include <string>
+#include <vector>
+#include <fstream> // ifstream
+#include <sstream> // stringstream
+#include <iostream>
+
+# ifndef NDEBUG
+#define SHADERS_RESOURCES "../resources/shaders/"
+#else
+#define SHADERS_RESOURCES "resources/shaders/"
+#endif
+/**
+ * Compile a shader:
+ * - Shader should contains both vertex and fragment code
+ * - Vertex code should begin with: // ----- Vertex Shader -----
+ * - Fragment code should begin with: // ----- Fragment Shader -----
+ * @param shader_path
+ * @return The generated program id
+ */
+GLuint CompileShader(std::string shader_path);
diff --git a/src/rms.cpp b/src/rms.cpp
new file mode 100644
index 0000000..d2c6136
--- /dev/null
+++ b/src/rms.cpp
@@ -0,0 +1,45 @@
+#include <SFML/Window.hpp>
+#include "opengl/renderer.hpp"
+
+#define WIDTH 1200
+#define HEIGHT 800
+
+int main(int argc, char *argv[])
+{
+ // Init SFML
+ sf::ContextSettings settings;
+ settings.depthBits = 24;
+ settings.stencilBits = 8;
+ settings.antialiasingLevel = 3;
+ settings.attributeFlags=sf::ContextSettings::Core;
+ sf::Window window(sf::VideoMode(WIDTH, HEIGHT,32), "SFML/OpenGL Ray Marching", sf::Style::Close, settings);
+ window.setFramerateLimit(60); // Limit to 60 frames per second
+
+ // Init Renderer/OpenGL
+ Renderer renderer(WIDTH,HEIGHT);
+
+ // Main loop
+ bool running=true;
+ while (running)
+ {
+ // gestion des évènements
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ if (event.type == sf::Event::Closed)
+ running=false;
+ else if (event.type == sf::Event::Resized)
+ renderer.AjustViewport(event.size.width,event.size.height);
+ else if (event.key.code == sf::Keyboard::R)
+ renderer.UpdateShader("square.glsl");
+ }
+
+ renderer.Render();
+ window.display(); // Refresh screen
+ }
+
+ return 0;
+}
+
+
+
diff --git a/tools/shader_watcher.sh b/tools/shader_watcher.sh
new file mode 100755
index 0000000..d32285d
--- /dev/null
+++ b/tools/shader_watcher.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# ____ _ _ _ ____ _____ ____
+# / ___|| | | | / \ | _ \| ____| _ \
+# \___ \| |_| | / _ \ | | | | _| | |_) |
+# ___) | _ |/ ___ \| |_| | |___| _ <
+# |____/|_| |_/_/ \_\____/|_____|_| \_\
+#
+# __ ___ _____ ____ _ _ _____ ____
+# \ \ / / \|_ _/ ___| | | | ____| _ \
+# \ \ /\ / / _ \ | || | | |_| | _| | |_) |
+# \ V V / ___ \| || |___| _ | |___| _ <
+# \_/\_/_/ \_\_| \____|_| |_|_____|_| \_\
+#
+# This program require xdotool to communicate
+# with the window.
+
+wai=$(dirname $(readlink -f "$0")) # Current script directory
+
+
+refresh() {
+ wid=$(xdotool search --name 'SFML/OpenGL Ray Marching')
+ [ ! -z "$wid" ] && xdotool key --window "$wid" R
+}
+
+usage() {
+ echo "Usage: $0 [options]"
+ echo "Options:"
+ echo " --every <time> Refresh shader every <time> seconds"
+ exit 1
+}
+
+[ $# -ne 2 ] && [ $# -ne 0 ] && usage
+
+if [ $# -eq 2 ] && [ $1 == "--every" ]
+then
+ shift
+ time=$1
+ while [ true ]
+ do
+ sleep $time
+ refresh
+ done
+else
+
+ while [ true ]
+ do
+ ls $wai/../resources/shaders/*.glsl | entr -pd -s 'kill $PPID'
+ refresh
+ done
+fi