diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/pica_state.h | 12 | ||||
| -rw-r--r-- | src/video_core/regs_lighting.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 128 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_gen.cpp | 110 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 40 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 27 |
7 files changed, 175 insertions, 151 deletions
diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h index f46db09fb..3b00df0b3 100644 --- a/src/video_core/pica_state.h +++ b/src/video_core/pica_state.h | |||
| @@ -87,12 +87,18 @@ struct State { | |||
| 87 | // LUT value, encoded as 12-bit fixed point, with 12 fraction bits | 87 | // LUT value, encoded as 12-bit fixed point, with 12 fraction bits |
| 88 | BitField<0, 12, u32> value; // 0.0.12 fixed point | 88 | BitField<0, 12, u32> value; // 0.0.12 fixed point |
| 89 | 89 | ||
| 90 | // Used by HW for efficient interpolation, Citra does not use these | 90 | // Used for efficient interpolation. |
| 91 | BitField<12, 12, s32> difference; // 1.0.11 fixed point | 91 | BitField<12, 11, u32> difference; // 0.0.11 fixed point |
| 92 | BitField<23, 1, u32> neg_difference; | ||
| 92 | 93 | ||
| 93 | float ToFloat() { | 94 | float ToFloat() const { |
| 94 | return static_cast<float>(value) / 4095.f; | 95 | return static_cast<float>(value) / 4095.f; |
| 95 | } | 96 | } |
| 97 | |||
| 98 | float DiffToFloat() const { | ||
| 99 | float diff = static_cast<float>(difference) / 2047.f; | ||
| 100 | return neg_difference ? -diff : diff; | ||
| 101 | } | ||
| 96 | }; | 102 | }; |
| 97 | 103 | ||
| 98 | std::array<std::array<LutEntry, 256>, 24> luts; | 104 | std::array<std::array<LutEntry, 256>, 24> luts; |
diff --git a/src/video_core/regs_lighting.h b/src/video_core/regs_lighting.h index 7221d1688..b89709cfe 100644 --- a/src/video_core/regs_lighting.h +++ b/src/video_core/regs_lighting.h | |||
| @@ -26,6 +26,8 @@ struct LightingRegs { | |||
| 26 | DistanceAttenuation = 16, | 26 | DistanceAttenuation = 16, |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | static constexpr unsigned NumLightingSampler = 24; | ||
| 30 | |||
| 29 | static LightingSampler SpotlightAttenuationSampler(unsigned index) { | 31 | static LightingSampler SpotlightAttenuationSampler(unsigned index) { |
| 30 | return static_cast<LightingSampler>( | 32 | return static_cast<LightingSampler>( |
| 31 | static_cast<unsigned>(LightingSampler::SpotlightAttenuation) + index); | 33 | static_cast<unsigned>(LightingSampler::SpotlightAttenuation) + index); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index e6cccebf6..8b7991c04 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -49,9 +49,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 49 | 49 | ||
| 50 | uniform_block_data.dirty = true; | 50 | uniform_block_data.dirty = true; |
| 51 | 51 | ||
| 52 | for (unsigned index = 0; index < lighting_luts.size(); index++) { | 52 | uniform_block_data.lut_dirty.fill(true); |
| 53 | uniform_block_data.lut_dirty[index] = true; | ||
| 54 | } | ||
| 55 | 53 | ||
| 56 | uniform_block_data.fog_lut_dirty = true; | 54 | uniform_block_data.fog_lut_dirty = true; |
| 57 | 55 | ||
| @@ -96,18 +94,16 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 96 | framebuffer.Create(); | 94 | framebuffer.Create(); |
| 97 | 95 | ||
| 98 | // Allocate and bind lighting lut textures | 96 | // Allocate and bind lighting lut textures |
| 99 | for (size_t i = 0; i < lighting_luts.size(); ++i) { | 97 | lighting_lut_buffer.Create(); |
| 100 | lighting_luts[i].Create(); | 98 | state.lighting_lut.texture_buffer = lighting_lut.handle; |
| 101 | state.lighting_luts[i].texture_1d = lighting_luts[i].handle; | ||
| 102 | } | ||
| 103 | state.Apply(); | 99 | state.Apply(); |
| 104 | 100 | lighting_lut.Create(); | |
| 105 | for (size_t i = 0; i < lighting_luts.size(); ++i) { | 101 | glBindBuffer(GL_TEXTURE_BUFFER, lighting_lut_buffer.handle); |
| 106 | glActiveTexture(static_cast<GLenum>(GL_TEXTURE3 + i)); | 102 | glBufferData(GL_TEXTURE_BUFFER, |
| 107 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); | 103 | sizeof(GLfloat) * 2 * 256 * Pica::LightingRegs::NumLightingSampler, nullptr, |
| 108 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 104 | GL_DYNAMIC_DRAW); |
| 109 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 105 | glActiveTexture(TextureUnits::LightingLUT.Enum()); |
| 110 | } | 106 | glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, lighting_lut_buffer.handle); |
| 111 | 107 | ||
| 112 | // Setup the LUT for the fog | 108 | // Setup the LUT for the fog |
| 113 | { | 109 | { |
| @@ -116,7 +112,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 116 | } | 112 | } |
| 117 | state.Apply(); | 113 | state.Apply(); |
| 118 | 114 | ||
| 119 | glActiveTexture(GL_TEXTURE9); | 115 | glActiveTexture(TextureUnits::FogLUT.Enum()); |
| 120 | glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr); | 116 | glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr); |
| 121 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 117 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 122 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 118 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -125,7 +121,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 125 | proctex_noise_lut.Create(); | 121 | proctex_noise_lut.Create(); |
| 126 | state.proctex_noise_lut.texture_1d = proctex_noise_lut.handle; | 122 | state.proctex_noise_lut.texture_1d = proctex_noise_lut.handle; |
| 127 | state.Apply(); | 123 | state.Apply(); |
| 128 | glActiveTexture(GL_TEXTURE10); | 124 | glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); |
| 129 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); | 125 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); |
| 130 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 126 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 131 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 127 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -134,7 +130,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 134 | proctex_color_map.Create(); | 130 | proctex_color_map.Create(); |
| 135 | state.proctex_color_map.texture_1d = proctex_color_map.handle; | 131 | state.proctex_color_map.texture_1d = proctex_color_map.handle; |
| 136 | state.Apply(); | 132 | state.Apply(); |
| 137 | glActiveTexture(GL_TEXTURE11); | 133 | glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); |
| 138 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); | 134 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); |
| 139 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 135 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 140 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 136 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -143,7 +139,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 143 | proctex_alpha_map.Create(); | 139 | proctex_alpha_map.Create(); |
| 144 | state.proctex_alpha_map.texture_1d = proctex_alpha_map.handle; | 140 | state.proctex_alpha_map.texture_1d = proctex_alpha_map.handle; |
| 145 | state.Apply(); | 141 | state.Apply(); |
| 146 | glActiveTexture(GL_TEXTURE12); | 142 | glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); |
| 147 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); | 143 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RG32F, 128, 0, GL_RG, GL_FLOAT, nullptr); |
| 148 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 144 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 149 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 145 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -152,7 +148,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 152 | proctex_lut.Create(); | 148 | proctex_lut.Create(); |
| 153 | state.proctex_lut.texture_1d = proctex_lut.handle; | 149 | state.proctex_lut.texture_1d = proctex_lut.handle; |
| 154 | state.Apply(); | 150 | state.Apply(); |
| 155 | glActiveTexture(GL_TEXTURE13); | 151 | glActiveTexture(TextureUnits::ProcTexLUT.Enum()); |
| 156 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); | 152 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); |
| 157 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 153 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 158 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 154 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -161,7 +157,7 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) { | |||
| 161 | proctex_diff_lut.Create(); | 157 | proctex_diff_lut.Create(); |
| 162 | state.proctex_diff_lut.texture_1d = proctex_diff_lut.handle; | 158 | state.proctex_diff_lut.texture_1d = proctex_diff_lut.handle; |
| 163 | state.Apply(); | 159 | state.Apply(); |
| 164 | glActiveTexture(GL_TEXTURE14); | 160 | glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); |
| 165 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); | 161 | glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 256, 0, GL_RGBA, GL_FLOAT, nullptr); |
| 166 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 162 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 167 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 163 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| @@ -313,7 +309,7 @@ void RasterizerOpenGL::DrawTriangles() { | |||
| 313 | } | 309 | } |
| 314 | 310 | ||
| 315 | // Sync the lighting luts | 311 | // Sync the lighting luts |
| 316 | for (unsigned index = 0; index < lighting_luts.size(); index++) { | 312 | for (unsigned index = 0; index < uniform_block_data.lut_dirty.size(); index++) { |
| 317 | if (uniform_block_data.lut_dirty[index]) { | 313 | if (uniform_block_data.lut_dirty[index]) { |
| 318 | SyncLightingLUT(index); | 314 | SyncLightingLUT(index); |
| 319 | uniform_block_data.lut_dirty[index] = false; | 315 | uniform_block_data.lut_dirty[index] = false; |
| @@ -851,7 +847,7 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { | |||
| 851 | case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce): | 847 | case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[6], 0x1ce): |
| 852 | case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf): { | 848 | case PICA_REG_INDEX_WORKAROUND(lighting.lut_data[7], 0x1cf): { |
| 853 | auto& lut_config = regs.lighting.lut_config; | 849 | auto& lut_config = regs.lighting.lut_config; |
| 854 | uniform_block_data.lut_dirty[lut_config.type / 4] = true; | 850 | uniform_block_data.lut_dirty[lut_config.type] = true; |
| 855 | break; | 851 | break; |
| 856 | } | 852 | } |
| 857 | } | 853 | } |
| @@ -1187,77 +1183,57 @@ void RasterizerOpenGL::SetShader() { | |||
| 1187 | state.Apply(); | 1183 | state.Apply(); |
| 1188 | 1184 | ||
| 1189 | // Set the texture samplers to correspond to different texture units | 1185 | // Set the texture samplers to correspond to different texture units |
| 1190 | GLuint uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[0]"); | 1186 | GLint uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[0]"); |
| 1191 | if (uniform_tex != -1) { | 1187 | if (uniform_tex != -1) { |
| 1192 | glUniform1i(uniform_tex, 0); | 1188 | glUniform1i(uniform_tex, TextureUnits::PicaTexture(0).id); |
| 1193 | } | 1189 | } |
| 1194 | uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[1]"); | 1190 | uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[1]"); |
| 1195 | if (uniform_tex != -1) { | 1191 | if (uniform_tex != -1) { |
| 1196 | glUniform1i(uniform_tex, 1); | 1192 | glUniform1i(uniform_tex, TextureUnits::PicaTexture(1).id); |
| 1197 | } | 1193 | } |
| 1198 | uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[2]"); | 1194 | uniform_tex = glGetUniformLocation(shader->shader.handle, "tex[2]"); |
| 1199 | if (uniform_tex != -1) { | 1195 | if (uniform_tex != -1) { |
| 1200 | glUniform1i(uniform_tex, 2); | 1196 | glUniform1i(uniform_tex, TextureUnits::PicaTexture(2).id); |
| 1201 | } | 1197 | } |
| 1202 | 1198 | ||
| 1203 | // Set the texture samplers to correspond to different lookup table texture units | 1199 | // Set the texture samplers to correspond to different lookup table texture units |
| 1204 | GLuint uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[0]"); | 1200 | GLint uniform_lut = glGetUniformLocation(shader->shader.handle, "lighting_lut"); |
| 1205 | if (uniform_lut != -1) { | ||
| 1206 | glUniform1i(uniform_lut, 3); | ||
| 1207 | } | ||
| 1208 | uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[1]"); | ||
| 1209 | if (uniform_lut != -1) { | ||
| 1210 | glUniform1i(uniform_lut, 4); | ||
| 1211 | } | ||
| 1212 | uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[2]"); | ||
| 1213 | if (uniform_lut != -1) { | ||
| 1214 | glUniform1i(uniform_lut, 5); | ||
| 1215 | } | ||
| 1216 | uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[3]"); | ||
| 1217 | if (uniform_lut != -1) { | 1201 | if (uniform_lut != -1) { |
| 1218 | glUniform1i(uniform_lut, 6); | 1202 | glUniform1i(uniform_lut, TextureUnits::LightingLUT.id); |
| 1219 | } | ||
| 1220 | uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[4]"); | ||
| 1221 | if (uniform_lut != -1) { | ||
| 1222 | glUniform1i(uniform_lut, 7); | ||
| 1223 | } | ||
| 1224 | uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[5]"); | ||
| 1225 | if (uniform_lut != -1) { | ||
| 1226 | glUniform1i(uniform_lut, 8); | ||
| 1227 | } | 1203 | } |
| 1228 | 1204 | ||
| 1229 | GLuint uniform_fog_lut = glGetUniformLocation(shader->shader.handle, "fog_lut"); | 1205 | GLint uniform_fog_lut = glGetUniformLocation(shader->shader.handle, "fog_lut"); |
| 1230 | if (uniform_fog_lut != -1) { | 1206 | if (uniform_fog_lut != -1) { |
| 1231 | glUniform1i(uniform_fog_lut, 9); | 1207 | glUniform1i(uniform_fog_lut, TextureUnits::FogLUT.id); |
| 1232 | } | 1208 | } |
| 1233 | 1209 | ||
| 1234 | GLuint uniform_proctex_noise_lut = | 1210 | GLint uniform_proctex_noise_lut = |
| 1235 | glGetUniformLocation(shader->shader.handle, "proctex_noise_lut"); | 1211 | glGetUniformLocation(shader->shader.handle, "proctex_noise_lut"); |
| 1236 | if (uniform_proctex_noise_lut != -1) { | 1212 | if (uniform_proctex_noise_lut != -1) { |
| 1237 | glUniform1i(uniform_proctex_noise_lut, 10); | 1213 | glUniform1i(uniform_proctex_noise_lut, TextureUnits::ProcTexNoiseLUT.id); |
| 1238 | } | 1214 | } |
| 1239 | 1215 | ||
| 1240 | GLuint uniform_proctex_color_map = | 1216 | GLint uniform_proctex_color_map = |
| 1241 | glGetUniformLocation(shader->shader.handle, "proctex_color_map"); | 1217 | glGetUniformLocation(shader->shader.handle, "proctex_color_map"); |
| 1242 | if (uniform_proctex_color_map != -1) { | 1218 | if (uniform_proctex_color_map != -1) { |
| 1243 | glUniform1i(uniform_proctex_color_map, 11); | 1219 | glUniform1i(uniform_proctex_color_map, TextureUnits::ProcTexColorMap.id); |
| 1244 | } | 1220 | } |
| 1245 | 1221 | ||
| 1246 | GLuint uniform_proctex_alpha_map = | 1222 | GLint uniform_proctex_alpha_map = |
| 1247 | glGetUniformLocation(shader->shader.handle, "proctex_alpha_map"); | 1223 | glGetUniformLocation(shader->shader.handle, "proctex_alpha_map"); |
| 1248 | if (uniform_proctex_alpha_map != -1) { | 1224 | if (uniform_proctex_alpha_map != -1) { |
| 1249 | glUniform1i(uniform_proctex_alpha_map, 12); | 1225 | glUniform1i(uniform_proctex_alpha_map, TextureUnits::ProcTexAlphaMap.id); |
| 1250 | } | 1226 | } |
| 1251 | 1227 | ||
| 1252 | GLuint uniform_proctex_lut = glGetUniformLocation(shader->shader.handle, "proctex_lut"); | 1228 | GLint uniform_proctex_lut = glGetUniformLocation(shader->shader.handle, "proctex_lut"); |
| 1253 | if (uniform_proctex_lut != -1) { | 1229 | if (uniform_proctex_lut != -1) { |
| 1254 | glUniform1i(uniform_proctex_lut, 13); | 1230 | glUniform1i(uniform_proctex_lut, TextureUnits::ProcTexLUT.id); |
| 1255 | } | 1231 | } |
| 1256 | 1232 | ||
| 1257 | GLuint uniform_proctex_diff_lut = | 1233 | GLint uniform_proctex_diff_lut = |
| 1258 | glGetUniformLocation(shader->shader.handle, "proctex_diff_lut"); | 1234 | glGetUniformLocation(shader->shader.handle, "proctex_diff_lut"); |
| 1259 | if (uniform_proctex_diff_lut != -1) { | 1235 | if (uniform_proctex_diff_lut != -1) { |
| 1260 | glUniform1i(uniform_proctex_diff_lut, 14); | 1236 | glUniform1i(uniform_proctex_diff_lut, TextureUnits::ProcTexDiffLUT.id); |
| 1261 | } | 1237 | } |
| 1262 | 1238 | ||
| 1263 | current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get(); | 1239 | current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get(); |
| @@ -1387,7 +1363,7 @@ void RasterizerOpenGL::SyncFogLUT() { | |||
| 1387 | 1363 | ||
| 1388 | if (new_data != fog_lut_data) { | 1364 | if (new_data != fog_lut_data) { |
| 1389 | fog_lut_data = new_data; | 1365 | fog_lut_data = new_data; |
| 1390 | glActiveTexture(GL_TEXTURE9); | 1366 | glActiveTexture(TextureUnits::FogLUT.Enum()); |
| 1391 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RED_INTEGER, GL_UNSIGNED_INT, | 1367 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RED_INTEGER, GL_UNSIGNED_INT, |
| 1392 | fog_lut_data.data()); | 1368 | fog_lut_data.data()); |
| 1393 | } | 1369 | } |
| @@ -1426,17 +1402,18 @@ static void SyncProcTexValueLUT(const std::array<Pica::State::ProcTex::ValueEntr | |||
| 1426 | } | 1402 | } |
| 1427 | 1403 | ||
| 1428 | void RasterizerOpenGL::SyncProcTexNoiseLUT() { | 1404 | void RasterizerOpenGL::SyncProcTexNoiseLUT() { |
| 1429 | SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, GL_TEXTURE10); | 1405 | SyncProcTexValueLUT(Pica::g_state.proctex.noise_table, proctex_noise_lut_data, |
| 1406 | TextureUnits::ProcTexNoiseLUT.Enum()); | ||
| 1430 | } | 1407 | } |
| 1431 | 1408 | ||
| 1432 | void RasterizerOpenGL::SyncProcTexColorMap() { | 1409 | void RasterizerOpenGL::SyncProcTexColorMap() { |
| 1433 | SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, | 1410 | SyncProcTexValueLUT(Pica::g_state.proctex.color_map_table, proctex_color_map_data, |
| 1434 | GL_TEXTURE11); | 1411 | TextureUnits::ProcTexColorMap.Enum()); |
| 1435 | } | 1412 | } |
| 1436 | 1413 | ||
| 1437 | void RasterizerOpenGL::SyncProcTexAlphaMap() { | 1414 | void RasterizerOpenGL::SyncProcTexAlphaMap() { |
| 1438 | SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, | 1415 | SyncProcTexValueLUT(Pica::g_state.proctex.alpha_map_table, proctex_alpha_map_data, |
| 1439 | GL_TEXTURE12); | 1416 | TextureUnits::ProcTexAlphaMap.Enum()); |
| 1440 | } | 1417 | } |
| 1441 | 1418 | ||
| 1442 | void RasterizerOpenGL::SyncProcTexLUT() { | 1419 | void RasterizerOpenGL::SyncProcTexLUT() { |
| @@ -1451,7 +1428,7 @@ void RasterizerOpenGL::SyncProcTexLUT() { | |||
| 1451 | 1428 | ||
| 1452 | if (new_data != proctex_lut_data) { | 1429 | if (new_data != proctex_lut_data) { |
| 1453 | proctex_lut_data = new_data; | 1430 | proctex_lut_data = new_data; |
| 1454 | glActiveTexture(GL_TEXTURE13); | 1431 | glActiveTexture(TextureUnits::ProcTexLUT.Enum()); |
| 1455 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_lut_data.data()); | 1432 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_lut_data.data()); |
| 1456 | } | 1433 | } |
| 1457 | } | 1434 | } |
| @@ -1468,7 +1445,7 @@ void RasterizerOpenGL::SyncProcTexDiffLUT() { | |||
| 1468 | 1445 | ||
| 1469 | if (new_data != proctex_diff_lut_data) { | 1446 | if (new_data != proctex_diff_lut_data) { |
| 1470 | proctex_diff_lut_data = new_data; | 1447 | proctex_diff_lut_data = new_data; |
| 1471 | glActiveTexture(GL_TEXTURE14); | 1448 | glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); |
| 1472 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_diff_lut_data.data()); | 1449 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, proctex_diff_lut_data.data()); |
| 1473 | } | 1450 | } |
| 1474 | } | 1451 | } |
| @@ -1571,20 +1548,17 @@ void RasterizerOpenGL::SyncGlobalAmbient() { | |||
| 1571 | } | 1548 | } |
| 1572 | 1549 | ||
| 1573 | void RasterizerOpenGL::SyncLightingLUT(unsigned lut_index) { | 1550 | void RasterizerOpenGL::SyncLightingLUT(unsigned lut_index) { |
| 1574 | std::array<GLvec4, 256> new_data; | 1551 | std::array<GLvec2, 256> new_data; |
| 1575 | 1552 | const auto& source_lut = Pica::g_state.lighting.luts[lut_index]; | |
| 1576 | for (unsigned offset = 0; offset < new_data.size(); ++offset) { | 1553 | std::transform(source_lut.begin(), source_lut.end(), new_data.begin(), [](const auto& entry) { |
| 1577 | new_data[offset][0] = Pica::g_state.lighting.luts[(lut_index * 4) + 0][offset].ToFloat(); | 1554 | return GLvec2{entry.ToFloat(), entry.DiffToFloat()}; |
| 1578 | new_data[offset][1] = Pica::g_state.lighting.luts[(lut_index * 4) + 1][offset].ToFloat(); | 1555 | }); |
| 1579 | new_data[offset][2] = Pica::g_state.lighting.luts[(lut_index * 4) + 2][offset].ToFloat(); | ||
| 1580 | new_data[offset][3] = Pica::g_state.lighting.luts[(lut_index * 4) + 3][offset].ToFloat(); | ||
| 1581 | } | ||
| 1582 | 1556 | ||
| 1583 | if (new_data != lighting_lut_data[lut_index]) { | 1557 | if (new_data != lighting_lut_data[lut_index]) { |
| 1584 | lighting_lut_data[lut_index] = new_data; | 1558 | lighting_lut_data[lut_index] = new_data; |
| 1585 | glActiveTexture(GL_TEXTURE3 + lut_index); | 1559 | glBindBuffer(GL_TEXTURE_BUFFER, lighting_lut_buffer.handle); |
| 1586 | glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RGBA, GL_FLOAT, | 1560 | glBufferSubData(GL_TEXTURE_BUFFER, lut_index * new_data.size() * sizeof(GLvec2), |
| 1587 | lighting_lut_data[lut_index].data()); | 1561 | new_data.size() * sizeof(GLvec2), new_data.data()); |
| 1588 | } | 1562 | } |
| 1589 | } | 1563 | } |
| 1590 | 1564 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index d9a3e9d1c..79acd4230 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -263,7 +263,7 @@ private: | |||
| 263 | 263 | ||
| 264 | struct { | 264 | struct { |
| 265 | UniformData data; | 265 | UniformData data; |
| 266 | bool lut_dirty[6]; | 266 | std::array<bool, Pica::LightingRegs::NumLightingSampler> lut_dirty; |
| 267 | bool fog_lut_dirty; | 267 | bool fog_lut_dirty; |
| 268 | bool proctex_noise_lut_dirty; | 268 | bool proctex_noise_lut_dirty; |
| 269 | bool proctex_color_map_dirty; | 269 | bool proctex_color_map_dirty; |
| @@ -279,8 +279,9 @@ private: | |||
| 279 | OGLBuffer uniform_buffer; | 279 | OGLBuffer uniform_buffer; |
| 280 | OGLFramebuffer framebuffer; | 280 | OGLFramebuffer framebuffer; |
| 281 | 281 | ||
| 282 | std::array<OGLTexture, 6> lighting_luts; | 282 | OGLBuffer lighting_lut_buffer; |
| 283 | std::array<std::array<GLvec4, 256>, 6> lighting_lut_data{}; | 283 | OGLTexture lighting_lut; |
| 284 | std::array<std::array<GLvec2, 256>, Pica::LightingRegs::NumLightingSampler> lighting_lut_data{}; | ||
| 284 | 285 | ||
| 285 | OGLTexture fog_lut; | 286 | OGLTexture fog_lut; |
| 286 | std::array<GLuint, 128> fog_lut_data{}; | 287 | std::array<GLuint, 128> fog_lut_data{}; |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 540cbb9d0..0c7c4dd5c 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp | |||
| @@ -562,9 +562,9 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 562 | out += "vec3 normal = quaternion_rotate(normalized_normquat, surface_normal);\n"; | 562 | out += "vec3 normal = quaternion_rotate(normalized_normquat, surface_normal);\n"; |
| 563 | out += "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\n"; | 563 | out += "vec3 tangent = quaternion_rotate(normalized_normquat, surface_tangent);\n"; |
| 564 | 564 | ||
| 565 | // Gets the index into the specified lookup table for specular lighting | 565 | // Samples the specified lookup table for specular lighting |
| 566 | auto GetLutIndex = [&lighting](unsigned light_num, LightingRegs::LightingLutInput input, | 566 | auto GetLutValue = [&lighting](LightingRegs::LightingSampler sampler, unsigned light_num, |
| 567 | bool abs) { | 567 | LightingRegs::LightingLutInput input, bool abs) { |
| 568 | std::string index; | 568 | std::string index; |
| 569 | switch (input) { | 569 | switch (input) { |
| 570 | case LightingRegs::LightingLutInput::NH: | 570 | case LightingRegs::LightingLutInput::NH: |
| @@ -610,22 +610,18 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 610 | break; | 610 | break; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | std::string sampler_string = std::to_string(static_cast<unsigned>(sampler)); | ||
| 614 | |||
| 613 | if (abs) { | 615 | if (abs) { |
| 614 | // LUT index is in the range of (0.0, 1.0) | 616 | // LUT index is in the range of (0.0, 1.0) |
| 615 | index = lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" | 617 | index = lighting.light[light_num].two_sided_diffuse ? "abs(" + index + ")" |
| 616 | : "max(" + index + ", 0.0)"; | 618 | : "max(" + index + ", 0.0)"; |
| 619 | return "LookupLightingLUTUnsigned(" + sampler_string + ", " + index + ")"; | ||
| 617 | } else { | 620 | } else { |
| 618 | // LUT index is in the range of (-1.0, 1.0) | 621 | // LUT index is in the range of (-1.0, 1.0) |
| 619 | index = "((" + index + " < 0) ? " + index + " + 2.0 : " + index + ") / 2.0"; | 622 | return "LookupLightingLUTSigned(" + sampler_string + ", " + index + ")"; |
| 620 | } | 623 | } |
| 621 | 624 | ||
| 622 | return "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; | ||
| 623 | }; | ||
| 624 | |||
| 625 | // Gets the lighting lookup table value given the specified sampler and index | ||
| 626 | auto GetLutValue = [](LightingRegs::LightingSampler sampler, std::string lut_index) { | ||
| 627 | return std::string("texture(lut[" + std::to_string((unsigned)sampler / 4) + "], " + | ||
| 628 | lut_index + ")[" + std::to_string((unsigned)sampler & 3) + "]"); | ||
| 629 | }; | 625 | }; |
| 630 | 626 | ||
| 631 | // Write the code to emulate each enabled light | 627 | // Write the code to emulate each enabled light |
| @@ -653,21 +649,21 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 653 | if (light_config.spot_atten_enable && | 649 | if (light_config.spot_atten_enable && |
| 654 | LightingRegs::IsLightingSamplerSupported( | 650 | LightingRegs::IsLightingSamplerSupported( |
| 655 | lighting.config, LightingRegs::LightingSampler::SpotlightAttenuation)) { | 651 | lighting.config, LightingRegs::LightingSampler::SpotlightAttenuation)) { |
| 656 | std::string index = | 652 | std::string value = |
| 657 | GetLutIndex(light_config.num, lighting.lut_sp.type, lighting.lut_sp.abs_input); | 653 | GetLutValue(LightingRegs::SpotlightAttenuationSampler(light_config.num), |
| 658 | auto sampler = LightingRegs::SpotlightAttenuationSampler(light_config.num); | 654 | light_config.num, lighting.lut_sp.type, lighting.lut_sp.abs_input); |
| 659 | spot_atten = "(" + std::to_string(lighting.lut_sp.scale) + " * " + | 655 | spot_atten = "(" + std::to_string(lighting.lut_sp.scale) + " * " + value + ")"; |
| 660 | GetLutValue(sampler, index) + ")"; | ||
| 661 | } | 656 | } |
| 662 | 657 | ||
| 663 | // If enabled, compute distance attenuation value | 658 | // If enabled, compute distance attenuation value |
| 664 | std::string dist_atten = "1.0"; | 659 | std::string dist_atten = "1.0"; |
| 665 | if (light_config.dist_atten_enable) { | 660 | if (light_config.dist_atten_enable) { |
| 666 | std::string index = "(" + light_src + ".dist_atten_scale * length(-view - " + | 661 | std::string index = "clamp(" + light_src + ".dist_atten_scale * length(-view - " + |
| 667 | light_src + ".position) + " + light_src + ".dist_atten_bias)"; | 662 | light_src + ".position) + " + light_src + |
| 668 | index = "(OFFSET_256 + SCALE_256 * clamp(" + index + ", 0.0, 1.0))"; | 663 | ".dist_atten_bias, 0.0, 1.0)"; |
| 669 | auto sampler = LightingRegs::DistanceAttenuationSampler(light_config.num); | 664 | auto sampler = LightingRegs::DistanceAttenuationSampler(light_config.num); |
| 670 | dist_atten = GetLutValue(sampler, index); | 665 | dist_atten = "LookupLightingLUTUnsigned(" + |
| 666 | std::to_string(static_cast<unsigned>(sampler)) + "," + index + ")"; | ||
| 671 | } | 667 | } |
| 672 | 668 | ||
| 673 | // If enabled, clamp specular component if lighting result is negative | 669 | // If enabled, clamp specular component if lighting result is negative |
| @@ -686,10 +682,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 686 | LightingRegs::IsLightingSamplerSupported( | 682 | LightingRegs::IsLightingSamplerSupported( |
| 687 | lighting.config, LightingRegs::LightingSampler::Distribution0)) { | 683 | lighting.config, LightingRegs::LightingSampler::Distribution0)) { |
| 688 | // Lookup specular "distribution 0" LUT value | 684 | // Lookup specular "distribution 0" LUT value |
| 689 | std::string index = | 685 | std::string value = |
| 690 | GetLutIndex(light_config.num, lighting.lut_d0.type, lighting.lut_d0.abs_input); | 686 | GetLutValue(LightingRegs::LightingSampler::Distribution0, light_config.num, |
| 691 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + | 687 | lighting.lut_d0.type, lighting.lut_d0.abs_input); |
| 692 | GetLutValue(LightingRegs::LightingSampler::Distribution0, index) + ")"; | 688 | d0_lut_value = "(" + std::to_string(lighting.lut_d0.scale) + " * " + value + ")"; |
| 693 | } | 689 | } |
| 694 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; | 690 | std::string specular_0 = "(" + d0_lut_value + " * " + light_src + ".specular_0)"; |
| 695 | if (light_config.geometric_factor_0) { | 691 | if (light_config.geometric_factor_0) { |
| @@ -700,10 +696,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 700 | if (lighting.lut_rr.enable && | 696 | if (lighting.lut_rr.enable && |
| 701 | LightingRegs::IsLightingSamplerSupported(lighting.config, | 697 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 702 | LightingRegs::LightingSampler::ReflectRed)) { | 698 | LightingRegs::LightingSampler::ReflectRed)) { |
| 703 | std::string index = | 699 | std::string value = |
| 704 | GetLutIndex(light_config.num, lighting.lut_rr.type, lighting.lut_rr.abs_input); | 700 | GetLutValue(LightingRegs::LightingSampler::ReflectRed, light_config.num, |
| 705 | std::string value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + | 701 | lighting.lut_rr.type, lighting.lut_rr.abs_input); |
| 706 | GetLutValue(LightingRegs::LightingSampler::ReflectRed, index) + ")"; | 702 | value = "(" + std::to_string(lighting.lut_rr.scale) + " * " + value + ")"; |
| 707 | out += "refl_value.r = " + value + ";\n"; | 703 | out += "refl_value.r = " + value + ";\n"; |
| 708 | } else { | 704 | } else { |
| 709 | out += "refl_value.r = 1.0;\n"; | 705 | out += "refl_value.r = 1.0;\n"; |
| @@ -713,11 +709,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 713 | if (lighting.lut_rg.enable && | 709 | if (lighting.lut_rg.enable && |
| 714 | LightingRegs::IsLightingSamplerSupported(lighting.config, | 710 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 715 | LightingRegs::LightingSampler::ReflectGreen)) { | 711 | LightingRegs::LightingSampler::ReflectGreen)) { |
| 716 | std::string index = | 712 | std::string value = |
| 717 | GetLutIndex(light_config.num, lighting.lut_rg.type, lighting.lut_rg.abs_input); | 713 | GetLutValue(LightingRegs::LightingSampler::ReflectGreen, light_config.num, |
| 718 | std::string value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + | 714 | lighting.lut_rg.type, lighting.lut_rg.abs_input); |
| 719 | GetLutValue(LightingRegs::LightingSampler::ReflectGreen, index) + | 715 | value = "(" + std::to_string(lighting.lut_rg.scale) + " * " + value + ")"; |
| 720 | ")"; | ||
| 721 | out += "refl_value.g = " + value + ";\n"; | 716 | out += "refl_value.g = " + value + ";\n"; |
| 722 | } else { | 717 | } else { |
| 723 | out += "refl_value.g = refl_value.r;\n"; | 718 | out += "refl_value.g = refl_value.r;\n"; |
| @@ -727,11 +722,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 727 | if (lighting.lut_rb.enable && | 722 | if (lighting.lut_rb.enable && |
| 728 | LightingRegs::IsLightingSamplerSupported(lighting.config, | 723 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 729 | LightingRegs::LightingSampler::ReflectBlue)) { | 724 | LightingRegs::LightingSampler::ReflectBlue)) { |
| 730 | std::string index = | 725 | std::string value = |
| 731 | GetLutIndex(light_config.num, lighting.lut_rb.type, lighting.lut_rb.abs_input); | 726 | GetLutValue(LightingRegs::LightingSampler::ReflectBlue, light_config.num, |
| 732 | std::string value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + | 727 | lighting.lut_rb.type, lighting.lut_rb.abs_input); |
| 733 | GetLutValue(LightingRegs::LightingSampler::ReflectBlue, index) + | 728 | value = "(" + std::to_string(lighting.lut_rb.scale) + " * " + value + ")"; |
| 734 | ")"; | ||
| 735 | out += "refl_value.b = " + value + ";\n"; | 729 | out += "refl_value.b = " + value + ";\n"; |
| 736 | } else { | 730 | } else { |
| 737 | out += "refl_value.b = refl_value.r;\n"; | 731 | out += "refl_value.b = refl_value.r;\n"; |
| @@ -743,10 +737,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 743 | LightingRegs::IsLightingSamplerSupported( | 737 | LightingRegs::IsLightingSamplerSupported( |
| 744 | lighting.config, LightingRegs::LightingSampler::Distribution1)) { | 738 | lighting.config, LightingRegs::LightingSampler::Distribution1)) { |
| 745 | // Lookup specular "distribution 1" LUT value | 739 | // Lookup specular "distribution 1" LUT value |
| 746 | std::string index = | 740 | std::string value = |
| 747 | GetLutIndex(light_config.num, lighting.lut_d1.type, lighting.lut_d1.abs_input); | 741 | GetLutValue(LightingRegs::LightingSampler::Distribution1, light_config.num, |
| 748 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + | 742 | lighting.lut_d1.type, lighting.lut_d1.abs_input); |
| 749 | GetLutValue(LightingRegs::LightingSampler::Distribution1, index) + ")"; | 743 | d1_lut_value = "(" + std::to_string(lighting.lut_d1.scale) + " * " + value + ")"; |
| 750 | } | 744 | } |
| 751 | std::string specular_1 = | 745 | std::string specular_1 = |
| 752 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; | 746 | "(" + d1_lut_value + " * refl_value * " + light_src + ".specular_1)"; |
| @@ -759,10 +753,10 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { | |||
| 759 | LightingRegs::IsLightingSamplerSupported(lighting.config, | 753 | LightingRegs::IsLightingSamplerSupported(lighting.config, |
| 760 | LightingRegs::LightingSampler::Fresnel)) { | 754 | LightingRegs::LightingSampler::Fresnel)) { |
| 761 | // Lookup fresnel LUT value | 755 | // Lookup fresnel LUT value |
| 762 | std::string index = | 756 | std::string value = |
| 763 | GetLutIndex(light_config.num, lighting.lut_fr.type, lighting.lut_fr.abs_input); | 757 | GetLutValue(LightingRegs::LightingSampler::Fresnel, light_config.num, |
| 764 | std::string value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + | 758 | lighting.lut_fr.type, lighting.lut_fr.abs_input); |
| 765 | GetLutValue(LightingRegs::LightingSampler::Fresnel, index) + ")"; | 759 | value = "(" + std::to_string(lighting.lut_fr.scale) + " * " + value + ")"; |
| 766 | 760 | ||
| 767 | // Enabled for difffuse lighting alpha component | 761 | // Enabled for difffuse lighting alpha component |
| 768 | if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || | 762 | if (lighting.fresnel_selector == LightingRegs::LightingFresnelSelector::PrimaryAlpha || |
| @@ -1016,10 +1010,6 @@ std::string GenerateFragmentShader(const PicaShaderConfig& config) { | |||
| 1016 | #define NUM_TEV_STAGES 6 | 1010 | #define NUM_TEV_STAGES 6 |
| 1017 | #define NUM_LIGHTS 8 | 1011 | #define NUM_LIGHTS 8 |
| 1018 | 1012 | ||
| 1019 | // Texture coordinate offsets and scales | ||
| 1020 | #define OFFSET_256 (0.5 / 256.0) | ||
| 1021 | #define SCALE_256 (255.0 / 256.0) | ||
| 1022 | |||
| 1023 | in vec4 primary_color; | 1013 | in vec4 primary_color; |
| 1024 | in vec2 texcoord[3]; | 1014 | in vec2 texcoord[3]; |
| 1025 | in float texcoord0_w; | 1015 | in float texcoord0_w; |
| @@ -1061,7 +1051,7 @@ layout (std140) uniform shader_data { | |||
| 1061 | }; | 1051 | }; |
| 1062 | 1052 | ||
| 1063 | uniform sampler2D tex[3]; | 1053 | uniform sampler2D tex[3]; |
| 1064 | uniform sampler1D lut[6]; | 1054 | uniform samplerBuffer lighting_lut; |
| 1065 | uniform usampler1D fog_lut; | 1055 | uniform usampler1D fog_lut; |
| 1066 | uniform sampler1D proctex_noise_lut; | 1056 | uniform sampler1D proctex_noise_lut; |
| 1067 | uniform sampler1D proctex_color_map; | 1057 | uniform sampler1D proctex_color_map; |
| @@ -1074,6 +1064,24 @@ vec3 quaternion_rotate(vec4 q, vec3 v) { | |||
| 1074 | return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); | 1064 | return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); |
| 1075 | } | 1065 | } |
| 1076 | 1066 | ||
| 1067 | float LookupLightingLUT(int lut_index, int index, float delta) { | ||
| 1068 | vec2 entry = texelFetch(lighting_lut, lut_index * 256 + index).rg; | ||
| 1069 | return entry.r + entry.g * delta; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | float LookupLightingLUTUnsigned(int lut_index, float pos) { | ||
| 1073 | int index = clamp(int(pos * 256.0), 0, 255); | ||
| 1074 | float delta = pos * 256.0 - index; | ||
| 1075 | return LookupLightingLUT(lut_index, index, delta); | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | float LookupLightingLUTSigned(int lut_index, float pos) { | ||
| 1079 | int index = clamp(int(pos * 128.0), -128, 127); | ||
| 1080 | float delta = pos * 128.0 - index; | ||
| 1081 | if (index < 0) index += 256; | ||
| 1082 | return LookupLightingLUT(lut_index, index, delta); | ||
| 1083 | } | ||
| 1084 | |||
| 1077 | )"; | 1085 | )"; |
| 1078 | 1086 | ||
| 1079 | if (config.state.proctex.enable) | 1087 | if (config.state.proctex.enable) |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index bf837a7fb..14e63115c 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -52,9 +52,7 @@ OpenGLState::OpenGLState() { | |||
| 52 | texture_unit.sampler = 0; | 52 | texture_unit.sampler = 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | for (auto& lut : lighting_luts) { | 55 | lighting_lut.texture_buffer = 0; |
| 56 | lut.texture_1d = 0; | ||
| 57 | } | ||
| 58 | 56 | ||
| 59 | fog_lut.texture_1d = 0; | 57 | fog_lut.texture_1d = 0; |
| 60 | 58 | ||
| @@ -185,7 +183,7 @@ void OpenGLState::Apply() const { | |||
| 185 | // Textures | 183 | // Textures |
| 186 | for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { | 184 | for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { |
| 187 | if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { | 185 | if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { |
| 188 | glActiveTexture(GL_TEXTURE0 + i); | 186 | glActiveTexture(TextureUnits::PicaTexture(i).Enum()); |
| 189 | glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); | 187 | glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); |
| 190 | } | 188 | } |
| 191 | if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { | 189 | if (texture_units[i].sampler != cur_state.texture_units[i].sampler) { |
| @@ -194,46 +192,44 @@ void OpenGLState::Apply() const { | |||
| 194 | } | 192 | } |
| 195 | 193 | ||
| 196 | // Lighting LUTs | 194 | // Lighting LUTs |
| 197 | for (unsigned i = 0; i < ARRAY_SIZE(lighting_luts); ++i) { | 195 | if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) { |
| 198 | if (lighting_luts[i].texture_1d != cur_state.lighting_luts[i].texture_1d) { | 196 | glActiveTexture(TextureUnits::LightingLUT.Enum()); |
| 199 | glActiveTexture(GL_TEXTURE3 + i); | 197 | glBindTexture(GL_TEXTURE_BUFFER, cur_state.lighting_lut.texture_buffer); |
| 200 | glBindTexture(GL_TEXTURE_1D, lighting_luts[i].texture_1d); | ||
| 201 | } | ||
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | // Fog LUT | 200 | // Fog LUT |
| 205 | if (fog_lut.texture_1d != cur_state.fog_lut.texture_1d) { | 201 | if (fog_lut.texture_1d != cur_state.fog_lut.texture_1d) { |
| 206 | glActiveTexture(GL_TEXTURE9); | 202 | glActiveTexture(TextureUnits::FogLUT.Enum()); |
| 207 | glBindTexture(GL_TEXTURE_1D, fog_lut.texture_1d); | 203 | glBindTexture(GL_TEXTURE_1D, fog_lut.texture_1d); |
| 208 | } | 204 | } |
| 209 | 205 | ||
| 210 | // ProcTex Noise LUT | 206 | // ProcTex Noise LUT |
| 211 | if (proctex_noise_lut.texture_1d != cur_state.proctex_noise_lut.texture_1d) { | 207 | if (proctex_noise_lut.texture_1d != cur_state.proctex_noise_lut.texture_1d) { |
| 212 | glActiveTexture(GL_TEXTURE10); | 208 | glActiveTexture(TextureUnits::ProcTexNoiseLUT.Enum()); |
| 213 | glBindTexture(GL_TEXTURE_1D, proctex_noise_lut.texture_1d); | 209 | glBindTexture(GL_TEXTURE_1D, proctex_noise_lut.texture_1d); |
| 214 | } | 210 | } |
| 215 | 211 | ||
| 216 | // ProcTex Color Map | 212 | // ProcTex Color Map |
| 217 | if (proctex_color_map.texture_1d != cur_state.proctex_color_map.texture_1d) { | 213 | if (proctex_color_map.texture_1d != cur_state.proctex_color_map.texture_1d) { |
| 218 | glActiveTexture(GL_TEXTURE11); | 214 | glActiveTexture(TextureUnits::ProcTexColorMap.Enum()); |
| 219 | glBindTexture(GL_TEXTURE_1D, proctex_color_map.texture_1d); | 215 | glBindTexture(GL_TEXTURE_1D, proctex_color_map.texture_1d); |
| 220 | } | 216 | } |
| 221 | 217 | ||
| 222 | // ProcTex Alpha Map | 218 | // ProcTex Alpha Map |
| 223 | if (proctex_alpha_map.texture_1d != cur_state.proctex_alpha_map.texture_1d) { | 219 | if (proctex_alpha_map.texture_1d != cur_state.proctex_alpha_map.texture_1d) { |
| 224 | glActiveTexture(GL_TEXTURE12); | 220 | glActiveTexture(TextureUnits::ProcTexAlphaMap.Enum()); |
| 225 | glBindTexture(GL_TEXTURE_1D, proctex_alpha_map.texture_1d); | 221 | glBindTexture(GL_TEXTURE_1D, proctex_alpha_map.texture_1d); |
| 226 | } | 222 | } |
| 227 | 223 | ||
| 228 | // ProcTex LUT | 224 | // ProcTex LUT |
| 229 | if (proctex_lut.texture_1d != cur_state.proctex_lut.texture_1d) { | 225 | if (proctex_lut.texture_1d != cur_state.proctex_lut.texture_1d) { |
| 230 | glActiveTexture(GL_TEXTURE13); | 226 | glActiveTexture(TextureUnits::ProcTexLUT.Enum()); |
| 231 | glBindTexture(GL_TEXTURE_1D, proctex_lut.texture_1d); | 227 | glBindTexture(GL_TEXTURE_1D, proctex_lut.texture_1d); |
| 232 | } | 228 | } |
| 233 | 229 | ||
| 234 | // ProcTex Diff LUT | 230 | // ProcTex Diff LUT |
| 235 | if (proctex_diff_lut.texture_1d != cur_state.proctex_diff_lut.texture_1d) { | 231 | if (proctex_diff_lut.texture_1d != cur_state.proctex_diff_lut.texture_1d) { |
| 236 | glActiveTexture(GL_TEXTURE14); | 232 | glActiveTexture(TextureUnits::ProcTexDiffLUT.Enum()); |
| 237 | glBindTexture(GL_TEXTURE_1D, proctex_diff_lut.texture_1d); | 233 | glBindTexture(GL_TEXTURE_1D, proctex_diff_lut.texture_1d); |
| 238 | } | 234 | } |
| 239 | 235 | ||
| @@ -274,6 +270,20 @@ void OpenGLState::ResetTexture(GLuint handle) { | |||
| 274 | unit.texture_2d = 0; | 270 | unit.texture_2d = 0; |
| 275 | } | 271 | } |
| 276 | } | 272 | } |
| 273 | if (cur_state.lighting_lut.texture_buffer == handle) | ||
| 274 | cur_state.lighting_lut.texture_buffer = 0; | ||
| 275 | if (cur_state.fog_lut.texture_1d == handle) | ||
| 276 | cur_state.fog_lut.texture_1d = 0; | ||
| 277 | if (cur_state.proctex_noise_lut.texture_1d == handle) | ||
| 278 | cur_state.proctex_noise_lut.texture_1d = 0; | ||
| 279 | if (cur_state.proctex_color_map.texture_1d == handle) | ||
| 280 | cur_state.proctex_color_map.texture_1d = 0; | ||
| 281 | if (cur_state.proctex_alpha_map.texture_1d == handle) | ||
| 282 | cur_state.proctex_alpha_map.texture_1d = 0; | ||
| 283 | if (cur_state.proctex_lut.texture_1d == handle) | ||
| 284 | cur_state.proctex_lut.texture_1d = 0; | ||
| 285 | if (cur_state.proctex_diff_lut.texture_1d == handle) | ||
| 286 | cur_state.proctex_diff_lut.texture_1d = 0; | ||
| 277 | } | 287 | } |
| 278 | 288 | ||
| 279 | void OpenGLState::ResetSampler(GLuint handle) { | 289 | void OpenGLState::ResetSampler(GLuint handle) { |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 7dcc03bd5..bb0218708 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -6,6 +6,29 @@ | |||
| 6 | 6 | ||
| 7 | #include <glad/glad.h> | 7 | #include <glad/glad.h> |
| 8 | 8 | ||
| 9 | namespace TextureUnits { | ||
| 10 | |||
| 11 | struct TextureUnit { | ||
| 12 | GLint id; | ||
| 13 | constexpr GLenum Enum() const { | ||
| 14 | return static_cast<GLenum>(GL_TEXTURE0 + id); | ||
| 15 | } | ||
| 16 | }; | ||
| 17 | |||
| 18 | constexpr TextureUnit PicaTexture(int unit) { | ||
| 19 | return TextureUnit{unit}; | ||
| 20 | } | ||
| 21 | |||
| 22 | constexpr TextureUnit LightingLUT{3}; | ||
| 23 | constexpr TextureUnit FogLUT{4}; | ||
| 24 | constexpr TextureUnit ProcTexNoiseLUT{5}; | ||
| 25 | constexpr TextureUnit ProcTexColorMap{6}; | ||
| 26 | constexpr TextureUnit ProcTexAlphaMap{7}; | ||
| 27 | constexpr TextureUnit ProcTexLUT{8}; | ||
| 28 | constexpr TextureUnit ProcTexDiffLUT{9}; | ||
| 29 | |||
| 30 | } // namespace TextureUnits | ||
| 31 | |||
| 9 | class OpenGLState { | 32 | class OpenGLState { |
| 10 | public: | 33 | public: |
| 11 | struct { | 34 | struct { |
| @@ -64,8 +87,8 @@ public: | |||
| 64 | } texture_units[3]; | 87 | } texture_units[3]; |
| 65 | 88 | ||
| 66 | struct { | 89 | struct { |
| 67 | GLuint texture_1d; // GL_TEXTURE_BINDING_1D | 90 | GLuint texture_buffer; // GL_TEXTURE_BINDING_BUFFER |
| 68 | } lighting_luts[6]; | 91 | } lighting_lut; |
| 69 | 92 | ||
| 70 | struct { | 93 | struct { |
| 71 | GLuint texture_1d; // GL_TEXTURE_BINDING_1D | 94 | GLuint texture_1d; // GL_TEXTURE_BINDING_1D |