Skip to content

Commit 2bdfeff

Browse files
committed
renderer: redesign the rendering pipeline to support offscreen RTs rendering
It also fixes the issue with MSAA fbo by disabling the fbo switch at rendering opaques and transparent objects.
1 parent b072b48 commit 2bdfeff

File tree

89 files changed

+7155
-2073
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+7155
-2073
lines changed

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@
9797
"memory_resource": "cpp",
9898
"__availability": "cpp",
9999
"span": "cpp",
100-
"execution": "cpp"
100+
"execution": "cpp",
101+
"cassert": "cpp"
101102
},
102103
"cmake.buildDirectory": "${workspaceFolder}/build/targets/darwin",
103104
"C_Cpp.default.cppStandard": "c++17",

fixtures/html/three-shaders-ocean.html

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
// Skybox
5656
const sky = new Sky();
57-
sky.scale.setScalar(10000);
57+
sky.scale.setScalar(100);
5858
scene.add(sky);
5959

6060
const skyUniforms = sky.material.uniforms;
@@ -64,8 +64,8 @@
6464
skyUniforms['mieDirectionalG'].value = 0.8;
6565

6666
const parameters = {
67-
elevation: 2,
68-
azimuth: 180
67+
elevation: 90,
68+
azimuth: 0
6969
};
7070

7171
const pmremGenerator = new THREE.PMREMGenerator(renderer);
@@ -80,7 +80,9 @@
8080
sky.material.uniforms['sunPosition'].value.copy(sun);
8181
water.material.uniforms['sunDirection'].value.copy(sun).normalize();
8282

83-
if (renderTarget !== undefined) renderTarget.dispose();
83+
if (renderTarget !== undefined) {
84+
renderTarget.dispose();
85+
}
8486

8587
sceneEnv.add(sky);
8688
renderTarget = pmremGenerator.fromScene(sceneEnv);
@@ -90,10 +92,10 @@
9092

9193
updateSun();
9294

93-
const geometry = new THREE.BoxGeometry(1, 1, 1);
95+
const geometry = new THREE.BoxGeometry(10, 10, 10);
9496
const material = new THREE.MeshStandardMaterial({ roughness: 0 });
9597
mesh = new THREE.Mesh(geometry, material);
96-
mesh.position.z = -5;
98+
mesh.position.z = -30;
9799
scene.add(mesh);
98100
}
99101

@@ -119,7 +121,7 @@
119121

