mirror of https://github.com/PCSX2/pcsx2.git
gsdx-ogl: make VS more generic
Texture coordinate could be dummy/float/int integral/int normalized. Old behavior: * VS was in charge to select the texture coordinate * int integral format wasn't supported New behavior: * Always compute all formats * FS will be in charge to select the good format Impact: * VS will be slightly slower but it reduces shaders permutation from little to 0 (won't be bad for CPU) * FS speed isn't impacted as 2 separate code paths were already required to support both format * Rasterizer will be 33% slower but unlikely to be the limited factor of the GPU * In future we could directly use the integral format in the FS. V2: remove useless PSin_t
This commit is contained in:
parent
44e6445180
commit
f8c442cf76
|
@ -691,8 +691,6 @@ GLuint GSDeviceOGL::CompileVS(VSSelector sel, int logz)
|
|||
{
|
||||
std::string macro = format("#define VS_BPPZ %d\n", sel.bppz)
|
||||
+ format("#define VS_LOGZ %d\n", logz)
|
||||
+ format("#define VS_TME %d\n", sel.tme)
|
||||
+ format("#define VS_FST %d\n", sel.fst)
|
||||
+ format("#define VS_WILDHACK %d\n", sel.wildhack)
|
||||
;
|
||||
|
||||
|
|
|
@ -153,10 +153,8 @@ class GSDeviceOGL : public GSDevice
|
|||
{
|
||||
uint32 wildhack:1;
|
||||
uint32 bppz:2;
|
||||
uint32 tme:1;
|
||||
uint32 fst:1;
|
||||
|
||||
uint32 _free:27;
|
||||
uint32 _free:29;
|
||||
};
|
||||
|
||||
uint32 key;
|
||||
|
@ -438,7 +436,7 @@ class GSDeviceOGL : public GSDevice
|
|||
GSUniformBufferOGL *cb;
|
||||
} m_shadeboost;
|
||||
|
||||
GLuint m_vs[1<<5];
|
||||
GLuint m_vs[1<<3];
|
||||
GLuint m_gs[1<<2];
|
||||
GLuint m_ps_ss[1<<4];
|
||||
GSDepthStencilOGL* m_om_dss[1<<4];
|
||||
|
|
|
@ -778,8 +778,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
|
||||
// vs
|
||||
|
||||
vs_sel.tme = PRIM->TME;
|
||||
vs_sel.fst = PRIM->FST;
|
||||
vs_sel.wildhack = (UserHacks_WildHack && !isPackedUV_HackFlag) ? 1 : 0;
|
||||
|
||||
// The real GS appears to do no masking based on the Z buffer format and writing larger Z values
|
||||
|
|
|
@ -53,12 +53,8 @@ void GSDeviceOGL::CreateTextureFX()
|
|||
GL_PUSH("Compile VS");
|
||||
|
||||
for (uint32 key = 0; key < countof(m_vs); key++) {
|
||||
// wildhack is only useful if both TME and FST are enabled.
|
||||
VSSelector sel(key);
|
||||
if (sel.wildhack && (!sel.tme || !sel.fst))
|
||||
m_vs[key] = 0;
|
||||
else
|
||||
m_vs[key] = CompileVS(sel, !GLLoader::found_GL_ARB_clip_control);
|
||||
m_vs[key] = CompileVS(sel, !GLLoader::found_GL_ARB_clip_control);
|
||||
}
|
||||
|
||||
GL_POP();
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
|
||||
in SHADER
|
||||
{
|
||||
vec4 t;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
flat vec4 fc;
|
||||
} PSin;
|
||||
|
||||
#define PSin_t (PSin.t)
|
||||
#define PSin_c (PSin.c)
|
||||
#define PSin_fc (PSin.fc)
|
||||
|
||||
|
@ -206,13 +206,8 @@ mat4 sample_4p(vec4 u)
|
|||
return c;
|
||||
}
|
||||
|
||||
vec4 sample_color(vec2 st, float q)
|
||||
vec4 sample_color(vec2 st)
|
||||
{
|
||||
//FIXME: maybe we can set gl_Position.w = q in VS
|
||||
#if (PS_FST == 0)
|
||||
st /= q;
|
||||
#endif
|
||||
|
||||
#if (PS_TCOFFSETHACK == 1)
|
||||
st += TC_OffsetHack.xy;
|
||||
#endif
|
||||
|
@ -362,7 +357,13 @@ void fog(inout vec4 C, float f)
|
|||
|
||||
vec4 ps_color()
|
||||
{
|
||||
vec4 T = sample_color(PSin_t.xy, PSin_t.w);
|
||||
//FIXME: maybe we can set gl_Position.w = q in VS
|
||||
#if (PS_FST == 0)
|
||||
vec4 T = sample_color(PSin.t_float.xy / PSin.t_float.w);
|
||||
#else
|
||||
// Note xy are normalized coordinate
|
||||
vec4 T = sample_color(PSin.t_int.xy);
|
||||
#endif
|
||||
|
||||
#if PS_IIP == 1
|
||||
vec4 C = tfx(T, PSin_c);
|
||||
|
@ -372,7 +373,7 @@ vec4 ps_color()
|
|||
|
||||
atst(C);
|
||||
|
||||
fog(C, PSin_t.z);
|
||||
fog(C, PSin.t_float.z);
|
||||
|
||||
#if (PS_CLR1 != 0) // needed for Cd * (As/Ad/F + 1) blending modes
|
||||
C.rgb = vec3(255.0f);
|
||||
|
|
|
@ -45,12 +45,12 @@ layout(location = 7) in vec4 i_f;
|
|||
|
||||
out SHADER
|
||||
{
|
||||
vec4 t;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
flat vec4 fc;
|
||||
} VSout;
|
||||
|
||||
#define VSout_t (VSout.t)
|
||||
#define VSout_c (VSout.c)
|
||||
#define VSout_fc (VSout.fc)
|
||||
|
||||
|
@ -70,27 +70,22 @@ const float exp_min31 = exp2(-31.0f);
|
|||
|
||||
void texture_coord()
|
||||
{
|
||||
if(VS_TME != 0)
|
||||
{
|
||||
if(VS_FST != 0)
|
||||
{
|
||||
if (VS_WILDHACK == 1) {
|
||||
VSout_t.xy = vec2(i_uv & uvec2(0x3FEF, 0x3FEF)) * TextureScale;
|
||||
} else {
|
||||
VSout_t.xy = vec2(i_uv) * TextureScale;
|
||||
}
|
||||
VSout_t.w = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
VSout_t.xy = i_st;
|
||||
VSout_t.w = i_q;
|
||||
}
|
||||
// Float coordinate
|
||||
VSout.t_float.xy = i_st;
|
||||
VSout.t_float.w = i_q;
|
||||
|
||||
// Integer coordinate
|
||||
// => normalized
|
||||
if (VS_WILDHACK == 1) {
|
||||
VSout.t_int.xy = vec2(i_uv & uvec2(0x3FEF, 0x3FEF)) * TextureScale;
|
||||
} else {
|
||||
VSout.t_int.xy = vec2(i_uv) * TextureScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
VSout_t.xy = vec2(0.0f, 0.0f);
|
||||
VSout_t.w = 1.0f;
|
||||
// => integral
|
||||
if (VS_WILDHACK == 1) {
|
||||
VSout.t_int.zw = vec2(i_uv & uvec2(0x3FEF, 0x3FEF));
|
||||
} else {
|
||||
VSout.t_int.zw = vec2(i_uv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,7 +128,7 @@ void vs_main()
|
|||
|
||||
VSout_c = i_c;
|
||||
VSout_fc = i_c;
|
||||
VSout_t.z = i_f.x;
|
||||
VSout.t_float.z = i_f.x; // pack for with texture
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -160,14 +155,16 @@ out gl_PerVertex {
|
|||
|
||||
in SHADER
|
||||
{
|
||||
vec4 t;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
flat vec4 fc;
|
||||
} GSin[];
|
||||
|
||||
out SHADER
|
||||
{
|
||||
vec4 t;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
flat vec4 fc;
|
||||
} GSout;
|
||||
|
@ -180,26 +177,24 @@ layout(std140, binding = 22) uniform cb22
|
|||
|
||||
struct vertex
|
||||
{
|
||||
vec4 t;
|
||||
vec4 t_float;
|
||||
vec4 t_int;
|
||||
vec4 c;
|
||||
};
|
||||
|
||||
void out_vertex(in vertex v)
|
||||
{
|
||||
GSout.t = v.t;
|
||||
GSout.c = v.c;
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void out_flat()
|
||||
{
|
||||
GSout.t_float = v.t_float;
|
||||
GSout.t_int = v.t_int;
|
||||
GSout.c = v.c;
|
||||
// Flat output
|
||||
#if GS_POINT == 1
|
||||
GSout.fc = GSin[0].fc;
|
||||
GSout.fc = GSin[0].fc;
|
||||
#else
|
||||
GSout.fc = GSin[1].fc;
|
||||
GSout.fc = GSin[1].fc;
|
||||
#endif
|
||||
gl_PrimitiveID = gl_PrimitiveIDIn;
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
#if GS_POINT == 1
|
||||
|
@ -214,11 +209,11 @@ void gs_main()
|
|||
// left top => GSin[0];
|
||||
// right bottom => GSin[1];
|
||||
#if GS_POINT == 1
|
||||
vertex rb = vertex(GSin[0].t, GSin[0].c);
|
||||
vertex rb = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
|
||||
#else
|
||||
vertex rb = vertex(GSin[1].t, GSin[1].c);
|
||||
vertex rb = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);
|
||||
#endif
|
||||
vertex lt = vertex(GSin[0].t, GSin[0].c);
|
||||
vertex lt = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
|
||||
|
||||
#if GS_POINT == 1
|
||||
vec4 rb_p = gl_in[0].gl_Position + vec4(PointSize.x, PointSize.y, 0.0f, 0.0f);
|
||||
|
@ -233,19 +228,21 @@ void gs_main()
|
|||
// flat depth
|
||||
lt_p.z = rb_p.z;
|
||||
// flat fog and texture perspective
|
||||
lt.t.zw = rb.t.zw;
|
||||
lt.t_float.zw = rb.t_float.zw;
|
||||
// flat color
|
||||
lt.c = rb.c;
|
||||
#endif
|
||||
|
||||
// Swap texture and position coordinate
|
||||
vertex lb = rb;
|
||||
lb.t.x = lt.t.x;
|
||||
lb.t_int.x = lt.t_int.x;
|
||||
lb.t_int.z = lt.t_int.z;
|
||||
lb_p.x = lt_p.x;
|
||||
|
||||
vertex rt = rb;
|
||||
rt_p.y = lt_p.y;
|
||||
rt.t.y = lt.t.y;
|
||||
rt.t_int.y = lt.t_int.y;
|
||||
rt.t_int.w = lt.t_int.w;
|
||||
|
||||
|
||||
// Triangle 1
|
||||
|
@ -256,7 +253,6 @@ void gs_main()
|
|||
out_vertex(lb);
|
||||
|
||||
gl_Position = rt_p;
|
||||
out_flat();
|
||||
out_vertex(rt);
|
||||
EndPrimitive();
|
||||
|
||||
|
@ -268,7 +264,6 @@ void gs_main()
|
|||
out_vertex(rt);
|
||||
|
||||
gl_Position = rb_p;
|
||||
out_flat();
|
||||
out_vertex(rb);
|
||||
EndPrimitive();
|
||||
}
|
||||
|
|
|
@ -670,12 +670,12 @@ static const char* tfx_vgs_glsl =
|
|||
"\n"
|
||||
"out SHADER\n"
|
||||
"{\n"
|
||||
" vec4 t;\n"
|
||||
" vec4 t_float;\n"
|
||||
" vec4 t_int;\n"
|
||||
" vec4 c;\n"
|
||||
" flat vec4 fc;\n"
|
||||
"} VSout;\n"
|
||||
"\n"
|
||||
"#define VSout_t (VSout.t)\n"
|
||||
"#define VSout_c (VSout.c)\n"
|
||||
"#define VSout_fc (VSout.fc)\n"
|
||||
"\n"
|
||||
|
@ -695,27 +695,22 @@ static const char* tfx_vgs_glsl =
|
|||
"\n"
|
||||
"void texture_coord()\n"
|
||||
"{\n"
|
||||
" if(VS_TME != 0)\n"
|
||||
" {\n"
|
||||
" if(VS_FST != 0)\n"
|
||||
" {\n"
|
||||
" if (VS_WILDHACK == 1) {\n"
|
||||
" VSout_t.xy = vec2(i_uv & uvec2(0x3FEF, 0x3FEF)) * TextureScale;\n"
|
||||
" } else {\n"
|
||||
" VSout_t.xy = vec2(i_uv) * TextureScale;\n"
|
||||
" }\n"
|
||||
" VSout_t.w = 1.0f;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" VSout_t.xy = i_st;\n"
|
||||
" VSout_t.w = i_q;\n"
|
||||
" }\n"
|
||||
" // Float coordinate\n"
|
||||
" VSout.t_float.xy = i_st;\n"
|
||||
" VSout.t_float.w = i_q;\n"
|
||||
"\n"
|
||||
" // Integer coordinate\n"
|
||||
" // => normalized\n"
|
||||
" if (VS_WILDHACK == 1) {\n"
|
||||
" VSout.t_int.xy = vec2(i_uv & uvec2(0x3FEF, 0x3FEF)) * TextureScale;\n"
|
||||
" } else {\n"
|
||||
" VSout.t_int.xy = vec2(i_uv) * TextureScale;\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" VSout_t.xy = vec2(0.0f, 0.0f);\n"
|
||||
" VSout_t.w = 1.0f;\n"
|
||||
" // => integral\n"
|
||||
" if (VS_WILDHACK == 1) {\n"
|
||||
" VSout.t_int.zw = vec2(i_uv & uvec2(0x3FEF, 0x3FEF));\n"
|
||||
" } else {\n"
|
||||
" VSout.t_int.zw = vec2(i_uv);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
@ -758,7 +753,7 @@ static const char* tfx_vgs_glsl =
|
|||
"\n"
|
||||
" VSout_c = i_c;\n"
|
||||
" VSout_fc = i_c;\n"
|
||||
" VSout_t.z = i_f.x;\n"
|
||||
" VSout.t_float.z = i_f.x; // pack for with texture\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"#endif\n"
|
||||
|
@ -785,14 +780,16 @@ static const char* tfx_vgs_glsl =
|
|||
"\n"
|
||||
"in SHADER\n"
|
||||
"{\n"
|
||||
" vec4 t;\n"
|
||||
" vec4 t_float;\n"
|
||||
" vec4 t_int;\n"
|
||||
" vec4 c;\n"
|
||||
" flat vec4 fc;\n"
|
||||
"} GSin[];\n"
|
||||
"\n"
|
||||
"out SHADER\n"
|
||||
"{\n"
|
||||
" vec4 t;\n"
|
||||
" vec4 t_float;\n"
|
||||
" vec4 t_int;\n"
|
||||
" vec4 c;\n"
|
||||
" flat vec4 fc;\n"
|
||||
"} GSout;\n"
|
||||
|
@ -805,26 +802,24 @@ static const char* tfx_vgs_glsl =
|
|||
"\n"
|
||||
"struct vertex\n"
|
||||
"{\n"
|
||||
" vec4 t;\n"
|
||||
" vec4 t_float;\n"
|
||||
" vec4 t_int;\n"
|
||||
" vec4 c;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"void out_vertex(in vertex v)\n"
|
||||
"{\n"
|
||||
" GSout.t = v.t;\n"
|
||||
" GSout.c = v.c;\n"
|
||||
" gl_PrimitiveID = gl_PrimitiveIDIn;\n"
|
||||
" EmitVertex();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void out_flat()\n"
|
||||
"{\n"
|
||||
" GSout.t_float = v.t_float;\n"
|
||||
" GSout.t_int = v.t_int;\n"
|
||||
" GSout.c = v.c;\n"
|
||||
" // Flat output\n"
|
||||
"#if GS_POINT == 1\n"
|
||||
" GSout.fc = GSin[0].fc;\n"
|
||||
" GSout.fc = GSin[0].fc;\n"
|
||||
"#else\n"
|
||||
" GSout.fc = GSin[1].fc;\n"
|
||||
" GSout.fc = GSin[1].fc;\n"
|
||||
"#endif\n"
|
||||
" gl_PrimitiveID = gl_PrimitiveIDIn;\n"
|
||||
" EmitVertex();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"#if GS_POINT == 1\n"
|
||||
|
@ -839,11 +834,11 @@ static const char* tfx_vgs_glsl =
|
|||
" // left top => GSin[0];\n"
|
||||
" // right bottom => GSin[1];\n"
|
||||
"#if GS_POINT == 1\n"
|
||||
" vertex rb = vertex(GSin[0].t, GSin[0].c);\n"
|
||||
" vertex rb = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);\n"
|
||||
"#else\n"
|
||||
" vertex rb = vertex(GSin[1].t, GSin[1].c);\n"
|
||||
" vertex rb = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);\n"
|
||||
"#endif\n"
|
||||
" vertex lt = vertex(GSin[0].t, GSin[0].c);\n"
|
||||
" vertex lt = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);\n"
|
||||
"\n"
|
||||
"#if GS_POINT == 1\n"
|
||||
" vec4 rb_p = gl_in[0].gl_Position + vec4(PointSize.x, PointSize.y, 0.0f, 0.0f);\n"
|
||||
|
@ -858,19 +853,21 @@ static const char* tfx_vgs_glsl =
|
|||
" // flat depth\n"
|
||||
" lt_p.z = rb_p.z;\n"
|
||||
" // flat fog and texture perspective\n"
|
||||
" lt.t.zw = rb.t.zw;\n"
|
||||
" lt.t_float.zw = rb.t_float.zw;\n"
|
||||
" // flat color\n"
|
||||
" lt.c = rb.c;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
" // Swap texture and position coordinate\n"
|
||||
" vertex lb = rb;\n"
|
||||
" lb.t.x = lt.t.x;\n"
|
||||
" lb.t_int.x = lt.t_int.x;\n"
|
||||
" lb.t_int.z = lt.t_int.z;\n"
|
||||
" lb_p.x = lt_p.x;\n"
|
||||
"\n"
|
||||
" vertex rt = rb;\n"
|
||||
" rt_p.y = lt_p.y;\n"
|
||||
" rt.t.y = lt.t.y;\n"
|
||||
" rt.t_int.y = lt.t_int.y;\n"
|
||||
" rt.t_int.w = lt.t_int.w;\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" // Triangle 1\n"
|
||||
|
@ -881,7 +878,6 @@ static const char* tfx_vgs_glsl =
|
|||
" out_vertex(lb);\n"
|
||||
"\n"
|
||||
" gl_Position = rt_p;\n"
|
||||
" out_flat();\n"
|
||||
" out_vertex(rt);\n"
|
||||
" EndPrimitive();\n"
|
||||
"\n"
|
||||
|
@ -893,7 +889,6 @@ static const char* tfx_vgs_glsl =
|
|||
" out_vertex(rt);\n"
|
||||
"\n"
|
||||
" gl_Position = rb_p;\n"
|
||||
" out_flat();\n"
|
||||
" out_vertex(rb);\n"
|
||||
" EndPrimitive();\n"
|
||||
"}\n"
|
||||
|
@ -932,12 +927,12 @@ static const char* tfx_fs_all_glsl =
|
|||
"\n"
|
||||
"in SHADER\n"
|
||||
"{\n"
|
||||
" vec4 t;\n"
|
||||
" vec4 t_float;\n"
|
||||
" vec4 t_int;\n"
|
||||
" vec4 c;\n"
|
||||
" flat vec4 fc;\n"
|
||||
"} PSin;\n"
|
||||
"\n"
|
||||
"#define PSin_t (PSin.t)\n"
|
||||
"#define PSin_c (PSin.c)\n"
|
||||
"#define PSin_fc (PSin.fc)\n"
|
||||
"\n"
|
||||
|
@ -960,8 +955,8 @@ static const char* tfx_fs_all_glsl =
|
|||
"// early_fragment_tests must still be enabled in the first pass of the 2 passes algo\n"
|
||||
"// First pass search the first primitive that will write the bad alpha value. Value\n"
|
||||
"// won't be written if the fragment fails the depth test.\n"
|
||||
"// \n"
|
||||
"// In theory the best solution will be do \n"
|
||||
"//\n"
|
||||
"// In theory the best solution will be do\n"
|
||||
"// 1/ copy the depth buffer\n"
|
||||
"// 2/ do the full depth (current depth writes are disabled)\n"
|
||||
"// 3/ restore the depth buffer for 2nd pass\n"
|
||||
|
@ -1110,13 +1105,8 @@ static const char* tfx_fs_all_glsl =
|
|||
" return c;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 sample_color(vec2 st, float q)\n"
|
||||
"vec4 sample_color(vec2 st)\n"
|
||||
"{\n"
|
||||
" //FIXME: maybe we can set gl_Position.w = q in VS\n"
|
||||
"#if (PS_FST == 0)\n"
|
||||
" st /= q;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if (PS_TCOFFSETHACK == 1)\n"
|
||||
" st += TC_OffsetHack.xy;\n"
|
||||
"#endif\n"
|
||||
|
@ -1266,7 +1256,13 @@ static const char* tfx_fs_all_glsl =
|
|||
"\n"
|
||||
"vec4 ps_color()\n"
|
||||
"{\n"
|
||||
" vec4 T = sample_color(PSin_t.xy, PSin_t.w);\n"
|
||||
" //FIXME: maybe we can set gl_Position.w = q in VS\n"
|
||||
"#if (PS_FST == 0)\n"
|
||||
" vec4 T = sample_color(PSin.t_float.xy / PSin.t_float.w);\n"
|
||||
"#else\n"
|
||||
" // Note xy are normalized coordinate\n"
|
||||
" vec4 T = sample_color(PSin.t_int.xy);\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"#if PS_IIP == 1\n"
|
||||
" vec4 C = tfx(T, PSin_c);\n"
|
||||
|
@ -1276,7 +1272,7 @@ static const char* tfx_fs_all_glsl =
|
|||
"\n"
|
||||
" atst(C);\n"
|
||||
"\n"
|
||||
" fog(C, PSin_t.z);\n"
|
||||
" fog(C, PSin.t_float.z);\n"
|
||||
"\n"
|
||||
"#if (PS_CLR1 != 0) // needed for Cd * (As/Ad/F + 1) blending modes\n"
|
||||
" C.rgb = vec3(255.0f);\n"
|
||||
|
|
Loading…
Reference in New Issue