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