forked from vova616/GarageEngine
/
Material.go
237 lines (177 loc) · 4.68 KB
/
Material.go
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package engine
import (
"fmt"
"github.com/go-gl/gl"
)
var lastProgram Program
type Program struct {
gl.Program
}
func (p Program) Use() {
if lastProgram != p {
p.Program.Use()
lastProgram = p
}
}
type Material interface {
Load() error
Begin(gobj *GameObject)
End(gobj *GameObject)
}
type BasicMaterial struct {
Program Program
vertexShader string
fragmentShader string
ViewMatrix, ProjMatrix, ModelMatrix, AddColor, Texture, Tiling, Offset gl.UniformLocation
Verts, UV gl.AttribLocation
}
func NewBasicMaterial(vertexShader, fragmentShader string) *BasicMaterial {
return &BasicMaterial{Program: Program{gl.CreateProgram()}, vertexShader: vertexShader, fragmentShader: fragmentShader}
}
func (b *BasicMaterial) Load() error {
program := b.Program
vrt := gl.CreateShader(gl.VERTEX_SHADER)
frg := gl.CreateShader(gl.FRAGMENT_SHADER)
vrt.Source(b.vertexShader)
frg.Source(b.fragmentShader)
vrt.Compile()
if vrt.Get(gl.COMPILE_STATUS) != 1 {
return fmt.Errorf("Error in Compiling Vertex Shader:%s\n", vrt.GetInfoLog())
}
frg.Compile()
if frg.Get(gl.COMPILE_STATUS) != 1 {
return fmt.Errorf("Error in Compiling Fragment Shader:%s\n", frg.GetInfoLog())
}
program.AttachShader(vrt)
program.AttachShader(frg)
program.BindAttribLocation(0, "vertexPos")
program.BindAttribLocation(1, "vertexUV")
program.Link()
b.Verts = program.GetAttribLocation("vertexPos")
b.UV = program.GetAttribLocation("vertexUV")
b.ViewMatrix = program.GetUniformLocation("MView")
b.ProjMatrix = program.GetUniformLocation("MProj")
b.ModelMatrix = program.GetUniformLocation("MModel")
b.Texture = program.GetUniformLocation("mytexture")
b.AddColor = program.GetUniformLocation("addcolor")
b.Tiling = program.GetUniformLocation("tiling")
b.Offset = program.GetUniformLocation("offset")
b.Offset.Uniform2f(0, 0)
b.Tiling.Uniform2f(1, 1)
b.AddColor.Uniform4f(1, 1, 1, 1)
return nil
}
func (b *BasicMaterial) Begin(gobj *GameObject) {
b.Program.Use()
}
func (b *BasicMaterial) End(gobj *GameObject) {
}
var TextureShader gl.Program
var TextureMaterial *BasicMaterial
var internalMaterial *BasicMaterial
var SDFMaterial *BasicMaterial
const spriteVertexShader = `
#version 110
uniform mat4 MProj;
uniform mat4 MView;
uniform mat4 MModel;
uniform vec2 tiling;
uniform vec2 offset;
attribute vec3 vertexPos;
attribute vec2 vertexUV;
varying vec2 UV;
void main(void)
{
gl_Position = MProj * MView * MModel * vec4(vertexPos, 1.0);
UV = (vertexUV * tiling) + offset;
}
`
const spriteFragmentShader = `
#version 110
varying vec2 UV;
uniform sampler2D mytexture;
uniform vec4 addcolor;
void main(void)
{
gl_FragColor = texture2D(mytexture, UV)*addcolor;
}
`
const sdfVertexShader = `
#version 110
uniform mat4 MProj;
uniform mat4 MView;
uniform mat4 MModel;
attribute vec3 vertexPos;
attribute vec2 vertexUV;
varying vec2 UV;
void main(void)
{
gl_Position = MProj * MView * MModel * vec4(vertexPos, 1.0);
UV = vertexUV;
}
`
//Note: This shader needs to get better and get outline/shadow/glow support
const sdfFragmentShader = `
#version 110
varying vec2 UV;
uniform sampler2D mytexture;
uniform vec4 bcolor;
uniform vec4 addcolor;
float aastep(float dist)
{
float threshold = 0.5;
float afwidth = 0.7 * length(vec2(dFdx(dist), dFdy(dist)));
return smoothstep(threshold - afwidth, threshold + afwidth, dist);
}
float aastep2(float dist)
{
float smoothness = 45.0;
float w = clamp( smoothness * (abs(dFdx(dist)) + abs(dFdy(dist))), 0.0, 0.5);
return smoothstep(0.5-w, 0.5+w, dist);
}
void main(void)
{
// retrieve distance from texture
float sdf = texture2D( mytexture, UV).a;
float gamma = 2.2;
vec4 basecolor = addcolor;
bool outline = false;
float outline_min = 0.4;
float outline_min1 = 0.5;
float outline_max = 0.4;
float outline_max1 = 0.6;
vec4 outline_color = vec4(1,0,0,1);
bool softEdges = true;
float softEdgeMin = 0.4;
float softEdgeMax = 0.6;
if (outline && sdf >= outline_min && sdf <= outline_max1 ) {
float ofactor = 1.0;
if (sdf <= outline_min1) {
ofactor = smoothstep(outline_min, outline_min1, sdf);
} else {
ofactor = smoothstep(outline_max1, outline_max, sdf);
}
//lerp
basecolor = addcolor + (outline_color - addcolor) * ofactor;
}
/*
if (softEdges) {
basecolor.a *= smoothstep(softEdgeMin, softEdgeMax, sdf);
} else {
if (sdf >= 0.5) {
basecolor.a = 1.0;
} else {
basecolor.a = 0.0;
}
}
gl_FragColor = basecolor;
*/
// perform adaptive anti-aliasing of the edges\n
float a = aastep(sdf);
a *= basecolor.a;
// gamma correction for linear attenuation
a = pow(a, 1.0/gamma);
gl_FragColor.rgb = basecolor.rgb;
gl_FragColor.a = a;
}
`