Shader编程学习笔记(九)—— Cg语言入门1

摘要:
在之前的课程中,我们学习了渲染管道、顶点和剪辑程序、颜色计算等。在本总结中,我们将学习简单着色器顶点和剪辑的输入和输出,以及常见的语义。其中,Cg是一个嵌入式代码段。在ShaderLab语法中,需要使用关键字“CGPROGRAM”和“ENDCG”来包含用于编译的Cg代码段。请注意,这两个关键字是大写的。接下来,创建使用该着色器的材质,并在场景中创建立方体以使用该材质。

Cg入门一:输入输出和语义

  本小节对Cg语言进行一个入门了解。

  在以前的课程中,我们了解了渲染管线、顶点和片段程序和颜色计算等,在本小结中来了解一个简单的shader的顶点和片段程序的输入输出以及常用语义。

  编写一个简单的顶点和片段着色器,代码如下:

Shader编程学习笔记(九)—— Cg语言入门1第1张Shader编程学习笔记(九)—— Cg语言入门1第2张
Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
            }

            void frag(out float4 col:COLOR){
                col = float4(1,0,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

  Surface Shader没有pass通道,Vertex & Frament Shader至少有一个pass通道。其中,Cg是一个镶嵌的代码段,在ShaderLab语法中需要使用关键词“CGPROGRAM”和“ENDCG”将Cg代码段包含起来才能编译使用,需要注意的是这两个关键词都是大写的。

  顶点程序会对顶点做一系列的处理,如几何变换,在处理后把需要的数据传递给片段程序,片段程序拿到顶点程序当中处理后的数据继续进行最终的计算。“void vert(in float2 objPos:POSITION, out float4 pos:POSITION)” 中有两个参数,其中第一个参数中的“in”表示引擎提供的输入,“float2”表示数据的类型为二阶的向量,参数名“objPos”冒号后需要带上语义,语义指的是顶点程序和片段程序能够被识别的变量的实际意义,这里使用“POSITION”。第二个参数中“out”表示输出,数据类型为“float4”,语义也是“POSITION”。如果顶点程序要输出一个“POSITION”语义的变量,这个变量必须要以“float4”四阶向量的形式。另外,在片段程序中需要有语义为“COLOR”的变量作为输入,这里使用“out float4 col:COLOR”作为颜色变量的输出,语义“COLOR”就是指“COLOR0”。

  接下来创建一个使用该shader的Material,并在场景创建一个Cube使用该Material。效果如下:

Shader编程学习笔记(九)—— Cg语言入门1第3张

  拖动场景窗口,可以发现物体的大小随着窗口的变化而变化。目前需要了解的就是传递给顶点程序的就是模型的顶点数据,由模型的(x,y)凑成一个四阶向量,“POSITION”语义变量并没有在片段程序中输出,但是物体确实有大小上的变化,实际上“POSITION”语义是比较特殊的,可以不用在片段程序中直接使用“POSITION”输出,它被图形硬件直接做最后的处理和显示。在这里目前需要关心的是颜色的显示,我们可以在顶点程序中为颜色计算做一个输出,代码和效果如下:

Shader编程学习笔记(九)—— Cg语言入门1第4张Shader编程学习笔记(九)—— Cg语言入门1第5张
Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
                col = float4(0,0,1,1);
            }

            void frag(inout float4 col:COLOR){
                // col = float4(0,1,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

 Shader编程学习笔记(九)—— Cg语言入门1第6张

  片段程序的颜色设置已经注释掉了,否则会覆盖顶点程序的颜色值。需要注意的是作为输出的“COLOR”变量要放在作为输出的“POSITION”语义之前,如“vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION)”,否则颜色输出始终是无法改变的。

  计算机图形硬件想要对3D场景中的物体做一个正确的显示时,它需要经过一系列的坐标系变换,如果输入一个物体的坐标系,这个物体的坐标系是没有参考价值的,它只存在物体自身的空间当中,物体在世界坐标中,与其他物体之间有一个相对位置,被摄像机照射时,物体在不同的位置,摄像机最终获取的结果是不一样的。通过这一些列的变换,会得到一个称为“CVV(Canonical View Volume)”的裁剪立方体,“CVV”实际上就是在进行摄像机透视投影在齐次空间当中的一个裁剪立方体,称为“正规化可视空间”,它的x值和y值总是在-1到1之间。

  对于Unity中默认创建的一个Cube,它的网格数据的顶点信息中存储的x值和y值最大为0.5,最小为-0.5,模型的坐标中心为正中间(0,0)。当模型空间当中的x和y作为一个“POSITION”语义的输入时,可以知道它最大值为(0.5,0.5,0,1),最小为(-0.5,-0.5,0,1),在“CVV”的裁剪立方体当中x值和y值始终是-0.5到0.5,场景窗口最左边位置x为-1,正中间x为0,最右边位置x为1,y值同理。因此拖动窗口时,物体总是会随着窗口的变化而变化。

  注释掉片段程序中的颜色输出,在顶点程序中将位置信息“pos”作为颜色信息,在Cg当中只要数据类型相同,两者之间是可以互相赋值的,尽管语义不同,语义只是在顶点和片段程序中输入输出的一个规范。代码和效果如下:

Shader编程学习笔记(九)—— Cg语言入门1第7张Shader编程学习笔记(九)—— Cg语言入门1第8张
Shader "Lesson/vertex&fragment"{
    SubShader{
        pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            void vert(in float2 objPos:POSITION, out float4 col:COLOR, out float4 pos:POSITION){
                pos = float4(objPos,0,1);
                col = pos;
            }

            void frag(inout float4 col:COLOR){
                // col = float4(0,1,0,1);
            }
            ENDCG
        }
    }
}
vertex&fragment

