├── LICENSE ├── Makefile ├── build └── vc │ ├── SDL2GLSL.sln │ ├── SDL2GLSL.vcxproj │ └── SDL2GLSL.vcxproj.filters ├── ext ├── bin │ ├── x64 │ │ └── README.txt │ └── x86 │ │ └── README.txt ├── include │ └── SDL2 │ │ └── README.txt └── lib │ ├── x64 │ └── README.txt │ └── x86 │ └── README.txt ├── include └── main.h ├── res ├── README_ryu.txt ├── crt.fragment ├── crt.uwol.fragment ├── image.png └── std.vertex └── src └── main.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Augusto Ruiz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | INCDIR=include 2 | SRCDIR=src 3 | OBJDIR=obj 4 | BINDIR=bin 5 | LIBDIR=lib 6 | MKDIR=mkdir 7 | 8 | UNAME_S = $(shell uname -s) 9 | 10 | USE_SDL_FROM_BREW?=false 11 | 12 | CXX=g++ 13 | ifeq (${UNAME_S},Darwin) 14 | ifneq (${USE_SDL_FROM_BREW},false) 15 | CXXFLAGS=-std=c++11 -F/Library/Frameworks -O3 -Werror -Wall -fsigned-char `sdl2-config --cflags` -mmacosx-version-min=10.7 -stdlib=libc++ -pedantic-errors 16 | LDFLAGS=-std=c++11 -O3 -Werror -Wall -fsigned-char -mmacosx-version-min=10.7 -stdlib=libc++ -F/Library/Frameworks 17 | LDLIBS=-L/usr/local/lib `sdl2-config --libs` -lSDL2_image -lm -framework OpenGL -framework CoreFoundation 18 | else 19 | CXXFLAGS=-std=c++11 -F/Library/Frameworks -I/Library/Frameworks/SDL2.framework/Headers -I/Library/Frameworks/SDL2_image.framework/Headers -O3 -Werror -Wall -fsigned-char -mmacosx-version-min=10.7 -stdlib=libc++ -pedantic-errors 20 | LDFLAGS=-std=c++11 -O3 -Werror -Wall -fsigned-char -mmacosx-version-min=10.7 -stdlib=libc++ -F/Library/Frameworks 21 | LDLIBS=-L/usr/local/lib -lm -framework OpenGL -framework SDL2 -framework SDL2_image -framework CoreFoundation 22 | endif 23 | else 24 | CXXFLAGS=-std=c++11 -D_GNU_SOURCE=1 -D_THREAD_SAFE -Werror -Wall -fsigned-char `sdl2-config --cflags` 25 | LDLIBS=-L/usr/local/lib `sdl2-config --libs` -lSDL2_image -lGL 26 | LDFLAGS= 27 | endif 28 | 29 | vpath %.h $(INCDIR) 30 | vpath %.cpp $(SRCDIR) 31 | vpath %.cc $(SRCDIR) 32 | vpath %.o $(OBJDIR) 33 | 34 | HEADERS = $(shell find $(INCDIR)) 35 | INCLUDES = $(sort $(addprefix -I,$(dir $(HEADERS)))) 36 | SRCS = $(shell find $(SRCDIR) -name *.cc) $(shell find $(SRCDIR) -name *.cpp) 37 | OBJS = $(patsubst $(SRCDIR)%,$(OBJDIR)%,$(patsubst %.cc,%.o,$(patsubst %.cpp,%.o,$(SRCS)))) 38 | APPNAME = $(BINDIR)/testSdl2 39 | 40 | all: createFolders $(APPNAME) 41 | 42 | $(APPNAME): $(OBJS) resources 43 | $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) -v 44 | 45 | $(OBJDIR)/%.o: %.cc 46 | $(MKDIR) -p $(dir $@) 47 | $(CXX) $(CXXFLAGS) -o $@ -c $(INCLUDES) $< 48 | 49 | $(OBJDIR)/%.o: %.cpp 50 | $(MKDIR) -p $(dir $@) 51 | $(CXX) $(CXXFLAGS) -o $@ -c $(INCLUDES) $< 52 | 53 | createFolders: 54 | $(MKDIR) -p $(BINDIR) 55 | 56 | resources: 57 | cp res/* bin 58 | 59 | clean: 60 | $(RM) -rf $(OBJDIR) 61 | 62 | cleanall: clean 63 | $(RM) $(APPNAME) 64 | -------------------------------------------------------------------------------- /build/vc/SDL2GLSL.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.7 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2GLSL", "SDL2GLSL.vcxproj", "{67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Debug|x64.ActiveCfg = Debug|x64 17 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Debug|x64.Build.0 = Debug|x64 18 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Debug|x86.ActiveCfg = Debug|Win32 19 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Debug|x86.Build.0 = Debug|Win32 20 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Release|x64.ActiveCfg = Release|x64 21 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Release|x64.Build.0 = Release|x64 22 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Release|x86.ActiveCfg = Release|Win32 23 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /build/vc/SDL2GLSL.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {67F2DA5F-F108-4BA7-B2AB-958EBE7B946A} 24 | Win32Proj 25 | 10.0.10586.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | 33 | 34 | Application 35 | false 36 | v141 37 | 38 | 39 | Application 40 | true 41 | v141 42 | 43 | 44 | Application 45 | false 46 | v141 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | true 68 | 69 | 70 | true 71 | 72 | 73 | 74 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 75 | $(ProjectDir)..\..\include;$(ProjectDir)..\..\ext\include;$(ProjectDir)..\..\ext\include\SDL2;$(ProjectDir)..\..\ext\include\SDL2_image;%(AdditionalIncludeDirectories) 76 | MultiThreadedDebugDLL 77 | Level3 78 | ProgramDatabase 79 | Disabled 80 | 81 | 82 | MachineX86 83 | true 84 | Windows 85 | $(ProjectDir)..\..\ext\lib\x86 86 | SDL2.lib;SDL2main.lib;SDL2_image.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 87 | 88 | 89 | 90 | 91 | 92 | 93 | copy $(ProjectDir)..\..\ext\bin\$(PlatformShortName)\* $(OutDir) 94 | copy $(ProjectDir)..\..\res\* $(OutDir) 95 | 96 | 97 | Copying external libraries... 98 | 99 | 100 | 101 | 102 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 103 | $(ProjectDir)..\..\include;$(ProjectDir)..\..\ext\include;$(ProjectDir)..\..\ext\include\SDL2;$(ProjectDir)..\..\ext\include\SDL2_image;%(AdditionalIncludeDirectories) 104 | MultiThreadedDLL 105 | Level3 106 | ProgramDatabase 107 | 108 | 109 | MachineX86 110 | true 111 | Windows 112 | true 113 | true 114 | $(ProjectDir)..\..\ext\lib\x86 115 | SDL2.lib;SDL2main.lib;SDL2_image.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 116 | 117 | 118 | 119 | 120 | 121 | 122 | copy $(ProjectDir)..\..\ext\bin\$(PlatformShortName)\* $(OutDir) 123 | copy $(ProjectDir)..\..\res\* $(OutDir) 124 | 125 | 126 | Copying external libraries... 127 | 128 | 129 | 130 | 131 | $(ProjectDir)..\..\include;$(ProjectDir)..\..\ext\include;$(ProjectDir)..\..\ext\include\SDL2;$(ProjectDir)..\..\ext\include\SDL2_image;%(AdditionalIncludeDirectories) 132 | 133 | 134 | $(ProjectDir)..\..\ext\lib\x64 135 | SDL2.lib;SDL2main.lib;SDL2_image.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 136 | Windows 137 | 138 | 139 | 140 | 141 | 142 | 143 | copy $(ProjectDir)..\..\ext\bin\$(PlatformShortName)\* $(OutDir) 144 | copy $(ProjectDir)..\..\res\* $(OutDir) 145 | 146 | 147 | Copying external libraries... 148 | 149 | 150 | 151 | 152 | $(ProjectDir)..\..\include;$(ProjectDir)..\..\ext\include;$(ProjectDir)..\..\ext\include\SDL2;$(ProjectDir)..\..\ext\include\SDL2_image;%(AdditionalIncludeDirectories) 153 | 154 | 155 | $(ProjectDir)..\..\ext\lib\x64 156 | SDL2.lib;SDL2main.lib;SDL2_image.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 157 | Windows 158 | 159 | 160 | 161 | 162 | 163 | 164 | copy $(ProjectDir)..\..\ext\bin\$(PlatformShortName)\* $(OutDir) 165 | copy $(ProjectDir)..\..\res\* $(OutDir) 166 | 167 | 168 | Copying external libraries... 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | true 180 | 181 | 182 | 183 | true 184 | 185 | 186 | 187 | 188 | true 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /build/vc/SDL2GLSL.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | 29 | Resource Files 30 | 31 | 32 | Resource Files 33 | 34 | 35 | Resource Files 36 | 37 | 38 | 39 | 40 | Resource Files 41 | 42 | 43 | -------------------------------------------------------------------------------- /ext/bin/x64/README.txt: -------------------------------------------------------------------------------- 1 | Place here .dll files for 64-bit... 2 | -------------------------------------------------------------------------------- /ext/bin/x86/README.txt: -------------------------------------------------------------------------------- 1 | Place here .dll files for 32-bit... 2 | -------------------------------------------------------------------------------- /ext/include/SDL2/README.txt: -------------------------------------------------------------------------------- 1 | Place here SDL2 include files... 2 | -------------------------------------------------------------------------------- /ext/lib/x64/README.txt: -------------------------------------------------------------------------------- 1 | Place here .lib files for 64-bit... 2 | -------------------------------------------------------------------------------- /ext/lib/x86/README.txt: -------------------------------------------------------------------------------- 1 | Place here .lib files for 32-bit... 2 | -------------------------------------------------------------------------------- /include/main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #ifdef __APPLE__ 9 | #include "CoreFoundation/CoreFoundation.h" 10 | #include 11 | 12 | #if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 13 | #include 14 | #else 15 | #include 16 | #endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 17 | #else 18 | #include 19 | #include 20 | #endif 21 | -------------------------------------------------------------------------------- /res/README_ryu.txt: -------------------------------------------------------------------------------- 1 | Ryu image (c) dollarcube@gmail.com. -------------------------------------------------------------------------------- /res/crt.fragment: -------------------------------------------------------------------------------- 1 | // 2 | // PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER 3 | // 4 | // by Timothy Lottes 5 | // 6 | // This is more along the style of a really good CGA arcade monitor. 7 | // With RGB inputs instead of NTSC. 8 | // The shadow mask example has the mask rotated 90 degrees for less chromatic aberration. 9 | // 10 | // Left it unoptimized to show the theory behind the algorithm. 11 | // 12 | // It is an example what I personally would want as a display option for pixel art games. 13 | // Please take and use, change, or whatever. 14 | // 15 | 16 | varying vec4 v_color; 17 | varying vec2 v_texCoord; 18 | 19 | uniform sampler2D tex0; 20 | 21 | // Hardness of scanline. 22 | // -8.0 = soft 23 | // -16.0 = medium 24 | float hardScan=-8.0; 25 | 26 | // Hardness of pixels in scanline. 27 | // -2.0 = soft 28 | // -4.0 = hard 29 | float hardPix=-2.0; 30 | 31 | // Display warp. 32 | // 0.0 = none 33 | // 1.0/8.0 = extreme 34 | vec2 warp=vec2(1.0/32.0,1.0/24.0); 35 | 36 | // Amount of shadow mask. 37 | float maskDark=1.0; 38 | float maskLight=1.5; 39 | 40 | vec2 res = vec2(640.0,480.0); // /3.0 41 | 42 | //------------------------------------------------------------------------ 43 | 44 | // sRGB to Linear. 45 | // Assuing using sRGB typed textures this should not be needed. 46 | float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);} 47 | vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));} 48 | 49 | // Linear to sRGB. 50 | // Assuing using sRGB typed textures this should not be needed. 51 | float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);} 52 | vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));} 53 | 54 | // Nearest emulated sample given floating point position and texel offset. 55 | // Also zero's off screen. 56 | vec3 Fetch(vec2 pos,vec2 off){ 57 | pos=floor(pos*res+off)/res; 58 | if(max(abs(pos.x-0.5),abs(pos.y-0.5))>0.5)return vec3(0.0,0.0,0.0); 59 | return ToLinear(texture2D(tex0,pos.xy,-16.0).rgb);} 60 | 61 | // Distance in emulated pixels to nearest texel. 62 | vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));} 63 | 64 | // 1D Gaussian. 65 | float Gaus(float pos,float scale){return exp2(scale*pos*pos);} 66 | 67 | // 3-tap Gaussian filter along horz line. 68 | vec3 Horz3(vec2 pos,float off){ 69 | vec3 b=Fetch(pos,vec2(-1.0,off)); 70 | vec3 c=Fetch(pos,vec2( 0.0,off)); 71 | vec3 d=Fetch(pos,vec2( 1.0,off)); 72 | float dst=Dist(pos).x; 73 | // Convert distance to weight. 74 | float scale=hardPix; 75 | float wb=Gaus(dst-1.0,scale); 76 | float wc=Gaus(dst+0.0,scale); 77 | float wd=Gaus(dst+1.0,scale); 78 | // Return filtered sample. 79 | return (b*wb+c*wc+d*wd)/(wb+wc+wd);} 80 | 81 | // 5-tap Gaussian filter along horz line. 82 | vec3 Horz5(vec2 pos,float off){ 83 | vec3 a=Fetch(pos,vec2(-2.0,off)); 84 | vec3 b=Fetch(pos,vec2(-1.0,off)); 85 | vec3 c=Fetch(pos,vec2( 0.0,off)); 86 | vec3 d=Fetch(pos,vec2( 1.0,off)); 87 | vec3 e=Fetch(pos,vec2( 2.0,off)); 88 | float dst=Dist(pos).x; 89 | // Convert distance to weight. 90 | float scale=hardPix; 91 | float wa=Gaus(dst-2.0,scale); 92 | float wb=Gaus(dst-1.0,scale); 93 | float wc=Gaus(dst+0.0,scale); 94 | float wd=Gaus(dst+1.0,scale); 95 | float we=Gaus(dst+2.0,scale); 96 | // Return filtered sample. 97 | return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);} 98 | 99 | // Return scanline weight. 100 | float Scan(vec2 pos,float off){ 101 | float dst=Dist(pos).y; 102 | return Gaus(dst+off,hardScan);} 103 | 104 | // Allow nearest three lines to effect pixel. 105 | vec3 Tri(vec2 pos){ 106 | vec3 a=Horz3(pos,-1.0); 107 | vec3 b=Horz5(pos, 0.0); 108 | vec3 c=Horz3(pos, 1.0); 109 | float wa=Scan(pos,-1.0); 110 | float wb=Scan(pos, 0.0); 111 | float wc=Scan(pos, 1.0); 112 | return a*wa+b*wb+c*wc;} 113 | 114 | // Distortion of scanlines, and end of screen alpha. 115 | vec2 Warp(vec2 pos){ 116 | pos=pos*2.0-1.0; 117 | pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y); 118 | return pos*0.5+0.5;} 119 | 120 | // Shadow mask. 121 | vec3 Mask(vec2 pos){ 122 | pos.x+=pos.y*3.0; 123 | vec3 mask=vec3(maskDark,maskDark,maskDark); 124 | pos.x=fract(pos.x/6.0); 125 | if(pos.x<0.333)mask.r=maskLight; 126 | else if(pos.x<0.666)mask.g=maskLight; 127 | else mask.b=maskLight; 128 | return mask;} 129 | 130 | // Draw dividing bars. 131 | float Bar(float pos,float bar){pos-=bar;return pos*pos<4.0?0.0:1.0;} 132 | 133 | // Entry. 134 | void main(){ 135 | // Unmodified. 136 | vec2 pos=Warp(v_texCoord); 137 | vec4 fragColor; 138 | fragColor.rgb=Tri(pos)*Mask(gl_FragCoord.xy); 139 | fragColor.rgb=ToSrgb(fragColor.rgb); 140 | gl_FragColor=v_color * vec4(fragColor.rgb, 1.0); 141 | } 142 | 143 | -------------------------------------------------------------------------------- /res/crt.uwol.fragment: -------------------------------------------------------------------------------- 1 | varying vec4 v_color; 2 | varying vec2 v_texCoord; 3 | 4 | uniform sampler2D tex0; 5 | 6 | // Hardness of scanline. 7 | // -8.0 = soft 8 | // -16.0 = medium 9 | float hardScan=-8.0; 10 | 11 | // Hardness of pixels in scanline. 12 | // -2.0 = soft 13 | // -4.0 = hard 14 | float hardPix=-3.0; 15 | 16 | // Display warp. 17 | // 0.0 = none 18 | // 1.0/8.0 = extreme 19 | vec2 warp = vec2(1.0/32.0, 1.0/24.0); 20 | 21 | // Amount of shadow mask. 22 | float maskDark=0.5; 23 | float maskLight=1.5; 24 | 25 | vec2 iResolution = vec2(640.0,480.0); 26 | 27 | //------------------------------------------------------------------------ 28 | // sRGB to Linear. 29 | // Assuing using sRGB typed textures this should not be needed. 30 | float ToLinear1(float c){return(c<=0.04045)?c/12.92:pow((c+0.055)/1.055,2.4);} 31 | vec3 ToLinear(vec3 c){return vec3(ToLinear1(c.r),ToLinear1(c.g),ToLinear1(c.b));} 32 | 33 | // Linear to sRGB. 34 | // Assuing using sRGB typed textures this should not be needed. 35 | float ToSrgb1(float c){return(c<0.0031308?c*12.92:1.055*pow(c,0.41666)-0.055);} 36 | vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));} 37 | 38 | // Nearest emulated sample given floating point position and texel offset. 39 | // Also zero's off screen. 40 | vec3 Fetch(vec2 pos,vec2 off){ 41 | vec3 result; 42 | pos = (floor(pos*iResolution + off) + vec2(0.5,0.5))/iResolution; 43 | result = ToLinear(1.2 * texture2D(tex0 , pos.xy, -16.0).rgb); 44 | return result; 45 | } 46 | 47 | // Distance in emulated pixels to nearest texel. 48 | vec2 Dist(vec2 pos){pos=pos*iResolution;return -((pos-floor(pos))-vec2(0.5));} 49 | // 1D Gaussian. 50 | float Gaus(float pos,float scale){return exp2(scale*pos*pos);} 51 | 52 | // 3-tap Gaussian filter along horz line. 53 | vec3 Horz3(vec2 pos,float off){ 54 | vec3 b=Fetch(pos,vec2(-1.0,off)); 55 | vec3 c=Fetch(pos,vec2( 0.0,off)); 56 | vec3 d=Fetch(pos,vec2( 1.0,off)); 57 | float dst=Dist(pos).x; 58 | // Convert distance to weight. 59 | float scale=hardPix; 60 | float wb=Gaus(dst-1.0,scale); 61 | float wc=Gaus(dst+0.0,scale); 62 | float wd=Gaus(dst+1.0,scale); 63 | // Return filtered sample. 64 | return (b*wb+c*wc+d*wd)/(wb+wc+wd); 65 | } 66 | 67 | // 5-tap Gaussian filter along horz line. 68 | vec3 Horz5(vec2 pos,float off){ 69 | vec3 a=Fetch(pos,vec2(-2.0,off)); 70 | vec3 b=Fetch(pos,vec2(-1.0,off)); 71 | vec3 c=Fetch(pos,vec2( 0.0,off)); 72 | vec3 d=Fetch(pos,vec2( 1.0,off)); 73 | vec3 e=Fetch(pos,vec2( 2.0,off)); 74 | float dst=Dist(pos).x; 75 | // Convert distance to weight. 76 | float scale=hardPix; 77 | float wa=Gaus(dst-2.0,scale); 78 | float wb=Gaus(dst-1.0,scale); 79 | float wc=Gaus(dst+0.0,scale); 80 | float wd=Gaus(dst+1.0,scale); 81 | float we=Gaus(dst+2.0,scale); 82 | // Return filtered sample. 83 | return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we); 84 | } 85 | 86 | // Return scanline weight. 87 | float Scan(vec2 pos,float off){ 88 | float dst=Dist(pos).y; 89 | return Gaus(dst+off,hardScan); 90 | } 91 | 92 | // Allow nearest three lines to effect pixel. 93 | vec3 Tri(vec2 pos){ 94 | vec3 a=Horz3(pos,-1.0); 95 | vec3 b=Horz5(pos, 0.0); 96 | vec3 c=Horz3(pos, 1.0); 97 | float wa=Scan(pos,-1.0); 98 | float wb=Scan(pos, 0.0); 99 | float wc=Scan(pos, 1.0); 100 | return a*wa + b*wb + c*wc; 101 | } 102 | 103 | // Distortion of scanlines, and end of screen alpha. 104 | vec2 Warp(vec2 pos){ 105 | pos = pos*2.0-1.0; 106 | pos *= vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y); 107 | return pos*0.5+0.5; 108 | } 109 | 110 | vec3 Mask(vec2 pos) { 111 | pos.x+=pos.y*3.0; 112 | vec3 mask=vec3(maskDark,maskDark,maskDark); 113 | pos.x=fract(pos.x/6.0); 114 | if(pos.x<0.333)mask.r=maskLight; 115 | else if(pos.x<0.666)mask.g=maskLight; 116 | else mask.b=maskLight; 117 | return mask; 118 | } 119 | 120 | void main() 121 | { 122 | vec2 pos = Warp(v_texCoord); 123 | vec4 result; 124 | result.rgb = Tri(pos) * Mask(gl_FragCoord.xy); 125 | gl_FragColor = v_color * vec4(ToSrgb(result.rgb), 1.0); 126 | } 127 | -------------------------------------------------------------------------------- /res/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustoRuiz/sdl2glsl/94afb548170cd30fe8400b89f7cddb1ab6866040/res/image.png -------------------------------------------------------------------------------- /res/std.vertex: -------------------------------------------------------------------------------- 1 | varying vec4 v_color; 2 | varying vec2 v_texCoord; 3 | 4 | void main() 5 | { 6 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 7 | v_color = gl_Color; 8 | v_texCoord = vec2(gl_MultiTexCoord0); 9 | } 10 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "main.h" 4 | 5 | const int WIN_WIDTH = 640; 6 | const int WIN_HEIGHT = 480; 7 | 8 | const int WORLD_WIDTH = 320; 9 | const int WORLD_HEIGHT = 240; 10 | 11 | struct sprite { 12 | float x; 13 | float y; 14 | float vx; 15 | float vy; 16 | }; 17 | 18 | const int MAX_SPRITES = 20; 19 | 20 | #ifndef __APPLE__ 21 | 22 | // I'm avoiding the use of GLEW or some extensions handler, but that 23 | // doesn't mean you should... 24 | PFNGLCREATESHADERPROC glCreateShader; 25 | PFNGLSHADERSOURCEPROC glShaderSource; 26 | PFNGLCOMPILESHADERPROC glCompileShader; 27 | PFNGLGETSHADERIVPROC glGetShaderiv; 28 | PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; 29 | PFNGLDELETESHADERPROC glDeleteShader; 30 | PFNGLATTACHSHADERPROC glAttachShader; 31 | PFNGLCREATEPROGRAMPROC glCreateProgram; 32 | PFNGLLINKPROGRAMPROC glLinkProgram; 33 | PFNGLVALIDATEPROGRAMPROC glValidateProgram; 34 | PFNGLGETPROGRAMIVPROC glGetProgramiv; 35 | PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; 36 | PFNGLUSEPROGRAMPROC glUseProgram; 37 | 38 | bool initGLExtensions() { 39 | glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"); 40 | glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"); 41 | glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"); 42 | glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv"); 43 | glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog"); 44 | glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader"); 45 | glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader"); 46 | glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram"); 47 | glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram"); 48 | glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram"); 49 | glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv"); 50 | glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog"); 51 | glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"); 52 | 53 | return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv && 54 | glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram && 55 | glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog && 56 | glUseProgram; 57 | } 58 | 59 | #endif 60 | 61 | GLuint compileShader(const char* source, GLuint shaderType) { 62 | std::cout << "Compilando shader:" << std::endl << source << std::endl; 63 | // Create ID for shader 64 | GLuint result = glCreateShader(shaderType); 65 | // Define shader text 66 | glShaderSource(result, 1, &source, NULL); 67 | // Compile shader 68 | glCompileShader(result); 69 | 70 | //Check vertex shader for errors 71 | GLint shaderCompiled = GL_FALSE; 72 | glGetShaderiv( result, GL_COMPILE_STATUS, &shaderCompiled ); 73 | if( shaderCompiled != GL_TRUE ) { 74 | std::cout << "Error en la compilación: " << result << "!" << std::endl; 75 | GLint logLength; 76 | glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength); 77 | if (logLength > 0) 78 | { 79 | GLchar *log = (GLchar*)malloc(logLength); 80 | glGetShaderInfoLog(result, logLength, &logLength, log); 81 | std::cout << "Shader compile log:" << log << std::endl; 82 | free(log); 83 | } 84 | glDeleteShader(result); 85 | result = 0; 86 | } else { 87 | std::cout << "Shader compilado correctamente. Id = " << result << std::endl; 88 | } 89 | return result; 90 | } 91 | 92 | GLuint compileProgram(const char* vtxFile, const char* fragFile) { 93 | GLuint programId = 0; 94 | GLuint vtxShaderId, fragShaderId; 95 | 96 | programId = glCreateProgram(); 97 | 98 | std::ifstream f(vtxFile); 99 | std::string source((std::istreambuf_iterator(f)), 100 | std::istreambuf_iterator()); 101 | vtxShaderId = compileShader(source.c_str(), GL_VERTEX_SHADER); 102 | 103 | f=std::ifstream(fragFile); 104 | source=std::string((std::istreambuf_iterator(f)), 105 | std::istreambuf_iterator()); 106 | fragShaderId = compileShader(source.c_str(), GL_FRAGMENT_SHADER); 107 | 108 | if(vtxShaderId && fragShaderId) { 109 | // Associate shader with program 110 | glAttachShader(programId, vtxShaderId); 111 | glAttachShader(programId, fragShaderId); 112 | glLinkProgram(programId); 113 | glValidateProgram(programId); 114 | 115 | // Check the status of the compile/link 116 | GLint logLen; 117 | glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen); 118 | if(logLen > 0) { 119 | char* log = (char*) malloc(logLen * sizeof(char)); 120 | // Show any errors as appropriate 121 | glGetProgramInfoLog(programId, logLen, &logLen, log); 122 | std::cout << "Prog Info Log: " << std::endl << log << std::endl; 123 | free(log); 124 | } 125 | } 126 | if(vtxShaderId) { 127 | glDeleteShader(vtxShaderId); 128 | } 129 | if(fragShaderId) { 130 | glDeleteShader(fragShaderId); 131 | } 132 | return programId; 133 | } 134 | 135 | void presentBackBuffer(SDL_Renderer *renderer, SDL_Window* win, SDL_Texture* backBuffer, GLuint programId) { 136 | GLint oldProgramId; 137 | // Guarrada para obtener el textureid (en driverdata->texture) 138 | //Detach the texture 139 | SDL_SetRenderTarget(renderer, NULL); 140 | SDL_RenderClear(renderer); 141 | 142 | SDL_GL_BindTexture(backBuffer, NULL, NULL); 143 | if(programId != 0) { 144 | glGetIntegerv(GL_CURRENT_PROGRAM,&oldProgramId); 145 | glUseProgram(programId); 146 | } 147 | 148 | GLfloat minx, miny, maxx, maxy; 149 | GLfloat minu, maxu, minv, maxv; 150 | 151 | // Coordenadas de la ventana donde pintar. 152 | minx = 0.0f; 153 | miny = 0.0f; 154 | maxx = WIN_WIDTH; 155 | maxy = WIN_HEIGHT; 156 | 157 | minu = 0.0f; 158 | maxu = 1.0f; 159 | minv = 0.0f; 160 | maxv = 1.0f; 161 | 162 | glBegin(GL_TRIANGLE_STRIP); 163 | glTexCoord2f(minu, minv); 164 | glVertex2f(minx, miny); 165 | glTexCoord2f(maxu, minv); 166 | glVertex2f(maxx, miny); 167 | glTexCoord2f(minu, maxv); 168 | glVertex2f(minx, maxy); 169 | glTexCoord2f(maxu, maxv); 170 | glVertex2f(maxx, maxy); 171 | glEnd(); 172 | SDL_GL_SwapWindow(win); 173 | 174 | if(programId != 0) { 175 | glUseProgram(oldProgramId); 176 | } 177 | } 178 | 179 | #ifdef __APPLE__ 180 | void initializeFileSystem() { 181 | CFBundleRef mainBundle = CFBundleGetMainBundle(); 182 | CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); 183 | char path[PATH_MAX]; 184 | if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)) 185 | { 186 | std::cerr << "Couldn't get file system representation! " << std::endl; 187 | } 188 | CFRelease(resourcesURL); 189 | chdir(path); 190 | } 191 | #endif 192 | 193 | int main(int argc, char **argv){ 194 | GLuint programId; 195 | 196 | #ifdef __APPLE__ 197 | initializeFileSystem(); 198 | #endif 199 | 200 | if (SDL_Init(SDL_INIT_EVERYTHING | SDL_VIDEO_OPENGL) != 0){ 201 | std::cerr << "SDL_Init failed: " << SDL_GetError() << "\n"; 202 | return 1; 203 | } 204 | 205 | SDL_Window *win = SDL_CreateWindow("Custom shader with SDL2 renderer!", SDL_WINDOWPOS_CENTERED, 206 | SDL_WINDOWPOS_CENTERED, WIN_WIDTH, WIN_HEIGHT, 0); 207 | 208 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); 209 | 210 | SDL_Renderer *renderer = SDL_CreateRenderer(win, -1, 211 | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); 212 | 213 | SDL_RendererInfo rendererInfo; 214 | SDL_GetRendererInfo(renderer, &rendererInfo); 215 | 216 | if(!strncmp(rendererInfo.name, "opengl", 6)) { 217 | std::cout << "Es OpenGL!" << std::endl; 218 | #ifndef __APPLE__ 219 | // If you want to use GLEW or some other GL extension handler, do it here! 220 | if (!initGLExtensions()) { 221 | std::cout << "Couldn't init GL extensions!" << std::endl; 222 | SDL_Quit(); 223 | exit(-1); 224 | } 225 | #endif 226 | // Compilar el shader y dejarlo listo para usar. 227 | programId = compileProgram("std.vertex", "crt.fragment"); 228 | std::cout << "programId = " << programId << std::endl; 229 | } 230 | 231 | //Put your own bmp image here 232 | SDL_Surface *bmpSurf = IMG_Load("image.png"); 233 | SDL_Texture *bmpTex = SDL_CreateTextureFromSurface(renderer, bmpSurf); 234 | SDL_FreeSurface(bmpSurf); 235 | 236 | //Make a target texture to render too 237 | SDL_Texture *texTarget = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, 238 | SDL_TEXTUREACCESS_TARGET, WORLD_WIDTH, WORLD_HEIGHT); 239 | 240 | int done = 0; 241 | int useShader = 0; 242 | SDL_Rect targetRect; 243 | 244 | targetRect.x = 0; targetRect.y=0; targetRect.w=32; targetRect.h=32; 245 | 246 | struct sprite sprites[MAX_SPRITES]; 247 | 248 | for(int i=0;i < MAX_SPRITES;++i) { 249 | sprites[i].x = (float) (rand() % (WORLD_WIDTH - targetRect.w)); 250 | sprites[i].y = (float) (rand() % (WORLD_HEIGHT - targetRect.h)); 251 | sprites[i].vx = (float) (rand() % 5 / 10.0f) - 0.2f; 252 | sprites[i].vy = (float) (rand() % 5 / 10.0f) - 0.2f; 253 | } 254 | 255 | // Voy a poner el fondo blanco para que se vea el shader 256 | SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 257 | 258 | while ( ! done ) { 259 | //Render to the texture 260 | SDL_SetRenderTarget(renderer, texTarget); 261 | SDL_RenderClear(renderer); 262 | 263 | // Pintamos MAX_SPRITES UWOLes 264 | struct sprite* spr; 265 | for(int i=0;i < MAX_SPRITES;++i) { 266 | spr = &(sprites[i]); 267 | spr->x += spr->vx; 268 | if(spr->x < 0) { 269 | spr->x = 0; 270 | spr->vx *= -1; 271 | } 272 | if(spr->x > WORLD_WIDTH - targetRect.w) { 273 | spr->x = (float) (WORLD_WIDTH - targetRect.w); 274 | spr->vx *= -1; 275 | } 276 | spr->y += spr->vy; 277 | if(spr->y < 0) { 278 | spr->y = 0; 279 | spr->vy *= -1; 280 | } 281 | if(spr->y > WORLD_HEIGHT - targetRect.h) { 282 | spr->y = (float) (WORLD_HEIGHT - targetRect.h); 283 | spr->vy *= -1; 284 | } 285 | 286 | targetRect.x = (int)spr->x; 287 | targetRect.y = (int)spr->y; 288 | 289 | SDL_RenderCopy(renderer, bmpTex, NULL, &targetRect); 290 | } 291 | 292 | presentBackBuffer(renderer, win, texTarget, programId); 293 | 294 | /* This could go in a separate function */ 295 | SDL_Event event; 296 | while ( SDL_PollEvent(&event) ) { 297 | if ( event.type == SDL_QUIT ) { 298 | done = 1; 299 | } 300 | if ( event.type == SDL_KEYDOWN ) { 301 | if ( event.key.keysym.sym == SDLK_SPACE ) { 302 | useShader ^= 1; 303 | std::cout << "useShader = " << (useShader ? "true" : "false") << std::endl; 304 | } 305 | if ( event.key.keysym.sym == SDLK_ESCAPE ) { 306 | done = 1; 307 | } 308 | } 309 | } 310 | } 311 | 312 | SDL_DestroyTexture(texTarget); 313 | SDL_DestroyTexture(bmpTex); 314 | SDL_DestroyRenderer(renderer); 315 | SDL_DestroyWindow(win); 316 | SDL_Quit(); 317 | return 0; 318 | } 319 | --------------------------------------------------------------------------------