120122
function animate() {
121123
const time = performance.now() * 0.001;
122-
mesh.position.y = Math.sin(time) * 1;
124+
mesh.position.y = Math.sin(time) * 5;
123125
mesh.rotation.x = time * 0.5;
124126
mesh.rotation.z = time * 0.51;
125127
water.material.uniforms['time'].value += 1.0 / 120.0;

fixtures/html/three/portal.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import * as THREE from 'three';
22
import * as CameraUtils from 'three/addons/utils/CameraUtils.js';
33

44
const scene = new THREE.Scene();
5-
const camera = new THREE.PerspectiveCamera(75, 1.0, 0.1, 1000);
5+
const camera = new THREE.PerspectiveCamera(60, 1.6, 0.1, 100);
66

77
// Create lights
88
const light = new THREE.DirectionalLight(0xffffff, 0.5);
99
light.position.set(0, 1, 1);
1010
scene.add(light);
1111

12+
let scale;
1213
let renderer;
13-
let cameraControls;
1414
let smallSphereOne, smallSphereTwo;
1515
let portalCamera, leftPortal, rightPortal, leftPortalTexture, reflectedPosition,
1616
rightPortalTexture, bottomLeftCorner, bottomRightCorner, topLeftCorner;
@@ -33,7 +33,7 @@ let portalCamera, leftPortal, rightPortal, leftPortalTexture, reflectedPosition,
3333
scene.add(smallSphereTwo);
3434

3535
// portals
36-
portalCamera = new THREE.PerspectiveCamera(45, 1.0, 0.1, 500.0);
36+
portalCamera = new THREE.PerspectiveCamera(45, 1.0, 0.01, 100.0);
3737
scene.add(portalCamera);
3838
//frustumHelper = new THREE.CameraHelper( portalCamera );
3939
//scene.add( frustumHelper );
@@ -114,7 +114,7 @@ let portalCamera, leftPortal, rightPortal, leftPortalTexture, reflectedPosition,
114114
}
115115
});
116116
const size = box.getSize(new THREE.Vector3());
117-
const scale = 0.3 / Math.max(size.x, size.y, size.z);
117+
scale = 0.3 / Math.max(size.x, size.y, size.z);
118118
console.info('Scaling scene by', scale);
119119
scene.scale.set(scale, scale, scale);
120120
})();
@@ -123,17 +123,19 @@ let portalCamera, leftPortal, rightPortal, leftPortalTexture, reflectedPosition,
123123
function renderPortal(thisPortalMesh, otherPortalMesh, thisPortalTexture) {
124124
// set the portal camera position to be reflected about the portal plane
125125
thisPortalMesh.worldToLocal(reflectedPosition.copy(camera.position));
126-
reflectedPosition.x *= - 1.0; reflectedPosition.z *= - 1.0;
126+
// reflectedPosition.x *= - 1.0;
127+
// reflectedPosition.z *= - 1.0;
127128
otherPortalMesh.localToWorld(reflectedPosition);
128129
portalCamera.position.copy(reflectedPosition);
129130

131+
let unit = 50.05;
130132
// grab the corners of the other portal
131133
// - note: the portal is viewed backwards; flip the left/right coordinates
132-
otherPortalMesh.localToWorld(bottomLeftCorner.set(50.05, - 50.05, 0.0));
133-
otherPortalMesh.localToWorld(bottomRightCorner.set(- 50.05, - 50.05, 0.0));
134-
otherPortalMesh.localToWorld(topLeftCorner.set(50.05, 50.05, 0.0));
134+
otherPortalMesh.localToWorld(bottomLeftCorner.set(unit, - unit, 0.0));
135+
otherPortalMesh.localToWorld(bottomRightCorner.set(- unit, - unit, 0.0));
136+
otherPortalMesh.localToWorld(topLeftCorner.set(unit, unit, 0.0));
135137
// set the projection matrix to encompass the portal's frame
136-
CameraUtils.frameCorners(portalCamera, bottomLeftCorner, bottomRightCorner, topLeftCorner, false);
138+
// CameraUtils.frameCorners(portalCamera, bottomLeftCorner, bottomRightCorner, topLeftCorner, false);
137139

138140
// render the portal
139141
thisPortalTexture.texture.colorSpace = renderer.outputColorSpace;

src/bindings/webgl/rendering_context-inl.hpp

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
#include "./program.hpp"
1515
#include "./texture.hpp"
1616
#include "./shader.hpp"
17-
#include "./uniform_location.hpp"
1817
#include "./active_info.hpp"
18+
#include "./uniform_location.hpp"
1919

2020
using namespace std;
2121
using namespace node;
@@ -324,15 +324,8 @@ namespace webgl
324324
auto program = Napi::ObjectWrap<WebGLProgram>::Unwrap(info[0].As<Napi::Object>());
325325
int pname = info[1].As<Napi::Number>().Int32Value();
326326

327-
try
328-
{
329-
int v = glContext_->getProgramParameter(program->handle(), pname);
330-
return Napi::Number::New(env, v);
331-
}
332-
catch (const std::exception &e)
333-
{
334-
return env.Undefined();
335-
}
327+
int v = glContext_->getProgramParameter(program->handle(), pname);
328+
return Napi::Number::New(env, v);
336329
}
337330

338331
template <typename ObjectType, typename ContextType>
@@ -860,41 +853,70 @@ namespace webgl
860853
Napi::TypeError::New(env, "framebufferTexture2D() takes 5 arguments.").ThrowAsJavaScriptException();
861854
return env.Undefined();
862855
}
863-
auto jsTexture = info[3];
864-
if (!jsTexture.IsObject() || WebGLTexture::IsInstanceOf(jsTexture))
856+
857+
auto target = info[0].ToNumber().Int32Value();
858+
auto attachment = info[1].ToNumber().Int32Value();
859+
auto textarget = info[2].ToNumber().Int32Value();
860+
auto level = info[4].ToNumber().Int32Value();
861+
862+
if (target != WEBGL_FRAMEBUFFER &&
863+
target != WEBGL2_DRAW_FRAMEBUFFER &&
864+
target != WEBGL2_READ_FRAMEBUFFER) [[unlikely]]
865865
{
866-
glContext_->setError("framebufferTexture2d", client_graphics::WebGLError::kInvalidOperation, "texture isn't 0 or the name of an existing texture object");
866+
glContext_->setError("framebufferTexture2d",
867+
client_graphics::WebGLError::kInvalidEnum,
868+
"target must be FRAMEBUFFER");
867869
return env.Undefined();
868870
}
869871

870-
auto target = info[0].As<Napi::Number>().Int32Value();
871-
auto attachment = info[1].As<Napi::Number>().Int32Value();
872-
auto textarget = info[2].As<Napi::Number>().Int32Value();
873-
auto texture = Napi::ObjectWrap<WebGLTexture>::Unwrap(jsTexture.As<Napi::Object>());
874-
auto level = info[4].As<Napi::Number>().Int32Value();
875-
876-
if (target != WEBGL_FRAMEBUFFER)
872+
Napi::Value jsTexture = info[3];
873+
WebGLTexture *textureObject = nullptr;
874+
if (jsTexture.IsNumber())
877875
{
878-
glContext_->setError("framebufferTexture2d", client_graphics::WebGLError::kInvalidEnum, "target must be FRAMEBUFFER");
879-
return env.Undefined();
876+
// Only the number 0 is allowed to reset the texture binding.
877+
if (jsTexture.ToNumber().Int32Value() != 0)
878+
{
879+
glContext_->setError("framebufferTexture2d",
880+
client_graphics::WebGLError::kInvalidOperation,
881+
"texture must be 0 if it is a number");
882+
return env.Undefined();
883+
}
884+
else
885+
{
886+
textureObject = nullptr;
887+
}
888+
}
889+
else if (jsTexture.IsNull()) // `null` means reset framebuffer's texture
890+
{
891+
textureObject = nullptr;
880892
}
881-
if (textarget != WEBGL_TEXTURE_2D &&
882-
textarget != WEBGL_TEXTURE_CUBE_MAP_POSITIVE_X &&
883-
textarget != WEBGL_TEXTURE_CUBE_MAP_NEGATIVE_X &&
884-
textarget != WEBGL_TEXTURE_CUBE_MAP_POSITIVE_Y &&
885-
textarget != WEBGL_TEXTURE_CUBE_MAP_NEGATIVE_Y &&
886-
textarget != WEBGL_TEXTURE_CUBE_MAP_POSITIVE_Z &&
887-
textarget != WEBGL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
893+
else if (jsTexture.IsObject())
888894
{
889-
glContext_->setError("framebufferTexture2d", client_graphics::WebGLError::kInvalidEnum, "textarget must be TEXTURE_2D or one of the TEXTURE_CUBE_MAP_* targets");
895+
if (!WebGLTexture::IsInstanceOf(jsTexture))
896+
{
897+
glContext_->setError("framebufferTexture2d",
898+
client_graphics::WebGLError::kInvalidOperation,
899+
"texture is not a valid WebGLTexture object.");
900+
return env.Undefined();
901+
}
902+
else
903+
{
904+
textureObject = Napi::ObjectWrap<WebGLTexture>::Unwrap(jsTexture.ToObject());
905+
}
906+
}
907+
else
908+
{
909+
glContext_->setError("framebufferTexture2d",
910+
client_graphics::WebGLError::kInvalidOperation,
911+
"texture must be a number, null or a WebGLTexture object");
890912
return env.Undefined();
891913
}
892914

893915
glContext_->framebufferTexture2D(
894916
static_cast<client_graphics::WebGLFramebufferBindingTarget>(target),
895917
static_cast<client_graphics::WebGLFramebufferAttachment>(attachment),
896918
static_cast<client_graphics::WebGLTexture2DTarget>(textarget),
897-
texture->handle(),
919+
textureObject != nullptr ? textureObject->handle() : nullptr,
898920
level);
899921
return env.Undefined();
900922
}
@@ -1455,12 +1477,13 @@ namespace webgl
14551477
Napi::TypeError::New(env, "vertexAttribPointer() takes 6 arguments.").ThrowAsJavaScriptException();
14561478
return env.Undefined();
14571479
}
1458-
auto index = info[0].As<Napi::Number>().Uint32Value();
1459-
auto size = info[1].As<Napi::Number>().Uint32Value();
1460-
auto type = info[2].As<Napi::Number>().Uint32Value();
1461-
auto normalized = info[3].As<Napi::Boolean>().Value();
1462-
auto stride = info[4].As<Napi::Number>().Uint32Value();
1463-
auto offset = info[5].As<Napi::Number>().Uint32Value();
1480+
1481+
auto index = info[0].ToNumber().Uint32Value();
1482+
auto size = info[1].ToNumber().Uint32Value();
1483+
auto type = info[2].ToNumber().Uint32Value();
1484+
auto normalized = info[3].ToBoolean().Value();
1485+
auto stride = info[4].ToNumber().Uint32Value();
1486+
auto offset = info[5].ToNumber().Uint32Value();
14641487

14651488
glContext_->vertexAttribPointer(index, size, type, normalized, stride, offset);
14661489
return env.Undefined();
@@ -1545,10 +1568,10 @@ namespace webgl
15451568
auto program = Napi::ObjectWrap<WebGLProgram>::Unwrap(info[0].As<Napi::Object>());
15461569
std::string name = info[1].As<Napi::String>().Utf8Value();
15471570
auto loc = glContext_->getAttribLocation(program->handle(), name);
1548-
if (loc.has_value())
1549-
return Napi::Number::New(env, loc.value());
1550-
else
1571+
if (!loc.has_value())
15511572
return Napi::Number::New(env, -1);
1573+
else
1574+
return Napi::Number::New(env, loc.value().index.value_or(-1));
15521575
}
15531576

