├── .gitignore ├── thumbnail.png ├── README.md ├── LICENSE └── main.pas /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | main.o -------------------------------------------------------------------------------- /thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rexim/freepascal-opengl-shaders/HEAD/thumbnail.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreePascal OpenGL Shaders Example 2 | 3 | ![thumbnail](./thumbnail.png) 4 | 5 | ## Quick Start 6 | 7 | Install [FPC](https://www.freepascal.org/) 8 | 9 | ```console 10 | $ fpc main.pas 11 | $ ./main 12 | ``` 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Alexey Kutepov 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /main.pas: -------------------------------------------------------------------------------- 1 | { -*- mode: opascal; opascal-indent-level: 4 -*- } 2 | program main; 3 | 4 | {$H+} 5 | 6 | uses 7 | GL, GLEXT, GLUT, Math; 8 | 9 | const 10 | CIRCLE_VERTEX_COUNT = 10; 11 | SCREEN_WIDTH = 800; 12 | SCREEN_HEIGHT = 600; 13 | 14 | procedure DisplayWindow; cdecl; 15 | begin 16 | glClearColor(0, 0, 0, 1); 17 | glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); 18 | 19 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 20 | 21 | glutSwapBuffers; 22 | end; 23 | 24 | function CompileShaderSource(ShaderType: GLenum; ShaderSource: PChar; var Shader: GLuint): Boolean; 25 | const 26 | INFO_LOG_CAPACITY = 1024; 27 | var 28 | Compiled : GLint; 29 | InfoLog : array[0 .. INFO_LOG_CAPACITY - 1] of GLchar; 30 | InfoLogLength : GLsizei; 31 | begin 32 | Shader := glCreateShader(ShaderType); 33 | glShaderSource(Shader, 1, @ShaderSource, nil); 34 | glCompileShader(Shader); 35 | glGetShaderiv(Shader, GL_COMPILE_STATUS, @Compiled); 36 | 37 | if not Boolean(Compiled) then 38 | begin 39 | glGetShaderInfoLog(Shader, INFO_LOG_CAPACITY, @InfoLogLength, @InfoLog); 40 | WriteLn(InfoLog); 41 | end; 42 | 43 | CompileShaderSource := Boolean(Compiled); 44 | end; 45 | 46 | function LinkShaderProgram(Shaders: array of GLuint; var ShaderProgram: GLuint): Boolean; 47 | const 48 | INFO_LOG_CAPACITY = 1024; 49 | var 50 | i : Integer; 51 | Linked: GLint; 52 | InfoLog : array[0 .. INFO_LOG_CAPACITY - 1] of GLchar; 53 | InfoLogLength : GLsizei; 54 | begin 55 | ShaderProgram := glCreateProgram(); 56 | for i := Low(Shaders) to High(Shaders) do 57 | glAttachShader(ShaderProgram, Shaders[i]); 58 | glLinkProgram(ShaderProgram); 59 | glGetProgramiv(ShaderProgram, GL_LINK_STATUS, @Linked); 60 | 61 | if not Boolean(Linked) then 62 | begin 63 | glGetProgramInfoLog(ShaderProgram, INFO_LOG_CAPACITY, @InfoLogLength, @InfoLog); 64 | WriteLn(InfoLog); 65 | end; 66 | 67 | LinkShaderProgram := Boolean(Linked); 68 | end; 69 | 70 | var 71 | Time: GLfloat = 0; 72 | UniformTime: GLint; 73 | UniformResolution: GLint; 74 | 75 | procedure OnTimer(value: LongInt); cdecl; 76 | begin 77 | glutPostRedisplay; 78 | Time := Time + 0.020; 79 | glUniform1f(UniformTime, Time); 80 | glutTimerFunc(20, @OnTimer, 0); 81 | end; 82 | 83 | var 84 | VertexShaderSource : PChar = 85 | '#version 300 es'#10 + 86 | 'precision mediump float;'#10 + 87 | 'uniform vec2 resolution;'#10 + 88 | ''#10 + 89 | 'out vec2 uv;'#10 + 90 | ''#10 + 91 | 'void main() {'#10 + 92 | ' float aspect = resolution.y / resolution.x;'#10 + 93 | ' float x = float(gl_VertexID & 1);'#10 + 94 | ' float y = float((gl_VertexID >> 1) & 1);'#10 + 95 | ' gl_Position = vec4((x - 0.5) * aspect, y - 0.5, 0.0, 1.0);'#10 + 96 | ' uv = vec2(x, y);'#10 + 97 | '}'#10 + 98 | ''; 99 | FragmentShaderSource : PChar = 100 | '#version 300 es'#10 + 101 | 'precision mediump float;'#10 + 102 | ''#10 + 103 | 'uniform float time;'#10 + 104 | ''#10 + 105 | 'in vec2 uv;'#10 + 106 | 'out vec4 output_color;'#10 + 107 | ''#10 + 108 | 'void main() {'#10 + 109 | ' float radius = (sin(time) + 1.0) / 4.0;'#10 + 110 | ' float r = (sin(uv.x + time) + 1.0) / 2.0;'#10 + 111 | ' float g = (cos(uv.y + time) + 1.0) / 2.0;'#10 + 112 | ' float b = (cos(uv.x + time + 0.5) + 1.0) / 2.0;'#10 + 113 | ' float d = length(uv - vec2(0.5, 0.5));'#10 + 114 | ' output_color = d <= radius ? vec4(r, g, b, 1.0) : vec4(0.0);'#10 + 115 | '}'#10 + 116 | ''; 117 | Shaders: array [0..1] of GLuint; 118 | ShaderProgram: GLuint; 119 | 120 | procedure OnReshape(WindowWidth, WindowHeight: LongInt); cdecl; 121 | var 122 | ViewWidth : Single; 123 | ViewHeight : Single; 124 | begin 125 | ViewWidth := Single(WindowWidth); 126 | ViewHeight := Single(WindowWidth) * (Single(SCREEN_HEIGHT) / Single(SCREEN_WIDTH)); 127 | 128 | if (ViewHeight > WindowHeight) then 129 | begin 130 | ViewHeight := WindowHeight; 131 | ViewWidth := WindowHeight * (Single(SCREEN_WIDTH) / Single(SCREEN_HEIGHT)); 132 | end; 133 | 134 | glViewport( 135 | Floor(Single(WindowWidth) * 0.5 - ViewWidth * 0.5), 136 | Floor(Single(WindowHeight) * 0.5 - ViewHeight * 0.5), 137 | Floor(ViewWidth), 138 | Floor(ViewHeight)); 139 | 140 | glUniform2f(UniformResolution, Single(SCREEN_WIDTH), Single(SCREEN_HEIGHT)); 141 | end; 142 | 143 | begin 144 | glutInit(@argc, argv); 145 | glutInitDisplayMode(GLUT_RGB or GLUT_DOUBLE or GLUT_DEPTH); 146 | glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT); 147 | glutCreateWindow('Pascalik'); 148 | glutDisplayFunc(@DisplayWindow); 149 | glutTimerFunc(20, @OnTimer, 0); 150 | glutReshapeFunc(@OnReshape); 151 | 152 | Load_GL_VERSION_3_0(); 153 | 154 | glEnable(GL_BLEND); 155 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 156 | 157 | WriteLn; 158 | WriteLn('GL info:'); 159 | WriteLn(' Vendor: ', glGetString(GL_VENDOR)); 160 | WriteLn(' Renderer: ', glGetString(GL_RENDERER)); 161 | WriteLn(' Version: ', glGetString(GL_VERSION)); 162 | // WriteLn(' Extensions: ', glGetString(GL_EXTENSIONS)); 163 | 164 | if CompileShaderSource(GL_VERTEX_SHADER, VertexShaderSource, Shaders[0]) then 165 | WriteLn('Successfully compiled vertex shader') 166 | else 167 | WriteLn('ERROR: Failed to compile vertex shader'); 168 | 169 | if CompileShaderSource(GL_FRAGMENT_SHADER, FragmentShaderSource, Shaders[1]) then 170 | WriteLn('Successfully compiled fragment shader') 171 | else 172 | WriteLn('ERROR: Failed to compile fragment shader'); 173 | 174 | if LinkShaderProgram(Shaders, ShaderProgram) then 175 | WriteLn('Successfully linked the shader program') 176 | else 177 | WriteLn('ERROR: Failed to link the shader program'); 178 | 179 | UniformTime := glGetUniformLocation(ShaderProgram, 'time'); 180 | UniformResolution := glGetUniformLocation(ShaderProgram, 'resolution'); 181 | 182 | glUniform1f(UniformTime, Time); 183 | glUniform2f(UniformResolution, Single(SCREEN_WIDTH), Single(SCREEN_HEIGHT)); 184 | 185 | glUseProgram(ShaderProgram); 186 | 187 | glutMainLoop; 188 | end. 189 | --------------------------------------------------------------------------------