存档

2017年5月 的存档

OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现

2017年5月17日 没有评论

常规的 光源类型 有三种。最简单的自然是平行光。稍复杂些的为点光源,最复杂的为聚光灯。总体说来,在可编程管线中原理是一样的。在OpenGL代码中传入必要的参数,在shader中进行相关的计算绘制出效果。本文分别介绍三种效果的shader实现。

平行光

平行光我们已经写的轻车熟路了。它只需要一个光源方向就够了。通常我们会定义一个光源点,它与坐标轴原点的连线就是光线方向。

//GL Code
float lightPos[] = { 0.0f,1.5f,0.0f,0.0f };
float diffuseLightColor[] = { 1.0f,1.0f,1.0f,1.0f };

glUniformMatrix4fv(gpuProgram.GetLocation("M"), 1,GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(gpuProgram.GetLocation("V"), 1, GL_FALSE, identity);
glUniformMatrix4fv(gpuProgram.GetLocation("P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniformMatrix4fv(gpuProgram.GetLocation("NM"), 1, GL_FALSE, glm::value_ptr(normalMatrix));
glUniform4fv(gpuProgram.GetLocation("U_LightPos"), 1, lightPos);
glUniform4fv(gpuProgram.GetLocation("U_DiffuseLightColor"), 1, diffuseLightColor);

//fs
void main(){
    //...
    vec3 n = normalize(V_Normal);
    vec3 L = U_LightPos.xyz;
    float diffuseIntensity=max(0.0,dot(L,n));
    vec4 diffuseColor=U_DiffuseLightColor*diffuseIntensity;
    //...
    gl_FragColor=ambientColor+diffuseColor;
}

获取的光线方向直接与法线点乘,即为光照强度。

点光源

在平行光的基础上,根据模型与光源之间的距离进行衰减。衰减为与距离相关的二次函数。因此需要加入三个因数,分别为expFactorlinearFactorconstantFactor

//GL Code
float constantFactor = 1.0;
float linearFactor = 0.2;
float expFactor=0.0;

glUniform1f(gpuProgram.GetLocation("U_ConstantFactorn"), 1, constantFactor);
glUniform1f(gpuProgram.GetLocation("U_LinearFactor"), 1, linearFactor);
glUniform1f(gpuProgram.GetLocation("U_ExpFactor"), 1, expFactor);


//fs
float attenuation =  1.0;

void main(){
    //...
    vec3 n = normalize(V_Normal);
    vec3 L = U_LightPos.xyz - V_WorldPos;
    float distance = length(L);
    attenuation = 1.0/(U_ExpFactor*distance*distance + U_LinearFactor*distance + U_ConstantFactor);
    float diffuseIntensity = max(0.0,dot(L,n));
    vec4 diffuseColor = U_DiffuseLightColor*attenuation*diffuseIntensity;
    //...
    gl_FragColor=ambientColor+diffuseColor;
}

聚光灯

在点光源的基础上,添加一个带角度的锥形区域的检测。只有在区域内的部分才有照亮处理。因此需要传入shader两个参数,分别为光照方向和范围角度。

//GL Code
//...
float spotLightDirection[] = { 0.0f,-1.0f,0.0f,128.0f };
float spotLightCutoff = 15.0f;

glUniform1f(gpuProgram.GetLocation("U_Cutoff"), spotLightCutoff);
glUniform4fv(gpuProgram.GetLocation("U_LightDirection"), 1, spotLightDirection);

//...

//fs
float attenuation =  1.0;

void main(){
    //...

    float radianCutoff = U_Cutoff*3.14/180;
    float cosThta = cos(radianCutoff);
    vec3 spotLightDirection = normalize(U_LightDirection.xyz);

    vec3 n = normalize(V_Normal);
    vec3 L = U_LightPos.xyz - V_WorldPos;
    float distance = length(L);
    attenuation = 1.0/(U_ExpFactor*distance*distance + U_LinearFactor*distance + U_ConstantFactor);
    
    float currentCosThta=max(0.0,dot(-L,spotLightDirection));
    float diffuseIntensity = 0.0;
    if(currentCosThta > cosThta)
    {
        if(dot(L,n) >0.0)
        {
            diffuseIntensity = pow(currentCosThta,U_LightDirection.w); 
        }
    }
    vec4 diffuseColor = U_DiffuseLightColor*attenuation*diffuseIntensity;

    //...
    gl_FragColor=ambientColor+diffuseColor;
}

总结

以上为三种光源的OpenGL实现,可以看出,计算量最大的为聚光灯效果,而且为了让边缘柔和,需要pow的大量计算。移动端跑实时运算估计要优化算法了。

OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现

关注我的微信公众号,获取更多优质内容

分类: 未分类 标签:

Mac搭建本地局域网SVN服务(Cornerstone)

2017年5月10日 没有评论

下周需要和团队一起去外地工作几天,发现提交代码合并比较麻烦,考虑到团队还有美术同学,想想还是本地开启个svn,先临时用用吧。

mac系统是已经安装了svn服务的,所以这里我们只需要开启就行了。

1. 验证本地已安装svn服务。

$ svnserve --version

2. 创建代码库文件夹LocalSVNServer

$ sudo mkdir -p ~/Documents/LocalSVNServer

3. 初始化svn代码库

$ sudo svnadmin create ~/Documents/LocalSVNServer

打开LocalSVNServer文件夹,你会发现已经生成了svn服务。
Mac搭建本地局域网SVN服务(Cornerstone)

4. 配置svn用户权限,打开conf/svnserve.conf

Mac搭建本地局域网SVN服务(Cornerstone)

修改以上位置,其中anon-access = read代表匿名访问的时候是只读的,若改为anon-access = none代表禁止匿名访问,需要帐号密码才能访问

5. 配置账号passwd文件,打开conf/passwd

Mac搭建本地局域网SVN服务(Cornerstone)
[users]标签下面的是用户账号,把需要的 用户名=密码 添加在这里

6. 配置权限authz文件,打开conf/authz

Mac搭建本地局域网SVN服务(Cornerstone)
在[groups]下添加dev = liuyanghui标示创建了一个用户组dev,此用户组包含有liuyanghui用户,多个的话逗号连接:dev = liuyanghui,liuyanghui2

[/]
@dev = rw 这两句标示给dev用户组相应的权限

[/]表示授权的目录路径,这里是根目录,假如根目录下有一个目录叫做test,那么我们如果要编辑此目录的权限那么就要写成[test:/]

@dev表示给用户组授权,如果要给某一个用户授权则不用写前面的@,r表示可读,w表示可写

7. 启动svn(启动成功后活动监视器中可以搜索svnserve,会发现存在)

$ svnserve -d -r ~/Documents/LocalSVNServer

  • 关闭SVN
  • 命令终端直接输入下面命令,第一个数字为进程号。
  • $ ps aux | grep svn
  • Mac搭建本地局域网SVN服务(Cornerstone)
  • 然后$ sudo kill -xxx (xxx代表进程号),上面图片就是18328
  • 可以在活动监视器里进行搜索:svnserve,停止该服务

8. Cornerstone添加svn仓库,局域网其他机器svn地址写ip。本机的话localhost

Mac搭建本地局域网SVN服务(Cornerstone)

9. 如果发现提交svn出现文件夹无权限的话(一般是txn-current-lock无读写权限),增加svn仓库文件夹权限

$ sudo chmod -R a+w ~/Documents/LocalSVNServer/

分类: 未分类 标签:

OpenGL(十一) 可编程管线 基础光照 的实现

2017年5月2日 没有评论

在OpenGL中创建 基础光照 ,主要的工作将模型中的法线信息和法线空间运算矩阵传入到shader中。另一方面,LightDir,ViewDir通常是在shader中从引擎参数获取的,为了简化光照模型的实现,这里我们可以在shader中写死。至于经典的 ambient+diffuse+specular 光照原理,不是本文的重点,就在shader中一笔带过了。

原理

通过函数

glm::mat4 normalMatrix = glm::inverseTranspose(s_shaderData.model);

可以获取当前模型的法线矩阵。用来将法线信息从模型坐标转换为世界坐标。这个矩阵是随着模型的Transform改变而改变的,因此需要在Render时动态计算。

实现

在 基础光照 中,数据传递没什么特殊的,将Normal信息作为attribute传递到shader,将NormalMatrix作为uniform传递到shader。

//normalmatrix
glm::mat4 normalMatrix = glm::inverseTranspose(s_shaderData.model)
glUniformMatrix4fv(s_shaderData.NMLocation,1,GL_FALSE,glm::value_ptr(normalMatrix))

// normal
glEnableVertexAttribArray(s_shaderData.normalLocation);
glVertexAttribPointer(s_shaderData.normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)(sizeof(float)*5)); 

vs中首先将法线转置到世界坐标,然后将其传递给fs。

//vs
attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;

uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
uniform mat4 NM;

varying vec3 V_Normal;
varying vec3 V_WorldPos;

void main()
{
    V_Normal = mat3(NM)*normal;
    V_WorldPos = M * vec4(pos,1.0);
    gl_Position=P*V*M*vec4(pos,1.0);
}

在fs中使用经典的pong公式做个最简单的效果。

varying vec3 V_Normal;
varying vec3 V_WorldPos;

void main()
{
    vec3 lightPos = vec3(10.0,10.0,0.0);
    vec3 L = lightPos;

    L = normalize(L);
    vec3 n = normalize(V_Normal);

    //ambient
    vec4 AmbientLightColor = vec4(0.2,0.2,0.2,1.0);
    vec4 AmbientMaterial = vec4(0.2,0.2,0.2,1.0);
    vec4 ambientColor = AmbientLightColor * AmbientMaterial;
    
    //diffuse
    vec4 DiffuseLightColor = vec4(1.0,1.0,1.0,1.0);
    vec4 DiffuseMaterial = vec4(0.8,0.8,0.8,1.0);
    vec4 diffuseColor = DiffuseLightColor * DiffuseMaterial * max(0.0,dot(L,n));

    //specular
    vec3 reflectDir = normalize(reflect(-L,n));
    vec3 viewDir = normalize(vec3(0.0)-V_WorldPos.xyz);
    vec4 SpecularLightColor = vec4(1.0,1.0,1.0,1.0);
    vec4 SpecularMaterial = vec4(1.0,1.0,1.0,1.0);
    vec4 specularColor = SpecularLightColor*SpecularMaterial*pow(max(0.0,dot(viewDir,reflectDir)),128);

    gl_FragColor= ambientColor+diffuseColor+specularColor;
}

另外需要注意的是,有光照的模型通常需要打开深度测试,也需要记得将深度缓存清空。

//Open test
glEnable(GL_DEPTH_TEST);

//when render
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

总结

通过上面的代码,搭建基本框架。可以实现 基础光照 模型。如果需要添加其他参数效果,则需要增加Uniform传递的参数了。

OpenGL(十一) 可编程管线 基础光照 的实现

关注我的微信公众号,获取更多优质内容

分类: 未分类 标签: