学习ShaderToy第一天: glsl语言内置函数gl_FragCoord

运行环境:Android
opengl es版本: 2.0
3D引擎库 : Rajawali3D

ShaderToy上用的shader语言 为glsl , 效果是用webgl跑的,而webgl封装了opengl es, 所以ShaderToy上的例子同样使用于Android端。

ShaderToy基本上 都是用fragment shader 对栅格化后的像素进行处理。 大部分会用到纹理来丰富最终渲染结果的形状和质地,有些也会用到声音,键盘等外部输入信息。 但是,最终都是归结为对栅格化区域内的每个像素进行处理,因此,我们首先来认识gl_FragCoord这个内置变量以及其与屏幕坐标的关系。

gl_FragCoord根据glsl language spec的解释为:
它是fragment shaders的输入变量,并持有该framgent的屏幕相对坐标(x, y, z, 1/w)

什么是屏幕相对坐标,它的坐标范围是多少,这些都没有告诉我们。需要我们实验

假设我们采用2d ortho projection的方式来渲染,输入的顶点信息为屏幕的4个顶点坐标,这样我们最终渲染出来的是一个 铺满屏幕的图。
由于是2D渲染,最终每个fragment的 gl_FragCoord的z接近0.0, 而w 为1.0, 而它的x, y分量,是相对于屏幕左下角为原点的屏幕坐标。什么意思?
假如,我们设定的viewport的渲染区域为(0, 0, 1280, 574) 这么大,那么,gl_Fragment的x分量 范围就在0~1280之间, y分量就在0~574之间。

我们可以用一下测试用例来进行测试:
vertex shader:

precision mediump float ;

uniform mat4 uMVPMatrix;
attribute vec4 aPosition;

void main(){
position = vec3 (uMVPMatrixaPosition);
gl_Position = uMVPMatrix
aPosition;
}

fragment shader:

precision mediump float ;

uniform vec2 screenSize; // step 1 gl_FragCoord的坐标像素范围

void main()
{
vec2 uv = vec2(gl_FragCoord.xy/screenSize.xy); // step 2 将每个fragment的 每个gl_FragCoord归一化,这是一个惯例,利于后面计算,screenSize 表示屏幕的宽度和宽高

//Calculate polar coordinates
 float r = length(uv);
 float c = 0.0;

if(uv.x>0.98 &&uv.x<1.0 )                       // step 3
{
   c = 1.0;
}

 if(uv.y>0.98 &&uv.y<1.0 )                     // step 4
 {
   c = 1.0;
 }

 //Calculate the final color mixing lines and backgrounds.
 vec3 bg = mix(vec3(0.93 , 0.71 ,  0.62 ),  vec3(0.9 , 0.44 , 0.44),   r);  // step 5
 bg = mix(bg, vec3 (0.9 , 0.91 , 0.62 ), c);                                //  step 6

 gl_FragColor = vec4(bg, 1.0);

}

运行后,效果图如下:

这里主要说下 fragment shader:
step 1: 之前说到, gl_FragCoord的坐标范围, 这里screenSize 表示屏幕的宽高。
step 2 : 将每个fragment的 每个gl_FragCoord归一化,这是一个惯例,利于后面计算
step3: 和 step4: 这两个分别表示,当fragment的坐标(x, y) 的x和y分量分别落在这个范围时(即中间)c 的值会发生变化
step5: step5 和 step6都用到了glsl 的 mix内置函数, 考虑到 bg = mix(color1, color2, r)它的意思,就是将color1和color2 两种颜色,按照bg = color1*(1-r)+r*color2的方式混合,其中bg, color1, color2都是表示颜色,有三个分量。 那么,当r=0.0时,表示的是color1颜色,当r = 1.0表示的是color2颜色。 我们利用mix可以在一种背景上标记出另一种颜色。

step3 和 step4 表示,当x, y 分别落在值范围的中间时,c的值从0.0变为1.0, 即在这个范围内,背景色变为我们设置的颜色。

当我们把step3 和 step4 改为:
if (uv.x> 0.09 &&uv.x< 0.11 ) // step 3
{
c = 1.0;
}

  if  (uv.y> 0.09  &&uv.y< 0.11  )                     // step 4
 {
   c = 1.0;
 }

效果图如下:

在这里插入图片描述

通过,以上的例子我们得出gl_FragCoord的正确表示方式。

上面是标准的GLSL语法,如果要改成shadertoy能运行的shader,需要修改:

//void mainImage( out vec4 fragColor, in vec2 fragCoord )
//{
//    // Normalized pixel coordinates (from 0 to 1)
//    vec2 uv = fragCoord/iResolution.xy;
//
//    // Time varying pixel color
//    vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
//
//    // Output to screen
//    fragColor = vec4(col,1.0);
//}



//uniform vec2 screenSize;  // step  1precision mediump float ;
//uniform vec4 gl_FragColor;
//vec4 FragColor;

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    

     vec2 uv = fragCoord/iResolution.xy; // step 2

    //Calculate polar coordinates
     float r = length(uv);
     float c = 0.0;

    if(uv.x>0.98 &&uv.x<1.0 )                       // step 3
    {
       c = 1.0;
    }

     if(uv.y>0.98 &&uv.y<1.0 )                     // step 4
     {
       c = 1.0;
     }

     //Calculate the final color mixing lines and backgrounds.
     vec3 bg = mix(vec3(0.93 , 0.71 ,  0.62 ),  vec3(0.9 , 0.44 , 0.44),   r);  // step 5
     bg = mix(bg, vec3 (0.9 , 0.91 , 0.62 ), c);                                //  step 6

     //fragCoord = vec4(bg, 1.0);
      fragColor = vec4(bg, 1.0);
}


在这里插入图片描述
最后附上一张shadertoy官网的图片,凑够三张图,哈哈
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值