add initial normalmaps support

This commit is contained in:
Ivan Avdeev 2021-11-17 09:43:10 -08:00
parent 311e6214c8
commit 6df830dd0a
9 changed files with 67 additions and 7 deletions

View File

@ -63,6 +63,10 @@ vec4 sampleTexture(uint tex_index, vec2 uv, vec4 uv_lods) {
return textureGrad(textures[nonuniformEXT(tex_index)], uv, uv_lods.xy, uv_lods.zw);
}
vec3 baryMix(vec3 v1, vec3 v2, vec3 v3, vec2 bary) {
return v1 * (1. - bary.x - bary.y) + v2 * bary.x + v3 * bary.y;
}
void main() {
payload.t_offset += gl_HitTEXT;
@ -82,7 +86,7 @@ void main() {
// TODO use already inverse gl_WorldToObject ?
const mat3 matWorldRotation = mat3(gl_ObjectToWorldEXT);
const mat3 normalTransformMat = transpose(inverse(matWorldRotation));
const vec3 normal = normalize(normalTransformMat * (n1 * (1. - bary.x - bary.y) + n2 * bary.x + n3 * bary.y));
vec3 normal = normalize(normalTransformMat * (n1 * (1. - bary.x - bary.y) + n2 * bary.x + n3 * bary.y));
const vec2 uvs[3] = {
vertices[vi1].gl_tc,
@ -108,7 +112,7 @@ void main() {
const float ray_cone_width = payload.pixel_cone_spread_angle * payload.t_offset;
vec4 uv_lods;
computeAnisotropicEllipseAxes(hit_pos, normal, gl_WorldRayDirectionEXT, ray_cone_width, pos, uvs, texture_uv_stationary, uv_lods.xy, uv_lods.zw);
computeAnisotropicEllipseAxes(hit_pos, /* TODO geom_?*/ normal, gl_WorldRayDirectionEXT, ray_cone_width, pos, uvs, texture_uv_stationary, uv_lods.xy, uv_lods.zw);
const uint tex_index = kusochki[kusok_index].tex_base_color;
const vec4 tex_color = sampleTexture(tex_index, texture_uv, uv_lods);
@ -117,12 +121,24 @@ void main() {
/* tex_color = pow(tex_color, vec4(2.)); */
/* const vec3 base_color = tex_color.rgb; */
normal *= geom_normal_sign;
const uint tex_normal = kusochki[kusok_index].tex_normalmap;
vec3 T = baryMix(vertices[vi1].tangent, vertices[vi2].tangent, vertices[vi3].tangent, bary);
if (tex_normal > 0 && dot(T,T) > .5) {
T = normalize(normalTransformMat * T);
T = normalize(T - dot(T, normal) * normal);
const vec3 B = normalize(cross(normal, T));
const mat3 TBN = mat3(T, B, normal);
const vec3 tnorm = sampleTexture(tex_normal, texture_uv, uv_lods).xyz * 2. - 1.; // TODO is this sampling correct for normal data?
normal = normalize(TBN * tnorm);
}
// FIXME read alpha from texture
payload.hit_pos_t = vec4(hit_pos, gl_HitTEXT);
payload.base_color = base_color * kusochki[kusok_index].color.rgb;
payload.transmissiveness = (1. - tex_color.a * kusochki[kusok_index].color.a);
payload.normal = normal * geom_normal_sign;
payload.normal = normal;
payload.geometry_normal = geom_normal;
payload.emissive = kusochki[kusok_index].emissive * base_color; // TODO emissive should have a special texture
payload.kusok_index = kusok_index;

View File

@ -422,6 +422,13 @@ void main() {
imageStore(out_image_base_color, ivec2(gl_LaunchIDEXT.xy), vec4(payload_opaque.base_color, 0.));
imageStore(out_image_normals, ivec2(gl_LaunchIDEXT.xy), vec4(geometryNormal.xy, shadingNormal.xy));
payload_opaque.base_color = vec3(1.);
#if 0
imageStore(out_image_diffuse_gi, ivec2(gl_LaunchIDEXT.xy), vec4(0));
imageStore(out_image_specular, ivec2(gl_LaunchIDEXT.xy), vec4(0.));
imageStore(out_image_additive, ivec2(gl_LaunchIDEXT.xy), vec4(clamp(payload_opaque.normal, vec3(0.), vec3(1.)), 0.));
return;
#endif
}
// TODO should we do this after reflect/transmit decision?

View File

@ -8,6 +8,7 @@
struct Vertex {
vec3 pos;
vec3 normal;
vec3 tangent;
vec2 gl_tc;
vec2 _unused_lm_tc;

View File

@ -456,6 +456,9 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
vk_render_geometry_t *model_geometry = bmodel->render_model.geometries + num_geometries;
const float sample_size = gEngine.Mod_SampleSizeForFace( surf );
int index_count = 0;
vec3_t pos[3];
vec2_t uv[3];
vec3_t tangent;
if (!renderableSurface(surf, -1))
continue;
@ -511,6 +514,18 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
vertex.gl_tc[0] = s;
vertex.gl_tc[1] = t;
// TODO replace this with constructing tangent from surf->texinfo->vecs
if (k < 3) {
VectorCopy(vertex.pos, pos[k]);
Vector2Copy(vertex.gl_tc, uv[k]);
if (k == 2) {
computeTangent(tangent, pos[0], pos[1], pos[2], uv[0], uv[1], uv[2]);
VectorCopy(tangent, bvert[-1].tangent);
VectorCopy(tangent, bvert[-2].tangent);
}
}
VectorCopy(tangent, vertex.tangent);
// lightmap texture coordinates
s = DotProduct( in_vertex->position, info->lmvecs[0] ) + info->lmvecs[0][3];
s -= info->lightmapmins[0];

View File

@ -54,7 +54,7 @@ static void loadMaterialsFromFile( const char *filename ) {
.base_color = -1,
.metalness = tglob.blackTexture,
.roughness = tglob.whiteTexture,
.normalmap = tglob.grayTexture,
.normalmap = 0,
};
int current_material_index = -1;
@ -80,7 +80,7 @@ static void loadMaterialsFromFile( const char *filename ) {
.base_color = -1,
.metalness = tglob.blackTexture,
.roughness = tglob.whiteTexture,
.normalmap = tglob.grayTexture,
.normalmap = 0,
};
continue;
}
@ -105,7 +105,7 @@ static void loadMaterialsFromFile( const char *filename ) {
} else if (Q_stricmp(key, "normal_map") == 0) {
if ((current_material.normalmap = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load normal_map texture %s\n", value);
current_material.normalmap = tglob.grayTexture;
current_material.normalmap = 0;
}
} else if (Q_stricmp(key, "metal_map") == 0) {
if ((current_material.metalness = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
@ -138,7 +138,7 @@ void XVK_ReloadMaterials( void ) {
mat->base_color = i;
mat->metalness = tglob.blackTexture;
mat->roughness = tglob.whiteTexture;
mat->normalmap = tglob.grayTexture;
mat->normalmap = 0;
}
loadMaterialsFromFile( "pbr/materials.mat" );

View File

@ -266,3 +266,19 @@ void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z )
Matrix4x4_CreateScale3( temp, x, y, z );
Matrix4x4_Concat( out, base, temp );
}
void computeTangent(vec3_t out_tangent, vec3_t v0, vec3_t v1, vec3_t v2, vec2_t uv0, vec2_t uv1, vec2_t uv2) {
vec3_t e1, e2;
vec2_t duv1, duv2;
float f;
VectorSubtract(v1, v0, e1);
VectorSubtract(v2, v0, e2);
Vector2Subtract(uv1, uv0, duv1);
Vector2Subtract(uv2, uv0, duv2);
f = 1.f / (duv1[0] * duv2[1] - duv1[1] * duv2[0]);
out_tangent[0] = f * (duv2[1] * e1[0] - duv1[1] * e2[0]);
out_tangent[1] = f * (duv2[1] * e1[1] - duv1[1] * e2[1]);
out_tangent[2] = f * (duv2[1] * e1[2] - duv1[1] * e2[2]);
}

View File

@ -20,3 +20,5 @@ void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z );
void Matrix4x4_CreateProjection(matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar);
void Matrix4x4_CreateOrtho(matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar);
void Matrix4x4_CreateModelview( matrix4x4 out );
void computeTangent(vec3_t out_tangent, vec3_t v0, vec3_t v1, vec3_t v2, vec2_t uv0, vec2_t uv1, vec2_t uv2);

View File

@ -51,6 +51,7 @@ typedef struct vk_vertex_s {
// TODO padding needed for storage buffer reading, figure out how to fix in GLSL/SPV side
vec3_t pos; float p0_;
vec3_t normal; uint32_t flags;
vec3_t tangent; uint32_t p1_;
vec2_t gl_tc; //float p2_[2];
vec2_t lm_tc; //float p3_[2];

View File

@ -42,6 +42,8 @@ void VK_SceneInit( void )
{
g_lists.draw_list = g_lists.draw_stack;
g_lists.draw_stack_pos = 0;
gEngine.Cmd_AddCommand("vk_rtx_reload_materials", XVK_ReloadMaterials, "Reload PBR materials");
}
#define R_ModelOpaque( rm ) ( rm == kRenderNormal )