Skip to content

Commit

Permalink
fix(camera): fix orthogonal camera rendering error (#466)
Browse files Browse the repository at this point in the history
Fix rendering in orthogonal camera mode
add support for orbit in ortho camera
  • Loading branch information
hellmor authored Jan 18, 2025
1 parent 9fa23b4 commit 5dedb08
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@orillusion/core",
"version": "0.8.5-dev.3",
"version": "0.8.5-dev.5",
"author": "Orillusion",
"description": "Orillusion WebGPU Engine",
"type": "module",
Expand Down
100 changes: 100 additions & 0 deletions samples/base/Sample_CameraType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Engine3D, Scene3D, AtmosphericComponent, HoverCameraController, Object3D, MeshRenderer, BoxGeometry, LitMaterial, DirectLight, View3D, Camera3D, Frustum, OrbitController, Vector3, Color, AxisObject, GridObject } from "@orillusion/core";
import { Stats } from "@orillusion/stats";
import * as dat from "dat.gui"

// initializa engine
await Engine3D.init();

// create new scene as root node
let scene3D: Scene3D = new Scene3D();

// add performance stats
scene3D.addComponent(Stats)

// add an Atmospheric sky enviroment
let sky = scene3D.addComponent(AtmosphericComponent);
sky.sunY = 0.6;

// create camera
let cameraObj: Object3D = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
// adjust camera view
camera.perspective(45, Engine3D.aspect, 0.1, 1000.0);
camera.lookAt(new Vector3(0, 10, 10), Vector3.ZERO, Vector3.UP)
// set camera controller
let controller = cameraObj.addComponent(OrbitController);
controller.maxDistance = 200;
// add camera node
scene3D.addChild(cameraObj);

// create light obj
let light: Object3D = new Object3D();
// adjust light rotation
light.rotationX = 45;
light.rotationY = 30;
// add direct light component
let dirLight: DirectLight = light.addComponent(DirectLight);
dirLight.intensity = 3;
// add light object to scene
scene3D.addChild(light);

// create a box
const box: Object3D = new Object3D();
// add MeshRenderer
let mr: MeshRenderer = box.addComponent(MeshRenderer);
// set geometry
mr.geometry = new BoxGeometry(1, 1, 1);
// set material
mr.material = new LitMaterial();
// set rotation
box.y = 0
scene3D.addChild(box);

// create a box
const box2: Object3D = new Object3D();
// add MeshRenderer
let mr2: MeshRenderer = box2.addComponent(MeshRenderer);
// set geometry
mr2.geometry = new BoxGeometry(1, 1, 1);
// set material
mr2.material = new LitMaterial();
mr2.material.baseColor = Color.COLOR_RED
// set rotation
box2.y = 1
box2.x = 1
scene3D.addChild(box2);

scene3D.addChild(new AxisObject(10));
scene3D.addChild(new GridObject(1000, 100));

// create a view with target scene and camera
let view = new View3D();
view.scene = scene3D;
view.camera = camera;
// start render
Engine3D.startRenderView(view);

// add debug GUI
let gui = new dat.GUI();
let f = gui.addFolder('Camera')
let options = {
'ortho': () => {
camera.ortho(camera.frustumSize || 50, camera.frustumDepth || 100)
},
'perspective': () => {
camera.near = 0.1
camera.perspective(camera.fov, camera.aspect, camera.near, camera.far)
}
}
f.add(camera, 'near', 0.1, 100).listen().onChange(() => {
camera.type === 1 ? options.perspective() : options.ortho()
})
f.add(camera, 'far', 1, 1000).listen().onChange(() => {
camera.type === 1 ? options.perspective() : options.ortho()
})
f.add(options, 'perspective')
f.add(camera, 'fov', 1, 179).listen().onChange(() => options.perspective())
f.add(options, 'ortho')
f.add(camera, 'frustumSize', 1, 200).listen().onChange(() => options.ortho())
f.add(camera, 'frustumDepth', 1, 200).listen().onChange(() => options.ortho())
f.open()
1 change: 1 addition & 0 deletions src/assets/shader/sky/CubeSky_Shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class CubeSky_Shader {
fixViewMat[3].z = 0.0 ;
var clipPos = fixProjMat * fixViewMat * ORI_VertexOut.vWorldPos;
clipPos.z = clipPos.w;
ORI_VertexOut.vClipPos = clipPos ;
ORI_VertexOut.member = clipPos;
return ORI_VertexOut;
Expand Down
15 changes: 13 additions & 2 deletions src/components/controller/OrbitController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Vector3 } from '../../math/Vector3';
import { Vector3Ex } from '../../util/Vector3Ex';
import { clamp } from '../../math/MathUtil';
import { PointerEvent3D } from '../../event/eventConst/PointerEvent3D';
import { CameraType } from '../../core/CameraType';

/**
* Orbit Camera Controller
Expand Down Expand Up @@ -190,6 +191,7 @@ export class OrbitController extends ComponentBase {
}
if (changed) {
this._spherical.setCoords(this._position.x - this._target.x, this._position.y - this._target.y, this._position.z - this._target.z)
this.updateCamera();
} else if (!this._isMouseDown && this.autoRotate) {
this._spherical.theta -= this.autoRotateSpeed * Math.PI / 180;
this.updateCamera();
Expand All @@ -207,10 +209,19 @@ export class OrbitController extends ComponentBase {
* @internal
*/
private onWheel(e: PointerEvent3D) {
e.deltaY = clamp(e.deltaY, -this._spherical.radius, this._spherical.radius)
this._spherical.radius += e.deltaY * this.zoomFactor;
let deltaY = clamp(e.deltaY, -this._spherical.radius, this._spherical.radius)
this._spherical.radius += deltaY * this.zoomFactor;
this._spherical.radius = clamp(this._spherical.radius, this.minDistance, this.maxDistance);
this.updateCamera();

if(this._camera.type === CameraType.ortho){
this._camera.frustumSize += e.deltaY * this.zoomFactor
if(this._camera.frustumSize < this._minDistance)
this._camera.frustumSize = this._minDistance
else if(this._camera.frustumSize > this._maxDistance)
this._camera.frustumSize = this._maxDistance
this._camera.updateProjection()
}
}
/**
* @internal
Expand Down
44 changes: 35 additions & 9 deletions src/core/Camera3D.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ export class Camera3D extends ComponentBase {
/**
* orth view size
*/
public frustumSize: number = 100;
public frustumSize: number = 0;
public frustumDepth: number = 0;

