diff --git a/include/PICA/pica_frag_config.hpp b/include/PICA/pica_frag_config.hpp index 337fd2116..5d5f84205 100644 --- a/include/PICA/pica_frag_config.hpp +++ b/include/PICA/pica_frag_config.hpp @@ -35,9 +35,6 @@ namespace PICA { BitField<0, 3, FogMode> mode; BitField<3, 1, u32> flipDepth; - BitField<8, 8, u32> fogColorR; - BitField<16, 8, u32> fogColorG; - BitField<24, 8, u32> fogColorB; }; }; @@ -238,9 +235,6 @@ namespace PICA { if (fogConfig.mode == FogMode::Fog) { fogConfig.flipDepth = Helpers::getBit<16>(regs[InternalRegs::TexEnvUpdateBuffer]); - fogConfig.fogColorR = Helpers::getBits<0, 8>(regs[InternalRegs::FogColor]); - fogConfig.fogColorG = Helpers::getBits<8, 8>(regs[InternalRegs::FogColor]); - fogConfig.fogColorB = Helpers::getBits<16, 8>(regs[InternalRegs::FogColor]); } } }; diff --git a/include/PICA/pica_frag_uniforms.hpp b/include/PICA/pica_frag_uniforms.hpp index 09722d61f..781fdcd30 100644 --- a/include/PICA/pica_frag_uniforms.hpp +++ b/include/PICA/pica_frag_uniforms.hpp @@ -34,8 +34,10 @@ namespace PICA { alignas(16) vec4 tevBufferColor; alignas(16) vec4 clipCoords; - // Note: We upload this as a u32 and decode on GPU + // Note: We upload these as a u32 and decode on GPU. + // Particularly the fog colour since fog is really uncommon and it doesn't matter if we decode on GPU. u32 globalAmbientLight; + u32 fogColor; // NOTE: THIS MUST BE LAST so that if lighting is disabled we can potentially omit uploading it LightUniform lightUniforms[8]; }; diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index f5a964a34..42b8bba1a 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -69,11 +69,11 @@ class RendererGL final : public Renderer { // The "default" vertex shader to use when using specialized shaders but not PICA vertex shader -> GLSL recompilation // We can compile this once and then link it with all other generated fragment shaders OpenGL::Shader defaultShadergenVs; + GLuint shadergenFragmentUBO; // Cached recompiled fragment shader struct CachedProgram { OpenGL::Program program; - uint uboBinding; }; std::unordered_map shaderCache; diff --git a/src/core/PICA/shader_gen_glsl.cpp b/src/core/PICA/shader_gen_glsl.cpp index 1db239f9f..41b33d886 100644 --- a/src/core/PICA/shader_gen_glsl.cpp +++ b/src/core/PICA/shader_gen_glsl.cpp @@ -27,6 +27,7 @@ static constexpr const char* uniformDefinition = R"( // Note: We upload this as a u32 and decode on GPU uint globalAmbientLight; + uint inFogColor; LightSource lightSources[8]; }; )"; @@ -656,10 +657,6 @@ void FragmentGenerator::compileFog(std::string& shader, const PICA::FragmentConf return; } - float r = config.fogConfig.fogColorR / 255.0f; - float g = config.fogConfig.fogColorG / 255.0f; - float b = config.fogConfig.fogColorB / 255.0f; - if (config.fogConfig.flipDepth) { shader += "float fog_index = (1.0 - depth) * 128.0;\n"; } else { @@ -668,7 +665,7 @@ void FragmentGenerator::compileFog(std::string& shader, const PICA::FragmentConf shader += "float clamped_index = clamp(floor(fog_index), 0.0, 127.0);"; shader += "float delta = fog_index - clamped_index;"; - shader += "vec3 fog_color = vec3(" + std::to_string(r) + ", " + std::to_string(g) + ", " + std::to_string(b) + ");"; + shader += "vec3 fog_color = (1.0 / 255.0) * vec3(float(inFogColor & 0xffu), float((inFogColor >> 8u) & 0xffu), float((inFogColor >> 16u) & 0xffu));"; shader += "vec2 value = texelFetch(u_tex_luts, ivec2(int(clamped_index), 24), 0).rg;"; // fog LUT is past the light LUTs shader += "float fog_factor = clamp(value.r + value.g * delta, 0.0, 1.0);"; shader += "combinerOutput.rgb = mix(fog_color, combinerOutput.rgb, fog_factor);"; diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 8b614d2db..f8fc31e7d 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -77,6 +77,11 @@ void RendererGL::initGraphicsContextInternal() { gl.useProgram(displayProgram); glUniform1i(OpenGL::uniformLocation(displayProgram, "u_texture"), 0); // Init sampler object + // Allocate memory for the shadergen fragment uniform UBO + glGenBuffers(1, &shadergenFragmentUBO); + gl.bindUBO(shadergenFragmentUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(PICA::FragmentUniforms), nullptr, GL_DYNAMIC_DRAW); + vbo.createFixedSize(sizeof(Vertex) * vertexBufferSize, GL_STREAM_DRAW); gl.bindVBO(vbo); vao.create(); @@ -853,17 +858,12 @@ OpenGL::Program& RendererGL::getSpecializedShader() { glUniform1i(OpenGL::uniformLocation(program, "u_tex2"), 2); glUniform1i(OpenGL::uniformLocation(program, "u_tex_luts"), 3); - // Allocate memory for the program UBO - glGenBuffers(1, &programEntry.uboBinding); - gl.bindUBO(programEntry.uboBinding); - glBufferData(GL_UNIFORM_BUFFER, sizeof(PICA::FragmentUniforms), nullptr, GL_DYNAMIC_DRAW); - // Set up the binding for our UBO. Sadly we can't specify it in the shader like normal people, // As it's an OpenGL 4.2 feature that MacOS doesn't support... uint uboIndex = glGetUniformBlockIndex(program.handle(), "FragmentUniforms"); glUniformBlockBinding(program.handle(), uboIndex, uboBlockBinding); } - glBindBufferBase(GL_UNIFORM_BUFFER, uboBlockBinding, programEntry.uboBinding); + glBindBufferBase(GL_UNIFORM_BUFFER, uboBlockBinding, shadergenFragmentUBO); // Upload uniform data to our shader's UBO PICA::FragmentUniforms uniforms; @@ -903,6 +903,8 @@ OpenGL::Program& RendererGL::getSpecializedShader() { vec[3] = float((color >> 24) & 0xFF) / 255.0f; } + uniforms.fogColor = regs[PICA::InternalRegs::FogColor]; + // Append lighting uniforms if (fsConfig.lighting.enable) { uniforms.globalAmbientLight = regs[InternalRegs::LightGlobalAmbient]; @@ -945,7 +947,7 @@ OpenGL::Program& RendererGL::getSpecializedShader() { } } - gl.bindUBO(programEntry.uboBinding); + gl.bindUBO(shadergenFragmentUBO); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(PICA::FragmentUniforms), &uniforms); return program; @@ -980,7 +982,6 @@ void RendererGL::clearShaderCache() { for (auto& shader : shaderCache) { CachedProgram& cachedProgram = shader.second; cachedProgram.program.free(); - glDeleteBuffers(1, &cachedProgram.uboBinding); } shaderCache.clear(); diff --git a/src/panda_sdl/frontend_sdl.cpp b/src/panda_sdl/frontend_sdl.cpp index 0c78eea15..3c7ccc1db 100644 --- a/src/panda_sdl/frontend_sdl.cpp +++ b/src/panda_sdl/frontend_sdl.cpp @@ -35,7 +35,7 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, config.rendererType == RendererType::Software ? 3 : 4); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, config.rendererType == RendererType::Software ? 3 : 1); - window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_OPENGL); + window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (window == nullptr) { Helpers::panic("Window creation failed: %s", SDL_GetError()); @@ -55,7 +55,7 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp #ifdef PANDA3DS_ENABLE_VULKAN if (config.rendererType == RendererType::Vulkan) { - window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_VULKAN); + window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); if (window == nullptr) { Helpers::warn("Window creation failed: %s", SDL_GetError()); @@ -289,6 +289,15 @@ void FrontendSDL::run() { } break; } + + case SDL_WINDOWEVENT: { + auto type = event.window.event; + if (type == SDL_WINDOWEVENT_RESIZED) { + const u32 width = event.window.data1; + const u32 height = event.window.data2; + emu.setOutputSize(width, height); + } + } } }