Skip to content

Commit

Permalink
Add color space (#543)
Browse files Browse the repository at this point in the history
* feat: add engine settings
  • Loading branch information
GuoLei1990 authored Oct 25, 2021
1 parent b1b2878 commit 60c6f80
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 28 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/Camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ export class Camera extends Component {

// union scene and camera macro.
ShaderMacroCollection.unionCollection(
this.scene.shaderData._macroCollection,
this.scene._globalShaderMacro,
this.shaderData._macroCollection,
this._globalShaderMacro
);
Expand Down
34 changes: 28 additions & 6 deletions packages/core/src/Engine.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { IPhysics } from "@oasis-engine/design";
import { ColorSpace } from ".";
import { ResourceManager } from "./asset/ResourceManager";
import { Event, EventDispatcher, Logger, Time } from "./base";
import { Canvas } from "./Canvas";
import { ComponentsManager } from "./ComponentsManager";
import { EngineFeature } from "./EngineFeature";
import { EngineSettings } from "./EngineSettings";
import { Entity } from "./Entity";
import { FeatureManager } from "./FeatureManager";
import { InputManager } from "./input/InputManager";
import { RenderQueueType } from "./material/enums/RenderQueueType";
import { Material } from "./material/Material";
import { ModelMesh, PrimitiveMesh } from "./mesh";
import { PhysicsManager } from "./physics";
import { IHardwareRenderer } from "./renderingHardwareInterface/IHardwareRenderer";
import { ClassPool } from "./RenderPipeline/ClassPool";
import { RenderContext } from "./RenderPipeline/RenderContext";
Expand All @@ -16,20 +22,18 @@ import { SpriteMaskElement } from "./RenderPipeline/SpriteMaskElement";
import { SpriteMaskManager } from "./RenderPipeline/SpriteMaskManager";
import { Scene } from "./Scene";
import { SceneManager } from "./SceneManager";
import { CompareFunction } from "./shader";
import { BlendFactor } from "./shader/enums/BlendFactor";
import { BlendOperation } from "./shader/enums/BlendOperation";
import { ColorWriteMask } from "./shader/enums/ColorWriteMask";
import { CullMode } from "./shader/enums/CullMode";
import { Shader } from "./shader/Shader";
import { ShaderMacro } from "./shader/ShaderMacro";
import { ShaderMacroCollection } from "./shader/ShaderMacroCollection";
import { ShaderPool } from "./shader/ShaderPool";
import { ShaderProgramPool } from "./shader/ShaderProgramPool";
import { RenderState } from "./shader/state/RenderState";
import { Texture2D, TextureCubeFace, TextureCubeMap, TextureFormat } from "./texture";
import { ModelMesh, PrimitiveMesh } from "./mesh";
import { CompareFunction } from "./shader";
import { InputManager } from "./input/InputManager";
import { IPhysics } from "@oasis-engine/design";
import { PhysicsManager } from "./physics";

/** TODO: delete */
const engineFeatureManager = new FeatureManager<EngineFeature>();
Expand All @@ -39,6 +43,9 @@ ShaderPool.init();
* Engine.
*/
export class Engine extends EventDispatcher {
/** @internal */
static _gammaMacro: ShaderMacro = Shader.getMacroByName("OASIS_COLORSPACE_GAMMA");

/** Physics manager of Engine. */
readonly physicsManager: PhysicsManager;

Expand Down Expand Up @@ -68,8 +75,12 @@ export class Engine extends EventDispatcher {
_spriteMaskManager: SpriteMaskManager;
/** @internal */
_inputManager: InputManager;
/** @internal */
_macroCollection: ShaderMacroCollection = new ShaderMacroCollection();

protected _canvas: Canvas;

private _settings: EngineSettings = {};
private _resourceManager: ResourceManager = new ResourceManager(this);
private _sceneManager: SceneManager = new SceneManager(this);
private _vSyncCount: number = 1;
Expand All @@ -94,6 +105,13 @@ export class Engine extends EventDispatcher {
}
};

/**
* Settings of Engine.
*/
get settings(): Readonly<EngineSettings> {
return this._settings;
}

/**
* The canvas to use for rendering.
*/
Expand Down Expand Up @@ -163,7 +181,7 @@ export class Engine extends EventDispatcher {
* @param hardwareRenderer - Graphics API renderer
* @param physics - native physics Engine
*/
constructor(canvas: Canvas, hardwareRenderer: IHardwareRenderer, physics?: IPhysics) {
constructor(canvas: Canvas, hardwareRenderer: IHardwareRenderer, physics?: IPhysics, settings?: EngineSettings) {
super(null);
this._hardwareRenderer = hardwareRenderer;
this._hardwareRenderer.init(canvas);
Expand Down Expand Up @@ -206,6 +224,10 @@ export class Engine extends EventDispatcher {

this._backgroundTextureMesh = PrimitiveMesh.createPlane(this, 2, 2, 1, 1, false);
this._backgroundTextureMesh.isGCIgnored = true;

const colorSpace = settings?.colorSpace || ColorSpace.Linear;
colorSpace === ColorSpace.Gamma && this._macroCollection.enable(Engine._gammaMacro);
this._settings.colorSpace = colorSpace;
}

/**
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/EngineSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ColorSpace } from "./enums/ColorSpace";

/**
* Render settings.
*/
export interface EngineSettings {
/** Color space.*/
colorSpace?: ColorSpace;
}
16 changes: 12 additions & 4 deletions packages/core/src/Scene.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { Vector3 } from "@oasis-engine/math";
import { Background } from "./Background";
import { EngineObject, GLCapabilityType, Logger } from "./base";
import { EngineObject, Logger } from "./base";
import { Camera } from "./Camera";
import { Engine } from "./Engine";
import { Entity } from "./Entity";
import { FeatureManager } from "./FeatureManager";
import { Layer } from "./Layer";
import { AmbientLight } from "./lighting/AmbientLight";
import { LightFeature } from "./lighting/LightFeature";
import { SceneFeature } from "./SceneFeature";
import { ShaderDataGroup } from "./shader/enums/ShaderDataGroup";
import { ShaderData } from "./shader/ShaderData";
import { ShaderMacroCollection } from "./shader/ShaderMacroCollection";

/**
* Scene.
Expand All @@ -33,6 +32,8 @@ export class Scene extends EngineObject {
_activeCameras: Camera[] = [];
/** @internal */
_isActiveInEngine: boolean = false;
/** @internal */
_globalShaderMacro: ShaderMacroCollection = new ShaderMacroCollection();

private _destroyed: boolean = false;
private _rootEntities: Entity[] = [];
Expand Down Expand Up @@ -239,7 +240,14 @@ export class Scene extends EngineObject {
/**
* @internal
*/
_updateShaderData() {
_updateShaderData(): void {
// union scene and camera macro.
ShaderMacroCollection.unionCollection(
this.engine._macroCollection,
this.shaderData._macroCollection,
this._globalShaderMacro
);

const lightMgr = this.findFeature(LightFeature);

lightMgr._updateShaderData(this.shaderData);
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/enums/ColorSpace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Color Space.
*/
export enum ColorSpace {
/** Linear color space. */
Linear,
/** Gamma color space. */
Gamma
}
3 changes: 3 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export { dependencies } from "./ComponentsDependencies";
export { Camera } from "./Camera";
export { Transform } from "./Transform";
export { UpdateFlag } from "./UpdateFlag";
export type { EngineSettings } from "./EngineSettings";

export { request } from "./asset/request";
export { Loader } from "./asset/Loader";
export { ResourceManager, resourceLoader } from "./asset/ResourceManager";
Expand All @@ -39,6 +41,7 @@ Scene.registerFeature(LightFeature);
export { Background } from "./Background";
export { BackgroundMode } from "./enums/BackgroundMode";
export { CameraClearFlags } from "./enums/CameraClearFlags";
export { ColorSpace } from "./enums/ColorSpace";
export * from "./lighting/index";
export * from "./material/index";
export * from "./texture/index";
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/shader/ShaderData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class ShaderData implements IRefObject, IClone {
_properties: Record<number, ShaderPropertyValueType> = Object.create(null);
/** @internal */
_macroCollection: ShaderMacroCollection = new ShaderMacroCollection();


private _variableMacros: Record<string, string> = Object.create(null);
private _refCount: number = 0;
Expand Down
48 changes: 39 additions & 9 deletions packages/core/src/shader/ShaderUniform.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Color, Matrix, Vector2, Vector3, Vector4 } from "@oasis-engine/math";
import { Engine } from "../Engine";
import { ColorSpace } from "../enums/ColorSpace";
import { IHardwareRenderer } from "../renderingHardwareInterface/IHardwareRenderer";
import { Texture } from "../texture/Texture";
import { ShaderPropertyValueType } from "./ShaderData";
Expand All @@ -19,11 +20,13 @@ export class ShaderUniform {

private _rhi: IHardwareRenderer;
private _gl: WebGLRenderingContext;
private _colorSpace: ColorSpace;

constructor(engine: Engine) {
const rhi = engine._hardwareRenderer;
this._rhi = rhi;
this._gl = rhi.gl;
this._colorSpace = engine.settings.colorSpace;
}

upload1f(shaderUniform: ShaderUniform, value: number): void {
Expand All @@ -41,7 +44,15 @@ export class ShaderUniform {
const cacheValue = <Vector2>this.cacheValue;
if ((<Color>value).r !== undefined) {
if (cacheValue.x !== (<Color>value).r || cacheValue.y !== (<Color>value).g) {
this._gl.uniform2f(shaderUniform.location, (<Color>value).r, (<Color>value).g);
if (this._colorSpace === ColorSpace.Linear) {
this._gl.uniform2f(
shaderUniform.location,
Color.gammaToLinearSpace((<Color>value).r),
Color.gammaToLinearSpace((<Color>value).g)
);
} else {
this._gl.uniform2f(shaderUniform.location, (<Color>value).r, (<Color>value).g);
}
cacheValue.x = (<Color>value).r;
cacheValue.y = (<Color>value).g;
}
Expand All @@ -62,7 +73,16 @@ export class ShaderUniform {
const cacheValue = <Vector3>this.cacheValue;
if ((<Color>value).r !== undefined) {
if (cacheValue.x !== (<Color>value).r || cacheValue.y !== (<Color>value).g || cacheValue.z !== (<Color>value).b) {
this._gl.uniform3f(shaderUniform.location, (<Color>value).r, (<Color>value).g, (<Color>value).b);
if (this._colorSpace === ColorSpace.Linear) {
this._gl.uniform3f(
shaderUniform.location,
Color.gammaToLinearSpace((<Color>value).r),
Color.gammaToLinearSpace((<Color>value).g),
Color.gammaToLinearSpace((<Color>value).b)
);
} else {
this._gl.uniform3f(shaderUniform.location, (<Color>value).r, (<Color>value).g, (<Color>value).b);
}
cacheValue.x = (<Color>value).r;
cacheValue.y = (<Color>value).g;
cacheValue.z = (<Color>value).b;
Expand Down Expand Up @@ -94,13 +114,23 @@ export class ShaderUniform {
cacheValue.z !== (<Color>value).b ||
cacheValue.w !== (<Color>value).a
) {
this._gl.uniform4f(
shaderUniform.location,
(<Color>value).r,
(<Color>value).g,
(<Color>value).b,
(<Color>value).a
);
if (this._colorSpace === ColorSpace.Linear) {
this._gl.uniform4f(
shaderUniform.location,
Color.gammaToLinearSpace((<Color>value).r),
Color.gammaToLinearSpace((<Color>value).g),
Color.gammaToLinearSpace((<Color>value).b),
Color.gammaToLinearSpace((<Color>value).a)
);
} else {
this._gl.uniform4f(
shaderUniform.location,
(<Color>value).r,
(<Color>value).g,
(<Color>value).b,
(<Color>value).a
);
}
cacheValue.x = (<Color>value).r;
cacheValue.y = (<Color>value).g;
cacheValue.z = (<Color>value).b;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/shaderlib/pbr/ibl_frag_define.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ vec3 getLightProbeRadiance(GeometricContext geometry, float roughness, int maxMI
#endif

envMapColor.rgb = RGBMToLinear(envMapColor, 5.0).rgb;
#ifdef OASIS_COLORSPACE_GAMMA
envMapColor = linearTogamma(envMapColor);
#endif
return envMapColor.rgb * specularIntensity;

#endif
Expand Down
18 changes: 15 additions & 3 deletions packages/core/src/shaderlib/pbr/pbr_frag.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ addTotalDirectRadiance(geometry, material, reflectedLight);

// IBL diffuse
#ifdef O3_USE_SH
vec3 irradiance = getLightProbeIrradiance(u_env_sh, geometry.normal) * u_envMapLight.diffuseIntensity;
vec3 irradiance = getLightProbeIrradiance(u_env_sh, geometry.normal);
#ifdef OASIS_COLORSPACE_GAMMA
irradiance = linearTogamma(irradiance);
#endif
irradiance *= u_envMapLight.diffuseIntensity;
#else
vec3 irradiance = u_envMapLight.diffuse * u_envMapLight.diffuseIntensity;
irradiance *= PI;
Expand All @@ -32,7 +36,11 @@ reflectedLight.indirectSpecular += radiance * envBRDFApprox(material.specularCol
// Emissive
vec3 emissiveRadiance = u_emissiveColor;
#ifdef HAS_EMISSIVEMAP
emissiveRadiance *= gammaToLinear(texture2D(u_emissiveSampler, v_uv)).rgb;
vec4 emissiveColor = texture2D(u_emissiveSampler, v_uv);
#ifndef OASIS_COLORSPACE_GAMMA
emissiveColor = gammaToLinear(emissiveColor);
#endif
emissiveRadiance *= emissiveColor;
#endif

// Total
Expand All @@ -42,4 +50,8 @@ vec3 totalRadiance = reflectedLight.directDiffuse +
reflectedLight.indirectSpecular +
emissiveRadiance;

gl_FragColor = linearToGamma (vec4(totalRadiance, u_baseColor.a));
vec4 tagetColor =vec4(totalRadiance, u_baseColor.a);
#ifndef OASIS_COLORSPACE_GAMMA
tagetColor = linearToGamma (tagetColor);
#endif
gl_FragColor = tagetColor;
14 changes: 9 additions & 5 deletions packages/core/src/shaderlib/pbr/pbr_helper.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ float pow2(float x ) {
return x * x;
}

vec4 gammaToLinear(vec4 srgbIn){
return vec4( pow(srgbIn.rgb, vec3(2.2)), srgbIn.a);
}

vec4 RGBMToLinear(vec4 value, float maxRange ) {
return vec4( value.rgb * value.a * maxRange, 1.0 );
}

vec4 gammaToLinear(vec4 srgbIn){
return vec4( pow(srgbIn.rgb, vec3(2.2)), srgbIn.a);
}

vec4 linearToGamma(vec4 linearIn){
return vec4( pow(linearIn.rgb, vec3(1.0 / 2.2)), linearIn.a);
}
Expand All @@ -37,7 +37,11 @@ PhysicalMaterial getPhysicalMaterial(
PhysicalMaterial material;

#ifdef HAS_BASECOLORMAP
diffuseColor *= gammaToLinear(texture2D(u_baseColorSampler, v_uv));
vec4 baseColor = texture2D(u_baseColorSampler, v_uv);
#ifndef OASIS_COLORSPACE_GAMMA
baseColor = gammaToLinear(baseColor);
#endif
diffuseColor *= baseColor;
#endif

#ifdef O3_HAS_VERTEXCOLOR
Expand Down

0 comments on commit 60c6f80

Please sign in to comment.