Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for compressed sRGB formats #6743

Merged
merged 7 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions examples/src/examples/graphics/shader-burn.shader.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ uniform sampler2D uDiffuseMap;
uniform sampler2D uHeightMap;
uniform float uTime;

vec3 gammaCorrectOutput(vec3 color) {
return pow(color + 0.0000001, vec3(1.0 / 2.2));
}

void main(void)
{
float height = texture2D(uHeightMap, vUv0).r;
vec4 color = texture2D(uDiffuseMap, vUv0);
vec4 linearColor = texture2D(uDiffuseMap, vUv0);
if (height < uTime) {
discard;
discard;
}
if (height < (uTime + uTime * 0.1)) {
color = vec4(1.0, 0.2, 0.0, 1.0);
linearColor = vec4(1.0, 0.02, 0.0, 1.0);
}
gl_FragColor = color;
gl_FragColor.rgb = gammaCorrectOutput(linearColor.rgb);
gl_FragColor.a = 1.0;
}
8 changes: 7 additions & 1 deletion examples/src/examples/graphics/shader-wobble.shader.frag
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ uniform sampler2D uDiffuseMap;

varying vec2 vUv0;

vec3 gammaCorrectOutput(vec3 color) {
return pow(color + 0.0000001, vec3(1.0 / 2.2));
}

void main(void)
{
gl_FragColor = texture2D(uDiffuseMap, vUv0);
vec4 linearColor = texture2D(uDiffuseMap, vUv0);
gl_FragColor.rgb = gammaCorrectOutput(linearColor.rgb);
gl_FragColor.a = 1.0;
}
2 changes: 1 addition & 1 deletion examples/src/examples/graphics/texture-basis.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pc.basisInitialize({
});

