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:
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
|
#version 330 core
|
||||||
|
|
||||||
#include <globals.glsl>
|
#include <globals.glsl>
|
||||||
|
// Note: The sampler uniform is declared here because it differs for MSAA
|
||||||
uniform sampler2DMS src_color;
|
#include <anti-aliasing.glsl>
|
||||||
|
|
||||||
in vec2 f_pos;
|
in vec2 f_pos;
|
||||||
|
|
||||||
@ -13,137 +13,6 @@ uniform u_locals {
|
|||||||
|
|
||||||
out vec4 tgt_color;
|
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) {
|
vec3 rgb2hsv(vec3 c) {
|
||||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
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));
|
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);
|
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float FXAA_SCALE = 1.5;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 uv = (f_pos + 1.0) * 0.5;
|
vec2 uv = (f_pos + 1.0) * 0.5;
|
||||||
|
|
||||||
@ -170,22 +37,16 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//vec4 fxaa_color = fxaa_apply(src_color, uv * screen_res.xy * FXAA_SCALE, screen_res.xy * FXAA_SCALE);
|
vec4 aa_color = aa_apply(src_color, uv * screen_res.xy, screen_res.xy);
|
||||||
//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 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
//vec4 hsva_color = vec4(rgb2hsv(fxaa_color.rgb), fxaa_color.a);
|
||||||
hsva_color.y *= 1.45;
|
//hsva_color.y *= 1.45;
|
||||||
hsva_color.z *= 0.85;
|
//hsva_color.z *= 0.85;
|
||||||
//hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0);
|
//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) {
|
if (medium.x == 1u) {
|
||||||
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
final_color *= vec4(0.2, 0.2, 0.8, 1.0);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ use social::{Social, SocialTab};
|
|||||||
use spell::Spell;
|
use spell::Spell;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
render::{Consts, Globals, Renderer},
|
render::{AaMode, Consts, Globals, Renderer},
|
||||||
scene::camera::Camera,
|
scene::camera::Camera,
|
||||||
settings::ControlSettings,
|
settings::ControlSettings,
|
||||||
ui::{Ingameable, ScaleMode, Ui},
|
ui::{Ingameable, ScaleMode, Ui},
|
||||||
@ -158,6 +158,7 @@ pub enum Event {
|
|||||||
ChangeAudioDevice(String),
|
ChangeAudioDevice(String),
|
||||||
ChangeMaxFPS(u32),
|
ChangeMaxFPS(u32),
|
||||||
ChangeFOV(u16),
|
ChangeFOV(u16),
|
||||||
|
ChangeAaMode(AaMode),
|
||||||
CrosshairTransp(f32),
|
CrosshairTransp(f32),
|
||||||
CrosshairType(CrosshairType),
|
CrosshairType(CrosshairType),
|
||||||
ToggleXpBar(XpBar),
|
ToggleXpBar(XpBar),
|
||||||
@ -832,6 +833,9 @@ impl Hud {
|
|||||||
settings_window::Event::AdjustFOV(new_fov) => {
|
settings_window::Event::AdjustFOV(new_fov) => {
|
||||||
events.push(Event::ChangeFOV(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,
|
img_ids::Imgs, BarNumbers, CrosshairType, Fonts, ShortcutNumbers, Show, XpBar, TEXT_COLOR,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
ui::{ImageSlider, ScaleMode, ToggleButton},
|
render::AaMode,
|
||||||
|
ui::{ImageSlider, RadioList, ScaleMode, ToggleButton},
|
||||||
GlobalState,
|
GlobalState,
|
||||||
};
|
};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
@ -76,6 +77,8 @@ widget_ids! {
|
|||||||
fov_slider,
|
fov_slider,
|
||||||
fov_text,
|
fov_text,
|
||||||
fov_value,
|
fov_value,
|
||||||
|
aa_radio_buttons,
|
||||||
|
aa_mode_text,
|
||||||
audio_volume_slider,
|
audio_volume_slider,
|
||||||
audio_volume_text,
|
audio_volume_text,
|
||||||
sfx_volume_slider,
|
sfx_volume_slider,
|
||||||
@ -153,6 +156,7 @@ pub enum Event {
|
|||||||
AdjustMouseZoom(u32),
|
AdjustMouseZoom(u32),
|
||||||
AdjustViewDistance(u32),
|
AdjustViewDistance(u32),
|
||||||
AdjustFOV(u16),
|
AdjustFOV(u16),
|
||||||
|
ChangeAaMode(AaMode),
|
||||||
AdjustMusicVolume(f32),
|
AdjustMusicVolume(f32),
|
||||||
AdjustSfxVolume(f32),
|
AdjustSfxVolume(f32),
|
||||||
ChangeAudioDevice(String),
|
ChangeAudioDevice(String),
|
||||||
@ -1196,6 +1200,37 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.font_id(self.fonts.opensans)
|
.font_id(self.fonts.opensans)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.fov_value, ui);
|
.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 -----------------------------------
|
// 5) Sound Tab -----------------------------------
|
||||||
|
@ -52,3 +52,15 @@ use gfx;
|
|||||||
pub trait Pipeline {
|
pub trait Pipeline {
|
||||||
type Vertex: Clone + gfx::traits::Pod + gfx::pso::buffer::Structure<gfx::format::Format>;
|
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},
|
model::{DynamicModel, Model},
|
||||||
pipelines::{figure, fluid, postprocess, skybox, sprite, terrain, ui, Globals, Light, Shadow},
|
pipelines::{figure, fluid, postprocess, skybox, sprite, terrain, ui, Globals, Light, Shadow},
|
||||||
texture::Texture,
|
texture::Texture,
|
||||||
Pipeline, RenderError,
|
AaMode, Pipeline, RenderError,
|
||||||
};
|
};
|
||||||
use common::assets::{self, watch::ReloadIndicator};
|
use common::assets::{self, watch::ReloadIndicator};
|
||||||
use gfx::{
|
use gfx::{
|
||||||
@ -71,6 +71,8 @@ pub struct Renderer {
|
|||||||
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
postprocess_pipeline: GfxPipeline<postprocess::pipe::Init<'static>>,
|
||||||
|
|
||||||
shader_reload_indicator: ReloadIndicator,
|
shader_reload_indicator: ReloadIndicator,
|
||||||
|
|
||||||
|
aa_mode: AaMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
@ -80,6 +82,7 @@ impl Renderer {
|
|||||||
mut factory: gfx_backend::Factory,
|
mut factory: gfx_backend::Factory,
|
||||||
win_color_view: WinColorView,
|
win_color_view: WinColorView,
|
||||||
win_depth_view: WinDepthView,
|
win_depth_view: WinDepthView,
|
||||||
|
aa_mode: AaMode,
|
||||||
) -> Result<Self, RenderError> {
|
) -> Result<Self, RenderError> {
|
||||||
let mut shader_reload_indicator = ReloadIndicator::new();
|
let mut shader_reload_indicator = ReloadIndicator::new();
|
||||||
|
|
||||||
@ -91,11 +94,11 @@ impl Renderer {
|
|||||||
sprite_pipeline,
|
sprite_pipeline,
|
||||||
ui_pipeline,
|
ui_pipeline,
|
||||||
postprocess_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 dims = win_color_view.get_dimensions();
|
||||||
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
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();
|
let sampler = factory.create_sampler_linear();
|
||||||
|
|
||||||
@ -122,6 +125,8 @@ impl Renderer {
|
|||||||
postprocess_pipeline,
|
postprocess_pipeline,
|
||||||
|
|
||||||
shader_reload_indicator,
|
shader_reload_indicator,
|
||||||
|
|
||||||
|
aa_mode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +154,19 @@ impl Renderer {
|
|||||||
(&mut self.win_color_view, &mut self.win_depth_view)
|
(&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.
|
/// Resize internal render targets to match window render target dimensions.
|
||||||
pub fn on_resize(&mut self) -> Result<(), RenderError> {
|
pub fn on_resize(&mut self) -> Result<(), RenderError> {
|
||||||
let dims = self.win_color_view.get_dimensions();
|
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.
|
// Avoid panics when creating texture with w,h of 0,0.
|
||||||
if dims.0 != 0 && dims.1 != 0 {
|
if dims.0 != 0 && dims.1 != 0 {
|
||||||
let (tgt_color_view, tgt_depth_view, tgt_color_res) =
|
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_res = tgt_color_res;
|
||||||
self.tgt_color_view = tgt_color_view;
|
self.tgt_color_view = tgt_color_view;
|
||||||
self.tgt_depth_view = tgt_depth_view;
|
self.tgt_depth_view = tgt_depth_view;
|
||||||
@ -168,8 +186,26 @@ impl Renderer {
|
|||||||
fn create_rt_views(
|
fn create_rt_views(
|
||||||
factory: &mut gfx_device_gl::Factory,
|
factory: &mut gfx_device_gl::Factory,
|
||||||
size: (u16, u16),
|
size: (u16, u16),
|
||||||
|
aa_mode: AaMode,
|
||||||
) -> Result<(TgtColorView, TgtDepthView, TgtColorRes), RenderError> {
|
) -> 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 levels = 1;
|
||||||
|
|
||||||
let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
|
let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
|
||||||
@ -222,7 +258,17 @@ impl Renderer {
|
|||||||
|
|
||||||
// If the shaders files were changed attempt to recreate the shaders
|
// If the shaders files were changed attempt to recreate the shaders
|
||||||
if self.shader_reload_indicator.reloaded() {
|
if self.shader_reload_indicator.reloaded() {
|
||||||
match create_pipelines(&mut self.factory, &mut self.shader_reload_indicator) {
|
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((
|
Ok((
|
||||||
skybox_pipeline,
|
skybox_pipeline,
|
||||||
figure_pipeline,
|
figure_pipeline,
|
||||||
@ -246,7 +292,6 @@ impl Renderer {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new set of constants with the provided values.
|
/// Create a new set of constants with the provided values.
|
||||||
pub fn create_consts<T: Copy + gfx::traits::Pod>(
|
pub fn create_consts<T: Copy + gfx::traits::Pod>(
|
||||||
@ -595,6 +640,7 @@ struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
|||||||
/// Creates all the pipelines used to render.
|
/// Creates all the pipelines used to render.
|
||||||
fn create_pipelines(
|
fn create_pipelines(
|
||||||
factory: &mut gfx_backend::Factory,
|
factory: &mut gfx_backend::Factory,
|
||||||
|
aa_mode: AaMode,
|
||||||
shader_reload_indicator: &mut ReloadIndicator,
|
shader_reload_indicator: &mut ReloadIndicator,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
@ -624,12 +670,29 @@ fn create_pipelines(
|
|||||||
assets::load_watched::<String>("voxygen.shaders.include.random", shader_reload_indicator)
|
assets::load_watched::<String>("voxygen.shaders.include.random", shader_reload_indicator)
|
||||||
.unwrap();
|
.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();
|
let mut include_ctx = IncludeContext::new();
|
||||||
include_ctx.include("globals.glsl", &globals);
|
include_ctx.include("globals.glsl", &globals);
|
||||||
include_ctx.include("sky.glsl", &sky);
|
include_ctx.include("sky.glsl", &sky);
|
||||||
include_ctx.include("light.glsl", &light);
|
include_ctx.include("light.glsl", &light);
|
||||||
include_ctx.include("srgb.glsl", &srgb);
|
include_ctx.include("srgb.glsl", &srgb);
|
||||||
include_ctx.include("random.glsl", &random);
|
include_ctx.include("random.glsl", &random);
|
||||||
|
include_ctx.include("anti-aliasing.glsl", &anti_alias);
|
||||||
|
|
||||||
// Construct a pipeline for rendering skyboxes
|
// Construct a pipeline for rendering skyboxes
|
||||||
let skybox_pipeline = create_pipeline(
|
let skybox_pipeline = create_pipeline(
|
||||||
|
@ -455,7 +455,17 @@ impl PlayState for SessionState {
|
|||||||
HudEvent::ChangeFOV(new_fov) => {
|
HudEvent::ChangeFOV(new_fov) => {
|
||||||
global_state.settings.graphics.fov = new_fov;
|
global_state.settings.graphics.fov = new_fov;
|
||||||
global_state.settings.save_to_file_warn();
|
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::{
|
use crate::{
|
||||||
hud::{BarNumbers, CrosshairType, ShortcutNumbers, XpBar},
|
hud::{BarNumbers, CrosshairType, ShortcutNumbers, XpBar},
|
||||||
|
render::AaMode,
|
||||||
ui::ScaleMode,
|
ui::ScaleMode,
|
||||||
window::KeyMouse,
|
window::KeyMouse,
|
||||||
};
|
};
|
||||||
@ -160,6 +161,7 @@ pub struct GraphicsSettings {
|
|||||||
pub view_distance: u32,
|
pub view_distance: u32,
|
||||||
pub max_fps: u32,
|
pub max_fps: u32,
|
||||||
pub fov: u16,
|
pub fov: u16,
|
||||||
|
pub aa_mode: AaMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GraphicsSettings {
|
impl Default for GraphicsSettings {
|
||||||
@ -168,6 +170,7 @@ impl Default for GraphicsSettings {
|
|||||||
view_distance: 5,
|
view_distance: 5,
|
||||||
max_fps: 60,
|
max_fps: 60,
|
||||||
fov: 75,
|
fov: 75,
|
||||||
|
aa_mode: AaMode::Fxaa,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ pub use widgets::{
|
|||||||
image_frame::ImageFrame,
|
image_frame::ImageFrame,
|
||||||
image_slider::ImageSlider,
|
image_slider::ImageSlider,
|
||||||
ingame::{Ingame, IngameAnchor, Ingameable},
|
ingame::{Ingame, IngameAnchor, Ingameable},
|
||||||
|
radio_list::RadioList,
|
||||||
toggle_button::ToggleButton,
|
toggle_button::ToggleButton,
|
||||||
tooltip::{Tooltip, TooltipManager, Tooltipable},
|
tooltip::{Tooltip, TooltipManager, Tooltipable},
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod image_frame;
|
pub mod image_frame;
|
||||||
pub mod image_slider;
|
pub mod image_slider;
|
||||||
pub mod ingame;
|
pub mod ingame;
|
||||||
|
pub mod radio_list;
|
||||||
pub mod toggle_button;
|
pub mod toggle_button;
|
||||||
pub mod tooltip;
|
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 {
|
Ok(Self {
|
||||||
events_loop,
|
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,
|
window,
|
||||||
cursor_grabbed: false,
|
cursor_grabbed: false,
|
||||||
pan_sensitivity: settings.gameplay.pan_sensitivity,
|
pan_sensitivity: settings.gameplay.pan_sensitivity,
|
||||||
|
Reference in New Issue
Block a user