GLSL下几个简单的Shader

在ShaderDesigner下编Shader是最为方便的,但这里先用OpenGL下的编程来举例

转载请注明 如有疑问欢迎留言

这几个Shader的实际效果:

1.最简单的固定单色Shader

Vertex Shader

坐标经过投影矩阵变换:vTrans = projection * modelview * incomingVertex

void main(){gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;}或者更简单的方式,使用ftransform函数void main(){gl_Position = ftransform();}Fragment Shader

赋予像素一个固定值的颜色

void main(){gl_FragColor = vec4(0.4,0.4,0.8,1.0);}

2.颜色Shader

在OpenGL程序当中使用 glColor函数指定颜色时,接收该颜色值的Shader

例如OpenGL程序当中画一个红色茶壶: glColor3f(1, 0, 0);glutSolidTeapot(1);

glColor在Shader当中总共涉及四个值

attribute vec4 gl_Color;varying vec4 gl_FrontColor; // writable on the vertex shadervarying vec4 gl_BackColor; // writable on the vertex shadervarying vec4 gl_Color; // readable on the fragment shader

流程如下:

OpenGL程序使用glColor函数后,将颜色值以attribute gl_Color的形式传给了Vertex Shader, Vertext Shader接受到后开始计算gl_FontColor和gl_BackColor,而在Fragment Shader则会接受到一个由FontColor和BackColor插值计算出来的varying gl_Color(注意:该gl_Color与Vertex Shader当中的不同),因而可以基于gl_Color开始计算gl_FragColor

Vertex Shader

void main(){gl_FrontColor = gl_Color;gl_Position = ftransform();}Fragment Shadervoid main(){gl_FragColor = gl_Color;}

3.动态变形Shader

随着时间变动,改变渲染坐标。关键在于如何把OpenGl的变量传递给Shader

比如在OpenGL中设定一个时间变量time,初始化为0,每次渲染时增加0.1:

float t = 0;void renderScene(void) {…t += 0.001;}那么将其传递给Shader需要做的是:

1.在初始化阶段使用glGetUniformLocation获取Shader里变量的存取位置

2.在渲染阶段使用glUniform给该存取位置变量赋值

GLint loc;float t = 0;void renderScene(void) {…glUniform1f(loc, t);t += 0.001;}void setShaders() {… glUseProgram(p);loc = glGetUniformLocation(p, "time");}最后在shader中使用时声明一下即可使用(本例当中让图形沿x轴3d翻转)

Vertex Shader

uniform float time;void main(){ gl_FrontColor = gl_Color; vec4 v = vec4(gl_Vertex); v.y=v.y*cos(time)+v.y*sin(time);     v.z=-v.y*sin(time)+cos(time)*v.z;gl_Position = gl_ModelViewProjectionMatrix * v;}

Fragment Shader

void main(){gl_FragColor = gl_Color;}

4.Lambert Shader

Lambert模型下的Shader,只考虑漫反射,反射强度正比于入射光与法线方向的夹角余弦值:Io= Ld*Md*cosθ

Ld是散射光颜色(gl_LightSource[0].diffuse),Md是材质散射系数(gl_FrontMaterial.diffuse),夹角余弦cosθ可由正规化的法线向量(normal)和入射光向量(lightDir)点乘得到。

OpenGL当中可以对材质和光照的属性进行设置

float lpos[4] = { 1, 0.5, 1, 0 };float lAmb[4] = { 0.2, 0.5, 1.0, 1 };float lDif[4] = { 0.2, 1.0, 1.0, 1 };float lSpe[4] = { 1.0, 1.0, 1.0, 1 }; glLightfv(GL_LIGHT0, GL_POSITION, lpos);glLightfv(GL_LIGHT0, GL_AMBIENT, lAmb);glLightfv(GL_LIGHT0, GL_DIFFUSE, lDif);glLightfv(GL_LIGHT0, GL_SPECULAR, lSpe); GLfloat ambient [] = { 0.1f, 0.1f, 0.1f, 1.0f};GLfloat diffuse [] = { 1.0f, 0.0f, 0.0f, 1.0f};GLfloat specular [] = { 1.0f, 1.0f, 1.0f, 1.0f};GLfloat shininess[] = { 0.0f};glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);glMaterialfv(GL_FRONT, GL_SPECULAR, specular);glMaterialfv(GL_FRONT, GL_SHININESS, shininess);

Vertex Shader

void main() {    vec3 normal, lightDir;    vec4 diffuse;    float NdotL;    /* 法线向量 */    normal = normalize(gl_NormalMatrix * gl_Normal);    /* 入射光向量*/    lightDir = normalize(vec3(gl_LightSource[0].position));   /* cosθ */NdotL = max(dot(normal, lightDir), 0.0);/* 散射项 */diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;  gl_FrontColor = NdotL * diffuse;gl_Position = ftransform();}

Fragment Shader

void main(){gl_FragColor = gl_Color;}

如果再考虑上环境散射项,那么OpenGL中使用glLightfv来设定环境光

float lpos[4] = { 1, 0.5, 1, 0 };float lAmb[4] = { 0.2, 0.5, 1, 1 };void renderScene(void) {…glLightfv(GL_LIGHT0, GL_POSITION, lpos);glLightfv(GL_LIGHT0, GL_AMBIENT, lAmb);…}

Vertex Shader

void main(){vec3 normal, lightDir;vec4 diffuse, ambient, globalAmbient;float NdotL;normal = normalize(gl_NormalMatrix * gl_Normal);lightDir = normalize(vec3(gl_LightSource[0].position));NdotL = max(dot(normal, lightDir), 0.0);diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;/* Compute the ambient and globalAmbient terms */ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;globalAmbient = gl_LightModel.ambient * gl_FrontMaterial.ambient;gl_FrontColor = NdotL * diffuse + globalAmbient + ambient;gl_Position = ftransform();}放下一处烦恼,收获一个惊喜;放下一种偏见,收获一种幸福;

GLSL下几个简单的Shader

相关文章:

你感兴趣的文章:

标签云: