mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add aa modes, with ui interface to switch
This commit is contained in:
parent
432e828517
commit
a3daa6065a
137
assets/voxygen/shaders/antialias/fxaa.glsl
Normal file
137
assets/voxygen/shaders/antialias/fxaa.glsl
Normal file
@ -0,0 +1,137 @@
|
||||
uniform sampler2D src_color;
|
||||
|
||||
const float FXAA_SCALE = 1.5;
|
||||
|
||||
/**
|
||||
Basic FXAA implementation based on the code on geeks3d.com with the
|
||||
modification that the texture2DLod stuff was removed since it's
|
||||
unsupported by WebGL.
|
||||
|
||||
--
|
||||
|
||||
From:
|
||||
https://github.com/mitsuhiko/webgl-meincraft
|
||||
|
||||
Copyright (c) 2011 by Armin Ronacher.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FXAA_REDUCE_MIN
|
||||
#define FXAA_REDUCE_MIN (1.0/ 128.0)
|
||||
#endif
|
||||
#ifndef FXAA_REDUCE_MUL
|
||||
#define FXAA_REDUCE_MUL (1.0 / 8.0)
|
||||
#endif
|
||||
#ifndef FXAA_SPAN_MAX
|
||||
#define FXAA_SPAN_MAX 8.0
|
||||
#endif
|
||||
|
||||
//optimized version for mobile, where dependent
|
||||
//texture reads can be a bottleneck
|
||||
vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,
|
||||
vec2 v_rgbNW, vec2 v_rgbNE,
|
||||
vec2 v_rgbSW, vec2 v_rgbSE,
|
||||
vec2 v_rgbM) {
|
||||
vec4 color;
|
||||
mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);
|
||||
vec3 rgbNW = texture(tex, v_rgbNW).xyz;
|
||||
vec3 rgbNE = texture(tex, v_rgbNE).xyz;
|
||||
vec3 rgbSW = texture(tex, v_rgbSW).xyz;
|
||||
vec3 rgbSE = texture(tex, v_rgbSE).xyz;
|
||||
vec4 texColor = texture(tex, v_rgbM);
|
||||
vec3 rgbM = texColor.xyz;
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
|
||||
mediump vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
|
||||
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
|
||||
(0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||
|
||||
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) * inverseVP;
|
||||
|
||||
vec3 rgbA = 0.5 * (
|
||||
texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
|
||||
texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
|
||||
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||
texture(tex, fragCoord * inverseVP + dir * -0.5).xyz +
|
||||
texture(tex, fragCoord * inverseVP + dir * 0.5).xyz);
|
||||
|
||||
float lumaB = dot(rgbB, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax))
|
||||
color = vec4(rgbA, texColor.a);
|
||||
else
|
||||
color = vec4(rgbB, texColor.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void texcoords(vec2 fragCoord, vec2 resolution,
|
||||
out vec2 v_rgbNW, out vec2 v_rgbNE,
|
||||
out vec2 v_rgbSW, out vec2 v_rgbSE,
|
||||
out vec2 v_rgbM) {
|
||||
vec2 inverseVP = 1.0 / resolution.xy;
|
||||
v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;
|
||||
v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;
|
||||
v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;
|
||||
v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;
|
||||
v_rgbM = vec2(fragCoord * inverseVP);
|
||||
}
|
||||
|
||||
|
||||
vec4 aa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) {
|
||||
mediump vec2 v_rgbNW;
|
||||
mediump vec2 v_rgbNE;
|
||||
mediump vec2 v_rgbSW;
|
||||
mediump vec2 v_rgbSE;
|
||||
mediump vec2 v_rgbM;
|
||||
|
||||
vec2 scaled_fc = fragCoord * FXAA_SCALE;
|
||||
vec2 scaled_res = resolution * FXAA_SCALE;
|
||||
|
||||
//compute the texture coords
|
||||
texcoords(scaled_fc, scaled_res, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
|
||||
|
||||
//compute FXAA
|
||||
return fxaa(tex, scaled_fc, scaled_res, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
|
||||
}
|
30
assets/voxygen/shaders/antialias/msaa-x16.glsl
Normal file
30
assets/voxygen/shaders/antialias/msaa-x16.glsl
Normal file
@ -0,0 +1,30 @@
|
||||
uniform sampler2DMS src_color;
|
||||
|
||||
vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) {
|
||||
ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y);
|
||||
|
||||
vec4 sample1 = texelFetch(tex, texel_coord, 0);
|
||||
vec4 sample2 = texelFetch(tex, texel_coord, 1);
|
||||
vec4 sample3 = texelFetch(tex, texel_coord, 2);
|
||||
vec4 sample4 = texelFetch(tex, texel_coord, 3);
|
||||
vec4 sample5 = texelFetch(tex, texel_coord, 4);
|
||||
vec4 sample6 = texelFetch(tex, texel_coord, 5);
|
||||
vec4 sample7 = texelFetch(tex, texel_coord, 6);
|
||||
vec4 sample8 = texelFetch(tex, texel_coord, 7);
|
||||
vec4 sample9 = texelFetch(tex, texel_coord, 8);
|
||||
vec4 sample10 = texelFetch(tex, texel_coord, 9);
|
||||
vec4 sample11 = texelFetch(tex, texel_coord, 11);
|
||||
vec4 sample12 = texelFetch(tex, texel_coord, 12);
|
||||
vec4 sample13 = texelFetch(tex, texel_coord, 13);
|
||||
vec4 sample14 = texelFetch(tex, texel_coord, 14);
|
||||
vec4 sample15 = texelFetch(tex, texel_coord, 15);
|
||||
vec4 sample16 = texelFetch(tex, texel_coord, 16);
|
||||
|
||||
// Average Samples
|
||||
vec4 msaa_color = (
|
||||
sample1 + sample2 + sample3 + sample4 + sample5 + sample6 + sample7 + sample8 +
|
||||
sample9 + sample10 + sample11 + sample12 + sample13 + sample14 + sample15 + sample16
|
||||
) / 16.0;
|
||||
|
||||
return msaa_color;
|
||||
}
|
15
assets/voxygen/shaders/antialias/msaa-x4.glsl
Normal file
15
assets/voxygen/shaders/antialias/msaa-x4.glsl
Normal file
@ -0,0 +1,15 @@
|
||||
uniform sampler2DMS src_color;
|
||||
|
||||
vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) {
|
||||
ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y);
|
||||
|
||||
vec4 sample1 = texelFetch(tex, texel_coord, 0);
|
||||
vec4 sample2 = texelFetch(tex, texel_coord, 1);
|
||||
vec4 sample3 = texelFetch(tex, texel_coord, 2);
|
||||
vec4 sample4 = texelFetch(tex, texel_coord, 3);
|
||||
|
||||
// Average Samples
|
||||
vec4 msaa_color = (sample1 + sample2 + sample3 + sample4) / 4.0;
|
||||
|
||||
return msaa_color;
|
||||
}
|
19
assets/voxygen/shaders/antialias/msaa-x8.glsl
Normal file
19
assets/voxygen/shaders/antialias/msaa-x8.glsl
Normal file
@ -0,0 +1,19 @@
|
||||
uniform sampler2DMS src_color;
|
||||
|
||||
vec4 aa_apply(sampler2DMS tex, vec2 fragCoord, vec2 resolution) {
|
||||
ivec2 texel_coord = ivec2(fragCoord.x, fragCoord.y);
|
||||
|
||||
vec4 sample1 = texelFetch(tex, texel_coord, 0);
|
||||
vec4 sample2 = texelFetch(tex, texel_coord, 1);
|
||||
vec4 sample3 = texelFetch(tex, texel_coord, 2);
|
||||
vec4 sample4 = texelFetch(tex, texel_coord, 3);
|
||||
vec4 sample5 = texelFetch(tex, texel_coord, 4);
|
||||
vec4 sample6 = texelFetch(tex, texel_coord, 5);
|
||||
vec4 sample7 = texelFetch(tex, texel_coord, 6);
|
||||
vec4 sample8 = texelFetch(tex, texel_coord, 7);
|
||||
|
||||
// Average Samples
|
||||
vec4 msaa_color = (sample1 + sample2 + sample3 + sample4 + sample5 + sample6 + sample7 + sample8) / 8.0;
|
||||
|
||||
return msaa_color;
|
||||
}
|
5
assets/voxygen/shaders/antialias/none.glsl
Normal file
5
assets/voxygen/shaders/antialias/none.glsl
Normal file
@ -0,0 +1,5 @@
|
||||
uniform sampler2D src_color;
|
||||
|
||||
vec4 aa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) {
|
||||
return texture(src_color, fragCoord / resolution);
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
#version 330 core
|
||||
|
||||
#include <globals.glsl>
|
||||
|
||||
uniform sampler2DMS src_color;
|
||||
// Note: The sampler uniform is declared here because it differs for MSAA
|
||||
#include <anti-aliasing.glsl>
|
||||
|
||||
in vec2 f_pos;
|
||||
|
||||
@ -13,137 +13,6 @@ uniform u_locals {
|
||||
|
||||
out vec4 tgt_color;
|
||||
|
||||
/**
|
||||
Basic FXAA implementation based on the code on geeks3d.com with the
|
||||
modification that the texture2DLod stuff was removed since it's
|
||||
unsupported by WebGL.
|
||||
|
||||
--
|
||||
|
||||
From:
|
||||
https://github.com/mitsuhiko/webgl-meincraft
|
||||
|
||||
Copyright (c) 2011 by Armin Ronacher.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FXAA_REDUCE_MIN
|
||||
#define FXAA_REDUCE_MIN (1.0/ 128.0)
|
||||
#endif
|
||||
#ifndef FXAA_REDUCE_MUL
|
||||
#define FXAA_REDUCE_MUL (1.0 / 8.0)
|
||||
#endif
|
||||
#ifndef FXAA_SPAN_MAX
|
||||
#define FXAA_SPAN_MAX 8.0
|
||||
#endif
|
||||
|
||||
//optimized version for mobile, where dependent
|
||||
//texture reads can be a bottleneck
|
||||
vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution,
|
||||
vec2 v_rgbNW, vec2 v_rgbNE,
|
||||
vec2 v_rgbSW, vec2 v_rgbSE,
|
||||
vec2 v_rgbM) {
|
||||
vec4 color;
|
||||
mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);
|
||||
vec3 rgbNW = texture(tex, v_rgbNW).xyz;
|
||||
vec3 rgbNE = texture(tex, v_rgbNE).xyz;
|
||||
vec3 rgbSW = texture(tex, v_rgbSW).xyz;
|
||||
vec3 rgbSE = texture(tex, v_rgbSE).xyz;
|
||||
vec4 texColor = texture(tex, v_rgbM);
|
||||
vec3 rgbM = texColor.xyz;
|
||||
vec3 luma = vec3(0.299, 0.587, 0.114);
|
||||
float lumaNW = dot(rgbNW, luma);
|
||||
float lumaNE = dot(rgbNE, luma);
|
||||
float lumaSW = dot(rgbSW, luma);
|
||||
float lumaSE = dot(rgbSE, luma);
|
||||
float lumaM = dot(rgbM, luma);
|
||||
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
|
||||
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
|
||||
|
||||
mediump vec2 dir;
|
||||
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
|
||||
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
|
||||
|
||||
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *
|
||||
(0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
|
||||
|
||||
float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
|
||||
dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
|
||||
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
|
||||
dir * rcpDirMin)) * inverseVP;
|
||||
|
||||
vec3 rgbA = 0.5 * (
|
||||
texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
|
||||
texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
|
||||
vec3 rgbB = rgbA * 0.5 + 0.25 * (
|
||||
texture(tex, fragCoord * inverseVP + dir * -0.5).xyz +
|
||||
texture(tex, fragCoord * inverseVP + dir * 0.5).xyz);
|
||||
|
||||
float lumaB = dot(rgbB, luma);
|
||||
if ((lumaB < lumaMin) || (lumaB > lumaMax))
|
||||
color = vec4(rgbA, texColor.a);
|
||||
else
|
||||
color = vec4(rgbB, texColor.a);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void texcoords(vec2 fragCoord, vec2 resolution,
|
||||
out vec2 v_rgbNW, out vec2 v_rgbNE,
|
||||
out vec2 v_rgbSW, out vec2 v_rgbSE,
|
||||
out vec2 v_rgbM) {
|
||||
vec2 inverseVP = 1.0 / resolution.xy;
|
||||
v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;
|
||||
v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;
|
||||
v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;
|
||||
v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;
|
||||
v_rgbM = vec2(fragCoord * inverseVP);
|
||||
}
|
||||
|
||||
|
||||
vec4 fxaa_apply(sampler2D tex, vec2 fragCoord, vec2 resolution) {
|
||||
mediump vec2 v_rgbNW;
|
||||
mediump vec2 v_rgbNE;
|
||||
mediump vec2 v_rgbSW;
|
||||
mediump vec2 v_rgbSE;
|
||||
mediump vec2 v_rgbM;
|
||||
|
||||
//compute the texture coords
|
||||
texcoords(fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
|
||||
|
||||
//compute FXAA
|
||||
return fxaa(tex, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);
|
||||
}
|
||||
|
||||
vec3 rgb2hsv(vec3 c) {
|
||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
@ -160,8 +29,6 @@ vec3 hsv2rgb(vec3 c) {
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
const float FXAA_SCALE = 1.5;
|
||||
|
||||
void main() {
|
||||
vec2 uv = (f_pos + 1.0) * 0.5;
|
||||
|
||||
@ -170,21 +37,15 @@ void main() {
|
||||
}
|
||||
|
||||
|
||||
//vec4 fxaa_color = fxaa_apply(src_color, uv * screen_res.xy * FXAA_SCALE, screen_res.xy * FXAA_SCALE);
|
||||
//vec4 fxaa_color = texture(src_color, uv);
|
||||
ivec2 uv_int = ivec2(uv.x * screen_res.x, uv.y * screen_res.y);
|
||||
vec4 sample1 = texelFetch(src_color, uv_int, 0);
|
||||
vec4 sample2 = texelFetch(src_color, uv_int, 1);
|
||||
vec4 sample3 = texelFetch(src_color, uv_int, 2);
|
||||
vec4 sample4 = texelFetch(src_color, uv_int, 3);
|
||||
vec4 fxaa_color = (sample1 + sample2 + sample3 + sample4) / 4.0;
|
||||
vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy);
|
||||
|
||||
vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||
hsva_color.y *= 1.45;
|
||||
hsva_color.z *= 0.85;
|
||||
//vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||
//hsva_color.y *= 1.45;
|
||||
//hsva_color.z *= 0.85;
|
||||
//hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
|
||||
vec4 final_color = fxaa_color;
|
||||
//vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
|
||||
//vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a);
|
||||
|
||||
vec4 final_color = aa_color;
|
||||
|
||||
if (medium.x == 1u) {
|
||||
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
||||
|
@ -32,7 +32,7 @@ use social::{Social, SocialTab};
|
||||
use spell::Spell;
|
||||
|
||||
use crate::{
|
||||
render::{Consts, Globals, Renderer},
|
||||
render::{AaMode, Consts, Globals, Renderer},
|
||||
scene::camera::Camera,
|
||||
settings::ControlSettings,
|
||||
ui::{Ingameable, ScaleMode, Ui},
|
||||
@ -158,6 +158,7 @@ pub enum Event {
|
||||
ChangeAudioDevice(String),
|
||||
ChangeMaxFPS(u32),
|
||||
ChangeFOV(u16),
|
||||
ChangeAaMode(AaMode),
|
||||
CrosshairTransp(f32),
|
||||
CrosshairType(CrosshairType),
|
||||
ToggleXpBar(XpBar),
|
||||
@ -832,6 +833,9 @@ impl Hud {
|
||||
settings_window::Event::AdjustFOV(new_fov) => {
|
||||
events.push(Event::ChangeFOV(new_fov));
|
||||
}
|
||||
settings_window::Event::ChangeAaMode(new_aa_mode) => {
|
||||
events.push(Event::ChangeAaMode(new_aa_mode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ use super::{
|
||||
img_ids::Imgs, BarNumbers, CrosshairType, Fonts, ShortcutNumbers, Show, XpBar, TEXT_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
ui::{ImageSlider, ScaleMode, ToggleButton},
|
||||
render::AaMode,
|
||||
ui::{ImageSlider, RadioList, ScaleMode, ToggleButton},
|
||||
GlobalState,
|
||||
};
|
||||
use conrod_core::{
|
||||
@ -76,6 +77,8 @@ widget_ids! {
|
||||
fov_slider,
|
||||
fov_text,
|
||||
fov_value,
|
||||
aa_radio_buttons,
|
||||
aa_mode_text,
|
||||
audio_volume_slider,
|
||||
audio_volume_text,
|
||||
sfx_volume_slider,
|
||||
@ -153,6 +156,7 @@ pub enum Event {
|
||||
AdjustMouseZoom(u32),
|
||||
AdjustViewDistance(u32),
|
||||
AdjustFOV(u16),
|
||||
ChangeAaMode(AaMode),
|
||||
AdjustMusicVolume(f32),
|
||||
AdjustSfxVolume(f32),
|
||||
ChangeAudioDevice(String),
|
||||
@ -1196,6 +1200,37 @@ impl<'a> Widget for SettingsWindow<'a> {
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.fov_value, ui);
|
||||
|
||||
// AaMode
|
||||
Text::new("AntiAliasing Mode")
|
||||
.down_from(state.ids.fov_slider, 8.0)
|
||||
.font_size(14)
|
||||
.font_id(self.fonts.opensans)
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.aa_mode_text, ui);
|
||||
let mode_label_list = [
|
||||
(&AaMode::None, "No AA"),
|
||||
(&AaMode::Fxaa, "FXAA"),
|
||||
(&AaMode::MsaaX4, "MSAA x4"),
|
||||
(&AaMode::MsaaX8, "MSAA x8"),
|
||||
(&AaMode::MsaaX16, "MSAA x16 (experimental)"),
|
||||
(&AaMode::SsaaX4, "SSAA x4"),
|
||||
];
|
||||
if let Some((_, mode)) = RadioList::new(
|
||||
(0..mode_label_list.len())
|
||||
.find(|i| *mode_label_list[*i].0 == self.global_state.settings.graphics.aa_mode)
|
||||
.unwrap_or(0),
|
||||
self.imgs.check,
|
||||
self.imgs.check_checked,
|
||||
&mode_label_list,
|
||||
)
|
||||
.down_from(state.ids.aa_mode_text, 8.0)
|
||||
.text_color(TEXT_COLOR)
|
||||
.font_size(12)
|
||||
.set(state.ids.aa_radio_buttons, ui)
|
||||
{
|
||||
events.push(Event::ChangeAaMode(*mode))
|
||||
}
|
||||
}
|
||||
|
||||
// 5) Sound Tab -----------------------------------
|
||||
|
@ -52,3 +52,15 @@ use gfx;
|
||||
pub trait Pipeline {
|
||||
type Vertex: Clone + gfx::traits::Pod + gfx::pso::buffer::Structure<gfx::format::Format>;
|
||||
}
|
||||
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
/// Anti-aliasing modes
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum AaMode {
|
||||
None,
|
||||
Fxaa,
|
||||
MsaaX4,
|
||||
MsaaX8,
|
||||
MsaaX16,
|
||||
SsaaX4,
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use super::{
|
||||
model::{DynamicModel, Model},
|
||||
pipelines::{figure, fluid, postprocess, skybox, sprite, terrain, ui, Globals, Light, Shadow},
|
||||
texture::Texture,
|
||||
Pipeline, RenderError,
|
||||
AaMode, Pipeline, RenderError,
|
||||
};
|
||||
use common::assets::{self, watch::ReloadIndicator};
|
||||
use gfx::{
|
||||
@ -71,6 +71,8 @@ pub struct Renderer {
|
||||
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||
|
||||
shader_reload_indicator: ReloadIndicator,
|
||||
|
||||
aa_mode: AaMode,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
@ -80,6 +82,7 @@ impl Renderer {
|
||||
mut factory: gfx_backend::Factory,
|
||||
win_color_view: WinColorView,
|
||||
win_depth_view: WinDepthView,
|
||||
aa_mode: AaMode,
|
||||
) -> Result<Self, RenderError> {
|
||||
let mut shader_reload_indicator = ReloadIndicator::new();
|
||||
|
||||
@ -91,11 +94,11 @@ impl Renderer {
|
||||
sprite_pipeline,
|
||||
ui_pipeline,
|
||||
postprocess_pipeline,
|
||||
) = create_pipelines(&mut factory, &mut shader_reload_indicator)?;
|
||||
) = create_pipelines(&mut factory, aa_mode, &mut shader_reload_indicator)?;
|
||||
|
||||
let dims = win_color_view.get_dimensions();
|
||||
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
||||
Self::create_rt_views(&mut factory, (dims.0, dims.1))?;
|
||||
Self::create_rt_views(&mut factory, (dims.0, dims.1), aa_mode)?;
|
||||
|
||||
let sampler = factory.create_sampler_linear();
|
||||
|
||||
@ -122,6 +125,8 @@ impl Renderer {
|
||||
postprocess_pipeline,
|
||||
|
||||
shader_reload_indicator,
|
||||
|
||||
aa_mode,
|
||||
})
|
||||
}
|
||||
|
||||
@ -149,6 +154,19 @@ impl Renderer {
|
||||
(&mut self.win_color_view, &mut self.win_depth_view)
|
||||
}
|
||||
|
||||
/// Change the anti-aliasing mode
|
||||
pub fn set_aa_mode(&mut self, aa_mode: AaMode) -> Result<(), RenderError> {
|
||||
self.aa_mode = aa_mode;
|
||||
|
||||
// Recreate render target
|
||||
self.on_resize()?;
|
||||
|
||||
// Recreate pipelines with the new AA mode
|
||||
self.recreate_pipelines();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resize internal render targets to match window render target dimensions.
|
||||
pub fn on_resize(&mut self) -> Result<(), RenderError> {
|
||||
let dims = self.win_color_view.get_dimensions();
|
||||
@ -156,7 +174,7 @@ impl Renderer {
|
||||
// Avoid panics when creating texture with w,h of 0,0.
|
||||
if dims.0 != 0 && dims.1 != 0 {
|
||||
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
||||
Self::create_rt_views(&mut self.factory, (dims.0, dims.1))?;
|
||||
Self::create_rt_views(&mut self.factory, (dims.0, dims.1), self.aa_mode)?;
|
||||
self.tgt_color_res = tgt_color_res;
|
||||
self.tgt_color_view = tgt_color_view;
|
||||
self.tgt_depth_view = tgt_depth_view;
|
||||
@ -168,8 +186,26 @@ impl Renderer {
|
||||
fn create_rt_views(
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
size: (u16, u16),
|
||||
aa_mode: AaMode,
|
||||
) -> Result<(TgtColorView, TgtDepthView, TgtColorRes), RenderError> {
|
||||
let kind = gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(4));
|
||||
let kind = match aa_mode {
|
||||
AaMode::None | AaMode::Fxaa => {
|
||||
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Single)
|
||||
}
|
||||
// TODO: Ensure sampling in the shader is exactly between the 4 texels
|
||||
AaMode::SsaaX4 => {
|
||||
gfx::texture::Kind::D2(size.0 * 2, size.1 * 2, gfx::texture::AaMode::Single)
|
||||
}
|
||||
AaMode::MsaaX4 => {
|
||||
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(4))
|
||||
}
|
||||
AaMode::MsaaX8 => {
|
||||
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(8))
|
||||
}
|
||||
AaMode::MsaaX16 => {
|
||||
gfx::texture::Kind::D2(size.0, size.1, gfx::texture::AaMode::Multi(16))
|
||||
}
|
||||
};
|
||||
let levels = 1;
|
||||
|
||||
let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
|
||||
@ -222,29 +258,38 @@ impl Renderer {
|
||||
|
||||
// If the shaders files were changed attempt to recreate the shaders
|
||||
if self.shader_reload_indicator.reloaded() {
|
||||
match create_pipelines(&mut self.factory, &mut self.shader_reload_indicator) {
|
||||
Ok((
|
||||
skybox_pipeline,
|
||||
figure_pipeline,
|
||||
terrain_pipeline,
|
||||
fluid_pipeline,
|
||||
sprite_pipeline,
|
||||
ui_pipeline,
|
||||
postprocess_pipeline,
|
||||
)) => {
|
||||
self.skybox_pipeline = skybox_pipeline;
|
||||
self.figure_pipeline = figure_pipeline;
|
||||
self.terrain_pipeline = terrain_pipeline;
|
||||
self.fluid_pipeline = fluid_pipeline;
|
||||
self.sprite_pipeline = sprite_pipeline;
|
||||
self.ui_pipeline = ui_pipeline;
|
||||
self.postprocess_pipeline = postprocess_pipeline;
|
||||
}
|
||||
Err(e) => error!(
|
||||
"Could not recreate shaders from assets due to an error: {:#?}",
|
||||
e
|
||||
),
|
||||
self.recreate_pipelines();
|
||||
}
|
||||
}
|
||||
|
||||
/// Recreate the pipelines
|
||||
fn recreate_pipelines(&mut self) {
|
||||
match create_pipelines(
|
||||
&mut self.factory,
|
||||
self.aa_mode,
|
||||
&mut self.shader_reload_indicator,
|
||||
) {
|
||||
Ok((
|
||||
skybox_pipeline,
|
||||
figure_pipeline,
|
||||
terrain_pipeline,
|
||||
fluid_pipeline,
|
||||
sprite_pipeline,
|
||||
ui_pipeline,
|
||||
postprocess_pipeline,
|
||||
)) => {
|
||||
self.skybox_pipeline = skybox_pipeline;
|
||||
self.figure_pipeline = figure_pipeline;
|
||||
self.terrain_pipeline = terrain_pipeline;
|
||||
self.fluid_pipeline = fluid_pipeline;
|
||||
self.sprite_pipeline = sprite_pipeline;
|
||||
self.ui_pipeline = ui_pipeline;
|
||||
self.postprocess_pipeline = postprocess_pipeline;
|
||||
}
|
||||
Err(e) => error!(
|
||||
"Could not recreate shaders from assets due to an error: {:#?}",
|
||||
e
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -595,6 +640,7 @@ struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
||||
/// Creates all the pipelines used to render.
|
||||
fn create_pipelines(
|
||||
factory: &mut gfx_backend::Factory,
|
||||
aa_mode: AaMode,
|
||||
shader_reload_indicator: &mut ReloadIndicator,
|
||||
) -> Result<
|
||||
(
|
||||
@ -624,12 +670,29 @@ fn create_pipelines(
|
||||
assets::load_watched::<String>("voxygen.shaders.include.random", shader_reload_indicator)
|
||||
.unwrap();
|
||||
|
||||
let anti_alias = assets::load_watched::<String>(
|
||||
&[
|
||||
"voxygen.shaders.antialias.",
|
||||
match aa_mode {
|
||||
AaMode::None | AaMode::SsaaX4 => "none",
|
||||
AaMode::Fxaa => "fxaa",
|
||||
AaMode::MsaaX4 => "msaa-x4",
|
||||
AaMode::MsaaX8 => "msaa-x8",
|
||||
AaMode::MsaaX16 => "msaa-x16",
|
||||
},
|
||||
]
|
||||
.concat(),
|
||||
shader_reload_indicator,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut include_ctx = IncludeContext::new();
|
||||
include_ctx.include("globals.glsl", &globals);
|
||||
include_ctx.include("sky.glsl", &sky);
|
||||
include_ctx.include("light.glsl", &light);
|
||||
include_ctx.include("srgb.glsl", &srgb);
|
||||
include_ctx.include("random.glsl", &random);
|
||||
include_ctx.include("anti-aliasing.glsl", &anti_alias);
|
||||
|
||||
// Construct a pipeline for rendering skyboxes
|
||||
let skybox_pipeline = create_pipeline(
|
||||
|
@ -455,7 +455,17 @@ impl PlayState for SessionState {
|
||||
HudEvent::ChangeFOV(new_fov) => {
|
||||
global_state.settings.graphics.fov = new_fov;
|
||||
global_state.settings.save_to_file_warn();
|
||||
&self.scene.camera_mut().set_fov_deg(new_fov);
|
||||
self.scene.camera_mut().set_fov_deg(new_fov);
|
||||
}
|
||||
HudEvent::ChangeAaMode(new_aa_mode) => {
|
||||
// Do this first so if it crashes the setting isn't saved :)
|
||||
global_state
|
||||
.window
|
||||
.renderer_mut()
|
||||
.set_aa_mode(new_aa_mode)
|
||||
.unwrap();
|
||||
global_state.settings.graphics.aa_mode = new_aa_mode;
|
||||
global_state.settings.save_to_file_warn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
hud::{BarNumbers, CrosshairType, ShortcutNumbers, XpBar},
|
||||
render::AaMode,
|
||||
ui::ScaleMode,
|
||||
window::KeyMouse,
|
||||
};
|
||||
@ -160,6 +161,7 @@ pub struct GraphicsSettings {
|
||||
pub view_distance: u32,
|
||||
pub max_fps: u32,
|
||||
pub fov: u16,
|
||||
pub aa_mode: AaMode,
|
||||
}
|
||||
|
||||
impl Default for GraphicsSettings {
|
||||
@ -168,6 +170,7 @@ impl Default for GraphicsSettings {
|
||||
view_distance: 5,
|
||||
max_fps: 60,
|
||||
fov: 75,
|
||||
aa_mode: AaMode::Fxaa,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ pub use widgets::{
|
||||
image_frame::ImageFrame,
|
||||
image_slider::ImageSlider,
|
||||
ingame::{Ingame, IngameAnchor, Ingameable},
|
||||
radio_list::RadioList,
|
||||
toggle_button::ToggleButton,
|
||||
tooltip::{Tooltip, TooltipManager, Tooltipable},
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod image_frame;
|
||||
pub mod image_slider;
|
||||
pub mod ingame;
|
||||
pub mod radio_list;
|
||||
pub mod toggle_button;
|
||||
pub mod tooltip;
|
||||
|
202
voxygen/src/ui/widgets/radio_list.rs
Normal file
202
voxygen/src/ui/widgets/radio_list.rs
Normal file
@ -0,0 +1,202 @@
|
||||
use conrod_core::{
|
||||
builder_methods, image, text,
|
||||
widget::{self, button},
|
||||
widget_ids, Color, FontSize, Positionable, Rect, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
|
||||
#[derive(Clone, WidgetCommon)]
|
||||
pub struct RadioList<'a, T> {
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
f_image: button::Image,
|
||||
t_image: button::Image,
|
||||
selected: usize,
|
||||
options_labels: &'a [(&'a T, &'a str)],
|
||||
label_style: widget::text::Style,
|
||||
label_spacing: f64,
|
||||
button_spacing: [f64; 2],
|
||||
button_dims: [f64; 2],
|
||||
}
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
buttons[],
|
||||
labels[],
|
||||
}
|
||||
}
|
||||
|
||||
pub struct State {
|
||||
ids: Ids,
|
||||
}
|
||||
|
||||
impl<'a, T> RadioList<'a, T> {
|
||||
pub fn new(
|
||||
selected: usize,
|
||||
f_image_id: image::Id,
|
||||
t_image_id: image::Id,
|
||||
options_labels: &'a [(&'a T, &'a str)],
|
||||
) -> Self {
|
||||
Self {
|
||||
common: widget::CommonBuilder::default(),
|
||||
f_image: button::Image {
|
||||
image_id: f_image_id,
|
||||
hover_image_id: None,
|
||||
press_image_id: None,
|
||||
src_rect: None,
|
||||
color: button::ImageColor::None,
|
||||
},
|
||||
t_image: button::Image {
|
||||
image_id: t_image_id,
|
||||
hover_image_id: None,
|
||||
press_image_id: None,
|
||||
src_rect: None,
|
||||
color: button::ImageColor::None,
|
||||
},
|
||||
selected,
|
||||
label_style: widget::text::Style::default(),
|
||||
options_labels,
|
||||
label_spacing: 10.0,
|
||||
button_spacing: [5.0, 5.0],
|
||||
button_dims: [15.0, 15.0],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source_rectangle(mut self, rect: Rect) -> Self {
|
||||
self.f_image.src_rect = Some(rect);
|
||||
self.t_image.src_rect = Some(rect);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn image_colors(mut self, f_color: Color, t_color: Color) -> Self {
|
||||
self.f_image.color = button::ImageColor::Normal(f_color);
|
||||
self.t_image.color = button::ImageColor::Normal(t_color);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn image_color_with_feedback(mut self, f_color: Color, t_color: Color) -> Self {
|
||||
self.f_image.color = button::ImageColor::WithFeedback(f_color);
|
||||
self.t_image.color = button::ImageColor::WithFeedback(t_color);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn hover_images(mut self, f_id: image::Id, t_id: image::Id) -> Self {
|
||||
self.f_image.hover_image_id = Some(f_id);
|
||||
self.t_image.hover_image_id = Some(t_id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn press_images(mut self, f_id: image::Id, t_id: image::Id) -> Self {
|
||||
self.f_image.press_image_id = Some(f_id);
|
||||
self.t_image.press_image_id = Some(t_id);
|
||||
self
|
||||
}
|
||||
builder_methods! {
|
||||
pub text_color { label_style.color = Some(Color) }
|
||||
pub font_size { label_style.font_size = Some(FontSize) }
|
||||
pub justify { label_style.justify = Some(text::Justify) }
|
||||
pub line_spacing { label_style.line_spacing = Some(f64) }
|
||||
pub label_spacing { label_spacing = f64 }
|
||||
pub button_spacing { button_spacing = [f64; 2] }
|
||||
pub button_dims { button_dims = [f64; 2] }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Widget for RadioList<'a, T> {
|
||||
type State = State;
|
||||
type Style = ();
|
||||
type Event = Option<(usize, &'a T)>;
|
||||
|
||||
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
||||
State {
|
||||
ids: Ids::new(id_gen),
|
||||
}
|
||||
}
|
||||
|
||||
fn style(&self) -> Self::Style {
|
||||
()
|
||||
}
|
||||
|
||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||
let widget::UpdateArgs {
|
||||
id,
|
||||
state,
|
||||
ui,
|
||||
rect,
|
||||
..
|
||||
} = args;
|
||||
let Self {
|
||||
f_image,
|
||||
t_image,
|
||||
selected,
|
||||
options_labels,
|
||||
label_style,
|
||||
label_spacing,
|
||||
button_spacing,
|
||||
button_dims,
|
||||
..
|
||||
} = self;
|
||||
|
||||
// Ensure we have enough widget ids
|
||||
let num_items = options_labels.len();
|
||||
if state.ids.buttons.len() < num_items || state.ids.labels.len() < num_items {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.buttons
|
||||
.resize(num_items, &mut ui.widget_id_generator());
|
||||
s.ids
|
||||
.labels
|
||||
.resize(num_items, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
|
||||
// Check if the button was clicked.
|
||||
// (Can't use `.set().was_clicked()` because we are changing the image after setting the
|
||||
// widget, which causes flickering since it takes a frame to change after the mouse button
|
||||
// is lifted).
|
||||
let current_selection = (0..num_items)
|
||||
.find(|i| {
|
||||
ui.widget_input(state.ids.buttons[*i])
|
||||
.clicks()
|
||||
.left()
|
||||
.count()
|
||||
% 2
|
||||
== 1
|
||||
})
|
||||
.unwrap_or(selected);
|
||||
|
||||
let (x, y, w, h) = rect.x_y_w_h();
|
||||
for i in 0..num_items {
|
||||
let image = if i == current_selection {
|
||||
t_image
|
||||
} else {
|
||||
f_image
|
||||
};
|
||||
// Button
|
||||
let mut button = button::Button::image(image.image_id)
|
||||
.wh(button_dims)
|
||||
//TODO: implement default width / height functions
|
||||
.x_y(
|
||||
x - w / 2.0 + button_spacing[0],
|
||||
y - h / 2.0
|
||||
- i as f64 * (button_dims[1] + button_spacing[1])
|
||||
- button_spacing[1],
|
||||
)
|
||||
.parent(id);
|
||||
button.show = image;
|
||||
button.set(state.ids.buttons[i], ui);
|
||||
// Label
|
||||
widget::Text::new(options_labels[i].1)
|
||||
.graphics_for(state.ids.buttons[i])
|
||||
.parent(id)
|
||||
.with_style(label_style)
|
||||
.right_from(state.ids.buttons[i], label_spacing)
|
||||
.set(state.ids.labels[i], ui);
|
||||
}
|
||||
|
||||
if current_selection != selected {
|
||||
Some((current_selection, options_labels[current_selection].0))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
@ -225,7 +225,13 @@ impl Window {
|
||||
|
||||
Ok(Self {
|
||||
events_loop,
|
||||
renderer: Renderer::new(device, factory, win_color_view, win_depth_view)?,
|
||||
renderer: Renderer::new(
|
||||
device,
|
||||
factory,
|
||||
win_color_view,
|
||||
win_depth_view,
|
||||
settings.graphics.aa_mode,
|
||||
)?,
|
||||
window,
|
||||
cursor_grabbed: false,
|
||||
pan_sensitivity: settings.gameplay.pan_sensitivity,
|
||||
|
Loading…
Reference in New Issue
Block a user