我试图实现正常/陡峭的视差贴图,但我得到了一些奇怪的人工制品。它看起来像视图和&当光矢量被转换为切线空间时,它们会被扭曲,导致光照和视差的紫外偏移是不正确的。
顶点着色器源:
// parallax.vert
#version 330
// Some drivers require the following
precision highp float;
//per vertex inputs stored on GPU memory
in vec3 in_Position;
in vec3 in_Normal;
in vec4 tangent;
//per mesh data sent at rendering time
uniform mat4 model; //object to world space transformations
uniform mat4 view; //world to eye space transformations
uniform mat4 projection; //eye space to screen space
uniform mat3 normalMat; //for transforming normals in
uniform vec4 lightPosition; //light position in world space
uniform vec3 eyePosition; //eye position in world space
//outputs to fragment shader
in vec2 in_TexCoord;
// multiply each vertex position by the MVP matrix
// and find V, L, and TBN Matrix vectors for the fragment shader
out VertexData
{
vec3 ts_L; //view vector tangent space
vec3 ts_V; //light vector tangent space
vec2 ex_TexCoord;
float dist;
} vertex;
void main(void)
{
//view space position for lighting calculations
vec3 position = ( ( view * model ) * vec4( in_Position,1.0 ) ).xyz;
//calculate view vector and light vector in view space
vec3 ex_V = -position;
vec3 ex_L = ( view * vec4( lightPosition.xyz,1.0 ) ).xyz - position;
vertex.ex_TexCoord = in_TexCoord;
//now calculate tbn matrix
//calculate biTangent, in view space
vec3 normal = normalMat*in_Normal;
vec3 tan = normalMat * tangent.xyz;
vec3 bitangent = normalize( cross( normal, tan.xyz ) * tangent.w );
//fragment stage will need this value for calculating light attenuation
vertex.dist = length( ex_L );
//calculate transpose tangent space matrix, as we are doing everything in T space in fragment stage
mat3 transTBN = transpose( mat3( tan, bitangent, normal ) );
//transform view space vertex view & light vectors into tangent space
vertex.ts_V = normalize( transTBN * ex_V );
vertex.ts_L = normalize( transTBN * ex_L );
gl_Position = projection * vec4(position,1.0);
}
片段着色器源:
// parallax.frag
#version 330
// Some drivers require the following
precision highp float;
struct lightStruct
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
float radius;
};
struct materialStruct
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 emissive;
float shininess;
};
//uniforms sent at render time
uniform lightStruct light;
uniform materialStruct material;
uniform vec2 scaleBias;
//texture information
uniform sampler2D colourMap;
uniform sampler2D normalMap;
uniform sampler2D specularMap;
uniform sampler2D heightMap;
uniform sampler2D glossMap;
//inputs from vertex shader stage
in VertexData
{
vec3 ts_L; //view vector tangent space
vec3 ts_V; //light vector tangent space
vec2 ex_TexCoord;
float dist;
} vertex;
//final fragment colour
layout(location = 0) out vec4 out_Color;
void main(void) {
//calculate halfway vector for blinn phong
vec3 Half = normalize( vertex.ts_V + vertex.ts_L );
//and create some temporary types algorithm will need
vec2 texCoord;
vec3 diffuseTexel ;
vec3 specularTexel;
float gloss;
vec3 normal;
//first sample texel value from height map
float height = texture( heightMap, vertex.ex_TexCoord.st ).r;
//-----------------------------------------------
// steep parallax
float start = 1.0;
int numsteps = 50;
float step = 1.0/numsteps;
vec2 offset = vertex.ex_TexCoord;
vec2 delta = -vertex.ts_V.xy * scaleBias.r / (vertex.ts_V.z * numsteps);
for (int i = 0; i < numsteps; i++)
{
if(height < start)
{
start-=step;
offset+=delta;
height = texture(heightMap,offset).r;
}
else
{
texCoord = offset;
break;
}
}
//---------------------------------------------------
//normal maps are encoded with values between 0.0 and 0.5 being negative, so need to remove the encoding.
//sample textures
diffuseTexel = texture(colourMap,texCoord.st).rgb;
specularTexel = texture(specularMap,texCoord.st).rgb;
normal = normalize(texture(normalMap,texCoord.st).rgb * 2.0 - 1.0);
gloss = texture(glossMap,texCoord.st).r;
//--------------------------------------------------
//Lighting -- Blinn/Phong Lighting with specular, normal and gloss mapping
float lambert = max( dot (normal, vertex.ts_L ), 0.0 );
vec3 litColour = vec3(0.0,0.0,0.0);
//if light is worth calculating
if (lambert > 0.0)
{
vec3 R = normalize(-reflect(vertex.ts_L,normal));
float specularPower = pow(max(dot(R,Half),0.0),material.shininess);
litColour += light.diffuse.xyz * material.diffuse.xyz * lambert;
litColour += light.specular.xyz * material.specular.xyz * specularPower * gloss;
float attenuation = 1.0 + (0.01 * vertex.dist*vertex.dist) + (0.01 * vertex.dist);
attenuation = 1.0/attenuation;
litColour *= attenuation;
}
out_Color = vec4( litColour *diffuseTexel*(specularTexel) ,1.0);
}
通过
计算正常矩阵transpose( inverse( modelview ) );
我可能错过了一些非常明显的东西,但我无法看到它,并会对一些意见表示感谢。
更新
我已经修改过以执行照明&amp;基于世界空间向量的偏移,现已产生以下结果:
照明现在是正确的,从近距离表面看法时视差很好,但......
视角与视角之间的角度正常增加,视差非常奇怪。
我再次感激你的帮助。
答案 0 :(得分:0)
vec3 ex_V = -position;
不应该是这样的:
vec3 ex_V = eyePosition - position;