Create basics source files
This commit is contained in:
parent
0d0652bbc0
commit
e29a9115d1
8 changed files with 477 additions and 0 deletions
41
CMakeLists.txt
Normal file
41
CMakeLists.txt
Normal file
|
@ -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)
|
||||||
|
|
||||||
|
|
29
resources/shaders/square.glsl
Normal file
29
resources/shaders/square.glsl
Normal file
|
@ -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);
|
||||||
|
}
|
88
src/opengl/renderer.cpp
Normal file
88
src/opengl/renderer.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
54
src/opengl/renderer.hpp
Normal file
54
src/opengl/renderer.hpp
Normal file
|
@ -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);
|
||||||
|
};
|
149
src/opengl/shaders.cpp
Normal file
149
src/opengl/shaders.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
21
src/opengl/shaders.hpp
Normal file
21
src/opengl/shaders.hpp
Normal file
|
@ -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);
|
45
src/rms.cpp
Normal file
45
src/rms.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
50
tools/shader_watcher.sh
Executable file
50
tools/shader_watcher.sh
Executable file
|
@ -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
|
Loading…
Add table
Reference in a new issue