cut down on redundant gl uniform changes
This commit is contained in:
@@ -56,10 +56,10 @@ public:
|
||||
uint32_t height = 0;
|
||||
|
||||
// physical (framebuffer) dimensions
|
||||
uint32_t fb_width = 0;
|
||||
uint32_t fb_height = 0;
|
||||
float fb_width = 0;
|
||||
float fb_height = 0;
|
||||
|
||||
double pixelRatio = 1;
|
||||
float pixelRatio = 1;
|
||||
|
||||
private:
|
||||
double x = 0, y = 0; // pixel values of the map center in the current scale
|
||||
|
||||
@@ -11,18 +11,38 @@ public:
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
int32_t a_pos;
|
||||
int32_t a_extrude;
|
||||
// int32_t a_linesofar;
|
||||
void setExtrudeMatrix(const std::array<float, 16>& exmatrix);
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
void setLineWidth(const std::array<float, 2>& linewidth);
|
||||
void setRatio(float ratio);
|
||||
void setDashArray(const std::array<float, 2>& dasharray);
|
||||
void setDebug(float debug);
|
||||
|
||||
int32_t u_exmatrix;
|
||||
int32_t u_linewidth;
|
||||
int32_t u_color;
|
||||
int32_t u_ratio;
|
||||
int32_t u_dasharray;
|
||||
int32_t u_debug;
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
int32_t a_extrude = -1;
|
||||
// int32_t a_linesofar = -1;
|
||||
|
||||
std::array<float, 16> exmatrix = {};
|
||||
int32_t u_exmatrix = -1;
|
||||
|
||||
std::array<float, 4> color = {};
|
||||
int32_t u_color = -1;
|
||||
|
||||
std::array<float, 2> linewidth = {};
|
||||
int32_t u_linewidth = -1;
|
||||
|
||||
float ratio = 0;
|
||||
int32_t u_ratio = -1;
|
||||
|
||||
std::array<float, 2> dasharray = {};
|
||||
int32_t u_dasharray = -1;
|
||||
|
||||
float debug = 0;
|
||||
int32_t u_debug = -1;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,12 +11,25 @@ public:
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
int32_t a_pos;
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
void setWorld(const std::array<float, 2>& world);
|
||||
void setLineWidth(const std::array<float, 2>& linewidth);
|
||||
void setSize(float size);
|
||||
|
||||
int32_t u_world;
|
||||
int32_t u_linewidth;
|
||||
int32_t u_color;
|
||||
int32_t u_size;
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
std::array<float, 4> color = {};
|
||||
int32_t u_color = -1;
|
||||
|
||||
std::array<float, 2> world = {};
|
||||
int32_t u_world = -1;
|
||||
|
||||
std::array<float, 2> linewidth = {};
|
||||
int32_t u_linewidth = -1;
|
||||
|
||||
float size = 0;
|
||||
int32_t u_size = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,14 +13,15 @@ public:
|
||||
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
void setWorld(const std::array<float, 2>& world);
|
||||
|
||||
private:
|
||||
int32_t a_pos;
|
||||
int32_t a_pos = -1;
|
||||
|
||||
std::array<float, 4> color;
|
||||
int32_t u_color;
|
||||
std::array<float, 4> color = {};
|
||||
int32_t u_color = -1;
|
||||
|
||||
std::array<float, 2> world;
|
||||
int32_t u_world;
|
||||
std::array<float, 2> world = {};
|
||||
int32_t u_world = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,14 +11,33 @@ public:
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
int32_t a_pos;
|
||||
int32_t u_color;
|
||||
int32_t u_offset;
|
||||
int32_t u_pattern_size;
|
||||
int32_t u_pattern_tl;
|
||||
int32_t u_pattern_br;
|
||||
int32_t u_mix;
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
void setOffset(const std::array<float, 2>& offset);
|
||||
void setPatternSize(const std::array<float, 2>& pattern_size);
|
||||
void setPatternTopLeft(const std::array<float, 2>& pattern_tl);
|
||||
void setPatternBottomRight(const std::array<float, 2>& pattern_br);
|
||||
void setMix(float mix);
|
||||
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
std::array<float, 4> color = {};
|
||||
int32_t u_color = -1;
|
||||
|
||||
std::array<float, 2> offset = {};
|
||||
int32_t u_offset = -1;
|
||||
|
||||
std::array<float, 2> pattern_size = {};
|
||||
int32_t u_pattern_size = -1;
|
||||
|
||||
std::array<float, 2> pattern_tl = {};
|
||||
int32_t u_pattern_tl = -1;
|
||||
|
||||
std::array<float, 2> pattern_br = {};
|
||||
int32_t u_pattern_br = -1;
|
||||
|
||||
float mix = 0;
|
||||
int32_t u_mix = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@ public:
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
|
||||
private:
|
||||
int32_t a_pos;
|
||||
int32_t a_pos = -1;
|
||||
|
||||
std::array<float, 4> color;
|
||||
int32_t u_color;
|
||||
std::array<float, 4> color = {};
|
||||
int32_t u_color = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define LLMR_RENDERER_SHADER
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
#include <llmr/util/noncopyable.hpp>
|
||||
#include <llmr/util/mat4.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
@@ -14,14 +14,14 @@ public:
|
||||
bool valid;
|
||||
uint32_t program;
|
||||
|
||||
void setMatrix(const mat4& matrix);
|
||||
void setMatrix(const std::array<float, 16>& matrix);
|
||||
|
||||
private:
|
||||
bool compileShader(uint32_t *shader, uint32_t type, const char *source);
|
||||
|
||||
protected:
|
||||
int32_t u_matrix;
|
||||
mat4 matrix;
|
||||
std::array<float, 16> matrix = {};
|
||||
int32_t u_matrix = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
}
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader->setWorld({{ (float)transform.fb_width, (float)transform.fb_height }});
|
||||
outlineShader->setWorld({{ transform.fb_width, transform.fb_height }});
|
||||
bucket.drawVertices(*outlineShader);
|
||||
}
|
||||
|
||||
@@ -259,23 +259,27 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
// Draw texture fill
|
||||
ImagePosition imagePos = style.sprite->getPosition(properties.image, true);
|
||||
|
||||
double factor = 8.0 / pow(2, transform.getIntegerZoom() - id.z);
|
||||
double mix = fmod(transform.getZoom(), 1.0);
|
||||
vec2<double> imageSize { imagePos.size.x * factor, imagePos.size.y * factor };
|
||||
float factor = 8.0 / pow(2, transform.getIntegerZoom() - id.z);
|
||||
float mix = fmod(transform.getZoom(), 1.0);
|
||||
|
||||
vec2<double> offset {
|
||||
fmod(id.x * 4096, imageSize.x),
|
||||
fmod(id.y * 4096, imageSize.y)
|
||||
};
|
||||
std::array<float, 2> imageSize = {{
|
||||
imagePos.size.x * factor,
|
||||
imagePos.size.y * factor
|
||||
}};
|
||||
|
||||
std::array<float, 2> offset = {{
|
||||
(float)fmod(id.x * 4096, imageSize[0]),
|
||||
(float)fmod(id.y * 4096, imageSize[1])
|
||||
}};
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->setMatrix(matrix);
|
||||
glUniform2f(patternShader->u_pattern_size, imageSize.x, imageSize.y);
|
||||
glUniform2f(patternShader->u_offset, offset.x, offset.y);
|
||||
glUniform2f(patternShader->u_pattern_tl, imagePos.tl.x, imagePos.tl.y);
|
||||
glUniform2f(patternShader->u_pattern_br, imagePos.br.x, imagePos.br.y);
|
||||
glUniform4fv(patternShader->u_color, 1, fill_color.data());
|
||||
glUniform1f(patternShader->u_mix, mix);
|
||||
patternShader->setOffset(offset);
|
||||
patternShader->setPatternSize(imageSize);
|
||||
patternShader->setPatternTopLeft({{ imagePos.tl.x, imagePos.tl.y }});
|
||||
patternShader->setPatternBottomRight({{ imagePos.br.x, imagePos.br.y }});
|
||||
patternShader->setColor(fill_color);
|
||||
patternShader->setMix(mix);
|
||||
style.sprite->bind(true);
|
||||
|
||||
// Draw a rectangle that covers the entire viewport.
|
||||
@@ -303,13 +307,13 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
if (bucket.empty()) return;
|
||||
if (properties.hidden) return;
|
||||
|
||||
double width = properties.width;
|
||||
double offset = properties.offset / 2;
|
||||
float width = properties.width;
|
||||
float offset = properties.offset / 2;
|
||||
|
||||
// These are the radii of the line. We are limiting it to 16, which will result
|
||||
// in a point size of 64 on retina.
|
||||
double inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f);
|
||||
double outset = fmin(offset + width / 2 + 0.5, 16.0f);
|
||||
float inset = fmin((fmax(-1, offset - width / 2 - 0.5) + 1), 16.0f);
|
||||
float outset = fmin(offset + width / 2 + 0.5, 16.0f);
|
||||
|
||||
Color color = properties.color;
|
||||
color[0] *= properties.opacity;
|
||||
@@ -321,14 +325,21 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
if (bucket.hasPoints() && outset > 1.0f) {
|
||||
useProgram(linejoinShader->program);
|
||||
linejoinShader->setMatrix(matrix);
|
||||
glUniform4fv(linejoinShader->u_color, 1, color.data());
|
||||
glUniform2f(linejoinShader->u_world, transform.fb_width / 2, transform.fb_height / 2);
|
||||
glUniform2f(linejoinShader->u_linewidth, (outset - 0.25) * transform.pixelRatio, (inset - 0.25) * transform.pixelRatio);
|
||||
linejoinShader->setColor(color);
|
||||
linejoinShader->setWorld({{
|
||||
transform.fb_width * 0.5f,
|
||||
transform.fb_height * 0.5f
|
||||
}});
|
||||
linejoinShader->setLineWidth({{
|
||||
((outset - 0.25f) * transform.pixelRatio),
|
||||
((inset - 0.25f) * transform.pixelRatio)
|
||||
}});
|
||||
|
||||
float pointSize = ceil(transform.pixelRatio * outset * 2.0);
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
glUniform1f(linejoinShader->u_size, ceil(transform.pixelRatio * outset * 2.0));
|
||||
linejoinShader->setSize(pointSize);
|
||||
#else
|
||||
glPointSize(ceil(transform.pixelRatio * outset * 2.0));
|
||||
glPointSize(pointSize);
|
||||
#endif
|
||||
|
||||
bucket.drawPoints(*linejoinShader);
|
||||
@@ -352,16 +363,16 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
} else {
|
||||
useProgram(lineShader->program);
|
||||
lineShader->setMatrix(matrix);
|
||||
glUniformMatrix4fv(lineShader->u_exmatrix, 1, GL_FALSE, exMatrix.data());
|
||||
lineShader->setExtrudeMatrix(exMatrix);
|
||||
|
||||
// TODO: Move this to transform?
|
||||
const double tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8;
|
||||
const float tilePixelRatio = transform.getScale() / (1 << transform.getIntegerZoom()) / 8;
|
||||
|
||||
glUniform2f(lineShader->u_dasharray, 1, -1);
|
||||
glUniform2f(lineShader->u_linewidth, outset, inset);
|
||||
glUniform1f(lineShader->u_ratio, tilePixelRatio);
|
||||
glUniform4fv(lineShader->u_color, 1, color.data());
|
||||
glUniform1f(lineShader->u_debug, 0);
|
||||
lineShader->setDashArray({{ 1, -1 }});
|
||||
lineShader->setLineWidth({{ outset, inset }});
|
||||
lineShader->setRatio(tilePixelRatio);
|
||||
lineShader->setColor(color);
|
||||
lineShader->setDebug(0);
|
||||
bucket.drawLines(*lineShader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,4 +47,46 @@ void LineShader::bind(char *offset) {
|
||||
|
||||
glEnableVertexAttribArray(a_extrude);
|
||||
glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4);
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setExtrudeMatrix(const std::array<float, 16>& new_exmatrix) {
|
||||
if (exmatrix != new_exmatrix) {
|
||||
glUniformMatrix4fv(u_exmatrix, 1, GL_FALSE, new_exmatrix.data());
|
||||
exmatrix = new_exmatrix;
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setColor(const std::array<float, 4>& new_color) {
|
||||
if (color != new_color) {
|
||||
glUniform4fv(u_color, 1, new_color.data());
|
||||
color = new_color;
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setLineWidth(const std::array<float, 2>& new_linewidth) {
|
||||
if (linewidth != new_linewidth) {
|
||||
glUniform2fv(u_linewidth, 1, new_linewidth.data());
|
||||
linewidth = new_linewidth;
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setRatio(float new_ratio) {
|
||||
if (ratio != new_ratio) {
|
||||
glUniform1f(u_ratio, new_ratio);
|
||||
ratio = new_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setDashArray(const std::array<float, 2>& new_dasharray) {
|
||||
if (dasharray != new_dasharray) {
|
||||
glUniform2fv(u_dasharray, 1, new_dasharray.data());
|
||||
dasharray = new_dasharray;
|
||||
}
|
||||
}
|
||||
|
||||
void LineShader::setDebug(float new_debug) {
|
||||
if (debug != new_debug) {
|
||||
glUniform1f(u_debug, new_debug);
|
||||
debug = new_debug;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,3 +37,31 @@ void LinejoinShader::bind(char *offset) {
|
||||
// Note: We're referring to the vertices in a line array, which are 8 bytes long!
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset);
|
||||
}
|
||||
|
||||
void LinejoinShader::setColor(const std::array<float, 4>& new_color) {
|
||||
if (color != new_color) {
|
||||
glUniform4fv(u_color, 1, new_color.data());
|
||||
color = new_color;
|
||||
}
|
||||
}
|
||||
|
||||
void LinejoinShader::setWorld(const std::array<float, 2>& new_world) {
|
||||
if (world != new_world) {
|
||||
glUniform2fv(u_world, 1, new_world.data());
|
||||
world = new_world;
|
||||
}
|
||||
}
|
||||
|
||||
void LinejoinShader::setLineWidth(const std::array<float, 2>& new_linewidth) {
|
||||
if (linewidth != new_linewidth) {
|
||||
glUniform2fv(u_linewidth, 1, new_linewidth.data());
|
||||
linewidth = new_linewidth;
|
||||
}
|
||||
}
|
||||
|
||||
void LinejoinShader::setSize(float new_size) {
|
||||
if (size != new_size) {
|
||||
glUniform1f(u_size, new_size);
|
||||
size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,3 +40,46 @@ void PatternShader::bind(char *offset) {
|
||||
glEnableVertexAttribArray(a_pos);
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
|
||||
}
|
||||
|
||||
void PatternShader::setColor(const std::array<float, 4>& new_color) {
|
||||
if (color != new_color) {
|
||||
glUniform4fv(u_color, 1, new_color.data());
|
||||
color = new_color;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternShader::setOffset(const std::array<float, 2>& new_offset) {
|
||||
if (offset != new_offset) {
|
||||
glUniform2fv(u_offset, 1, new_offset.data());
|
||||
offset = new_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternShader::setPatternSize(const std::array<float, 2>& new_pattern_size) {
|
||||
if (pattern_size != new_pattern_size) {
|
||||
glUniform2fv(u_pattern_size, 1, new_pattern_size.data());
|
||||
pattern_size = new_pattern_size;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternShader::setPatternTopLeft(const std::array<float, 2>& new_pattern_tl) {
|
||||
if (pattern_tl != new_pattern_tl) {
|
||||
glUniform2fv(u_pattern_tl, 1, new_pattern_tl.data());
|
||||
pattern_tl = new_pattern_tl;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternShader::setPatternBottomRight(const std::array<float, 2>& new_pattern_br) {
|
||||
if (pattern_br != new_pattern_br) {
|
||||
glUniform2fv(u_pattern_br, 1, new_pattern_br.data());
|
||||
pattern_br = new_pattern_br;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternShader::setMix(float new_mix) {
|
||||
if (mix != new_mix) {
|
||||
glUniform1f(u_mix, new_mix);
|
||||
mix = new_mix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
|
||||
}
|
||||
|
||||
|
||||
void Shader::setMatrix(const mat4& newMatrix) {
|
||||
void Shader::setMatrix(const std::array<float, 16>& newMatrix) {
|
||||
if (matrix != newMatrix) {
|
||||
glUniformMatrix4fv(u_matrix, 1, GL_FALSE, newMatrix.data());
|
||||
matrix = newMatrix;
|
||||
|
||||
@@ -8,8 +8,7 @@ void main() {
|
||||
// If the x coordinate is the maximum integer, we move the z coordinates out
|
||||
// of the view plane so that the triangle gets clipped. This makes it easier
|
||||
// for us to create degenerate triangle strips.
|
||||
float z = step(32767.0, a_pos.x) * 2.0;
|
||||
gl_Position = u_matrix * vec4(a_pos, z, 1);
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
|
||||
v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,5 @@ attribute vec2 a_pos;
|
||||
uniform mat4 u_matrix;
|
||||
|
||||
void main() {
|
||||
float z = step(32767.0, a_pos.x) * 2.0;
|
||||
gl_Position = u_matrix * vec4(a_pos, z, 1);
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
"uniform vec4 u_color;\nuniform vec2 u_linewidth;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n\n // Calculate the antialiasing fade factor. This is either when fading in\n // the line in case of an offset line (v_linewidth.t) or when fading out\n // (v_linewidth.s)\n float alpha = clamp(min(dist - (u_linewidth.t - 1.0), u_linewidth.s - dist), 0.0, 1.0);\n gl_FragColor = u_color * alpha;\n}\n",
|
||||
},
|
||||
{
|
||||
"attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n",
|
||||
"attribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\n\nvarying vec2 v_pos;\n\nvoid main() {\n // If the x coordinate is the maximum integer, we move the z coordinates out\n // of the view plane so that the triangle gets clipped. This makes it easier\n // for us to create degenerate triangle strips.\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n\n v_pos = (gl_Position.xy + 1.0) / 2.0 * u_world;\n}\n",
|
||||
"uniform vec4 u_color;\n\nvarying vec2 v_pos;\n\nvoid main() {\n float dist = length(v_pos - gl_FragCoord.xy);\n float alpha = smoothstep(1.0, 0.0, dist);\n gl_FragColor = u_color * alpha;\n}\n",
|
||||
},
|
||||
{
|
||||
@@ -21,7 +21,7 @@ const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
"uniform vec4 u_color;\n\nuniform vec2 u_offset;\nuniform vec2 u_pattern_size;\nuniform vec2 u_pattern_tl;\nuniform vec2 u_pattern_br;\nuniform float u_mix;\n\n\nuniform sampler2D u_image;\n\nvarying vec2 v_pos;\n\nvoid main() {\n\n vec2 imagecoord = mod((v_pos + u_offset) / u_pattern_size, 1.0);\n vec2 pos = mix(u_pattern_tl, u_pattern_br, imagecoord);\n vec4 color1 = texture2D(u_image, pos);\n\n vec2 imagecoord2 = mod(imagecoord * 2.0, 1.0);\n vec2 pos2 = mix(u_pattern_tl, u_pattern_br, imagecoord2);\n vec4 color2 = texture2D(u_image, pos2);\n\n vec4 color = mix(color1, color2, u_mix);\n gl_FragColor = color + u_color * (1.0 - color.a);\n}\n",
|
||||
},
|
||||
{
|
||||
"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n float z = step(32767.0, a_pos.x) * 2.0;\n gl_Position = u_matrix * vec4(a_pos, z, 1);\n}\n",
|
||||
"attribute vec2 a_pos;\n\nuniform mat4 u_matrix;\n\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0, 1);\n}\n",
|
||||
"uniform vec4 u_color;\n\nvoid main() {\n gl_FragColor = u_color;\n}\n",
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user