我想用棋子给四边形着色:
f(P)=[下限(Px)+下限(Py)]mod2。
我的四边形是:
glBegin(GL_QUADS);
glVertex3f(0,0,0.0);
glVertex3f(4,0,0.0);
glVertex3f(4,4,0.0);
glVertex3f(0,4, 0.0);
glEnd();
顶点着色器文件:
varying float factor;
float x,y;
void main(){
x=floor(gl_Position.x);
y=floor(gl_Position.y);
factor = mod((x+y),2.0);
}
片段着色器文件是:
varying float factor;
void main(){
gl_FragColor = vec4(factor,factor,factor,1.0);
}
但我明白了:
似乎 mod 功能不起作用或者可能是其他原因...... 有什么帮助吗?
最好在片段着色器中计算这种效果,类似这样:
顶点程序=>
varying vec2 texCoord;
void main(void)
{
gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0);
gl_Position = sign(gl_Position);
texCoord = (vec2(gl_Position.x, gl_Position.y)
+ vec2(1.0)) / vec2(2.0);
}
片段程序=>
#extension GL_EXT_gpu_shader4 : enable
uniform sampler2D Texture0;
varying vec2 texCoord;
void main(void)
{
ivec2 size = textureSize2D(Texture0, 0);
float total = floor(texCoord.x * float(size.x)) +
floor(texCoord.y * float(size.y));
bool isEven = mod(total, 2.0) == 0.0;
vec4 col1 = vec4(0.0, 0.0, 0.0, 1.0);
vec4 col2 = vec4(1.0, 1.0, 1.0, 1.0);
gl_FragColor = (isEven) ? col1 : col2;
}
输出=>
祝你好运!
在片段着色器中尝试此功能:
vec3 checker(in float u, in float v)
{
float checkSize = 2;
float fmodResult = mod(floor(checkSize * u) + floor(checkSize * v), 2.0);
float fin = max(sign(fmodResult), 0.0);
return vec3(fin, fin, fin);
}
然后在 main 中你可以使用以下方式调用它:
vec3 check = checker(fs_vertex_texture.x, fs_vertex_texture.y);
只需传递从顶点着色器获得的 x 和 y 即可。之后您所要做的就是在计算 vFragColor 时将其包含在内。
请记住,您只需修改 checkSize 值即可更改检查大小。
您的代码所做的是计算因子 4 次(每个顶点一次,因为它是顶点着色器代码),然后插入这些值(因为它被写入变化的变量中),然后在片段着色器中将该变量输出为颜色。
所以它不是这样工作的。您需要直接在片段着色器中进行该计算。您可以使用片段着色器中的 gl_FragCoord 内置变量来获取片段位置。
我可以提出以下建议:
float result = mod(dot(vec2(1.0), step(vec2(0.5), fract(v_uv * u_repeat))), 2.0);
gl_FragColor = mix(vec4(1.0, 1.0, 1.0, 1.0), vec4(0.0, 0.0, 0.0, 1.0) result);
另一种不错的方法是平铺已知图案(缩小)。假设你有一个正方形画布:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
uv -= 0.5; // moving the coordinate system to middle of screen
// Output to screen
fragColor = vec4(vec3(step(uv.x * uv.y, 0.)), 1.);
}
上面的代码给了你这种模式。
下面的代码只需缩放 4.5 倍并取小数部分即可重复该模式 4.5 次,从而每行有 9 个正方形。
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fract(fragCoord/iResolution.xy * 4.5);
uv -= 0.5; // moving the coordinate system to middle of screen
// Output to screen
fragColor = vec4(vec3(step(uv.x * uv.y, 0.)), 1.);
}
当前的答案都提供了很好的解决方案,但也都依赖于浮点运算,例如
mod
,fract
和floor
。这种方法将浮点数转换为整数,使用最少的操作,因此有可能更快。至少,它展示了一种替代实现。
片段着色器:
const vec3 white = vec3(1.0F);
const vec3 black = vec3(0.0F);
in vec2 uv; // In range [0, 1]^2
uniform float scale = 8.0F; // The number of squares in one dimension
out vec4 fragColor;
void main()
{
ivec2 uvInt = ivec2(scale * uv); // Scale and truncate the fractional part
bool isOdd = bool((uvInt.x + uvInt.y) & 1); // Odd or even check using a bit-wise operation
fragColor = vec4(isOdd ? white : black, 1.0F);
}
在将四边形的 uv 坐标发送到 GPU 之前将其与
scale
相乘并忽略片段着色器中的缩放,可以提高效率。
最初的问题是在 2011 年提出的,并使用
varying
,这意味着旧的 GLSL 版本的目标是什么。按位运算可能无法在所有/大多数硬件上使用,因为这些运算是在 GLSL 130(2009 年 11 月)中引入的。在这种情况下,奇偶检查可以用(uvInt.x + uvInt.y) % 2 == 1
代替。如果余数运算符也不可用(例如,在较旧的 WebGL 版本上有时会出现这种情况),则可以使用以下技巧 - 使用整数除法:
int sum = uvInt.x + uvInt.y;
vec3 color = sum / 2 * 2 == sum ? white : black;
输出:
如果四边形是矩形,那么棋盘将包含黑白矩形而不是正方形:
要对此进行调整,需要考虑宽高比。 ShaderToy的示例代码,方便实验,与 WebGL 1 兼容:
const vec3 white = vec3(1.0);
const vec3 black = vec3(0.0);
const float scale = 8.0; // The number of *vertical* squares
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord / iResolution.xy;
float aspectRatio = iResolution.x / iResolution.y;
uv.x *= aspectRatio; // Adjust the horizontal scaling for the aspect ratio
ivec2 uvInt = ivec2(scale * uv);
int sum = uvInt.x + uvInt.y;
vec3 color = sum / 2 * 2 == sum ? white : black; // Odd or even check
fragColor = vec4(color, 1.0);
}
请注意,在独立应用程序中,缩放比例和纵横比调整的计算可以吸收到 uv 坐标本身中,从而从着色器代码中消除,以获得更好的性能。 结果: