diff options
| author | Loic Guegan <manzerbredes@mailbox.org> | 2020-07-09 13:02:31 +0200 |
|---|---|---|
| committer | Loic Guegan <manzerbredes@mailbox.org> | 2020-07-09 13:02:31 +0200 |
| commit | 12829892b262a0c7fcccba9198e5b6b31b2a8015 (patch) | |
| tree | 908152ccc4fd1f4ee2c16b4bb8e0bee215ebdae7 | |
| parent | aac94e911b0bab8db5cdb5efb8d4d8f2d4072610 (diff) | |
| -rw-r--r-- | resources/shaders/algorithms/normal.frag | 24 | ||||
| -rw-r--r-- | resources/shaders/algorithms/ray_marching.glsl | 5 | ||||
| -rw-r--r-- | resources/shaders/algorithms/raymarching.frag | 26 | ||||
| -rw-r--r-- | resources/shaders/julia.frag | 48 | ||||
| -rw-r--r-- | resources/shaders/main.frag (renamed from resources/shaders/main.glsl) | 46 | ||||
| -rw-r--r-- | resources/shaders/objects/sphere.frag | 7 | ||||
| -rw-r--r-- | resources/shaders/objects/sphere.glsl | 4 | ||||
| -rw-r--r-- | src/opengl/shaders.cpp | 164 | ||||
| -rw-r--r-- | src/rms.cpp | 9 |
9 files changed, 165 insertions, 168 deletions
diff --git a/resources/shaders/algorithms/normal.frag b/resources/shaders/algorithms/normal.frag new file mode 100644 index 0000000..0f61544 --- /dev/null +++ b/resources/shaders/algorithms/normal.frag @@ -0,0 +1,24 @@ +// Requirements: +// #define NORMAL_ACCURACY 0.01 +// GetDist: (vec3 position) => float +// GetDist should return the closest object point distance from position (in the whole scene) + +/** + * Compute the normal of an object at a given surface point + * this can be usefull for lighting etc.. + * This function exploit the fact that the gradient on a given surface point in 3D space + * given the normal direction (source: https://fr.wikipedia.org/wiki/Gradient#Dimension_3_:_gradient_normal_%C3%A0_une_surface_en_un_point,_plan_tangent) + * + * + */ +vec3 GetNormal(vec3 point_position) { + float point_distance = GetDist(point_position); + vec2 epsilon = vec2(NORMAL_ACCURACY, 0); // Just a convenient way to use NORMAL_ACCURACY and 0 + // Compute the gradient + vec3 gradient = point_distance - vec3( + GetDist(point_position-epsilon.xyy), + GetDist(point_position-epsilon.yxy), + GetDist(point_position-epsilon.yyx)); + + return normalize(gradient); +}
\ No newline at end of file diff --git a/resources/shaders/algorithms/ray_marching.glsl b/resources/shaders/algorithms/ray_marching.glsl deleted file mode 100644 index d984c0e..0000000 --- a/resources/shaders/algorithms/ray_marching.glsl +++ /dev/null @@ -1,5 +0,0 @@ - - -RayMarching(vec3 ro, vec3 rd){ - -}
\ No newline at end of file diff --git a/resources/shaders/algorithms/raymarching.frag b/resources/shaders/algorithms/raymarching.frag new file mode 100644 index 0000000..b8de515 --- /dev/null +++ b/resources/shaders/algorithms/raymarching.frag @@ -0,0 +1,26 @@ +// Requirements: +// #define MAX_STEPS 100 +// #define MAX_DIST 100. +// GetDist: (vec3 position) => float +// GetDist should return the closest object point distance from position (in the whole scene) + +/** + * Ray Marching algorithm + * Please take a look at: https://www.youtube.com/watch?v=PGtv-dBi2wE&t=1367s + * This function return the distance reached by the ray: + * - If dist<MAX_DIST we hit something + */ +float RayMarch(vec3 ray_origin, vec3 ray_direction) { + float dist_origin=0.; // Ray start at the origin + for(int i=0; i<MAX_STEPS; i++) { // If we take to much time to converge (i>=MAX_STEPS) + // We move the ray: + vec3 ray_position = ray_origin + ray_direction*dist_origin; + // We find the next closest point: + float closest_point = GetDist(ray_position); + // Increase the ray distance + dist_origin += closest_point; + // Check if we went to far or we are too close from a point (we hit a surface) + if(dist_origin>MAX_DIST || closest_point<SURF_DIST) break; + } + return dist_origin; +}
\ No newline at end of file diff --git a/resources/shaders/julia.frag b/resources/shaders/julia.frag new file mode 100644 index 0000000..12d923b --- /dev/null +++ b/resources/shaders/julia.frag @@ -0,0 +1,48 @@ +// ----- Vertex Shader ----- +#version 410 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 410 core + +uniform vec2 resolution; +uniform float time; + +out vec3 color; + +#define ACCURACY 1000 +#define LIMIT 1000 + +vec2 cmult(vec2 z1,vec2 z2){ + return(vec2(z1.x*z2.x-z1.y*z2.y,z1.x*z2.y+z1.y*z2.x)); +} + +vec2 IsDiverging(vec2 coord){ + vec2 z=vec2(coord.x,coord.y); + int i; + for(i=0;i<ACCURACY;i++){ + z=cmult(z,z)+vec2(-0.3,0.5); + if(length(z) > LIMIT) + break; + + } + return(z); +} + + +void main() +{ + vec2 coord=gl_FragCoord.xy/resolution.xy; + coord-=0.5; + coord/=(time/10); + float d=length(IsDiverging(coord)); + color=vec3(LIMIT/(d*2),0,0); +} diff --git a/resources/shaders/main.glsl b/resources/shaders/main.frag index 2888d56..590b849 100644 --- a/resources/shaders/main.glsl +++ b/resources/shaders/main.frag @@ -1,16 +1,3 @@ -// ----- 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; @@ -18,45 +5,24 @@ uniform float time; out vec3 color; - #define MAX_STEPS 100 #define MAX_DIST 100. #define SURF_DIST .01 +#define NORMAL_ACCURACY 0.01 +#include "objects/sphere.frag" float GetDist(vec3 p) { - vec4 s = vec4(0, 1, 6, 1); - - float sphereDist = length(p-s.xyz)-s.w; + float sphereDist = SphereSDF(p,vec3(0, 1, 6),1); float planeDist = p.y; float d = min(sphereDist, planeDist); return d; } -float RayMarch(vec3 ro, vec3 rd) { - float dO=0.; - - for(int i=0; i<MAX_STEPS; i++) { - vec3 p = ro + rd*dO; - float dS = GetDist(p); - dO += dS; - if(dO>MAX_DIST || dS<SURF_DIST) break; - } - - return dO; -} +#include "algorithms/raymarching.frag" +#include "algorithms/normal.frag" + -vec3 GetNormal(vec3 p) { - float d = GetDist(p); - vec2 e = vec2(.01, 0); - - vec3 n = d - vec3( - GetDist(p-e.xyy), - GetDist(p-e.yxy), - GetDist(p-e.yyx)); - - return normalize(n); -} float GetLight(vec3 p) { vec3 lightPos = vec3(0, 5, 6); diff --git a/resources/shaders/objects/sphere.frag b/resources/shaders/objects/sphere.frag new file mode 100644 index 0000000..e69deaa --- /dev/null +++ b/resources/shaders/objects/sphere.frag @@ -0,0 +1,7 @@ +/** + * Compute the Signed Distance Function (SDF) + * of a sphere. + */ +float SphereSDF(vec3 ray_position, vec3 sphere_position, float radius){ + return(length(ray_position - sphere_position)-radius); +}
\ No newline at end of file diff --git a/resources/shaders/objects/sphere.glsl b/resources/shaders/objects/sphere.glsl deleted file mode 100644 index a3d25eb..0000000 --- a/resources/shaders/objects/sphere.glsl +++ /dev/null @@ -1,4 +0,0 @@ - -float Sphere(vec3 ray_position, vec3 sphere_position){ - -}
\ No newline at end of file diff --git a/src/opengl/shaders.cpp b/src/opengl/shaders.cpp index 34d4e8f..41d5a90 100644 --- a/src/opengl/shaders.cpp +++ b/src/opengl/shaders.cpp @@ -1,42 +1,63 @@ #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); - } +/** + * Default Ray Marching Shader + * Any change is forbidden :P + */ +std::string VertexShader="\ +#version 330 core \n\ +layout(location = 0) in vec3 position; \n\ +uniform mat4 projection; \n\ +uniform mat4 model; \n\ +void main(){ \n\ + gl_Position = projection * model * vec4(position,1); \n\ +}"; + + +/** + * Read shaders and handle #include directive + * @param shader_name + * @return string containing shader source code + */ +std::string ReadShader(std::string shader_name){ + std::string shader_path=std::string(SHADERS_RESOURCES) + "/" + shader_name; + std::ifstream shader_file; + shader_file.open(shader_path); + if(!shader_file.is_open()) { + std::cout << "Failed to open: " << shader_path << std::endl; + exit(EXIT_FAILURE); + } + std::string line; + std::stringstream src; + while(getline(shader_file, line)){ + if(line.find("#include")!=std::string::npos){ + int from=line.find("\"")+1; + if(from !=std::string::npos){ + int until=line.size()-from-1; + src << ReadShader(line.substr(from,until)) << std::endl; + continue; + } + } + src << line << std::endl; + } + return(src.str()); +} - 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; - } +GLuint CompileShader(std::string shader_name){ // 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(); + char const * vsrc_c = VertexShader.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(); + std::string fsrc_cpp=ReadShader(shader_name); + char const * fsrc_c = fsrc_cpp.c_str(); glShaderSource(FragmentShaderID, 1, &fsrc_c, NULL); glCompileShader(FragmentShaderID); @@ -54,96 +75,3 @@ GLuint CompileShader(std::string shader_name){ 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/rms.cpp b/src/rms.cpp index b7cf93b..a9bb166 100644 --- a/src/rms.cpp +++ b/src/rms.cpp @@ -8,6 +8,12 @@ void OnWindowResize(GLFWwindow* window, int width, int height){ AppContext->renderer.AjustViewport(width,height); } +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (key == GLFW_KEY_R && action == GLFW_PRESS) + AppContext->renderer.RefreshShader(); +} + int main(int argc, char *argv[]) { GLFWwindow* window; @@ -29,7 +35,7 @@ int main(int argc, char *argv[]) // Init Renderer/OpenGL APP_CONTEXT InitContext={ - Renderer(WIDTH,HEIGHT,"main.glsl"), + Renderer(WIDTH,HEIGHT,"main.frag"), HUD(window) }; AppContext=&InitContext; @@ -37,6 +43,7 @@ int main(int argc, char *argv[]) glfwSetWindowSizeCallback(window, OnWindowResize); + glfwSetKeyCallback(window, key_callback); /* Loop until the user closes the window */ double InitTime = glfwGetTime(); |