const assets = {
color: new pc.Asset('color', 'texture', { url: rootPath + '/static/assets/textures/seaside-rocks01-color.basis' }),
color: new pc.Asset('color', 'texture', { url: rootPath + '/static/assets/textures/seaside-rocks01-color.basis' }, { srgb: true }),
gloss: new pc.Asset('gloss', 'texture', { url: rootPath + '/static/assets/textures/seaside-rocks01-gloss.basis' }),
normal: new pc.Asset(
'normal',
Expand Down
8 changes: 4 additions & 4 deletions src/framework/handlers/basis-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function BasisWorker() {
};

// return true if the texture dimensions are valid for the target format
const dimensionsValid = (width, height, format, webgl2) => {
const dimensionsValid = (width, height, format) => {
switch (format) {
// etc1, 2
case BASIS_FORMAT.cTFETC1:
Expand All @@ -171,7 +171,7 @@ function BasisWorker() {
// pvrtc
case BASIS_FORMAT.cTFPVRTC1_4_RGB:
case BASIS_FORMAT.cTFPVRTC1_4_RGBA:
return isPOT(width, height) && ((width === height) || webgl2);
return isPOT(width, height);
// astc
case BASIS_FORMAT.cTFASTC_4x4:
return true;
Expand Down Expand Up @@ -221,7 +221,7 @@ function BasisWorker() {
basisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];

// if image dimensions don't work on target, fall back to uncompressed
if (!dimensionsValid(width, height, basisFormat, options.deviceDetails.webgl2)) {
if (!dimensionsValid(width, height, basisFormat)) {
basisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;
}
}
Expand Down Expand Up @@ -307,7 +307,7 @@ function BasisWorker() {
basisFormat = hasAlpha ? alphaMapping[format] : opaqueMapping[format];

// if image dimensions don't work on target, fall back to uncompressed
if (!dimensionsValid(width, height, basisFormat, options.deviceDetails.webgl2)) {
if (!dimensionsValid(width, height, basisFormat)) {
basisFormat = hasAlpha ? BASIS_FORMAT.cTFRGBA32 : BASIS_FORMAT.cTFRGB565;
}
}
Expand Down
1 change: 0 additions & 1 deletion src/framework/handlers/basis.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ function basisTranscode(device, url, data, callback, options) {

if (!deviceDetails) {
deviceDetails = {
webgl2: device.isWebGL2,
formats: getCompressionFormats(device)
};
}
Expand Down
42 changes: 37 additions & 5 deletions src/framework/parsers/glb-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2050,7 +2050,31 @@ const createImages = (gltf, bufferViews, urlBase, registry, options) => {
'image/vnd-ms.dds': 'dds'
};

const loadTexture = (gltfImage, url, bufferView, mimeType, options) => {
// a Set of image indices that use sRGB textures (base and emissive)
const getGammaTextures = (gltf) => {
const set = new Set();

if (gltf.hasOwnProperty('materials')) {
gltf.materials.forEach((gltfMaterial) => {

// base texture
if (gltfMaterial.hasOwnProperty('pbrMetallicRoughness')) {
const pbrData = gltfMaterial.pbrMetallicRoughness;
if (pbrData.hasOwnProperty('baseColorTexture')) {
set.add(pbrData.baseColorTexture.index);
}
}

// emissive
if (gltfMaterial.hasOwnProperty('emissiveTexture')) {
set.add(gltfMaterial.emissiveTexture.index);
}
});
}
return set;
};

const loadTexture = (gltfImage, url, bufferView, mimeType, options, srgb) => {
return new Promise((resolve, reject) => {
const continuation = (bufferViewData) => {
const name = (gltfImage.name || 'gltf-texture') + '-' + gltfTextureUniqueId++;
Expand All @@ -2070,7 +2094,9 @@ const createImages = (gltf, bufferViews, urlBase, registry, options) => {
}

// create and load the asset
const asset = new Asset(name, 'texture', file, null, options);
const data = { srgb };

const asset = new Asset(name, 'texture', file, data, options);
asset.on('load', asset => resolve(asset));
asset.on('error', err => reject(err));
registry.add(asset);
Expand All @@ -2085,6 +2111,8 @@ const createImages = (gltf, bufferViews, urlBase, registry, options) => {
});
};

const gammaTextures = getGammaTextures(gltf);

return gltf.images.map((gltfImage, i) => {
if (preprocess) {
preprocess(gltfImage);
Expand All @@ -2108,17 +2136,21 @@ const createImages = (gltf, bufferViews, urlBase, registry, options) => {
}

promise = promise.then((textureAsset) => {

// if the image uses sRGB, pass it as an option to the texture creation
const srgb = gammaTextures.has(i);

if (textureAsset) {
return textureAsset;
} else if (gltfImage.hasOwnProperty('uri')) {
// uri specified
if (isDataURI(gltfImage.uri)) {
return loadTexture(gltfImage, gltfImage.uri, null, getDataURIMimeType(gltfImage.uri), null);
return loadTexture(gltfImage, gltfImage.uri, null, getDataURIMimeType(gltfImage.uri), null, srgb);
}
return loadTexture(gltfImage, ABSOLUTE_URL.test(gltfImage.uri) ? gltfImage.uri : path.join(urlBase, gltfImage.uri), null, null, { crossOrigin: 'anonymous' });
return loadTexture(gltfImage, ABSOLUTE_URL.test(gltfImage.uri) ? gltfImage.uri : path.join(urlBase, gltfImage.uri), null, null, { crossOrigin: 'anonymous' }, srgb);
} else if (gltfImage.hasOwnProperty('bufferView') && gltfImage.hasOwnProperty('mimeType')) {
// bufferview
return loadTexture(gltfImage, null, bufferViews[gltfImage.bufferView], gltfImage.mimeType, null);
return loadTexture(gltfImage, null, bufferViews[gltfImage.bufferView], gltfImage.mimeType, null, srgb);
}

// fail
Expand Down
5 changes: 3 additions & 2 deletions src/framework/parsers/texture/basis.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ADDRESS_CLAMP_TO_EDGE, ADDRESS_REPEAT, TEXHINT_ASSET } from '../../../platform/graphics/constants.js';
import { ADDRESS_CLAMP_TO_EDGE, ADDRESS_REPEAT, TEXHINT_ASSET, pixelFormatLinearToGamma } from '../../../platform/graphics/constants.js';
import { Texture } from '../../../platform/graphics/texture.js';

import { Asset } from '../../asset/asset.js';
Expand Down Expand Up @@ -46,6 +46,7 @@ class BasisParser extends TextureParser {

// our async transcode call provides the neat structure we need to create the texture instance
open(url, data, device, textureOptions = {}) {
const format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;
mvaligursky marked this conversation as resolved.
Show resolved Hide resolved
const texture = new Texture(device, {
name: url,
// #if _PROFILER
Expand All @@ -55,7 +56,7 @@ class BasisParser extends TextureParser {
addressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,
width: data.width,
height: data.height,
format: data.format,
format: format,
cubemap: data.cubemap,
levels: data.levels,

Expand Down
10 changes: 6 additions & 4 deletions src/framework/parsers/texture/ktx.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
PIXELFORMAT_PVRTC_4BPP_RGB_1, PIXELFORMAT_PVRTC_2BPP_RGB_1, PIXELFORMAT_PVRTC_4BPP_RGBA_1, PIXELFORMAT_PVRTC_2BPP_RGBA_1,
PIXELFORMAT_RGB8, PIXELFORMAT_RGBA8, PIXELFORMAT_SRGB8, PIXELFORMAT_SRGBA8,
PIXELFORMAT_111110F, PIXELFORMAT_RGB16F, PIXELFORMAT_RGBA16F,
TEXHINT_ASSET
TEXHINT_ASSET,
pixelFormatLinearToGamma
} from '../../../platform/graphics/constants.js';
import { Texture } from '../../../platform/graphics/texture.js';

Expand All @@ -32,8 +33,8 @@ const KNOWN_FORMATS = {
0x8C03: PIXELFORMAT_PVRTC_2BPP_RGBA_1,

// uncompressed formats
0x8051: PIXELFORMAT_RGB8, // GL_RGB8
0x8058: PIXELFORMAT_RGBA8, // GL_RGBA8
0x8051: PIXELFORMAT_RGB8, // GL_RGB8
0x8058: PIXELFORMAT_RGBA8, // GL_RGBA8
0x8C41: PIXELFORMAT_SRGB8, // GL_SRGB8
0x8C43: PIXELFORMAT_SRGBA8, // GL_SRGB8_ALPHA8
0x8C3A: PIXELFORMAT_111110F, // GL_R11F_G11F_B10F
Expand Down Expand Up @@ -69,6 +70,7 @@ class KtxParser extends TextureParser {
return null;
}

const format = textureOptions.srgb ? pixelFormatLinearToGamma(textureData.format) : textureData.format;
const texture = new Texture(device, {
name: url,
// #if _PROFILER
Expand All @@ -78,7 +80,7 @@ class KtxParser extends TextureParser {
addressV: textureData.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,
width: textureData.width,
height: textureData.height,
format: textureData.format,
format: format,
cubemap: textureData.cubemap,
levels: textureData.levels,

Expand Down
5 changes: 3 additions & 2 deletions src/framework/parsers/texture/ktx2.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Debug } from '../../../core/debug.js';
import { ReadStream } from '../../../core/read-stream.js';

import { ADDRESS_CLAMP_TO_EDGE, ADDRESS_REPEAT, TEXHINT_ASSET } from '../../../platform/graphics/constants.js';
import { ADDRESS_CLAMP_TO_EDGE, ADDRESS_REPEAT, TEXHINT_ASSET, pixelFormatLinearToGamma } from '../../../platform/graphics/constants.js';
import { Texture } from '../../../platform/graphics/texture.js';

import { Asset } from '../../asset/asset.js';
Expand Down Expand Up @@ -37,6 +37,7 @@ class Ktx2Parser extends TextureParser {
}

open(url, data, device, textureOptions = {}) {
const format = textureOptions.srgb ? pixelFormatLinearToGamma(data.format) : data.format;
const texture = new Texture(device, {
name: url,
// #if _PROFILER
Expand All @@ -46,7 +47,7 @@ class Ktx2Parser extends TextureParser {
addressV: data.cubemap ? ADDRESS_CLAMP_TO_EDGE : ADDRESS_REPEAT,
width: data.width,
height: data.height,
format: data.format,
format: format,
cubemap: data.cubemap,
levels: data.levels,

Expand Down
Loading