1. 云栖社区>
2. PHP教程>
3. 正文

# 如何把一个标准 GLSL 例程改写为 Codea shader

# 如何把一个标准 GLSL 例程改写为 Codea shader
## 概述

## 法线贴图例程
### 顶点着色器代码

```
uniform mat4 u_matViewInverse;
uniform mat4 u_matViewProjection;
uniform vec3 u_lightPosition;
uniform vec3 u_eyePosition;
varying vec2 v_texcoord
varying vec3 v_viewDirection
varying vec3 v_lightDirection
attribute vec4 a_vertex;
attribute vec2 a_texcoord0;
attribute vec3 a_normal;
attribute vec3 a_binormal;
attribute vec3 a_tangent;
void main(void) {
// Transform eye vector into world space
vec3 eyePositionWorld =
(u_matViewInverse * vec4(u_eyePosition, 1.0)).xyz;
// Compute world space direction vector
vec3 viewDirectionWorld = eyePositionWorld - a_vertex.xyz;
// Transform light position into world space vec3 lightPositionWorld =
(u_matViewInverse * vec4(u_lightPosition, 1.0)).xyz;
// Compute world space light direction vector
vec3 lightDirectionWorld = lightPositionWorld - a_vertex.xyz;
// Create the tangent matrix
mat3 tangentMat = mat3(a_tangent,
a_binormal,
a_normal);

// Transform the view and light vectors into tangent space
v_viewDirection = viewDirectionWorld * tangentMat;
v_lightDirection = lightDirectionWorld * tangentMat;
// Transform output position
gl_Position = u_matViewProjection * a_vertex;
// Pass through texture coordinate
v_texcoord = a_texcoord0.xy;
}
```

### 统一变量的对应设置
4个统一变量如下:
```
uniform mat4 u_matViewInverse;
uniform mat4 u_matViewProjection;
uniform vec3 u_lightPosition;
uniform vec3 u_eyePosition;
```

- `u_matViewInverse` 应该是 `viewMatrix` 的逆矩阵;
- `u_matViewProjection` 应该是 `viewMatrix` 和 `projectionMatrix` 的相乘;
- `u_lightPosition` 应该是光源位置, 由我们自行设置;
- `u_eyePosition` 应该是摄像机位置, 可以通过 `camera` 来设置.

### 属性的对应设置

- `position` 顶点坐标
- `texCoord` 顶点的纹理坐标
- `color` 顶点的颜色
- `normal` 顶点的法线

```
attribute vec4 a_vertex;
attribute vec2 a_texcoord0;
attribute vec3 a_normal;
attribute vec3 a_binormal;
attribute vec3 a_tangent;
```

- `a_vertex` 跟 `position` 一样;
- `a_texcoord0` 跟 `texCoord` 一样;
- `a_normal` 跟 `normal` 一样.

```
vec3 tangent;
vec3 binormal;

vec3 c1 = cross(gl_Normal, vec3(0.0, 0.0, 1.0));
vec3 c2 = cross(gl_Normal, vec3(0.0, 1.0, 0.0));

if(length(c1)>length(c2))
{
tangent = c1;
}
else
{
tangent = c2;
}

// 归一化切线
tangent = normalize(tangent);

binormal = cross(gl_Normal, tangent);
binormal = normalize(binormal);
```

```
uniform mat4 u_matViewInverse;
uniform mat4 u_matViewProjection;
uniform vec3 u_lightPosition;
uniform vec3 u_eyePosition;
varying vec2 v_texcoord
varying vec3 v_viewDirection
varying vec3 v_lightDirection
attribute vec4 a_vertex;
attribute vec2 a_texcoord0;
attribute vec3 a_normal;
// attribute vec3 a_binormal;
// attribute vec3 a_tangent;
void main(void) {
// 先根据 normal 计算 binormal 和 tangent
vec3 tangent;
vec3 binormal;

vec3 c1 = cross(normal, vec3(0.0, 0.0, 1.0));
vec3 c2 = cross(normal, vec3(0.0, 1.0, 0.0));

if(length(c1)>length(c2))
{
tangent = c1;
}
else
{
tangent = c2;
}

// 归一化切线和次法线
tangent = normalize(tangent);
binormal = cross(normal, tangent);
binormal = normalize(binormal);
// 坐标空间转换: 摄像机坐标 Transform eye vector into world space
vec3 eyePositionWorld =
(u_matViewInverse * vec4(u_eyePosition, 1.0)).xyz;
// Compute world space direction vector
vec3 viewDirectionWorld = eyePositionWorld - a_vertex.xyz;
// Transform light position into world space
vec3 lightPositionWorld =
(u_matViewInverse * vec4(u_lightPosition, 1.0)).xyz;
// Compute world space light direction vector
vec3 lightDirectionWorld = lightPositionWorld - a_vertex.xyz;
// Create the tangent matrix
mat3 tangentMat = mat3(a_tangent,
a_binormal,
a_normal);

// Transform the view and light vectors into tangent space
v_viewDirection = viewDirectionWorld * tangentMat;
v_lightDirection = lightDirectionWorld * tangentMat;
// Transform output position
gl_Position = u_matViewProjection * a_vertex;
// Pass through texture coordinate
v_texcoord = a_texcoord0.xy;
}
```### 片段着色器代码

```
precision mediump float;
uniform vec4 u_ambient;
uniform vec4 u_specular;
uniform vec4 u_diffuse;
uniform float u_specularPower;
uniform sampler2D s_baseMap;
uniform sampler2D s_bumpMap;
varying vec2 v_texcoord;
varying vec3 v_viewDirection;
varying vec3 v_lightDirection;
void main(void) {
// Fetch basemap color
vec4 baseColor = texture2D(s_baseMap, v_texcoord);
// Fetch the tangent-space normal from normal map
vec3 normal = texture2D(s_bumpMap, v_texcoord).xyz;
// Scale and bias from [0, 1] to [-1, 1] and normalize
normal = normalize(normal * 2.0 - 1.0);
// Normalize the light direction and view direction
vec3 lightDirection = normalize(v_lightDirection);
vec3 viewDirection = normalize(v_viewDirection);
// Compute N.L
float nDotL = dot(normal, lightDirection);
// Compute reflection vector
vec3 reflection = (2.0 * normal * nDotL) - lightDirection;
// Compute R.V
float rDotV = max(0.0, dot(reflection, viewDirection));
// Compute Ambient term
vec4 ambient = u_ambient * baseColor;
// Compute Diffuse term
vec4 diffuse = u_diffuse * nDotL * baseColor;
// Compute Specular term
vec4 specular = u_specular * pow(rDotV, u_specularPower);
// Output final color
gl_FragColor = ambient + diffuse + specular;
}
```

## Lua 主程序

```
function setup()
print("normal 3D")
tchx=0
tchy=0createMesh()
cam = vec3(0, 0, 1000)
obj = vec3(0, 0, 0)
light = vec3(tchx, tchy, 0.075)
end
function draw()
perspective(50, WIDTH/HEIGHT)
light = vec3(tchx, tchy, 0.0075)
camera(cam.x, cam.y, cam.z, obj.x, obj.y, obj.z)
m:draw()
end
function createMesh()
m = mesh()
local w,h = WIDTH,HEIGHT
--]]--[[
m.shader.u_lightPosition = light or vec3(100, 100, 100)
m.shader.u_eyePosition = cam or vec3(100, 100, 100)
-- ambient/specular/diffuse 环境光，反射光，散射
m.shader.u_ambient = vec4(0.15, 0.15, 0.15, 0.8)
m.shader.u_specular = vec4(0.05, 0.05, 0.05, 0.8)
m.shader.u_diffuse = vec4(0.105, 0.005, 0.005, 0.8)
--]]-- m.texture = img1
end
m.shader.u_lightPosition = light or vec3(100, 100, 100)
m.shader.u_eyePosition = cam or vec3(100, 100, 100)
-- ambient/specular/diffuse 环境光，反射光，散射
end
function touched(touch)
if touch.state == BEGAN or touch.state == MOVING then
tchx=touch.x+50
tchy=touch.y+50
end
end
```
## 问题
### 1 无法改变距离

```
gl_Position = u_matViewProjection * a_vertex;
```

```
uniform mat4 modelViewProjection;
gl_Position = modelViewProjection * a_vertex;
```

### 2 上下坐标错位

```
mat4 mm = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, -1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0.
0.0, 0.0, 0.0, 1.0);

gl_Position = mm * modelViewProjection * a_vertex;
```
### 3 光线没有设置衰减

## 参考
[Mesh Deformers with the GLSL](http://www.ozone3d.net/tutorials/mesh_deformer_p2.php)

40+云计算产品，6个月免费体验