Skip to content

Commit

Permalink
UPBGE: Fix parallax and normal tangent.
Browse files Browse the repository at this point in the history
Previously the tangent was not changed when the texture
was rotated using the "rotation" value in texture panel.

Because this vector was not rotated along the face normal it
caused the normal mapping to not change the shading what ever
the orientation and it caused parallax to use odd workaround
to counter the wrong tangent vector.

When the tangent is properly rotated around the normal thanks
to the function mtex_tangent_rotate, this tangent is sent to the
parallax and normal function as it.

In consideration the size and mat attributes are not anymore sent
to the parallax function.

Note that the function mtex_mapping_transform now construct the
matrix internally and justify the erasing of math_rot_mat.
  • Loading branch information
panzergame committed Jul 29, 2017
1 parent 73c3843 commit a60c590
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 38 deletions.
56 changes: 32 additions & 24 deletions source/blender/gpu/intern/gpu_material.c
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ static void do_material_tex(GPUShadeInput *shi)
GPUMaterial *mat = shi->gpumat;
MTex *mtex;
Tex *tex;
GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac, *rotmat;
GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac, *tangent;
GPUNodeLink *texco_norm, *texco_orco, *texco_object;
GPUNodeLink *texco_global, *texco_uv = NULL;
GPUNodeLink *newnor, *orn;
Expand Down Expand Up @@ -1332,31 +1332,35 @@ static void do_material_tex(GPUShadeInput *shi)
if (ma->mtex[tex_nr]) {
mtex = ma->mtex[tex_nr];
tex = mtex->tex;
if (tex == NULL || !((mtex->texflag & MTEX_PARALLAX_UV) || (mtex->mapto & MAP_PARALLAX)) || mtex->texco != TEXCO_UV) {

if (tex == NULL || !(mtex->mapto & MAP_PARALLAX)) {
continue;
}

GPU_link(mat, "mtex_tangent_rotate", GPU_attribute(CD_TANGENT, ""), orn,
GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma),
&tangent);

GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
texco = texco_uv;

if (mtex->mapto & MAP_PARALLAX) {
GPU_link(mat, "mat_math_rot", GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma), &rotmat);
GPU_link(mat, "mtex_mapping_transform", texco, rotmat,
GPU_select_uniform(mtex->ofs, GPU_DYNAMIC_TEX_UVOFFSET, NULL, ma),
GPU_select_uniform(mtex->size, GPU_DYNAMIC_TEX_UVSIZE, NULL, ma),
&texco);

discard = (mtex->parflag & MTEX_DISCARD_AT_EDGES) != 0 ? 1.0f : 0.0f;
GPU_link(mat, "parallax_out", texco,
GPU_builtin(GPU_VIEW_POSITION), GPU_attribute(CD_TANGENT, ""),
GPU_builtin(GPU_VIEW_NORMAL),
GPU_select_uniform(mtex->size, GPU_DYNAMIC_TEX_UVSIZE, NULL, ma), rotmat,
GPU_image(tex->ima, &tex->iuser, false),
GPU_select_uniform(&mtex->parallaxsteps, GPU_DYNAMIC_TEX_PARALLAXSTEP, NULL, ma),
GPU_select_uniform(&mtex->parallaxbumpsc, GPU_DYNAMIC_TEX_PARALLAXBUMP, NULL, ma),
GPU_uniform(&discard),
&parco);
}
GPU_link(mat, "mtex_mapping_transform", texco,
GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma),
GPU_select_uniform(mtex->ofs, GPU_DYNAMIC_TEX_UVOFFSET, NULL, ma),
GPU_select_uniform(mtex->size, GPU_DYNAMIC_TEX_UVSIZE, NULL, ma),
&texco);

discard = (mtex->parflag & MTEX_DISCARD_AT_EDGES) != 0 ? 1.0f : 0.0f;
GPU_link(mat, "mtex_parallax", texco,
GPU_builtin(GPU_VIEW_POSITION), tangent, orn,
GPU_image(tex->ima, &tex->iuser, false),
GPU_select_uniform(&mtex->parallaxsteps, GPU_DYNAMIC_TEX_PARALLAXSTEP, NULL, ma),
GPU_select_uniform(&mtex->parallaxbumpsc, GPU_DYNAMIC_TEX_PARALLAXBUMP, NULL, ma),
GPU_uniform(&discard),
&parco);

// only one parallax per material.
break;
}
}

Expand Down Expand Up @@ -1410,8 +1414,8 @@ static void do_material_tex(GPUShadeInput *shi)
(mtex->ofs[0] == 0.0f || mtex->ofs[1] == 0.0f) ||
(mtex->rot != 0.0f)))
{
GPU_link(mat, "mat_math_rot", GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma), &rotmat);
GPU_link(mat, "mtex_mapping_transform", texco, rotmat,
GPU_link(mat, "mtex_mapping_transform", texco,
GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma),
GPU_select_uniform(mtex->ofs, GPU_DYNAMIC_TEX_UVOFFSET, NULL, ma),
GPU_select_uniform(mtex->size, GPU_DYNAMIC_TEX_UVSIZE, NULL, ma),
&texco);
Expand Down Expand Up @@ -1547,18 +1551,22 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor);

