2016/07/17 11:38

# 如何把一个标准 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` 来设置.

### 属性的对应设置

`Codea` 中, 有一些约定俗成的设置, 比如顶点的属性 `attribute`, 就有一些预先定义好的:

• `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=0

createMesh()
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;
``````

## 参考

Mesh Deformers with the GLSL

0
1 收藏

0 评论
1 收藏
0