Skip to content

Commit 5dedb08

Browse files
authored
fix(camera): fix orthogonal camera rendering error (#466)
Fix rendering in orthogonal camera mode add support for orbit in ortho camera
1 parent 9fa23b4 commit 5dedb08

File tree

9 files changed

+163
-25
lines changed

9 files changed

+163
-25
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@orillusion/core",
3-
"version": "0.8.5-dev.3",
3+
"version": "0.8.5-dev.5",
44
"author": "Orillusion",
55
"description": "Orillusion WebGPU Engine",
66
"type": "module",

samples/base/Sample_CameraType.ts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { Engine3D, Scene3D, AtmosphericComponent, HoverCameraController, Object3D, MeshRenderer, BoxGeometry, LitMaterial, DirectLight, View3D, Camera3D, Frustum, OrbitController, Vector3, Color, AxisObject, GridObject } from "@orillusion/core";
2+
import { Stats } from "@orillusion/stats";
3+
import * as dat from "dat.gui"
4+
5+
// initializa engine
6+
await Engine3D.init();
7+
8+
// create new scene as root node
9+
let scene3D: Scene3D = new Scene3D();
10+
11+
// add performance stats
12+
scene3D.addComponent(Stats)
13+
14+
// add an Atmospheric sky enviroment
15+
let sky = scene3D.addComponent(AtmosphericComponent);
16+
sky.sunY = 0.6;
17+
18+
// create camera
19+
let cameraObj: Object3D = new Object3D();
20+
let camera = cameraObj.addComponent(Camera3D);
21+
// adjust camera view
22+
camera.perspective(45, Engine3D.aspect, 0.1, 1000.0);
23+
camera.lookAt(new Vector3(0, 10, 10), Vector3.ZERO, Vector3.UP)
24+
// set camera controller
25+
let controller = cameraObj.addComponent(OrbitController);
26+
controller.maxDistance = 200;
27+
// add camera node
28+
scene3D.addChild(cameraObj);
29+
30+
// create light obj
31+
let light: Object3D = new Object3D();
32+
// adjust light rotation
33+
light.rotationX = 45;
34+
light.rotationY = 30;
35+
// add direct light component
36+
let dirLight: DirectLight = light.addComponent(DirectLight);
37+
dirLight.intensity = 3;
38+
// add light object to scene
39+
scene3D.addChild(light);
40+
41+
// create a box
42+
const box: Object3D = new Object3D();
43+
// add MeshRenderer
44+
let mr: MeshRenderer = box.addComponent(MeshRenderer);
45+
// set geometry
46+
mr.geometry = new BoxGeometry(1, 1, 1);
47+
// set material
48+
mr.material = new LitMaterial();
49+
// set rotation
50+
box.y = 0
51+
scene3D.addChild(box);
52+
53+
// create a box
54+
const box2: Object3D = new Object3D();
55+
// add MeshRenderer
56+
let mr2: MeshRenderer = box2.addComponent(MeshRenderer);
57+
// set geometry
58+
mr2.geometry = new BoxGeometry(1, 1, 1);
59+
// set material
60+
mr2.material = new LitMaterial();
61+
mr2.material.baseColor = Color.COLOR_RED
62+
// set rotation
63+
box2.y = 1
64+
box2.x = 1
65+
scene3D.addChild(box2);
66+
67+
scene3D.addChild(new AxisObject(10));
68+
scene3D.addChild(new GridObject(1000, 100));
69+
70+
// create a view with target scene and camera
71+
let view = new View3D();
72+
view.scene = scene3D;
73+
view.camera = camera;
74+
// start render
75+
Engine3D.startRenderView(view);
76+
77+
// add debug GUI
78+
let gui = new dat.GUI();
79+
let f = gui.addFolder('Camera')
80+
let options = {
81+
'ortho': () => {
82+
camera.ortho(camera.frustumSize || 50, camera.frustumDepth || 100)
83+
},
84+
'perspective': () => {
85+
camera.near = 0.1
86+
camera.perspective(camera.fov, camera.aspect, camera.near, camera.far)
87+
}
88+
}
89+
f.add(camera, 'near', 0.1, 100).listen().onChange(() => {
90+
camera.type === 1 ? options.perspective() : options.ortho()
91+
})
92+
f.add(camera, 'far', 1, 1000).listen().onChange(() => {
93+
camera.type === 1 ? options.perspective() : options.ortho()
94+
})
95+
f.add(options, 'perspective')
96+
f.add(camera, 'fov', 1, 179).listen().onChange(() => options.perspective())
97+
f.add(options, 'ortho')
98+
f.add(camera, 'frustumSize', 1, 200).listen().onChange(() => options.ortho())
99+
f.add(camera, 'frustumDepth', 1, 200).listen().onChange(() => options.ortho())
100+
f.open()

src/assets/shader/sky/CubeSky_Shader.ts

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export class CubeSky_Shader {
4040
fixViewMat[3].z = 0.0 ;
4141
4242
var clipPos = fixProjMat * fixViewMat * ORI_VertexOut.vWorldPos;
43+
clipPos.z = clipPos.w;
4344
ORI_VertexOut.vClipPos = clipPos ;
4445
ORI_VertexOut.member = clipPos;
4546
return ORI_VertexOut;

src/components/controller/OrbitController.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Vector3 } from '../../math/Vector3';
55
import { Vector3Ex } from '../../util/Vector3Ex';
66
import { clamp } from '../../math/MathUtil';
77
import { PointerEvent3D } from '../../event/eventConst/PointerEvent3D';
8+
import { CameraType } from '../../core/CameraType';
89

910
/**
1011
* Orbit Camera Controller
@@ -190,6 +191,7 @@ export class OrbitController extends ComponentBase {
190191
}
191192
if (changed) {
192193
this._spherical.setCoords(this._position.x - this._target.x, this._position.y - this._target.y, this._position.z - this._target.z)
194+
this.updateCamera();
193195
} else if (!this._isMouseDown && this.autoRotate) {
194196
this._spherical.theta -= this.autoRotateSpeed * Math.PI / 180;
195197
this.updateCamera();
@@ -207,10 +209,19 @@ export class OrbitController extends ComponentBase {
207209
* @internal
208210
*/
209211
private onWheel(e: PointerEvent3D) {
210-
e.deltaY = clamp(e.deltaY, -this._spherical.radius, this._spherical.radius)
211-
this._spherical.radius += e.deltaY * this.zoomFactor;
212+
let deltaY = clamp(e.deltaY, -this._spherical.radius, this._spherical.radius)
213+
this._spherical.radius += deltaY * this.zoomFactor;
212214
this._spherical.radius = clamp(this._spherical.radius, this.minDistance, this.maxDistance);
213215
this.updateCamera();
216+
217+
if(this._camera.type === CameraType.ortho){
218+
this._camera.frustumSize += e.deltaY * this.zoomFactor
219+
if(this._camera.frustumSize < this._minDistance)
220+
this._camera.frustumSize = this._minDistance
221+
else if(this._camera.frustumSize > this._maxDistance)
222+
this._camera.frustumSize = this._maxDistance
223+
this._camera.updateProjection()
224+
}
214225
}
215226
/**
216227
* @internal

src/core/Camera3D.ts

+35-9
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ export class Camera3D extends ComponentBase {
7070
/**
7171
* orth view size
7272
*/
73-
public frustumSize: number = 100;
73+
public frustumSize: number = 0;
74+
public frustumDepth: number = 0;
7475

7576
/**
7677
* camera view port size
@@ -176,8 +177,10 @@ export class Camera3D extends ComponentBase {
176177
if (this.type == CameraType.perspective) {
177178
this.perspective(this.fov, this.aspect, this.near, this.far);
178179
}else if(this.type == CameraType.ortho) {
179-
if(this.frustumSize)
180-
this.ortho(this.frustumSize, this.near, this.far);
180+
if(this.frustumSize && this.frustumDepth)
181+
this.ortho(this.frustumSize, this.frustumDepth);
182+
else if(this.frustumSize)
183+
this.ortho2(this.frustumSize, this.near, this.far);
181184
else
182185
this.orthoOffCenter(this.left, this.right, this.bottom, this.top, this.near, this.far);
183186
}
@@ -242,22 +245,45 @@ export class Camera3D extends ComponentBase {
242245
}
243246

244247
/**
245-
* set an orthographic camera with a frustumSize
246-
* @param frustumSize the frustum size
248+
* set an orthographic camera with a frustumSize(viewHeight) and frustumSizeDepth
249+
* @param frustumSize the frustum view height
250+
* @param frustumSizeDepth the frustum view depth
251+
*/
252+
public ortho(frustumSize: number, frustumDepth: number) {
253+
this.frustumSize = frustumSize;
254+
this.frustumDepth = frustumDepth;
255+
256+
let w = frustumSize * this.aspect;
257+
let h = frustumSize;
258+
let left = -w / 2;
259+
let right = w / 2;
260+
let top = h / 2;
261+
let bottom = -h / 2;
262+
263+
let dis = Vector3.distance(this.object3D.localPosition, this.lookTarget)
264+
let near = dis - frustumDepth
265+
let far = dis + frustumDepth
266+
267+
this.orthoOffCenter(left, right, bottom, top, near, far);
268+
}
269+
/**
270+
* set an orthographic camera with a frustumSize(viewHeight) and specific near & far
271+
* @param frustumSize the frustum view height
247272
* @param near camera near plane
248273
* @param far camera far plane
249274
*/
250-
public ortho(frustumSize: number, near: number, far: number) {
275+
public ortho2(frustumSize: number, near: number, far: number) {
251276
this.frustumSize = frustumSize;
252-
let w = frustumSize * 0.5 * this.aspect;
253-
let h = frustumSize * 0.5;
277+
let w = frustumSize * this.aspect;
278+
let h = frustumSize;
254279
let left = -w / 2;
255280
let right = w / 2;
256281
let top = h / 2;
257282
let bottom = -h / 2;
283+
258284
this.orthoOffCenter(left, right, bottom, top, near, far);
259285
}
260-
286+
261287
/**
262288
* set an orthographic camera with specified frustum space
263289
* @param left camera left plane

src/gfx/generate/PassGenerate.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ export class PassGenerate {
8888
if (useMorphNormals) {
8989
shadowPass.setDefine(`USE_MORPHNORMALS`, useMorphNormals);
9090
}
91-
// shadowMaterialPass.shaderState.cullMode = material.getShader().cullMode;
92-
if (colorPass.cullMode == `none`) {
93-
shadowPass.shaderState.cullMode = `none`;
94-
} else if (colorPass.cullMode == `back`) {
95-
shadowPass.shaderState.cullMode = `front`;
96-
} else if (colorPass.cullMode == `front`) {
97-
shadowPass.shaderState.cullMode = `back`;
98-
}
91+
// shadowPass.shaderState.cullMode = colorPass.cullMode;
92+
// if (colorPass.cullMode == `none`) {
93+
// shadowPass.shaderState.cullMode = `none`;
94+
// } else if (colorPass.cullMode == `back`) {
95+
// shadowPass.shaderState.cullMode = `front`;
96+
// } else if (colorPass.cullMode == `front`) {
97+
// shadowPass.shaderState.cullMode = `back`;
98+
// }
9999
shadowPass.preCompile(renderNode.geometry);
100100
shader.addRenderPass(shadowPass);
101101
}

src/loader/parser/prefab/mats/shader/SkyShader.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ export class SkyShader extends Shader {
2222
colorShader.setUniformFloat(`roughness`, 0.0);
2323

2424
let shaderState = colorShader.shaderState;
25-
shaderState.frontFace = `cw`;
26-
shaderState.cullMode = GPUCullMode.back;
25+
shaderState.frontFace = `ccw`;
26+
shaderState.cullMode = GPUCullMode.front;
2727
shaderState.depthWriteEnabled = false;
28-
shaderState.depthCompare = GPUCompareFunction.less;
28+
shaderState.depthCompare = GPUCompareFunction.less_equal;
2929
}
3030
}

src/materials/multiPass/SkyGBufferPass.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ export class SkyGBufferPass extends RenderShaderPass {
2121
shaderState.frontFace = `ccw`;
2222
shaderState.cullMode = GPUCullMode.front;
2323
shaderState.depthWriteEnabled = false;
24-
shaderState.depthCompare = GPUCompareFunction.less;
24+
shaderState.depthCompare = GPUCompareFunction.less_equal;
2525
}
2626
}

src/math/Matrix4.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ export class Matrix4 {
703703
public orthoOffCenter(l: number, r: number, b: number, t: number, zn: number, zf: number) {
704704
let data = this.rawData;
705705

706-
data[0] = 2 / (r - l);
706+
data[0] = -2 / (r - l);
707707
data[1] = 0;
708708
data[2] = 0;
709709
data[3] = 0;

0 commit comments

Comments
 (0)