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

feat(atmosphere): Hillarie Phisically Based Atmosphere Shader #444

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
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
227 changes: 227 additions & 0 deletions packages/atmosphere/component/AtmosphericComponent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { AtmosphericScatteringSky, AtmosphericScatteringSkySetting } from "../textures/AtmosphericScatteringSky";
import { SkyRenderer } from "../renderer/SkyRenderer";
import { ShaderLib, Transform } from "@orillusion/core";
import { AtmosphericScatteringSky_shader } from "../shader/AtmosphericScatteringSky_shader";

class HistoryData {
public rotateX: number;
public rotateY: number;

public sunX: number;
public sunY: number;

constructor() {
this.reset();
}

public reset(): this {
this.rotateX = this.rotateY = this.sunX = this.sunY = Number.MAX_VALUE;
return this;
}

public isRotateChange(rx: number, ry: number): boolean {
return Math.abs(this.rotateX - rx) >= 0.001 || Math.abs(this.rotateY - ry) >= 0.001;
}

public isSkyChange(x: number, y: number): boolean {
return Math.abs(this.sunX - x) >= 0.001 || Math.abs(this.sunY - y) >= 0.001;
}

public save(x: number, y: number, rx: number, ry: number): this {
this.sunX = x;
this.sunY = y;
this.rotateX = rx;
this.rotateY = ry;

return this;
}
}

/**
*
* Atmospheric Sky Box Component
* @group Components
*/
export class AtmosphericComponent extends SkyRenderer {

private _atmosphericScatteringSky: AtmosphericScatteringSky;
private _onChange: boolean = true;
private _relatedTransform: Transform;
private _historyData: HistoryData;
public get sunX() {
return this._atmosphericScatteringSky.setting.sunX;
}

public set sunX(value) {
if (this._atmosphericScatteringSky.setting.sunX != value) {
this._atmosphericScatteringSky.setting.sunX = value;
if (this._relatedTransform) {
this._relatedTransform.rotationY = value * 360 - 90;
}
this._onChange = true;
}
}

public get sunY() {
return this._atmosphericScatteringSky.setting.sunY;
}

public set sunY(value) {
if (this._atmosphericScatteringSky.setting.sunY != value) {
this._atmosphericScatteringSky.setting.sunY = value;
if (this._relatedTransform) {
this._relatedTransform.rotationX = (value - 0.5) * 180;
}
this._onChange = true;
}
}

public get eyePos() {
return this._atmosphericScatteringSky.setting.eyePos;
}

public set eyePos(value) {
if (this._atmosphericScatteringSky.setting.eyePos != value) {
this._atmosphericScatteringSky.setting.eyePos = value;
this._onChange = true;
}
}

public get sunRadius() {
return this._atmosphericScatteringSky.setting.sunRadius;
}

public set sunRadius(value) {
if (this._atmosphericScatteringSky.setting.sunRadius != value) {
this._atmosphericScatteringSky.setting.sunRadius = value;
this._onChange = true;
}
}

public get sunRadiance() {
return this._atmosphericScatteringSky.setting.sunRadiance;
}

public set sunRadiance(value) {
if (this._atmosphericScatteringSky.setting.sunRadiance != value) {
this._atmosphericScatteringSky.setting.sunRadiance = value;
this._onChange = true;
}
}

public get sunBrightness() {
return this._atmosphericScatteringSky.setting.sunBrightness;
}

public set sunBrightness(value) {
if (this._atmosphericScatteringSky.setting.sunBrightness != value) {
this._atmosphericScatteringSky.setting.sunBrightness = value;
this._onChange = true;
}
}

public get displaySun() {
return this._atmosphericScatteringSky.setting.displaySun;
}

public set displaySun(value) {
if (this._atmosphericScatteringSky.setting.displaySun != value) {
this._atmosphericScatteringSky.setting.displaySun = value;
this._onChange = true;
}
}

public get enableClouds() {
return this._atmosphericScatteringSky.setting.enableClouds;
}

public set enableClouds(value) {
if (this._atmosphericScatteringSky.setting.enableClouds != value) {
this._atmosphericScatteringSky.setting.enableClouds = value;
this._onChange = true;
}
}

public get showV1() {
return this._atmosphericScatteringSky.setting.showV1;
}

public set showV1(value) {
if (this._atmosphericScatteringSky.setting.showV1 != value) {
this._atmosphericScatteringSky.setting.showV1 = value;
this._onChange = true;
}
}

public get hdrExposure() {
return this._atmosphericScatteringSky.setting.hdrExposure;
}

public set hdrExposure(value) {
if (this._atmosphericScatteringSky.setting.hdrExposure != value) {
this._atmosphericScatteringSky.setting.hdrExposure = value;
this._onChange = true;
}
}


public init(): void {
super.init();
this._historyData = new HistoryData();
ShaderLib.register('AtmosphericScatteringIntegration', AtmosphericScatteringSky_shader.integration);
ShaderLib.register('AtmosphereEarth', AtmosphericScatteringSky_shader.earth);
ShaderLib.register('AtmosphereUniforms', AtmosphericScatteringSky_shader.uniforms);
this._atmosphericScatteringSky = new AtmosphericScatteringSky(new AtmosphericScatteringSkySetting());

let view3D = this.transform.view3D;
let scene = this.transform.scene3D;
this.map = this._atmosphericScatteringSky;
scene.envMap = this._atmosphericScatteringSky;
scene.envMap.isHDRTexture = true;
this.onUpdate(view3D);
}

public start(view?: any): void {
let scene = this.transform.scene3D;
this.map = this._atmosphericScatteringSky;
scene.envMap = this._atmosphericScatteringSky;
scene.envMap.isHDRTexture = true;
super.start();
}

public get relativeTransform() {
return this._relatedTransform;
}

public set relativeTransform(value: Transform) {
this._relatedTransform = value;
this._historyData.reset();
}

public onUpdate(view?: any) {
if (this._relatedTransform) {
this._relatedTransform.rotationZ = 0;
if (this._historyData.isRotateChange(this._relatedTransform.rotationX, this._relatedTransform.rotationY)) {
this.sunX = (this._relatedTransform.rotationY + 90) / 360//
this.sunY = this._relatedTransform.rotationX / 180 + 0.5;
} else if (this._historyData.isSkyChange(this.sunX, this.sunY)) {
this._relatedTransform.rotationY = this.sunX * 360 - 90;
this._relatedTransform.rotationX = (this.sunY - 0.5) * 180;
}
this._historyData.save(this.sunX, this.sunY, this._relatedTransform.rotationX, this._relatedTransform.rotationY);
}

if (this._onChange) {
this._onChange = false;
this._atmosphericScatteringSky.apply(view);
}

}

public destroy(force?: boolean): void {
super.destroy(force);
this._atmosphericScatteringSky.destroy();
this._atmosphericScatteringSky = null;
this._onChange = null;
}
}
3 changes: 3 additions & 0 deletions packages/atmosphere/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './component/AtmosphericComponent';
export * from './renderer/SkyRenderer';
export * from './textures/AtmosphericScatteringSky';
26 changes: 26 additions & 0 deletions packages/atmosphere/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@orillusion/atmosphere",
"version": "0.1.0",
"author": "Orillusion",
"description": "Orillusion Atmosphere Plugin",
"main": "./dist/atmosphere.umd.js",
"module": "./dist/atmosphere.es.js",
"module:dev": "./index.ts",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "vite build && npm run build:types && npm run build:clean",
"build:types": "tsc --emitDeclarationOnly -p tsconfig.json",
"build:clean": "mv dist/packages/atmosphere/* dist && rm -rf dist/src && rm -rf dist/packages"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/Orillusion/orillusion.git"
},
"dependencies": {
"@orillusion/core": "^0.8.0"
}
}
104 changes: 104 additions & 0 deletions packages/atmosphere/renderer/SkyRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
Engine3D,
View3D,
MeshRenderer,
BoundingBox,
Texture,
EntityCollect,
ClusterLightingBuffer,
RendererMask,
RendererPassState,
PassType,
SkyMaterial,
Vector3,
SphereGeometry
} from "@orillusion/core";

