Skip to content

Commit 41f1135

Browse files
aidinabediwilleastcottmvaligursky
authored
Detail Maps (playcanvas#1968)
* add vertexColor boolean parameter to _defineTex2D * fix minor bug regarding diffuseDetailMapChannel * add shader chunks for diffuseDetailMap and normalDetailMap * use new shader chunks in standard material * add normalDetailMapBumpiness * add constants pc.DETAILBLEND_COLORS_* and pc.DETAILBLEND_NORMALS_* * add diffuseDetailBlend and normalDetailBlend * optimize code generation for fragshader * add documentation for new material parameters and detail blend methods * add documentation for non-obvious blend implementations * normalize output of blendNormals_rnm * remove normalDetailBlend and enums * rename diffuseDetailBlend to diffuseDetailMode Co-authored-by: Will Eastcott <will@playcanvas.com> Co-authored-by: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com>
1 parent 017c629 commit 41f1135

11 files changed

+240
-53
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
vec3 detailMode_mul(vec3 c1, vec3 c2) {
2+
return c1 * c2;
3+
}
4+
5+
vec3 detailMode_add(vec3 c1, vec3 c2) {
6+
return c1 + c2;
7+
}
8+
9+
// https://en.wikipedia.org/wiki/Blend_modes#Screen
10+
vec3 detailMode_screen(vec3 c1, vec3 c2) {
11+
return 1.0 - (1.0 - c1)*(1.0 - c2);
12+
}
13+
14+
// https://en.wikipedia.org/wiki/Blend_modes#Overlay
15+
vec3 detailMode_overlay(vec3 c1, vec3 c2) {
16+
return mix(1.0 - 2.0*(1.0 - c1)*(1.0 - c2), 2.0*c1*c2, step(c1, vec3(0.5)));
17+
}
18+
19+
vec3 detailMode_min(vec3 c1, vec3 c2) {
20+
return min(c1, c2);
21+
}
22+
23+
vec3 detailMode_max(vec3 c1, vec3 c2) {
24+
return max(c1, c2);
25+
}
26+

src/graphics/program-lib/chunks/diffuse.frag

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ void getAlbedo() {
1414
#endif
1515

1616
#ifdef MAPTEXTURE
17-
dAlbedo *= texture2DSRGB(texture_diffuseMap, $UV).$CH;
17+
dAlbedo *= gammaCorrectInput(addAlbedoDetail(texture2D(texture_diffuseMap, $UV).$CH));
1818
#endif
1919

2020
#ifdef MAPVERTEX
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifdef MAPTEXTURE
2+
uniform sampler2D texture_diffuseDetailMap;
3+
#endif
4+
5+
vec3 addAlbedoDetail(vec3 albedo) {
6+
#ifdef MAPTEXTURE
7+
vec3 albedoDetail = vec3(texture2D(texture_diffuseDetailMap, $UV).$CH);
8+
return detailMode_$DETAILMODE(albedo, albedoDetail);
9+
#else
10+
return albedo;
11+
#endif
12+
}
13+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifdef MAPTEXTURE
2+
uniform sampler2D texture_normalDetailMap;
3+
uniform float material_normalDetailMapBumpiness;
4+
5+
vec3 blendNormals(vec3 n1, vec3 n2) {
6+
// https://blog.selfshadow.com/publications/blending-in-detail/#detail-oriented
7+
n1 += vec3(0, 0, 1);
8+
n2 *= vec3(-1, -1, 1);
9+
return normalize(n1*dot(n1, n2)/n1.z - n2);
10+
}
11+
#endif
12+
13+
vec3 addNormalDetail(vec3 normalMap) {
14+
#ifdef MAPTEXTURE
15+
vec3 normalDetailMap = unpackNormal(texture2D(texture_normalDetailMap, $UV));
16+
normalDetailMap = normalize(mix(vec3(0.0, 0.0, 1.0), normalDetailMap, material_normalDetailMapBumpiness));
17+
return blendNormals(normalMap, normalDetailMap);
18+
#else
19+
return normalMap;
20+
#endif
21+
}
22+

src/graphics/program-lib/chunks/normalMap.frag

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ uniform sampler2D texture_normalMap;
22
uniform float material_bumpiness;
33
void getNormal() {
44
vec3 normalMap = unpackNormal(texture2D(texture_normalMap, $UV));
5-
dNormalMap = normalMap;
6-
normalMap = mix(vec3(0.0, 0.0, 1.0), normalMap, material_bumpiness);
7-
dNormalW = normalize(dTBN * normalMap);
5+
normalMap = normalize(mix(vec3(0.0, 0.0, 1.0), normalMap, material_bumpiness));
6+
dNormalMap = addNormalDetail(normalMap);
7+
dNormalW = dTBN * dNormalMap;
88
#ifdef CLEARCOAT
99
ccNormalW = normalize(dVertexNormalW);
1010
#endif
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
uniform sampler2D texture_normalMap;
2-
uniform float material_bumpiness;
32
void getNormal() {
43
vec3 normalMap = unpackNormal(texture2D(texture_normalMap, $UV));
5-
dNormalMap = normalMap;
6-
dNormalW = dTBN * normalMap;
4+
dNormalMap = addNormalDetail(normalMap);
5+
dNormalW = dTBN * dNormalMap;
76
#ifdef CLEARCOAT
87
ccNormalW = normalize(dVertexNormalW);
9-
#endif
8+
#endif
109
}

src/graphics/program-lib/standard.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,12 @@ pc.programlib.standard = {
293293
var vertexColorChannelPropName = propName + "VertexColorChannel";
294294
var tintPropName = propName + "Tint";
295295
var vertexColorPropName = propName + "VertexColor";
296+
var detailModePropName = propName + "Mode";
296297

297298
var tintOption = options[tintPropName];
298299
var vertexColorOption = options[vertexColorPropName];
299300
var textureOption = options[mapPropName];
301+
var detailModeOption = options[detailModePropName];
300302

301303
var subCode = chunks[chunkName];
302304

@@ -315,6 +317,10 @@ pc.programlib.standard = {
315317
subCode = subCode.replace(/\$VC/g, options[vertexColorChannelPropName]);
316318
}
317319

320+
if (detailModeOption) {
321+
subCode = subCode.replace(/\$DETAILMODE/g, detailModeOption);
322+
}
323+
318324
var isFloatTint = (tintOption === 1);
319325
var isVecTint = (tintOption === 3);
320326

@@ -866,6 +872,10 @@ pc.programlib.standard = {
866872
// code += chunks.basePS;
867873
code = this._fsAddBaseCode(code, device, chunks, options);
868874

875+
if (options.detailModes) {
876+
code += chunks.detailModesPS;
877+
}
878+
869879
var codeBegin = code;
870880
code = "";
871881

@@ -952,6 +962,10 @@ pc.programlib.standard = {
952962
if (options.normalMap) {
953963
code += options.packedNormal ? chunks.normalXYPS : chunks.normalXYZPS;
954964

965+
if (options.normalDetail) {
966+
code += this._addMap("normalDetail", "normalDetailMapPS", options, chunks);
967+
}
968+
955969
var transformedNormalMapUv = this._getUvSourceExpression("normalMapTransform", "normalMapUv", options);
956970
if (options.normalizeNormalMap) {
957971
code += chunks.normalMapPS.replace(/\$UV/g, transformedNormalMapUv);
@@ -983,7 +997,12 @@ pc.programlib.standard = {
983997
code += options.skyboxIntensity ? chunks.envMultiplyPS : chunks.envConstPS;
984998
}
985999

1000+
if (options.diffuseDetail) {
1001+
code += this._addMap("diffuseDetail", "diffuseDetailMapPS", options, chunks);
1002+
}
1003+
9861004
code += this._addMap("diffuse", "diffusePS", options, chunks);
1005+
9871006
if (options.blendType !== pc.BLEND_NONE || options.alphaTest || options.alphaToCoverage) {
9881007
code += this._addMap("opacity", "opacityPS", options, chunks);
9891008
}

src/scene/materials/standard-material-options-builder.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ Object.assign(pc, function () {
123123
options.twoSidedLighting = stdMat.twoSidedLighting;
124124
options.pixelSnap = stdMat.pixelSnap;
125125
options.aoMapUv = stdMat.aoUvSet; // backwards componen
126+
options.diffuseDetail = !!stdMat.diffuseMap;
127+
options.normalDetail = !!stdMat.normalMap;
128+
options.diffuseDetailMode = stdMat.diffuseDetailMode;
129+
options.detailModes = !!options.diffuseDetail;
126130
};
127131

128132
StandardMaterialOptionsBuilder.prototype._updateEnvOptions = function (options, stdMat, scene, prefilteredCubeMap128) {

src/scene/materials/standard-material-parameters.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@
2727
diffuseMapUv: 'number',
2828
diffuseMapTiling: 'vec2',
2929
diffuseMapOffset: 'vec2',
30+
diffuseDetailMap: 'texture',
31+
diffuseDetailMapChannel: 'string',
32+
diffuseDetailMapUv: 'number',
33+
diffuseDetailMapTiling: 'vec2',
34+
diffuseDetailMapOffset: 'vec2',
35+
diffuseDetailMode: 'string',
3036

3137
specular: 'rgb',
3238
specularTint: 'boolean',
@@ -84,6 +90,11 @@
8490
normalMapUv: 'number',
8591
bumpiness: 'number',
8692
// normalMapFactor: 'number', // TODO rename bumpiness to normalMapFactor
93+
normalDetailMap: 'texture',
94+
normalDetailMapTiling: 'vec2',
95+
normalDetailMapOffset: 'vec2',
96+
normalDetailMapUv: 'number',
97+
normalDetailMapBumpiness: 'number',
8798

8899
heightMap: 'texture',
89100
heightMapChannel: 'string',

0 commit comments

Comments
 (0)