1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
use gl::*;
use glw;
use trace;
let VAO_BLOCKS: uint = 0;
let SHADER_BLOCKS: uint = 0;
let VAO_GUI: uint = 0;
let SHADER_GUI: uint = 0;
fn shaders_init() void = {
trace::info(&trace::root, "loading shaders...");
glGenVertexArrays(1, &VAO_BLOCKS);
glBindVertexArray(VAO_BLOCKS);
glEnableVertexAttribArray(0);
glVertexAttribBinding(0, 0);
glVertexAttribFormat(0, 3, GL_UNSIGNED_SHORT, 0,
offset(Vertex { ... }.position): uint);
glEnableVertexAttribArray(1);
glVertexAttribBinding(1, 0);
glVertexAttribFormat(1, 3, GL_BYTE, 1,
offset(Vertex { ... }.normal): uint);
glEnableVertexAttribArray(2);
glVertexAttribBinding(2, 0);
glVertexAttribFormat(2, 2, GL_UNSIGNED_SHORT, 0,
offset(Vertex { ... }.texcoord): uint);
glEnableVertexAttribArray(3);
glVertexAttribBinding(3, 0);
glVertexAttribIFormat(3, 1, GL_UNSIGNED_BYTE,
offset(Vertex { ... }.flags): uint);
glBindVertexArray(0);
SHADER_BLOCKS = glCreateProgram();
glAttachShader(SHADER_BLOCKS, glw::compile_shader_src(
GL_VERTEX_SHADER,
"#version 310 es
layout(location = 0) uniform mat4 u_transform;
layout(location = 1) uniform vec3 u_position;
layout(location = 2) uniform float u_texcoord_scale;
layout(location = 0) in vec3 a_position;
layout(location = 1) in lowp vec3 a_normal;
layout(location = 2) in vec2 a_texcoord;
layout(location = 3) in lowp uint a_flags;
const lowp uint U_EXCL = 1u << 0u;
const lowp uint V_EXCL = 1u << 1u;
// the smallest value such that 1.0 - EPSILON < 1.0
const float EPSILON = 1.0 / float(1 << 24);
out lowp vec3 v_normal;
out vec2 v_texcoord;
void main() {
vec3 position = a_position * (1.0 / 2048.0) - 1.0 + u_position;
gl_Position = u_transform * vec4(position, 1.0);
v_normal = a_normal;
v_texcoord = u_texcoord_scale * a_texcoord;
// XXX: This fixes an issue with occassional texture
// bleeding at the scale of individual pixels on the
// bottom and right edges of a sprite, caused by the
// interpolated texture coordinate coming out as equal
// to the upper limit for that quad, which under
// GL_NEAREST filtering actually belongs to a texel on
// the wrong side of the sprite boundary.
//
// For whatever reason Mesa llvmpipe exhibits more
// severe rounding errors on all sprite edges, where
// v_texcoord in the fragment shader can be _below_ the
// supposed lower bound. An EPSILON of 2^-16 applied
// to all edges seems to be necessary in that case.
// I assume this to be a numerical compromise in favor
// of acceptable software rendering performance, but
// wasn't able to find a mention of it anywhere
// (I didn't look at the code, though), and the GL spec
// doesn't seem to explicitly permit it, though I well
// might be wrong about that.
//
// (2024 note): I am very tempted to remove all that and
// replace it with 'Removes Herobrine. Do not touch.'.
if ((a_flags & U_EXCL) != 0u) {
v_texcoord.x -= EPSILON;
}
if ((a_flags & V_EXCL) != 0u) {
v_texcoord.y -= EPSILON;
}
}
",
));
glAttachShader(SHADER_BLOCKS, glw::compile_shader_src(
GL_FRAGMENT_SHADER,
"#version 310 es
precision mediump float;
layout(location = 3) uniform mediump sampler2D tex_albedo;
in lowp vec3 v_normal;
in highp vec2 v_texcoord;
layout(location = 0) out vec4 f_color;
void main() {
vec4 albedo = texture(tex_albedo, v_texcoord);
if (albedo.a < 0.1) {
discard;
}
float light = 0.7
+ dot(vec3(0, 0.2, 0), v_normal)
+ abs(dot(vec3(0.1, 0, 0), v_normal));
f_color = vec4(light * albedo.rgb, albedo.a);
}
",
));
glw::link_program(SHADER_BLOCKS);
glUseProgram(SHADER_BLOCKS);
glUniform1f(2, 1.0 / ATLAS_BLOCKS.width: f32);
glUniform1i(3, 0);
glGenVertexArrays(1, &VAO_GUI);
glBindVertexArray(VAO_GUI);
glEnableVertexAttribArray(0);
glVertexAttribBinding(0, 0);
glVertexAttribFormat(0, 2, GL_FLOAT, 0,
offset(GuiVertex { ... }.position): uint);
glEnableVertexAttribArray(1);
glVertexAttribBinding(1, 0);
glVertexAttribFormat(1, 2, GL_FLOAT, 0,
offset(GuiVertex { ... }.texcoord): uint);
glEnableVertexAttribArray(2);
glVertexAttribBinding(2, 0);
glVertexAttribFormat(2, 3, GL_UNSIGNED_BYTE, 1,
offset(GuiVertex { ... }.color): uint);
glBindVertexArray(0);
SHADER_GUI = glCreateProgram();
glAttachShader(SHADER_GUI, glw::compile_shader_src(
GL_VERTEX_SHADER,
"#version 310 es
layout(location = 0) uniform mat4 u_transform;
layout(location = 0) in vec2 a_position;
layout(location = 1) in vec2 a_texcoord;
layout(location = 2) in vec4 a_color;
out vec2 v_texcoord;
out vec4 v_color;
void main() {
gl_Position = u_transform * vec4(a_position, 0.0, 1.0);
v_texcoord = a_texcoord;
// XXX: crude srgb for now...
v_color = vec4(pow(a_color.rgb, vec3(2.2)), a_color.a);
}
",
));
glAttachShader(SHADER_GUI, glw::compile_shader_src(
GL_FRAGMENT_SHADER,
"#version 310 es
precision mediump float;
layout(location = 1) uniform sampler2D tex_color;
in vec2 v_texcoord;
in vec4 v_color;
layout(location = 0) out vec4 f_color;
void main() {
f_color = v_color * texture(tex_color, v_texcoord);
}
",
));
glw::link_program(SHADER_GUI);
glUseProgram(SHADER_GUI);
glUniform1i(1, 0);
glUseProgram(0);
};
|