15541577
template <typename ObjectType, typename ContextType>

src/bindings/webgl/rendering_context.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,11 +1443,11 @@ namespace webgl
14431443
return env.Undefined();
14441444
}
14451445

1446-
auto index = info[0].As<Napi::Number>().Uint32Value();
1447-
auto size = info[1].As<Napi::Number>().Uint32Value();
1448-
auto type = info[2].As<Napi::Number>().Uint32Value();
1449-
auto stride = info[3].As<Napi::Number>().Uint32Value();
1450-
auto offset = info[4].As<Napi::Number>().Uint32Value();
1446+
auto index = info[0].ToNumber().Uint32Value();
1447+
auto size = info[1].ToNumber().Uint32Value();
1448+
auto type = info[2].ToNumber().Uint32Value();
1449+
auto stride = info[3].ToNumber().Uint32Value();
1450+
auto offset = info[4].ToNumber().Uint32Value();
14511451

14521452
glContext_->vertexAttribIPointer(index, size, type, stride, offset);
14531453
return env.Undefined();

src/bindings/webgl/uniform_location.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace webgl
2121
*/
2222
int value() const
2323
{
24-
return handle_.has_value() ? handle_->index : -1;
24+
return handle_.has_value() ? handle_->index.value_or(-1) : -1;
2525
}
2626
/**
2727
* @returns the name of the uniform location.

src/client/builtin_scene/client_renderer.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ namespace builtin_scene
5353
/**
5454
* Configure the vertext attributes.
5555
*/
56-
auto configureAttribute = [this](const IVertexAttribute &attrib, int index, size_t stride, size_t offset)
56+
auto configureAttribute = [this](const IVertexAttribute &attrib,
57+
int index,
58+
size_t stride,
59+
size_t offset)
5760
{
5861
glContext_->vertexAttribPointer(index,
5962
attrib.size(),
@@ -94,7 +97,10 @@ namespace builtin_scene
9497
/**
9598
* Configure the instance attributes.
9699
*/
97-
auto configureInstanceAttribute = [this](const IVertexAttribute &attrib, int index, size_t stride, size_t offset)
100+
auto configureInstanceAttribute = [this](const IVertexAttribute &attrib,
101+
int index,
102+
size_t stride,
103+
size_t offset)
98104
{
99105
glContext_->enableVertexAttribArray(index);
100106
glContext_->vertexAttribPointer(index,

src/client/builtin_scene/instanced_mesh.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,20 @@ namespace builtin_scene
107107
}
108108
}
109109

110+
bool Instance::skipToDraw() const
111+
{
112+
// Skip if the instance is not enabled.
113+
if (!enabled_)
114+
return true;
115+
116+
// Skip if the instance is transparent and not own a texture.
117+
if (data_.isTransparent() && !data_.ownTexture())
118+
return true;
119+
120+
// Otherwise, the instance is ready to draw.
121+
return false;
122+
}
123+
110124
RenderableInstancesList::RenderableInstancesList(InstanceFilter filter,
111125
shared_ptr<WebGLVertexArray> vao,
112126
shared_ptr<WebGLBuffer> instanceVbo)
@@ -126,7 +140,7 @@ namespace builtin_scene
126140
{
127141
if (TR_UNLIKELY(instance == nullptr))
128142
continue;
129-
if (!instance->enabled_)
143+
if (instance->skipToDraw())
130144
continue;
131145

132146
if (filter == InstanceFilter::kAll)
@@ -223,7 +237,10 @@ namespace builtin_scene
223237
}
224238

225239
size_t InstancedMeshBase::iterateInstanceAttributes(shared_ptr<WebGLProgram> program,
226-
function<void(const IVertexAttribute &, int, size_t, size_t)> callback) const
240+
function<void(const IVertexAttribute &,
241+
int,
242+
size_t,
243+
size_t)> callback) const
227244
{
228245
auto glContext = glContext_.lock();
229246
if (glContext == nullptr)
@@ -234,10 +251,10 @@ namespace builtin_scene
234251
for (size_t i = 0; i < INSTANCE_ATTRIBUTES.size(); i++)
235252
{
236253
auto &name = INSTANCE_ATTRIBUTES[i];
237-
auto index = glContext->getAttribLocation(program, name);
238-
if (index.has_value())
254+
auto attribLocation = glContext->getAttribLocation(program, name);
255+
if (attribLocation.has_value())
239256
{
240-
auto instanceIndex = index.value();
257+
auto instanceIndex = attribLocation.value().index.value_or(-1);
241258
if (name == "instanceTransform")
242259
{
243260
for (int i = 0; i < 4; i++)

0 commit comments

Comments
 (0)