mse / RSOD (public) (License: CC0 and other licenses) (since 2025-03-01) (hash sha1)
Free software FPS engine
List of commits:
Subject Hash Author Date (UTC)
Simplify debug build, add tonemapping postfx d7a1fdba5076eed05f2eb461c2db055bbfcd1dc3 MSE 2025-03-28 07:17:04
Continue interrupted dependency downloads b4b1b6527beae96cdb22e86d1f85579097e510ff MSE 2025-02-20 03:39:47
Add non-PBR rendering mode 73e514a9ee1d293da1882be089e063299efb58ed MSE 2025-02-08 00:36:59
Support non-square particle textures c89c63128d49d85411cb734580ad3bcfe972ba84 MSE 2025-01-02 08:41:59
Add aggressive/non-aggressive states to AI 2d34985bb1de0e18b1362471b53febf52a06fa23 MSE 2024-12-31 19:28:15
Emit particles within discRadius on XZ plane 2dc76026bf72da5951acf460de7dba9e7a4ac176 MSE 2024-12-30 20:25:52
Fix particle system regression 3711cfc1cfb24de67a75c5327b71825cad86f730 MSE 2024-12-24 02:08:06
Bugfix: clear particles on world unload 7b324698fce599637dd36c8e2e22056b2102c98f MSE 2024-12-20 02:20:25
Support vertical billboard particles 30d41a303b59d60439e30607b3345f5485fb1eb5 MSE 2024-12-20 02:12:41
Add continuous particle emitters 60abc606556ec80c0c930a504da4c24e1571fbc5 MSE 2024-12-18 06:45:42
Add defaultRain field (for later use) ecb27b40a1f17abdcdfb72f38945d1f98fabc648 MSE 2024-12-15 02:42:08
Support negative mass particles 37a0a4bfc78adb26ba4b9ba69688738c6c7467dc MSE 2024-12-13 17:35:01
Prevent Avatar::blendTo from freezing on same animation d990a5b32602a879e405c5e527ce3047e346bfba MSE 2024-09-25 02:37:26
Restructure Avatar::simulate 9519e901631ea04a1a93e24504d8f37c521164d1 MSE 2024-09-24 06:51:15
Blend avatar jump animations 8d26db0ecd4ef6a48546684e4bf2200bfea0f41b MSE 2024-09-20 08:19:20
Work on animation blending system eb5cfcf1387131b1ec8449e671d30efd787363b2 MSE 2024-09-20 06:40:35
Update stb_truetype 4948f1d29f33a33dc126d842d8d20f732f4cdef0 MSE 2024-09-18 17:38:06
Allow joystick to override mouse 6aba7a71ebe0dbd67717ae5a37e1729ebfe9895c MSE 2024-09-15 23:13:30
Add weapon switching via D-pad db14ce946f4c65ab6625875f00f82ee1b8052374 MSE 2024-09-15 20:10:20
Allow crouch to be turned off via playerCrouch flag 024d43d877ca16d21e0feeb50d70f82acd449335 MSE 2024-09-15 03:02:29
Commit d7a1fdba5076eed05f2eb461c2db055bbfcd1dc3 - Simplify debug build, add tonemapping postfx
Author: MSE
Author date (UTC): 2025-03-28 07:17
Committer name: MSE
Committer date (UTC): 2025-03-28 07:17
Parent(s): b4b1b6527beae96cdb22e86d1f85579097e510ff
Signer:
Signing key:
Signing status: N
Tree: d33f7cf02b37d53f721728f34eb34969b74559a8
File Lines added Lines deleted
Makefile 3 3
base/glsl/fxaa.frag 0 53
base/glsl/postfx.frag 77 0
base/glsl/postfx.vert 0 0
include/fg3/fg3.h 26 0
src/rsod.cpp 95 20
File Makefile changed (mode: 100644) (index b64a072..91e57f2)
... ... $(PROGRAM)-steam: $(OBJECTS_LIN) libSDL2.a $(BULLET_DYNAMICS) src/$(PROGRAM).cpp
87 87 $(LINCXX) $(CXXFLAGS) -static-libgcc -static-libstdc++ -O3 -D__STEAM__ -o $@ src/$(PROGRAM).cpp $(OBJECTS_LIN) libSDL2.a \ $(LINCXX) $(CXXFLAGS) -static-libgcc -static-libstdc++ -O3 -D__STEAM__ -o $@ src/$(PROGRAM).cpp $(OBJECTS_LIN) libSDL2.a \
88 88 -Wl,-rpath,. -L. -ldl -pthread -lsteam_api $(BULLET_LINKS) $(shell pkg-config --libs gtk+-3.0) -Wl,-rpath,. -L. -ldl -pthread -lsteam_api $(BULLET_LINKS) $(shell pkg-config --libs gtk+-3.0)
89 89
90 debug: clean $(OBJECTS_LIN) libSDL2.a $(BULLET_DYNAMICS) src/$(PROGRAM).cpp
91 $(LINCXX) -Iinclude -Isrc -I$(BULLET_DIR)/src -std=$(CXXSTD) -Wall -Wextra -Wfatal-errors -g -D__DEBUG__ -o $@ src/$(PROGRAM).cpp $(OBJECTS_LIN) libSDL2.a \
92 -Wl,-rpath,. -L. -ldl -pthread $(BULLET_LINKS) $(shell pkg-config --libs gtk+-3.0) -lopenxr_loader
90 debug: clean $(OBJECTS_LIN) $(BULLET_DYNAMICS) src/$(PROGRAM).cpp
91 $(LINCXX) -Iinclude -Isrc -I$(BULLET_DIR)/src -std=$(CXXSTD) -Wall -Wextra -Wfatal-errors -g -D__DEBUG__ -o $@ src/$(PROGRAM).cpp $(OBJECTS_LIN) \
92 -Wl,-rpath,. -L. -ldl -pthread -lSDL2 $(BULLET_LINKS) $(shell pkg-config --libs gtk+-3.0)
93 93
94 94 lint: lint:
95 95 clang-tidy src/$(PROGRAM).cpp -checks=cert-*-cpp -- $(CXXDYNAMIC) clang-tidy src/$(PROGRAM).cpp -checks=cert-*-cpp -- $(CXXDYNAMIC)
File base/glsl/fxaa.frag deleted (index e2d4891..0000000)
1 uniform sampler2D u_texture;
2 in vec2 v_UV;
3 out vec4 fragColor;
4
5 const float FXAA_SUBPIX_SHIFT = 1.0 / 4.0;
6 const float FXAA_REDUCE_MIN = 1.0 / 128.0;
7 const float FXAA_SPAN_MAX = 8.0;
8 const float FXAA_REDUCE_MUL = 1.0 / 8.0;
9
10 void main(){
11 vec2 rcpFrame = v_UV / gl_FragCoord.xy;
12 vec2 tc = v_UV - rcpFrame * ( 0.5 + FXAA_SUBPIX_SHIFT );
13 vec3 rgbNW = textureLod(u_texture, tc, 0.0).xyz;
14 vec3 rgbNE = textureLodOffset(u_texture, tc, 0.0, ivec2(1,0)).xyz;
15 vec3 rgbSW = textureLodOffset(u_texture, tc, 0.0, ivec2(0,1)).xyz;
16 vec3 rgbSE = textureLodOffset(u_texture, tc, 0.0, ivec2(1,1)).xyz;
17 vec3 rgbM = textureLod(u_texture, v_UV, 0.0).xyz;
18
19 vec3 luma = vec3(0.2126729, 0.7151522, 0.072175); // Linear weights.
20 float lumaNW = dot(rgbNW, luma);
21 float lumaNE = dot(rgbNE, luma);
22 float lumaSW = dot(rgbSW, luma);
23 float lumaSE = dot(rgbSE, luma);
24 float lumaM = dot(rgbM, luma);
25
26 float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
27 float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
28
29 vec2 dir = vec2(
30 -((lumaNW + lumaNE) - (lumaSW + lumaSE)),
31 ((lumaNW + lumaSW) - (lumaNE + lumaSE))
32 );
33
34 float dirReduce = max(
35 (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
36 FXAA_REDUCE_MIN);
37
38 float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
39
40 dir = min(
41 vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
42 max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)
43 ) * rcpFrame.xy;
44
45 vec3 rgbA = (1.0 / 2.0) * (
46 textureLod(u_texture, v_UV + dir * (1.0 / 3.0 - 0.5), 0.0).xyz +
47 textureLod(u_texture, v_UV + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
48 vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (
49 textureLod(u_texture, v_UV + dir * (0.0 / 3.0 - 0.5), 0.0).xyz +
50 textureLod(u_texture, v_UV + dir * (3.0 / 3.0 - 0.5), 0.0).xyz);
51 float lumaB = dot(rgbB, luma);
52 fragColor = vec4((lumaB < lumaMin) || (lumaB > lumaMax) ? rgbA : rgbB, 1.0);
53 }
File base/glsl/postfx.frag added (mode: 100644) (index 0000000..d4e95df)
1 uniform sampler2D u_texture;
2 in vec2 v_UV;
3 out vec4 fragColor;
4
5 // Perform antialiasing step?
6 uniform int u_AA;
7
8 // RGB control points.
9 uniform vec3 u_shadow;
10 uniform vec3 u_midtone;
11 uniform vec3 u_highlight;
12
13 const float FXAA_SUBPIX_SHIFT = 1.0 / 4.0;
14 const float FXAA_REDUCE_MIN = 1.0 / 128.0;
15 const float FXAA_SPAN_MAX = 8.0;
16 const float FXAA_REDUCE_MUL = 1.0 / 8.0;
17
18 // Bezier-like tone curve function for a single channel.
19 float ToneCurve(float x, float a, float b, float c){
20 return (1.0 - x) * (1.0 - x) * a + 2.0 * (1.0 - x) * x * b + x * x * c;
21 }
22
23 void main(){
24 vec3 color;
25 if(u_AA == 0){
26 color = textureLod(u_texture, v_UV, 0.0).xyz;
27 }else{
28 vec2 rcpFrame = v_UV / gl_FragCoord.xy;
29 vec2 tc = v_UV - rcpFrame * ( 0.5 + FXAA_SUBPIX_SHIFT );
30 vec3 rgbNW = textureLod(u_texture, tc, 0.0).xyz;
31 vec3 rgbNE = textureLodOffset(u_texture, tc, 0.0, ivec2(1,0)).xyz;
32 vec3 rgbSW = textureLodOffset(u_texture, tc, 0.0, ivec2(0,1)).xyz;
33 vec3 rgbSE = textureLodOffset(u_texture, tc, 0.0, ivec2(1,1)).xyz;
34 vec3 rgbM = textureLod(u_texture, v_UV, 0.0).xyz;
35
36 vec3 luma = vec3(0.2126729, 0.7151522, 0.072175); // Linear weights.
37 float lumaNW = dot(rgbNW, luma);
38 float lumaNE = dot(rgbNE, luma);
39 float lumaSW = dot(rgbSW, luma);
40 float lumaSE = dot(rgbSE, luma);
41 float lumaM = dot(rgbM, luma);
42
43 float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
44 float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
45
46 vec2 dir = vec2(
47 -((lumaNW + lumaNE) - (lumaSW + lumaSE)),
48 ((lumaNW + lumaSW) - (lumaNE + lumaSE))
49 );
50
51 float dirReduce = max(
52 (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
53 FXAA_REDUCE_MIN);
54
55 float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
56
57 dir = min(
58 vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
59 max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)
60 ) * rcpFrame.xy;
61
62 vec3 rgbA = (1.0 / 2.0) * (
63 textureLod(u_texture, v_UV + dir * (1.0 / 3.0 - 0.5), 0.0).xyz +
64 textureLod(u_texture, v_UV + dir * (2.0 / 3.0 - 0.5), 0.0).xyz);
65 vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (
66 textureLod(u_texture, v_UV + dir * (0.0 / 3.0 - 0.5), 0.0).xyz +
67 textureLod(u_texture, v_UV + dir * (3.0 / 3.0 - 0.5), 0.0).xyz);
68 float lumaB = dot(rgbB, luma);
69 color = (lumaB < lumaMin) || (lumaB > lumaMax) ? rgbA : rgbB;
70 }
71 // Apply tone curve to each channel independently.
72 color.r = ToneCurve(color.r, u_shadow.r, u_midtone.r, u_highlight.r);
73 color.g = ToneCurve(color.g, u_shadow.g, u_midtone.g, u_highlight.g);
74 color.b = ToneCurve(color.b, u_shadow.b, u_midtone.b, u_highlight.b);
75
76 fragColor = vec4(color, 1.0);
77 }
File base/glsl/postfx.vert renamed from base/glsl/fxaa.vert (similarity 100%)
File include/fg3/fg3.h changed (mode: 100644) (index 9928925..a5a3477)
... ... Framebuffer createFramebuffer( GLsizei width, GLsizei height, bool cubemap = fal
260 260 void resizeFramebuffer( Framebuffer &fb, GLsizei width, GLsizei height, GLsizei multisample = 0 ); void resizeFramebuffer( Framebuffer &fb, GLsizei width, GLsizei height, GLsizei multisample = 0 );
261 261 Texture getFramebufferTexture( Framebuffer &fb ); Texture getFramebufferTexture( Framebuffer &fb );
262 262 void setFramebuffer( Framebuffer fb = newFramebuffer, float viewScale = 1.0f ); void setFramebuffer( Framebuffer fb = newFramebuffer, float viewScale = 1.0f );
263 void drawQuadToRegion( double x, double y, double width, double height );
263 264 void drawFramebuffer( Framebuffer &fb, bool draw_z = false, float viewScale = 1.0f ); void drawFramebuffer( Framebuffer &fb, bool draw_z = false, float viewScale = 1.0f );
264 265 Framebuffer getIrradianceFramebuffer( Texture in_cubemap, Framebuffer fb = newFramebuffer ); Framebuffer getIrradianceFramebuffer( Texture in_cubemap, Framebuffer fb = newFramebuffer );
265 266 void drawSkybox( Texture &tex, linalg::mat<double,4,4> view, linalg::mat<double,4,4> proj, Color tint = newColor ); void drawSkybox( Texture &tex, linalg::mat<double,4,4> view, linalg::mat<double,4,4> proj, Color tint = newColor );
 
... ... void setFramebuffer( Framebuffer fb, float viewScale ){
1815 1816 } }
1816 1817 } }
1817 1818
1819 // Draw a plane using the provided pixel coordinates.
1820 void drawQuadToRegion(double x, double y, double width, double height){
1821 double screenWidth = getDisplayWidth(), screenHeight = getDisplayHeight();
1822
1823 double normalizedX = (x / screenWidth) * 2.0 - 1.0;
1824 double normalizedY = (y / screenHeight) * -2.0 + 1.0;
1825 double normalizedWidth = (width / screenWidth) * 2.0;
1826 double normalizedHeight = (height / screenHeight) * -2.0;
1827
1828 linalg::vec<double,3> scaleVec = {normalizedWidth, normalizedHeight, 0.0};
1829 linalg::vec<double,3> translateVec = {normalizedX, normalizedY, 0.0};
1830
1831 linalg::mat<double,4,4> modelMat = linalg::mul(
1832 linalg::translation_matrix(translateVec),
1833 linalg::scaling_matrix(scaleVec)
1834 );
1835
1836 drawMesh(
1837 planeMesh,
1838 modelMat,
1839 linalg::identity,
1840 linalg::identity
1841 );
1842 }
1843
1818 1844 void drawFramebuffer( Framebuffer &fb, bool draw_z, float viewScale ){ void drawFramebuffer( Framebuffer &fb, bool draw_z, float viewScale ){
1819 1845 if( !fb.success ) return; if( !fb.success ) return;
1820 1846 if( fb.multisample > 0 ){ if( fb.multisample > 0 ){
File src/rsod.cpp changed (mode: 100644) (index f65ceb1..0f88a0b)
... ... std::vector<std::string> mod_paths = { "game" };
242 242
243 243 fgl::Framebuffer fb_left, fb_right, fb_resolved, fb_bloom_multisample, fb_bloom, fb_bloom_temp, fb_minimap; fgl::Framebuffer fb_left, fb_right, fb_resolved, fb_bloom_multisample, fb_bloom, fb_bloom_temp, fb_minimap;
244 244
245 fgl::Pipeline fxaaPipeline, anaglyphPipeline, bloomBlurPipeline;
245 fgl::Pipeline postfxPipeline, anaglyphPipeline, bloomBlurPipeline;
246 246
247 247 linalg::vec<double,3> player_angle_init{}; linalg::vec<double,3> player_angle_init{};
248 248
 
... ... fgl::Color ambient_colors[] = {
261 261
262 262 fgl::Color ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f }; fgl::Color ambient_light = { 1.0f, 1.0f, 1.0f, 1.0f };
263 263
264 std::map<std::string,std::vector<fgl::Color>> tonemaps;
265 std::string current_tonemap = "default";
266
264 267 double fadeLevel = 0.0; double fadeLevel = 0.0;
265 268 std::string fade_to = ""; std::string fade_to = "";
266 269
 
... ... int main( int argc, char* argv[] ){
718 721 // Load the trinkets. // Load the trinkets.
719 722 dungeon.appendTrinkets( data_path + "/trinkets", data_path + "/trinkets/unique_trinkets.json" ); dungeon.appendTrinkets( data_path + "/trinkets", data_path + "/trinkets/unique_trinkets.json" );
720 723
721 fxaaPipeline = dungeon.loadShaders( data_path + "/glsl/fxaa.vert", data_path + "/glsl/fxaa.frag", { "u_texture" } );
724 postfxPipeline = dungeon.loadShaders( data_path + "/glsl/postfx.vert", data_path + "/glsl/postfx.frag", { "u_texture" } );
722 725 anaglyphPipeline = dungeon.loadShaders( data_path + "/glsl/anaglyph.vert", data_path + "/glsl/anaglyph.frag", { "u_texture" } ); anaglyphPipeline = dungeon.loadShaders( data_path + "/glsl/anaglyph.vert", data_path + "/glsl/anaglyph.frag", { "u_texture" } );
723 726 bloomBlurPipeline = dungeon.loadShaders( data_path + "/glsl/bloom_blur.vert", data_path + "/glsl/bloom_blur.frag", { "u_texture" } ); bloomBlurPipeline = dungeon.loadShaders( data_path + "/glsl/bloom_blur.vert", data_path + "/glsl/bloom_blur.frag", { "u_texture" } );
724 727
 
... ... void InitEngine( std::string file_name ){
1224 1227 fprintf( stderr, "Warning: ambientColors must include 6 RGB triplets.\n" ); fprintf( stderr, "Warning: ambientColors must include 6 RGB triplets.\n" );
1225 1228 } }
1226 1229 } }
1230 // Map assignments must happen at runtime.
1231 std::vector<fgl::Color> tonemap_colors(3);
1232 tonemap_colors[0] = { 0.0f, 0.0f, 0.0f, 1.0f }; // Shadows.
1233 tonemap_colors[1] = { 1.0f, 1.0f, 1.0f, 1.0f }; // Midtones.
1234 tonemap_colors[2] = { 1.0f, 1.0f, 1.0f, 1.0f }; // Highlights.
1235 tonemaps["default"] = tonemap_colors;
1236 if( info["tonemaps"] ){
1237 for( auto &o : info["tonemaps"].getObject() ){
1238 auto tc = o.value.getArray();
1239 if( tc.size() >= 3 ){
1240 for( size_t i = 0; i < 3; i++ ){
1241 auto c = tc[i].getArray();
1242 if( c.size() >= 3 ){
1243 tonemap_colors[i] =
1244 { c[0].getFloat(), c[1].getFloat(), c[2].getFloat(), 1.0f };
1245 }
1246 }
1247 tonemaps[viewToString( o.name )] = tonemap_colors;
1248 }else{
1249 fprintf( stderr,
1250 "Warning: Each tonemap must include 3 RGB triplets (shadows, midtones, highlights).\n" );
1251 }
1252 }
1253 }
1227 1254
1228 1255 jsonFreeDocument( &allocatedDocument ); jsonFreeDocument( &allocatedDocument );
1229 1256 } }
 