if (mtex->normapspace == MTEX_NSPACE_TANGENT) {
GPU_link(mat, "mtex_tangent_rotate", GPU_attribute(CD_TANGENT, ""), orn,
GPU_select_uniform(&mtex->rot, GPU_DYNAMIC_TEX_UVROTATION, NULL, ma),
&tangent);

if (iFirstTimeNMap != 0) {
// use unnormalized normal (this is how we bake it - closer to gamedev)
GPUNodeLink *vNegNorm;
GPU_link(mat, "vec_math_negate",
GPU_builtin(GPU_VIEW_NORMAL), &vNegNorm);
GPU_link(mat, "mtex_nspace_tangent",
GPU_attribute(CD_TANGENT, ""), vNegNorm, tnor, &newnor);
tangent, vNegNorm, tnor, &newnor);
iFirstTimeNMap = 0;
}
else { /* otherwise use accumulated perturbations */
GPU_link(mat, "mtex_nspace_tangent",
GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor);
tangent, shi->vn, tnor, &newnor);
}
}
else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
Expand Down
34 changes: 20 additions & 14 deletions source/blender/gpu/shaders/gpu_shader_material.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -494,13 +494,6 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
outdot = dot(normalize(dir), nor);
}

void mat_math_rot(float rot, out mat3 mat)
{
mat = mat3(cos(rot), -sin(rot), 0.0,
sin(rot), cos(rot), 0.0,
0.0, 0.0, 1.0);
}

void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
Expand Down Expand Up @@ -1384,14 +1377,25 @@ void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
outtexco = texco + ofs;
}

void mtex_tangent_rotate(vec4 tangent, vec3 n, float rot, out vec4 outtangent)
{
float cosr = cos(rot);
float sinr = sin(rot);
outtangent.xyz = tangent.xyz * cosr + cross(tangent.xyz, n) * sinr - n * dot(tangent.xyz, n) * (1.0 - cosr);
outtangent.w = tangent.w;
}

void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
{
outtexco = size * texco;
}

void mtex_mapping_transform(vec3 texco, mat3 mat, vec3 ofs, vec3 size, out vec3 outtexco)
void mtex_mapping_transform(vec3 texco, float rot, vec3 ofs, vec3 size, out vec3 outtexco)
{
outtexco = (texco - vec3(0.5)) * mat * size + vec3(0.5) + ofs;
mat2 mat = mat2(cos(rot), -sin(rot),
sin(rot), cos(rot));

outtexco = vec3((texco.xy - vec2(0.5)) * mat, texco.z - 0.5) * size + vec3(0.5) + ofs;
}

void mtex_2d_mapping(vec3 vec, out vec3 outvec)
Expand Down Expand Up @@ -4042,15 +4046,17 @@ void node_output_world(vec4 surface, vec4 volume, out vec4 result)
result = surface;
}

void parallax_out(vec3 texco, vec3 vp, vec4 tangent, vec3 vn, vec3 size, mat3 mat, sampler2D ima, float numsteps,
void mtex_parallax(vec3 texco, vec3 vp, vec4 tangent, vec3 vn, sampler2D ima, float numsteps,
float bumpscale, float discarduv, out vec3 ptexcoord)
{
// Compute binormal/bitangent from tangent and normal.
vec3 binormal = cross(-vn, tangent.xyz) * tangent.w;
// Transform the fragment position in texture space.
vec3 vvec = vec3(dot(tangent.xyz, vp), dot(binormal, vp), dot(-vn, vp));
vec3 vv = normalize(vvec);

// The uv shift per depth step, multitply by rotation and after size.
vec2 delta = (vec3(-vv.x, gl_FrontFacing ? vv.y : -vv.y, 0.0) * mat * size * bumpscale / vv.z).xy;
// The uv shift per depth step.
vec2 delta = (vec3(-vv.x, gl_FrontFacing ? vv.y : -vv.y, 0.0) * bumpscale / vv.z).xy;

float height = 0.0;

Expand Down Expand Up @@ -4103,8 +4109,8 @@ void parallax_out(vec3 texco, vec3 vp, vec4 tangent, vec3 vn, vec3 size, mat3 ma
const vec2 clampmax = vec2(0.5);

if ((discarduv == 1.0) &&
(finaltexuv.x - 0.5 < clampmin.x * size.x || finaltexuv.x - 0.5 > clampmax.x * size.x ||
finaltexuv.y - 0.5 < clampmin.y * size.y || finaltexuv.y - 0.5 > clampmax.y * size.y))
(finaltexuv.x - 0.5 < clampmin.x || finaltexuv.x - 0.5 > clampmax.x ||
finaltexuv.y - 0.5 < clampmin.y || finaltexuv.y - 0.5 > clampmax.y))
{
discard;
}
Expand Down

0 comments on commit a60c590

Please sign in to comment.