├── .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 | 
37 |
38 | - `1a` - Draw rectangles
39 |
40 | 
41 |
42 | - `1b` - Rotate rectangles uniformly
43 |
44 | 
45 |
46 | - `1c` - Rotate rectangles individually
47 |
48 | 
49 |
50 | - `1d` - SGI Teapot Demo ported to SDL2 (**TBD**) - perhaps
51 |
52 |
53 | 
54 |
55 | - `1e` - SGI Atlantis Demo ported to SDL2 (**TBD**) - perhaps
56 |
57 |
58 | 
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 | 
72 |
73 | 
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 | 
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 |
--------------------------------------------------------------------------------