Shader编程学习笔记(九)—— Cg语言入门1第9张

  物体的颜色会随着位置的变化而变化,颜色值的范围是(-0.5,-0.5,0,1)到(0.5,0.5,0,1)。

免责声明:文章转载自《Shader编程学习笔记(九)—— Cg语言入门1》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Eclipse里Tomcat报错:Document base ……does not exist or is not a readable directory(图文详解)数据库部署之导入的视图数量少于脚本中的视图、函数/存储过程导入完毕存在大红叹号问题原因及解决方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

z-index 应用简单总结

做过页面布局的同学对z-index属性应该是很熟悉了,z-index是针对网页显示中的一个特殊属性。因为显示器是显示的图案是一个二维平面,拥有x轴和y轴来表示位置属性。为了表示三维立体的概念如显示元素的上下层的叠加顺序引入了z-index属性来表示z轴的区别。表示一个元素在叠加顺序上的上下立体关系。 z-index值较大的元素将叠加在z-index值较小的...

RecyclerView的万能适配器+定义可以到底部自动刷新的RecyclerView

RecyclerView的重要性就不做重复说明了,为了方便以后直接使用写了这个,主要有:   万能适配器在使用的时候分为定义布局和绑定数据,方便直接套用。加入了底部刷新,需要配合自己写的RecyclerView一起使用,对于布局中各个子布局和控件可以做到响应各种点击事件:     首先抽取ViewHolder:这里的要点是用到了SparseArray(源码...

(转载)Cocos2dx-OpenGL ES2.0教程:初识MVP(3)

在上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix。它其实是一个uniform,每一个cocos2d-x预定义的shader都包含有这个uniform, 但是如果你在shader里面不使用这个变量的话,OpenGL底层会把它优化掉。 但是,CC_MVPMatrix是在什么时候设置进来的呢?我在shader里面明...

shader 的 nounroll

刚刚解决了一个特别坑的问题。 客户有个需求 需要shader里面 loop 的iterator数量 在运行时确定。z 这样对于里面存在  sample的loop就会被force unroll但因为count不确定 就没法unroll就编译不过了 我发现只有一个方法就是 关掉unroll  我试验了各种 在shader里面用预编译指令 关unroll 的方法...

第一百八十节,jQuery-UI,知问前端--消息提示 UI

jQuery-UI,知问前端--消息提示 UI 学习要点:   1.HTML 部分   2.CSS 部分   3.jQuery 部分 通过前面已学的 jQuery UI 部件,我们来创建一个注册表单。 html <div id="reg" title="会员注册"> <p> <label fo...

每次都能让人头大的 Shader -- 从一次简单的功能说起

  最近有个功能, 要渲染从主相机视角看到的另一个相机的可视范围和不可见范围, 大概如下图 :    简单来说就是主相机视野和观察者相机视野重合的地方, 能标记出观察者相机的可见和不可见, 实现原理就跟 ShadowMap 一样, 就是有关深度图, 世界坐标转换之类的, 每次有此类的功能都会很悲催, 虽然它的逻辑很简单, 可是用Unity3D做起来很麻烦...