├── .gitattributes
├── .gitignore
├── Clouds.sln
├── Clouds.vcxproj
├── Clouds.vcxproj.filters
├── res
└── shaders
│ ├── blur.frag
│ ├── blur.vert
│ ├── post.frag
│ ├── post.vert
│ ├── resolve.vert
│ ├── resolve_noise.frag
│ ├── resolve_tile.frag
│ ├── sky.frag
│ ├── sky.vert
│ ├── terrain.frag
│ └── terrain.vert
└── src
├── camera.cpp
├── camera.h
├── cloud_preprocess.cpp
├── cloud_preprocess.h
├── cloud_tiling.cpp
├── cloud_tiling.h
├── framebuffer.cpp
├── framebuffer.h
├── fullscreen_quad.cpp
├── fullscreen_quad.h
├── log.cpp
├── log.h
├── main.cpp
├── model.cpp
├── model.h
├── quad.cpp
├── quad.h
├── shader.cpp
├── shader.h
├── texture.cpp
└── texture.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | bld/
16 | [Bb]in/
17 | [Oo]bj/
18 |
19 | # Roslyn cache directories
20 | *.ide/
21 |
22 | # MSTest test Results
23 | [Tt]est[Rr]esult*/
24 | [Bb]uild[Ll]og.*
25 |
26 | #NUNIT
27 | *.VisualState.xml
28 | TestResult.xml
29 |
30 | # Build Results of an ATL Project
31 | [Dd]ebugPS/
32 | [Rr]eleasePS/
33 | dlldata.c
34 |
35 | *_i.c
36 | *_p.c
37 | *_i.h
38 | *.ilk
39 | *.meta
40 | *.obj
41 | *.pch
42 | *.pdb
43 | *.pgc
44 | *.pgd
45 | *.rsp
46 | *.sbr
47 | *.tlb
48 | *.tli
49 | *.tlh
50 | *.tmp
51 | *.tmp_proj
52 | *.log
53 | *.vspscc
54 | *.vssscc
55 | .builds
56 | *.pidb
57 | *.svclog
58 | *.scc
59 |
60 | # Chutzpah Test files
61 | _Chutzpah*
62 |
63 | # Visual C++ cache files
64 | ipch/
65 | *.aps
66 | *.ncb
67 | *.opensdf
68 | *.sdf
69 | *.cachefile
70 |
71 | # Visual Studio profiler
72 | *.psess
73 | *.vsp
74 | *.vspx
75 |
76 | # TFS 2012 Local Workspace
77 | $tf/
78 |
79 | # Guidance Automation Toolkit
80 | *.gpState
81 |
82 | # ReSharper is a .NET coding add-in
83 | _ReSharper*/
84 | *.[Rr]e[Ss]harper
85 | *.DotSettings.user
86 |
87 | # JustCode is a .NET coding addin-in
88 | .JustCode
89 |
90 | # TeamCity is a build add-in
91 | _TeamCity*
92 |
93 | # DotCover is a Code Coverage Tool
94 | *.dotCover
95 |
96 | # NCrunch
97 | _NCrunch_*
98 | .*crunch*.local.xml
99 |
100 | # MightyMoose
101 | *.mm.*
102 | AutoTest.Net/
103 |
104 | # Web workbench (sass)
105 | .sass-cache/
106 |
107 | # Installshield output folder
108 | [Ee]xpress/
109 |
110 | # DocProject is a documentation generator add-in
111 | DocProject/buildhelp/
112 | DocProject/Help/*.HxT
113 | DocProject/Help/*.HxC
114 | DocProject/Help/*.hhc
115 | DocProject/Help/*.hhk
116 | DocProject/Help/*.hhp
117 | DocProject/Help/Html2
118 | DocProject/Help/html
119 |
120 | # Click-Once directory
121 | publish/
122 |
123 | # Publish Web Output
124 | *.[Pp]ublish.xml
125 | *.azurePubxml
126 | ## TODO: Comment the next line if you want to checkin your
127 | ## web deploy settings but do note that will include unencrypted
128 | ## passwords
129 | #*.pubxml
130 |
131 | # NuGet Packages Directory
132 | packages/*
133 | ## TODO: If the tool you use requires repositories.config
134 | ## uncomment the next line
135 | #!packages/repositories.config
136 |
137 | # Enable "build/" folder in the NuGet Packages folder since
138 | # NuGet packages use it for MSBuild targets.
139 | # This line needs to be after the ignore of the build folder
140 | # (and the packages folder if the line above has been uncommented)
141 | !packages/build/
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # LightSwitch generated files
187 | GeneratedArtifacts/
188 | _Pvt_Extensions/
189 | ModelManifest.xml
--------------------------------------------------------------------------------
/Clouds.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.40629.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Clouds", "Clouds.vcxproj", "{F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}.Debug|Win32.Build.0 = Debug|Win32
16 | {F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}.Release|Win32.ActiveCfg = Release|Win32
17 | {F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}.Release|Win32.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/Clouds.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {F4A9BBD7-2B15-44A7-BFEE-CC408D2D0DF8}
15 | Clouds
16 |
17 |
18 |
19 | Application
20 | true
21 | v120
22 | MultiByte
23 |
24 |
25 | Application
26 | false
27 | v120
28 | true
29 | MultiByte
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | .\src;$(SourcePath)
43 | $(Configuration)\
44 |
45 |
46 | .\src;$(SourcePath)
47 | $(Configuration)\
48 |
49 |
50 |
51 | EnableAllWarnings
52 | Disabled
53 | true
54 | .\lib\glm;.\lib\SDL2-2.0.4\include;.\lib\glew-1.13.0\include;%(AdditionalIncludeDirectories)
55 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
56 |
57 |
58 | true
59 | .\lib\glew-1.13.0\lib\Release\Win32;.\lib\SDL2-2.0.4\lib\x86;%(AdditionalLibraryDirectories)
60 | glew32.lib;SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)
61 | Console
62 |
63 |
64 |
65 |
66 | Level3
67 | MaxSpeed
68 | true
69 | true
70 | true
71 | .\lib\glm;.\lib\SDL2-2.0.4\include;.\lib\glew-1.13.0\include;%(AdditionalIncludeDirectories)
72 | _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
73 |
74 |
75 | true
76 | true
77 | true
78 | .\lib\glew-1.13.0\lib\Release\Win32;.\lib\SDL2-2.0.4\lib\x86;%(AdditionalLibraryDirectories)
79 | glew32.lib;SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)
80 | Console
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/Clouds.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;mfcribbon-ms
15 |
16 |
17 | {af1ec427-23f4-4281-85b0-ff4ffcfde3b5}
18 |
19 |
20 | {a9078203-df9d-4ab6-ba4a-fc93490c2bdf}
21 |
22 |
23 |
24 |
25 | Resource Files\models
26 |
27 |
28 | Resource Files\models
29 |
30 |
31 | Resource Files\shaders
32 |
33 |
34 | Resource Files\shaders
35 |
36 |
37 | Resource Files\shaders
38 |
39 |
40 | Resource Files\shaders
41 |
42 |
43 | Resource Files\shaders
44 |
45 |
46 | Resource Files\shaders
47 |
48 |
49 | Resource Files\shaders
50 |
51 |
52 | Resource Files\shaders
53 |
54 |
55 | Resource Files\shaders
56 |
57 |
58 | Resource Files\shaders
59 |
60 |
61 | Resource Files\shaders
62 |
63 |
64 |
65 |
66 | Resource Files
67 |
68 |
69 |
70 |
71 | Source Files
72 |
73 |
74 | Source Files
75 |
76 |
77 | Source Files
78 |
79 |
80 | Source Files
81 |
82 |
83 | Source Files
84 |
85 |
86 | Source Files
87 |
88 |
89 | Source Files
90 |
91 |
92 | Source Files
93 |
94 |
95 | Source Files
96 |
97 |
98 | Source Files
99 |
100 |
101 | Source Files
102 |
103 |
104 |
105 |
106 | Header Files
107 |
108 |
109 | Header Files
110 |
111 |
112 | Header Files
113 |
114 |
115 | Header Files
116 |
117 |
118 | Header Files
119 |
120 |
121 | Header Files
122 |
123 |
124 | Header Files
125 |
126 |
127 | Header Files
128 |
129 |
130 | Header Files
131 |
132 |
133 | Header Files
134 |
135 |
136 |
--------------------------------------------------------------------------------
/res/shaders/blur.frag:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | out vec4 fcolor;
4 |
5 | in vec2 TexCoords;
6 |
7 | uniform sampler2D image;
8 | uniform bool horizontal;
9 |
10 | uniform float weight[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
11 |
12 | void main() {
13 |
14 | vec2 tex_offset = 1.0 / textureSize(image, 0);
15 | vec3 result = texture(image, TexCoords).rgb * weight[0];
16 |
17 | if(horizontal) {
18 | for(int i = 1; i < 5; ++i) {
19 | result += texture(image, TexCoords + vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
20 | result += texture(image, TexCoords - vec2(tex_offset.x * i, 0.0)).rgb * weight[i];
21 | }
22 | } else {
23 | for(int i = 1; i < 5; ++i) {
24 | result += texture(image, TexCoords + vec2(0.0, tex_offset.y * i)).rgb * weight[i];
25 | result += texture(image, TexCoords - vec2(0.0, tex_offset.y * i)).rgb * weight[i];
26 | }
27 | }
28 |
29 | fcolor = vec4(result * 1, 1.0);
30 | }
--------------------------------------------------------------------------------
/res/shaders/blur.vert:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout (location = 0) in vec3 position;
4 | layout (location = 1) in vec2 texCoords;
5 |
6 | out vec2 TexCoords;
7 |
8 | void main()
9 | {
10 | gl_Position = vec4(position, 1.0f);
11 | TexCoords = texCoords;
12 | }
--------------------------------------------------------------------------------
/res/shaders/post.frag:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) out vec4 frag_color;
4 |
5 | uniform sampler2D HDR_buffer;
6 | uniform sampler2D bloom_blur;
7 |
8 |
9 | void main() {
10 | const float gamma = 2.2;
11 | const float exposure = 0.1;
12 |
13 | vec3 hdrColor = texelFetch(HDR_buffer, ivec2(gl_FragCoord.xy), 0).rgb;
14 | vec3 bloomColor = texelFetch(bloom_blur, ivec2(gl_FragCoord.xy), 0).rgb;
15 | hdrColor += bloomColor;
16 |
17 | // Reinhard tone mapping
18 | vec3 mapped = hdrColor / (hdrColor + vec3(1.0));
19 | // Exposure tone mapping
20 | //vec3 mapped = vec3(1.0) - exp(-hdrColor * exposure);
21 | // Gamma correction
22 | //mapped = pow(mapped, vec3(1.0 / gamma));
23 |
24 | frag_color = vec4(mapped, 1.0);
25 | }
--------------------------------------------------------------------------------
/res/shaders/post.vert:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in vec3 vert;
4 |
5 | void main() {
6 | gl_Position = vec4(vert, 1.0f);
7 | }
--------------------------------------------------------------------------------
/res/shaders/resolve.vert:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in vec3 vert;
4 |
5 | layout(location = 0) out vec3 vertex_pos;
6 |
7 | void main() {
8 | vertex_pos = vert;
9 | gl_Position = vec4(vert, 1.0);
10 | }
--------------------------------------------------------------------------------
/res/shaders/resolve_noise.frag:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikardolajos/clouds/855cd20a7ab389136a38e8dfe9571531cd034959/res/shaders/resolve_noise.frag
--------------------------------------------------------------------------------
/res/shaders/resolve_tile.frag:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in vec3 vertex_pos;
4 |
5 | out vec4 frag_color;
6 |
7 | uniform sampler1D mie_texture;
8 | uniform sampler3D cloud_structure;
9 | uniform sampler3D cloud_tile00;
10 |
11 | uniform sampler2D diffuse_buffer;
12 | uniform sampler2D depth_buffer;
13 |
14 | uniform vec2 view_port;
15 | uniform vec3 camera_pos;
16 | uniform vec3 sun_pos;
17 |
18 | uniform mat4 view;
19 | uniform mat4 proj;
20 |
21 | float PI = 3.1415962;
22 | float PI_r = 0.3183098;
23 |
24 | float HG(float costheta) {
25 | float g = 0.99;
26 | return 0.25 * PI_r * (1 - pow(g, 2.0)) / pow((1 + pow(g, 2.0) - 2 * g * costheta), 1.5);
27 | }
28 |
29 | float Mie(float costheta) {
30 | float angle = acos(costheta);
31 | return texture(mie_texture, (PI - angle) * PI_r).r;
32 | }
33 |
34 | float phase(vec3 v1, vec3 v2) {
35 | float costheta = dot(v1, v2) / length(v1) / length(v2);
36 | return HG(-costheta);
37 | //return Mie(costheta);
38 | }
39 |
40 | float cloud_sampling_structure(vec3 v, float delta) {
41 | /* Reposition the cloud first */
42 | v = (v + vec3(500, -50, 500)) * 0.001;
43 |
44 | vec4 texture = texture(cloud_structure, v);
45 | return texture.r;
46 | }
47 |
48 | float cloud_sampling_tile(float tile, vec3 v, float delta) {
49 | /* Reposition the tile first */
50 | v = (v + vec3(500, -50, 500)) * 0.256;
51 | v = fract(v);
52 |
53 | if (tile * 255 == 1) {
54 | return texture(cloud_tile00, v).r * delta;
55 | }
56 |
57 | if (tile * 255 == 255) {
58 | /* This is the safety tile that surrounds all non-zero tiles */
59 | return 0.008 * delta;
60 | }
61 |
62 | return 0;
63 | }
64 |
65 | float cast_scatter_ray(vec3 origin, vec3 dir) {
66 | float delta = 5.0;
67 | float end = 50.0;
68 |
69 | vec3 sample_point = vec3(0.0);
70 | float inside = 0.0;
71 |
72 | float phase = phase(dir, vec3(camera_pos - origin));
73 |
74 | for (float t = 0.0; t < end; t += delta) {
75 | sample_point = origin + dir * t;
76 | //inside += cloud_sampling(sample_point, delta);
77 | }
78 |
79 | float beer = exp(-0.2 * inside);
80 |
81 | float value = phase + beer;
82 | return value;
83 | }
84 |
85 | // http://www.iquilezles.org/www/articles/terrainmarching/terrainmarching.htm
86 | vec4 cast_ray(vec3 origin, vec3 dir) {
87 | float delta_large = 10.0;
88 | float delta_small = 0.1;
89 | float start = gl_DepthRange.near;
90 | float end = 500.0;
91 |
92 | vec4 value = vec4(0.0);
93 | vec3 cloud_color = vec3(0.93, 0.93, 0.95);
94 | vec3 cloud_shade = vec3(0.859, 0.847, 0.757) - 0.1;
95 | vec3 cloud_bright = vec3(0.99, 0.96, 0.95);
96 | vec3 cloud_dark = vec3(0.671, 0.725, 0.753);
97 | value.rgb = cloud_dark;
98 |
99 | bool inside = false;
100 | bool looking_for_new_tile = true;
101 | int points_inside = 0;
102 | vec3 sample_point = origin;
103 |
104 | float tile;
105 | float delta = delta_large;
106 | for (float t = start; t < end; t += delta) {
107 | sample_point = origin + dir * t;
108 |
109 | /* Stop rays that are going below ground */
110 | if (sample_point.y < 0.0) {
111 | break;
112 | }
113 |
114 | /* Stop rays that already reach full opacity */
115 | if (value.a > 1.0) {
116 | break;
117 | }
118 |
119 | float alpha;
120 | if (!inside) {
121 | tile = cloud_sampling_structure(sample_point, delta);
122 | if (tile > 0.0) {
123 | inside = true;
124 | } else {
125 | looking_for_new_tile = true;
126 | }
127 | }
128 |
129 | if (inside) {
130 | /* Start of a new tile? */
131 | if (looking_for_new_tile) {
132 | /* Move the starting point a large delta backwards */
133 | t -= delta_large;
134 | if (t < gl_DepthRange.near) {
135 | t = gl_DepthRange.near;
136 | }
137 | sample_point = origin + dir * t;
138 | delta = delta_small;
139 |
140 | looking_for_new_tile = false;
141 | points_inside = 0;
142 | }
143 | delta = delta_small;
144 | alpha = cloud_sampling_tile(tile, sample_point, delta);
145 | value.a += alpha;
146 | points_inside += 1;
147 | }
148 |
149 | /* Check next structure block if we are still inside */
150 | if (inside && points_inside * delta_small > delta_large) {
151 | tile = cloud_sampling_structure(sample_point, delta);
152 | if (tile == 0.0) {
153 | inside = false;
154 | looking_for_new_tile = true;
155 |
156 | delta = delta_large;
157 | } else {
158 | points_inside = 0;
159 | }
160 | }
161 |
162 | /* Calculate the scattering */
163 | float energy = cast_scatter_ray(sample_point, normalize(sun_pos - sample_point));
164 | //value.rgb = mix(cloud_dark, cloud_bright, energy);
165 | }
166 |
167 | return clamp(value, 0.0, 1.0);
168 | }
169 |
170 | void main() {
171 | /* Calculate the ray */
172 | // http://antongerdelan.net/opengl/raycasting.html
173 | float x = 2.0 * gl_FragCoord.x / view_port.x - 1.0;
174 | float y = 2.0 * gl_FragCoord.y / view_port.y - 1.0;
175 | vec2 ray_nds = vec2(x, y);
176 | vec4 ray_clip = vec4(ray_nds, -1.0, 1.0);
177 | vec4 ray_view = inverse(proj) * ray_clip;
178 | ray_view = vec4(ray_view.xy, -1.0, 0.0);
179 | vec3 ray_world = (inverse(view) * ray_view).xyz;
180 | ray_world = normalize(ray_world);
181 |
182 | vec4 cloud_color = cast_ray(camera_pos, ray_world);
183 |
184 | vec4 diffuse_color = texelFetch(diffuse_buffer, ivec2(gl_FragCoord.xy), 0);
185 | float depth = pow(texelFetch(depth_buffer, ivec2(gl_FragCoord.xy), 0).x, 128.0);
186 |
187 | frag_color.a = 1.0;
188 | frag_color.rgb = mix(diffuse_color.rgb, cloud_color.rgb, cloud_color.a);
189 |
190 | //frag_color.rgb = texture(cloud_structure, vec3(gl_FragCoord.xy / view_port.xy, 0.5)).rrr;
191 | }
--------------------------------------------------------------------------------
/res/shaders/sky.frag:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) smooth in vec3 N;
4 | layout(location = 1) in vec3 S;
5 |
6 | layout(location = 0) out vec4 fcolor;
7 |
8 | void main () {
9 |
10 | float sun = dot(normalize(-S), normalize(N));
11 | float sun_pos = smoothstep(0.9995, 0.99995, sun);
12 | vec3 sun_color = vec3(1, 0.55, 0.15) * 1000;
13 |
14 | vec3 deep_blue = vec3(0.3421052632, 0.9029850746, 2.311688312);
15 | vec3 light_blue = deep_blue + 1;
16 |
17 | /* Lighter around the horizon */
18 | vec3 sky_color = mix(deep_blue, light_blue, smoothstep(-1.0, 0.7, dot(normalize(N), vec3(0.0, 1.0, 0.0))));
19 | /* Lighter around the sun */
20 | sky_color += 0.15 * mix(vec3(0.0), vec3(1.0), smoothstep(0.85, 1.0, sun));
21 | sky_color += 0.2 * mix(vec3(0.0), vec3(1.0), smoothstep(0.75, 1.0, sun));
22 |
23 | vec3 color = sky_color + sun_pos * sun_color;
24 | fcolor = vec4(color, 1.0);
25 | }
--------------------------------------------------------------------------------
/res/shaders/sky.vert:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in vec3 vert;
4 | layout(location = 1) in vec3 norm;
5 |
6 | layout(location = 0) smooth out vec3 N;
7 | layout(location = 1) out vec3 S;
8 |
9 | uniform mat4 model;
10 | uniform mat4 view;
11 | uniform mat4 proj;
12 |
13 | uniform vec3 camera_pos;
14 | uniform vec3 sun_pos;
15 |
16 | void main() {
17 | N = norm;
18 | S = sun_pos - camera_pos;
19 | gl_Position = proj * view * model * vec4(vert, 1.0);
20 | }
--------------------------------------------------------------------------------
/res/shaders/terrain.frag:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in float height;
4 | layout(location = 1) in float dist;
5 | layout(location = 2) in vec2 pos;
6 | layout(location = 3) in vec2 uv;
7 |
8 | layout(location = 0) out vec4 fcolor;
9 |
10 | uniform sampler2D terrain_texture;
11 |
12 |
13 | void main() {
14 |
15 | vec3 fog_color = vec3(0.3, 0.3, 0.7);
16 | vec3 terrain_color_base = vec3(0.30, 0.34, 0.05);
17 | vec3 terrain_color_top = vec3(0.5, 0.4, 0.1);
18 |
19 | vec3 fog = fog_color * smoothstep(300, 500, dist) * 1;
20 | vec3 terrain = terrain_color_base + clamp(height, -0.8, 1.0) * terrain_color_top * texture(terrain_texture, uv * 100).rgb;
21 | vec3 color = terrain + fog;
22 |
23 | fcolor = vec4(color, smoothstep(580, 330, dist));
24 | fcolor.rgb *= 1.5;
25 |
26 | /* Grid */
27 | if (mod(pos.x, 4) < 0.2 || mod(pos.y, 4) < 0.2) {
28 | //fcolor = vec4(1.0, 1.0, 0.4, 1.0);
29 | }
30 | }
--------------------------------------------------------------------------------
/res/shaders/terrain.vert:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | layout(location = 0) in vec3 vert;
4 | layout(location = 1) in vec3 norm;
5 | layout(location = 2) in vec2 text;
6 |
7 | layout(location = 0) out float height;
8 | layout(location = 1) out float dist;
9 | layout(location = 2) out vec2 pos;
10 | layout(location = 3) out vec2 uv;
11 |
12 | uniform sampler2D terrain_texture;
13 |
14 | uniform mat4 model;
15 | uniform mat4 view;
16 | uniform mat4 proj;
17 |
18 | uniform vec3 camera_pos;
19 |
20 | void main() {
21 | dist = length(vert - camera_pos);
22 | height = texture(terrain_texture, vert.xz * 5).g * 0.4;
23 | pos = vec2(vert.x, vert.z);
24 | uv = text;
25 | gl_Position = proj * view * model * vec4(vert.x, vert.y + height * 3 - 3, vert.z, 1.0);
26 | }
--------------------------------------------------------------------------------
/src/camera.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikardolajos/clouds/855cd20a7ab389136a38e8dfe9571531cd034959/src/camera.cpp
--------------------------------------------------------------------------------
/src/camera.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMERA_H
2 | #define CAMERA_H
3 |
4 | #include "glm/glm.hpp"
5 | #include "SDL.h"
6 |
7 | #define CAMERA_NEAR 0.1f
8 | #define CAMERA_FAR 2000.0f
9 | #define CAMERA_FOV 60.0f
10 |
11 | typedef struct Camera Camera;
12 | struct Camera {
13 | int width;
14 | int height;
15 |
16 | float fov;
17 | float z_near;
18 | float z_far;
19 |
20 | glm::vec3 position;
21 | glm::vec3 front;
22 | glm::vec3 up;
23 |
24 | float pitch;
25 | float yaw;
26 | float sensitivity;
27 | SDL_bool enabled;
28 | };
29 |
30 | /* Initialize a camera at (0, 2, 0) with (0, 1, 0) as up vector, looking down negative z-axis */
31 | void camera_init(Camera* c, int width, int height, float fov, float z_near, float z_far);
32 | glm::mat4 camera_view_matrix(Camera* c);
33 | glm::mat4 camera_projection_matrix(Camera* c);
34 | void camera_translate(Camera* c, const char* direction, float delta_time);
35 | void camera_movement(Camera* c, float delta_time);
36 | void camera_toggle_mouse(Camera* c, SDL_Window* w);
37 | void camera_track1(Camera* c, Uint32 time, Uint32 duration);
38 | void camera_track2(Camera* c, Uint32 time, Uint32 duration);
39 | void camera_track3(Camera* c, Uint32 time, Uint32 duration);
40 | void camera_track4(Camera* c, Uint32 time, Uint32 duration);
41 |
42 | #endif
--------------------------------------------------------------------------------
/src/cloud_preprocess.cpp:
--------------------------------------------------------------------------------
1 | #include "cloud_preprocess.h"
2 |
3 | #include "glm/glm.hpp"
4 |
5 | #include "texture.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | /* 1 = inside cloud, else 0 */
12 | GLubyte structure(GLubyte pixel)
13 | {
14 | if (pixel / 255.0 > 0.35) {
15 | return 1;
16 | }
17 | return 0;
18 | }
19 |
20 | int cloud_preprocess(Texture* cloud_structure, Texture source)
21 | {
22 | /* Read the source texture */
23 | GLubyte* cloud_pixels = (GLubyte*)malloc(source.width * source.height * source.depth * 4 * sizeof(GLubyte));
24 | glBindTexture(GL_TEXTURE_3D, source.object);
25 | glGetTexImage(GL_TEXTURE_3D, 0, GL_RGBA, GL_UNSIGNED_BYTE, cloud_pixels);
26 |
27 | /* Set size of structure texture */
28 | cloud_structure->width = 32; /* Creates 4x4x4 cubes of original 128x128x128 texture */
29 | cloud_structure->height = 32;
30 | cloud_structure->depth = 32;
31 |
32 | /* Pick the red channel and procces it */
33 | GLubyte* temp = (GLubyte*)malloc(source.width * source.height * source.depth * sizeof(GLubyte));
34 | for (int i = 0; i < source.width * source.height * source.depth; i++) {
35 | temp[i] = structure(cloud_pixels[i * 4]);
36 | }
37 |
38 | GLubyte* new_structure = (GLubyte*)malloc(cloud_structure->width * cloud_structure->height * cloud_structure->depth * sizeof(GLubyte));
39 |
40 | /* Analyze every 4x4x4 block of the original texture */
41 | int inside = 0;
42 | for (int i = 0; i < cloud_structure->width; i++) {
43 | for (int j = 0; j < cloud_structure->height; j++) {
44 | for (int k = 0; k < cloud_structure->depth; k++) {
45 |
46 | inside = 0;
47 |
48 | for (int u = 0; u < 4; u++) {
49 | for (int v = 0; v < 4; v++) {
50 | for (int w = 0; w < 4; w++) {
51 |
52 | int x = i * 4 + u;
53 | int y = j * 4 + v;
54 | int z = k * 4 + w;
55 |
56 | inside += temp[x + y * source.height + z * source.height * source.depth];
57 |
58 | }
59 | }
60 | }
61 |
62 | if (inside < 8) {
63 | new_structure[i + j * cloud_structure->height + k * cloud_structure->height * cloud_structure->depth] = 0;
64 | } else {
65 | new_structure[i + j * cloud_structure->height + k * cloud_structure->height * cloud_structure->depth] = 255;
66 | }
67 |
68 | }
69 | }
70 | }
71 |
72 | /* Post process -- expanding the structure to reduce artifacts */
73 | GLubyte* post_pixels = (GLubyte*)calloc(cloud_structure->width * cloud_structure->height * cloud_structure->depth, sizeof(GLubyte));
74 |
75 | for (int i = 0; i < cloud_structure->width; i++) {
76 | for (int j = 0; j < cloud_structure->height; j++) {
77 | for (int k = 0; k < cloud_structure->depth; k++) {
78 |
79 | if (new_structure[k + j * cloud_structure->height + i * cloud_structure->height * cloud_structure->depth] == 0) {
80 | continue;
81 | }
82 |
83 | for (int ii = -1; ii < 2; ii++) {
84 | if (i + ii < 0 || i + ii >= cloud_structure->width) continue;
85 | for (int jj = -1; jj < 2; jj++) {
86 | if (j + jj < 0 || j + jj >= cloud_structure->height) continue;
87 | for (int kk = -1; kk < 2; kk++) {
88 | if (k + kk < 0 || k + kk >= cloud_structure->depth) continue;
89 |
90 | post_pixels[(k + kk) + (j + jj) * cloud_structure->height + (i + ii) * cloud_structure->height * cloud_structure->depth] = 255;
91 | }
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | /* Bind the new texture */
99 | glGenTextures(1, &cloud_structure->object);
100 | glBindTexture(GL_TEXTURE_3D, cloud_structure->object);
101 |
102 | /* Give it an index */
103 | texture_activate(cloud_structure);
104 |
105 | glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, cloud_structure->width, cloud_structure->height, cloud_structure->depth, 0, GL_RED, GL_UNSIGNED_BYTE, post_pixels);
106 | glGenerateMipmap(GL_TEXTURE_3D);
107 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
108 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
109 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
110 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
111 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
112 |
113 | free(cloud_pixels);
114 | free(temp);
115 | free(new_structure);
116 | free(post_pixels);
117 |
118 | return 0;
119 | }
--------------------------------------------------------------------------------
/src/cloud_preprocess.h:
--------------------------------------------------------------------------------
1 | #ifndef CLOUD_PREPROCESS_H
2 | #define CLOUD_PREPROCESS_H
3 |
4 | #include "texture.h"
5 |
6 | int cloud_preprocess(Texture* cloud_structure, Texture source);
7 |
8 | #endif
--------------------------------------------------------------------------------
/src/cloud_tiling.cpp:
--------------------------------------------------------------------------------
1 | #include "cloud_tiling.h"
2 |
3 | #include "glm/glm.hpp"
4 |
5 | #include "texture.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | int cloud_tiling_structure(Texture* cloud_structure)
12 | {
13 | /* Set up cloud structure */
14 | cloud_structure->width = 256;
15 | cloud_structure->height = 256;
16 | cloud_structure->depth = 256;
17 |
18 | GLubyte* pixels = (GLubyte*)malloc(cloud_structure->width * cloud_structure->height * cloud_structure->depth * sizeof(GLubyte));
19 |
20 | /* Process the pixels */
21 | for (int i = 0; i < cloud_structure->width; i++) {
22 | for (int j = 0; j < cloud_structure->height; j++) {
23 | for (int k = 0; k < cloud_structure->depth; k++) {
24 | if (j == 1 && i == 127 && k == 127) {
25 | pixels[k + j * cloud_structure->height + i * cloud_structure->height * cloud_structure->depth] = 1;
26 | } else {
27 | pixels[k + j * cloud_structure->height + i * cloud_structure->height * cloud_structure->depth] = 0;
28 | }
29 | }
30 | }
31 | }
32 |
33 | /* Post process -- expanding the structure to reduce artifacts */
34 | GLubyte* post_pixels = (GLubyte*)calloc(cloud_structure->width * cloud_structure->height * cloud_structure->depth, sizeof(GLubyte));
35 |
36 | for (int i = 0; i < cloud_structure->width; i++) {
37 | for (int j = 0; j < cloud_structure->height; j++) {
38 | for (int k = 0; k < cloud_structure->depth; k++) {
39 |
40 | if (pixels[k + j * cloud_structure->height + i * cloud_structure->height * cloud_structure->depth] == 0) {
41 | continue;
42 | }
43 |
44 | for (int ii = -10; ii < 11; ii++) {
45 | if (i + ii < 0 || i + ii >= cloud_structure->width) continue;
46 | for (int jj = -10; jj < 11; jj++) {
47 | if (j + jj < 0 || j + jj >= cloud_structure->height) continue;
48 | for (int kk = -10; kk < 11; kk++) {
49 | if (k + kk < 0 || k + kk >= cloud_structure->depth) continue;
50 |
51 | GLubyte p = pixels[(k + kk) + (j + jj) * cloud_structure->height + (i + ii) * cloud_structure->height * cloud_structure->depth];
52 | if (p == 0) {
53 | post_pixels[(k + kk) + (j + jj) * cloud_structure->height + (i + ii) * cloud_structure->height * cloud_structure->depth] = 255;
54 | } else {
55 | post_pixels[(k + kk) + (j + jj) * cloud_structure->height + (i + ii) * cloud_structure->height * cloud_structure->depth] = p;
56 | }
57 | }
58 | }
59 | }
60 | }
61 | }
62 | }
63 |
64 | /* Bind the new texture */
65 | glGenTextures(1, &cloud_structure->object);
66 | glBindTexture(GL_TEXTURE_3D, cloud_structure->object);
67 |
68 | /* Give it an index */
69 | texture_activate(cloud_structure);
70 |
71 | glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, cloud_structure->width, cloud_structure->height, cloud_structure->depth, 0, GL_RED, GL_UNSIGNED_BYTE, post_pixels);
72 | glGenerateMipmap(GL_TEXTURE_3D);
73 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
74 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
75 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
76 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
77 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
78 |
79 | free(pixels);
80 | free(post_pixels);
81 |
82 | return 0;
83 | }
84 |
85 | int cloud_tiling_init(Texture cloud_tiles[], Texture* cloud_structure)
86 | {
87 | /* Set size of structure texture */
88 | cloud_tiles[0].width = 64;
89 | cloud_tiles[0].height = 64;
90 | cloud_tiles[0].depth = 64;
91 |
92 | GLubyte* pixels = (GLubyte*)malloc(cloud_tiles[0].width * cloud_tiles[0].height * cloud_tiles[0].depth * sizeof(GLubyte));
93 |
94 | /* Process the pixels */
95 | for (int i = 0; i < cloud_tiles[0].width; i++) {
96 | for (int j = 0; j < cloud_tiles[0].height; j++) {
97 | for (int k = 0; k < cloud_tiles[0].depth; k++) {
98 | if (i > 32 && j > 32) {
99 | pixels[k + j * cloud_tiles[0].height + i * cloud_tiles[0].height * cloud_tiles[0].depth] = 255;
100 | } else {
101 | pixels[k + j * cloud_tiles[0].height + i * cloud_tiles[0].height * cloud_tiles[0].depth] = 0;
102 | }
103 | }
104 | }
105 | }
106 |
107 | /* Bind the new texture */
108 | glGenTextures(1, &cloud_tiles[0].object);
109 | glBindTexture(GL_TEXTURE_3D, cloud_tiles[0].object);
110 |
111 | /* Give it an index */
112 | texture_activate(&cloud_tiles[0]);
113 |
114 | glTexImage3D(GL_TEXTURE_3D, 0, GL_RED, cloud_tiles[0].width, cloud_tiles[0].height, cloud_tiles[0].depth, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
115 | glGenerateMipmap(GL_TEXTURE_3D);
116 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
117 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
118 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
119 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
120 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
121 |
122 | free(pixels);
123 |
124 | cloud_tiling_structure(cloud_structure);
125 |
126 | return 0;
127 | }
--------------------------------------------------------------------------------
/src/cloud_tiling.h:
--------------------------------------------------------------------------------
1 | #ifndef CLOUD_TILING_H
2 | #define CLOUD_TILING_H
3 |
4 | #include "texture.h"
5 |
6 | int cloud_tiling_init(Texture cloud_tiles[], Texture* cloud_structure);
7 |
8 | #endif
--------------------------------------------------------------------------------
/src/framebuffer.cpp:
--------------------------------------------------------------------------------
1 | #include "framebuffer.h"
2 |
3 | #include "log.h"
4 |
5 | #include "GL/glew.h"
6 |
7 | #include
8 |
9 | void framebuffer_scene_init(Framebuffer* f, int screen_width, int screen_height)
10 | {
11 | glGenFramebuffers(1, &f->fbo);
12 | glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
13 |
14 | glGenTextures(1, &f->color_buffer[0]);
15 |
16 | glBindTexture(GL_TEXTURE_2D, f->color_buffer[0]);
17 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, screen_width, screen_height, 0, GL_RGB, GL_FLOAT, NULL);
18 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
19 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
20 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
21 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
22 |
23 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, f->color_buffer[0], 0);
24 |
25 | GLuint depth_rbo;
26 | glGenRenderbuffers(1, &depth_rbo);
27 | glBindRenderbuffer(GL_RENDERBUFFER, depth_rbo);
28 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screen_width, screen_height);
29 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rbo);
30 |
31 | GLuint scene_attachments[1] = { GL_COLOR_ATTACHMENT0 };
32 | glDrawBuffers(1, scene_attachments);
33 |
34 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
35 | log("Error: Framebuffer not created!\n");
36 | }
37 | }
38 |
39 | void framebuffer_cloud_init(Framebuffer* f, int screen_width, int screen_height)
40 | {
41 | glGenFramebuffers(1, &f->fbo);
42 | glBindFramebuffer(GL_FRAMEBUFFER, f->fbo);
43 |
44 | glGenTextures(2, f->color_buffer);
45 | for (GLuint i = 0; i < 2; i++) {
46 | glBindTexture(GL_TEXTURE_2D, f->color_buffer[i]);
47 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, screen_width, screen_height, 0, GL_RGB, GL_FLOAT, NULL);
48 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
49 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
50 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
51 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
52 |
53 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, f->color_buffer[i], 0);
54 | }
55 |
56 | GLuint cloud_attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
57 | glDrawBuffers(2, cloud_attachments);
58 |
59 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
60 | log("Error: Framebuffer not created!\n");
61 | }
62 | }
63 |
64 | void framebuffer_pingpong_init(Framebuffer f[2], int screen_width, int screen_height)
65 | {
66 | glGenFramebuffers(1, &f[0].fbo);
67 | glGenTextures(1, f[0].color_buffer);
68 |
69 | glGenFramebuffers(1, &f[1].fbo);
70 | glGenTextures(1, f[1].color_buffer);
71 |
72 | for (GLuint i = 0; i < 2; i++) {
73 | glBindFramebuffer(GL_FRAMEBUFFER, f[i].fbo);
74 | glBindTexture(GL_TEXTURE_2D, f[i].color_buffer[0]);
75 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, screen_width, screen_height, 0, GL_RGB, GL_FLOAT, NULL);
76 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
77 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
78 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
79 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
80 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, f[i].color_buffer[0], 0);
81 |
82 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
83 | log("Framebuffer not complete!");
84 | }
85 |
86 | glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
87 | }
--------------------------------------------------------------------------------
/src/framebuffer.h:
--------------------------------------------------------------------------------
1 | #ifndef FRAMEBUFFER_H
2 | #define FRAMEBUFFER_H
3 |
4 | #include "GL/glew.h"
5 |
6 | typedef struct Framebuffer Framebuffer;
7 | struct Framebuffer {
8 | GLuint fbo;
9 | GLuint color_buffer[2];
10 | };
11 |
12 | void framebuffer_scene_init(Framebuffer* f, int screen_width, int screen_height);
13 | void framebuffer_cloud_init(Framebuffer* f, int screen_width, int screen_height);
14 | void framebuffer_pingpong_init(Framebuffer* f, int screen_width, int screen_height);
15 |
16 | #endif
--------------------------------------------------------------------------------
/src/fullscreen_quad.cpp:
--------------------------------------------------------------------------------
1 | #include "fullscreen_quad.h"
2 |
3 | #include "GL/glew.h"
4 | #include "log.h"
5 | #include "texture.h"
6 |
7 | #include
8 |
9 | /* http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-14-render-to-texture/ */
10 | /* http://learnopengl.com/#!Advanced-Lighting/HDR */
11 | /* http://learnopengl.com/#!Advanced-Lighting/Bloom */
12 |
13 | void fs_quad_init(FS_Quad* q, int screen_width, int screen_height, Shader s)
14 | {
15 | q->screen_width = screen_width;
16 | q->screen_height = screen_height;
17 | q->shader = s;
18 |
19 | /* Reserve two texture indices */
20 | texture_activate(&q->texture);
21 | texture_activate(&q->texture);
22 | q->texture.index--;
23 |
24 | /* Create framebuffer */
25 | glGenFramebuffers(1, &q->framebuffer_object);
26 | glBindFramebuffer(GL_FRAMEBUFFER, q->framebuffer_object);
27 |
28 | /* Create textures to render to */
29 | glGenTextures(2, q->color_buffers);
30 | q->texture.object = q->color_buffers[0];
31 |
32 | for (GLuint i = 0; i < 2; i++) {
33 | /* Send an empty texture to OpenGL and set some filtering */
34 | glBindTexture(GL_TEXTURE_2D, q->color_buffers[i]);
35 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, q->screen_width, q->screen_height, 0, GL_RGBA, GL_FLOAT, 0);
36 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
37 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
38 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
39 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
40 |
41 | /* Set color attachment */
42 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, q->color_buffers[i], 0);
43 | }
44 |
45 | /* Depth buffer */
46 | glGenRenderbuffers(1, &q->depth_render_buffer);
47 | glBindRenderbuffer(GL_RENDERBUFFER, q->depth_render_buffer);
48 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, q->screen_width, q->screen_height);
49 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, q->depth_render_buffer);
50 |
51 | /* Set the list of draw buffers */
52 | GLenum draw_buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
53 | glDrawBuffers(2, draw_buffers);
54 |
55 | /* Check for errors */
56 | if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
57 | log("Error: Framebuffer not created!\n");
58 | }
59 |
60 | /* Create fullscreen quad */
61 | float quad[] = {
62 | -1.0f, -1.0f, 0.0f,
63 | 1.0f, -1.0f, 0.0f,
64 | 1.0f, 1.0f, 0.0f,
65 | -1.0f, -1.0f, 0.0f,
66 | 1.0f, 1.0f, 0.0f,
67 | -1.0f, 1.0f, 0.0f
68 | };
69 |
70 | GLuint vbo;
71 | glGenBuffers(1, &vbo);
72 | glBindBuffer(GL_ARRAY_BUFFER, vbo);
73 | glBufferData(GL_ARRAY_BUFFER, sizeof quad, quad, GL_STATIC_DRAW);
74 |
75 | glGenVertexArrays(1, &q->vertex_array_object);
76 | glBindVertexArray(q->vertex_array_object);
77 |
78 | glEnableVertexAttribArray(0);
79 | glBindBuffer(GL_ARRAY_BUFFER, vbo);
80 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
81 | }
82 |
83 | void fs_quad_pingpong_init(FS_Quad pingpong[2], int screen_width, int screen_height, Shader s)
84 | {
85 | pingpong[0].screen_width = screen_width;
86 | pingpong[0].screen_height = screen_height;
87 | pingpong[0].shader = s;
88 |
89 | pingpong[1].screen_width = screen_width;
90 | pingpong[1].screen_height = screen_height;
91 | pingpong[1].shader = s;
92 |
93 | texture_activate(&pingpong[0].texture);
94 | texture_activate(&pingpong[1].texture);
95 |
96 | glGenFramebuffers(1, &pingpong[0].framebuffer_object);
97 | glGenTextures(1, &pingpong[0].texture.object);
98 |
99 | glGenFramebuffers(1, &pingpong[1].framebuffer_object);
100 | glGenTextures(1, &pingpong[1].texture.object);
101 |
102 | for (GLuint i = 0; i < 2; i++) {
103 | glBindFramebuffer(GL_FRAMEBUFFER, pingpong[i].framebuffer_object);
104 | glBindTexture(GL_TEXTURE_2D, pingpong[i].texture.object);
105 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, pingpong[i].screen_width, pingpong[i].screen_height, 0, GL_RGB, GL_FLOAT, NULL);
106 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
107 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
108 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
109 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
110 | glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pingpong[i].texture.object, 0);
111 | }
112 |
113 | /* Create fullscreen quad */
114 | float quad[] = {
115 | -1.0f, -1.0f, 0.0f,
116 | 1.0f, -1.0f, 0.0f,
117 | 1.0f, 1.0f, 0.0f,
118 | -1.0f, -1.0f, 0.0f,
119 | 1.0f, 1.0f, 0.0f,
120 | -1.0f, 1.0f, 0.0f
121 | };
122 |
123 | GLuint vbo;
124 | glGenBuffers(1, &vbo);
125 | glBindBuffer(GL_ARRAY_BUFFER, vbo);
126 | glBufferData(GL_ARRAY_BUFFER, sizeof quad, quad, GL_STATIC_DRAW);
127 |
128 | glGenVertexArrays(1, &pingpong[0].vertex_array_object);
129 | glBindVertexArray(pingpong[0].vertex_array_object);
130 |
131 | glEnableVertexAttribArray(0);
132 | glBindBuffer(GL_ARRAY_BUFFER, vbo);
133 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
134 | }
135 |
136 | /* http://learnopengl.com/#!Advanced-Lighting/Bloom */
137 | void fs_quad_pingpong_render(FS_Quad pingpong[2], FS_Quad q)
138 | {
139 | GLboolean horizontal = true;
140 | GLboolean first_iteration = true;
141 | GLuint amount = 10;
142 |
143 | glUseProgram(pingpong[0].shader.shader_program);
144 |
145 | for (GLuint i = 0; i < amount; i++) {
146 | glBindFramebuffer(GL_FRAMEBUFFER, pingpong[horizontal].framebuffer_object);
147 |
148 | glUniform1i(glGetUniformLocation(pingpong[0].shader.shader_program, "horizontal"), horizontal);
149 |
150 | glActiveTexture(GL_TEXTURE0);
151 | glBindTexture(GL_TEXTURE_2D, first_iteration ? q.color_buffers[1] : pingpong[!horizontal].texture.object);
152 | GLuint image = glGetUniformLocation(pingpong[0].shader.shader_program, "image");
153 | glUniform1i(image, 0);
154 |
155 | glBindVertexArray(pingpong[0].vertex_array_object);
156 | glDrawArrays(GL_TRIANGLES, 0, 6);
157 | glBindVertexArray(0);
158 |
159 | horizontal = !horizontal;
160 | if (first_iteration)
161 | first_iteration = false;
162 | }
163 | }
164 |
165 | void fs_quad_set_as_render_target(FS_Quad q)
166 | {
167 | glBindFramebuffer(GL_FRAMEBUFFER, q.framebuffer_object);
168 | glViewport(0, 0, q.screen_width, q.screen_height);
169 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
170 | }
171 |
172 | void fs_quad_render_to_post(FS_Quad q, FS_Quad post)
173 | {
174 | glBindFramebuffer(GL_FRAMEBUFFER, post.framebuffer_object);
175 | glViewport(0, 0, post.screen_width, post.screen_height);
176 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
177 |
178 | glUseProgram(q.shader.shader_program);
179 |
180 | glActiveTexture(GL_TEXTURE0 + q.texture.index);
181 | glBindTexture(GL_TEXTURE_2D, q.texture.object);
182 | GLuint buffer = glGetUniformLocation(q.shader.shader_program, "diffuse_buffer");
183 | glUniform1i(buffer, q.texture.index);
184 |
185 | glBindVertexArray(q.vertex_array_object);
186 | glDrawArrays(GL_TRIANGLES, 0, 6);
187 | }
188 |
189 | void fs_quad_render_to_screen(FS_Quad q, FS_Quad pingpong[2])
190 | {
191 | glBindFramebuffer(GL_FRAMEBUFFER, 0);
192 | glViewport(0, 0, q.screen_width, q.screen_height);
193 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194 |
195 | glUseProgram(q.shader.shader_program);
196 |
197 | glActiveTexture(GL_TEXTURE0);
198 | glBindTexture(GL_TEXTURE_2D, q.texture.object);
199 | GLuint buffer = glGetUniformLocation(q.shader.shader_program, "HDR_buffer");
200 | glUniform1i(buffer, 0);
201 |
202 | glActiveTexture(GL_TEXTURE1);
203 | glBindTexture(GL_TEXTURE_2D, pingpong[1].texture.object);
204 | GLuint bloom = glGetUniformLocation(q.shader.shader_program, "bloom_blur");
205 | glUniform1i(bloom, 1);
206 |
207 | glBindVertexArray(q.vertex_array_object);
208 | glDrawArrays(GL_TRIANGLES, 0, 6);
209 | }
--------------------------------------------------------------------------------
/src/fullscreen_quad.h:
--------------------------------------------------------------------------------
1 | #ifndef FULLSCREEN_QUAD_H
2 | #define FULLSCREEN_QUAD_H
3 |
4 | #include "shader.h"
5 |
6 | typedef struct FS_Quad FS_Quad;
7 | struct FS_Quad {
8 | GLuint framebuffer_object;
9 | GLuint vertex_array_object;
10 | GLuint depth_render_buffer;
11 |
12 | GLuint color_buffers[2];
13 |
14 | int screen_width;
15 | int screen_height;
16 |
17 | Shader shader;
18 | Texture texture;
19 | };
20 |
21 | void fs_quad_init(FS_Quad* q, int screen_width, int screen_height, Shader s);
22 | void fs_quad_pingpong_init(FS_Quad pingpong[2], int screen_width, int screen_height, Shader s);
23 | void fs_quad_pingpong_render(FS_Quad pingpong[2], FS_Quad q);
24 | void fs_quad_set_as_render_target(FS_Quad q);
25 | void fs_quad_render_to_post(FS_Quad q, FS_Quad post);
26 | void fs_quad_render_to_screen(FS_Quad q, FS_Quad pingpong[2]);
27 |
28 |
29 | #endif
--------------------------------------------------------------------------------
/src/log.cpp:
--------------------------------------------------------------------------------
1 | #include "log.h"
2 |
3 | #include "GL/glew.h"
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | void log_init()
10 | {
11 | if (ERROR_LOG == 1) {
12 | FILE* file = fopen("../log.txt", "a");
13 | if (!file) fprintf(stdout, "Could not open log.txt for appending!");
14 | CString t = CTime::GetCurrentTime().Format("%Y-%m-%d %H:%M");
15 | fprintf(file, "\n\n[%s]\n", t);
16 | fclose(file);
17 | }
18 | }
19 |
20 | void log(const char* message, ...)
21 | {
22 | va_list args;
23 |
24 | va_start(args, message);
25 |
26 | if (ERROR_LOG == 1) {
27 | FILE* file = fopen("../log.txt", "a");
28 | if (!file) fprintf(stdout, "Could not open log.txt for appending!");
29 | vfprintf(file, message, args);
30 | fclose(file);
31 | }
32 | else {
33 | vfprintf(stderr, message, args);
34 | }
35 |
36 | va_end(args);
37 | }
38 |
39 | void log_opengl_error()
40 | {
41 | int e = glGetError();
42 | if (e != 0) {
43 | printf("OpenGL Error: 0x%x\n\n", e);
44 | }
45 | }
46 |
47 | void log_opengl_clear_errors()
48 | {
49 | while (glGetError() != 0);
50 | }
--------------------------------------------------------------------------------
/src/log.h:
--------------------------------------------------------------------------------
1 | #ifndef LOG_H
2 | #define LOH_H
3 |
4 | #define ERROR_LOG 0 /* 0 = print errors to stdout
5 | 1 = print errors to log.txt */
6 |
7 | void log_init();
8 | void log(const char* message, ...);
9 | void log_opengl_error();
10 | void log_opengl_clear_errors();
11 |
12 | #endif
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "GL/glew.h"
2 | #include "SDL.h"
3 | #include "SDL_opengl.h"
4 |
5 | #include "glm/glm.hpp"
6 | #include "glm/gtc/matrix_transform.hpp"
7 | #include "glm/gtc/type_ptr.hpp"
8 |
9 | #include "camera.h"
10 | #include "cloud_tiling.h"
11 | #include "cloud_preprocess.h"
12 | #include "framebuffer.h"
13 | #include "fullscreen_quad.h"
14 | #include "log.h"
15 | #include "model.h"
16 | #include "quad.h"
17 | #include "shader.h"
18 | #include "texture.h"
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #define OPENGL_MAJOR_VERSION 4
27 | #define OPENGL_MINOR_VERSION 5
28 |
29 | #define FULLSCREEN 0
30 | #define VERTICAL_SYNC 0
31 |
32 | #define CLOUD_TILE 0
33 |
34 | #if FULLSCREEN
35 | #define SCREEN_WIDTH 1920
36 | #define SCREEN_HEIGHT 1600
37 | #else
38 | #define SCREEN_WIDTH 1280
39 | #define SCREEN_HEIGHT 720
40 | #endif
41 |
42 | /* Main function */
43 | int main(int argc, char** argv)
44 | {
45 | /* Initialize Log file */
46 | log_init();
47 |
48 | /* Initialize SDL */
49 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
50 | log("Error: %s\n", SDL_GetError());
51 | return 1;
52 | }
53 |
54 | /*Set OpenGL attributes */
55 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_MAJOR_VERSION);
56 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_MINOR_VERSION);
57 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
58 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
59 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
60 | SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
61 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
62 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
63 | SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
64 | SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); // Anti-aliasing: 0 = Off, 4 = On
65 |
66 | /* Create SDL window */
67 | #if FULLSCREEN
68 | SDL_Window* window = SDL_CreateWindow("Clouds", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
69 | SCREEN_WIDTH, SCREEN_HEIGHT,
70 | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN);
71 | #else
72 | SDL_Window* window = SDL_CreateWindow("Clouds", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
73 | SCREEN_WIDTH, SCREEN_HEIGHT,
74 | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
75 | #endif
76 |
77 | if (window == NULL) {
78 | log("Error: %s\n", SDL_GetError());
79 | return -1;
80 | }
81 |
82 | /* Create a window icon */
83 | SDL_Surface *icon = SDL_LoadBMP("./res/window_icon.bmp");
84 | SDL_SetWindowIcon(window, icon);
85 | SDL_FreeSurface(icon);
86 |
87 | /* Create OpenGL context */
88 | SDL_GLContext context = SDL_GL_CreateContext(window);
89 | if (context == NULL) {
90 | log("Error: %s\n", SDL_GetError());
91 | return -1;
92 | }
93 |
94 | /* Use vertical sync */
95 | if (SDL_GL_SetSwapInterval(VERTICAL_SYNC) != 0) {
96 | log("Error: %s\n", SDL_GetError());
97 | }
98 |
99 | /* Start GLEW */
100 | glewExperimental = GL_TRUE;
101 | if (glewInit() != GLEW_OK) {
102 | log("Error: GLEW failed to initialize.\n");
103 | }
104 |
105 | /* OpenGL settings */
106 | log_opengl_clear_errors();
107 | glEnable(GL_DEPTH_TEST);
108 | glDepthFunc(GL_LESS);
109 | glClearColor(0.0, 0.0, 0.0, 1.0);
110 | glFrontFace(GL_CCW);
111 | glEnable(GL_CULL_FACE);
112 | glCullFace(GL_BACK);
113 | glEnable(GL_BLEND);
114 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
115 | glDepthRange(CAMERA_NEAR, CAMERA_FAR);
116 | //glEnable(GL_TEXTURE_3D);
117 | log_opengl_error();
118 |
119 | /* Initialize camera */
120 | Camera camera;
121 | camera_init(&camera, SCREEN_WIDTH, SCREEN_HEIGHT, CAMERA_FOV, CAMERA_NEAR, CAMERA_FAR);
122 |
123 | /* Initialize shaders */
124 | log("Loading sky shader...\n");
125 | Shader sky_shader;
126 | if (shader_init(&sky_shader, "./res/shaders/sky.vert", "./res/shaders/sky.frag") != 0) {
127 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
128 | }
129 |
130 | log("Loading terrain shader...\n");
131 | Shader terrain_shader;
132 | if (shader_init(&terrain_shader, "./res/shaders/terrain.vert", "./res/shaders/terrain.frag") != 0) {
133 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
134 | }
135 |
136 | #if CLOUD_TILE
137 | log("Loading resolve shader (tile based)...\n");
138 | Shader resolve_shader;
139 | if (shader_init(&resolve_shader, "./res/shaders/resolve.vert", "./res/shaders/resolve_tile.frag") != 0) {
140 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
141 | }
142 | #else
143 | log("Loading resolve shader (noise based)...\n");
144 | Shader resolve_shader;
145 | if (shader_init(&resolve_shader, "./res/shaders/resolve.vert", "./res/shaders/resolve_noise.frag") != 0) {
146 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
147 | }
148 | #endif
149 |
150 | log("Loading blur shader...\n");
151 | Shader blur_shader;
152 | if (shader_init(&blur_shader, "./res/shaders/blur.vert", "./res/shaders/blur.frag") != 0) {
153 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
154 | }
155 |
156 | log("Loading post shader...\n");
157 | Shader post_shader;
158 | if (shader_init(&post_shader, "./res/shaders/post.vert", "./res/shaders/post.frag") != 0) {
159 | log("Error: Failed to initialize shader in %s at line %d.\n\n", __FILE__, __LINE__);
160 | }
161 |
162 | /* Set up framebuffers */
163 | log("Setting up framebuffers...\n");
164 | Framebuffer scene_framebuffer;
165 | framebuffer_scene_init(&scene_framebuffer, SCREEN_WIDTH, SCREEN_HEIGHT);
166 |
167 | Framebuffer cloud_framebuffer;
168 | framebuffer_cloud_init(&cloud_framebuffer, SCREEN_WIDTH, SCREEN_HEIGHT);
169 |
170 | Framebuffer pingpong_framebuffer[2];
171 | framebuffer_pingpong_init(pingpong_framebuffer, SCREEN_WIDTH, SCREEN_HEIGHT);
172 |
173 | /* Load models */
174 | log("\nLoading sky dome...\n");
175 | Model sky_model;
176 | if (model_load_obj(&sky_model, "./res/models/sky_uv.obj") != 0) {
177 | log("Error: Failed to load model in %s at line %d.\n\n", __FILE__, __LINE__);
178 | }
179 | sky_model.shader = sky_shader;
180 | sky_model.scale = glm::vec3(1000.0f, 1000.0f, 1000.0f);
181 | Model sun;
182 |
183 | log("Loading terrain plane...\n");
184 | Model terrain_model;
185 | if (model_load_obj(&terrain_model, "./res/models/terrain_uv.obj") != 0) {
186 | log("Error: Failed to load model in %s at line %d.\n\n", __FILE__, __LINE__);
187 | }
188 | terrain_model.shader = terrain_shader;
189 |
190 | /* Create textures */
191 | log("\nLoading terrain texture...\n");
192 | Texture terrain_texture;
193 | if (texture2D_from_ex5(&terrain_texture, "./res/textures/terrain.ex5") != 0) {
194 | log("Error: Failed to load texture in %s at line %d.\n\n", __FILE__, __LINE__);
195 | }
196 |
197 | log("Loading 3D cloud texture...\n");
198 | Texture cloud_texture;
199 | if (texture3D_from_ex5(&cloud_texture, "./res/textures/noise5.ex5") != 0) {
200 | log("Error: Failed to load texture in %s at line %d.\n\n", __FILE__, __LINE__);
201 | }
202 |
203 | log("Loading Mie phase texture...\n");
204 | Texture mie_texture;
205 | if (texture1D_phase(&mie_texture, "./res/textures/phase.txt") != 0) {
206 | log("Error: Failed to load texture in %s at line %d.\n\n", __FILE__, __LINE__);
207 | }
208 |
209 | #if CLOUD_TILE
210 | /* Preprocess for the tile based clouds */
211 | log("\nPreprocessing cloud structure (tile based)...\n");
212 | Texture cloud_structure;
213 | Texture cloud_tiles[5];
214 | cloud_tiling_init(cloud_tiles, &cloud_structure);
215 |
216 | /* Send textures to shaders */
217 | shader_send_texture3D(resolve_shader, cloud_structure, "cloud_structure");
218 | shader_send_texture3D(resolve_shader, cloud_tiles[0], "cloud_tile00");
219 | #else
220 | /* Preprocess the structure of the noise based clouds */
221 | log("\nPreprocessing cloud structure (noise based)...\n");
222 | Texture cloud_structure_texture;
223 | cloud_preprocess(&cloud_structure_texture, cloud_texture);
224 |
225 | /* Send textures to shaders */
226 | shader_send_texture3D(resolve_shader, cloud_texture, "cloud_texture");
227 | shader_send_texture3D(resolve_shader, cloud_structure_texture, "cloud_structure");
228 | #endif
229 |
230 | /* Send textures to shaders */
231 | shader_send_texture2D(terrain_shader, terrain_texture, "terrain_texture");
232 | shader_send_texture1D(resolve_shader, mie_texture, "mie_texture");
233 |
234 | /* Main loop */
235 | log("\nStarting main loop.\n");
236 | bool exit = false;
237 | float delta_time = 0.0f;
238 | auto last_frame = std::chrono::high_resolution_clock::now();
239 | float avrage_timer = 0.0f;
240 | bool camera_test = false;
241 | int camera_track = 1;
242 | Uint64 camera_time = 0;
243 | Uint64 camera_start = 0;
244 | Uint64 camera_end = 0;
245 | Uint64 camera_era = 0;
246 | Uint64 camera_duration = 20 * SDL_GetPerformanceFrequency();
247 | Uint64 frame_counter = 0;
248 | FILE* perf;
249 | Uint64 prev_count = 0;
250 |
251 | while (!exit) {
252 | /* Frame time calculation */
253 | auto current_time = std::chrono::high_resolution_clock::now();
254 | delta_time = std::chrono::duration_cast(current_time - last_frame).count() / 1000.0;
255 | last_frame = current_time;
256 | avrage_timer += delta_time;
257 |
258 | if (avrage_timer > 1000) {
259 | char title[128];
260 | sprintf(title, "Clouds -- Frame time: %.2f ms, FPS: %.0f", delta_time, 1000.0 / delta_time);
261 | SDL_SetWindowTitle(window, title);
262 | avrage_timer = 0;
263 | }
264 |
265 | /* Event handling */
266 | SDL_Event e;
267 | while (SDL_PollEvent(&e)) {
268 | if (e.type == SDL_QUIT) {
269 | exit = true;
270 | }
271 |
272 | if (e.type == SDL_KEYDOWN) {
273 | if (e.key.keysym.sym == SDLK_ESCAPE) {
274 | exit = true;;
275 | }
276 | if (e.key.keysym.sym == SDLK_r) {
277 | log("Recompiling active shaders...\n\n");
278 | shader_recompile();
279 |
280 | /* Send textures to shaders */
281 | #if CLOUD_TILE
282 |
283 | shader_send_texture3D(resolve_shader, cloud_structure, "cloud_structure");
284 | shader_send_texture3D(resolve_shader, cloud_tiles[0], "cloud_tile00");
285 | #else
286 | shader_send_texture3D(resolve_shader, cloud_texture, "cloud_texture");
287 | shader_send_texture3D(resolve_shader, cloud_structure_texture, "cloud_structure");
288 | #endif
289 | shader_send_texture2D(terrain_shader, terrain_texture, "terrain_texture");
290 | shader_send_texture1D(resolve_shader, mie_texture, "mie_texture");
291 | }
292 | if (e.key.keysym.sym == SDLK_F1) {
293 | if (!camera_test) {
294 | log("Running performance test...");
295 | perf = fopen("./performance_data_inv_cpu.txt", "w");
296 | frame_counter = 0;
297 | prev_count = SDL_GetPerformanceCounter();
298 | camera_track = 1;
299 | camera_start = SDL_GetPerformanceCounter();
300 | camera_end = camera_start + camera_duration;
301 | camera_era = camera_start;
302 | camera_test = true;
303 | }
304 | }
305 | }
306 |
307 | if (e.type == SDL_MOUSEBUTTONDOWN) {
308 | if (e.button.button == SDL_BUTTON_LEFT) {
309 | camera_toggle_mouse(&camera, window);
310 | }
311 | }
312 |
313 | if (e.type == SDL_MOUSEMOTION) {
314 | if (camera.enabled == SDL_TRUE) {
315 | camera.pitch -= camera.sensitivity * e.motion.yrel;
316 | camera.yaw += camera.sensitivity * e.motion.xrel;
317 | }
318 |
319 | }
320 | }
321 |
322 | ///////////////////////////////////////////////////// http://advances.realtimerendering.com/s2015/The%20Real-time%20Volumetric%20Cloudscapes%20of%20Horizon%20-%20Zero%20Dawn%20-%20ARTR.pdf
323 | ///////////////////////////////////////////////////// http://freespace.virgin.net/hugo.elias/models/m_clouds.htm
324 | ///////////////////////////////////////////////////// http://www.neilblevins.com/cg_education/procedural_noise/procedural_noise.html
325 | ///////////////////////////////////////////////////// http://wiki.nuaj.net/index.php?title=Clouds
326 | ///////////////////////////////////////////////////// http://www-evasion.imag.fr/Publications/2006/BNL06/
327 | ///////////////////////////////////////////////////// http://learnopengl.com/#!Advanced-Lighting/HDR
328 |
329 | /* Camera movement */
330 | if (camera_test) {
331 |
332 | camera_time = SDL_GetPerformanceCounter() - camera_start;
333 |
334 |
335 | double frame_time = (double)((SDL_GetPerformanceCounter() - prev_count) * 1000) / SDL_GetPerformanceFrequency();
336 | double total_time = (double)((SDL_GetPerformanceCounter() - camera_era) * 1000) / SDL_GetPerformanceFrequency();
337 |
338 | fprintf(perf, "%f %f\n", total_time, frame_time);
339 | prev_count = SDL_GetPerformanceCounter();
340 |
341 | switch (camera_track) {
342 | case 1:
343 | camera_track1(&camera, camera_time, camera_duration);
344 | break;
345 | case 2:
346 | camera_track2(&camera, camera_time, camera_duration);
347 | break;
348 | case 3:
349 | camera_track3(&camera, camera_time, camera_duration);
350 | break;
351 | case 4:
352 | camera_track4(&camera, camera_time, camera_duration);
353 | break;
354 | }
355 |
356 | if (camera_time > camera_duration) {
357 | camera_track++;
358 | camera_time = 0;
359 | camera_start = SDL_GetPerformanceCounter();
360 | camera_end = camera_start + camera_duration;
361 | double elapsed_time = (double)((camera_start - camera_era) * 1000) / SDL_GetPerformanceFrequency();
362 | if (camera_track > 4) {
363 | log("Done\n");
364 | log("Time passed: %f ms\n", elapsed_time);
365 | log("Total frames rendered: %" SDL_PRIu64 "\n", frame_counter);
366 | log("Average frame time: %f ms\n", elapsed_time / frame_counter);
367 | log("Average frequency: %f f/s\n\n", (double)frame_counter / (elapsed_time / 1000));
368 | fprintf(perf, "\n");
369 | fclose(perf);
370 | camera_test = false;
371 | }
372 | }
373 | } else {
374 | camera_movement(&camera, delta_time);
375 | }
376 | sky_model.position = camera.position;
377 | sun.position = camera.position + glm::vec3(1000.0f, 1000.0f, 1000.0f);
378 |
379 | /* Calculate view and projection matrices and send them to shaders */
380 | shader_uniform_mat4(terrain_shader, model_model_matrix(terrain_model), "model");
381 | shader_uniform_mat4(terrain_shader, camera_view_matrix(&camera), "view");
382 | shader_uniform_mat4(terrain_shader, camera_projection_matrix(&camera), "proj");
383 |
384 | shader_uniform_mat4(sky_shader, model_model_matrix(sky_model), "model");
385 | shader_uniform_mat4(sky_shader, camera_view_matrix(&camera), "view");
386 | shader_uniform_mat4(sky_shader, camera_projection_matrix(&camera), "proj");
387 |
388 | shader_uniform_mat4(resolve_shader, camera_view_matrix(&camera), "view");
389 | shader_uniform_mat4(resolve_shader, camera_projection_matrix(&camera), "proj");
390 |
391 | shader_uniform_mat4(resolve_shader, glm::inverse(camera_view_matrix(&camera)), "inv_view");
392 | shader_uniform_mat4(resolve_shader, glm::inverse(camera_projection_matrix(&camera)), "inv_proj");
393 |
394 | /* Send miscellaneous uniforms to shaders */
395 | shader_uniform_vec3(terrain_shader, camera.position, "camera_pos");
396 |
397 | shader_uniform_vec3(sky_shader, camera.position, "camera_pos");
398 | shader_uniform_vec3(sky_shader, sun.position, "sun_pos");
399 |
400 | shader_uniform_vec2(resolve_shader, glm::vec2(SCREEN_WIDTH, SCREEN_HEIGHT), "view_port");
401 | shader_uniform_vec3(resolve_shader, camera.position, "camera_pos");
402 | shader_uniform_vec3(resolve_shader, sun.position, "sun_pos");
403 |
404 | /*** OpenGL rendering ***/
405 |
406 | /* Render terrain and sky */
407 | glBindFramebuffer(GL_FRAMEBUFFER, scene_framebuffer.fbo);
408 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
409 | model_render(sky_model);
410 | model_render(terrain_model);
411 |
412 | /* Render clouds via resolve shader */
413 | glBindFramebuffer(GL_FRAMEBUFFER, cloud_framebuffer.fbo);
414 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
415 |
416 | shader_use(resolve_shader);
417 |
418 | glActiveTexture(GL_TEXTURE10);
419 | glBindTexture(GL_TEXTURE_2D, scene_framebuffer.color_buffer[0]);
420 | GLuint diffuse_buffer = glGetUniformLocation(resolve_shader.shader_program, "diffuse_buffer");
421 | glUniform1i(diffuse_buffer, 10);
422 |
423 | render_quad();
424 |
425 | /* Pinpong buffers for bloom */
426 | GLboolean horizontal = true, first_iteration = true;
427 | GLuint amount = 10;
428 | shader_use(blur_shader);
429 | for (GLuint i = 0; i < amount; i++) {
430 | glBindFramebuffer(GL_FRAMEBUFFER, pingpong_framebuffer[horizontal].fbo);
431 | glUniform1i(glGetUniformLocation(blur_shader.shader_program, "horizontal"), horizontal);
432 | glActiveTexture(GL_TEXTURE5);
433 | glBindTexture(GL_TEXTURE_2D, first_iteration ? cloud_framebuffer.color_buffer[1] : pingpong_framebuffer[!horizontal].color_buffer[0]);
434 | GLuint image = glGetUniformLocation(blur_shader.shader_program, "image");
435 | glUniform1i(image, 5);
436 |
437 | render_quad();
438 | horizontal = !horizontal;
439 | if (first_iteration)
440 | first_iteration = false;
441 | }
442 |
443 | /* Render to screen via post shader */
444 | glBindFramebuffer(GL_FRAMEBUFFER, 0);
445 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
446 | shader_use(post_shader);
447 |
448 | glActiveTexture(GL_TEXTURE11);
449 | glBindTexture(GL_TEXTURE_2D, cloud_framebuffer.color_buffer[0]);
450 | GLuint hdr_buffer = glGetUniformLocation(post_shader.shader_program, "HDR_buffer");
451 | glUniform1i(hdr_buffer, 11);
452 |
453 | glActiveTexture(GL_TEXTURE12);
454 | glBindTexture(GL_TEXTURE_2D, pingpong_framebuffer[!horizontal].color_buffer[0]);
455 | GLuint bloom = glGetUniformLocation(post_shader.shader_program, "bloom_blur");
456 | glUniform1i(bloom, 12);
457 |
458 | render_quad();
459 |
460 | SDL_GL_SwapWindow(window);
461 |
462 | frame_counter++;
463 | }
464 |
465 | /* Shutdown functions */
466 | SDL_Quit();
467 |
468 | return 0;
469 | }
--------------------------------------------------------------------------------
/src/model.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rikardolajos/clouds/855cd20a7ab389136a38e8dfe9571531cd034959/src/model.cpp
--------------------------------------------------------------------------------
/src/model.h:
--------------------------------------------------------------------------------
1 | #ifndef MODEL_H
2 | #define MODEL_H
3 |
4 | #include "GL/glew.h"
5 | #include "shader.h"
6 | #include "glm/glm.hpp"
7 |
8 | typedef struct Model Model;
9 | struct Model {
10 | Shader shader;
11 | GLuint vertex_array_object;
12 | int triangles;
13 |
14 | glm::vec3 position;
15 | glm::vec3 rotation;
16 | glm::vec3 scale;
17 | };
18 |
19 | int model_load_obj(Model* m, const char* file_path);
20 | void model_render(Model m);
21 | glm::mat4 model_model_matrix(Model m);
22 |
23 | #endif
--------------------------------------------------------------------------------
/src/quad.cpp:
--------------------------------------------------------------------------------
1 | #include "quad.h"
2 |
3 | #include "GL/glew.h"
4 |
5 | static GLuint quad_vao = 0;
6 | static GLuint quad_vbo = 0;
7 |
8 | void render_quad()
9 | {
10 | if (quad_vao == 0) {
11 | GLfloat quadVertices[] = {
12 | // Positions // Texture Coords
13 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
14 | -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
15 | 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
16 | 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
17 | };
18 | glGenVertexArrays(1, &quad_vao);
19 | glGenBuffers(1, &quad_vbo);
20 | glBindVertexArray(quad_vao);
21 | glBindBuffer(GL_ARRAY_BUFFER, quad_vbo);
22 | glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
23 | glEnableVertexAttribArray(0);
24 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
25 | glEnableVertexAttribArray(1);
26 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
27 | }
28 | glBindVertexArray(quad_vao);
29 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
30 | glBindVertexArray(0);
31 | }
--------------------------------------------------------------------------------
/src/quad.h:
--------------------------------------------------------------------------------
1 | #ifndef QUAD_H
2 | #define QUAD_H
3 |
4 | void render_quad();
5 |
6 | #endif
--------------------------------------------------------------------------------
/src/shader.cpp:
--------------------------------------------------------------------------------
1 | #include "shader.h"
2 |
3 | #include "GL/glew.h"
4 | #include "glm/gtc/type_ptr.hpp"
5 |
6 | #include "log.h"
7 | #include "texture.h"
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | static Shader* active_shaders[24] = { 0 };
15 | static int active_index = 0;
16 |
17 | #define ERROR_LOG 0 /* 0 = print errors to stderr
18 | 1 = print errors to shader_error_log.txt */
19 |
20 | static void shader_info_log(GLuint s)
21 | {
22 | int max_length = 2048;
23 | int len = 0;
24 | char info_log[2048] = { 0 };
25 | glGetShaderInfoLog(s, max_length, &len, info_log);
26 | log("--> %s\n", info_log);
27 | }
28 |
29 | static void program_info_log(GLuint s)
30 | {
31 | int max_length = 2048;
32 | int len = 0;
33 | char info_log[2048] = { 0 };
34 | glGetProgramInfoLog(s, max_length, &len, info_log);
35 | log("--> %s\n", info_log);
36 | }
37 |
38 | /* Read from file and store in a string */
39 | static char* read_file(const char* file_path)
40 | {
41 | char* file_contents;
42 | long input_file_size;
43 |
44 | FILE* input_file = fopen(file_path, "rb");
45 | if (input_file == NULL) {
46 | log("Error: Unable to open file: %s\n", file_path);
47 | return NULL;
48 | }
49 | fseek(input_file, 0, SEEK_END);
50 | input_file_size = ftell(input_file);
51 | rewind(input_file);
52 | file_contents = (char*)malloc((input_file_size + 1) * (sizeof(char)));
53 | fread(file_contents, sizeof(char), input_file_size, input_file);
54 | fclose(input_file);
55 | file_contents[input_file_size] = 0;
56 |
57 | return file_contents;
58 | }
59 |
60 | int shader_init(Shader* shader, const char* vertex_shader_path, const char* fragment_shader_path, int recompile)
61 | {
62 | char* vertex_source = read_file(vertex_shader_path);
63 | char* fragment_source = read_file(fragment_shader_path);
64 |
65 | if (vertex_source == NULL || fragment_source == NULL) {
66 | return -1;
67 | }
68 |
69 | strcpy(shader->path_vertex, vertex_shader_path);
70 | strcpy(shader->path_fragment, fragment_shader_path);
71 |
72 | if (recompile == 0) {
73 | active_shaders[active_index++] = shader;
74 | }
75 |
76 | /* Compile vertex shader */
77 | log("Compiling: %s\n", vertex_shader_path);
78 | if (recompile == 0) {
79 | shader->vertex_shader = glCreateShader(GL_VERTEX_SHADER);
80 | }
81 | glShaderSource(shader->vertex_shader, 1, &vertex_source, NULL);
82 | glCompileShader(shader->vertex_shader);
83 |
84 | int params = -1;
85 | glGetShaderiv(shader->vertex_shader, GL_COMPILE_STATUS, ¶ms);
86 | if (GL_TRUE != params) {
87 | log("Error: Shader %s did not compile.\n", vertex_shader_path);
88 | shader_info_log(shader->vertex_shader);
89 | return -1;
90 | }
91 |
92 | /* Compile fragment shader */
93 | log("Compiling: %s\n", fragment_shader_path);
94 | if (recompile == 0) {
95 | shader->fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
96 | }
97 | glShaderSource(shader->fragment_shader, 1, &fragment_source, NULL);
98 | glCompileShader(shader->fragment_shader);
99 |
100 | glGetShaderiv(shader->fragment_shader, GL_COMPILE_STATUS, ¶ms);
101 | if (GL_TRUE != params) {
102 | log("Error: Shader %s did not compile.\n", fragment_shader_path);
103 | shader_info_log(shader->fragment_shader);
104 | return -1;
105 | }
106 |
107 | /* Link vertex shader and fragment shader */
108 | log("Linking: %s and %s\n", vertex_shader_path, fragment_shader_path);
109 | if (recompile == 0) {
110 | shader->shader_program = glCreateProgram();
111 | }
112 | glAttachShader(shader->shader_program, shader->vertex_shader);
113 | glAttachShader(shader->shader_program, shader->fragment_shader);
114 | glLinkProgram(shader->shader_program);
115 |
116 | glGetProgramiv(shader->shader_program, GL_LINK_STATUS, ¶ms);
117 | if (GL_TRUE != params) {
118 | log("Error: Could not link shader program %s and %s.\n", vertex_shader_path, fragment_shader_path);
119 | program_info_log(shader->shader_program);
120 | return -1;
121 | }
122 | log("Shader program compiled and linked successfully.\n\n");
123 |
124 | free(vertex_source);
125 | free(fragment_source);
126 |
127 | return 0;
128 | }
129 |
130 | void shader_recompile()
131 | {
132 | for (int i = 0; i < active_index; i++) {
133 | shader_init(active_shaders[i], active_shaders[i]->path_vertex, active_shaders[i]->path_fragment, 1);
134 | }
135 | }
136 |
137 | void shader_use(Shader shader)
138 | {
139 | glUseProgram(shader.shader_program);
140 | }
141 |
142 | void shader_uniform_mat4(Shader shader, glm::mat4 matrix, const char* name)
143 | {
144 | glUseProgram(shader.shader_program);
145 | GLint uni = glGetUniformLocation(shader.shader_program, name);
146 | glUniformMatrix4fv(uni, 1, GL_FALSE, glm::value_ptr(matrix));
147 | }
148 |
149 | void shader_uniform_vec2(Shader shader, glm::vec2 vector, const char* name)
150 | {
151 | glUseProgram(shader.shader_program);
152 | GLint uni = glGetUniformLocation(shader.shader_program, name);
153 | glUniform2fv(uni, 1, glm::value_ptr(vector));
154 | }
155 |
156 | void shader_uniform_vec3(Shader shader, glm::vec3 vector, const char* name)
157 | {
158 | glUseProgram(shader.shader_program);
159 | GLint uni = glGetUniformLocation(shader.shader_program, name);
160 | glUniform3fv(uni, 1, glm::value_ptr(vector));
161 | }
162 |
163 | void shader_uniform_1f(Shader shader, float f, const char* name)
164 | {
165 | glUseProgram(shader.shader_program);
166 | GLint uni = glGetUniformLocation(shader.shader_program, name);
167 | glUniform1f(uni, f);
168 | }
169 |
170 | void shader_send_texture1D(Shader shader, Texture t, const char* name)
171 | {
172 | glUseProgram(shader.shader_program);
173 | GLint uni = glGetUniformLocation(shader.shader_program, name);
174 | glUniform1i(uni, t.index);
175 | glActiveTexture(GL_TEXTURE0 + t.index);
176 | glBindTexture(GL_TEXTURE_1D, t.object);
177 | }
178 |
179 | void shader_send_texture2D(Shader shader, Texture t, const char* name)
180 | {
181 | glUseProgram(shader.shader_program);
182 | GLint uni = glGetUniformLocation(shader.shader_program, name);
183 | glUniform1i(uni, t.index);
184 | glActiveTexture(GL_TEXTURE0 + t.index);
185 | glBindTexture(GL_TEXTURE_2D, t.object);
186 | }
187 |
188 | void shader_send_texture3D(Shader shader, Texture t, const char* name)
189 | {
190 | glUseProgram(shader.shader_program);
191 | GLint uni = glGetUniformLocation(shader.shader_program, name);
192 | glUniform1i(uni, t.index);
193 | glActiveTexture(GL_TEXTURE0 + t.index);
194 | glBindTexture(GL_TEXTURE_3D, t.object);
195 | }
--------------------------------------------------------------------------------
/src/shader.h:
--------------------------------------------------------------------------------
1 | #ifndef SHADER_H
2 | #define SHADER_H
3 |
4 | #include "GL/glew.h"
5 | #include "glm/glm.hpp"
6 |
7 | #include "texture.h"
8 |
9 | typedef struct Shader Shader;
10 | struct Shader {
11 | GLuint vertex_shader;
12 | GLuint fragment_shader;
13 | GLuint shader_program;
14 | char path_vertex[256];
15 | char path_fragment[256];
16 | };
17 |
18 |
19 | int shader_init(Shader* shader, const char* vertex_shader_path, const char* fragment_shader_path, int recompile = 0);
20 | void shader_recompile();
21 | void shader_use(Shader shader);
22 | void shader_uniform_mat4(Shader shader, glm::mat4 matrix, const char* name);
23 | void shader_uniform_vec2(Shader shader, glm::vec2 vector, const char* name);
24 | void shader_uniform_vec3(Shader shader, glm::vec3 vector, const char* name);
25 | void shader_uniform_1f(Shader shader, float f, const char* name);
26 | void shader_send_texture1D(Shader shader, Texture t, const char* name);
27 | void shader_send_texture2D(Shader shader, Texture t, const char* name);
28 | void shader_send_texture3D(Shader shader, Texture t, const char* name);
29 |
30 | #endif
--------------------------------------------------------------------------------
/src/texture.cpp:
--------------------------------------------------------------------------------
1 | #include "texture.h"
2 |
3 | #include "GL/glew.h"
4 |
5 | #include "log.h"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | static int active_textures = 0;
13 |
14 | void texture_activate(Texture* t)
15 | {
16 | t->index = active_textures++;
17 | }
18 |
19 | int texture1D_phase(Texture* t, const char* file_path)
20 | {
21 | FILE* fp = fopen(file_path, "r");
22 |
23 | if (fp == NULL) {
24 | return -1;
25 | }
26 |
27 | texture_activate(t);
28 |
29 | /* Create image */
30 | uint8_t* data = (uint8_t*)calloc(1801, sizeof *data);
31 |
32 | /* Read image*/
33 | int i = 0;
34 | char value[128];
35 | while (fgets(value, 128, fp)) {
36 | value[strlen(value) - 1] = '\0';
37 | data[i++] = (uint8_t)(255 * atof(value));
38 | }
39 |
40 | glGenTextures(1, &t->object);
41 | glBindTexture(GL_TEXTURE_1D, t->object);
42 |
43 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RED, 1800, 0, GL_RED, GL_UNSIGNED_BYTE, data);
44 | glGenerateMipmap(GL_TEXTURE_1D);
45 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
46 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
47 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
48 |
49 | free(data);
50 |
51 | return 0;
52 | }
53 |
54 | int texture2D_from_ex5(Texture* t, const char* file_path)
55 | {
56 | FILE* fp = fopen(file_path, "r");
57 |
58 | if (fp == NULL) {
59 | return -1;
60 | }
61 |
62 | texture_activate(t);
63 |
64 | /* Read header */
65 | fscanf(fp, "%d", &t->width);
66 | fscanf(fp, "%d", &t->height);
67 |
68 | /* Create image */
69 | uint8_t* data = (uint8_t*)calloc(t->width * t->height * 4, sizeof *data);
70 |
71 | /* Read image*/
72 | int i = 0;
73 | uint32_t pixel;
74 | while (fscanf(fp, "%d", &pixel) == 1) {
75 | data[i++] = pixel >> 24;
76 | data[i++] = pixel >> 16;
77 | data[i++] = pixel >> 8;
78 | data[i++] = pixel >> 0;
79 | }
80 |
81 | glGenTextures(1, &t->object);
82 | glBindTexture(GL_TEXTURE_2D, t->object);
83 |
84 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t->width, t->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
85 | glGenerateMipmap(GL_TEXTURE_2D);
86 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
87 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
88 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
89 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
90 |
91 | free(data);
92 |
93 | return 0;
94 | }
95 |
96 | int texture3D_from_ex5(Texture* t, const char* file_path)
97 | {
98 | FILE* fp = fopen(file_path, "r");
99 |
100 | if (fp == NULL) {
101 | return -1;
102 | }
103 |
104 | texture_activate(t);
105 |
106 | /* Read header */
107 | fscanf(fp, "%d", &t->width);
108 | fscanf(fp, "%d", &t->height);
109 | fscanf(fp, "%d", &t->depth);
110 |
111 | /* Create image */
112 | uint8_t* data = (uint8_t*)calloc(t->width * t->height * t->depth * 4, sizeof *data);
113 |
114 | /* Read image*/
115 | int i = 0;
116 | uint32_t pixel;
117 | while (fscanf(fp, "%d", &pixel) == 1) {
118 | data[i++] = pixel >> 24;
119 | data[i++] = pixel >> 16;
120 | data[i++] = pixel >> 8;
121 | data[i++] = pixel >> 0;
122 | }
123 |
124 | glGenTextures(1, &t->object);
125 | glBindTexture(GL_TEXTURE_3D, t->object);
126 |
127 | glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, t->width, t->height, t->depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
128 | glGenerateMipmap(GL_TEXTURE_3D);
129 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
130 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
131 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
132 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
133 | glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
134 |
135 | free(data);
136 |
137 | return 0;
138 | }
--------------------------------------------------------------------------------
/src/texture.h:
--------------------------------------------------------------------------------
1 | #ifndef TEXTURE_H
2 | #define TEXTURE_H
3 |
4 | #include "GL/glew.h"
5 |
6 | typedef struct Texture Texture;
7 | struct Texture {
8 | GLuint object;
9 | GLuint index;
10 | int width, height, depth;
11 | };
12 |
13 | void texture_activate(Texture* t);
14 | int texture1D_phase(Texture* t, const char* file_path);
15 | int texture2D_from_ex5(Texture* t, const char* file_path);
16 | int texture3D_from_ex5(Texture* t, const char* file_path);
17 |
18 | #endif
--------------------------------------------------------------------------------