/**
* camera view port size
Expand Down Expand Up @@ -176,8 +177,10 @@ export class Camera3D extends ComponentBase {
if (this.type == CameraType.perspective) {
this.perspective(this.fov, this.aspect, this.near, this.far);
}else if(this.type == CameraType.ortho) {
if(this.frustumSize)
this.ortho(this.frustumSize, this.near, this.far);
if(this.frustumSize && this.frustumDepth)
this.ortho(this.frustumSize, this.frustumDepth);
else if(this.frustumSize)
this.ortho2(this.frustumSize, this.near, this.far);
else
this.orthoOffCenter(this.left, this.right, this.bottom, this.top, this.near, this.far);
}
Expand Down Expand Up @@ -242,22 +245,45 @@ export class Camera3D extends ComponentBase {
}

/**
* set an orthographic camera with a frustumSize
* @param frustumSize the frustum size
* set an orthographic camera with a frustumSize(viewHeight) and frustumSizeDepth
* @param frustumSize the frustum view height
* @param frustumSizeDepth the frustum view depth
*/
public ortho(frustumSize: number, frustumDepth: number) {
this.frustumSize = frustumSize;
this.frustumDepth = frustumDepth;

let w = frustumSize * this.aspect;
let h = frustumSize;
let left = -w / 2;
let right = w / 2;
let top = h / 2;
let bottom = -h / 2;

let dis = Vector3.distance(this.object3D.localPosition, this.lookTarget)
let near = dis - frustumDepth
let far = dis + frustumDepth

this.orthoOffCenter(left, right, bottom, top, near, far);
}
/**
* set an orthographic camera with a frustumSize(viewHeight) and specific near & far
* @param frustumSize the frustum view height
* @param near camera near plane
* @param far camera far plane
*/
public ortho(frustumSize: number, near: number, far: number) {
public ortho2(frustumSize: number, near: number, far: number) {
this.frustumSize = frustumSize;
let w = frustumSize * 0.5 * this.aspect;
let h = frustumSize * 0.5;
let w = frustumSize * this.aspect;
let h = frustumSize;
let left = -w / 2;
let right = w / 2;
let top = h / 2;
let bottom = -h / 2;

this.orthoOffCenter(left, right, bottom, top, near, far);
}

/**
* set an orthographic camera with specified frustum space
* @param left camera left plane
Expand Down
16 changes: 8 additions & 8 deletions src/gfx/generate/PassGenerate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ export class PassGenerate {
if (useMorphNormals) {
shadowPass.setDefine(`USE_MORPHNORMALS`, useMorphNormals);
}
// shadowMaterialPass.shaderState.cullMode = material.getShader().cullMode;
if (colorPass.cullMode == `none`) {
shadowPass.shaderState.cullMode = `none`;
} else if (colorPass.cullMode == `back`) {
shadowPass.shaderState.cullMode = `front`;
} else if (colorPass.cullMode == `front`) {
shadowPass.shaderState.cullMode = `back`;
}
// shadowPass.shaderState.cullMode = colorPass.cullMode;
// if (colorPass.cullMode == `none`) {
// shadowPass.shaderState.cullMode = `none`;
// } else if (colorPass.cullMode == `back`) {
// shadowPass.shaderState.cullMode = `front`;
// } else if (colorPass.cullMode == `front`) {
// shadowPass.shaderState.cullMode = `back`;
// }
shadowPass.preCompile(renderNode.geometry);
shader.addRenderPass(shadowPass);
}
Expand Down
6 changes: 3 additions & 3 deletions src/loader/parser/prefab/mats/shader/SkyShader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ export class SkyShader extends Shader {
colorShader.setUniformFloat(`roughness`, 0.0);

let shaderState = colorShader.shaderState;
shaderState.frontFace = `cw`;
shaderState.cullMode = GPUCullMode.back;
shaderState.frontFace = `ccw`;
shaderState.cullMode = GPUCullMode.front;
shaderState.depthWriteEnabled = false;
shaderState.depthCompare = GPUCompareFunction.less;
shaderState.depthCompare = GPUCompareFunction.less_equal;
}
}
2 changes: 1 addition & 1 deletion src/materials/multiPass/SkyGBufferPass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ export class SkyGBufferPass extends RenderShaderPass {
shaderState.frontFace = `ccw`;
shaderState.cullMode = GPUCullMode.front;
shaderState.depthWriteEnabled = false;
shaderState.depthCompare = GPUCompareFunction.less;
shaderState.depthCompare = GPUCompareFunction.less_equal;
}
}
2 changes: 1 addition & 1 deletion src/math/Matrix4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ export class Matrix4 {
public orthoOffCenter(l: number, r: number, b: number, t: number, zn: number, zf: number) {
let data = this.rawData;

data[0] = 2 / (r - l);
data[0] = -2 / (r - l);
data[1] = 0;
data[2] = 0;
data[3] = 0;
Expand Down

0 comments on commit 5dedb08

Please sign in to comment.