Create basics source files

This commit is contained in:
Loic Guegan 2020-07-05 18:55:39 +02:00
parent 0d0652bbc0
commit e29a9115d1
8 changed files with 477 additions and 0 deletions

41
CMakeLists.txt Normal file
View 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)

View 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
View 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
View 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
View 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
View 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
View 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
View 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