shadertoy学习记录(1)

最近准备继续学习一下图形学,从打基础开始,看了GAMES101但是一直都是停留在理论学习的部分,因此这次从大佬推荐的shadertoy入手学习一下图形学,由于没有学过opengl等其他知识,因此只是对自己学习的监督,如果有错误的地方希望大家批评指正。(以下都是按照自己的理解进行表达)

一、认识UV

在我看来UV就是一张图片的XY坐标,只不过这里是作为二维图像,因此换了个名称进行表达,这里就叫做UV。u代表横坐标,v代表纵坐标。而一张图像不管分辨率是多少的,我们都可以看成是u和v分别是从0到1的过程。

而一张图片是如何进行绘制的?

在图片的区域内,每个像素值都有一个颜色,有三通道的RGB来代表。RGB分别代表红绿蓝,RGB的取值也是0到1,因此定义一个像素点的颜色就可以用一个三维向量来表示,比如vec3(0.5,0.5,0.5)

知道这些后,我们应该怎么样在图片中正确绘制出图片呢?,先从绘制一个圆开始。

float circle(vec2 uv,float radius){
    float d =length(uv);
    if(d < radius)
        return 1.;
    else
        return 0.;

}




void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    uv -=0.5;
    uv.x *=iResolution.x/iResolution.y;

    
    // Time varying pixel color
    
    float c = circle(uv,.5);

    // Output to screen
    fragColor = vec4(vec3(c),1.0);
}

 首先是在mainImage,这个函数专门用来绘制图形。可以看到它传入了两个参数,一个是fragcolor,这个就是屏幕颜色,另一个是fragcoord,是屏幕的坐标。

首先得到了一个从0到1的uv。这个时候屏幕左下角为(0,0),右上角为(1,1)。而我们想让这个图的原点在正中间,因此用uv -= 0.5的方式,把所有的uv坐标都减去0.5,这样此时图像的左下角坐标为(-0.5,-0.5),而右上角的坐标为(0.5,0.5)。此时的坐标原点为(0,0)。这时还要解决的就是屏幕长短比例的问题,如果没有解决,那么得到的图像就是会随着分辨率的变化而进行拉伸,比如此时分辨率为800*450,明显是横向更长,因此图像就会在水平方向进行拉伸。

因此这行代码就是为了解决拉伸的问题。

那么该进行怎么画圆的部分了吧

因为图像本身是全为0的黑色图像,我们只需要让半径之内的值全部返回为1即可实现圆的效果。最终可以得到一个圆。

这是问题就来了,这样得到的颜色只是黑白图片不够美观,如果想得到其他颜色的图像怎么办?

二、像素的加减乘法

 

在上面第一步肘,用fragcolor对图像进行绘制,只需要关注第一个参数即可,这个参数表示了对三个通道颜色的控制,但是怎么才能即让图形绘制出来,还能让这个图形换个颜色呢?这里用到了乘法。

这里使用乘法可以让原本黑色的地方还是黑色,而不是黑色的地方换成其他的颜色,原理就是0乘任何一个数还是0,但是1乘任何一个数得到的就是那个数本身,因此,如果我们这里想得到一个黄色的圆,只需要乘上一个黄色的数值即可,修改代码如下:

fragColor = vec4(vec3(c)*vec3(1.,1.,0),1.0);

 得到的效果如下:

shadertoy学习记录(1)_第1张图片

 原本白色的地方变成了黄色!!!!!!

这里可以总结:如果想要将原本的颜色进行改变,可以使用乘法。

那么加法和减法的作用是什么呢?

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;
    uv -=0.5;
    uv.x *=iResolution.x/iResolution.y;

    
    // Time varying pixel color
    
    float bigcircle = circle(uv,.5);
    float smallcircle = circle(uv,.1);
    
    float mask = bigcircle - smallcircle;
    

    // Output to screen
    fragColor = vec4(vec3(mask)*vec3(1.,1.,0),1.0);
}

经过以上修改后,我们可以得到的效果是这样的:

shadertoy学习记录(1)_第2张图片

可以看到中间一块变成了黑色,那么为什么会空出来呢?因此我们定义的bigcirle会得到以原点为圆心半径为0.5的圆,这个圆内所有的值都为1,但是我们定义了一个一原点为圆心半径为0.1的小圆,这个小圆内部所有的值也为1,因此,这个时候用的大圆减去小圆得到的结果就是将小圆的部分变成了0!。那么加法的原理也是类似的。只是会让图像中多一个区域出来。

float mask = bigcircle - smallcircle;
    mask += thirdcircle;

shadertoy学习记录(1)_第3张图片

 因此我们可以得到结论:

用代码绘制出 图像来,究其原理其实就是数学的运行,加法和减法是对图像进行叠加,而乘法则是对对图像的颜色进行改变。

你可能感兴趣的:(图形渲染)