在阅读有关GLSL的this Tutorial以及如何使用“法线贴图”从简单的石墙中创建如此强大的动态Texture
之后,我对Shader
的强大力量印象深刻秒。
由于我对Shader
和3D很新,我想知道如何将这种Shader
应用到我的wip 3D游戏中。所以我正在寻找更多的教程,我找到了this,这让我对Shader
及其逻辑有了更多的了解。但我不知道我是否真的理解它,所以我在这里问
我想做什么:我有一些基本的Wall
,由简单的纹理立方体组成。 Texture
与我链接的第一个教程大致相同。我有Normal Map
Texture
,也就像在教程中一样,我希望为那些Texture
添加相同的效果,但正如我所说的那样是3D。
因此,据我所知,我不需要改变任何东西,而是Normal Map
。我必须知道块的面,Texture
和将其法线乘以面法线(例如左面的Vector3(-1,0,0))旋转它(例如,Y-Axis
绕着Face
旋转90°。这个假设是正确的还是我走错了路?
如果我是对的,而不是使用Normal Map Texture
,还有一种方法可以获得导入的g3db Model
的每个“像素”(点)的正常吗?
答案 0 :(得分:1)
您可以使用您想要的着色器作为输入,但texure是每个片段修改的常见输入。
Uniform Buffer vs Texture Performances considerations
具有切线空间信息(每个像素坐标系)的经典法线贴图技术可以被其他技术(例如凹凸贴图)甚至您自己的实现覆盖。请注意,必须预先计算用于法线或凹凸贴图的切线矢量(Tangent,Binormal,Normal)并将其添加到顶点属性中。您可以使用脏技巧在顶点着色器中计算它们,但这会导致一些故障。
您的示例仅使用片段着色器,因此您确定缺少某些内容以使其在3d场景中工作。
为了在3d中工作,你需要实现一个顶点着色器,它将处理每个顶点法线(here is a implementation):
[Vertex_Shader]
varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoord;
attribute vec3 vTangent;
void main(void)
{
gl_Position = ftransform();
texCoord = gl_MultiTexCoord0.xy;
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * vTangent);
vec3 b = cross(n, t);
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;
lightVec.x = dot(tmpVec, t);
lightVec.y = dot(tmpVec, b);
lightVec.z = dot(tmpVec, n);
tmpVec = -vVertex;
eyeVec.x = dot(tmpVec, t);
eyeVec.y = dot(tmpVec, b);
eyeVec.z = dot(tmpVec, n);
}
[Pixel_Shader]
varying vec3 lightVec;
varying vec3 eyeVec;
varying vec2 texCoord;
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform float invRadius;
void main (void)
{
float distSqr = dot(lightVec, lightVec);
float att = clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0);
vec3 lVec = lightVec * inversesqrt(distSqr);
vec3 vVec = normalize(eyeVec);
vec4 base = texture2D(colorMap, texCoord);
vec3 bump = normalize( texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);
vec4 vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
float diffuse = max( dot(lVec, bump), 0.0 );
vec4 vDiffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse *
diffuse;
float specular = pow(clamp(dot(reflect(-lVec, bump), vVec), 0.0, 1.0),
gl_FrontMaterial.shininess );
vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular *
specular;
gl_FragColor = ( vAmbient*base +
vDiffuse*base +
vSpecular) * att;
}
如果你不将它们添加到你的顶点属性中,你可以使用脏技巧来获得切线
vec3 c1 = cross( gl_Normal, vec3( 0, 0, 1 ) );
vec3 c2 = cross( gl_Normal, vec3( 0, 1, 0 ) );
if( length( c1 ) > length( c2 ) ) tangent = normalize( c1 );
else tangent = normalize( c2 );