网页资讯视频图片知道文库贴吧地图采购
进入贴吧全吧搜索

 
 
 
日一二三四五六
       
       
       
       
       
       

签到排名:今日本吧第个签到,

本吧因你更精彩,明天继续来努力!

本吧签到人数:0

一键签到
成为超级会员,使用一键签到
一键签到
本月漏签0次!
0
成为超级会员,赠送8张补签卡
如何使用?
点击日历上漏签日期,即可进行补签。
连续签到:天  累计签到:天
0
超级会员单次开通12个月以上,赠送连续签到卡3张
使用连续签到卡
06月13日漏签0天
codea吧 关注:923贴子:10,893
  • 看贴

  • 图片

  • 吧主推荐

  • 游戏

  • 13回复贴,共1页
<<返回codea吧
>0< 加载中...

法线贴图的效果+代码

  • 只看楼主
  • 收藏

  • 回复
  • HexBlues
  • 颇具盛名
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
直接上图先
原始纹理贴图

法线图

光照效果





  • HexBlues
  • 颇具盛名
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
-- 各种贴图效果 shader
shaders = {
--normal mapping
NormalMapping = { vs=[[
//--------vertex shader---------
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying vec2 vTexCoord;
varying vec4 vColor;
uniform mat4 modelViewProjection;
void main()
{
vColor = color;
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]],
fs=[[
//---------Fragment shader------------
//Default precision qualifier
precision highp float;
varying vec2 vTexCoord;
varying vec4 vColor;
// 纹理贴图
uniform sampler2D tex;
// 对应的法向图
uniform lowp sampler2D s_multitex;
uniform vec2 Resolution;
uniform vec3 LightPos;
uniform vec4 LightColor;
uniform vec4 AmbientColor;
uniform vec3 Falloff;
void main()
{
//vec4 DiffuseColor = texture2D(tex,vTexCoord);
//vec3 NormalMap = texture2D(s_multitex,vTexCoord).rgb;
vec4 DiffuseColor = texture2D(tex,vec2(mod(vTexCoord.x,1.0), mod(vTexCoord.y,1.0)));
vec3 NormalMap = texture2D(s_multitex,vec2(mod(vTexCoord.x,1.0), mod(vTexCoord.y,1.0))).rgb;
//NormalMap.g = 1.0 - NormalMap.g;
vec3 LightDir = vec3(LightPos.xy-(vTexCoord.xy/Resolution.xy),LightPos.z);
LightDir.x *= Resolution.x/Resolution.y;
float D = length(LightDir);
vec3 N = normalize(NormalMap*2.0-1.0);
vec3 L = normalize(LightDir);
vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(N,L), 0.0);
vec3 Ambient = AmbientColor.rgb * AmbientColor.a;
float Attenuation = 1.0 / (Falloff.x + (Falloff.y*D) + (Falloff.z*D*D));
// 亮度 = 环境光 + 散射 * 衰减
vec3 Intensity = Ambient + Diffuse * Attenuation;
vec3 FinalColor = DiffuseColor.rgb * Intensity;
gl_FragColor = vColor * vec4(FinalColor,DiffuseColor.a);
}
]]},
-- 旧的用来生成法向图的 shader
genNormal = {
vs = [[
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying vec2 vTexCoord;
varying vec4 vColor;
varying vec4 vPosition;
uniform mat4 modelViewProjection;
void main()
{
vColor = color;
vTexCoord = texCoord;
vPosition = position;
gl_Position = modelViewProjection * position;
}
]],
fs = [[
precision highp float;
varying vec2 vTexCoord;
varying vec4 vColor;
varying vec4 vPosition;
uniform sampler2D texture;
// 纹理贴图
uniform sampler2D tex;
void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col = texture2D( texture, vTexCoord );
// vec4 normal = normalize(col.rgba);
//彩色法线效果. 法向图
// gl_FragColor = vec4(fmod( (normal.xyz+1.)/2.,1.0), 1.);
// 先求像素点的灰度值
float grey = 0.2126*col.r + 0.7152* col.g + 0.0722*col.b;
//把范围为 [0, 1.0] 的颜色值变换为范围为 [-1.0, 1.0] 的法线值
vec3 pos3D = vec3(vPosition.x, vPosition.y, grey);
vec3 greyCol = vec3(grey,grey,grey);
// 把灰度值作为 z 轴坐标, 组合出立体空间的 vec3 坐标
//vec3 normal = normalize(vec3(vPosition.x*2.-1., vPosition.y*2.-1., grey*2.-1.));
vec3 normal = normalize(vec3(vPosition.x/1000., vPosition.y/1000., grey*2.-1.));
// 直接使用灰度图
gl_FragColor = vec4(greyCol, col.a);
gl_FragColor = vec4((normal.xyz+1.)/2., col.a);
//Set the output color to the texture color
// gl_FragColor = col;
}
]]
},
-- 用 sobel 算子生成法线图 generate normal map with sobel operator
genNormal1 = {
vs = [[
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying vec2 vTexCoord;
varying vec4 vColor;
varying vec4 vPosition;
uniform mat4 modelViewProjection;
void main()
{
vColor = color;
vTexCoord = texCoord;
vPosition = position;
gl_Position = modelViewProjection * position;
}
]],
fs = [[
precision highp float;
varying vec2 vTexCoord;
varying vec4 vColor;
varying vec4 vPosition;
// 纹理贴图
uniform sampler2D tex;
uniform sampler2D texture;
//图像横向长度-宽度, 图像纵向长度-高度
uniform float w;
uniform float h;
float clamp1(float, float);
float intensity(vec4);
float clamp1(float pX, float pMax) {
if (pX > pMax)
return pMax;
else if (pX < 0.0)
return 0.0;
else
return pX;
}
float intensity(vec4 col) {
// 计算像素点的灰度值
return 0.3*col.x + 0.59*col.y + 0.11*col.z;
}
void main() {
// 横向步长-每像素点宽度,纵向步长-每像素点高度
float ws = 1.0/w ;
float hs = 1.0/h ;
float c[10];
vec2 p = vTexCoord;
lowp vec4 col = texture2D( texture, p );
// sobel operator
// position. Gx. Gy
// 1 2 3 |-1. 0. 1.| |-1. -2. -1.|
// 4 5 6 |-2. 0. 2.| | 0. 0. 0.|
// 7 8 9 |-1. 0. 1.| | 1. 2. 1.|
// 右上角,右,右下角
c[3] = intensity(texture2D( texture, vec2(clamp(p.x+ws,0.,w), clamp(p.y+hs,0.,h) )));
c[6] = intensity(texture2D( texture, vec2(clamp1(p.x+ws,w), clamp1(p.y,h))));
c[9] = intensity(texture2D( texture, vec2(clamp1(p.x+ws,w), clamp1(p.y-hs,h))));
// 上, 下
c[2] = intensity(texture2D( texture, vec2(clamp1(p.x,w), clamp1(p.y+hs,h))));
c[8] = intensity(texture2D( texture, vec2(clamp1(p.x,w), clamp1(p.y-hs,h))));
// 左上角, 左, 左下角
c[1] = intensity(texture2D( texture, vec2(clamp1(p.x-ws,w), clamp1(p.y+hs,h))));
c[4] = intensity(texture2D( texture, vec2(clamp1(p.x-ws,w), clamp1(p.y,h))));
c[7] = intensity(texture2D( texture, vec2(clamp1(p.x-ws,w), clamp1(p.y-hs,h))));
// 先进行 sobel 滤波, 再把范围从 [-1,1] 调整到 [0,1]
float dx = (c[3]+2.*c[6]+c[9]-(c[1]+2.*c[4]+c[7]) + 1.0) / 2.0;
float dy = (c[7]+2.*c[8]+c[9]-(c[1]+2.*c[2]+c[3]) + 1.0) / 2.0;
float dz = (1.0 + 1.0) / 2.0;
gl_FragColor = vec4(vec3(dx,dy,dz), col.a);
}
]]
}
}


2025-06-13 07:32:59
广告
  • HexBlues
  • 颇具盛名
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
为什么不太喜欢在贴吧贴技术贴, 就是因为这破地方老是瞎JB删帖, 搞来搞去特麻烦
-- normal maping
--[[
The Normal Mapping code from Author: @1980geeksquad
Link: https://codea.io/talk/discussion/4674/example-of-normal-mapping
法线贴图光照效果的代码来自 @1980geeksquad
--]]
function setup()
displayMode(OVERLAY)
-- 用 shader 生成法线图
m1=mesh()
m1Tex = readImage("Dropbox:n1")
m1.shader=shader(shaders["genNormal1"].vs,shaders["genNormal1"].fs)
m1.shader.texture = m1Tex
m1.shader.w, m1.shader.h = m1Tex.width, m1Tex.height
-- 单独显示由 shader 生成的法线图
m1:addRect(m1Tex.width/2,m1Tex.height/2, m1Tex.width, m1Tex.height)
-- 用 nMap 保存由 shader 生成的法线图
nMap = image(m1Tex.width, m1Tex.height )
setContext(nMap)
m1:draw()
setContext()
-- 用 shader 演示法线贴图-法线映射
m = mesh()
img = readImage("Dropbox:n1")
m.shader=shader(shaders["NormalMapping"].vs,shaders["NormalMapping"].fs)
local w,h = img.width, img.height
local ws,hs=WIDTH/w, HEIGHT/h
--ws,hs = 1,1
m.shader.Resolution = vec2(ws,hs)
m.shader.LightPos = vec3(0,0,0.075)
m.shader.LightColor = vec4(0.94,0.77,0.17,0.9)
m.shader.AmbientColor = vec4(0.6,0.6,1.0,0.5)
m.shader.Falloff = vec3(0.4,2.0,10.0)
m:setRectTex(m:addRect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT),0,0,ws,hs)
-- the same as above line 手工定义顶点
-- m.vertices={vec2(0,0),vec2(WIDTH,0),vec2(0,HEIGHT),vec2(WIDTH,0),vec2(0,HEIGHT),vec2(WIDTH,HEIGHT) }
-- m.texCoords = {vec2(0,0),vec2(ws,0),vec2(0,hs),vec2(ws,0),vec2(0,hs),vec2(ws,hs)}
m.shader.tex = "Dropbox:n1"
m.shader.s_multitex = "Dropbox:n2"
m.shader.s_multitex = nMap
--[[
bumpImg = genBumpMap(img,0.007)
greyImg = genGreyMap(img,1)
--nMap = genNormalMap(img, 0.8)
gnMap = greyNormal(greyImg,2)
-- m.shader.tex = img
m.shader.s_multitex = gnMap
--saveImage("Dropbox:grey1",greyImg)
--saveImage("Dropbox:nmap1",gnMap)
--]]
tchx=0
tchy=0
end
function draw()
background(0)
-- 设置光源位置坐标
m.shader.LightPos = vec3(tchx/WIDTH,tchy/HEIGHT,0.015)
m:draw()
--[[
m1:draw()
sprite(bumpImg,WIDTH/2+300,400)
sprite(greyImg,WIDTH/2+300,150)
--sprite(nMap,WIDTH/2,450)
sprite(gnMap,WIDTH/2+350,650)
sprite("Dropbox:n2",WIDTH/2,650)
--]]
sprite(nMap,WIDTH/2,650)
end
function touched(touch)
if touch.state == BEGAN or touch.state == MOVING then
tchx=touch.x+50
tchy=touch.y+50
end
end
-- 法线图生成函数:从高度图(灰度图)生成
-- 确保像素点坐标落在纹理贴图内: (1, pMax)
function clamp(pX, pMax)
if (pX > pMax) then
return pMax;
elseif (pX < 1) then
return 1;
else
return pX;
end
end
-- 像素点光强度: 高度
function intensity(col)
-- 计算像素点的灰度值
--local average = (col.r + col.g + col.b)/3;
return 0.3*col.r + 0.59*col.g + 0.11*col.b
end
-- 把单位向量从 [-1.0, 1.0] 转换范围到 [0,255]
function normal2Color(p)
return (p + vec3(1,1,1)) * (255 / 2)
end
-- 直接从纹理贴图生成法线图
function genNormalMap(img,s)
local w,h = img.width,img.height
local temp = image(w,h)
for y =1,img.height do
for x = 1,img.width do
-- 取得周围的像素点的 rgba值(灰度值-亮度)
topLeft = color(img:get(clamp( x - 1, w), clamp(y + 1, h)))
top = color(img:get(clamp( x , w), clamp(y + 1, h)))
topRight = color(img:get(clamp( x + 1, w), clamp(y + 1, h)))
right = color(img:get(clamp( x + 1, w), clamp(y , h)))
bottomRight = color(img:get(clamp( x + 1, w), clamp(y - 1 , h)))
bottom = color(img:get(clamp( x , w), clamp(y - 1 , h)))
bottomLeft = color(img:get(clamp( x - 1, w), clamp(y - 1 , h)))
left = color(img:get(clamp( x - 1, w), clamp(y , h)))
-- 计算得到灰度值
tl = intensity(topLeft)
t = intensity(top);
tr = intensity(topRight);
r = intensity(right);
br = intensity(bottomRight);
b = intensity(bottom);
bl = intensity(bottomLeft);
l = intensity(left);
--滤波 sobel filter
dX = (tr + 2.0 * r + br) - (tl + 2.0 * l + bl);
dY = (bl + 2.0 * b + br) - (tl + 2.0 * t + tr);
dZ = 255 / s;
newCol = normal2Color(vec3(dX,dY,dZ))
newCol = normal2Color(vec3(dX,dY,dZ):normalize())
--print(newCol)
temp:set(x,y,color(newCol.x, newCol.y, newCol.z, 255))
end
end
return temp
end
-- 从灰度图生成法线图
function greyNormal(img,s)
local w,h = img.width,img.height
local temp = image(w,h)
local sobel = math.sqrt(2.0)
local sobel = 1.0
for y =1,img.height do
for x = 1,img.width do
-- 取得 me 周围的像素点的 rgba值(灰度值)
tl = color(img:get(clamp( x - 1, w), clamp(y + 1, h)))
t = color(img:get(clamp( x , w), clamp(y + 1, h)))
tr = color(img:get(clamp( x + 1, w), clamp(y + 1, h)))
r = color(img:get(clamp( x + 1, w), clamp(y , h)))
br = color(img:get(clamp( x + 1, w), clamp(y - 1 , h)))
b = color(img:get(clamp( x , w), clamp(y - 1 , h)))
bl = color(img:get(clamp( x - 1, w), clamp(y - 1 , h)))
l = color(img:get(clamp( x - 1, w), clamp(y , h)))
me = color(img:get(clamp( x , w), clamp(y , h)))
--滤波 sobel filter
dX = (tr.r + sobel * r.r + br.r) - (tl.r + sobel * l.r + bl.r)
dY = (bl.r + sobel * b.r + br.r) - (tl.r + sobel * t.r + tr.r)
dZ = 255 / s
newCol = normal2Color(vec3(dX,dY,dZ):normalize())
--print(newCol)
temp:set(x,y,color(newCol.x, newCol.y, newCol.z, 255))
end
end
return temp
end
-- 灰度图生成函数
function genGreyMap(img, s)
local t = image(img.width, img.height)
for y =1,img.height do
for x = 1,img.width do
local r,g,b,a = img:get(x,y)
local g = (0.3*r+0.59*g+0.11*b)*s
t:set(x,y,color(g,g,g,255))
end
end
return t
end


  • HexBlues
  • 颇具盛名
    7
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
最近在试验一些场景相关的代码, 了解了下当前游戏中使用比较广泛的一些贴图技术, 例如什么凹凸贴图: Bump-Mapping, 法线贴图: Normal-Mapping, 视差贴图: Parallax-Mapping, 置换(移位)贴图: Displacement-Mapping, 个人感觉翻译成映射更好一些, 不过貌似贴图用得更多, 目前主流还是法线贴图和视差贴图, 置换贴图需要更高版本的 OpenGL ES 支持, 目测前三种应该都能在 Codea 里使用, 试着看看效果, 代码如上


  • 榆潭旅-
  • 声名远扬
    12
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
自己的水平已经跟不上时代的步伐了
——来自 三星 Windows Phone


  • 榆潭旅-
  • 声名远扬
    12
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
会有奇怪的变形


登录百度账号

扫二维码下载贴吧客户端

下载贴吧APP
看高清直播、视频!
  • 贴吧页面意见反馈
  • 违规贴吧举报反馈通道
  • 贴吧违规信息处理公示
  • 13回复贴,共1页
<<返回codea吧
分享到:
©2025 Baidu贴吧协议|隐私政策|吧主制度|意见反馈|网络谣言警示