mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'imbris/aa' into 'master'
Anti aliasing options See merge request veloren/veloren!514
This commit is contained in:
commit
315637c124
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 sampler2D 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;
|
||||
|
||||
@ -169,15 +36,16 @@ void main() {
|
||||
uv = clamp(uv + vec2(sin(uv.y * 16.0 + tick.x), sin(uv.x * 24.0 + tick.x)) * 0.005, 0, 1);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||
hsva_color.y *= 1.45;
|
||||
hsva_color.z *= 0.85;
|
||||
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;
|
||||
//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);
|
||||
|
@ -120,26 +120,23 @@ impl<'a> Widget for Bag<'a> {
|
||||
.w_h(61.0 * BAG_SCALE, 9.0 * BAG_SCALE)
|
||||
.bottom_right_with_margins_on(ui.window, 60.0, 5.0)
|
||||
.set(state.ids.bag_bot, ui);
|
||||
let mid_height = ((inventory.len() + 4) / 5) as f64 * 44.0;
|
||||
Image::new(self.imgs.bag_mid)
|
||||
.w_h(61.0 * BAG_SCALE, mid_height)
|
||||
.up_from(state.ids.bag_bot, 0.0)
|
||||
.set(state.ids.bag_mid, ui);
|
||||
Image::new(self.imgs.bag_top)
|
||||
.w_h(61.0 * BAG_SCALE, 9.0 * BAG_SCALE)
|
||||
.up_from(state.ids.bag_mid, 0.0)
|
||||
.set(state.ids.bag_top, ui);
|
||||
Image::new(self.imgs.bag_mid)
|
||||
.w_h(61.0 * BAG_SCALE, ((inventory.len() + 4) / 5) as f64 * 44.0)
|
||||
.up_from(state.ids.bag_bot, 0.0)
|
||||
.set(state.ids.bag_mid, ui);
|
||||
|
||||
// Alignment for Grid
|
||||
Rectangle::fill_with(
|
||||
[54.0 * BAG_SCALE, ((inventory.len() + 4) / 5) as f64 * 44.0],
|
||||
color::TRANSPARENT,
|
||||
)
|
||||
.top_left_with_margins_on(state.ids.bag_top, 9.0 * BAG_SCALE, 3.0 * BAG_SCALE)
|
||||
.scroll_kids()
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.inv_alignment, ui);
|
||||
// Create available inventory slot widgets
|
||||
Rectangle::fill_with([54.0 * BAG_SCALE, mid_height], color::TRANSPARENT)
|
||||
.top_left_with_margins_on(state.ids.bag_mid, 0.0, 3.0 * BAG_SCALE)
|
||||
.scroll_kids_vertically()
|
||||
.set(state.ids.inv_alignment, ui);
|
||||
|
||||
// Create available inventory slot widgets
|
||||
if state.ids.inv_slots.len() < inventory.len() {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
@ -147,7 +144,6 @@ impl<'a> Widget for Bag<'a> {
|
||||
.resize(inventory.len(), &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
|
||||
if state.ids.items.len() < inventory.len() {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
@ -157,7 +153,6 @@ impl<'a> Widget for Bag<'a> {
|
||||
}
|
||||
|
||||
// Display inventory contents
|
||||
|
||||
for (i, item) in inventory.slots().iter().enumerate() {
|
||||
let x = i % 5;
|
||||
let y = i / 5;
|
||||
@ -171,16 +166,15 @@ impl<'a> Widget for Bag<'a> {
|
||||
4.0 + y as f64 * (40.0 + 4.0),
|
||||
4.0 + x as f64 * (40.0 + 4.0),
|
||||
) // conrod uses a (y,x) format for placing...
|
||||
.parent(state.ids.inv_alignment) // Avoids the background overlapping available slots
|
||||
// (the margin placement functions do this because that is the same order as "top left")
|
||||
.w_h(40.0, 40.0)
|
||||
.image_color(if is_selected {
|
||||
color::WHITE
|
||||
} else {
|
||||
color::DARK_YELLOW
|
||||
})
|
||||
.floating(true);
|
||||
});
|
||||
|
||||
let slot_widget = if let Some(item) = item {
|
||||
let slot_widget_clicked = if let Some(item) = item {
|
||||
slot_widget
|
||||
.with_tooltip(
|
||||
self.tooltip_manager,
|
||||
@ -191,10 +185,11 @@ impl<'a> Widget for Bag<'a> {
|
||||
.set(state.ids.inv_slots[i], ui)
|
||||
} else {
|
||||
slot_widget.set(state.ids.inv_slots[i], ui)
|
||||
};
|
||||
}
|
||||
.was_clicked();
|
||||
|
||||
// Item
|
||||
if slot_widget.was_clicked() {
|
||||
if slot_widget_clicked {
|
||||
let selected_slot = match state.selected_slot {
|
||||
Some(a) => {
|
||||
if a == i {
|
||||
@ -227,7 +222,6 @@ impl<'a> Widget for Bag<'a> {
|
||||
}
|
||||
|
||||
// Close button
|
||||
|
||||
if Button::image(self.imgs.close_button)
|
||||
.w_h(28.0, 28.0)
|
||||
.hover_image(self.imgs.close_button_hover)
|
||||
|
@ -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,39 @@ 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,
|
||||
)
|
||||
.hover_images(self.imgs.check_mo, self.imgs.check_checked_mo)
|
||||
.press_images(self.imgs.check_press, self.imgs.check_press)
|
||||
.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 -----------------------------------
|
||||
|
94
voxygen/src/render/error.rs
Normal file
94
voxygen/src/render/error.rs
Normal file
@ -0,0 +1,94 @@
|
||||
/// Used to represent one of many possible errors that may be omitted by the rendering subsystem.
|
||||
#[derive(Debug)]
|
||||
pub enum RenderError {
|
||||
PipelineError(gfx::PipelineStateError<String>),
|
||||
UpdateError(gfx::UpdateError<usize>),
|
||||
TexUpdateError(gfx::UpdateError<[u16; 3]>),
|
||||
CombinedError(gfx::CombinedError),
|
||||
BufferCreationError(gfx::buffer::CreationError),
|
||||
IncludeError(glsl_include::Error),
|
||||
MappingError(gfx::mapping::Error),
|
||||
CopyError(gfx::CopyError<[u16; 3], usize>),
|
||||
}
|
||||
|
||||
impl From<gfx::PipelineStateError<String>> for RenderError {
|
||||
fn from(err: gfx::PipelineStateError<String>) -> Self {
|
||||
Self::PipelineError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::PipelineStateError<&str>> for RenderError {
|
||||
fn from(err: gfx::PipelineStateError<&str>) -> Self {
|
||||
match err {
|
||||
gfx::PipelineStateError::DescriptorInit(err) => {
|
||||
gfx::PipelineStateError::DescriptorInit(err.into())
|
||||
}
|
||||
err => err,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
impl From<gfx::shade::ProgramError> for RenderError {
|
||||
fn from(err: gfx::shade::ProgramError) -> Self {
|
||||
gfx::PipelineStateError::<String>::Program(err).into()
|
||||
}
|
||||
}
|
||||
impl From<gfx::UpdateError<usize>> for RenderError {
|
||||
fn from(err: gfx::UpdateError<usize>) -> Self {
|
||||
Self::UpdateError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::UpdateError<[u16; 3]>> for RenderError {
|
||||
fn from(err: gfx::UpdateError<[u16; 3]>) -> Self {
|
||||
Self::TexUpdateError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::CombinedError> for RenderError {
|
||||
fn from(err: gfx::CombinedError) -> Self {
|
||||
Self::CombinedError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::TargetViewError> for RenderError {
|
||||
fn from(err: gfx::TargetViewError) -> Self {
|
||||
Self::CombinedError(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::ResourceViewError> for RenderError {
|
||||
fn from(err: gfx::ResourceViewError) -> Self {
|
||||
Self::CombinedError(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::texture::CreationError> for RenderError {
|
||||
fn from(err: gfx::texture::CreationError) -> Self {
|
||||
Self::CombinedError(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::buffer::CreationError> for RenderError {
|
||||
fn from(err: gfx::buffer::CreationError) -> Self {
|
||||
Self::BufferCreationError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<glsl_include::Error> for RenderError {
|
||||
fn from(err: glsl_include::Error) -> Self {
|
||||
Self::IncludeError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::mapping::Error> for RenderError {
|
||||
fn from(err: gfx::mapping::Error) -> Self {
|
||||
Self::MappingError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<gfx::CopyError<[u16; 3], usize>> for RenderError {
|
||||
fn from(err: gfx::CopyError<[u16; 3], usize>) -> Self {
|
||||
Self::CopyError(err)
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod consts;
|
||||
mod error;
|
||||
pub mod instances;
|
||||
pub mod mesh;
|
||||
pub mod model;
|
||||
@ -10,6 +11,7 @@ mod util;
|
||||
// Reexports
|
||||
pub use self::{
|
||||
consts::Consts,
|
||||
error::RenderError,
|
||||
instances::Instances,
|
||||
mesh::{Mesh, Quad, Tri},
|
||||
model::{DynamicModel, Model},
|
||||
@ -37,19 +39,6 @@ use gfx_device_gl as gfx_backend;
|
||||
|
||||
use gfx;
|
||||
|
||||
/// Used to represent one of many possible errors that may be omitted by the rendering subsystem.
|
||||
#[derive(Debug)]
|
||||
pub enum RenderError {
|
||||
PipelineError(gfx::PipelineStateError<String>),
|
||||
UpdateError(gfx::UpdateError<usize>),
|
||||
TexUpdateError(gfx::UpdateError<[u16; 3]>),
|
||||
CombinedError(gfx::CombinedError),
|
||||
BufferCreationError(gfx::buffer::CreationError),
|
||||
IncludeError(glsl_include::Error),
|
||||
MappingError(gfx::mapping::Error),
|
||||
CopyError(gfx::CopyError<[u16; 3], usize>),
|
||||
}
|
||||
|
||||
/// Used to represent a specific rendering configuration.
|
||||
///
|
||||
/// Note that pipelines are tied to the
|
||||
@ -63,3 +52,15 @@ pub enum RenderError {
|
||||
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,13 +186,54 @@ impl Renderer {
|
||||
fn create_rt_views(
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
size: (u16, u16),
|
||||
aa_mode: AaMode,
|
||||
) -> Result<(TgtColorView, TgtDepthView, TgtColorRes), RenderError> {
|
||||
let (_, tgt_color_res, tgt_color_view) = factory
|
||||
.create_render_target::<TgtColorFmt>(size.0, size.1)
|
||||
.map_err(RenderError::CombinedError)?;;
|
||||
let tgt_depth_view = factory
|
||||
.create_depth_stencil_view_only::<TgtDepthFmt>(size.0, size.1)
|
||||
.map_err(RenderError::CombinedError)?;;
|
||||
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
|
||||
>::get_channel_type();
|
||||
let tgt_color_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(color_cty),
|
||||
)?;
|
||||
let tgt_color_res = factory.view_texture_as_shader_resource::<TgtColorFmt>(
|
||||
&tgt_color_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
|
||||
|
||||
let depth_cty = <<TgtDepthFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
|
||||
let tgt_depth_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_cty),
|
||||
)?;
|
||||
let tgt_depth_view = factory.view_texture_as_depth_stencil_trivial(&tgt_depth_tex)?;
|
||||
|
||||
Ok((tgt_color_view, tgt_depth_view, tgt_color_res))
|
||||
}
|
||||
|
||||
@ -199,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
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,33 +387,29 @@ impl Renderer {
|
||||
type WinSurfaceData = <<WinColorFmt as Formatted>::Surface as SurfaceTyped>::DataType;
|
||||
let download = self
|
||||
.factory
|
||||
.create_download_buffer::<WinSurfaceData>(width as usize * height as usize)
|
||||
.map_err(|err| RenderError::BufferCreationError(err))?;
|
||||
self.encoder
|
||||
.copy_texture_to_buffer_raw(
|
||||
self.win_color_view.raw().get_texture(),
|
||||
None,
|
||||
gfx::texture::RawImageInfo {
|
||||
xoffset: 0,
|
||||
yoffset: 0,
|
||||
zoffset: 0,
|
||||
width,
|
||||
height,
|
||||
depth: 0,
|
||||
format: WinColorFmt::get_format(),
|
||||
mipmap: 0,
|
||||
},
|
||||
download.raw(),
|
||||
0,
|
||||
)
|
||||
.map_err(|err| RenderError::CopyError(err))?;
|
||||
.create_download_buffer::<WinSurfaceData>(width as usize * height as usize)?;
|
||||
self.encoder.copy_texture_to_buffer_raw(
|
||||
self.win_color_view.raw().get_texture(),
|
||||
None,
|
||||
gfx::texture::RawImageInfo {
|
||||
xoffset: 0,
|
||||
yoffset: 0,
|
||||
zoffset: 0,
|
||||
width,
|
||||
height,
|
||||
depth: 0,
|
||||
format: WinColorFmt::get_format(),
|
||||
mipmap: 0,
|
||||
},
|
||||
download.raw(),
|
||||
0,
|
||||
)?;
|
||||
self.flush();
|
||||
|
||||
// Assumes that the format is Rgba8.
|
||||
let raw_data = self
|
||||
.factory
|
||||
.read_mapping(&download)
|
||||
.map_err(|err| RenderError::MappingError(err))?
|
||||
.read_mapping(&download)?
|
||||
.chunks_exact(width as usize)
|
||||
.rev()
|
||||
.flatten()
|
||||
@ -576,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<
|
||||
(
|
||||
@ -605,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(
|
||||
@ -722,38 +804,23 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
||||
ctx: &IncludeContext,
|
||||
cull_face: gfx::state::CullFace,
|
||||
) -> Result<GfxPipeline<P>, RenderError> {
|
||||
let vs = ctx.expand(vs).map_err(RenderError::IncludeError)?;
|
||||
let fs = ctx.expand(fs).map_err(RenderError::IncludeError)?;
|
||||
let vs = ctx.expand(vs)?;
|
||||
let fs = ctx.expand(fs)?;
|
||||
|
||||
let program = factory
|
||||
.link_program(vs.as_bytes(), fs.as_bytes())
|
||||
.map_err(|err| RenderError::PipelineError(gfx::PipelineStateError::Program(err)))?;
|
||||
let program = factory.link_program(vs.as_bytes(), fs.as_bytes())?;
|
||||
|
||||
Ok(GfxPipeline {
|
||||
pso: factory
|
||||
.create_pipeline_from_program(
|
||||
&program,
|
||||
gfx::Primitive::TriangleList,
|
||||
gfx::state::Rasterizer {
|
||||
front_face: gfx::state::FrontFace::CounterClockwise,
|
||||
cull_face,
|
||||
method: gfx::state::RasterMethod::Fill,
|
||||
offset: None,
|
||||
samples: Some(gfx::state::MultiSample),
|
||||
},
|
||||
pipe,
|
||||
)
|
||||
// Do some funky things to work around an oddity in gfx's error ownership rules.
|
||||
.map_err(|err| {
|
||||
RenderError::PipelineError(match err {
|
||||
gfx::PipelineStateError::Program(err) => gfx::PipelineStateError::Program(err),
|
||||
gfx::PipelineStateError::DescriptorInit(err) => {
|
||||
gfx::PipelineStateError::DescriptorInit(err.into())
|
||||
}
|
||||
gfx::PipelineStateError::DeviceCreate(err) => {
|
||||
gfx::PipelineStateError::DeviceCreate(err)
|
||||
}
|
||||
})
|
||||
})?,
|
||||
pso: factory.create_pipeline_from_program(
|
||||
&program,
|
||||
gfx::Primitive::TriangleList,
|
||||
gfx::state::Rasterizer {
|
||||
front_face: gfx::state::FrontFace::CounterClockwise,
|
||||
cull_face,
|
||||
method: gfx::state::RasterMethod::Fill,
|
||||
offset: None,
|
||||
samples: Some(gfx::state::MultiSample),
|
||||
},
|
||||
pipe,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
@ -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