... ... void LoadMap( std::string file_path ){
1948 1975 cs_stop_all_sounds( csctx ); cs_stop_all_sounds( csctx );
1949 1976 return; return;
1950 1977 } }
1978 // Set the tonemap.
1979 if( file_path.length() >= 9
1980 && file_path.substr( 0, 8 ) == "TONEMAP " ){
1981 current_tonemap = file_path.substr( 8 );
1982 return;
1983 }
1951 1984 // Shake the camera for a specified amount of time. // Shake the camera for a specified amount of time.
1952 1985 if( file_path.length() >= 7 && file_path.substr(0, 6) == "SHAKE " ){ if( file_path.length() >= 7 && file_path.substr(0, 6) == "SHAKE " ){
1953 1986 char* p; char* p;
 
... ... void LoadMap( std::string file_path ){
2255 2288 } }
2256 2289 // Stop the playlist. // Stop the playlist.
2257 2290 StopPlaylist(); StopPlaylist();
2291 // Reset the tonemap.
2292 current_tonemap = "default";
2258 2293 // Clear the fade_to string so Warp callbacks can trigger. // Clear the fade_to string so Warp callbacks can trigger.
2259 2294 fade_to = ""; fade_to = "";
2260 2295 // Display a loading screen. // Display a loading screen.
 
... ... void OpenMap(){ // TODO: DRY
2350 2385 fclose( file ); fclose( file );
2351 2386 // Stop the playlist. // Stop the playlist.
2352 2387 StopPlaylist(); StopPlaylist();
2388 // Reset the tonemap.
2389 current_tonemap = "default";
2353 2390 // Reset playtime. // Reset playtime.
2354 2391 playtime = 0.0; playtime = 0.0;
2355 2392 // Reset "map" variables along with map state so that they // Reset "map" variables along with map state so that they
 
... ... void Render(){
2888 2925 playtime += d; playtime += d;
2889 2926 } }
2890 2927
2891 // Resolve the eye framebuffer(s). Use FXAA if applicable.
2892 if( msaa == 0 )
2893 fgl::setPipeline( dungeon.pbr ? fxaaPipeline : fgl::unlitPipeline );
2928 // Resolve the eye framebuffer(s). Use post effects if PBR is enabled.
2929 if(dungeon.pbr){
2930 fgl::setPipeline(postfxPipeline);
2931 auto postprog = postfxPipeline.programObject;
2932 // Enable or disable FXAA.
2933 GLint u_AA = glGetUniformLocation(postprog, "u_AA");
2934 glUniform1i(u_AA, msaa == 0 ? 1 : 0);
2935 // Set tone curves.
2936 std::vector<fgl::Color> &tonemap_colors = tonemaps[current_tonemap];
2937 if(tonemap_colors.size() >= 3){
2938 glUniform3f(glGetUniformLocation(postprog, "u_shadow"),
2939 tonemap_colors[0].r, tonemap_colors[0].g, tonemap_colors[0].b);
2940 glUniform3f(glGetUniformLocation(postprog, "u_midtone"),
2941 tonemap_colors[1].r, tonemap_colors[1].g, tonemap_colors[1].b);
2942 glUniform3f(glGetUniformLocation(postprog, "u_highlight"),
2943 tonemap_colors[2].r, tonemap_colors[2].g, tonemap_colors[2].b);
2944 }
2945 }else{
2946 fgl::setPipeline(fgl::unlitPipeline);
2947 }
2894 2948 fgl::setFog({0.0f, 0.0f, 0.0f, 0.0f}); fgl::setFog({0.0f, 0.0f, 0.0f, 0.0f});
2895 2949 glDisable(GL_BLEND); glDisable(GL_BLEND);
2896 2950 for(int i = 0; i < (use_stereogram ? 2 : 1); i++){ for(int i = 0; i < (use_stereogram ? 2 : 1); i++){
 
... ... void Render(){
2902 2956 // Blit and rely on OpenGL to resolve samples. // Blit and rely on OpenGL to resolve samples.
2903 2957 // There must be zero scaling of the framebuffer // There must be zero scaling of the framebuffer
2904 2958 // when resolving multisampling samples. // when resolving multisampling samples.
2905 // TODO: Anaglyph FXAA.
2959 // TODO: Anaglyph postfx.
2906 2960 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.fbo); glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.fbo);
2907 2961 glBlitFramebuffer( glBlitFramebuffer(
2908 2962 0, 0, fb.width, fb.height, // source 0, 0, fb.width, fb.height, // source
 
... ... void Render(){
2920 2974 fgl::drawFramebuffer(fb_resolved, false, dungeon.frameBufScale); fgl::drawFramebuffer(fb_resolved, false, dungeon.frameBufScale);
2921 2975 } }
2922 2976 }else{ }else{
2923 // Draw the appropriate eye framebuffer.
2924 fgl::drawFramebuffer(fb);
2977 // **************************************************************
2978 // * *
2979 // * /\_/\ *
2980 // * ( o.o ) < This code draws framebuffers with shaders. *
2981 // * > ^ < *
2982 // * *
2983 // **************************************************************
2984 if(msaa == 0){
2985 // No MSAA, so draw the appropriate eye framebuffer.
2986 fgl::drawFramebuffer(fb);
2987 }else{
2988 // Resolve the multisampled framebuffer into fb_resolved.
2989 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.fbo);
2990 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_resolved.fbo);
2991 glBlitFramebuffer(
2992 0, 0, fb.width, fb.height,
2993 0, 0, fb_resolved.width, fb_resolved.height,
2994 GL_COLOR_BUFFER_BIT,
2995 GL_NEAREST
2996 );
2997 // Draw the resolved framebuffer with post effects.
2998 fgl::drawFramebuffer(fb_resolved);
2999 }
2925 3000 // Draw the resolved framebuffer to the screen. // Draw the resolved framebuffer to the screen.
2926 3001 fgl::setFramebuffer(); fgl::setFramebuffer();
3002 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_resolved.fbo);
2927 3003 // Blit the framebuffers left-right. // Blit the framebuffers left-right.
2928 3004 int x = i * fb_resolved.width; int x = i * fb_resolved.width;
2929 glBindFramebuffer( GL_READ_FRAMEBUFFER, fb_resolved.fbo );
2930 3005 glBlitFramebuffer( glBlitFramebuffer(
2931 3006 0, 0, fb_resolved.width * dungeon.frameBufScale, fb_resolved.height * dungeon.frameBufScale, // source 0, 0, fb_resolved.width * dungeon.frameBufScale, fb_resolved.height * dungeon.frameBufScale, // source
2932 3007 x, 0, x + fb_resolved.width + 1, fb_resolved.height + 1, // destination x, 0, x + fb_resolved.width + 1, fb_resolved.height + 1, // destination
 
... ... void Render(){
2936 3011 } }
2937 3012 } }
2938 3013 fgl::setPipeline(fgl::unlitPipeline); fgl::setPipeline(fgl::unlitPipeline);
2939
2940 // Draw the bloom framebuffer to the screen.
2941 if(bloomBlurPipeline.success && !use_stereogram){
2942 glEnable( GL_BLEND );
2943 glBlendFunc( GL_ONE, GL_ONE );
2944 fgl::drawFramebuffer( fb_bloom );
2945 //if( fgl::charKey('z') ){
2946 // glDisable( GL_BLEND );
2947 // fgl::drawFramebuffer( dungeon.shadowBuf );
2948 //}
2949 }
2950 3014 } }
2951 3015
2952 3016 Prepare2D(); Prepare2D();
 
... ... void FirstPersonLoop( double d ){
4040 4104 fgl::drawFramebuffer( fb_bloom_temp ); // from --> fgl::drawFramebuffer( fb_bloom_temp ); // from -->
4041 4105 } }
4042 4106
4107 // Draw the bloom framebuffer to the viewport framebuffer.
4108 if(bloomBlurPipeline.success && !use_stereogram){
4109 fgl::setFramebuffer( fb_left );
4110 // Clear only the depth buffer.
4111 //glClear( GL_DEPTH_BUFFER_BIT );
4112 glEnable( GL_BLEND );
4113 glBlendFunc( GL_ONE, GL_ONE );
4114 fgl::drawFramebuffer( fb_bloom, false, 1.0f / dungeon.frameBufScale );
4115 glDisable( GL_BLEND );
4116 }
4117
4043 4118 // Restore dungeon.playerZoom. // Restore dungeon.playerZoom.
4044 4119 if(use_stereogram && !use_anaglyph) dungeon.playerZoom = zoom_copy; if(use_stereogram && !use_anaglyph) dungeon.playerZoom = zoom_copy;
4045 4120 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/mse/RSOD

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/mse/RSOD

Clone this repository using git:
git clone git://git.rocketgit.com/user/mse/RSOD

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main