├── .gitignore ├── shots ├── atlantis.png ├── shot_1.c.jpg ├── shot_2.c.png ├── shot_3.c.jpg ├── teapot.png ├── shot_1a.c.jpg ├── shot_1b.c.jpg ├── shot_1c.c.jpg └── shot_2c.c.jpg ├── assets ├── gfx │ └── icon.png ├── textures │ └── tex02.jpg └── shader │ ├── vert │ ├── 1.vert │ └── 2.vert │ ├── frag │ ├── 1.frag │ ├── 2.frag │ ├── 3.frag │ ├── 4.frag │ └── 5.frag │ └── shadertoy │ ├── 4ltSRS_nebula_smoke │ └── Ms2SD1_Seascape ├── training_plan.md ├── .idea ├── vcs.xml ├── .gitignore ├── misc.xml └── icon.svg ├── src ├── helper.h ├── default_shader.h ├── helper.c ├── def_shaders.h ├── default_shaders.h ├── default_shaders_3a.h ├── texture_SOIL.c ├── 1.c ├── 1b.c ├── texture_devil.c ├── texture_stb_image.c ├── 0a.c ├── 0.c ├── 1c.c ├── 2b.c ├── texture_SDL2.c ├── 1a.c ├── 2.c ├── 2a.c ├── 2a1.c ├── 2c.c ├── 2d.c ├── 3.c ├── 3a1.c └── 3a2.c ├── hard_skills.md ├── Makefile └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | myNotes.md 3 | -------------------------------------------------------------------------------- /shots/atlantis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/atlantis.png -------------------------------------------------------------------------------- /shots/shot_1.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_1.c.jpg -------------------------------------------------------------------------------- /shots/shot_2.c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_2.c.png -------------------------------------------------------------------------------- /shots/shot_3.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_3.c.jpg -------------------------------------------------------------------------------- /shots/teapot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/teapot.png -------------------------------------------------------------------------------- /assets/gfx/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/assets/gfx/icon.png -------------------------------------------------------------------------------- /shots/shot_1a.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_1a.c.jpg -------------------------------------------------------------------------------- /shots/shot_1b.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_1b.c.jpg -------------------------------------------------------------------------------- /shots/shot_1c.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_1c.c.jpg -------------------------------------------------------------------------------- /shots/shot_2c.c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/shots/shot_2c.c.jpg -------------------------------------------------------------------------------- /assets/textures/tex02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Acry/SDL2-OpenGL/HEAD/assets/textures/tex02.jpg -------------------------------------------------------------------------------- /training_plan.md: -------------------------------------------------------------------------------- 1 | /home/carsten/NAS_PF/Carsten/IT/docs/Computer Science/Practical/Complex Subjects/Graphics/cg-wiki/opengl/workflow/training_plan.md -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /assets/shader/vert/1.vert: -------------------------------------------------------------------------------- 1 | #version 100 2 | // Unused shader, just for review of a simple passthrough vertex shader 3 | 4 | void main() 5 | { 6 | gl_Position = gl_Vertex; 7 | //contains the position of the current vertex 8 | } 9 | -------------------------------------------------------------------------------- /src/helper.h: -------------------------------------------------------------------------------- 1 | #ifndef _HELPER_H_ 2 | #define _HELPER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include // only to the the definitions in KDev 8 | 9 | extern SDL_Window *Window; 10 | extern SDL_Renderer *Renderer; 11 | 12 | void init (void); 13 | void exit_(void); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /assets/shader/vert/2.vert: -------------------------------------------------------------------------------- 1 | #version 110 2 | // - OpenGL 2.0, GLSL: #version 110 - 2004 3 | // - OpenGL 2.1, GLSL: #version 120 - 2006 4 | 5 | // Clip-space coordinates 6 | varying vec2 fragCoord; 7 | 8 | void main() 9 | { 10 | gl_Position = gl_Vertex; 11 | // Clip-space coordinates. 12 | // A normalized representation of vertex position in the 3D scene 13 | // (before being mapped to actual screen pixels). (gl_FragCoord) 14 | // vertex data is givven in range -1.0 to 1.0. 15 | fragCoord = gl_Position.xy; 16 | } 17 | -------------------------------------------------------------------------------- /src/default_shader.h: -------------------------------------------------------------------------------- 1 | // code from 2.vert as array of chars 2 | static const char vertex_shader[] = 3 | "#version 110\n" 4 | "varying vec2 fragCoord;\n" 5 | "void main(){gl_Position = gl_Vertex;fragCoord = gl_Position.xy;}"; 6 | 7 | // code from 5.frag as array of chars 8 | static const char fragment_shader[] = 9 | "#version 110\n" 10 | "varying vec2 fragCoord;\n" 11 | "uniform float fTime;\n" 12 | "void main(){vec2 uv = vec2( (fragCoord.xy + 1.0) / 2.0 );vec3 col = 0.5 + 0.5 * cos( fTime + uv.xyx + vec3(0,2,4) );gl_FragColor = vec4(col,1.0);}"; 13 | -------------------------------------------------------------------------------- /assets/shader/frag/1.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | #define GL_DARK_ORANGE 0.839, 0.423, 0.274, 1 3 | // fixed Color 4 | 5 | // Unused Shader, just for review 6 | void main() 7 | { 8 | gl_FragColor = vec4(GL_DARK_ORANGE); 9 | // gl_FragColor is deprecated since GLSL 1.3 (OpenGL 3.0) 10 | 11 | // A fragment shader can have multiple outputs gl_FragColor 12 | // at first was replaced by gl_FragData[i] where i was sent to the 13 | // i-th enabled draw buffer and these days fragment shader outputs 14 | // are simply declared as "out" variables, see also: 15 | // https://www.khronos.org/opengl/wiki/Fragment_Shader 16 | } 17 | -------------------------------------------------------------------------------- /src/helper.c: -------------------------------------------------------------------------------- 1 | #include "helper.h" 2 | SDL_Window *Window = NULL; 3 | SDL_Renderer *Renderer = NULL; 4 | SDL_GLContext glcontext = NULL; 5 | 6 | void init(void) 7 | { 8 | 9 | SDL_Init(SDL_INIT_EVERYTHING); 10 | Window = SDL_CreateWindow("", 0, 0, 0, 0, SDL_WINDOW_HIDDEN|SDL_WINDOW_OPENGL); 11 | glcontext = SDL_GL_CreateContext(Window); 12 | //BEGIN ICON 13 | SDL_Surface *icon; 14 | icon=IMG_Load("./assets/gfx/icon.png"); 15 | SDL_SetWindowIcon(Window, icon); 16 | SDL_FreeSurface(icon); 17 | //END ICON 18 | 19 | } 20 | 21 | void exit_(void) 22 | { 23 | 24 | SDL_GL_DeleteContext(glcontext); 25 | SDL_DestroyWindow(Window); 26 | SDL_Quit(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /assets/shader/frag/2.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | 3 | varying vec2 fragCoord; 4 | 5 | // Normalize NDC to range [0,1] 6 | float normalize_C(float x, float x_min, float x_max, float r_min, float r_max ) 7 | { 8 | //see https://github.com/Acry/C-math-normalization/blob/master/main.c 9 | 10 | // In general, you can always get a new variable xr in 11 | // [r_min,r_max] when you provide the Dataset [x_min,x_max] 12 | 13 | // xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 14 | 15 | float xr; 16 | xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 17 | return xr; 18 | } 19 | 20 | void main() 21 | { 22 | float x = normalize_C(fragCoord.x, -1.0, 1.0, 0.0, 1.0); 23 | float y = normalize_C(fragCoord.y, -1.0, 1.0, 0.0, 1.0); 24 | 25 | gl_FragColor = vec4(x,y,1.0-x,1.0); 26 | } 27 | -------------------------------------------------------------------------------- /assets/shader/frag/3.frag: -------------------------------------------------------------------------------- 1 | // linear horizontal gradient 2 | #version 110 3 | varying vec2 fragCoord; 4 | 5 | // Normalize NDC to range [0,1] 6 | float normalize_C(float x, float x_min, float x_max, float r_min, float r_max ) 7 | { 8 | //see https://github.com/Acry/C-math-normalization/blob/master/main.c 9 | 10 | // In general, you can always get a new variable xr in 11 | // [r_min,r_max] when you provide the Dataset [x_min,x_max] 12 | 13 | // xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 14 | 15 | float xr; 16 | xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 17 | return xr; 18 | } 19 | 20 | void main() 21 | { 22 | float x = normalize_C(fragCoord.x, -1.0, 1.0, 0.0, 1.0); 23 | // the red value is the normalized x coordinate 24 | // so the left side is black and the right side is red 25 | gl_FragColor.r=x; 26 | gl_FragColor.g=0.0; 27 | gl_FragColor.b=0.0; 28 | gl_FragColor.a=1.0; 29 | } 30 | -------------------------------------------------------------------------------- /assets/shader/frag/4.frag: -------------------------------------------------------------------------------- 1 | // This shader is unused and equivalent to the 5.frag. 2 | // It is only here for reference. 3 | #version 110 4 | // compare to https://www.shadertoy.com/new 5 | varying vec2 fragCoord; 6 | uniform float fTime; //Current time in float seconds 7 | 8 | float normalize_C(float x, float x_min, float x_max, float r_min, float r_max ) 9 | { 10 | //see https://github.com/Acry/C-math-normalization/blob/master/main.c 11 | 12 | // In general, you can always get a new variable xr in 13 | // [r_min,r_max] when you provide the Dataset [x_min,x_max] 14 | 15 | // xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 16 | 17 | float xr; 18 | xr = (r_max-r_min) * (x - x_min) / (x_max - x_min) + r_min; 19 | return xr; 20 | } 21 | 22 | void main() 23 | { 24 | float x = normalize_C(fragCoord.x, -1.0, 1.0, 0.0, 1.0); 25 | float y = normalize_C(fragCoord.y, -1.0, 1.0, 0.0, 1.0); 26 | 27 | vec2 uv = vec2(x, y); 28 | vec3 col = 0.5 + 0.5*cos(fTime+uv.xyx+vec3(0,2,4)); 29 | 30 | gl_FragColor = vec4(col,1.0); 31 | } 32 | -------------------------------------------------------------------------------- /assets/shader/frag/5.frag: -------------------------------------------------------------------------------- 1 | #version 110 2 | // compare to https://www.shadertoy.com/new 3 | varying vec2 fragCoord; 4 | uniform float fTime; //Current time in float seconds 5 | 6 | void main() 7 | { 8 | // simplified range switch from -1..1 to 0..1 9 | vec2 uv = (fragCoord.xy + 1.0) / 2.0; 10 | // It transforms the fragCoord values from clip space to a normalized space. 11 | // 12 | // In clip space, coordinates are typically in the range [-1.0, 1.0] for both x and y components. 13 | // The line of code takes each component of fragCoord, adds 1 to it, and then divides by 2. 14 | // 15 | // fragCoord.xy + 1.0: This operation shifts the range from [-1.0, 1.0] to [0.0, 2.0]. 16 | // Dividing by 2 (/ 2.0): This scales the range down to [0.0, 1.0]. 17 | // So, after this transformation, uv will contain values in a normalized range [0.0, 1.0] for both x and y 18 | // components. 19 | // 20 | // This type of transformation is common when you want to map clip space coordinates to texture coordinates 21 | // (or any other normalized space). In this normalized space, (0.0, 0.0) corresponds to the bottom-left corner, 22 | // and (1.0, 1.0) corresponds to the top-right corner. 23 | // 24 | // It allows you to easily sample a texture or perform computations in a standardized coordinate space, 25 | // where you're sure that values will always be between 0 and 1 regardless of their position on the screen. 26 | 27 | vec3 col = 0.5 + 0.5 * cos( fTime + uv.xyx + vec3(0,2,4) ); 28 | gl_FragColor = vec4(col,1.0); 29 | } 30 | -------------------------------------------------------------------------------- /assets/shader/shadertoy/4ltSRS_nebula_smoke: -------------------------------------------------------------------------------- 1 | float polygonDistance(vec2 p, float radius, float angleOffset, int sideCount) { 2 | float a = atan(p.x, p.y)+ angleOffset; 3 | float b = 6.28319 / float(sideCount); 4 | return cos(floor(.5 + a / b) * b - a) * length(p) - radius; 5 | } 6 | 7 | // from https://www.shadertoy.com/view/4djSRW 8 | #define HASHSCALE1 443.8975 9 | float hash11(float p) // assumes p in ~0-1 range 10 | { 11 | vec3 p3 = fract(vec3(p) * HASHSCALE1); 12 | p3 += dot(p3, p3.yzx + 19.19); 13 | return fract((p3.x + p3.y) * p3.z); 14 | } 15 | 16 | #define HASHSCALE3 vec3(.1031, .1030, .0973) 17 | vec2 hash21(float p) // assumes p in larger integer range 18 | { 19 | vec3 p3 = fract(vec3(p) * HASHSCALE3); 20 | p3 += dot(p3, p3.yzx + 19.19); 21 | return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); 22 | } 23 | 24 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) 25 | { 26 | vec2 uv = vec2(0.5) - (fragCoord.xy / iResolution.xy); 27 | uv.x *= iResolution.x / iResolution.y; 28 | 29 | float accum = 0.; 30 | for(int i = 0; i < 83; i++) { 31 | float fi = float(i); 32 | float thisYOffset = mod(hash11(fi * 0.017) * (iTime + 19.) * 0.2, 4.0) - 2.0; 33 | vec2 center = (hash21(fi) * 2. - 1.) * vec2(1.1, 1.0) - vec2(0.0, thisYOffset); 34 | float radius = 0.5; 35 | vec2 offset = uv - center; 36 | float twistFactor = (hash11(fi * 0.0347) * 2. - 1.) * 1.9; 37 | float rotation = 0.1 + iTime * 0.2 + sin(iTime * 0.1) * 0.9 + (length(offset) / radius) * twistFactor; 38 | accum += pow(smoothstep(radius, 0.0, polygonDistance(uv - center, 0.1 + hash11(fi * 2.3) * 0.2, rotation, 5) + 0.1), 3.0); 39 | } 40 | 41 | vec3 subColor = vec3(0.4, 0.8, 0.2); //vec3(0.4, 0.2, 0.8); 42 | vec3 addColor = vec3(0.3, 0.2, 0.1);//vec3(0.3, 0.1, 0.2); 43 | 44 | fragColor = vec4(vec3(1.0) - accum * subColor + addColor, 1.0); 45 | } 46 | -------------------------------------------------------------------------------- /hard_skills.md: -------------------------------------------------------------------------------- 1 | # OpenGL - Hard Skills 2 | 3 | Learning OpenGL is a rewarding but challenging experience. Here are some key points to focus on when diving into OpenGL: 4 | 5 | ## Basics of Graphics Programming 6 | 7 | 1. **Coordinate Systems**: Learn how the coordinate systems (object, world, screen, etc.) in OpenGL work. 8 | 2. **Vertices and Fragments**: Understand the fundamental building blocks of any shape in OpenGL. 9 | 10 | ## Shaders 11 | 12 | 1. **GLSL (OpenGL Shading Language)**: You'll need to learn GLSL to write shaders. 13 | 2. **Vertex Shaders**: These manipulate the vertex data of your shape. 14 | 3. **Fragment Shaders**: These handle pixel data and are crucial for texturing, lighting, and more. 15 | 16 | ## Texturing 17 | 18 | 1. **Texture Loading**: How to load 2D, 3D, and more complex textures into OpenGL. 19 | 2. **Texture Units**: How to use multiple textures in shaders. 20 | 21 | ## Buffer Objects 22 | 23 | 1. **VBO (Vertex Buffer Object)**: Stores vertex data. 24 | 2. **VAO (Vertex Array Object)**: Stores the format of vertex data. 25 | 3. **IBO/EBO (Index Buffer Object/Element Buffer Object)**: Stores indices of the vertices to draw. 26 | 27 | ## Transformations 28 | 29 | 1. **Model Matrix**: To transform the vertices of individual objects. 30 | 2. **View Matrix**: To simulate a camera. 31 | 3. **Projection Matrix**: To project the 3D world onto a 2D screen. 32 | 4. **Model-View-Projection Matrix (MVP)**: Often these are combined into a single matrix. 33 | 34 | ## Lighting 35 | 36 | 1. **Phong Lighting Model**: Understand the basics of ambient, diffuse, and specular lighting. 37 | 2. **Normal Mapping**: For more detailed lighting. 38 | 39 | ## Advanced Features 40 | 41 | 1. **Framebuffers**: For offscreen rendering, post-processing effects. 42 | 2. **Geometry and Tessellation Shaders**: For more advanced geometry manipulation. 43 | 3. **Instancing**: For efficient rendering of many objects. 44 | 45 | ## OpenGL Versions 46 | 47 | 1. **Compatibility vs Core Profile**: Learn about the differences and why you'd choose one over the other. 48 | 2. **Fixed-Function Pipeline vs Programmable Pipeline**: OpenGL has evolved a lot; make sure you're learning the modern approach. 49 | 50 | ## Debugging and Profiling 51 | 52 | 1. **OpenGL Errors**: Understand how to debug errors in OpenGL. 53 | 2. **Performance**: Use tools to profile and optimize your OpenGL code. 54 | 55 | ## Libraries and Additional Tools 56 | 57 | 1. **Windowing Libraries**: GLFW, SDL, etc. 58 | 2. **Loading Models**: Libraries like Assimp can load complex models for you. 59 | 3. **Image Loading**: Libraries like stb_image, SOIL, or DevIL can load textures. 60 | 4. **Math Libraries**: Libraries like GLM can help with mathematical operations. 61 | 62 | Remember to always look at examples, and don't hesitate to get your hands dirty with actual coding—it's the best way to learn. 63 | -------------------------------------------------------------------------------- /src/def_shaders.h: -------------------------------------------------------------------------------- 1 | static const char common_shader_header[] = 2 | "#version 100\n" 3 | "precision highp float;"; 4 | 5 | static const char vertex_shader_body[] = 6 | "attribute vec4 iPosition;" 7 | "void main(){gl_Position=iPosition;}"; 8 | 9 | static const char fragment_shader_header[] = 10 | "uniform vec3 iResolution;" 11 | "uniform float iTime;" 12 | "uniform float iChannelTime[4];" 13 | "uniform vec4 iMouse;" 14 | "uniform vec4 iDate;" 15 | "uniform float iSampleRate;" 16 | "uniform vec3 iChannelResolution[4];" 17 | "uniform sampler2D iChannel0;" 18 | "uniform sampler2D iChannel1;" 19 | "uniform sampler2D iChannel2;" 20 | "uniform sampler2D iChannel3;\n"; 21 | 22 | static const char fragment_shader_footer[] = 23 | "\nvoid main(){mainImage(gl_FragColor,gl_FragCoord.xy);}"; 24 | 25 | /* 26 | * Standard ShaderToy Shader 27 | * after 11/07/2017 - Release 0.9.3 28 | * https://www.shadertoy.com/new# 29 | */ 30 | static char *default_fragment_shader_1 = 31 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 32 | "{" 33 | "vec2 uv = fragCoord/iResolution.xy;" 34 | "vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));" 35 | "fragColor = vec4(col,1.0);" 36 | "}"; 37 | 38 | /* 39 | * Standard ShaderToy Shader 40 | * before 11/07/2017 - Release 0.9.3 41 | */ 42 | static char *default_fragment_shader_0 = 43 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 44 | "{" 45 | "vec2 uv=fragCoord.xy/iResolution.xy;" 46 | "fragColor = vec4(uv, 0.5+0.5*sin(iTime), 1.0);" 47 | "}"; 48 | 49 | static char *default_fragment_shader = 50 | "#define iterations 17\n" 51 | "#define formuparam 0.53\n" 52 | "#define volsteps 20\n" 53 | "#define stepsize 0.1\n" 54 | "#define zoom 0.800\n" 55 | "#define tile 0.850\n" 56 | "#define speed 0.010\n" 57 | "#define brightness 0.0015\n" 58 | "#define darkmatter 0.300\n" 59 | "#define distfading 0.730\n" 60 | "#define saturation 0.850\n" 61 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 62 | "{" 63 | "vec2 uv=fragCoord.xy/iResolution.xy-.5;" 64 | "uv.y*=iResolution.y/iResolution.x;" 65 | "vec3 dir=vec3(uv*zoom,1.);" 66 | "float time=iTime*speed+.25;" 67 | "float a1=.5+iMouse.x/iResolution.x*2.;" 68 | "float a2=.8+iMouse.y/iResolution.y*2.;" 69 | "mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));" 70 | "mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));" 71 | "dir.xz*=rot1;" 72 | "dir.xy*=rot2;" 73 | "vec3 from=vec3(1.,.5,0.5);" 74 | "from+=vec3(time*2.,time,-2.);" 75 | "from.xz*=rot1;" 76 | "from.xy*=rot2;" 77 | "float s=0.1,fade=1.;" 78 | "vec3 v=vec3(0.);" 79 | "for (int r=0; r6) fade*=1.-dm;" 91 | "v+=vec3(dm,dm*.5,0.);" 92 | "v+=fade;" 93 | "v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade;" 94 | "fade*=distfading;" 95 | "s+=stepsize;" 96 | "}" 97 | "v=mix(vec3(length(v)),v,saturation);" 98 | "fragColor = vec4(v*.01,1.);" 99 | "}"; 100 | -------------------------------------------------------------------------------- /src/default_shaders.h: -------------------------------------------------------------------------------- 1 | static const char common_shader_header[] = 2 | "#version 100\n" 3 | "precision highp float;"; 4 | 5 | static const char vertex_shader_body[] = 6 | "attribute vec4 iPosition;" 7 | "void main(){gl_Position=iPosition;}"; 8 | 9 | static const char fragment_shader_header[] = 10 | "uniform vec3 iResolution;" 11 | "uniform float iGlobalTime;" 12 | "uniform float iTime;" 13 | "uniform float iChannelTime[4];" 14 | "uniform vec4 iMouse;" 15 | "uniform vec4 iDate;" 16 | "uniform float iSampleRate;" 17 | "uniform vec3 iChannelResolution[4];" 18 | "uniform sampler2D iChannel0;" 19 | "uniform sampler2D iChannel1;" 20 | "uniform sampler2D iChannel2;" 21 | "uniform sampler2D iChannel3;\n"; 22 | 23 | static const char fragment_shader_footer[] = 24 | "\nvoid main(){mainImage(gl_FragColor,gl_FragCoord.xy);}"; 25 | 26 | /* 27 | * Standard ShaderToy Shader 28 | * after 11/07/2017 - Release 0.9.3 29 | * https://www.shadertoy.com/new# 30 | */ 31 | static char *default_fragment_shader_1 = 32 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 33 | "{" 34 | "vec2 uv = fragCoord/iResolution.xy;" 35 | "vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));" 36 | "fragColor = vec4(col,1.0);" 37 | "}"; 38 | 39 | /* 40 | * Standard ShaderToy Shader 41 | * before 11/07/2017 - Release 0.9.3 42 | */ 43 | static char *default_fragment_shader_0 = 44 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 45 | "{" 46 | "vec2 uv=fragCoord.xy/iResolution.xy;" 47 | "fragColor = vec4(uv, 0.5+0.5*sin(iGlobalTime), 1.0);" 48 | "}"; 49 | 50 | static char *default_fragment_shader = 51 | "#define iterations 17\n" 52 | "#define formuparam 0.53\n" 53 | "#define volsteps 20\n" 54 | "#define stepsize 0.1\n" 55 | "#define zoom 0.800\n" 56 | "#define tile 0.850\n" 57 | "#define speed 0.010\n" 58 | "#define brightness 0.0015\n" 59 | "#define darkmatter 0.300\n" 60 | "#define distfading 0.730\n" 61 | "#define saturation 0.850\n" 62 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 63 | "{" 64 | "vec2 uv=fragCoord.xy/iResolution.xy-.5;" 65 | "uv.y*=iResolution.y/iResolution.x;" 66 | "vec3 dir=vec3(uv*zoom,1.);" 67 | "float time=iGlobalTime*speed+.25;" 68 | "float a1=.5+iMouse.x/iResolution.x*2.;" 69 | "float a2=.8+iMouse.y/iResolution.y*2.;" 70 | "mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));" 71 | "mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));" 72 | "dir.xz*=rot1;" 73 | "dir.xy*=rot2;" 74 | "vec3 from=vec3(1.,.5,0.5);" 75 | "from+=vec3(time*2.,time,-2.);" 76 | "from.xz*=rot1;" 77 | "from.xy*=rot2;" 78 | "float s=0.1,fade=1.;" 79 | "vec3 v=vec3(0.);" 80 | "for (int r=0; r6) fade*=1.-dm;" 92 | "v+=vec3(dm,dm*.5,0.);" 93 | "v+=fade;" 94 | "v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade;" 95 | "fade*=distfading;" 96 | "s+=stepsize;" 97 | "}" 98 | "v=mix(vec3(length(v)),v,saturation);" 99 | "fragColor = vec4(v*.01,1.);" 100 | "}"; 101 | -------------------------------------------------------------------------------- /src/default_shaders_3a.h: -------------------------------------------------------------------------------- 1 | static const char common_shader_header[] = 2 | "#version 130\n" 3 | "precision highp float;"; 4 | 5 | static const char vertex_shader_body[] = 6 | "attribute vec4 iPosition;" 7 | "void main(){gl_Position=iPosition;}"; 8 | 9 | static const char fragment_shader_header[] = 10 | "uniform vec3 iResolution;" 11 | "uniform float iGlobalTime;" 12 | "uniform float iTime;" 13 | "uniform float iChannelTime[4];" 14 | "uniform vec4 iMouse;" 15 | "uniform vec4 iDate;" 16 | "uniform float iSampleRate;" 17 | "uniform vec3 iChannelResolution[4];" 18 | "uniform sampler2D iChannel0;" 19 | "uniform sampler2D iChannel1;" 20 | "uniform sampler2D iChannel2;" 21 | "uniform sampler2D iChannel3;\n"; 22 | 23 | static const char fragment_shader_footer[] = 24 | "\nvoid main(){mainImage(gl_FragColor,gl_FragCoord.xy);}"; 25 | 26 | /* 27 | * Standard ShaderToy Shader 28 | * after 11/07/2017 - Release 0.9.3 29 | * https://www.shadertoy.com/new# 30 | */ 31 | static char *default_fragment_shader_1 = 32 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)\n" 33 | "{\n" 34 | "\t//Normalized pixel coordinates (from 0 to 1)\n" 35 | "\tvec2 uv = fragCoord/iResolution.xy;\n" 36 | "\n" 37 | "\t// Time varying pixel color\n" 38 | "\tvec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));\n" 39 | "\n" 40 | "\t// Output to screen\n" 41 | "\tfragColor = vec4(col,1.0);\n" 42 | "}\n"; 43 | 44 | /* 45 | * Standard ShaderToy Shader 46 | * before 11/07/2017 - Release 0.9.3 47 | */ 48 | static char *default_fragment_shader_0 = 49 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 50 | "{" 51 | "vec2 uv=fragCoord.xy/iResolution.xy;" 52 | "fragColor = vec4(uv, 0.5+0.5*sin(iGlobalTime), 1.0);" 53 | "}"; 54 | 55 | static char *default_fragment_shader = 56 | "#define iterations 17\n" 57 | "#define formuparam 0.53\n" 58 | "#define volsteps 20\n" 59 | "#define stepsize 0.1\n" 60 | "#define zoom 0.800\n" 61 | "#define tile 0.850\n" 62 | "#define speed 0.010\n" 63 | "#define brightness 0.0015\n" 64 | "#define darkmatter 0.300\n" 65 | "#define distfading 0.730\n" 66 | "#define saturation 0.850\n" 67 | "void mainImage(out vec4 fragColor, in vec2 fragCoord)" 68 | "{" 69 | "vec2 uv=fragCoord.xy/iResolution.xy-.5;" 70 | "uv.y*=iResolution.y/iResolution.x;" 71 | "vec3 dir=vec3(uv*zoom,1.);" 72 | "float time=iGlobalTime*speed+.25;" 73 | "float a1=.5+iMouse.x/iResolution.x*2.;" 74 | "float a2=.8+iMouse.y/iResolution.y*2.;" 75 | "mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));" 76 | "mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));" 77 | "dir.xz*=rot1;" 78 | "dir.xy*=rot2;" 79 | "vec3 from=vec3(1.,.5,0.5);" 80 | "from+=vec3(time*2.,time,-2.);" 81 | "from.xz*=rot1;" 82 | "from.xy*=rot2;" 83 | "float s=0.1,fade=1.;" 84 | "vec3 v=vec3(0.);" 85 | "for (int r=0; r6) fade*=1.-dm;" 97 | "v+=vec3(dm,dm*.5,0.);" 98 | "v+=fade;" 99 | "v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade;" 100 | "fade*=distfading;" 101 | "s+=stepsize;" 102 | "}" 103 | "v=mix(vec3(length(v)),v,saturation);" 104 | "fragColor = vec4(v*.01,1.);" 105 | "}"; 106 | -------------------------------------------------------------------------------- /src/texture_SOIL.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* DEFINED PROGRESS GOALS 5 | * Render a Texture with SOIL as Image helper. 6 | * https://www.lonesock.net/soil.html 7 | * https://www.khronos.org/opengl/wiki/Image_Libraries 8 | */ 9 | //END DESCRIPTION 10 | 11 | //BEGIN INCLUDES 12 | //system headers 13 | #include 14 | #include 15 | //local headers 16 | #include "helper.h" 17 | //END INCLUDES 18 | 19 | //BEGIN CPP DEFINITIONS 20 | #define GL_WHITE 1,1,1,1 21 | #define WW 400 22 | #define WH 400 23 | //END CPP DEFINITIONS 24 | 25 | //BEGIN DATASTRUCTURES 26 | //END DATASTRUCTURES 27 | 28 | //BEGIN GLOBALS 29 | int ww=WW; 30 | int wh=WH; 31 | 32 | //BEGIN VISIBLES 33 | GLuint texture; 34 | //END VISIBLES 35 | 36 | //END GLOBALS 37 | 38 | //BEGIN FUNCTION PROTOTYPES 39 | void assets_in (void); 40 | //END FUNCTION PROTOTYPES 41 | 42 | //END HEAD 43 | 44 | //BEGIN MAIN FUNCTION 45 | int main(int argc, char *argv[]) 46 | { 47 | 48 | (void)argc; 49 | (void)argv; 50 | 51 | //BEGIN INIT 52 | init(); 53 | assets_in(); 54 | 55 | //BEGIN WINDOW 56 | SDL_SetWindowPosition(Window,0,0); 57 | SDL_SetWindowSize(Window,ww,wh); 58 | SDL_SetWindowTitle(Window, "Draw Texture with SOIL"); 59 | SDL_ShowWindow(Window); 60 | //END WINDOW 61 | 62 | glClearColor(GL_WHITE); 63 | glClear(GL_COLOR_BUFFER_BIT); 64 | 65 | glViewport (0, 0, ww, wh); 66 | SDL_Event event; 67 | int running = 1; 68 | //END INIT 69 | 70 | //BEGIN MAIN LOOP 71 | while(running){ 72 | 73 | //BEGIN EVENT LOOP 74 | while(SDL_PollEvent(&event)){ 75 | if(event.type == SDL_QUIT){ 76 | running =0; 77 | } 78 | if(event.type == SDL_MOUSEMOTION){ 79 | ; 80 | } 81 | if(event.type == SDL_MOUSEBUTTONDOWN){ 82 | if(event.button.button == SDL_BUTTON_RIGHT){ 83 | ; 84 | } 85 | if(event.button.button == SDL_BUTTON_MIDDLE){ 86 | ; 87 | } 88 | if(event.button.button==SDL_BUTTON_LEFT){ 89 | ; 90 | } 91 | } 92 | if(event.type == SDL_KEYDOWN ){ 93 | switch(event.key.keysym.sym ){ 94 | case SDLK_ESCAPE: 95 | running =0; 96 | break; 97 | 98 | case SDLK_r: 99 | case SDLK_BACKSPACE: 100 | break; 101 | 102 | case SDLK_p: 103 | case SDLK_SPACE: 104 | break; 105 | 106 | default: 107 | break; 108 | } 109 | } 110 | } 111 | //END EVENT LOOP 112 | 113 | //BEGIN RENDERING 114 | 115 | glBegin(GL_QUADS); // Draw textured Quad 116 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-.75f, .75f, 0.0f); // Top Left Corner 117 | glTexCoord2f(1.0f, 0.0f); glVertex3f( .75f, .75f, 0.0f); // Top Right Corner 118 | glTexCoord2f(1.0f, 1.0f); glVertex3f( .75f,-.75f, 0.0f); // Bottom Right Corner 119 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-.75f,-.75f, 0.0f); // Bottom Left Corner 120 | glEnd(); 121 | 122 | SDL_GL_SwapWindow(Window); 123 | //END RENDERING 124 | } 125 | //END MAIN LOOP 126 | glDeleteTextures( 1, &texture ); 127 | exit_(); 128 | return EXIT_SUCCESS; 129 | 130 | } 131 | //END MAIN FUNCTION 132 | 133 | //BEGIN FUNCTIONS 134 | void assets_in(void) 135 | { 136 | //BEGIN LOGO 137 | texture = SOIL_load_OGL_texture // load image as OpenGL texture 138 | ( 139 | "../assets/textures/tex02.jpg", 140 | 4, //SOIL_LOAD_RGBA 141 | 0, //SOIL_CREATE_NEW_ID 142 | SOIL_FLAG_POWER_OF_TWO 143 | ); 144 | 145 | glBindTexture(GL_TEXTURE_2D, texture); 146 | //END LOGO 147 | 148 | glEnable(GL_BLEND); 149 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 150 | 151 | glEnable(GL_TEXTURE_2D); 152 | } 153 | //END FUNCTIONS 154 | -------------------------------------------------------------------------------- /src/1.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | /* DEFINED PROGRESS GOALS 4 | * 5 | * Draw a white rectangle 6 | * using glRectf 7 | * 8 | */ 9 | //END DESCRIPTION 10 | 11 | //BEGIN INCLUDES 12 | //system headers 13 | #include 14 | //local headers 15 | #include "helper.h" 16 | //END INCLUDES 17 | 18 | //BEGIN CPP DEFINITIONS 19 | #define WW 550 20 | #define WH (WW/16)*12 21 | #define GL_GREY .5, .5, .5, 1 22 | #define GL_WHITE 1,1,1,1 23 | //END CPP DEFINITIONS 24 | 25 | //BEGIN DATASTRUCTURES 26 | //END DATASTRUCTURES 27 | 28 | //BEGIN GLOBALS 29 | int ww=WW; 30 | int wh=WH; 31 | 32 | //BEGIN VISIBLES 33 | //END VISIBLES 34 | 35 | //END GLOBALS 36 | 37 | //BEGIN FUNCTION PROTOTYPES 38 | //END FUNCTION PROTOTYPES 39 | 40 | //END HEAD 41 | 42 | //BEGIN MAIN FUNCTION 43 | int main(int argc, char *argv[]) 44 | { 45 | 46 | (void)argc; 47 | (void)argv; 48 | 49 | //BEGIN INIT 50 | init(); 51 | 52 | //BEGIN WINDOW 53 | SDL_SetWindowPosition(Window,0,0); 54 | SDL_SetWindowSize(Window,ww,wh); 55 | SDL_SetWindowTitle(Window, "Draw Rect"); 56 | SDL_ShowWindow(Window); 57 | //END WINDOW 58 | 59 | glClearColor(GL_GREY); 60 | glClear(GL_COLOR_BUFFER_BIT); 61 | 62 | glViewport (0, 0, ww, wh); 63 | 64 | //Set Draw color to white 65 | glColor4f(GL_WHITE); 66 | SDL_Event event; 67 | int running = 1; 68 | //END INIT 69 | 70 | //BEGIN MAIN LOOP 71 | while(running){ 72 | 73 | //BEGIN EVENT LOOP 74 | while(SDL_PollEvent(&event)){ 75 | if(event.type == SDL_QUIT){ 76 | running =0; 77 | } 78 | if(event.type == SDL_MOUSEMOTION){ 79 | ; 80 | } 81 | if(event.type == SDL_MOUSEBUTTONDOWN){ 82 | if(event.button.button == SDL_BUTTON_RIGHT){ 83 | ; 84 | } 85 | if(event.button.button == SDL_BUTTON_MIDDLE){ 86 | ; 87 | } 88 | if(event.button.button==SDL_BUTTON_LEFT){ 89 | ; 90 | } 91 | } 92 | if(event.type == SDL_KEYDOWN ){ 93 | switch(event.key.keysym.sym ){ 94 | case SDLK_ESCAPE: 95 | running =0; 96 | break; 97 | 98 | case SDLK_r: 99 | case SDLK_BACKSPACE: 100 | break; 101 | 102 | case SDLK_p: 103 | case SDLK_SPACE: 104 | break; 105 | 106 | default: 107 | break; 108 | } 109 | } 110 | } 111 | //END EVENT LOOP 112 | //BEGIN RENDERING 113 | //Draw a rect 114 | //If you worry about the strange floats, check 2a.c 115 | glRectf(-.75, .75, .75, -.75); 116 | 117 | // glRect(x1, y1, x2, y2 ) 118 | // Top Left, Bottom Right 119 | // is exactly equivalent to the following sequence: 120 | 121 | // glBegin(GL_QUADS); // Draw A Quad 122 | // glVertex3f(-.75f, .75f, 0.0f); // Top Left 123 | // glVertex3f( .75f, .75f, 0.0f); // Top Right 124 | // glVertex3f( .75f,-.75f, 0.0f); // Bottom Right 125 | // glVertex3f(-.75f,-.75f, 0.0f); // Bottom Left 126 | // glEnd(); 127 | 128 | /* 129 | * That is what the man-page says: 130 | * https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRect.xml 131 | * 132 | * BUT that isn't true! 133 | * 134 | * You can't rotate a rect like that properly. 135 | * And IMO the person who wrote that particular sentence into the 136 | * documentation should be fired and banned from the job field. 137 | * That stupid error has been there for at least ten years. 138 | * 139 | * And if you check: 140 | * https://www.khronos.org/members/list 141 | * That is the who is who in the computing industry, even Microsoft has 142 | * been there for a while before they started to provide DirectX what now 143 | * bounces back. 144 | * EOR - End of rant 145 | * 146 | */ 147 | 148 | SDL_GL_SwapWindow(Window); 149 | //END RENDERING 150 | } 151 | //END MAIN LOOP 152 | 153 | 154 | exit_(); 155 | return EXIT_SUCCESS; 156 | 157 | } 158 | //END MAIN FUNCTION 159 | 160 | //BEGIN FUNCTIONS 161 | //END FUNCTIONS 162 | -------------------------------------------------------------------------------- /src/1b.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | /* DEFINED PROGRESS GOALS 4 | * Draw 4 rectangles and rotate the screen 5 | * (viewport) with glRotate 6 | * 7 | */ 8 | 9 | //END DESCRIPTION 10 | 11 | //BEGIN INCLUDES 12 | //system headers 13 | #include 14 | //local headers 15 | #include "helper.h" 16 | //END INCLUDES 17 | 18 | //BEGIN CPP DEFINITIONS 19 | #define WW 550 20 | #define WH (WW/16)*12 21 | #define GL_GREY .5, .5, .5, 1 22 | #define GL_WHITE 1,1,1,1 23 | //END CPP DEFINITIONS 24 | 25 | //BEGIN DATASTRUCTURES 26 | //END DATASTRUCTURES 27 | 28 | //BEGIN GLOBALS 29 | int ww=WW; 30 | int wh=WH; 31 | 32 | //BEGIN VISIBLES 33 | //END VISIBLES 34 | 35 | //END GLOBALS 36 | 37 | //BEGIN FUNCTION PROTOTYPES 38 | double norm_RGB (double); 39 | double rescale_RGB (double); 40 | 41 | double norm_NDC_x (double); 42 | double norm_NDC_y (double); 43 | double rescale_NDC_x (double); 44 | double rescale_NDC_y (double); 45 | //END FUNCTION PROTOTYPES 46 | 47 | //END HEAD 48 | 49 | //BEGIN MAIN FUNCTION 50 | int main(int argc, char *argv[]) 51 | { 52 | 53 | (void)argc; 54 | (void)argv; 55 | 56 | //BEGIN INIT 57 | init(); 58 | 59 | //BEGIN WINDOW 60 | SDL_SetWindowPosition(Window,0,0); 61 | SDL_SetWindowSize(Window,ww,wh); 62 | SDL_SetWindowTitle(Window, "Rotate 4 Rects"); 63 | SDL_ShowWindow(Window); 64 | //END WINDOW 65 | 66 | glClearColor(GL_GREY); 67 | glClear(GL_COLOR_BUFFER_BIT); 68 | 69 | glViewport (0, 0, ww, wh); 70 | //BEGING INIT RECTS 71 | double rx1[4]; 72 | double rx2[4]; 73 | double ry1[4]; 74 | double ry2[4]; 75 | 76 | //rect top left 77 | rx1[0]=norm_NDC_x(10); 78 | ry1[0]=norm_NDC_y(wh-10); 79 | rx2[0]=norm_NDC_x(ww/2-5); 80 | ry2[0]=norm_NDC_y(wh/2+5); 81 | 82 | //rect bot left 83 | rx1[1]=norm_NDC_x(10); 84 | ry1[1]=norm_NDC_y(wh/2-5); 85 | rx2[1]=norm_NDC_x(ww/2-5); 86 | ry2[1]=norm_NDC_y(10); 87 | 88 | //rect top right 89 | rx1[2]=norm_NDC_x(ww/2+5); 90 | ry1[2]=norm_NDC_y(wh-10); 91 | rx2[2]=norm_NDC_x(ww-10); 92 | ry2[2]=norm_NDC_y(wh/2+5); 93 | 94 | //rect bot right 95 | rx1[3]=norm_NDC_x(ww/2+5); 96 | ry1[3]=norm_NDC_y(wh/2-5); 97 | rx2[3]=norm_NDC_x(ww-10); 98 | ry2[3]=norm_NDC_y(10); 99 | //END INIT RECTS 100 | 101 | SDL_Event event; 102 | int running = 1; 103 | //END INIT 104 | double a=.1; 105 | //BEGIN MAIN LOOP 106 | while(running){ 107 | 108 | //BEGIN EVENT LOOP 109 | while(SDL_PollEvent(&event)){ 110 | if(event.type == SDL_QUIT){ 111 | running =0; 112 | } 113 | if(event.type == SDL_MOUSEMOTION){ 114 | ; 115 | } 116 | if(event.type == SDL_MOUSEBUTTONDOWN){ 117 | if(event.button.button == SDL_BUTTON_RIGHT){ 118 | ; 119 | } 120 | if(event.button.button == SDL_BUTTON_MIDDLE){ 121 | ; 122 | } 123 | if(event.button.button==SDL_BUTTON_LEFT){ 124 | ; 125 | } 126 | } 127 | if(event.type == SDL_KEYDOWN ){ 128 | switch(event.key.keysym.sym ){ 129 | case SDLK_ESCAPE: 130 | running =0; 131 | break; 132 | 133 | case SDLK_r: 134 | case SDLK_BACKSPACE: 135 | break; 136 | 137 | case SDLK_p: 138 | case SDLK_SPACE: 139 | break; 140 | 141 | default: 142 | break; 143 | } 144 | } 145 | } 146 | //END EVENT LOOP 147 | //BEGIN RENDERING 148 | glClear(GL_COLOR_BUFFER_BIT); 149 | 150 | glRotated(a, 0.0f, 0.0f, 1); 151 | // https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml 152 | for (int i=0; i<4; i++){ 153 | glRectd(rx1[i], ry1[i], rx2[i], ry2[i]); 154 | } 155 | SDL_GL_SwapWindow(Window); 156 | //END RENDERING 157 | } 158 | //END MAIN LOOP 159 | 160 | 161 | exit_(); 162 | return EXIT_SUCCESS; 163 | 164 | } 165 | //END MAIN FUNCTION 166 | 167 | //BEGIN FUNCTIONS 168 | double norm_RGB(double x) 169 | { 170 | return (x - 0) / (255 - 0); 171 | } 172 | double rescale_RGB(double xr) 173 | { 174 | return xr * 255; 175 | } 176 | double norm_NDC_x(double x) 177 | { 178 | return (2 * (x - 0) / (ww - 0))-1; 179 | } 180 | double norm_NDC_y(double y) 181 | { 182 | return (2 * (y - 0) / (wh - 0))-1; 183 | } 184 | 185 | double rescale_NDC_x(double xr) 186 | { 187 | return ww * (xr - -1) / 2; 188 | } 189 | double rescale_NDC_y(double xr) 190 | { 191 | return wh * (xr - -1) / 2; 192 | } 193 | //END FUNCTIONS 194 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | .SUFFIXES: 3 | .SUFFIXES: .c .o 4 | 5 | CFLAGS = -Wall -Wextra -mtune=native -no-pie `sdl2-config --cflags` 6 | WARN_OFF = -Wno-implicit-function-declaration 7 | CFLAGS1 = $(CFLAGS) $(WARN_OFF) 8 | 9 | LDFLAGS = `sdl2-config --libs` -lm -lGL 10 | LDFLAGS1 = $(LDFLAGS) -lSDL2_image 11 | LDFLAGS3 = $(LDFLAGS1) -lGLEW 12 | LDFLAGS4 = $(LDFLAGS) -lGLU 13 | LDFLAGS5 = $(LDFLAGS1) $(LDFLAGS3) 14 | 15 | # Define the source directory 16 | SOURCE_DIR := src/ 17 | 18 | # Define the build directory 19 | BUILD_DIR := build/ 20 | 21 | # Create the build directory if it doesn't exist 22 | $(shell mkdir -p $(BUILD_DIR)) 23 | 24 | TARGETS = 0 \ 25 | 0a \ 26 | 1 \ 27 | 1a \ 28 | 1b \ 29 | 1c \ 30 | 2 \ 31 | 2a \ 32 | 2a1 \ 33 | 2b \ 34 | 2c \ 35 | 2d \ 36 | 3 \ 37 | 3a1 \ 38 | 3a2 \ 39 | texture_SOIL \ 40 | texture_SDL2 \ 41 | texture_devil \ 42 | texture_stb_image 43 | 44 | .PHONY: all 45 | all: $(TARGETS) 46 | 47 | # get an OpenGL Window 48 | 0: $(SOURCE_DIR)helper.c $(SOURCE_DIR)0.c 49 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 50 | 51 | # get used OpenGL Version 52 | 0a: $(SOURCE_DIR)helper.c $(SOURCE_DIR)0a.c 53 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 54 | 55 | # draw a white rectangle 56 | 1: $(SOURCE_DIR)helper.c $(SOURCE_DIR)1.c 57 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 58 | 59 | # draw 4 rectangles 60 | 1a: $(SOURCE_DIR)helper.c $(SOURCE_DIR)1a.c 61 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 62 | 63 | # draw 4 rectangles and rotate the screen 64 | 1b: $(SOURCE_DIR)helper.c $(SOURCE_DIR)1b.c 65 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 66 | 67 | # draw 4 rectangles and rotate them individually around their center. 68 | 1c: $(SOURCE_DIR)helper.c $(SOURCE_DIR)1c.c 69 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 70 | 71 | # use shader-program, one custom vertex-shader, one custom fragment-shader 72 | 2: $(SOURCE_DIR)2.c 73 | $(CC) $(CFLAGS1) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 74 | 75 | # animate gradient using attribute and uniform 76 | 2a: $(SOURCE_DIR)2a.c 77 | $(CC) $(CFLAGS1) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 78 | 79 | # animate gradient using attribute and uniform 80 | 2a1: $(SOURCE_DIR)2a1.c 81 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS3) 82 | 83 | # embed a default shader 84 | 2b: $(SOURCE_DIR)2b.c 85 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS3) 86 | 87 | # embed multiple shader 88 | 2c: $(SOURCE_DIR)2c.c 89 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS3) 90 | 91 | # make mouse work 92 | 2d: $(SOURCE_DIR)2d.c 93 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS3) 94 | 95 | # load shadertoy fragment shader optional 96 | 3: $(SOURCE_DIR)3.c 97 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS5) 98 | 99 | # getting Textures work 100 | 3a: $(SOURCE_DIR)3a.c 101 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS5) 102 | 103 | # make new shader in preferred Editor 104 | 3a1: $(SOURCE_DIR)3a1.c 105 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS5) 106 | 107 | # make new shader in preferred Editor, check file change via inotify an epoll 108 | 3a2: $(SOURCE_DIR)3a2.c 109 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS5) 110 | 111 | texture_SOIL: $(SOURCE_DIR)helper.c $(SOURCE_DIR)texture_SOIL.c 112 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) -lSOIL 113 | 114 | texture_SDL2: $(SOURCE_DIR)helper.c $(SOURCE_DIR)texture_SDL2.c 115 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 116 | 117 | texture_devil: $(SOURCE_DIR)helper.c $(SOURCE_DIR)texture_devil.c 118 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) -lIL -lILU 119 | 120 | texture_stb_image: $(SOURCE_DIR)helper.c $(SOURCE_DIR)texture_stb_image.c 121 | $(CC) $(CFLAGS) -o $(BUILD_DIR)$@ $+ $(LDFLAGS1) 122 | 123 | .PHONY: clean 124 | clean: 125 | @rm -rf $(BUILD_DIR) 2>/dev/null || true 126 | 127 | # Makefile Hilfe: 128 | # $< first dependency 129 | # $@ name of target 130 | # $+ list of all dependencies 131 | # $^ list of all dependencies, no duplicates 132 | 133 | # build after save: 134 | # while inotifywait -e close_write ./sourcefile.c; do date +%X; make > /dev/null; done -------------------------------------------------------------------------------- /src/texture_devil.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* DEFINED PROGRESS GOALS 5 | * Render a Texture with DevIL as Image helper. 6 | * https://openil.sourceforge.net 7 | * https://www.khronos.org/opengl/wiki/Image_Libraries 8 | */ 9 | //END DESCRIPTION 10 | 11 | //BEGIN INCLUDES 12 | //system headers 13 | #include 14 | #include 15 | //local headers 16 | #include "helper.h" 17 | //END INCLUDES 18 | 19 | //BEGIN CPP DEFINITIONS 20 | #define GL_WHITE 1,1,1,1 21 | #define WW 400 22 | #define WH 400 23 | //END CPP DEFINITIONS 24 | 25 | //BEGIN DATASTRUCTURES 26 | //END DATASTRUCTURES 27 | 28 | //BEGIN GLOBALS 29 | int ww=WW; 30 | int wh=WH; 31 | 32 | //BEGIN VISIBLES 33 | GLuint textureId; 34 | //END VISIBLES 35 | 36 | //END GLOBALS 37 | 38 | //BEGIN FUNCTION PROTOTYPES 39 | void assets_in (void); 40 | //END FUNCTION PROTOTYPES 41 | 42 | //END HEAD 43 | 44 | //BEGIN MAIN FUNCTION 45 | int main(int argc, char *argv[]) 46 | { 47 | 48 | (void)argc; 49 | (void)argv; 50 | 51 | //BEGIN INIT 52 | init(); 53 | assets_in(); 54 | 55 | //BEGIN WINDOW 56 | SDL_SetWindowPosition(Window,0,0); 57 | SDL_SetWindowSize(Window,ww,wh); 58 | SDL_SetWindowTitle(Window, "Draw Texture with DevIL"); 59 | SDL_ShowWindow(Window); 60 | //END WINDOW 61 | 62 | glClearColor(GL_WHITE); 63 | glClear(GL_COLOR_BUFFER_BIT); 64 | 65 | glViewport (0, 0, ww, wh); 66 | SDL_Event event; 67 | int running = 1; 68 | //END INIT 69 | 70 | //BEGIN MAIN LOOP 71 | while(running){ 72 | 73 | //BEGIN EVENT LOOP 74 | while(SDL_PollEvent(&event)){ 75 | if(event.type == SDL_QUIT){ 76 | running =0; 77 | } 78 | if(event.type == SDL_MOUSEMOTION){ 79 | ; 80 | } 81 | if(event.type == SDL_MOUSEBUTTONDOWN){ 82 | if(event.button.button == SDL_BUTTON_RIGHT){ 83 | ; 84 | } 85 | if(event.button.button == SDL_BUTTON_MIDDLE){ 86 | ; 87 | } 88 | if(event.button.button==SDL_BUTTON_LEFT){ 89 | ; 90 | } 91 | } 92 | if(event.type == SDL_KEYDOWN ){ 93 | switch(event.key.keysym.sym ){ 94 | case SDLK_ESCAPE: 95 | running =0; 96 | break; 97 | 98 | case SDLK_r: 99 | case SDLK_BACKSPACE: 100 | break; 101 | 102 | case SDLK_p: 103 | case SDLK_SPACE: 104 | break; 105 | 106 | default: 107 | break; 108 | } 109 | } 110 | } 111 | //END EVENT LOOP 112 | 113 | //BEGIN RENDERING 114 | 115 | glBegin(GL_QUADS); // Draw textured Quad 116 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-.75f, .75f, 0.0f); // Top Left Corner 117 | glTexCoord2f(1.0f, 0.0f); glVertex3f( .75f, .75f, 0.0f); // Top Right Corner 118 | glTexCoord2f(1.0f, 1.0f); glVertex3f( .75f,-.75f, 0.0f); // Bottom Right Corner 119 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-.75f,-.75f, 0.0f); // Bottom Left Corner 120 | glEnd(); 121 | 122 | SDL_GL_SwapWindow(Window); 123 | //END RENDERING 124 | } 125 | //END MAIN LOOP 126 | glDeleteTextures( 1, &textureId ); 127 | exit_(); 128 | return EXIT_SUCCESS; 129 | 130 | } 131 | //END MAIN FUNCTION 132 | 133 | //BEGIN FUNCTIONS 134 | void assets_in(void) 135 | { 136 | // Initialize DevIL 137 | ilInit(); 138 | iluInit(); 139 | 140 | // Load an image using DevIL 141 | ILuint imageID; 142 | ilGenImages(1, &imageID); 143 | ilBindImage(imageID); 144 | 145 | ilLoadImage("../assets/textures/tex02.jpg"); 146 | ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE); 147 | 148 | // Get image dimensions 149 | int width = ilGetInteger(IL_IMAGE_WIDTH); 150 | int height = ilGetInteger(IL_IMAGE_HEIGHT); 151 | 152 | glGenTextures(1, &textureId); 153 | glBindTexture(GL_TEXTURE_2D, textureId); 154 | 155 | glTexImage2D( 156 | GL_TEXTURE_2D, 0, GL_RGBA, 157 | ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 158 | 0, GL_RGBA, GL_UNSIGNED_BYTE, ilGetData() 159 | ); 160 | 161 | // Set texture parameters (you can customize these) 162 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 164 | 165 | ilDeleteImages(1, &imageID); 166 | 167 | glEnable(GL_BLEND); 168 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 169 | 170 | glEnable(GL_TEXTURE_2D); 171 | } 172 | //END FUNCTIONS 173 | -------------------------------------------------------------------------------- /src/texture_stb_image.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* DEFINED PROGRESS GOALS 5 | * Render a Texture with stb_image as Image helper. 6 | * https://github.com/nothings/stb/blob/master/stb_image.h 7 | * https://www.khronos.org/opengl/wiki/Image_Libraries 8 | */ 9 | //END DESCRIPTION 10 | 11 | //BEGIN INCLUDES 12 | //system headers 13 | 14 | //local headers 15 | #define STB_IMAGE_IMPLEMENTATION 16 | #include "stb_image.h" 17 | #include "helper.h" 18 | //END INCLUDES 19 | 20 | //BEGIN CPP DEFINITIONS 21 | #define GL_WHITE 1,1,1,1 22 | #define WW 400 23 | #define WH 400 24 | //END CPP DEFINITIONS 25 | 26 | //BEGIN DATASTRUCTURES 27 | //END DATASTRUCTURES 28 | 29 | //BEGIN GLOBALS 30 | int ww=WW; 31 | int wh=WH; 32 | 33 | //BEGIN VISIBLES 34 | GLuint textureId; 35 | //END VISIBLES 36 | 37 | //END GLOBALS 38 | 39 | //BEGIN FUNCTION PROTOTYPES 40 | void assets_in (void); 41 | //END FUNCTION PROTOTYPES 42 | 43 | //END HEAD 44 | 45 | //BEGIN MAIN FUNCTION 46 | int main(int argc, char *argv[]) 47 | { 48 | 49 | (void)argc; 50 | (void)argv; 51 | 52 | //BEGIN INIT 53 | init(); 54 | assets_in(); 55 | 56 | //BEGIN WINDOW 57 | SDL_SetWindowPosition(Window,0,0); 58 | SDL_SetWindowSize(Window,ww,wh); 59 | SDL_SetWindowTitle(Window, "Draw Texture with stb_image"); 60 | SDL_ShowWindow(Window); 61 | //END WINDOW 62 | 63 | glClearColor(GL_WHITE); 64 | glClear(GL_COLOR_BUFFER_BIT); 65 | 66 | glViewport (0, 0, ww, wh); 67 | SDL_Event event; 68 | int running = 1; 69 | //END INIT 70 | 71 | //BEGIN MAIN LOOP 72 | while(running){ 73 | 74 | //BEGIN EVENT LOOP 75 | while(SDL_PollEvent(&event)){ 76 | if(event.type == SDL_QUIT){ 77 | running =0; 78 | } 79 | if(event.type == SDL_MOUSEMOTION){ 80 | ; 81 | } 82 | if(event.type == SDL_MOUSEBUTTONDOWN){ 83 | if(event.button.button == SDL_BUTTON_RIGHT){ 84 | ; 85 | } 86 | if(event.button.button == SDL_BUTTON_MIDDLE){ 87 | ; 88 | } 89 | if(event.button.button==SDL_BUTTON_LEFT){ 90 | ; 91 | } 92 | } 93 | if(event.type == SDL_KEYDOWN ){ 94 | switch(event.key.keysym.sym ){ 95 | case SDLK_ESCAPE: 96 | running =0; 97 | break; 98 | 99 | case SDLK_r: 100 | case SDLK_BACKSPACE: 101 | break; 102 | 103 | case SDLK_p: 104 | case SDLK_SPACE: 105 | break; 106 | 107 | default: 108 | break; 109 | } 110 | } 111 | } 112 | //END EVENT LOOP 113 | 114 | //BEGIN RENDERING 115 | 116 | glBegin(GL_QUADS); // Draw textured Quad 117 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-.75f, .75f, 0.0f); // Top Left Corner 118 | glTexCoord2f(1.0f, 0.0f); glVertex3f( .75f, .75f, 0.0f); // Top Right Corner 119 | glTexCoord2f(1.0f, 1.0f); glVertex3f( .75f,-.75f, 0.0f); // Bottom Right Corner 120 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-.75f,-.75f, 0.0f); // Bottom Left Corner 121 | glEnd(); 122 | 123 | SDL_GL_SwapWindow(Window); 124 | //END RENDERING 125 | } 126 | //END MAIN LOOP 127 | glDeleteTextures( 1, &textureId ); 128 | exit_(); 129 | return EXIT_SUCCESS; 130 | 131 | } 132 | //END MAIN FUNCTION 133 | 134 | //BEGIN FUNCTIONS 135 | void assets_in(void) 136 | { 137 | int imageWidth, imageHeight, imageChannels; 138 | unsigned char* image = stbi_load("../assets/textures/tex02.jpg", &imageWidth, &imageHeight, &imageChannels, STBI_rgb_alpha); 139 | if (image) 140 | { 141 | printf("loaded texture image.\n"); 142 | } 143 | else 144 | { 145 | printf("Failed to load texture image.\n"); 146 | } 147 | 148 | SDL_Log("imageWidth: %d", imageWidth); 149 | SDL_Log("imageHeight: %d", imageHeight); 150 | 151 | glGenTextures(1, &textureId); 152 | glBindTexture(GL_TEXTURE_2D, textureId); 153 | 154 | glTexImage2D( 155 | GL_TEXTURE_2D, 156 | 0, 157 | GL_RGBA, 158 | imageWidth, 159 | imageHeight, 160 | 0, 161 | GL_RGBA, 162 | GL_UNSIGNED_BYTE, 163 | image 164 | ); 165 | 166 | // Set texture parameters (you can customize these) 167 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 168 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 169 | 170 | stbi_image_free(image); 171 | 172 | glEnable(GL_BLEND); 173 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 174 | 175 | glEnable(GL_TEXTURE_2D); 176 | } 177 | //END FUNCTIONS 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenGL - Playground 2 | 3 | This is a series of OpenGL examples. 4 | 5 | Some OpenGL 2.1 and 3.3 examples, using SDL2 and GLEW as function wrangler. 6 | And a bit GLSL for C-Coders. 7 | 8 | ___ 9 | 10 | ARCHIVED: 11 | 12 | This Repository is quite old and I will not update most of the code anymore. 13 | If I find bugs I will fix them, but I will not add new features. 14 | 15 | I corrected some misspellings und miss understandings I had back in the days and added some comments. 16 | 17 | The 3rd part will be refactored and corrected, but then this repository will be archived. 18 | 19 | The new work is not available publicly, since nobody really contributes to any open source code where he does not see 20 | any benefit, beside learning. 21 | 22 | There is a lot documentation in the code, but it is not a tutorial. 23 | To separate code and documentation the CG-Wiki was created. And in the continued project it is used as a submodule. 24 | 25 | ___ 26 | 27 | ## Legacy OpenGL 28 | 29 | [See Chapter 3 of the graphicsbook for a good introduction to OpenGL 1.1](https://math.hws.edu/graphicsbook/c3/index.html) 30 | 31 | `Immediate mode` is nice because the entry barrier is extremely low. 32 | 33 | - `0` - Init a simple OpenGL Window, on Linux it defaults to OpenGL 2.1 34 | - `1` - Draw rectangle 35 | 36 | ![Screenshot](shots/shot_1.c.jpg) 37 | 38 | - `1a` - Draw rectangles 39 | 40 | ![Screenshot](shots/shot_1a.c.jpg) 41 | 42 | - `1b` - Rotate rectangles uniformly 43 | 44 | ![Screenshot](shots/shot_1b.c.jpg) 45 | 46 | - `1c` - Rotate rectangles individually 47 | 48 | ![Screenshot](shots/shot_1c.c.jpg) 49 | 50 | - `1d` - SGI Teapot Demo ported to SDL2 (**TBD**) - perhaps 51 | 52 | 53 | ![Screenshot](shots/teapot.png) 54 | 55 | - `1e` - SGI Atlantis Demo ported to SDL2 (**TBD**) - perhaps 56 | 57 | 58 | ![Screenshot](shots/atlantis.png) 59 | 60 | ## Modern OpenGL 61 | 62 | Retained-mode using `VAO` / `VBO` 63 | 64 | It is much harder to do anything at all with modern OpenGL, but it is in fact easier once you are over the initial 65 | hurdle (and, much faster). 66 | 67 | ## GLSL - Shaders 68 | 69 | 2 - Shader-Setup 70 | 71 | ![Screenshot](shots/shot_2.c.png) 72 | 73 | ![Screenshot](shots/shot_2c.c.jpg) 74 | 75 | `2d.c` - uniform mouse and switch multiple shaders on middle mouse button 76 | 77 | ## Shadertoy - Fragment Shaders 78 | 79 | `3` - Load a [shadertoy](https://www.shadertoy.com/) shader from command line and switch between shaders with middle mouse button. 80 | 81 | ![Screenshot](shots/shot_3.c.jpg) 82 | 83 | Try: 84 | 85 | - `./3 ../assets/shader/shadertoy/4ltSRS_nebula_smoke` 86 | - `./3 ../assets/shader/shadertoy/Ms2SD1_Seascape` 87 | 88 | `3a1` - press `n` to create new shader, will open in Editor 89 | if file is changed and saved. press `c` to compile. 90 | 91 | `3a2` - should track if file in Editor was written and **auto-compile**. 92 | 93 | - When working with shaders use left mouse button and mouse motion to change view. 94 | - When working with multiple shaders use middle mouse button to switch shaders. 95 | 96 | The work on Shader Toy Fragment Shaders has been split out to an extra project: 97 | [Shade it!](https://github.com/Acry/Shade-it-) 98 | 99 | ## Image Texture Libraries 100 | 101 | Some examples to load image textures with selected libraries: 102 | 103 | - texture_devil 104 | - texture_SDL2, (flipping SDL2 surfaces manually) 105 | - texture_SOIL 106 | - texture_stb_image 107 | 108 | ## See also 109 | 110 | - [Training Plan](training_plan.md) 111 | - [OpenGL - Hard Skills](hard_skills.md) 112 | 113 | ## Dependencies 114 | 115 | `pacman -S soil devil sdl2 sdl2_image glew glu` 116 | 117 | ## Useful links 118 | 119 | [SDL2](https://www.libsdl.org/) | [SDL-Discourse](https://discourse.libsdl.org) | [SDL2-Example Code](https://gist.github.com/Acry/baa861b8e370c6eddbb18519c487d9d8) | [N. Nopper-Code](https://github.com/McNopper/OpenGL) | [McKesson-Book](https://paroj.github.io/gltut/) | [Íñigo Quílez](http://www.iquilezles.org/prods/index.htm) | [MESA Demos](https://archive.mesa3d.org/demos/) | [BSVino/docs.gl: OpenGL Reference Documentation](https://github.com/BSVino/docs.gl) | [graphicsbook: sources for a free graphics textbook hosted at https://math.hws.edu/graphicsbook](https://github.com/davidjeck/graphicsbook/) | [opengl46-quick-reference-card.pdf](https://www.khronos.org/assets/uploads/developers/presentations/opengl46-quick-reference-card.pdf) 120 | -------------------------------------------------------------------------------- /src/0a.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* As mentioned earlier, there is a lot of confusion around OpenGL. 5 | * I try to sort things out as good as I can. 6 | * 7 | * VERSIONS 8 | * Let's see which Version SDL2 will provide us 9 | * on a Linux based OS with calling: 10 | * 11 | * SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 12 | * SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 13 | * 14 | * after initializing SDL. 15 | * 16 | * SDL2 gives me OpenGL 2.1 without using a function loader. 17 | * That particular Version is from 2006. 18 | * 19 | * https://www.khronos.org/opengl/wiki/History_of_OpenGL#OpenGL_2.1_.282006.29 20 | * 21 | * Core features: 22 | * Addition Promoted from 23 | * Pixel buffer objects ARB_pixel_buffer_object 24 | * sRGB textures EXT_texture_sRGB 25 | * https://www.khronos.org/registry/OpenGL/specs/gl/glspec21.pdf 26 | * 27 | * Shading language 1.20: 28 | * Non-square matrices in GLSL. 29 | * https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.1.20.pdf 30 | * 31 | * This calls do query the Hardware. 32 | * const GLubyte* glGetString(GLenum name); 33 | * GL_VERSION 34 | * GL_SHADING_LANGUAGE_VERSION 35 | * GL_EXTENSIONS 36 | * 37 | * HINT: 38 | * If you try to find a tutorial online or a book, know which version it is 39 | * about, beside the toolchain and language the author uses. 40 | * 41 | * The release year of the book is a pretty good pointer which version 42 | * it is most likely about. 43 | * 44 | * See: 45 | * https://www.khronos.org/opengl/wiki/History_of_OpenGL 46 | * 47 | * FEATURES 48 | * Haven't used any so far. 49 | * 50 | * HELPER LIBS 51 | * Using SDL2 at the moment. 52 | * 53 | * https://www.khronos.org/opengl/wiki/Related_toolkits_and_APIs 54 | * 55 | * VARIABLE TYPE NAMES 56 | * typedef unsigned char GLubyte; 1-byte unsigned 57 | * 58 | */ 59 | 60 | /* DEFINED PROGRESS GOALS 61 | * 62 | * Get provided OpenGL Version. 63 | * 64 | */ 65 | //END DESCRIPTION 66 | 67 | //BEGIN INCLUDES 68 | //system headers 69 | #include 70 | //local headers 71 | #include "helper.h" 72 | //END INCLUDES 73 | 74 | //BEGIN CPP DEFINITIONS 75 | #define GL_GREY .5, .5, .5, 1 76 | 77 | #define WW 550 78 | #define WH (WW/16)*12 79 | //END CPP DEFINITIONS 80 | 81 | //BEGIN DATASTRUCTURES 82 | //END DATASTRUCTURES 83 | 84 | //BEGIN GLOBALS 85 | int ww=WW; 86 | int wh=WH; 87 | 88 | //BEGIN VISIBLES 89 | //END VISIBLES 90 | 91 | 92 | //END GLOBALS 93 | 94 | //BEGIN FUNCTION PROTOTYPES 95 | //END FUNCTION PROTOTYPES 96 | 97 | //END HEAD 98 | 99 | //BEGIN MAIN FUNCTION 100 | int main(int argc, char *argv[]) 101 | { 102 | 103 | (void)argc; 104 | (void)argv; 105 | 106 | //BEGIN INIT 107 | init(); 108 | 109 | //BEGIN WINDOW 110 | SDL_SetWindowPosition(Window,0,0); 111 | SDL_SetWindowSize(Window,ww,wh); 112 | SDL_SetWindowTitle(Window, "OpenGL Window"); 113 | SDL_ShowWindow(Window); 114 | //END WINDOW 115 | 116 | int maj; 117 | int min; 118 | 119 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 120 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 121 | SDL_Log("Maj: %d Min: %d", maj, min); 122 | 123 | const GLubyte* renderer; 124 | renderer = glGetString (GL_RENDERER); 125 | SDL_Log("Renderer: %s\n", renderer); 126 | 127 | const GLubyte* version; 128 | version = glGetString (GL_VERSION); 129 | SDL_Log("OpenGL version supported %s\n", version); 130 | 131 | glClearColor(GL_GREY); 132 | glClear(GL_COLOR_BUFFER_BIT); 133 | 134 | SDL_Event event; 135 | int running = 1; 136 | //END INIT 137 | 138 | //BEGIN MAIN LOOP 139 | while(running){ 140 | 141 | //BEGIN EVENT LOOP 142 | while(SDL_PollEvent(&event)){ 143 | if(event.type == SDL_QUIT){ 144 | running =0; 145 | } 146 | if(event.type == SDL_MOUSEMOTION){ 147 | ; 148 | } 149 | if(event.type == SDL_MOUSEBUTTONDOWN){ 150 | if(event.button.button == SDL_BUTTON_RIGHT){ 151 | ; 152 | } 153 | if(event.button.button == SDL_BUTTON_MIDDLE){ 154 | ; 155 | } 156 | if(event.button.button==SDL_BUTTON_LEFT){ 157 | ; 158 | } 159 | } 160 | if(event.type == SDL_KEYDOWN ){ 161 | switch(event.key.keysym.sym ){ 162 | case SDLK_ESCAPE: 163 | running =0; 164 | break; 165 | 166 | case SDLK_r: 167 | case SDLK_BACKSPACE: 168 | break; 169 | 170 | case SDLK_p: 171 | case SDLK_SPACE: 172 | break; 173 | 174 | default: 175 | break; 176 | } 177 | } 178 | } 179 | //END EVENT LOOP 180 | //BEGIN RENDERING 181 | SDL_GL_SwapWindow(Window); 182 | //END RENDERING 183 | } 184 | //END MAIN LOOP 185 | exit_(); 186 | return EXIT_SUCCESS; 187 | 188 | } 189 | //END MAIN FUNCTION 190 | 191 | //BEGIN FUNCTIONS 192 | //END FUNCTIONS 193 | -------------------------------------------------------------------------------- /src/0.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* Init a simple OpenGL Window */ 5 | 6 | /* This is a starter series about GLSL Shaders using SDL2 as OpenGL Helper and 7 | * a bit Shader-Language for C-Coders. 8 | * 9 | * Also the GL-API defines quite a sophisticated working set, which is pretty 10 | * mature but also very cluttered when it comes to Extensions. 11 | * 12 | * It's quite normal, the same happened to the X-Window System. 13 | * You can't have flexibility without complexity. 14 | * 15 | * And those API's are around for a long time in terms of 16 | * software-age and both are supporting a vast amount of hardware 17 | * and have tons of features. 18 | * 19 | * That and the fact that many developers were working on DirectX 20 | * only and now coming back to OGL since Android and IOS don't support 21 | * DX, lead to the development of Vulkan, which is the successor to OpenGL 22 | * like Wayland is to the X-Display-System. 23 | * 24 | * However, learning GLSL does open the door to modern Graphics Hardware, 25 | * the GPU offers thousands of parallel computing cores and GLSL can be used 26 | * with Vulkan also. 27 | */ 28 | 29 | /* DEFINED PROGRESS GOALS 30 | * 31 | * Initialize an OpenGL-Window 32 | * 33 | * #include in helper.h 34 | * so I need also -lGL in the LDFLAGS 35 | * 36 | * In helper.c 37 | * Init: 38 | * add SDL_WINDOW_OPENGL Flag to the window creation call. 39 | * SDL_GLContext glcontext = SDL_GL_CreateContext(Window); 40 | * SDL_GLContext is an alias for void *, a void pointer. 41 | * 42 | * Exit: 43 | * SDL_GL_DeleteContext(glcontext); 44 | * 45 | * SDL_GL_SwapWindow(Window) replaces SDL_RenderPresent(Renderer); 46 | * Not going to deal with the mix of both API's here! 47 | */ 48 | 49 | //END DESCRIPTION 50 | 51 | //BEGIN INCLUDES 52 | 53 | //system headers 54 | #include 55 | //local headers 56 | #include "helper.h" 57 | 58 | //END INCLUDES 59 | 60 | //BEGIN CPP DEFINITIONS 61 | 62 | #define GL_GREY .5, .5, .5, 1 63 | 64 | #define WW 550 65 | #define WH (WW/16)*12 66 | 67 | //END CPP DEFINITIONS 68 | 69 | //BEGIN DATASTRUCTURES 70 | 71 | //END DATASTRUCTURES 72 | 73 | //BEGIN GLOBALS 74 | 75 | int ww=WW; 76 | int wh=WH; 77 | 78 | //BEGIN VISIBLES 79 | 80 | //END VISIBLES 81 | 82 | //END GLOBALS 83 | 84 | //BEGIN FUNCTION PROTOTYPES 85 | 86 | //END FUNCTION PROTOTYPES 87 | 88 | //END HEAD 89 | 90 | //BEGIN MAIN FUNCTION 91 | 92 | int main(int argc, char *argv[]) 93 | { 94 | 95 | (void)argc; 96 | (void)argv; 97 | 98 | //BEGIN INIT 99 | 100 | init(); 101 | 102 | //BEGIN WINDOW 103 | 104 | SDL_SetWindowPosition(Window,0,0); 105 | SDL_SetWindowSize(Window,ww,wh); 106 | SDL_SetWindowTitle(Window, "OpenGL Window"); 107 | SDL_ShowWindow(Window); 108 | 109 | //END WINDOW 110 | 111 | // Don't clear a window to black, it's harder to debug! 112 | glClearColor(GL_GREY); 113 | // This will give a grey 114 | // it is a call like SDL_SetRenderDrawColor(Renderer,0,0,0,0); 115 | // but with range swapped values 127 in this case 116 | 117 | glClear(GL_COLOR_BUFFER_BIT); 118 | // similar to SDL_RenderClear(Renderer) 119 | // void glClear(GLbitfield mask); 120 | 121 | /* 122 | * The values are as follows: 123 | * 124 | * GL_COLOR_BUFFER_BIT 125 | * Indicates the buffers currently enabled for color writing. 126 | * 127 | * GL_DEPTH_BUFFER_BIT 128 | * Indicates the depth buffer. 129 | * 130 | * GL_ACCUM_BUFFER_BIT 131 | * Indicates the accumulation buffer. 132 | * 133 | * GL_STENCIL_BUFFER_BIT 134 | * Indicates the stencil buffer. 135 | * 136 | * The value to which each buffer is cleared depends on the setting of the 137 | * clear value for that buffer. 138 | * 139 | */ 140 | 141 | SDL_Event event; 142 | int running = 1; 143 | 144 | //END INIT 145 | 146 | //BEGIN MAIN LOOP 147 | 148 | while(running){ 149 | 150 | //BEGIN EVENT LOOP 151 | 152 | while(SDL_PollEvent(&event)){ 153 | if(event.type == SDL_QUIT){ 154 | running =0; 155 | } 156 | if(event.type == SDL_MOUSEMOTION){ 157 | ; 158 | } 159 | if(event.type == SDL_MOUSEBUTTONDOWN){ 160 | if(event.button.button == SDL_BUTTON_RIGHT){ 161 | ; 162 | } 163 | if(event.button.button == SDL_BUTTON_MIDDLE){ 164 | ; 165 | } 166 | if(event.button.button==SDL_BUTTON_LEFT){ 167 | ; 168 | } 169 | } 170 | if(event.type == SDL_KEYDOWN ){ 171 | switch(event.key.keysym.sym ){ 172 | case SDLK_ESCAPE: 173 | running =0; 174 | break; 175 | 176 | case SDLK_r: 177 | case SDLK_BACKSPACE: 178 | break; 179 | 180 | case SDLK_p: 181 | case SDLK_SPACE: 182 | break; 183 | 184 | default: 185 | break; 186 | } 187 | } 188 | } 189 | 190 | //END EVENT LOOP 191 | 192 | //BEGIN RENDERING 193 | 194 | SDL_GL_SwapWindow(Window); 195 | 196 | //END RENDERING 197 | 198 | } 199 | 200 | //END MAIN LOOP 201 | 202 | exit_(); 203 | return EXIT_SUCCESS; 204 | 205 | } 206 | //END MAIN FUNCTION 207 | 208 | //BEGIN FUNCTIONS 209 | 210 | //END FUNCTIONS 211 | -------------------------------------------------------------------------------- /src/1c.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | /* DEFINED PROGRESS GOALS 4 | * Draw 4 rectangles and rotate them individually 5 | * around their center. 6 | * 7 | * implement helper functions to create the rects and their centers: 8 | * init_rect 9 | */ 10 | 11 | //END DESCRIPTION 12 | 13 | //BEGIN INCLUDES 14 | //system headers 15 | #include 16 | //local headers 17 | #include "helper.h" 18 | //END INCLUDES 19 | 20 | //BEGIN CPP DEFINITIONS 21 | #define WW 550 22 | #define WH (WW/16)*12 23 | #define GL_GREY .5, .5, .5, 1 24 | #define GL_WHITE 1,1,1,1 25 | 26 | #define GL_PURPLE 0.992, 0.501, 1,1 27 | #define GL_DARK_ORANGE 0.839, 0.423, 0.274,1 28 | #define GL_MID_GREEN 0, 0.5, 0,1 29 | #define GL_BLUEISH 0.2, 0.2, 0.776,1 30 | 31 | //END CPP DEFINITIONS 32 | 33 | //BEGIN DATASTRUCTURES 34 | struct vec2{ 35 | double x; 36 | double y; 37 | }; 38 | 39 | struct rect{ 40 | struct vec2 tl; 41 | struct vec2 br; 42 | 43 | struct vec2 tr; 44 | struct vec2 bl; 45 | 46 | struct vec2 center; 47 | }; 48 | //END DATASTRUCTURES 49 | 50 | //BEGIN GLOBALS 51 | int ww=WW; 52 | int wh=WH; 53 | struct rect rect[4]; 54 | //BEGIN VISIBLES 55 | //END VISIBLES 56 | 57 | //END GLOBALS 58 | 59 | //BEGIN FUNCTION PROTOTYPES 60 | void init_rect (struct rect *, int, int, int, int); 61 | 62 | double norm_RGB (double); 63 | double rescale_RGB (double); 64 | 65 | double norm_NDC_x (double); 66 | double norm_NDC_y (double); 67 | double rescale_NDC_x (double); 68 | double rescale_NDC_y (double); 69 | //END FUNCTION PROTOTYPES 70 | 71 | //END HEAD 72 | 73 | //BEGIN MAIN FUNCTION 74 | int main(int argc, char *argv[]) 75 | { 76 | 77 | (void)argc; 78 | (void)argv; 79 | 80 | //BEGIN INIT 81 | init(); 82 | //BEGIN WINDOW 83 | SDL_SetWindowPosition(Window,0,0); 84 | SDL_SetWindowSize(Window,ww,wh); 85 | SDL_SetWindowTitle(Window, "Rotate Rects"); 86 | SDL_ShowWindow(Window); 87 | //END WINDOW 88 | 89 | glClearColor(GL_GREY); 90 | glClear(GL_COLOR_BUFFER_BIT); 91 | 92 | glViewport (0, 0, ww, wh); 93 | 94 | //BEGING INIT RECTS 95 | //rect top left 96 | init_rect(&rect[0], 10, wh-10, ww/2-5, wh/2+5); 97 | 98 | //rect bot left 99 | init_rect(&rect[1], 10, wh/2-5, ww/2-5, 10); 100 | 101 | //rect top right 102 | init_rect(&rect[2], ww/2+5, wh-10, ww-10, wh/2+5); 103 | 104 | //rect bot right 105 | init_rect(&rect[3], ww/2+5, wh/2-5, ww-10, 10); 106 | 107 | //END INIT RECTS 108 | glMatrixMode(GL_MODELVIEW); 109 | 110 | SDL_Event event; 111 | int running = 1; 112 | //END INIT 113 | double a=1; 114 | //BEGIN MAIN LOOP 115 | while(running){ 116 | 117 | //BEGIN EVENT LOOP 118 | while(SDL_PollEvent(&event)){ 119 | if(event.type == SDL_QUIT){ 120 | running =0; 121 | } 122 | if(event.type == SDL_MOUSEMOTION){ 123 | ; 124 | } 125 | if(event.type == SDL_MOUSEBUTTONDOWN){ 126 | if(event.button.button == SDL_BUTTON_RIGHT){ 127 | ; 128 | } 129 | if(event.button.button == SDL_BUTTON_MIDDLE){ 130 | ; 131 | } 132 | if(event.button.button==SDL_BUTTON_LEFT){ 133 | ; 134 | } 135 | } 136 | if(event.type == SDL_KEYDOWN ){ 137 | switch(event.key.keysym.sym ){ 138 | case SDLK_ESCAPE: 139 | running =0; 140 | break; 141 | 142 | case SDLK_r: 143 | case SDLK_BACKSPACE: 144 | break; 145 | 146 | case SDLK_p: 147 | case SDLK_SPACE: 148 | break; 149 | 150 | default: 151 | break; 152 | } 153 | } 154 | } 155 | //END EVENT LOOP 156 | //BEGIN RENDERING 157 | 158 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 159 | 160 | for (int i=0; i<4; i++){ 161 | glPushMatrix(); 162 | glTranslated(rect[i].center.x, rect[i].center.y, 0); 163 | if (i==0){ 164 | glRotated(a, 0, 1, 0); 165 | glColor4f(GL_PURPLE); 166 | } 167 | if (i==1){ 168 | glRotated(a, 0, 0, 1); 169 | glColor4f(GL_DARK_ORANGE); 170 | } 171 | if (i==2){ 172 | glRotated(a, 1, 0, 0); 173 | glColor4f(GL_MID_GREEN); 174 | } 175 | if (i==3){ 176 | glRotated(a, 1, 1, 1); 177 | glColor4f(GL_BLUEISH); 178 | } 179 | glTranslated(-rect[i].center.x, -rect[i].center.y, 0); //move object to center 180 | 181 | glBegin(GL_QUADS); // Draw A Quad 182 | glVertex3d(rect[i].tl.x, rect[i].tl.y, 0.0f); // Top Left Corner 183 | glVertex3d(rect[i].tr.x, rect[i].tr.y, 0.0f); // Top Right Corner 184 | glVertex3d(rect[i].br.x, rect[i].br.y, 0.0f); // Bottom Right Corner 185 | glVertex3d(rect[i].bl.x, rect[i].bl.y, 0.0f); // Bottom Left Corner 186 | glEnd(); 187 | 188 | glPopMatrix(); 189 | } 190 | a+=0.1; 191 | //optional 192 | if (a>180) 193 | a=0; 194 | 195 | SDL_GL_SwapWindow(Window); 196 | //END RENDERING 197 | } 198 | //END MAIN LOOP 199 | 200 | 201 | exit_(); 202 | return EXIT_SUCCESS; 203 | 204 | } 205 | //END MAIN FUNCTION 206 | 207 | //BEGIN FUNCTIONS 208 | void init_rect(struct rect *rect, int tlx, int tly, int brx, int bry) 209 | { 210 | rect->tl.x=norm_NDC_x(tlx); 211 | rect->tl.y=norm_NDC_y(tly); 212 | rect->br.x=norm_NDC_x(brx); 213 | rect->br.y=norm_NDC_y(bry); 214 | 215 | rect->tr.x=norm_NDC_x(brx); 216 | rect->tr.y=norm_NDC_y(tly); 217 | rect->bl.x=norm_NDC_x(tlx); 218 | rect->bl.y=norm_NDC_y(bry); 219 | 220 | rect->center.x=norm_NDC_x((brx - tlx)/2+tlx); 221 | SDL_Log("c.x: %d", (brx-tlx)/2+tlx); 222 | rect->center.y=norm_NDC_y((bry - tly)/2+tly); 223 | SDL_Log("c.y: %d", (bry - tly)/2+tly); 224 | 225 | } 226 | double norm_RGB(double x) 227 | { 228 | return (x - 0) / (255 - 0); 229 | } 230 | double rescale_RGB(double xr) 231 | { 232 | return xr * 255; 233 | } 234 | double norm_NDC_x(double x) 235 | { 236 | return (2 * (x - 0) / (ww - 0))-1; 237 | } 238 | double norm_NDC_y(double y) 239 | { 240 | return (2 * (y - 0) / (wh - 0))-1; 241 | } 242 | double rescale_NDC_x(double xr) 243 | { 244 | return ww * (xr - -1) / 2; 245 | } 246 | double rescale_NDC_y(double xr) 247 | { 248 | return wh * (xr - -1) / 2; 249 | } 250 | //END FUNCTIONS 251 | -------------------------------------------------------------------------------- /src/2b.c: -------------------------------------------------------------------------------- 1 | /* Using a shader from array in header */ 2 | 3 | #include 4 | #include 5 | #include // Just for the icon - easy to strip out 6 | #include "default_shader.h" 7 | 8 | int ww=800; 9 | int wh=600; 10 | 11 | char Running = 1; 12 | GLuint shading_program_id; 13 | 14 | GLuint default_shader (void); 15 | float fTime (void); 16 | void init_glew (void); 17 | 18 | GLuint compile_shader (GLenum type, GLsizei , const char **sources); 19 | GLuint program_check (GLuint program); 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | (void)argc; 24 | (void)argv; 25 | 26 | SDL_Init(SDL_INIT_VIDEO); 27 | 28 | SDL_Window *Window = SDL_CreateWindow("2b - Default Shader from array", 29 | SDL_WINDOWPOS_CENTERED, 30 | SDL_WINDOWPOS_CENTERED, 31 | ww, wh, 32 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 33 | 34 | //BEGIN ICON 35 | SDL_Surface *icon; 36 | icon=IMG_Load("../assets/gfx/icon.png"); 37 | SDL_SetWindowIcon(Window, icon); 38 | SDL_FreeSurface(icon); 39 | //END ICON 40 | 41 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 42 | init_glew(); 43 | shading_program_id = default_shader(); 44 | 45 | if (shading_program_id == 0){ 46 | Running = 0; 47 | } else 48 | SDL_Log("Using program %d\n", shading_program_id); 49 | 50 | if (glGetError()!=0) 51 | SDL_Log("glError: %#08x\n", glGetError()); 52 | 53 | glUseProgram(shading_program_id); 54 | 55 | static GLint uniform_gtime; 56 | uniform_gtime = glGetUniformLocation(shading_program_id, "fTime"); 57 | 58 | while (Running){ 59 | SDL_Event event; 60 | while ( SDL_PollEvent(&event) ){ 61 | if (event.type == SDL_QUIT) 62 | Running = 0; 63 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 64 | Running = 0; 65 | if(event.type == SDL_WINDOWEVENT){ 66 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 67 | glViewport (0, 0, event.window.data1, event.window.data2); 68 | } 69 | } 70 | } 71 | 72 | glClear(GL_COLOR_BUFFER_BIT); 73 | glRectf(-1.0f, -1.0f, 1.0f, 1.0f); 74 | glUniform1f(uniform_gtime, fTime()); 75 | SDL_GL_SwapWindow(Window); 76 | } 77 | 78 | SDL_GL_DeleteContext(glContext); 79 | SDL_Quit(); 80 | return EXIT_SUCCESS; 81 | } 82 | 83 | float fTime(void) 84 | { 85 | static Uint64 start = 0; 86 | static Uint64 frequency = 0; 87 | 88 | if (start==0){ 89 | start = SDL_GetPerformanceCounter(); 90 | frequency = SDL_GetPerformanceFrequency(); 91 | return 0.0f; 92 | } 93 | 94 | Uint64 counter = SDL_GetPerformanceCounter(); 95 | Uint64 accumulate = counter - start; 96 | return (float)accumulate / (float)frequency; 97 | } 98 | 99 | void init_glew(void) 100 | { 101 | GLenum status; 102 | status = glewInit(); 103 | 104 | if (status != GLEW_OK){ 105 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 106 | Running = 0; 107 | } 108 | 109 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 110 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 111 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 112 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 113 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 114 | 115 | int maj; 116 | int min; 117 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 118 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 119 | SDL_Log("Using OpenGL %d.%d", maj, min); 120 | 121 | if (!GLEW_VERSION_2_0){ 122 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 123 | Running = 0; 124 | } 125 | } 126 | 127 | //BEGIN GPU PROGRAM CREATION 128 | GLuint compile_shader(GLenum type, GLsizei sources_count, const char **sources) 129 | { 130 | GLuint shader; 131 | GLint success, len; 132 | GLsizei i, source_len[sources_count]; 133 | 134 | for (i = 0; i < sources_count; ++i) 135 | source_len[i] = (GLsizei)strlen(sources[i]); 136 | 137 | shader = glCreateShader(type); 138 | glShaderSource(shader, sources_count, sources, source_len); 139 | glCompileShader(shader); 140 | 141 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 142 | if (!success) { 143 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 144 | if (len > 1) { 145 | char *log; 146 | log = malloc(len); 147 | glGetShaderInfoLog(shader, len, NULL, log); 148 | fprintf(stderr, "%s\n\n", log); 149 | free(log); 150 | } 151 | SDL_Log("Error compiling shader.\n"); 152 | } 153 | SDL_Log("shader: %u",shader); 154 | return shader; 155 | } 156 | 157 | GLuint program_check(GLuint program) 158 | { 159 | //Error Checking 160 | GLint status; 161 | glValidateProgram(program); 162 | glGetProgramiv(program, GL_LINK_STATUS, &status); 163 | if (!status){ 164 | GLint len; 165 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 166 | SDL_Log("log length: %d",len); 167 | if (len > 1){ 168 | char *log; 169 | log = malloc(len); 170 | glGetProgramInfoLog(program, sizeof(log), &len, log); 171 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"%s\n\n", log); 172 | free(log); 173 | } 174 | glDeleteProgram(program); 175 | SDL_Log("Error linking shader default program.\n"); 176 | return GL_FALSE; 177 | } 178 | return GL_TRUE; 179 | } 180 | 181 | //END GPU PROGRAM CREATION 182 | 183 | GLuint default_shader(void) 184 | { 185 | GLuint vtx; 186 | const char *sources; 187 | sources = vertex_shader; 188 | vtx = compile_shader(GL_VERTEX_SHADER, 1, &sources); 189 | if (vtx==0) return 0; 190 | 191 | GLuint frag; 192 | sources = fragment_shader; 193 | frag = compile_shader(GL_FRAGMENT_SHADER, 1, &sources); 194 | if (frag==0) return 0; 195 | 196 | shading_program_id = glCreateProgram(); 197 | glAttachShader(shading_program_id, vtx); 198 | glAttachShader(shading_program_id, frag); 199 | glLinkProgram(shading_program_id); 200 | 201 | GLuint status; 202 | status=program_check(shading_program_id); 203 | if (status==GL_FALSE) return 0; 204 | 205 | return shading_program_id; 206 | } 207 | -------------------------------------------------------------------------------- /assets/shader/shadertoy/Ms2SD1_Seascape: -------------------------------------------------------------------------------- 1 | /* 2 | * "Seascape" by Alexander Alekseev aka TDM - 2014 3 | * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. 4 | * Contact: tdmaav@gmail.com 5 | */ 6 | 7 | const int NUM_STEPS = 8; 8 | const float PI = 3.141592; 9 | const float EPSILON = 1e-3; 10 | #define EPSILON_NRM (0.1 / iResolution.x) 11 | 12 | // sea 13 | const int ITER_GEOMETRY = 3; 14 | const int ITER_FRAGMENT = 5; 15 | const float SEA_HEIGHT = 0.6; 16 | const float SEA_CHOPPY = 4.0; 17 | const float SEA_SPEED = 0.8; 18 | const float SEA_FREQ = 0.16; 19 | const vec3 SEA_BASE = vec3(0.1,0.19,0.22); 20 | const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6); 21 | #define SEA_TIME (1.0 + iTime * SEA_SPEED) 22 | const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6); 23 | 24 | // math 25 | mat3 fromEuler(vec3 ang) { 26 | vec2 a1 = vec2(sin(ang.x),cos(ang.x)); 27 | vec2 a2 = vec2(sin(ang.y),cos(ang.y)); 28 | vec2 a3 = vec2(sin(ang.z),cos(ang.z)); 29 | mat3 m; 30 | m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x); 31 | m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x); 32 | m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y); 33 | return m; 34 | } 35 | float hash( vec2 p ) { 36 | float h = dot(p,vec2(127.1,311.7)); 37 | return fract(sin(h)*43758.5453123); 38 | } 39 | float noise( in vec2 p ) { 40 | vec2 i = floor( p ); 41 | vec2 f = fract( p ); 42 | vec2 u = f*f*(3.0-2.0*f); 43 | return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ), 44 | hash( i + vec2(1.0,0.0) ), u.x), 45 | mix( hash( i + vec2(0.0,1.0) ), 46 | hash( i + vec2(1.0,1.0) ), u.x), u.y); 47 | } 48 | 49 | // lighting 50 | float diffuse(vec3 n,vec3 l,float p) { 51 | return pow(dot(n,l) * 0.4 + 0.6,p); 52 | } 53 | float specular(vec3 n,vec3 l,vec3 e,float s) { 54 | float nrm = (s + 8.0) / (PI * 8.0); 55 | return pow(max(dot(reflect(e,n),l),0.0),s) * nrm; 56 | } 57 | 58 | // sky 59 | vec3 getSkyColor(vec3 e) { 60 | e.y = max(e.y,0.0); 61 | return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4); 62 | } 63 | 64 | // sea 65 | float sea_octave(vec2 uv, float choppy) { 66 | uv += noise(uv); 67 | vec2 wv = 1.0-abs(sin(uv)); 68 | vec2 swv = abs(cos(uv)); 69 | wv = mix(wv,swv,wv); 70 | return pow(1.0-pow(wv.x * wv.y,0.65),choppy); 71 | } 72 | 73 | float map(vec3 p) { 74 | float freq = SEA_FREQ; 75 | float amp = SEA_HEIGHT; 76 | float choppy = SEA_CHOPPY; 77 | vec2 uv = p.xz; uv.x *= 0.75; 78 | 79 | float d, h = 0.0; 80 | for(int i = 0; i < ITER_GEOMETRY; i++) { 81 | d = sea_octave((uv+SEA_TIME)*freq,choppy); 82 | d += sea_octave((uv-SEA_TIME)*freq,choppy); 83 | h += d * amp; 84 | uv *= octave_m; freq *= 1.9; amp *= 0.22; 85 | choppy = mix(choppy,1.0,0.2); 86 | } 87 | return p.y - h; 88 | } 89 | 90 | float map_detailed(vec3 p) { 91 | float freq = SEA_FREQ; 92 | float amp = SEA_HEIGHT; 93 | float choppy = SEA_CHOPPY; 94 | vec2 uv = p.xz; uv.x *= 0.75; 95 | 96 | float d, h = 0.0; 97 | for(int i = 0; i < ITER_FRAGMENT; i++) { 98 | d = sea_octave((uv+SEA_TIME)*freq,choppy); 99 | d += sea_octave((uv-SEA_TIME)*freq,choppy); 100 | h += d * amp; 101 | uv *= octave_m; freq *= 1.9; amp *= 0.22; 102 | choppy = mix(choppy,1.0,0.2); 103 | } 104 | return p.y - h; 105 | } 106 | 107 | vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) { 108 | float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0); 109 | fresnel = pow(fresnel,3.0) * 0.65; 110 | 111 | vec3 reflected = getSkyColor(reflect(eye,n)); 112 | vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12; 113 | 114 | vec3 color = mix(refracted,reflected,fresnel); 115 | 116 | float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0); 117 | color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten; 118 | 119 | color += vec3(specular(n,l,eye,60.0)); 120 | 121 | return color; 122 | } 123 | 124 | // tracing 125 | vec3 getNormal(vec3 p, float eps) { 126 | vec3 n; 127 | n.y = map_detailed(p); 128 | n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y; 129 | n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y; 130 | n.y = eps; 131 | return normalize(n); 132 | } 133 | 134 | float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) { 135 | float tm = 0.0; 136 | float tx = 1000.0; 137 | float hx = map(ori + dir * tx); 138 | if(hx > 0.0) return tx; 139 | float hm = map(ori + dir * tm); 140 | float tmid = 0.0; 141 | for(int i = 0; i < NUM_STEPS; i++) { 142 | tmid = mix(tm,tx, hm/(hm-hx)); 143 | p = ori + dir * tmid; 144 | float hmid = map(p); 145 | if(hmid < 0.0) { 146 | tx = tmid; 147 | hx = hmid; 148 | } else { 149 | tm = tmid; 150 | hm = hmid; 151 | } 152 | } 153 | return tmid; 154 | } 155 | 156 | // main 157 | void mainImage( out vec4 fragColor, in vec2 fragCoord ) { 158 | vec2 uv = fragCoord.xy / iResolution.xy; 159 | uv = uv * 2.0 - 1.0; 160 | uv.x *= iResolution.x / iResolution.y; 161 | float time = iTime * 0.3 + iMouse.x*0.01; 162 | 163 | // ray 164 | vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time); 165 | vec3 ori = vec3(0.0,3.5,time*5.0); 166 | vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15; 167 | dir = normalize(dir) * fromEuler(ang); 168 | 169 | // tracing 170 | vec3 p; 171 | heightMapTracing(ori,dir,p); 172 | vec3 dist = p - ori; 173 | vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM); 174 | vec3 light = normalize(vec3(0.0,1.0,0.8)); 175 | 176 | // color 177 | vec3 color = mix( 178 | getSkyColor(dir), 179 | getSeaColor(p,n,light,dir,dist), 180 | pow(smoothstep(0.0,-0.05,dir.y),0.3)); 181 | 182 | // post 183 | fragColor = vec4(pow(color,vec3(0.75)), 1.0); 184 | } 185 | -------------------------------------------------------------------------------- /src/texture_SDL2.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* DEFINED PROGRESS GOALS 5 | * Render a Texture with SDL2 as Image helper. 6 | * https://www.khronos.org/opengl/wiki/Image_Libraries 7 | */ 8 | //END DESCRIPTION 9 | 10 | //BEGIN INCLUDES 11 | //system headers 12 | #include 13 | //local headers 14 | #include "helper.h" 15 | //END INCLUDES 16 | 17 | //BEGIN CPP DEFINITIONS 18 | #define GL_WHITE 1,1,1,1 19 | #define WW 400 20 | #define WH 400 21 | //END CPP DEFINITIONS 22 | 23 | //BEGIN DATASTRUCTURES 24 | //END DATASTRUCTURES 25 | 26 | //BEGIN GLOBALS 27 | int ww=WW; 28 | int wh=WH; 29 | 30 | //BEGIN VISIBLES 31 | GLuint texture; 32 | //END VISIBLES 33 | 34 | //END GLOBALS 35 | 36 | //BEGIN FUNCTION PROTOTYPES 37 | void assets_in (void); 38 | 39 | // These functions are here for reference and might go to helper_sdl.c - but I am not sure, 40 | // which image library I will use in the end. 41 | 42 | // Other ways to flip images: 43 | // Flip Texture Coordinates in the Buffer Data. 44 | // Flip Texture Coordinates in the Vertex Shader. texCoord.y = 1.0 - texCoord.y; (once per vertex) 45 | // Flip Texture Coordinates in the Fragment Shader. texCoord.y = 1.0 - texCoord.y; (once per fragment) 46 | SDL_Surface * flip_vertical (SDL_Surface *); 47 | SDL_Surface * flip_horizontal (SDL_Surface *); 48 | //END FUNCTION PROTOTYPES 49 | 50 | //END HEAD 51 | 52 | //BEGIN MAIN FUNCTION 53 | int main(int argc, char *argv[]) 54 | { 55 | 56 | (void)argc; 57 | (void)argv; 58 | 59 | //BEGIN INIT 60 | init(); 61 | assets_in(); 62 | 63 | //BEGIN WINDOW 64 | SDL_SetWindowPosition(Window,0,0); 65 | SDL_SetWindowSize(Window,ww,wh); 66 | SDL_SetWindowTitle(Window, "Draw Texture with SDL2"); 67 | SDL_ShowWindow(Window); 68 | //END WINDOW 69 | 70 | glClearColor(GL_WHITE); 71 | glClear(GL_COLOR_BUFFER_BIT); 72 | glViewport (0, 0, ww, wh); 73 | SDL_Event event; 74 | int running = 1; 75 | //END INIT 76 | 77 | //BEGIN MAIN LOOP 78 | while(running){ 79 | 80 | //BEGIN EVENT LOOP 81 | while(SDL_PollEvent(&event)){ 82 | if(event.type == SDL_QUIT){ 83 | running =0; 84 | } 85 | if(event.type == SDL_MOUSEMOTION){ 86 | ; 87 | } 88 | if(event.type == SDL_MOUSEBUTTONDOWN){ 89 | if(event.button.button == SDL_BUTTON_RIGHT){ 90 | ; 91 | } 92 | if(event.button.button == SDL_BUTTON_MIDDLE){ 93 | ; 94 | } 95 | if(event.button.button==SDL_BUTTON_LEFT){ 96 | ; 97 | } 98 | } 99 | if(event.type == SDL_KEYDOWN ){ 100 | switch(event.key.keysym.sym ){ 101 | case SDLK_ESCAPE: 102 | running =0; 103 | break; 104 | 105 | case SDLK_r: 106 | case SDLK_BACKSPACE: 107 | break; 108 | 109 | case SDLK_p: 110 | case SDLK_SPACE: 111 | break; 112 | 113 | default: 114 | break; 115 | } 116 | } 117 | } 118 | //END EVENT LOOP 119 | 120 | //BEGIN RENDERING 121 | glClear(GL_COLOR_BUFFER_BIT); 122 | 123 | glBegin(GL_QUADS); // Draw textured Quad 124 | glTexCoord2f(0.0f, 0.0f); glVertex3f(-.75f, .75f, 0.0f); // Top Left Corner 125 | glTexCoord2f(1.0f, 0.0f); glVertex3f( .75f, .75f, 0.0f); // Top Right Corner 126 | glTexCoord2f(1.0f, 1.0f); glVertex3f( .75f,-.75f, 0.0f); // Bottom Right Corner 127 | glTexCoord2f(0.0f, 1.0f); glVertex3f(-.75f,-.75f, 0.0f); // Bottom Left Corner 128 | glEnd(); 129 | 130 | SDL_GL_SwapWindow(Window); 131 | //END RENDERING 132 | } 133 | //END MAIN LOOP 134 | glDeleteTextures( 1, &texture ); 135 | exit_(); 136 | return EXIT_SUCCESS; 137 | 138 | } 139 | //END MAIN FUNCTION 140 | 141 | //BEGIN FUNCTIONS 142 | void assets_in(void) 143 | { 144 | //BEGIN LOGO 145 | // Load surface 146 | SDL_Surface* surface = IMG_Load("../assets/textures/tex02.jpg"); 147 | SDL_Log("BytesPerPixel: %d",surface->format->BytesPerPixel); 148 | // surface=flip_vertical(surface); 149 | // surface=flip_horizontal(surface); 150 | glEnable(GL_TEXTURE_2D); 151 | 152 | // EnableTransparency 153 | // glEnable(GL_BLEND); 154 | // glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); 155 | 156 | glGenTextures(1, &texture); 157 | glBindTexture(GL_TEXTURE_2D, texture); 158 | 159 | 160 | // glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 161 | 162 | //Filtering 163 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 164 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 165 | 166 | //Wrapping 167 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 168 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 169 | 170 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); 171 | 172 | glTexImage2D (GL_TEXTURE_2D, // target 173 | 0, // level, 0 = base, no minimap, 174 | GL_RGB, // internalformat 175 | surface->w, // width 176 | surface->h, // height 177 | 0, // This value must be 0. 178 | GL_RGB, // format 179 | GL_UNSIGNED_BYTE, // data type of the pixel datatype 180 | surface->pixels); 181 | 182 | SDL_FreeSurface(surface); 183 | 184 | } 185 | 186 | SDL_Surface * flip_horizontal(SDL_Surface *sfc) 187 | { 188 | // What is pitch and stride? 189 | // Stride means bytes in a row of pixels including any padding. 190 | // Pitch should be a synonym. 191 | 192 | // Pitch, absolute value, the number of bytes per bitmap line; 193 | // it can be either positive or negative depending on the bitmap's vertical orientation 194 | 195 | // To find a specific pixel in the padded image, you go like this: 196 | // Pixel = (y * pitch) + x; 197 | // Pixel = (line*pitch ) +col 198 | 199 | // SDL_PixelFormat *format; Read-only 200 | // int w, h; Read-only 201 | // int pitch; Read-only, the length of a row of pixels in bytes 202 | // void *pixels; Read-write 203 | 204 | SDL_Surface *result= SDL_CreateRGBSurfaceWithFormat(0,sfc->w,sfc->h, sfc->format->BytesPerPixel, sfc->format->format); 205 | size_t pitch = sfc->pitch; 206 | int pxlength = pitch*sfc->h; 207 | 208 | void *pixels = sfc->pixels + pxlength; // last pixel 209 | void *rpixels = result->pixels; // first pixel 210 | 211 | for(int line = 0; line < sfc->h; ++line){ 212 | memcpy(rpixels,pixels,pitch); // copy the line 213 | pixels -= pitch; // count down 214 | rpixels += pitch; // count up 215 | } 216 | 217 | return result; 218 | } 219 | 220 | SDL_Surface * flip_vertical(SDL_Surface *sfc) 221 | { 222 | SDL_Surface *result= SDL_CreateRGBSurfaceWithFormat(0,sfc->w,sfc->h, sfc->format->BytesPerPixel, sfc->format->format); 223 | 224 | int pitch = sfc->pitch; 225 | void *pixels = sfc->pixels; 226 | void *rpixels = result->pixels+pitch; 227 | 228 | size_t lenght = sfc->format->BytesPerPixel; 229 | 230 | for(int line = 0; line < sfc->h; ++line){ 231 | for (int col = 0; col < sfc->w; col++){ 232 | memcpy(rpixels,pixels,lenght); 233 | pixels+=lenght; 234 | rpixels-=lenght; 235 | } 236 | rpixels+=2*pitch; 237 | } 238 | 239 | return result; 240 | } 241 | -------------------------------------------------------------------------------- /src/1a.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | /* DEFINED PROGRESS GOALS 4 | * 5 | * implement range-change functions. 6 | * draw 4 rectangles 7 | * 8 | */ 9 | 10 | /* 11 | * Coordinate Systems are a mess and most likely will always be. 12 | * OpenGL is right handed in object space and world space. 13 | * But in window space it is left handed; 14 | * Vulkan changes that again. 15 | * 16 | * If you are brilliant in this section and know all axes and origins 17 | * in every Coordinate-Space in every API, congratlulations. 18 | * For people like me it is enough to be aware that an axis 19 | * is not to be guaranteed to point in the direction I think or an Origin, 20 | * aka pivot-point (pivot french) for hinge pin, isn't at the point I am 21 | * thinking. I am pretty sure it was strange for many people starting SDL2 22 | * facing the fact the Window Coordinates Origin is top left. 23 | * 24 | * Also, this GL works a lot with normalized values, another term which is just 25 | * ridiculous imo. First of all, it has nothing to do with 26 | * 1NF, 2NF, 3NF and BCNF in Database Normalization. 27 | * 28 | * Normalization just means, map a value from one range to another range. 29 | * Changing the scale of a number. 30 | * 31 | * E.g. RGB-Color Model values. In SDL programmers are used to 0-255 for 32 | * one color channel, which are 256 possible Values. Dispite the C Array- 33 | * Notation, where 0 is a value, it is quite intuitive; well, maybe not 34 | * intuitive, but for many developers a dataset range of 0-256 is very common. 35 | * 36 | * 256×256×256 are 16,777,216 colors plus Transparency Channel. 37 | * 38 | * In OpenGL Color-values are "normalized" or range-swapped between 0 and 1. 39 | * Where 0 is nothing and 1 is full. 40 | * All on is white and all of is black. 41 | * Same as for the receptors in our Eyes. 42 | * Must not be true for Software, hinting to X (Black-pixel and white-pixel). 43 | * 44 | * So 256/2=128-1 would be the half of our RGB-Value for one Channel. 45 | * 0.5 is the normalized value. 46 | * 47 | * Screen-Coordinates are in the range of -1 to +1, they are also called 48 | * Normalized Screen Coordinates (NDC). 49 | * In other Graphics libraries you see normalized values in the range of 50 | * -2 to +2, 0 to 2 or something totally different. 51 | * 52 | * It's a matter of human arbitrariness, it is defined. 53 | * 54 | * Hint: 55 | * It is way easier to search the web with terms like change range scale 56 | * of numbers than look for Normalization. 57 | * 58 | * A tutorial with reasonable code is here: 59 | * https://github.com/Acry/C-math-normalization 60 | * 61 | * Ofc one can implement the functions as Macros 62 | * in CPP DEFINITIONS 63 | */ 64 | 65 | //END DESCRIPTION 66 | 67 | //BEGIN INCLUDES 68 | //system headers 69 | #include 70 | //local headers 71 | #include "helper.h" 72 | //END INCLUDES 73 | 74 | //BEGIN CPP DEFINITIONS 75 | #define WW 550 76 | #define WH (WW/16)*12 77 | #define GL_GREY .5, .5, .5, 1 78 | #define GL_WHITE 1,1,1,1 79 | //END CPP DEFINITIONS 80 | 81 | //BEGIN DATASTRUCTURES 82 | //END DATASTRUCTURES 83 | 84 | //BEGIN GLOBALS 85 | int ww=WW; 86 | int wh=WH; 87 | 88 | //BEGIN VISIBLES 89 | //END VISIBLES 90 | 91 | //END GLOBALS 92 | 93 | //BEGIN FUNCTION PROTOTYPES 94 | double norm_RGB (double); 95 | double rescale_RGB (double); 96 | 97 | double norm_NDC_x (double); 98 | double norm_NDC_y (double); 99 | double rescale_NDC_x (double); 100 | double rescale_NDC_y (double); 101 | //END FUNCTION PROTOTYPES 102 | 103 | //END HEAD 104 | 105 | //BEGIN MAIN FUNCTION 106 | int main(int argc, char *argv[]) 107 | { 108 | 109 | (void)argc; 110 | (void)argv; 111 | 112 | //BEGIN INIT 113 | init(); 114 | 115 | //BEGIN WINDOW 116 | SDL_SetWindowPosition(Window,0,0); 117 | SDL_SetWindowSize(Window,ww,wh); 118 | SDL_SetWindowTitle(Window, "Draw Rects"); 119 | SDL_ShowWindow(Window); 120 | //END WINDOW 121 | 122 | glClearColor(GL_GREY); 123 | glClear(GL_COLOR_BUFFER_BIT); 124 | 125 | glViewport (0, 0, ww, wh); 126 | 127 | //Set Draw color to white 128 | glColor4f(GL_WHITE); 129 | 130 | //I used this function call in 2.c to draw a rectangle 131 | // glRectf(-.75, .75, .75, -.75); 132 | 133 | //Let's see the screen coordinates 134 | double x1=rescale_NDC_x(-.75); 135 | double x2=rescale_NDC_x(.75); 136 | SDL_Log("x1: %.2f, x2: %.2f", x1, x2); 137 | 138 | SDL_Log("ww/4: %.2f",(float)ww/4); 139 | SDL_Log("wh/2: %.2f",(float)wh/2); 140 | 141 | //I want a border of ten 142 | //rect top left 143 | double r1x1=norm_NDC_x(10); 144 | SDL_Log("r1x1: %f", r1x1); 145 | double r1y1=norm_NDC_y(wh-10); 146 | SDL_Log("r1y1: %f", r1y1); 147 | double r1x2=norm_NDC_x(ww/2-5); 148 | SDL_Log("r1x2: %f", r1x2); 149 | double r1y2=norm_NDC_y(wh/2+5); 150 | SDL_Log("r1y2: %f", r1y2); 151 | 152 | //rect bot left 153 | double r2x1=norm_NDC_x(10); 154 | double r2y1=norm_NDC_y(wh/2-5); 155 | double r2x2=norm_NDC_x(ww/2-5); 156 | double r2y2=norm_NDC_y(10); 157 | 158 | //rect top right 159 | double r3x1=norm_NDC_x(ww/2+5); 160 | double r3y1=norm_NDC_y(wh-10); 161 | double r3x2=norm_NDC_x(ww-10); 162 | double r3y2=norm_NDC_y(wh/2+5); 163 | 164 | //rect bot right 165 | double r4x1=norm_NDC_x(ww/2+5); 166 | double r4y1=norm_NDC_y(wh/2-5); 167 | double r4x2=norm_NDC_x(ww-10); 168 | double r4y2=norm_NDC_y(10); 169 | SDL_Event event; 170 | int running = 1; 171 | //END INIT 172 | 173 | //BEGIN MAIN LOOP 174 | while(running){ 175 | 176 | //BEGIN EVENT LOOP 177 | while(SDL_PollEvent(&event)){ 178 | if(event.type == SDL_QUIT){ 179 | running =0; 180 | } 181 | if(event.type == SDL_MOUSEMOTION){ 182 | ; 183 | } 184 | if(event.type == SDL_MOUSEBUTTONDOWN){ 185 | if(event.button.button == SDL_BUTTON_RIGHT){ 186 | ; 187 | } 188 | if(event.button.button == SDL_BUTTON_MIDDLE){ 189 | ; 190 | } 191 | if(event.button.button==SDL_BUTTON_LEFT){ 192 | ; 193 | } 194 | } 195 | if(event.type == SDL_KEYDOWN ){ 196 | switch(event.key.keysym.sym ){ 197 | case SDLK_ESCAPE: 198 | running =0; 199 | break; 200 | 201 | case SDLK_r: 202 | case SDLK_BACKSPACE: 203 | break; 204 | 205 | case SDLK_p: 206 | case SDLK_SPACE: 207 | break; 208 | 209 | default: 210 | break; 211 | } 212 | } 213 | } 214 | //END EVENT LOOP 215 | //BEGIN RENDERING 216 | glRectf(r1x1, r1y1, r1x2, r1y2); 217 | glRectf(r2x1, r2y1, r2x2, r2y2); 218 | glRectf(r3x1, r3y1, r3x2, r3y2); 219 | glRectf(r4x1, r4y1, r4x2, r4y2); 220 | SDL_GL_SwapWindow(Window); 221 | //END RENDERING 222 | } 223 | //END MAIN LOOP 224 | 225 | 226 | exit_(); 227 | return EXIT_SUCCESS; 228 | 229 | } 230 | //END MAIN FUNCTION 231 | 232 | //BEGIN FUNCTIONS 233 | double norm_RGB(double x) 234 | { 235 | return (x - 0) / (255 - 0); 236 | } 237 | double rescale_RGB(double xr) 238 | { 239 | return xr * 255; 240 | } 241 | double norm_NDC_x(double x) 242 | { 243 | return (2 * (x - 0) / (ww - 0))-1; 244 | } 245 | double norm_NDC_y(double y) 246 | { 247 | return (2 * (y - 0) / (wh - 0))-1; 248 | } 249 | 250 | double rescale_NDC_x(double xr) 251 | { 252 | return ww * (xr - -1) / 2; 253 | } 254 | double rescale_NDC_y(double xr) 255 | { 256 | return wh * (xr - -1) / 2; 257 | } 258 | //END FUNCTIONS 259 | -------------------------------------------------------------------------------- /src/2.c: -------------------------------------------------------------------------------- 1 | /* Render a colorful gradient like in: 2 | * 3 | * https://github.com/Acry/SDL2-Surfaces/blob/master/src/7.c 4 | * and 5 | * https://github.com/Acry/SDL2-Renderer/blob/master/src/3.c 6 | * 7 | */ 8 | 9 | /* Trying to keep it as simple as possible. 10 | * That is why I don't handle the arguments. 11 | * 12 | * Vertex Shader and Fragment shader for the gradient will 13 | * be loaded into an array, but the path is defined. 14 | * 15 | * See that I only included SDL.h and SDL_opengl.h. 16 | * I am not dealing with manual function loading 17 | * or using a function pointer wrangler like glew, 18 | * GL3W, glLoadGen, glad, GLee - whatever. 19 | * https://www.khronos.org/opengl/wiki/OpenGL_Loading_Library 20 | * 21 | * So I needed -Wno-implicit-function-declaration 22 | * to silence gcc warnings. 23 | * 24 | */ 25 | 26 | /* 27 | * Going through the process of creating and using a GPU-Program. 28 | * 29 | * Shader loading, shader creation, program creation 30 | * 31 | * creation means creating the object-handle 32 | * 33 | * -get Shader Sources: File to Char Array or Char Array directly. 34 | * -glCreateShader type 35 | * -glShaderSource point compiler to source 36 | * -compile and return shader if everything went well 37 | * 38 | * -glCreateProgram 39 | * -glAttachShader 40 | * -glLinkProgram 41 | * -glUseProgram 42 | * 43 | * For now the code handles: 44 | * one custom vertex shader and one custom fragment shader. 45 | * 46 | */ 47 | 48 | 49 | #include 50 | #include 51 | #include // Just for the icon - easy to strip out 52 | 53 | #define FRAG "../assets/shader/frag/2.frag" 54 | //you can test 3.frag for a linear one colored gradient for playing around 55 | #define VERT "../assets/shader/vert/2.vert" 56 | 57 | /* Shader stuff: 58 | * 59 | * Vertex attributes are used to communicate from "outside" to the vertex shader. 60 | * Varying variables provide an interface between Vertex and Fragment Shader. 61 | * 62 | */ 63 | int ww=800; 64 | int wh=600; 65 | 66 | GLuint shading_program_id; 67 | 68 | // You can either declare new OpenGL functions as extern 69 | // or use -Wno-implicit-function-declaration to avoid warnings 70 | extern void glGetProgramInfoLog(GLuint , GLsizei , GLsizei *, GLchar *); 71 | 72 | // loads a shader from file and returns the compiled shader 73 | GLuint GetShader (GLenum , const char *); 74 | 75 | //Get and build custom program from 2 files 76 | GLuint custom_shaders (const char * , const char *); 77 | 78 | //see https://github.com/Acry/C-Files 79 | const char * read_file (const char *); 80 | 81 | GLuint compile_shader (GLenum type, GLsizei , const char **); 82 | GLuint program_check (GLuint); 83 | 84 | int main(int argc, char *argv[]) 85 | { 86 | (void)argc; 87 | (void)argv; 88 | 89 | SDL_Init(SDL_INIT_VIDEO); 90 | 91 | SDL_Window *Window = SDL_CreateWindow("2.c - Color Gradient", 92 | SDL_WINDOWPOS_CENTERED, 93 | SDL_WINDOWPOS_CENTERED, 94 | ww, wh, 95 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 96 | 97 | //BEGIN ICON 98 | SDL_Surface *icon; 99 | icon=IMG_Load("../assets/gfx/icon.png"); 100 | SDL_SetWindowIcon(Window, icon); 101 | SDL_FreeSurface(icon); 102 | //END ICON 103 | 104 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 105 | 106 | shading_program_id = custom_shaders(VERT, FRAG); 107 | 108 | char Running = 1; 109 | if (shading_program_id == 0){ 110 | Running = 0; 111 | } else 112 | SDL_Log("Using program %d\n", shading_program_id); 113 | 114 | if (glGetError()!=0) 115 | SDL_Log("glError: %#08x\n", glGetError()); 116 | 117 | glUseProgram(shading_program_id); 118 | 119 | while (Running){ 120 | SDL_Event event; 121 | while ( SDL_PollEvent(&event) ){ 122 | if (event.type == SDL_QUIT) 123 | Running = 0; 124 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 125 | Running = 0; 126 | if(event.type == SDL_WINDOWEVENT){ 127 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 128 | glViewport (0, 0, event.window.data1, event.window.data2); 129 | } 130 | } 131 | } 132 | 133 | glClear(GL_COLOR_BUFFER_BIT); 134 | glRectf(-1.0, -1.0, 1.0, 1.0); 135 | SDL_GL_SwapWindow(Window); 136 | } 137 | 138 | SDL_GL_DeleteContext(glContext); 139 | SDL_Quit(); 140 | return EXIT_SUCCESS; 141 | } 142 | 143 | const char * read_file(const char *filename) 144 | { 145 | long length = 0; 146 | char *result = NULL; 147 | FILE *file = fopen(filename, "r"); 148 | if(file) { 149 | int status = fseek(file, 0, SEEK_END); 150 | if(status != 0) { 151 | fclose(file); 152 | return NULL; 153 | } 154 | length = ftell(file); 155 | status = fseek(file, 0, SEEK_SET); 156 | if(status != 0) { 157 | fclose(file); 158 | return NULL; 159 | } 160 | result = malloc((length+1) * sizeof(char)); 161 | if(result) { 162 | size_t actual_length = fread(result, sizeof(char), length , file); 163 | result[actual_length++] = '\0'; 164 | } 165 | fclose(file); 166 | return result; 167 | } 168 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 169 | return NULL; 170 | } 171 | 172 | //BEGIN GPU PROGRAM CREATION 173 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 174 | { 175 | GLuint vertexShader; 176 | GLuint fragmentShader; 177 | 178 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 179 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 180 | 181 | shading_program_id = glCreateProgram(); 182 | 183 | glAttachShader(shading_program_id, vertexShader); 184 | glAttachShader(shading_program_id, fragmentShader); 185 | 186 | glLinkProgram(shading_program_id); 187 | 188 | 189 | //Error Checking 190 | GLuint status; 191 | status=program_check(shading_program_id); 192 | if (status==GL_FALSE) 193 | return 0; 194 | return shading_program_id; 195 | 196 | } 197 | 198 | GLuint GetShader(GLenum eShaderType, const char *filename) 199 | { 200 | 201 | const char *shaderSource=read_file(filename); 202 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 203 | return shader; 204 | 205 | } 206 | 207 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 208 | { 209 | 210 | GLuint shader; 211 | GLint success, len; 212 | GLsizei i, srclens[nsources]; 213 | 214 | for (i = 0; i < nsources; ++i) 215 | srclens[i] = (GLsizei)strlen(sources[i]); 216 | 217 | shader = glCreateShader(type); 218 | glShaderSource(shader, nsources, sources, srclens); 219 | glCompileShader(shader); 220 | 221 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 222 | if (!success) { 223 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 224 | if (len > 1) { 225 | char *log; 226 | log = malloc(len); 227 | glGetShaderInfoLog(shader, len, NULL, log); 228 | fprintf(stderr, "%s\n\n", log); 229 | free(log); 230 | } 231 | SDL_Log("Error compiling shader.\n"); 232 | } 233 | SDL_Log("shader: %u",shader); 234 | return shader; 235 | } 236 | 237 | GLuint program_check(GLuint program) 238 | { 239 | //Error Checking 240 | GLint status; 241 | glValidateProgram(program); 242 | glGetProgramiv(program, GL_LINK_STATUS, &status); 243 | if (!status){ 244 | GLint len; 245 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 246 | if (len > 1){ 247 | char *log; 248 | log = malloc(len); 249 | glGetProgramInfoLog(program, len, &len, log); 250 | fprintf(stderr, "%s\n\n", log); 251 | free(log); 252 | } 253 | SDL_Log("Error linking shader default program.\n"); 254 | return GL_FALSE; 255 | } 256 | return GL_TRUE; 257 | } 258 | //END GPU PROGRAM CREATION 259 | -------------------------------------------------------------------------------- /src/2a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 2a.c - Animated Gradient 3 | * This program does NOT work as expected. 4 | * It is here for reference. 5 | * I have no clue why it fails. 6 | */ 7 | 8 | /* Render a colorful gradient like in: 9 | * 10 | * https://github.com/Acry/SDL2-Surfaces/blob/master/src/7.c 11 | * and 12 | * https://github.com/Acry/SDL2-Renderer/blob/master/src/3.c 13 | * 14 | * and animate it. 15 | */ 16 | 17 | /* We need a timing function to provide time passed in float. 18 | * A uniform in the fragment shader: 19 | * uniform float fTime; 20 | * And use it int the equation to define the fragment color. 21 | */ 22 | 23 | /* 24 | * BUT - All I could get was this white flickering. 25 | * This was really bugging me, if you can explain to me why this doesn't 26 | * work, please contact me. IMO it should, but I needed to use glew to get it 27 | * running like expected. 28 | * look 2a1 for the expected output. 29 | * - fixed shader version mess, no impact 30 | */ 31 | 32 | #include 33 | #include 34 | #include // Just for the icon - easy to strip out 35 | 36 | #define FRAG "../assets/shader/frag/5.frag" 37 | #define VERT "../assets/shader/vert/2.vert" 38 | /* 39 | * Uniform variables are used to communicate with your vertex or fragment shader 40 | * from "outside". In your shader you use the uniform qualifier to declare the 41 | * variable. 42 | * 43 | * As of GLSL 130+, in and out are used instead of attribute and varying. 44 | * 45 | * I like this overview: 46 | * https://github.com/mattdesl/lwjgl-basics/wiki/glsl-versions 47 | */ 48 | 49 | int ww=800; 50 | int wh=600; 51 | char Running = 1; 52 | GLuint shading_program_id; 53 | 54 | // You can either declare new OpenGL functions as extern 55 | // or use -Wno-implicit-function-declaration to avoid warnings 56 | // extern void glGetProgramInfoLog(GLuint , GLsizei , GLsizei *, GLchar *); 57 | 58 | 59 | // loads a shader from file and returns the compiled shader 60 | GLuint GetShader (GLenum , const char *); 61 | 62 | //Get and build custom program from 2 files 63 | GLuint custom_shaders (const char * , const char *); 64 | 65 | const char * read_file (const char *); 66 | float fTime (void); 67 | 68 | GLuint compile_shader (GLenum type, GLsizei , const char **); 69 | GLuint program_check (GLuint); 70 | 71 | 72 | 73 | int main(int argc, char *argv[]) 74 | { 75 | (void)argc; 76 | (void)argv; 77 | 78 | SDL_Init(SDL_INIT_VIDEO); 79 | 80 | SDL_Window *Window = SDL_CreateWindow("2a - Animated Gradient", 81 | SDL_WINDOWPOS_CENTERED, 82 | SDL_WINDOWPOS_CENTERED, 83 | ww, wh, 84 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 85 | 86 | //BEGIN ICON 87 | SDL_Surface *icon; 88 | icon=IMG_Load("../assets/gfx/icon.png"); 89 | SDL_SetWindowIcon(Window, icon); 90 | SDL_FreeSurface(icon); 91 | //END ICON 92 | 93 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 94 | 95 | shading_program_id = custom_shaders(VERT, FRAG); 96 | 97 | if (shading_program_id == 0){ 98 | Running = 0; 99 | } else 100 | SDL_Log("Using program %d\n", shading_program_id); 101 | 102 | if (glGetError()!=0) 103 | SDL_Log("glError: %#08x\n", glGetError()); 104 | 105 | glUseProgram(shading_program_id); 106 | 107 | static GLint uniform_gtime; 108 | uniform_gtime = glGetUniformLocation(shading_program_id, "fTime"); 109 | 110 | while (Running){ 111 | SDL_Event event; 112 | while ( SDL_PollEvent(&event) ){ 113 | if (event.type == SDL_QUIT) 114 | Running = 0; 115 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 116 | Running = 0; 117 | if(event.type == SDL_WINDOWEVENT){ 118 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 119 | glViewport (0, 0, event.window.data1, event.window.data2); 120 | } 121 | } 122 | } 123 | 124 | glClear(GL_COLOR_BUFFER_BIT); 125 | glRectf(-1.0f, -1.0f, 1.0f, 1.0f); 126 | glUniform1f(uniform_gtime, fTime()); 127 | 128 | SDL_GL_SwapWindow(Window); 129 | } 130 | 131 | SDL_GL_DeleteContext(glContext); 132 | SDL_Quit(); 133 | return EXIT_SUCCESS; 134 | } 135 | 136 | const char * read_file(const char *filename) 137 | { 138 | long length = 0; 139 | char *result = NULL; 140 | FILE *file = fopen(filename, "r"); 141 | if(file) { 142 | int status = fseek(file, 0, SEEK_END); 143 | if(status != 0) { 144 | fclose(file); 145 | return NULL; 146 | } 147 | length = ftell(file); 148 | status = fseek(file, 0, SEEK_SET); 149 | if(status != 0) { 150 | fclose(file); 151 | return NULL; 152 | } 153 | result = malloc((length+1) * sizeof(char)); 154 | if(result) { 155 | size_t actual_length = fread(result, sizeof(char), length , file); 156 | result[actual_length++] = '\0'; 157 | } 158 | fclose(file); 159 | return result; 160 | } 161 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 162 | return NULL; 163 | } 164 | 165 | float fTime(void) 166 | { 167 | static Uint64 start = 0; 168 | static Uint64 frequency = 0; 169 | 170 | if (start==0){ 171 | start = SDL_GetPerformanceCounter(); 172 | frequency = SDL_GetPerformanceFrequency(); 173 | return 0.0f; 174 | } 175 | 176 | Uint64 counter = 0; 177 | counter = SDL_GetPerformanceCounter(); 178 | Uint64 accumulate = counter - start; 179 | return (float)accumulate / (float)frequency; 180 | } 181 | 182 | 183 | //BEGIN GPU PROGRAM CREATION 184 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 185 | { 186 | GLuint vertexShader; 187 | GLuint fragmentShader; 188 | 189 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 190 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 191 | 192 | shading_program_id = glCreateProgram(); 193 | 194 | glAttachShader(shading_program_id, vertexShader); 195 | glAttachShader(shading_program_id, fragmentShader); 196 | 197 | glLinkProgram(shading_program_id); 198 | 199 | 200 | //Error Checking 201 | GLuint status; 202 | status=program_check(shading_program_id); 203 | if (status==GL_FALSE) 204 | return 0; 205 | return shading_program_id; 206 | 207 | } 208 | 209 | GLuint GetShader(GLenum eShaderType, const char *filename) 210 | { 211 | const char *shaderSource=read_file(filename); 212 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 213 | return shader; 214 | } 215 | 216 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 217 | { 218 | GLuint shader; 219 | GLint success, len; 220 | GLsizei i, srclens[nsources]; 221 | 222 | for (i = 0; i < nsources; ++i) 223 | srclens[i] = (GLsizei)strlen(sources[i]); 224 | 225 | shader = glCreateShader(type); 226 | glShaderSource(shader, nsources, sources, srclens); 227 | glCompileShader(shader); 228 | 229 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 230 | if (!success) { 231 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 232 | if (len > 1) { 233 | char *log; 234 | log = malloc(len); 235 | glGetShaderInfoLog(shader, len, NULL, log); 236 | fprintf(stderr, "%s\n\n", log); 237 | free(log); 238 | } 239 | SDL_Log("Error compiling shader.\n"); 240 | } 241 | SDL_Log("shader: %u",shader); 242 | return shader; 243 | } 244 | 245 | GLuint program_check(GLuint program) 246 | { 247 | //Error Checking 248 | GLint status; 249 | glValidateProgram(program); 250 | glGetProgramiv(program, GL_LINK_STATUS, &status); 251 | if (!status){ 252 | GLint len; 253 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 254 | if (len > 1){ 255 | char *log; 256 | log = malloc(len); 257 | glGetProgramInfoLog(program, len, &len, log); 258 | fprintf(stderr, "%s\n\n", log); 259 | free(log); 260 | } 261 | SDL_Log("Error linking shader default program.\n"); 262 | return GL_FALSE; 263 | } 264 | return GL_TRUE; 265 | } 266 | //END GPU PROGRAM CREATION 267 | -------------------------------------------------------------------------------- /src/2a1.c: -------------------------------------------------------------------------------- 1 | /* Render a colorful gradient like in: 2 | * 3 | * https://github.com/Acry/SDL2-Surfaces/blob/master/src/7.c 4 | * and 5 | * https://github.com/Acry/SDL2-Renderer/blob/master/src/3.c 6 | * 7 | * and animate it. 8 | */ 9 | 10 | /* Changes: 11 | * All I did was initializing glew 12 | */ 13 | 14 | /* We need a timing function to provide time passed in float 15 | * 16 | * 17 | * As of GLSL 130+, in and out are used instead of attribute and varying. 18 | * 19 | * I like this overview: 20 | * https://github.com/mattdesl/lwjgl-basics/wiki/glsl-versions 21 | */ 22 | 23 | // careful: needs to be included before SDL 24 | #include 25 | #include 26 | #include // Just for the icon - easy to strip out 27 | 28 | #define FRAG "../assets/shader/frag/5.frag" 29 | #define VERT "../assets/shader/vert/2.vert" 30 | /* 31 | * Uniform variables are used to communicate with your vertex or fragment shader 32 | * from "outside". In your shader you use the uniform qualifier to declare the 33 | * variable. 34 | */ 35 | 36 | int ww=800; 37 | int wh=600; 38 | char Running = 1; 39 | GLuint shading_program_id; 40 | 41 | // You can either declare new OpenGL functions as extern 42 | // or use -Wno-implicit-function-declaration to avoid warnings 43 | // extern void glGetProgramInfoLog(GLuint , GLsizei , GLsizei *, GLchar *); 44 | 45 | 46 | // loads a shader from file and returns the compiled shader 47 | GLuint GetShader (GLenum , const char *); 48 | 49 | //Get and build custom program from 2 files 50 | GLuint custom_shaders (const char * , const char *); 51 | 52 | const char * read_file (const char *); 53 | float fTime (void); 54 | void init_glew (void); 55 | 56 | GLuint compile_shader (GLenum type, GLsizei , const char **); 57 | GLuint program_check (GLuint); 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | (void)argc; 62 | (void)argv; 63 | 64 | SDL_Init(SDL_INIT_VIDEO); 65 | 66 | SDL_Window *Window = SDL_CreateWindow("2a1 - Animated Gradient", 67 | SDL_WINDOWPOS_CENTERED, 68 | SDL_WINDOWPOS_CENTERED, 69 | ww, wh, 70 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 71 | 72 | //BEGIN ICON 73 | SDL_Surface *icon; 74 | icon=IMG_Load("../assets/gfx/icon.png"); 75 | SDL_SetWindowIcon(Window, icon); 76 | SDL_FreeSurface(icon); 77 | //END ICON 78 | 79 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 80 | init_glew(); 81 | shading_program_id = custom_shaders(VERT, FRAG); 82 | 83 | if (shading_program_id == 0){ 84 | Running = 0; 85 | } else 86 | SDL_Log("Using program %d\n", shading_program_id); 87 | 88 | if (glGetError()!=0) 89 | SDL_Log("glError: %#08x\n", glGetError()); 90 | 91 | glUseProgram(shading_program_id); 92 | 93 | static GLint uniform_gtime; 94 | uniform_gtime = glGetUniformLocation(shading_program_id, "fTime"); 95 | 96 | while (Running){ 97 | SDL_Event event; 98 | while ( SDL_PollEvent(&event) ){ 99 | if (event.type == SDL_QUIT) 100 | Running = 0; 101 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 102 | Running = 0; 103 | if(event.type == SDL_WINDOWEVENT){ 104 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 105 | glViewport (0, 0, event.window.data1, event.window.data2); 106 | } 107 | } 108 | } 109 | 110 | glClear(GL_COLOR_BUFFER_BIT); 111 | glRectf(-1.0f, -1.0f, 1.0f, 1.0f); 112 | glUniform1f(uniform_gtime, fTime()); 113 | SDL_GL_SwapWindow(Window); 114 | } 115 | 116 | SDL_GL_DeleteContext(glContext); 117 | SDL_Quit(); 118 | return EXIT_SUCCESS; 119 | } 120 | 121 | const char * read_file(const char *filename) 122 | { 123 | long length = 0; 124 | char *result = NULL; 125 | FILE *file = fopen(filename, "r"); 126 | if(file) { 127 | int status = fseek(file, 0, SEEK_END); 128 | if(status != 0) { 129 | fclose(file); 130 | return NULL; 131 | } 132 | length = ftell(file); 133 | status = fseek(file, 0, SEEK_SET); 134 | if(status != 0) { 135 | fclose(file); 136 | return NULL; 137 | } 138 | result = malloc((length+1) * sizeof(char)); 139 | if(result) { 140 | size_t actual_length = fread(result, sizeof(char), length , file); 141 | result[actual_length++] = '\0'; 142 | } 143 | fclose(file); 144 | return result; 145 | } 146 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 147 | return NULL; 148 | } 149 | 150 | float fTime(void) 151 | { 152 | static Uint64 start = 0; 153 | static Uint64 frequency = 0; 154 | 155 | if (start==0){ 156 | start = SDL_GetPerformanceCounter(); 157 | frequency = SDL_GetPerformanceFrequency(); 158 | return 0.0f; 159 | } 160 | 161 | Uint64 counter = 0; 162 | counter = SDL_GetPerformanceCounter(); 163 | Uint64 accumulate = counter - start; 164 | return (float)accumulate / (float)frequency; 165 | } 166 | 167 | void init_glew(void) 168 | { 169 | GLenum status; 170 | status = glewInit(); 171 | 172 | if (status != GLEW_OK){ 173 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 174 | Running = 0; 175 | } 176 | 177 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 178 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 179 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 180 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 181 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 182 | 183 | int maj; 184 | int min; 185 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 186 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 187 | SDL_Log("Using OpenGL %d.%d", maj, min); 188 | 189 | if (!GLEW_VERSION_2_0){ 190 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 191 | Running = 0; 192 | } 193 | } 194 | //BEGIN GPU PROGRAM CREATION 195 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 196 | { 197 | GLuint vertexShader; 198 | GLuint fragmentShader; 199 | 200 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 201 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 202 | 203 | shading_program_id = glCreateProgram(); 204 | 205 | glAttachShader(shading_program_id, vertexShader); 206 | glAttachShader(shading_program_id, fragmentShader); 207 | 208 | glLinkProgram(shading_program_id); 209 | 210 | 211 | //Error Checking 212 | GLuint status; 213 | status=program_check(shading_program_id); 214 | if (status==GL_FALSE) 215 | return 0; 216 | return shading_program_id; 217 | 218 | } 219 | 220 | GLuint GetShader(GLenum eShaderType, const char *filename) 221 | { 222 | const char *shaderSource=read_file(filename); 223 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 224 | return shader; 225 | } 226 | 227 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 228 | { 229 | GLuint shader; 230 | GLint success, len; 231 | GLsizei i, srclens[nsources]; 232 | 233 | for (i = 0; i < nsources; ++i) 234 | srclens[i] = (GLsizei)strlen(sources[i]); 235 | 236 | shader = glCreateShader(type); 237 | glShaderSource(shader, nsources, sources, srclens); 238 | glCompileShader(shader); 239 | 240 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 241 | if (!success) { 242 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 243 | if (len > 1) { 244 | char *log; 245 | log = malloc(len); 246 | glGetShaderInfoLog(shader, len, NULL, log); 247 | fprintf(stderr, "%s\n\n", log); 248 | free(log); 249 | } 250 | SDL_Log("Error compiling shader.\n"); 251 | } 252 | SDL_Log("shader: %u",shader); 253 | return shader; 254 | } 255 | 256 | GLuint program_check(GLuint program) 257 | { 258 | //Error Checking 259 | GLint status; 260 | glValidateProgram(program); 261 | glGetProgramiv(program, GL_LINK_STATUS, &status); 262 | if (!status){ 263 | GLint len; 264 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 265 | if (len > 1){ 266 | char *log; 267 | log = malloc(len); 268 | glGetProgramInfoLog(program, len, &len, log); 269 | fprintf(stderr, "%s\n\n", log); 270 | free(log); 271 | } 272 | SDL_Log("Error linking shader default program.\n"); 273 | return GL_FALSE; 274 | } 275 | return GL_TRUE; 276 | } 277 | //END GPU PROGRAM CREATION 278 | -------------------------------------------------------------------------------- /src/2c.c: -------------------------------------------------------------------------------- 1 | /* Using a default Shader-Program read from Array in Header */ 2 | 3 | #include 4 | #include 5 | #include // Just for the icon - easy to strip out 6 | #include "def_shaders.h" 7 | 8 | int ww=500; 9 | int wh=281; 10 | 11 | char Running = 1; 12 | GLuint switch_counter = 0; // switches shading programs 13 | 14 | GLfloat vertices[] = { 15 | -1.0f, -1.0f, 16 | 1.0f, -1.0f, 17 | -1.0f, 1.0f, 18 | 1.0f, 1.0f, 19 | }; 20 | 21 | GLint attrib_position; 22 | GLint uniform_res; // Resolution 23 | GLint uniform_gtime; 24 | 25 | GLuint default_shaders (GLuint); 26 | GLuint default_vertex (void); 27 | void shader_switch (void); 28 | 29 | GLuint shading_program_id[4]; 30 | 31 | // loads a shader from file and returns the compiled shader 32 | GLuint GetShader (GLenum , const char *); 33 | 34 | const char * read_file (const char *); 35 | float fTime (void); 36 | void init_glew (void); 37 | 38 | GLuint compile_shader (GLenum type, GLsizei , const char **); 39 | GLuint program_check (GLuint); 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | (void)argc; 44 | (void)argv; 45 | 46 | SDL_Init(SDL_INIT_VIDEO); 47 | 48 | SDL_Window *Window = SDL_CreateWindow("2c - Default Shaders", 49 | SDL_WINDOWPOS_CENTERED, 50 | SDL_WINDOWPOS_CENTERED, 51 | ww, wh, 52 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 53 | 54 | //BEGIN ICON 55 | SDL_Surface *icon; 56 | icon=IMG_Load("../assets/gfx/icon.png"); 57 | SDL_SetWindowIcon(Window, icon); 58 | SDL_FreeSurface(icon); 59 | //END ICON 60 | 61 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 62 | init_glew(); 63 | SDL_Log("Trying to build default shaders"); 64 | for (int i=0; i<3; i++){ 65 | shading_program_id[i] = default_shaders(i); 66 | SDL_Log("i: %d", i); 67 | } 68 | if (shading_program_id[0] == 0){ 69 | Running = 0; 70 | if (glGetError()!=0) 71 | SDL_Log("glError: %#08x\n", glGetError()); 72 | } 73 | glUseProgram(shading_program_id[0]); 74 | glEnableVertexAttribArray (attrib_position); 75 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 76 | uniform_res = glGetUniformLocation(shading_program_id[0], "iResolution"); 77 | uniform_gtime = glGetUniformLocation(shading_program_id[0], "iTime"); 78 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 79 | 80 | while (Running){ 81 | SDL_Event event; 82 | while ( SDL_PollEvent(&event) ){ 83 | 84 | if (event.type == SDL_QUIT) 85 | Running = 0; 86 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 87 | Running = 0; 88 | if(event.type == SDL_WINDOWEVENT){ 89 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 90 | ww = event.window.data1; 91 | wh = event.window.data2; 92 | glViewport (0, 0, ww, wh); 93 | } 94 | } 95 | if(event.type == SDL_MOUSEMOTION){ 96 | ; 97 | } 98 | if(event.type == SDL_MOUSEBUTTONDOWN){ 99 | if(event.button.button == SDL_BUTTON_RIGHT){ 100 | ; 101 | } 102 | if(event.button.button == SDL_BUTTON_MIDDLE){ 103 | shader_switch(); 104 | } 105 | } 106 | } 107 | 108 | glClear(GL_COLOR_BUFFER_BIT); 109 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 110 | glUniform1f(uniform_gtime, fTime()); 111 | SDL_GL_SwapWindow(Window); 112 | } 113 | 114 | // free resources 115 | for (int i=0; i<3; i++){ 116 | if (glIsProgram(shading_program_id[i])) 117 | glDeleteProgram(shading_program_id[i]); 118 | } 119 | SDL_GL_DeleteContext(glContext); 120 | SDL_Quit(); 121 | 122 | return EXIT_SUCCESS; 123 | } 124 | 125 | const char * read_file(const char *filename) 126 | { 127 | long length; 128 | char *result = NULL; 129 | FILE *file = fopen(filename, "r"); 130 | if(file) { 131 | int status = fseek(file, 0, SEEK_END); 132 | if(status != 0) { 133 | fclose(file); 134 | return NULL; 135 | } 136 | length = ftell(file); 137 | status = fseek(file, 0, SEEK_SET); 138 | if(status != 0) { 139 | fclose(file); 140 | return NULL; 141 | } 142 | result = malloc((length+1) * sizeof(char)); 143 | if(result) { 144 | size_t actual_length = fread(result, sizeof(char), length , file); 145 | result[actual_length++] = '\0'; 146 | } 147 | fclose(file); 148 | return result; 149 | } 150 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 151 | 152 | return NULL; 153 | } 154 | 155 | float fTime(void) 156 | { 157 | static Uint64 start = 0; 158 | static Uint64 frequency = 0; 159 | 160 | if (start==0){ 161 | start = SDL_GetPerformanceCounter(); 162 | frequency = SDL_GetPerformanceFrequency(); 163 | return 0.0f; 164 | } 165 | 166 | Uint64 counter = SDL_GetPerformanceCounter(); 167 | Uint64 accumulate = counter - start; 168 | 169 | return (float)accumulate / (float)frequency; 170 | } 171 | 172 | void init_glew(void) 173 | { 174 | GLenum status; 175 | status = glewInit(); 176 | 177 | if (status != GLEW_OK){ 178 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 179 | Running = 0; 180 | } 181 | 182 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 183 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 184 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 185 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 186 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 187 | 188 | int maj; 189 | int min; 190 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 191 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 192 | SDL_Log("Using OpenGL %d.%d", maj, min); 193 | 194 | if (!GLEW_VERSION_2_0){ 195 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 196 | Running = 0; 197 | } 198 | } 199 | //BEGIN GPU PROGRAM CREATION 200 | 201 | GLuint GetShader(GLenum eShaderType, const char *filename) 202 | { 203 | const char *shaderSource=read_file(filename); 204 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 205 | 206 | return shader; 207 | } 208 | 209 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 210 | { 211 | GLuint shader; 212 | GLint success, len; 213 | GLsizei i, srclens[nsources]; 214 | 215 | for (i = 0; i < nsources; ++i) 216 | srclens[i] = (GLsizei)strlen(sources[i]); 217 | 218 | shader = glCreateShader(type); 219 | glShaderSource(shader, nsources, sources, srclens); 220 | glCompileShader(shader); 221 | 222 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 223 | 224 | if (!success) { 225 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 226 | if (len > 1) { 227 | char *log; 228 | log = malloc(len); 229 | glGetShaderInfoLog(shader, len, NULL, log); 230 | fprintf(stderr, "%s\n\n", log); 231 | free(log); 232 | } 233 | SDL_Log("Error compiling shader.\n"); 234 | } 235 | SDL_Log("shader: %u",shader); 236 | 237 | return shader; 238 | } 239 | 240 | GLuint program_check(GLuint program) 241 | { 242 | //Error Checking 243 | GLint status; 244 | glValidateProgram(program); 245 | glGetProgramiv(program, GL_LINK_STATUS, &status); 246 | 247 | if (!status){ 248 | GLint len; 249 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 250 | SDL_Log("log lenght: %d",len); 251 | if (len > 1){ 252 | char *log; 253 | log = malloc(len); 254 | glGetProgramInfoLog(program, sizeof(log), &len, log); 255 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"%s\n\n", log); 256 | free(log); 257 | } 258 | glDeleteProgram(program); 259 | SDL_Log("Error linking shader default program.\n"); 260 | return GL_FALSE; 261 | } 262 | 263 | return GL_TRUE; 264 | } 265 | 266 | //END GPU PROGRAM CREATION 267 | 268 | GLuint default_shaders(GLuint choice) 269 | { 270 | SDL_Log("choice def: %d", choice); 271 | GLuint vtx; 272 | vtx = default_vertex(); 273 | 274 | if (vtx==0) return 0; 275 | 276 | GLuint frag; 277 | const char *sources[4]; 278 | sources[0] = common_shader_header; 279 | sources[1] = fragment_shader_header; 280 | 281 | switch(choice) 282 | { 283 | case 0: 284 | sources[2] = default_fragment_shader_0; 285 | break; 286 | case 1: 287 | sources[2] = default_fragment_shader_1; 288 | break; 289 | case 2: 290 | sources[2] = default_fragment_shader; 291 | break; 292 | default: 293 | break; 294 | } 295 | 296 | sources[3] = fragment_shader_footer; 297 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 298 | 299 | shading_program_id[choice] = glCreateProgram(); 300 | glAttachShader(shading_program_id[choice], vtx); 301 | glAttachShader(shading_program_id[choice], frag); 302 | glLinkProgram(shading_program_id[choice]); 303 | 304 | //Error Checking 305 | GLuint status; 306 | status=program_check(shading_program_id[choice]); 307 | if (status==GL_FALSE) return 0; 308 | 309 | return shading_program_id[choice]; 310 | } 311 | 312 | GLuint default_vertex(void) 313 | { 314 | GLuint vtx; 315 | const char *sources[2]; 316 | sources[0] = common_shader_header; 317 | sources[1] = vertex_shader_body; 318 | vtx = compile_shader(GL_VERTEX_SHADER, 2, sources); 319 | 320 | return vtx; 321 | } 322 | 323 | void shader_switch(void) 324 | { 325 | switch_counter++; 326 | if (switch_counter>(2)) 327 | switch_counter=0; 328 | SDL_Log("switch_counter: %d", switch_counter); 329 | glUseProgram(shading_program_id[switch_counter]); 330 | uniform_gtime = glGetUniformLocation(shading_program_id[switch_counter], "iTime"); 331 | uniform_res = glGetUniformLocation(shading_program_id[switch_counter], "iResolution"); 332 | glEnableVertexAttribArray (attrib_position); 333 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 334 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 335 | glViewport (0, 0, ww, wh); 336 | } 337 | -------------------------------------------------------------------------------- /src/2d.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Make uniform_mouse work 3 | * Use multiple multipart shaders 4 | * TODO explain vertices[] and glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 5 | */ 6 | 7 | #include 8 | #include 9 | #include // Just for the icon - easy to strip out 10 | #include "def_shaders.h" 11 | 12 | int ww=500; 13 | int wh=281; 14 | 15 | char Running = 1; 16 | GLuint switch_counter = 2; // switches shading programs 17 | 18 | GLfloat vertices[] = { 19 | -1.0f, -1.0f, 20 | 1.0f, -1.0f, 21 | -1.0f, 1.0f, 22 | 1.0f, 1.0f, 23 | }; 24 | 25 | GLint attrib_position; 26 | GLint uniform_res; // Resolution 27 | GLint uniform_gtime; 28 | GLint uniform_mouse; //image/buffer xy = current pixel coords (if LMB is down). zw = click pixel 29 | 30 | GLuint default_shaders (GLuint); 31 | GLuint default_vertex (void); 32 | void shader_switch (void); 33 | 34 | GLuint shading_program_id[4]; 35 | 36 | // loads a shader from file and returns the compiled shader 37 | GLuint GetShader (GLenum , const char *); 38 | 39 | const char * read_file (const char *); 40 | float fTime (void); 41 | void init_glew (void); 42 | 43 | GLuint compile_shader (GLenum type, GLsizei , const char **); 44 | GLuint program_check (GLuint); 45 | 46 | int main(int argc, char *argv[]) 47 | { 48 | (void)argc; 49 | (void)argv; 50 | 51 | SDL_Init(SDL_INIT_VIDEO); 52 | 53 | SDL_Window *Window = SDL_CreateWindow("2d - uniform mouse", 54 | SDL_WINDOWPOS_CENTERED, 55 | SDL_WINDOWPOS_CENTERED, 56 | ww, wh, 57 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 58 | 59 | //BEGIN ICON 60 | 61 | SDL_Surface *icon; 62 | icon=IMG_Load("../assets/gfx/icon.png"); 63 | SDL_SetWindowIcon(Window, icon); 64 | SDL_FreeSurface(icon); 65 | 66 | //END ICON 67 | 68 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 69 | init_glew(); 70 | SDL_Log("Trying to build default shaders"); 71 | for (int i=0; i<3; i++){ 72 | shading_program_id[i] = default_shaders(i); 73 | SDL_Log("i: %d", i); 74 | } 75 | if (shading_program_id[0] == 0){ 76 | Running = 0; 77 | if (glGetError()!=0) 78 | SDL_Log("glError: %#08x\n", glGetError()); 79 | } 80 | glUseProgram(shading_program_id[2]); 81 | glEnableVertexAttribArray (attrib_position); 82 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 83 | 84 | uniform_res = glGetUniformLocation(shading_program_id[2], "iResolution"); 85 | uniform_gtime = glGetUniformLocation(shading_program_id[2], "iTime"); 86 | uniform_mouse = glGetUniformLocation(shading_program_id[2], "iMouse"); 87 | 88 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 89 | 90 | SDL_Point mouse; 91 | char MBL_CLICK=0; 92 | 93 | while (Running){ 94 | SDL_Event event; 95 | while ( SDL_PollEvent(&event) ){ 96 | SDL_GetMouseState(&mouse.x, &mouse.y); 97 | if (event.type == SDL_QUIT) 98 | Running = 0; 99 | else if (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE) 100 | Running = 0; 101 | if(event.type == SDL_WINDOWEVENT){ 102 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 103 | ww = event.window.data1; 104 | wh = event.window.data2; 105 | glViewport (0, 0, ww, wh); 106 | } 107 | } 108 | if(event.type == SDL_MOUSEMOTION){ 109 | ; 110 | } 111 | if(event.type == SDL_MOUSEBUTTONDOWN){ 112 | if(event.button.button == SDL_BUTTON_RIGHT){ 113 | ; 114 | } 115 | if(event.button.button == SDL_BUTTON_MIDDLE){ 116 | shader_switch(); 117 | } 118 | if( event.button.button == SDL_BUTTON_LEFT){ 119 | MBL_CLICK=1; 120 | } 121 | } 122 | if(event.type == SDL_MOUSEBUTTONUP){ 123 | if( event.button.button == SDL_BUTTON_LEFT){ 124 | MBL_CLICK=0; 125 | } 126 | } 127 | } 128 | 129 | glClear(GL_COLOR_BUFFER_BIT); 130 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 131 | if (MBL_CLICK==1) 132 | glUniform4f(uniform_mouse, (float)mouse.x, (float)mouse.y, 0.0f, 0.0f ); 133 | 134 | glUniform1f(uniform_gtime, fTime()); 135 | 136 | SDL_GL_SwapWindow(Window); 137 | } 138 | 139 | // free resources 140 | for (int i=0; i<3; i++){ 141 | if (glIsProgram(shading_program_id[i])) 142 | glDeleteProgram(shading_program_id[i]); 143 | } 144 | SDL_GL_DeleteContext(glContext); 145 | SDL_Quit(); 146 | 147 | return EXIT_SUCCESS; 148 | } 149 | 150 | const char * read_file(const char *filename) 151 | { 152 | long length; 153 | char *result = NULL; 154 | FILE *file = fopen(filename, "r"); 155 | if(file) { 156 | int status = fseek(file, 0, SEEK_END); 157 | if(status != 0) { 158 | fclose(file); 159 | return NULL; 160 | } 161 | length = ftell(file); 162 | status = fseek(file, 0, SEEK_SET); 163 | if(status != 0) { 164 | fclose(file); 165 | return NULL; 166 | } 167 | result = malloc((length+1) * sizeof(char)); 168 | if(result) { 169 | size_t actual_length = fread(result, sizeof(char), length , file); 170 | result[actual_length++] = '\0'; 171 | } 172 | fclose(file); 173 | return result; 174 | } 175 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 176 | 177 | return NULL; 178 | } 179 | 180 | float fTime(void) 181 | { 182 | static Uint64 start = 0; 183 | static Uint64 frequency = 0; 184 | 185 | if (start==0){ 186 | start = SDL_GetPerformanceCounter(); 187 | frequency = SDL_GetPerformanceFrequency(); 188 | return 0.0f; 189 | } 190 | 191 | Uint64 counter = SDL_GetPerformanceCounter(); 192 | Uint64 accumulate = counter - start; 193 | 194 | return (float)accumulate / (float)frequency; 195 | } 196 | 197 | void init_glew(void) 198 | { 199 | GLenum status; 200 | status = glewInit(); 201 | 202 | if (status != GLEW_OK){ 203 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 204 | Running = 0; 205 | } 206 | 207 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 208 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 209 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 210 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 211 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 212 | 213 | int maj; 214 | int min; 215 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 216 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 217 | SDL_Log("Using OpenGL %d.%d", maj, min); 218 | 219 | if (!GLEW_VERSION_2_0){ 220 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 221 | Running = 0; 222 | } 223 | } 224 | //BEGIN GPU PROGRAM CREATION 225 | 226 | GLuint GetShader(GLenum eShaderType, const char *filename) 227 | { 228 | const char *shaderSource=read_file(filename); 229 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 230 | 231 | return shader; 232 | } 233 | 234 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 235 | { 236 | GLuint shader; 237 | GLint success, len; 238 | GLsizei i, srclens[nsources]; 239 | 240 | for (i = 0; i < nsources; ++i) 241 | srclens[i] = (GLsizei)strlen(sources[i]); 242 | 243 | shader = glCreateShader(type); 244 | glShaderSource(shader, nsources, sources, srclens); 245 | glCompileShader(shader); 246 | 247 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 248 | 249 | if (!success) { 250 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 251 | if (len > 1) { 252 | char *log; 253 | log = malloc(len); 254 | glGetShaderInfoLog(shader, len, NULL, log); 255 | fprintf(stderr, "%s\n\n", log); 256 | free(log); 257 | } 258 | SDL_Log("Error compiling shader.\n"); 259 | } 260 | SDL_Log("shader: %u",shader); 261 | 262 | return shader; 263 | } 264 | 265 | GLuint program_check(GLuint program) 266 | { 267 | //Error Checking 268 | GLint status; 269 | glValidateProgram(program); 270 | glGetProgramiv(program, GL_LINK_STATUS, &status); 271 | 272 | if (!status){ 273 | GLint len; 274 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 275 | SDL_Log("log lenght: %d",len); 276 | if (len > 1){ 277 | char *log; 278 | log = malloc(len); 279 | glGetProgramInfoLog(program, sizeof(log), &len, log); 280 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"%s\n\n", log); 281 | free(log); 282 | } 283 | glDeleteProgram(program); 284 | SDL_Log("Error linking shader default program.\n"); 285 | return GL_FALSE; 286 | } 287 | 288 | return GL_TRUE; 289 | } 290 | 291 | //END GPU PROGRAM CREATION 292 | 293 | GLuint default_shaders(GLuint choice) 294 | { 295 | SDL_Log("choice def: %d", choice); 296 | GLuint vtx; 297 | vtx = default_vertex(); 298 | 299 | if (vtx==0) return 0; 300 | 301 | GLuint frag; 302 | const char *sources[4]; 303 | sources[0] = common_shader_header; 304 | sources[1] = fragment_shader_header; 305 | 306 | switch(choice) 307 | { 308 | case 0: 309 | sources[2] = default_fragment_shader_0; 310 | break; 311 | case 1: 312 | sources[2] = default_fragment_shader_1; 313 | break; 314 | case 2: 315 | sources[2] = default_fragment_shader; 316 | break; 317 | default: 318 | break; 319 | } 320 | 321 | sources[3] = fragment_shader_footer; 322 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 323 | 324 | shading_program_id[choice] = glCreateProgram(); 325 | glAttachShader(shading_program_id[choice], vtx); 326 | glAttachShader(shading_program_id[choice], frag); 327 | glLinkProgram(shading_program_id[choice]); 328 | 329 | //Error Checking 330 | GLuint status; 331 | status=program_check(shading_program_id[choice]); 332 | if (status==GL_FALSE) return 0; 333 | 334 | return shading_program_id[choice]; 335 | } 336 | 337 | GLuint default_vertex(void) 338 | { 339 | GLuint vtx; 340 | const char *sources[2]; 341 | sources[0] = common_shader_header; 342 | sources[1] = vertex_shader_body; 343 | vtx = compile_shader(GL_VERTEX_SHADER, 2, sources); 344 | 345 | return vtx; 346 | } 347 | 348 | void shader_switch(void) 349 | { 350 | switch_counter++; 351 | if (switch_counter>(2)) switch_counter = 0; 352 | SDL_Log("switch_counter: %d", switch_counter); 353 | glUseProgram(shading_program_id[switch_counter]); 354 | uniform_gtime = glGetUniformLocation(shading_program_id[switch_counter], "iTime"); 355 | uniform_res = glGetUniformLocation(shading_program_id[switch_counter], "iResolution"); 356 | uniform_mouse = glGetUniformLocation(shading_program_id[switch_counter], "iMouse"); 357 | glEnableVertexAttribArray (attrib_position); 358 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 359 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 360 | glViewport (0, 0, ww, wh); 361 | } 362 | -------------------------------------------------------------------------------- /src/3.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | 3 | //BEGIN DESCRIPTION 4 | 5 | /* load shader toy fragment shader as argument 6 | * query some vars on demand 7 | * TODO: query all vars on demand 8 | * TODO: more flexibility through custom shader and query all vars after loading shader code. 9 | */ 10 | 11 | //END DESCRIPTION 12 | 13 | //BEGIN INCLUDES 14 | 15 | #ifdef _WIN32 16 | #include 17 | #include 18 | 19 | #else 20 | #include 21 | #include 22 | #endif 23 | #include //No clue how to do Cross-Platform 24 | //If anyone tries to build tell me 25 | #include 26 | #include // Just for the icon - easy to strip out 27 | #include "default_shaders.h" 28 | #include 29 | 30 | //END INCLUDES 31 | 32 | //BEGIN GLOBALS 33 | 34 | int ww=500; 35 | int wh=281; 36 | 37 | char Running = 1; // controls main loops 38 | GLuint switch_counter = 0; // tracks current used shading program 39 | GLuint argument_provided= 0; 40 | 41 | GLfloat vertices[] = { 42 | -1.0f, -1.0f, 43 | 1.0f, -1.0f, 44 | -1.0f, 1.0f, 45 | 1.0f, 1.0f, 46 | }; 47 | 48 | //3 from header, one optionally loaded 49 | GLuint shading_program_id[4]; 50 | 51 | GLint attrib_position; // Vertex Shader Attribute 52 | 53 | //Used Uniforms so far 54 | GLint uniform_gtime; 55 | GLint uniform_itime; // Don't need both of them 56 | 57 | GLint uniform_res; // Resolution 58 | 59 | //Next one to do 60 | GLint uniform_mouse; //image/buffer xy = current pixel coords (if LMB is down). zw = click pixel 61 | 62 | //Not used so far 63 | GLint sampler_channel[4]; 64 | GLint uniform_cres; 65 | GLint uniform_ctime; 66 | GLint uniform_date; 67 | GLint uniform_srate; 68 | //END GLOBALS 69 | 70 | // loads custom Vertex- and Fragment Shader from File 71 | GLuint custom_shaders (const char * , const char *); 72 | 73 | // uses default Vertex-Shader and loads a ST-Shader 74 | GLuint shadertoy_shader (const char *); 75 | 76 | // loads a shader from file and returns the compile shader 77 | GLuint GetShader (GLenum , const char *); 78 | 79 | // loads default Vertex- and Fragment Shader if no Arguments are provided 80 | GLuint default_shaders (GLuint); 81 | GLuint default_vertex (void); 82 | 83 | GLuint compile_shader (GLenum type, GLsizei , const char **); 84 | GLuint program_check (GLuint); 85 | 86 | void query_shadertoy_old_vars (GLuint); 87 | void query_vars (GLuint); 88 | 89 | void shader_switch (void); 90 | float fTime (void); 91 | void init_glew (void); 92 | const char *read_file (const char *); 93 | //END HEAD 94 | 95 | //BEGIN MAIN 96 | int main(int argc, const char *argv[]) 97 | { 98 | //BEGIN INIT 99 | 100 | if (argc==2){ 101 | argument_provided=1; 102 | SDL_Log("%s",argv[1]); 103 | //for now I will assume type shadertoy is provided 104 | } else { 105 | SDL_Log("No argument provided."); 106 | } 107 | 108 | //BEGIN INIT SDL2 109 | 110 | SDL_Init(SDL_INIT_VIDEO); 111 | SDL_Window *Window = SDL_CreateWindow("3 - load Shadertoy FS", 112 | SDL_WINDOWPOS_CENTERED, 113 | SDL_WINDOWPOS_CENTERED, 114 | ww, wh, 115 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 116 | 117 | //BEGIN ICON 118 | 119 | SDL_Surface *icon; 120 | icon=IMG_Load("../assets/gfx/icon.png"); 121 | SDL_SetWindowIcon(Window, icon); 122 | SDL_FreeSurface(icon); 123 | 124 | //END ICON 125 | 126 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 127 | 128 | //END INIT SDL2 129 | 130 | init_glew(); 131 | 132 | //BEGIN SHADER INIT 133 | 134 | SDL_Log("Trying to build default shaders"); 135 | for (int i=0; i<3; i++){ 136 | shading_program_id[i] = default_shaders(i); 137 | SDL_Log("i: %d", i); 138 | } 139 | if (shading_program_id[0] == 0){ 140 | Running = 0; 141 | if (glGetError()!=0) 142 | SDL_Log("glError: %#08x\n", glGetError()); 143 | } else { 144 | switch(argument_provided) 145 | { 146 | case 0: 147 | glUseProgram(shading_program_id[0]); 148 | query_vars(0); 149 | query_shadertoy_old_vars(0); 150 | SDL_Log("Using default shader"); 151 | break; 152 | case 1: 153 | SDL_Log("Trying to build shadertoy shader"); 154 | shading_program_id[3] = shadertoy_shader(argv[1]); 155 | glUseProgram(shading_program_id[3]); 156 | SDL_Log("Using shading program %d\n", shading_program_id[3]); 157 | query_vars(3); 158 | query_shadertoy_old_vars(3); 159 | switch_counter=4; 160 | break; 161 | default: 162 | break; 163 | } 164 | } 165 | 166 | glEnableVertexAttribArray (attrib_position); 167 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 168 | glUniform3f (uniform_res, ww, wh, 0.0f); 169 | 170 | //END SHADER INIT 171 | 172 | SDL_Point mouse; 173 | char MBL_CLICK=0; 174 | SDL_Event event; 175 | 176 | //END INIT 177 | 178 | //BEGIN MAINLOOP 179 | 180 | while (Running){ 181 | 182 | //BEGIN EVENTS 183 | 184 | while ( SDL_PollEvent(&event) ){ 185 | SDL_GetMouseState(&mouse.x, &mouse.y); 186 | if (event.type == SDL_QUIT) 187 | Running = 0; 188 | if(event.type == SDL_WINDOWEVENT){ 189 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 190 | ww = event.window.data1; 191 | wh = event.window.data2; 192 | glViewport (0, 0, ww, wh); 193 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 194 | } 195 | } 196 | if(event.type == SDL_MOUSEMOTION){ 197 | ; 198 | } 199 | if(event.type == SDL_MOUSEBUTTONDOWN){ 200 | if(event.button.button == SDL_BUTTON_RIGHT){ 201 | ; 202 | } 203 | if(event.button.button == SDL_BUTTON_MIDDLE){ 204 | shader_switch(); 205 | } 206 | if( event.button.button==SDL_BUTTON_LEFT){ 207 | MBL_CLICK=1; 208 | } 209 | } 210 | if(event.type == SDL_MOUSEBUTTONUP){ 211 | if( event.button.button==SDL_BUTTON_LEFT){ 212 | MBL_CLICK=0; 213 | } 214 | } 215 | if(event.type == SDL_KEYDOWN ){ 216 | switch(event.key.keysym.sym ){ 217 | case SDLK_ESCAPE: 218 | Running = 0; 219 | break; 220 | case SDLK_r: 221 | case SDLK_BACKSPACE: 222 | break; 223 | case SDLK_p: 224 | case SDLK_SPACE: 225 | break; 226 | default: 227 | break; 228 | } 229 | } 230 | 231 | } 232 | 233 | //END EVENTS 234 | 235 | //BEGIN UPDATE 236 | 237 | if (MBL_CLICK==1) 238 | glUniform4f(uniform_mouse, mouse.x, mouse.y, 0, 0 ); 239 | 240 | glUniform1f(uniform_gtime, fTime()); 241 | 242 | //END UPDATE 243 | 244 | //BEGIN RENDERING 245 | 246 | glClear(GL_COLOR_BUFFER_BIT); 247 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 248 | SDL_GL_SwapWindow(Window); 249 | 250 | //END RENDERING 251 | 252 | } 253 | 254 | //END MAINLOOP 255 | 256 | //BEGIN EXIT 257 | 258 | for (int i=0; i<3; i++){ 259 | if (glIsProgram(shading_program_id[i])) 260 | glDeleteProgram(shading_program_id[i]); 261 | } 262 | SDL_GL_DeleteContext(glContext); 263 | SDL_Quit(); 264 | 265 | return EXIT_SUCCESS; 266 | 267 | //END EXIT 268 | } 269 | 270 | //END MAIN 271 | 272 | //BEGIN FUNCTIONS 273 | 274 | //BEGIN GPU PROGRAM CREATION 275 | 276 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 277 | { 278 | GLuint vertexShader; 279 | GLuint fragmentShader; 280 | 281 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 282 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 283 | 284 | shading_program_id[3] = glCreateProgram(); 285 | 286 | glAttachShader(shading_program_id[3], vertexShader); 287 | glAttachShader(shading_program_id[3], fragmentShader); 288 | 289 | glLinkProgram(shading_program_id[3]); 290 | 291 | GLuint status; 292 | status=program_check(shading_program_id[3]); 293 | if (status==GL_FALSE) 294 | return 0; 295 | 296 | return shading_program_id[3]; 297 | } 298 | 299 | GLuint shadertoy_shader(const char *fsPath) 300 | { 301 | GLuint vtx; 302 | vtx = default_vertex(); 303 | if (vtx==0) 304 | return 0; 305 | 306 | GLuint frag; 307 | const char *sources[4]; 308 | sources[0] = common_shader_header; 309 | sources[1] = fragment_shader_header; 310 | sources[2] = read_file(fsPath); 311 | sources[3] = fragment_shader_footer; 312 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 313 | 314 | shading_program_id[3] = glCreateProgram(); 315 | 316 | glAttachShader(shading_program_id[3], vtx); 317 | glAttachShader(shading_program_id[3], frag); 318 | 319 | glLinkProgram(shading_program_id[3]); 320 | 321 | GLuint status; 322 | status=program_check(shading_program_id[3]); 323 | 324 | if (status==GL_FALSE) 325 | return 0; 326 | 327 | return shading_program_id[3]; 328 | } 329 | 330 | GLuint GetShader(GLenum eShaderType, const char *filename) 331 | { 332 | const char *shaderSource=read_file(filename); 333 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 334 | return shader; 335 | } 336 | 337 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 338 | { 339 | GLuint shader; 340 | GLint success, len; 341 | GLsizei i, srclens[nsources]; 342 | 343 | for (i = 0; i < nsources; ++i) 344 | srclens[i] = (GLsizei)strlen(sources[i]); 345 | 346 | shader = glCreateShader(type); 347 | glShaderSource(shader, nsources, sources, srclens); 348 | glCompileShader(shader); 349 | 350 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 351 | 352 | if (!success) { 353 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 354 | if (len > 1) { 355 | char *log; 356 | log = malloc(len); 357 | glGetShaderInfoLog(shader, len, NULL, log); 358 | fprintf(stderr, "%s\n\n", log); 359 | free(log); 360 | } 361 | SDL_Log("Error compiling shader.\n"); 362 | } 363 | SDL_Log("shader: %u",shader); 364 | 365 | return shader; 366 | } 367 | 368 | GLuint default_shaders(GLuint choice) 369 | { 370 | SDL_Log("choice def: %d", choice); 371 | GLuint vtx; 372 | vtx = default_vertex(); 373 | if (vtx==0) return 0; 374 | 375 | GLuint frag; 376 | const char *sources[4]; 377 | sources[0] = common_shader_header; 378 | sources[1] = fragment_shader_header; 379 | switch(choice) 380 | { 381 | case 0: 382 | sources[2] = default_fragment_shader_0; 383 | break; 384 | case 1: 385 | sources[2] = default_fragment_shader_1; 386 | break; 387 | case 2: 388 | sources[2] = default_fragment_shader; 389 | break; 390 | default: 391 | break; 392 | } 393 | 394 | sources[3] = fragment_shader_footer; 395 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 396 | 397 | shading_program_id[choice] = glCreateProgram(); 398 | glAttachShader(shading_program_id[choice], vtx); 399 | glAttachShader(shading_program_id[choice], frag); 400 | glLinkProgram(shading_program_id[choice]); 401 | 402 | //Error Checking 403 | GLuint status; 404 | status=program_check(shading_program_id[choice]); 405 | 406 | if (status==GL_FALSE) return 0; 407 | 408 | return shading_program_id[choice]; 409 | } 410 | 411 | GLuint default_vertex(void) 412 | { 413 | GLuint vtx; 414 | const char *sources[2]; 415 | sources[0] = common_shader_header; 416 | sources[1] = vertex_shader_body; 417 | vtx = compile_shader(GL_VERTEX_SHADER, 2, sources); 418 | 419 | return vtx; 420 | } 421 | 422 | GLuint program_check(GLuint program) 423 | { 424 | GLint status; 425 | glValidateProgram(program); 426 | glGetProgramiv(program, GL_LINK_STATUS, &status); 427 | if (!status){ 428 | GLint len; 429 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 430 | if (len > 1){ 431 | char *log; 432 | log = malloc(len); 433 | glGetProgramInfoLog(program, len, &len, log); 434 | fprintf(stderr, "%s\n\n", log); 435 | free(log); 436 | } 437 | SDL_Log("Error linking shader default program.\n"); 438 | return GL_FALSE; 439 | } 440 | 441 | return GL_TRUE; 442 | } 443 | 444 | //END GPU PROGRAM CREATION 445 | 446 | void query_shadertoy_old_vars(GLuint choice) 447 | { 448 | sampler_channel[0] = glGetUniformLocation(shading_program_id[choice], "iChannel0"); 449 | sampler_channel[1] = glGetUniformLocation(shading_program_id[choice], "iChannel1"); 450 | sampler_channel[2] = glGetUniformLocation(shading_program_id[choice], "iChannel2"); 451 | sampler_channel[3] = glGetUniformLocation(shading_program_id[choice], "iChannel3"); 452 | uniform_cres = glGetUniformLocation(shading_program_id[choice], "iChannelResolution"); 453 | uniform_ctime = glGetUniformLocation(shading_program_id[choice], "iChannelTime"); 454 | uniform_itime = glGetUniformLocation(shading_program_id[choice], "iTime"); 455 | uniform_res = glGetUniformLocation(shading_program_id[choice], "iResolution"); 456 | uniform_srate = glGetUniformLocation(shading_program_id[choice], "iSampleRate"); 457 | } 458 | 459 | void query_vars(GLuint choice) 460 | { 461 | GLint i; 462 | GLint count; 463 | 464 | GLint size; 465 | GLenum type; 466 | 467 | const GLsizei bufSize = 16; 468 | GLchar name[bufSize]; 469 | GLsizei length; 470 | 471 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_ATTRIBUTES, &count); 472 | 473 | for (i = 0; i < count; i++){ 474 | glGetActiveAttrib(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 475 | if (!strcmp("iPosition",name)){ 476 | attrib_position = i; 477 | } 478 | } 479 | 480 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_UNIFORMS, &count); 481 | 482 | char global_time1[]="iTime"; 483 | char global_time2[]="iGlobalTime"; 484 | for (i = 0; i < count; i++){ 485 | glGetActiveUniform(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 486 | 487 | SDL_Log("Uniform #%d Type: %u Name: %s\n", i, type, name); 488 | if (!strcmp(global_time1,name)||!strcmp(global_time2,name)){ 489 | uniform_gtime = i; 490 | } 491 | if (!strcmp("iMouse",name)) 492 | uniform_mouse = i; 493 | } 494 | } 495 | 496 | //BEGIN MISC 497 | 498 | float fTime(void) 499 | { 500 | static Uint64 start = 0; 501 | static Uint64 frequency = 0; 502 | 503 | if (start==0){ 504 | start = SDL_GetPerformanceCounter(); 505 | frequency = SDL_GetPerformanceFrequency(); 506 | return 0.0f; 507 | } 508 | 509 | Uint64 counter = SDL_GetPerformanceCounter(); 510 | Uint64 accumulate = counter - start; 511 | 512 | return (float)accumulate / (float)frequency; 513 | } 514 | 515 | void init_glew(void) 516 | { 517 | GLenum status; 518 | status = glewInit(); 519 | 520 | if (status != GLEW_OK){ 521 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 522 | Running = 0; 523 | } 524 | 525 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 526 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 527 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 528 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 529 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 530 | 531 | int maj; 532 | int min; 533 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 534 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 535 | SDL_Log("Using OpenGL %d.%d", maj, min); 536 | 537 | if (!GLEW_VERSION_2_0){ 538 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 539 | Running = 0; 540 | } 541 | } 542 | 543 | const char * read_file(const char *filename) 544 | { 545 | long length; 546 | char *result = NULL; 547 | FILE *file = fopen(filename, "r"); 548 | if(file) { 549 | int status = fseek(file, 0, SEEK_END); 550 | if(status != 0) { 551 | fclose(file); 552 | return NULL; 553 | } 554 | length = ftell(file); 555 | status = fseek(file, 0, SEEK_SET); 556 | if(status != 0) { 557 | fclose(file); 558 | return NULL; 559 | } 560 | result = malloc((length+1) * sizeof(char)); 561 | if(result) { 562 | size_t actual_length = fread(result, sizeof(char), length , file); 563 | result[actual_length++] = '\0'; 564 | } 565 | fclose(file); 566 | return result; 567 | } 568 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 569 | 570 | return NULL; 571 | } 572 | 573 | void shader_switch(void) 574 | { 575 | switch_counter++; 576 | if (switch_counter>(2+argument_provided)) switch_counter = 0; 577 | SDL_Log("switch_counter: %d", switch_counter); 578 | glUseProgram(shading_program_id[switch_counter]); 579 | query_vars(switch_counter); 580 | query_shadertoy_old_vars(switch_counter); 581 | glEnableVertexAttribArray (attrib_position); 582 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 583 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 584 | glViewport (0, 0, ww, wh); 585 | } 586 | 587 | //END MISC 588 | 589 | //END FUNCTIONS 590 | -------------------------------------------------------------------------------- /src/3a1.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | /* 4 | * Crate new shader and compile it 5 | * Press 'n' to write new shadertoy file, 6 | * should open in vscode for now. 7 | * Press 'c' to compile and use if valid 8 | * 9 | * TODO Try inotify interface to monitor file change and try shader compile 10 | */ 11 | //END DESCRIPTION 12 | 13 | //BEGIN INCLUDES 14 | 15 | #ifdef _WIN32 16 | #include 17 | #include 18 | 19 | #else 20 | #include 21 | #include 22 | #endif 23 | #include //No clue how to do Cross-Platform 24 | //If anyone tries to build tell me 25 | #include "default_shaders_3a.h" 26 | #include 27 | #include 28 | 29 | //END INCLUDES 30 | 31 | //BEGIN DEFINES 32 | 33 | // TODO Filename and Editor in Config-File 34 | #define NEW_FILE "STFS_new.glsl" 35 | #define EDITOR "/usr/bin/code" 36 | 37 | //END DEFINES 38 | 39 | //BEGIN GLOBALS 40 | int ww=500; 41 | int wh=281; 42 | 43 | char Running = 1; // controls main loops 44 | GLuint switch_counter = 0; // tracks current used shading program 45 | GLuint argument_provided= 0; 46 | 47 | const char editor_call[]={ ""EDITOR" "NEW_FILE }; 48 | // NOTE If default_fragment_shader_1 changes, hash needs to be updated! 49 | char hash_current[]="006a3fb6cfb35cc8eaeecf66a4fd166f49c6917e"; 50 | char hash_last[] ="006a3fb6cfb35cc8eaeecf66a4fd166f49c6917e"; 51 | 52 | GLfloat vertices[] = { 53 | -1.0f, -1.0f, 54 | 1.0f, -1.0f, 55 | -1.0f, 1.0f, 56 | 1.0f, 1.0f, 57 | }; 58 | 59 | //3 from header, one optionally loaded 60 | GLuint shading_program_id[5]; 61 | 62 | GLint attrib_position; // Vertex Shader Attribute 63 | 64 | //Used Uniforms so far 65 | GLint uniform_gtime; 66 | GLint uniform_itime; // Don't need both of them 67 | 68 | GLint uniform_res; // Resolution 69 | 70 | //Next one to do 71 | GLint uniform_mouse; //image/buffer xy = current pixel coords (if LMB is down). zw = click pixel 72 | 73 | //Not used so far 74 | GLint sampler_channel[4]; 75 | GLint uniform_cres; 76 | GLint uniform_ctime; 77 | GLint uniform_date; 78 | GLint uniform_srate; 79 | 80 | //END GLOBALS 81 | 82 | //BEGIN FUNCTIONS 83 | 84 | //BEGIN NEW FILE 85 | 86 | // writes def FS from default_fragment_shader_1 to NEW_FILE and calls EDITOR 87 | // first time 88 | int write_STFS (void); 89 | // returns if hash changed and keeps track of last hash 90 | int hash_check (void); 91 | // tries to compile and use new program if hash was changed 92 | GLuint compile_STFS (void); 93 | //END NEW FILE 94 | 95 | // loads custom Vertex- and Fragment Shader from File 96 | GLuint custom_shaders (const char * , const char *); 97 | 98 | // uses default Vertex-Shader and loads a ST-Shader 99 | GLuint shadertoy_shader (const char *); 100 | 101 | // loads a shader from file and returns the compile shader 102 | GLuint GetShader (GLenum , const char *); 103 | 104 | // loads default Vertex- and Fragment Shader if no Arguments are provided 105 | GLuint default_shaders (GLuint); 106 | GLuint default_vertex (void); 107 | 108 | GLuint compile_shader (GLenum type, GLsizei , const char **); 109 | GLuint program_check (GLuint); 110 | 111 | void query_shadertoy_old_vars (GLuint); 112 | void query_vars (GLuint); 113 | 114 | void shader_switch (void); 115 | float fTime (void); 116 | void init_glew (void); 117 | const char *read_file (const char *); 118 | 119 | //END FUNCTIONS 120 | 121 | //END HEAD 122 | 123 | //BEGIN MAIN 124 | 125 | int main(int argc, const char *argv[]) 126 | { 127 | //BEGIN INIT 128 | 129 | if (argc==2){ 130 | argument_provided=1; 131 | SDL_Log("%s",argv[1]); 132 | //for now I will assume type shadertoy is provided 133 | } else { 134 | SDL_Log("No argument provided."); 135 | } 136 | 137 | //BEGIN INIT SDL2 138 | 139 | SDL_Init(SDL_INIT_VIDEO); 140 | SDL_Window *Window = SDL_CreateWindow("3a1 - New File", 141 | SDL_WINDOWPOS_CENTERED, 142 | SDL_WINDOWPOS_CENTERED, 143 | ww, wh, 144 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 145 | 146 | //BEGIN ICON 147 | 148 | SDL_Surface *icon; 149 | icon=IMG_Load("../assets/gfx/icon.png"); 150 | SDL_SetWindowIcon(Window, icon); 151 | SDL_FreeSurface(icon); 152 | 153 | //END ICON 154 | 155 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 156 | 157 | //END INIT SDL2 158 | 159 | init_glew(); 160 | 161 | //BEGIN SHADER INIT 162 | 163 | SDL_Log("Trying to build default shaders"); 164 | for (int i=0; i<3; i++){ 165 | shading_program_id[i] = default_shaders(i); 166 | SDL_Log("i: %d", i); 167 | } 168 | if (shading_program_id[0] == 0){ 169 | Running = 0; 170 | if (glGetError()!=0) 171 | SDL_Log("glError: %#08x\n", glGetError()); 172 | } else { 173 | switch(argument_provided) 174 | { 175 | case 0: 176 | glUseProgram(shading_program_id[0]); 177 | query_vars(0); 178 | query_shadertoy_old_vars(0); 179 | SDL_Log("Using default shader"); 180 | break; 181 | case 1: 182 | SDL_Log("Trying to build shadertoy shader"); 183 | shading_program_id[3] = shadertoy_shader(argv[1]); 184 | glUseProgram(shading_program_id[3]); 185 | SDL_Log("Using shading program %d\n", shading_program_id[3]); 186 | query_vars(3); 187 | query_shadertoy_old_vars(3); 188 | switch_counter=4; 189 | break; 190 | default: 191 | break; 192 | } 193 | } 194 | 195 | glEnableVertexAttribArray (attrib_position); 196 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 197 | glUniform3f (uniform_res, ww, wh, 0.0f); 198 | 199 | //END SHADER INIT 200 | 201 | SDL_Point mouse; 202 | char MBL_CLICK=0; 203 | SDL_Event event; 204 | 205 | //END INIT 206 | 207 | //BEGIN MAINLOOP 208 | 209 | while (Running){ 210 | 211 | //BEGIN EVENTS 212 | 213 | while ( SDL_PollEvent(&event) ){ 214 | SDL_GetMouseState(&mouse.x, &mouse.y); 215 | if (event.type == SDL_QUIT) 216 | Running = 0; 217 | if(event.type == SDL_WINDOWEVENT){ 218 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 219 | ww = event.window.data1; 220 | wh = event.window.data2; 221 | glViewport (0, 0, ww, wh); 222 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 223 | } 224 | } 225 | if(event.type == SDL_MOUSEMOTION){ 226 | ; 227 | } 228 | if(event.type == SDL_MOUSEBUTTONDOWN){ 229 | if(event.button.button == SDL_BUTTON_RIGHT){ 230 | ; 231 | } 232 | if(event.button.button == SDL_BUTTON_MIDDLE){ 233 | shader_switch(); 234 | } 235 | if( event.button.button==SDL_BUTTON_LEFT){ 236 | MBL_CLICK=1; 237 | } 238 | } 239 | if(event.type == SDL_MOUSEBUTTONUP){ 240 | if( event.button.button==SDL_BUTTON_LEFT){ 241 | MBL_CLICK=0; 242 | } 243 | } 244 | if(event.type == SDL_KEYDOWN ){ 245 | switch(event.key.keysym.sym ){ 246 | case SDLK_ESCAPE: 247 | Running = 0; 248 | break; 249 | case SDLK_n: 250 | write_STFS(); 251 | break; 252 | case SDLK_c: 253 | compile_STFS(); 254 | break; 255 | case SDLK_r: 256 | case SDLK_BACKSPACE: 257 | break; 258 | case SDLK_p: 259 | case SDLK_SPACE: 260 | break; 261 | default: 262 | break; 263 | } 264 | } 265 | 266 | } 267 | 268 | //END EVENTS 269 | 270 | //BEGIN UPDATE 271 | 272 | if (MBL_CLICK==1) 273 | glUniform4f(uniform_mouse, mouse.x, mouse.y, 0, 0 ); 274 | 275 | glUniform1f(uniform_gtime, fTime()); 276 | 277 | //END UPDATE 278 | 279 | //BEGIN RENDERING 280 | 281 | glClear(GL_COLOR_BUFFER_BIT); 282 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 283 | SDL_GL_SwapWindow(Window); 284 | 285 | //END RENDERING 286 | 287 | } 288 | 289 | //END MAINLOOP 290 | 291 | //BEGIN EXIT 292 | 293 | for (int i=0; i<4; i++){ 294 | if (glIsProgram(shading_program_id[i])) 295 | glDeleteProgram(shading_program_id[i]); 296 | } 297 | SDL_GL_DeleteContext(glContext); 298 | SDL_Quit(); 299 | 300 | return EXIT_SUCCESS; 301 | 302 | //END EXIT 303 | } 304 | 305 | //END MAIN 306 | 307 | //BEGIN FUNCTIONS 308 | 309 | //BEGIN GPU PROGRAM CREATION 310 | 311 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 312 | { 313 | GLuint vertexShader; 314 | GLuint fragmentShader; 315 | 316 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 317 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 318 | 319 | shading_program_id[3] = glCreateProgram(); 320 | 321 | glAttachShader(shading_program_id[3], vertexShader); 322 | glAttachShader(shading_program_id[3], fragmentShader); 323 | 324 | glLinkProgram(shading_program_id[3]); 325 | 326 | GLuint status; 327 | status=program_check(shading_program_id[3]); 328 | if (status==GL_FALSE) 329 | return 0; 330 | 331 | return shading_program_id[3]; 332 | } 333 | 334 | GLuint shadertoy_shader(const char *fsPath) 335 | { 336 | GLuint vtx; 337 | vtx = default_vertex(); 338 | if (vtx==0) 339 | return 0; 340 | 341 | GLuint frag; 342 | const char *sources[4]; 343 | sources[0] = common_shader_header; 344 | sources[1] = fragment_shader_header; 345 | sources[2] = read_file(fsPath); 346 | sources[3] = fragment_shader_footer; 347 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 348 | 349 | shading_program_id[3] = glCreateProgram(); 350 | 351 | glAttachShader(shading_program_id[3], vtx); 352 | glAttachShader(shading_program_id[3], frag); 353 | 354 | glLinkProgram(shading_program_id[3]); 355 | 356 | GLuint status; 357 | status=program_check(shading_program_id[3]); 358 | 359 | if (status==GL_FALSE) 360 | return 0; 361 | 362 | return shading_program_id[3]; 363 | } 364 | 365 | GLuint GetShader(GLenum eShaderType, const char *filename) 366 | { 367 | const char *shaderSource=read_file(filename); 368 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 369 | return shader; 370 | } 371 | 372 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 373 | { 374 | GLuint shader; 375 | GLint success, len; 376 | GLsizei i, srclens[nsources]; 377 | 378 | for (i = 0; i < nsources; ++i) 379 | srclens[i] = (GLsizei)strlen(sources[i]); 380 | 381 | shader = glCreateShader(type); 382 | glShaderSource(shader, nsources, sources, srclens); 383 | glCompileShader(shader); 384 | 385 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 386 | 387 | if (!success) { 388 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 389 | if (len > 1) { 390 | char *log; 391 | log = malloc(len); 392 | glGetShaderInfoLog(shader, len, NULL, log); 393 | fprintf(stderr, "%s\n\n", log); 394 | free(log); 395 | } 396 | SDL_Log("Error compiling shader.\n"); 397 | } 398 | SDL_Log("shader: %u",shader); 399 | 400 | return shader; 401 | } 402 | 403 | GLuint default_shaders(GLuint choice) 404 | { 405 | SDL_Log("choice def: %d", choice); 406 | GLuint vtx; 407 | vtx = default_vertex(); 408 | if (vtx==0) return 0; 409 | 410 | GLuint frag; 411 | const char *sources[4]; 412 | sources[0] = common_shader_header; 413 | sources[1] = fragment_shader_header; 414 | switch(choice) 415 | { 416 | case 0: 417 | sources[2] = default_fragment_shader_0; 418 | break; 419 | case 1: 420 | sources[2] = default_fragment_shader_1; 421 | break; 422 | case 2: 423 | sources[2] = default_fragment_shader; 424 | break; 425 | default: 426 | break; 427 | } 428 | 429 | sources[3] = fragment_shader_footer; 430 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 431 | 432 | shading_program_id[choice] = glCreateProgram(); 433 | glAttachShader(shading_program_id[choice], vtx); 434 | glAttachShader(shading_program_id[choice], frag); 435 | glLinkProgram(shading_program_id[choice]); 436 | 437 | //Error Checking 438 | GLuint status; 439 | status=program_check(shading_program_id[choice]); 440 | 441 | if (status==GL_FALSE) return 0; 442 | 443 | return shading_program_id[choice]; 444 | } 445 | 446 | GLuint default_vertex(void) 447 | { 448 | GLuint vtx; 449 | const char *sources[2]; 450 | sources[0] = common_shader_header; 451 | sources[1] = vertex_shader_body; 452 | vtx = compile_shader(GL_VERTEX_SHADER, 2, sources); 453 | 454 | return vtx; 455 | } 456 | 457 | GLuint program_check(GLuint program) 458 | { 459 | GLint status; 460 | glValidateProgram(program); 461 | glGetProgramiv(program, GL_LINK_STATUS, &status); 462 | if (!status){ 463 | GLint len; 464 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 465 | if (len > 1){ 466 | char *log; 467 | log = malloc(len); 468 | glGetProgramInfoLog(program, len, &len, log); 469 | fprintf(stderr, "%s\n\n", log); 470 | free(log); 471 | } 472 | SDL_Log("Error linking shader default program.\n"); 473 | return GL_FALSE; 474 | } 475 | 476 | return GL_TRUE; 477 | } 478 | 479 | //END GPU PROGRAM CREATION 480 | 481 | void query_shadertoy_old_vars(GLuint choice) 482 | { 483 | sampler_channel[0] = glGetUniformLocation(shading_program_id[choice], "iChannel0"); 484 | sampler_channel[1] = glGetUniformLocation(shading_program_id[choice], "iChannel1"); 485 | sampler_channel[2] = glGetUniformLocation(shading_program_id[choice], "iChannel2"); 486 | sampler_channel[3] = glGetUniformLocation(shading_program_id[choice], "iChannel3"); 487 | uniform_cres = glGetUniformLocation(shading_program_id[choice], "iChannelResolution"); 488 | uniform_ctime = glGetUniformLocation(shading_program_id[choice], "iChannelTime"); 489 | uniform_itime = glGetUniformLocation(shading_program_id[choice], "iTime"); 490 | uniform_res = glGetUniformLocation(shading_program_id[choice], "iResolution"); 491 | uniform_srate = glGetUniformLocation(shading_program_id[choice], "iSampleRate"); 492 | } 493 | 494 | void query_vars(GLuint choice) 495 | { 496 | GLint i; 497 | GLint count; 498 | 499 | GLint size; 500 | GLenum type; 501 | 502 | const GLsizei bufSize = 16; 503 | GLchar name[bufSize]; 504 | GLsizei length; 505 | 506 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_ATTRIBUTES, &count); 507 | 508 | for (i = 0; i < count; i++){ 509 | glGetActiveAttrib(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 510 | if (!strcmp("iPosition",name)){ 511 | attrib_position = i; 512 | } 513 | } 514 | 515 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_UNIFORMS, &count); 516 | 517 | char global_time1[]="iTime"; 518 | char global_time2[]="iGlobalTime"; 519 | for (i = 0; i < count; i++){ 520 | glGetActiveUniform(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 521 | 522 | SDL_Log("Uniform #%d Type: %u Name: %s\n", i, type, name); 523 | if (!strcmp(global_time1,name)||!strcmp(global_time2,name)){ 524 | uniform_gtime = i; 525 | } 526 | if (!strcmp("iMouse",name)) 527 | uniform_mouse = i; 528 | } 529 | } 530 | 531 | //BEGIN MISC 532 | 533 | float fTime(void) 534 | { 535 | static Uint64 start = 0; 536 | static Uint64 frequency = 0; 537 | 538 | if (start==0){ 539 | start = SDL_GetPerformanceCounter(); 540 | frequency = SDL_GetPerformanceFrequency(); 541 | return 0.0f; 542 | } 543 | 544 | Uint64 counter = SDL_GetPerformanceCounter(); 545 | Uint64 accumulate = counter - start; 546 | 547 | return (float)accumulate / (float)frequency; 548 | } 549 | 550 | void init_glew(void) 551 | { 552 | GLenum status; 553 | status = glewInit(); 554 | 555 | if (status != GLEW_OK){ 556 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 557 | Running = 0; 558 | } 559 | 560 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 561 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 562 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 563 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 564 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 565 | 566 | int maj; 567 | int min; 568 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 569 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 570 | SDL_Log("Using OpenGL %d.%d", maj, min); 571 | 572 | if (!GLEW_VERSION_2_0){ 573 | SDL_Log("At least OpenGL 2.0 with GLSL 1.10 required."); 574 | Running = 0; 575 | } 576 | } 577 | 578 | const char * read_file(const char *filename) 579 | { 580 | long length; 581 | char *result = NULL; 582 | FILE *file = fopen(filename, "r"); 583 | if(file) { 584 | int status = fseek(file, 0, SEEK_END); 585 | if(status != 0) { 586 | fclose(file); 587 | return NULL; 588 | } 589 | length = ftell(file); 590 | status = fseek(file, 0, SEEK_SET); 591 | if(status != 0) { 592 | fclose(file); 593 | return NULL; 594 | } 595 | result = malloc((length+1) * sizeof(char)); 596 | if(result) { 597 | size_t actual_length = fread(result, sizeof(char), length , file); 598 | result[actual_length++] = '\0'; 599 | } 600 | fclose(file); 601 | return result; 602 | } 603 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 604 | 605 | return NULL; 606 | } 607 | 608 | int write_STFS(void) 609 | { 610 | FILE *fp; 611 | fp = fopen( ""NEW_FILE , "w" ); 612 | fputs(default_fragment_shader_1, fp); 613 | SDL_Log("Shader written"); 614 | fclose(fp); 615 | system(editor_call); 616 | switch_counter=0; 617 | shader_switch(); 618 | return(0); 619 | } 620 | 621 | GLuint compile_STFS(void) 622 | { 623 | if (hash_check()){ 624 | SDL_Log("hash changed"); 625 | GLuint vtx; 626 | vtx = default_vertex(); 627 | if (vtx==0) 628 | return 0; 629 | 630 | GLuint frag; 631 | const char *sources[4]; 632 | sources[0] = common_shader_header; 633 | sources[1] = fragment_shader_header; 634 | sources[2] = read_file(""NEW_FILE); 635 | sources[3] = fragment_shader_footer; 636 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 637 | 638 | shading_program_id[4] = glCreateProgram(); 639 | 640 | glAttachShader(shading_program_id[4], vtx); 641 | glAttachShader(shading_program_id[4], frag); 642 | 643 | glLinkProgram(shading_program_id[4]); 644 | 645 | GLuint status; 646 | status=program_check(shading_program_id[4]); 647 | if (status==GL_FALSE){ 648 | return 0; 649 | }else{ 650 | glUseProgram(shading_program_id[4]); 651 | SDL_Log("own_shading_program: %d", shading_program_id[4]); 652 | query_vars(4); 653 | query_shadertoy_old_vars(4); 654 | glEnableVertexAttribArray (attrib_position); 655 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 656 | 657 | glViewport (0, 0, ww, wh); 658 | glUniform3f(uniform_res, ww, wh, 0.0f); 659 | return 1; 660 | } 661 | } 662 | 663 | return 0; 664 | 665 | } 666 | 667 | int hash_check(void) 668 | { 669 | //GET HASH 670 | FILE *pipe_in; 671 | char pipe_buff[99]; 672 | 673 | if((pipe_in = popen("sha1sum "NEW_FILE, "r")) == NULL){ 674 | perror("popen"); 675 | exit(1); 676 | } 677 | 678 | while(fgets(pipe_buff, sizeof(pipe_buff), pipe_in)!=NULL){ 679 | // SDL_Log("hash: %s", pipe_buff); 680 | } 681 | 682 | size_t n=40; 683 | strncpy(hash_current, pipe_buff, n); 684 | hash_current[40] = '\0'; 685 | pclose(pipe_in); 686 | 687 | 688 | if ( strcmp(hash_last,hash_current) != 0 ){ 689 | strcpy(hash_last,hash_current); 690 | return 1; 691 | } else { 692 | return 0; 693 | } 694 | } 695 | 696 | void shader_switch(void) 697 | { 698 | switch_counter++; 699 | if (switch_counter>(2+argument_provided)) switch_counter = 0; 700 | SDL_Log("switch_counter: %d", switch_counter); 701 | glUseProgram(shading_program_id[switch_counter]); 702 | query_vars(switch_counter); 703 | query_shadertoy_old_vars(switch_counter); 704 | glEnableVertexAttribArray (attrib_position); 705 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 706 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 707 | glViewport (0, 0, ww, wh); 708 | } 709 | 710 | //END MISC 711 | 712 | //END FUNCTIONS 713 | -------------------------------------------------------------------------------- /src/3a2.c: -------------------------------------------------------------------------------- 1 | //BEGIN HEAD 2 | //BEGIN DESCRIPTION 3 | 4 | /* 5 | * Add inotify and epoll to detect changes in file and recompile shader. 6 | * 7 | * Press 'n' to write a default fragment shader in shadertoy-style to file. 8 | * #define NEW_FILE "STFS_new.glsl" - using the suffix for syntax-hilighting. 9 | * 10 | * It should open in vscode for now, but should work with every editor. 11 | * #define EDITOR "/usr/bin/vscode" 12 | * 13 | * Changing and saving in Editor should be enough to call compile. 14 | * 'c' to compile is still valid. 15 | * 16 | * Introduced function reset_poll using epoll and inotify. 17 | * Should be faster than STAT(2). 18 | * 19 | * TODO: Filename and Editor in Config-File 20 | * 21 | * So basically one can edit on the fly now or copy and paste shadercode 22 | * from shadertoy. With save-as in editor work is permanent. 23 | */ 24 | 25 | //END DESCRIPTION 26 | 27 | //BEGIN INCLUDES 28 | 29 | // gave up on cross-platform for now 30 | #include 31 | 32 | #include 33 | #include // Just for the icon - easy to strip out 34 | #include "default_shaders_3a.h" // Contains def vertex and frag shader 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | // #include 42 | #include 43 | #include 44 | 45 | //END INCLUDES 46 | 47 | //BEGIN DEFINES 48 | 49 | #define NEW_FILE "STFS_new.glsl" 50 | #define EDITOR "/usr/bin/code" 51 | 52 | //END DEFINES 53 | 54 | //BEGIN GLOBALS 55 | 56 | int ww=500; 57 | int wh=281; 58 | 59 | char Running = 1; // controls main loops 60 | GLuint switch_counter = 0; // tracks current used shading program 61 | GLuint argument_provided= 0; 62 | 63 | int NEW_SHADER=0; 64 | 65 | //inotify and epoll 66 | int wd, fd, efd, cfg; 67 | 68 | struct epoll_event ev; 69 | 70 | const char editor_call[]={ ""EDITOR" "NEW_FILE }; 71 | 72 | GLfloat vertices[] = { 73 | -1.0f, -1.0f, 74 | 1.0f, -1.0f, 75 | -1.0f, 1.0f, 76 | 1.0f, 1.0f, 77 | }; 78 | 79 | //3 from header, one optionally loaded 80 | GLuint shading_program_id[5]; 81 | 82 | GLint attrib_position; // Vertex Shader Attribute 83 | 84 | //Used Uniforms so far 85 | GLint uniform_gtime; 86 | GLint uniform_itime; // Don't need both of them 87 | GLint uniform_res; // Resolution 88 | 89 | //Next one to do 90 | GLint uniform_mouse; //image/buffer xy = current pixel coords (if LMB is down). zw = click pixel 91 | 92 | //Not used so far 93 | GLint sampler_channel[4]; 94 | GLint uniform_cres; 95 | GLint uniform_ctime; 96 | GLint uniform_date; 97 | GLint uniform_srate; 98 | 99 | //END GLOBALS 100 | 101 | //BEGIN FUNCTIONS 102 | 103 | //BEGIN NEW FILE 104 | 105 | // writes def FS from default_fragment_shader_1 to NEW_FILE and calls EDITOR 106 | // first time 107 | int write_STFS (void); 108 | 109 | struct epoll_event reset_poll(int); 110 | // tries to compile and use new program if hash was changed 111 | GLuint compile_STFS (void); 112 | //END NEW FILE 113 | 114 | // loads custom Vertex- and Fragment Shader from File 115 | GLuint custom_shaders (const char * , const char *); 116 | 117 | // uses default Vertex-Shader and loads a ST-Shader 118 | GLuint shadertoy_shader (const char *); 119 | 120 | // loads a shader from file and returns the compile shader 121 | GLuint GetShader (GLenum , const char *); 122 | 123 | // loads default Vertex- and Fragment Shader if no Arguments are provided 124 | GLuint default_shaders (GLuint); 125 | GLuint default_vertex (void); 126 | 127 | GLuint compile_shader (GLenum type, GLsizei , const char **); 128 | GLuint program_check (GLuint); 129 | 130 | void query_shadertoy_old_vars (GLuint); 131 | void query_vars (GLuint); 132 | 133 | void shader_switch (void); 134 | float fTime (void); 135 | void init_glew (void); 136 | const char *read_file (const char *); 137 | 138 | //END FUNCTIONS 139 | 140 | //END HEAD 141 | 142 | //BEGIN MAIN 143 | 144 | int main(int argc, const char *argv[]) 145 | { 146 | //BEGIN INIT 147 | 148 | if (argc==2){ 149 | argument_provided=1; 150 | SDL_Log("%s",argv[1]); 151 | //for now I will assume type shadertoy is provided 152 | } else { 153 | SDL_Log("No argument provided."); 154 | } 155 | 156 | //BEGIN INIT SDL2 157 | 158 | SDL_Init(SDL_INIT_VIDEO); 159 | SDL_Window *Window = SDL_CreateWindow("3a2 - compile on save", 160 | SDL_WINDOWPOS_CENTERED, 161 | SDL_WINDOWPOS_CENTERED, 162 | ww, wh, 163 | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE); 164 | 165 | //BEGIN ICON 166 | 167 | SDL_Surface *icon; 168 | icon=IMG_Load("../assets/gfx/icon.png"); 169 | SDL_SetWindowIcon(Window, icon); 170 | SDL_FreeSurface(icon); 171 | 172 | //END ICON 173 | 174 | SDL_GLContext glContext = SDL_GL_CreateContext(Window); 175 | 176 | //END INIT SDL2 177 | 178 | init_glew(); 179 | 180 | //BEGIN SHADER INIT 181 | 182 | SDL_Log("Trying to build default shaders"); 183 | for (int i=0; i<3; i++){ 184 | shading_program_id[i] = default_shaders(i); 185 | SDL_Log("i: %d", i); 186 | } 187 | if (shading_program_id[0] == 0){ 188 | Running = 0; 189 | if (glGetError()!=0) 190 | SDL_Log("glError: %#08x\n", glGetError()); 191 | } else { 192 | switch(argument_provided) 193 | { 194 | case 0: 195 | glUseProgram(shading_program_id[0]); 196 | query_vars(0); 197 | query_shadertoy_old_vars(0); 198 | SDL_Log("Using default shader"); 199 | break; 200 | case 1: 201 | SDL_Log("Trying to build shadertoy shader"); 202 | shading_program_id[3] = shadertoy_shader(argv[1]); 203 | glUseProgram(shading_program_id[3]); 204 | SDL_Log("Using shading program %d\n", shading_program_id[3]); 205 | query_vars(3); 206 | query_shadertoy_old_vars(3); 207 | switch_counter=4; 208 | break; 209 | default: 210 | break; 211 | } 212 | } 213 | 214 | glEnableVertexAttribArray (attrib_position); 215 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 216 | glUniform3f (uniform_res, ww, wh, 0.0f); 217 | 218 | //END SHADER INIT 219 | 220 | SDL_Point mouse; 221 | char MBL_CLICK=0; 222 | struct epoll_event ev; 223 | SDL_Event event; 224 | 225 | //END INIT 226 | 227 | //BEGIN MAINLOOP 228 | 229 | while (Running){ 230 | 231 | //BEGIN EVENTS 232 | 233 | while ( SDL_PollEvent(&event) ){ 234 | SDL_GetMouseState(&mouse.x, &mouse.y); 235 | if (event.type == SDL_QUIT) 236 | Running = 0; 237 | if(event.type == SDL_WINDOWEVENT){ 238 | if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED){ 239 | ww = event.window.data1; 240 | wh = event.window.data2; 241 | glViewport (0, 0, ww, wh); 242 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 243 | } 244 | } 245 | if(event.type == SDL_MOUSEMOTION){ 246 | ; 247 | } 248 | if(event.type == SDL_MOUSEBUTTONDOWN){ 249 | if(event.button.button == SDL_BUTTON_RIGHT){ 250 | ; 251 | } 252 | if(event.button.button == SDL_BUTTON_MIDDLE){ 253 | shader_switch(); 254 | } 255 | if( event.button.button==SDL_BUTTON_LEFT){ 256 | MBL_CLICK=1; 257 | } 258 | } 259 | if(event.type == SDL_MOUSEBUTTONUP){ 260 | if( event.button.button==SDL_BUTTON_LEFT){ 261 | MBL_CLICK=0; 262 | } 263 | } 264 | if(event.type == SDL_KEYDOWN ){ 265 | switch(event.key.keysym.sym ){ 266 | case SDLK_ESCAPE: 267 | Running = 0; 268 | break; 269 | case SDLK_n: 270 | write_STFS(); 271 | ev = reset_poll(0); 272 | break; 273 | case SDLK_c: 274 | compile_STFS(); 275 | break; 276 | case SDLK_r: 277 | case SDLK_BACKSPACE: 278 | break; 279 | case SDLK_p: 280 | case SDLK_SPACE: 281 | break; 282 | default: 283 | break; 284 | } 285 | } 286 | } 287 | 288 | //END EVENTS 289 | 290 | //BEGIN UPDATE 291 | 292 | if (MBL_CLICK==1) 293 | glUniform4f(uniform_mouse, mouse.x, mouse.y, 0, 0 ); 294 | 295 | if (NEW_SHADER==1){ 296 | if (epoll_wait(efd, &ev, sizeof(ev), 0) > 0){ 297 | SDL_Log("try compile"); 298 | compile_STFS(); 299 | ev = reset_poll(0); 300 | } 301 | } 302 | glUniform1f(uniform_gtime, fTime()); 303 | 304 | //END UPDATE 305 | 306 | //BEGIN RENDERING 307 | 308 | glClear(GL_COLOR_BUFFER_BIT); 309 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 310 | SDL_GL_SwapWindow(Window); 311 | 312 | //END RENDERING 313 | 314 | } 315 | 316 | //END MAINLOOP 317 | 318 | //BEGIN EXIT 319 | 320 | if (NEW_SHADER==1){ 321 | ev = reset_poll(1); 322 | } 323 | 324 | for (int i=0; i<4; i++){ 325 | if (glIsProgram(shading_program_id[i])) 326 | glDeleteProgram(shading_program_id[i]); 327 | } 328 | SDL_GL_DeleteContext(glContext); 329 | SDL_Quit(); 330 | 331 | return EXIT_SUCCESS; 332 | 333 | //END EXIT 334 | 335 | } 336 | 337 | //END MAIN 338 | 339 | //BEGIN FUNCTIONS 340 | 341 | //BEGIN GPU PROGRAM CREATION 342 | 343 | GLuint custom_shaders(const char *vsPath, const char *fsPath) 344 | { 345 | GLuint vertexShader; 346 | GLuint fragmentShader; 347 | 348 | vertexShader = GetShader(GL_VERTEX_SHADER, vsPath); 349 | fragmentShader = GetShader(GL_FRAGMENT_SHADER, fsPath); 350 | 351 | shading_program_id[3] = glCreateProgram(); 352 | 353 | glAttachShader(shading_program_id[3], vertexShader); 354 | glAttachShader(shading_program_id[3], fragmentShader); 355 | 356 | glLinkProgram(shading_program_id[3]); 357 | 358 | GLuint status; 359 | status=program_check(shading_program_id[3]); 360 | 361 | if (status==GL_FALSE) return 0; 362 | 363 | return shading_program_id[3]; 364 | } 365 | 366 | GLuint shadertoy_shader(const char *fsPath) 367 | { 368 | GLuint vtx; 369 | vtx = default_vertex(); 370 | if (vtx==0) return 0; 371 | 372 | GLuint frag; 373 | const char *sources[4]; 374 | sources[0] = common_shader_header; 375 | sources[1] = fragment_shader_header; 376 | sources[2] = read_file(fsPath); 377 | sources[3] = fragment_shader_footer; 378 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 379 | 380 | shading_program_id[3] = glCreateProgram(); 381 | 382 | glAttachShader(shading_program_id[3], vtx); 383 | glAttachShader(shading_program_id[3], frag); 384 | 385 | glLinkProgram(shading_program_id[3]); 386 | 387 | GLuint status; 388 | status=program_check(shading_program_id[3]); 389 | 390 | if (status==GL_FALSE) return 0; 391 | 392 | return shading_program_id[3]; 393 | } 394 | 395 | GLuint GetShader(GLenum eShaderType, const char *filename) 396 | { 397 | const char *shaderSource=read_file(filename); 398 | GLuint shader = compile_shader(eShaderType, 1, &shaderSource); 399 | return shader; 400 | } 401 | 402 | GLuint compile_shader(GLenum type, GLsizei nsources, const char **sources) 403 | { 404 | GLuint shader; 405 | GLint success, len; 406 | GLsizei i, srclens[nsources]; 407 | 408 | for (i = 0; i < nsources; ++i) 409 | srclens[i] = (GLsizei)strlen(sources[i]); 410 | 411 | shader = glCreateShader(type); 412 | glShaderSource(shader, nsources, sources, srclens); 413 | glCompileShader(shader); 414 | 415 | glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 416 | 417 | if (!success) { 418 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); 419 | if (len > 1) { 420 | char *log; 421 | log = malloc(len); 422 | glGetShaderInfoLog(shader, len, NULL, log); 423 | fprintf(stderr, "%s\n\n", log); 424 | free(log); 425 | } 426 | SDL_Log("Error compiling shader.\n"); 427 | } 428 | SDL_Log("shader: %u",shader); 429 | 430 | return shader; 431 | } 432 | 433 | GLuint default_shaders(GLuint choice) 434 | { 435 | SDL_Log("choice def: %d", choice); 436 | GLuint vtx; 437 | vtx = default_vertex(); 438 | if (vtx==0) return 0; 439 | 440 | GLuint frag; 441 | const char *sources[4]; 442 | sources[0] = common_shader_header; 443 | sources[1] = fragment_shader_header; 444 | switch(choice) 445 | { 446 | case 0: 447 | sources[2] = default_fragment_shader_0; 448 | break; 449 | case 1: 450 | sources[2] = default_fragment_shader_1; 451 | break; 452 | case 2: 453 | sources[2] = default_fragment_shader; 454 | break; 455 | default: 456 | break; 457 | } 458 | 459 | sources[3] = fragment_shader_footer; 460 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 461 | 462 | shading_program_id[choice] = glCreateProgram(); 463 | glAttachShader(shading_program_id[choice], vtx); 464 | glAttachShader(shading_program_id[choice], frag); 465 | glLinkProgram(shading_program_id[choice]); 466 | 467 | //Error Checking 468 | GLuint status; 469 | status=program_check(shading_program_id[choice]); 470 | 471 | if (status==GL_FALSE) return 0; 472 | 473 | return shading_program_id[choice]; 474 | } 475 | 476 | 477 | GLuint default_vertex(void) 478 | { 479 | GLuint vtx; 480 | const char *sources[2]; 481 | sources[0] = common_shader_header; 482 | sources[1] = vertex_shader_body; 483 | vtx = compile_shader(GL_VERTEX_SHADER, 2, sources); 484 | return vtx; 485 | } 486 | 487 | GLuint program_check(GLuint program) 488 | { 489 | GLint status; 490 | glValidateProgram(program); 491 | glGetProgramiv(program, GL_LINK_STATUS, &status); 492 | if (!status){ 493 | GLint len; 494 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); 495 | if (len > 1){ 496 | char *log; 497 | log = malloc(len); 498 | glGetProgramInfoLog(program, len, &len, log); 499 | fprintf(stderr, "%s\n\n", log); 500 | free(log); 501 | } 502 | SDL_Log("Error linking shader default program.\n"); 503 | return GL_FALSE; 504 | } 505 | return GL_TRUE; 506 | } 507 | 508 | //END GPU PROGRAM CREATION 509 | 510 | void query_shadertoy_old_vars(GLuint choice) 511 | { 512 | sampler_channel[0] = glGetUniformLocation(shading_program_id[choice], "iChannel0"); 513 | sampler_channel[1] = glGetUniformLocation(shading_program_id[choice], "iChannel1"); 514 | sampler_channel[2] = glGetUniformLocation(shading_program_id[choice], "iChannel2"); 515 | sampler_channel[3] = glGetUniformLocation(shading_program_id[choice], "iChannel3"); 516 | uniform_cres = glGetUniformLocation(shading_program_id[choice], "iChannelResolution"); 517 | uniform_ctime = glGetUniformLocation(shading_program_id[choice], "iChannelTime"); 518 | uniform_itime = glGetUniformLocation(shading_program_id[choice], "iTime"); 519 | uniform_res = glGetUniformLocation(shading_program_id[choice], "iResolution"); 520 | uniform_srate = glGetUniformLocation(shading_program_id[choice], "iSampleRate"); 521 | } 522 | 523 | void query_vars(GLuint choice) 524 | { 525 | GLint i; 526 | GLint count; 527 | 528 | GLint size; 529 | GLenum type; 530 | 531 | const GLsizei bufSize = 16; 532 | GLchar name[bufSize]; 533 | GLsizei length; 534 | 535 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_ATTRIBUTES, &count); 536 | 537 | for (i = 0; i < count; i++){ 538 | glGetActiveAttrib(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 539 | if (!strcmp("iPosition",name)){ 540 | attrib_position = i; 541 | } 542 | } 543 | 544 | glGetProgramiv(shading_program_id[choice], GL_ACTIVE_UNIFORMS, &count); 545 | 546 | char global_time1[]="iTime"; 547 | char global_time2[]="iGlobalTime"; 548 | for (i = 0; i < count; i++){ 549 | glGetActiveUniform(shading_program_id[choice], (GLuint)i, bufSize, &length, &size, &type, name); 550 | 551 | SDL_Log("Uniform #%d Type: %u Name: %s\n", i, type, name); 552 | if (!strcmp(global_time1,name)||!strcmp(global_time2,name)){ 553 | uniform_gtime = i; 554 | } 555 | if (!strcmp("iMouse",name)) 556 | uniform_mouse = i; 557 | } 558 | } 559 | 560 | //BEGIN MISC 561 | 562 | float fTime(void) 563 | { 564 | static Uint64 start = 0; 565 | static Uint64 frequency = 0; 566 | 567 | if (start==0){ 568 | start = SDL_GetPerformanceCounter(); 569 | frequency = SDL_GetPerformanceFrequency(); 570 | return 0.0f; 571 | } 572 | Uint64 counter = SDL_GetPerformanceCounter(); 573 | Uint64 accumulate = counter - start; 574 | 575 | return (float)accumulate / (float)frequency; 576 | } 577 | 578 | void init_glew(void) 579 | { 580 | GLenum status; 581 | status = glewInit(); 582 | 583 | if (status != GLEW_OK){ 584 | SDL_Log("glewInit error: %s\n", glewGetErrorString (status)); 585 | Running = 0; 586 | } 587 | 588 | SDL_Log("\nGL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" 589 | "GLEW_VERSION : %s\nGLSL VERSION : %s\n", 590 | glGetString (GL_VERSION), glGetString (GL_VENDOR), 591 | glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), 592 | glGetString (GL_SHADING_LANGUAGE_VERSION)); 593 | 594 | int maj; 595 | int min; 596 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &maj); 597 | SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &min); 598 | SDL_Log("Using OpenGL %d.%d", maj, min); 599 | 600 | if (!GLEW_VERSION_3_0){ 601 | SDL_Log("At least OpenGL 3.0 with GLSL 1.30 required."); 602 | Running = 0; 603 | } 604 | } 605 | 606 | const char * read_file(const char *filename) 607 | { 608 | long length = 0; 609 | char *result = NULL; 610 | FILE *file = fopen(filename, "r"); 611 | if(file) { 612 | int status = fseek(file, 0, SEEK_END); 613 | if(status != 0) { 614 | fclose(file); 615 | return NULL; 616 | } 617 | length = ftell(file); 618 | status = fseek(file, 0, SEEK_SET); 619 | if(status != 0) { 620 | fclose(file); 621 | return NULL; 622 | } 623 | result = malloc((length+1) * sizeof(char)); 624 | if(result) { 625 | size_t actual_length = fread(result, sizeof(char), length , file); 626 | result[actual_length++] = '\0'; 627 | } 628 | fclose(file); 629 | return result; 630 | } 631 | SDL_LogError(SDL_LOG_CATEGORY_ERROR,"Couldn't read %s", filename); 632 | 633 | return NULL; 634 | } 635 | 636 | int write_STFS(void) 637 | { 638 | FILE *fp; 639 | fp = fopen( ""NEW_FILE , "w" ); 640 | fputs(default_fragment_shader_1, fp); 641 | SDL_Log("Shader written"); 642 | fclose(fp); 643 | NEW_SHADER=1; 644 | system(editor_call); 645 | switch_counter=0; 646 | shader_switch(); 647 | 648 | return(0); 649 | } 650 | 651 | struct epoll_event reset_poll(int halt) 652 | { 653 | static struct epoll_event ev; 654 | if (halt){ 655 | // release epoll 656 | // NOTE One can't rely on close to clean up epoll subscriptions. 657 | // NOTE One always must always explicitly call epoll_ctl(EPOLL_CTL_DEL) 658 | // before calling close(). 659 | epoll_ctl(efd, EPOLL_CTL_DEL, fd, &ev); 660 | close(efd); 661 | 662 | // release inotify 663 | inotify_rm_watch( fd, wd ); 664 | close(wd); 665 | close(fd); 666 | return ev; 667 | } 668 | 669 | fd = inotify_init(); 670 | wd = inotify_add_watch(fd, ""NEW_FILE, IN_CLOSE_WRITE); 671 | ev.events = EPOLLIN|EPOLLOUT|EPOLLONESHOT; 672 | efd = epoll_create(sizeof(fd)); 673 | epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev); 674 | return ev; 675 | } 676 | 677 | GLuint compile_STFS(void) 678 | { 679 | GLuint vtx; 680 | vtx = default_vertex(); 681 | if (vtx==0) 682 | return 0; 683 | 684 | GLuint frag; 685 | const char *sources[4]; 686 | sources[0] = common_shader_header; 687 | sources[1] = fragment_shader_header; 688 | sources[2] = read_file(""NEW_FILE); 689 | sources[3] = fragment_shader_footer; 690 | frag = compile_shader(GL_FRAGMENT_SHADER, 4, sources); 691 | 692 | shading_program_id[4] = glCreateProgram(); 693 | 694 | glAttachShader(shading_program_id[4], vtx); 695 | glAttachShader(shading_program_id[4], frag); 696 | 697 | glLinkProgram(shading_program_id[4]); 698 | 699 | GLuint status; 700 | status=program_check(shading_program_id[4]); 701 | 702 | if (status==GL_FALSE){ 703 | return 0; 704 | }else{ 705 | glUseProgram(shading_program_id[4]); 706 | SDL_Log("own_shading_program: %d", shading_program_id[4]); 707 | query_vars(4); 708 | query_shadertoy_old_vars(4); 709 | glEnableVertexAttribArray (attrib_position); 710 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 711 | 712 | glViewport (0, 0, ww, wh); 713 | glUniform3f(uniform_res, ww, wh, 0.0f); 714 | return 1; 715 | } 716 | } 717 | 718 | void shader_switch(void) 719 | { 720 | switch_counter++; 721 | if (switch_counter>(2+argument_provided)) switch_counter = 0; 722 | SDL_Log("switch_counter: %d", switch_counter); 723 | glUseProgram(shading_program_id[switch_counter]); 724 | query_vars(switch_counter); 725 | query_shadertoy_old_vars(switch_counter); 726 | glEnableVertexAttribArray (attrib_position); 727 | glVertexAttribPointer (attrib_position, 2, GL_FLOAT, GL_FALSE, 0, vertices); 728 | glUniform3f(uniform_res, (float)ww, (float)wh, 0.0f); 729 | glViewport (0, 0, ww, wh); 730 | } 731 | 732 | //END MISC 733 | 734 | //END FUNCTIONS 735 | -------------------------------------------------------------------------------- /.idea/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 65 | --------------------------------------------------------------------------------