/**
*
* Sky Box Renderer Component
* @group Components
*/
export class SkyRenderer extends MeshRenderer {
/**
* The material used in the Sky Box.
*/
public skyMaterial: SkyMaterial;


public init(): void {
super.init();
this.castShadow = false;
this.castGI = true;
this.addRendererMask(RendererMask.Sky);
this.alwaysRender = true;

this.object3D.bound = new BoundingBox(Vector3.ZERO.clone(), Vector3.MAX);
this.geometry = new SphereGeometry(Engine3D.setting.sky.defaultFar, 20, 20);
this.skyMaterial ||= new SkyMaterial();
}

public onEnable(): void {
if (!this._readyPipeline) {
this.initPipeline();
} else {
this.castNeedPass();

if (!this._inRenderer && this.transform.scene3D) {
EntityCollect.instance.sky = this;
this._inRenderer = true;
}
}
}

public onDisable(): void {
if (this._inRenderer && this.transform.scene3D) {
this._inRenderer = false;
EntityCollect.instance.sky = null;
}
super.onDisable();
}

public renderPass2(view: View3D, passType: PassType, rendererPassState: RendererPassState, clusterLightingBuffer: ClusterLightingBuffer, encoder: GPURenderPassEncoder, useBundle: boolean = false) {
// this.transform.updateWorldMatrix();
super.renderPass2(view, passType, rendererPassState, clusterLightingBuffer, encoder, useBundle);
// this.transform.localPosition = Camera3D.mainCamera.transform.localPosition ;
}

/**
* set environment texture
*/
public set map(texture: Texture) {
this.skyMaterial.baseMap = texture;
if (this.skyMaterial.name == null) {
this.skyMaterial.name = 'skyMaterial';
}
this.material = this.skyMaterial;
}

/**
* get environment texture
*/
public get map(): Texture {
return this.skyMaterial.baseMap;
}

public get exposure() {
return this.skyMaterial.exposure;
}

public set exposure(value) {
if (this.skyMaterial)
this.skyMaterial.exposure = value;
}

public get roughness() {
return this.skyMaterial.roughness;
}

public set roughness(value) {
if (this.skyMaterial)
this.skyMaterial.roughness = value;
}

}
Loading