diff options
| author | 2014-08-15 16:33:17 +0200 | |
|---|---|---|
| committer | 2014-08-25 22:03:18 +0200 | |
| commit | 27cab6477e7e72771d0661418d71cce3c2721723 (patch) | |
| tree | 819e70f30fc8090232140fead77d2d4982a46deb /src/video_core/rasterizer.cpp | |
| parent | Pica: Add support for dumping textures. (diff) | |
| download | yuzu-27cab6477e7e72771d0661418d71cce3c2721723.tar.gz yuzu-27cab6477e7e72771d0661418d71cce3c2721723.tar.xz yuzu-27cab6477e7e72771d0661418d71cce3c2721723.zip | |
Pica/Rasterizer: Add initial implementation of texture combiners.
Diffstat (limited to 'src/video_core/rasterizer.cpp')
| -rw-r--r-- | src/video_core/rasterizer.cpp | 122 |
1 files changed, 121 insertions, 1 deletions
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index f418518a1..5a4155c84 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp | |||
| @@ -165,12 +165,132 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, | |||
| 165 | (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255) | 165 | (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255) |
| 166 | }; | 166 | }; |
| 167 | 167 | ||
| 168 | // Texture environment - consists of 6 stages of color and alpha combining. | ||
| 169 | // | ||
| 170 | // Color combiners take three input color values from some source (e.g. interpolated | ||
| 171 | // vertex color, texture color, previous stage, etc), perform some very simple | ||
| 172 | // operations on each of them (e.g. inversion) and then calculate the output color | ||
| 173 | // with some basic arithmetic. Alpha combiners can be configured separately but work | ||
| 174 | // analogously. | ||
| 175 | Math::Vec4<u8> combiner_output; | ||
| 176 | for (auto tev_stage : registers.GetTevStages()) { | ||
| 177 | using Source = Regs::TevStageConfig::Source; | ||
| 178 | using ColorModifier = Regs::TevStageConfig::ColorModifier; | ||
| 179 | using AlphaModifier = Regs::TevStageConfig::AlphaModifier; | ||
| 180 | using Operation = Regs::TevStageConfig::Operation; | ||
| 181 | |||
| 182 | auto GetColorSource = [&](Source source) -> Math::Vec3<u8> { | ||
| 183 | switch (source) { | ||
| 184 | case Source::PrimaryColor: | ||
| 185 | return primary_color.rgb(); | ||
| 186 | |||
| 187 | case Source::Constant: | ||
| 188 | return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b}; | ||
| 189 | |||
| 190 | case Source::Previous: | ||
| 191 | return combiner_output.rgb(); | ||
| 192 | |||
| 193 | default: | ||
| 194 | ERROR_LOG(GPU, "Unknown color combiner source %d\n", (int)source); | ||
| 195 | return {}; | ||
| 196 | } | ||
| 197 | }; | ||
| 198 | |||
| 199 | auto GetAlphaSource = [&](Source source) -> u8 { | ||
| 200 | switch (source) { | ||
| 201 | case Source::PrimaryColor: | ||
| 202 | return primary_color.a(); | ||
| 203 | |||
| 204 | case Source::Constant: | ||
| 205 | return tev_stage.const_a; | ||
| 206 | |||
| 207 | case Source::Previous: | ||
| 208 | return combiner_output.a(); | ||
| 209 | |||
| 210 | default: | ||
| 211 | ERROR_LOG(GPU, "Unknown alpha combiner source %d\n", (int)source); | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | }; | ||
| 215 | |||
| 216 | auto GetColorModifier = [](ColorModifier factor, const Math::Vec3<u8>& values) -> Math::Vec3<u8> { | ||
| 217 | switch (factor) | ||
| 218 | { | ||
| 219 | case ColorModifier::SourceColor: | ||
| 220 | return values; | ||
| 221 | default: | ||
| 222 | ERROR_LOG(GPU, "Unknown color factor %d\n", (int)factor); | ||
| 223 | return {}; | ||
| 224 | } | ||
| 225 | }; | ||
| 226 | |||
| 227 | auto GetAlphaModifier = [](AlphaModifier factor, u8 value) -> u8 { | ||
| 228 | switch (factor) { | ||
| 229 | case AlphaModifier::SourceAlpha: | ||
| 230 | return value; | ||
| 231 | default: | ||
| 232 | ERROR_LOG(GPU, "Unknown color factor %d\n", (int)factor); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | }; | ||
| 236 | |||
| 237 | auto ColorCombine = [](Operation op, const Math::Vec3<u8> input[3]) -> Math::Vec3<u8> { | ||
| 238 | switch (op) { | ||
| 239 | case Operation::Replace: | ||
| 240 | return input[0]; | ||
| 241 | |||
| 242 | case Operation::Modulate: | ||
| 243 | return ((input[0] * input[1]) / 255).Cast<u8>(); | ||
| 244 | |||
| 245 | default: | ||
| 246 | ERROR_LOG(GPU, "Unknown color combiner operation %d\n", (int)op); | ||
| 247 | return {}; | ||
| 248 | } | ||
| 249 | }; | ||
| 250 | |||
| 251 | auto AlphaCombine = [](Operation op, const std::array<u8,3>& input) -> u8 { | ||
| 252 | switch (op) { | ||
| 253 | case Operation::Replace: | ||
| 254 | return input[0]; | ||
| 255 | |||
| 256 | case Operation::Modulate: | ||
| 257 | return input[0] * input[1] / 255; | ||
| 258 | |||
| 259 | default: | ||
| 260 | ERROR_LOG(GPU, "Unknown alpha combiner operation %d\n", (int)op); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | }; | ||
| 264 | |||
| 265 | // color combiner | ||
| 266 | // NOTE: Not sure if the alpha combiner might use the color output of the previous | ||
| 267 | // stage as input. Hence, we currently don't directly write the result to | ||
| 268 | // combiner_output.rgb(), but instead store it in a temporary variable until | ||
| 269 | // alpha combining has been done. | ||
| 270 | Math::Vec3<u8> color_result[3] = { | ||
| 271 | GetColorModifier(tev_stage.color_modifier1, GetColorSource(tev_stage.color_source1)), | ||
| 272 | GetColorModifier(tev_stage.color_modifier2, GetColorSource(tev_stage.color_source2)), | ||
| 273 | GetColorModifier(tev_stage.color_modifier3, GetColorSource(tev_stage.color_source3)) | ||
| 274 | }; | ||
| 275 | auto color_output = ColorCombine(tev_stage.color_op, color_result); | ||
| 276 | |||
| 277 | // alpha combiner | ||
| 278 | std::array<u8,3> alpha_result = { | ||
| 279 | GetAlphaModifier(tev_stage.alpha_modifier1, GetAlphaSource(tev_stage.alpha_source1)), | ||
| 280 | GetAlphaModifier(tev_stage.alpha_modifier2, GetAlphaSource(tev_stage.alpha_source2)), | ||
| 281 | GetAlphaModifier(tev_stage.alpha_modifier3, GetAlphaSource(tev_stage.alpha_source3)) | ||
| 282 | }; | ||
| 283 | auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result); | ||
| 284 | |||
| 285 | combiner_output = Math::MakeVec(color_output, alpha_output); | ||
| 286 | } | ||
| 287 | |||
| 168 | u16 z = (u16)(((float)v0.screenpos[2].ToFloat32() * w0 + | 288 | u16 z = (u16)(((float)v0.screenpos[2].ToFloat32() * w0 + |
| 169 | (float)v1.screenpos[2].ToFloat32() * w1 + | 289 | (float)v1.screenpos[2].ToFloat32() * w1 + |
| 170 | (float)v2.screenpos[2].ToFloat32() * w2) * 65535.f / wsum); // TODO: Shouldn't need to multiply by 65536? | 290 | (float)v2.screenpos[2].ToFloat32() * w2) * 65535.f / wsum); // TODO: Shouldn't need to multiply by 65536? |
| 171 | SetDepth(x >> 4, y >> 4, z); | 291 | SetDepth(x >> 4, y >> 4, z); |
| 172 | 292 | ||
| 173 | DrawPixel(x >> 4, y >> 4, primary_color); | 293 | DrawPixel(x >> 4, y >> 4, combiner_output); |
| 174 | } | 294 | } |
| 175 | } | 295 | } |
| 176 | } | 296 | } |