Skip to content

Commit 59ea9d6

Browse files
authored
Add DepthTexture (#315)
1 parent c46616a commit 59ea9d6

File tree

10 files changed

+275
-8
lines changed

10 files changed

+275
-8
lines changed

examples/textures/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ add_example(NAME "data_texture" WEB WEB_EMBED
1111
"${PROJECT_SOURCE_DIR}/data/textures/crate.gif@data/textures/crate.gif"
1212
)
1313
add_example(NAME "imgui_framebuffer" LINK_IMGUI WEB)
14+
15+
add_example(NAME "depth_texture")
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
#include "threepp/materials/ShaderMaterial.hpp"
3+
#include "threepp/renderers/GLRenderTarget.hpp"
4+
#include "threepp/textures/DepthTexture.hpp"
5+
#include "threepp/threepp.hpp"
6+
7+
#include <threepp/geometries/TorusKnotGeometry.hpp>
8+
9+
#include <cmath>
10+
11+
using namespace threepp;
12+
13+
namespace {
14+
void setupScene(Scene& scene) {
15+
16+
const auto geometry = TorusKnotGeometry::create(1, 0.3, 128, 64);
17+
const auto material = MeshBasicMaterial::create({{"color", Color::blue}});
18+
19+
const auto count = 50;
20+
const auto scale = 5;
21+
22+
for (auto i = 0; i < count; i++) {
23+
24+
const auto r = math::randFloat() * 2.0f * math::PI;
25+
const auto z = (math::randFloat() * 2.0f) - 1.0f;
26+
const auto zScale = std::sqrt(1.0f - z * z) * scale;
27+
28+
const auto mesh = Mesh::create(geometry, material);
29+
mesh->position.set(
30+
std::cos(r) * zScale,
31+
std::sin(r) * zScale,
32+
z * scale);
33+
mesh->rotation.set(math::randFloat(), math::randFloat(), math::randFloat());
34+
scene.add(mesh);
35+
}
36+
}
37+
}// namespace
38+
39+
int main() {
40+
41+
Canvas canvas("Depth texture");
42+
GLRenderer renderer(canvas.size());
43+
renderer.checkShaderErrors = true;
44+
45+
PerspectiveCamera camera(70, canvas.aspect(), 0.01f, 50.f);
46+
camera.position.set(0, 0, 4);
47+
48+
Scene scene;
49+
setupScene(scene);
50+
51+
OrbitControls controls(camera, canvas);
52+
controls.enableDamping = true;
53+
54+
55+
GLRenderTarget::Options options;
56+
options.format = Format::RGB;
57+
options.minFilter = Filter::Nearest;
58+
options.magFilter = Filter::Nearest;
59+
options.generateMipmaps = false;
60+
options.stencilBuffer = false;
61+
options.depthBuffer = true;
62+
63+
options.depthTexture = DepthTexture::create();
64+
options.depthTexture->format = Format::Depth;
65+
options.depthTexture->type = Type::Float;
66+
67+
68+
GLRenderTarget target(canvas.size().width(), canvas.size().height(), options);
69+
70+
71+
auto postMaterial = ShaderMaterial::create();
72+
postMaterial->vertexShader = R"(
73+
varying vec2 vUv;
74+
75+
void main() {
76+
vUv = uv;
77+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
78+
}
79+
)";
80+
postMaterial->fragmentShader = R"(
81+
#include <packing>
82+
83+
varying vec2 vUv;
84+
uniform sampler2D tDiffuse;
85+
uniform sampler2D tDepth;
86+
uniform float cameraNear;
87+
uniform float cameraFar;
88+
89+
90+
float readDepth( sampler2D depthSampler, vec2 coord ) {
91+
float fragCoordZ = texture2D( depthSampler, coord ).x;
92+
float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );
93+
return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
94+
}
95+
96+
void main() {
97+
//vec3 diffuse = texture2D( tDiffuse, vUv ).rgb;
98+
float depth = readDepth( tDepth, vUv );
99+
100+
gl_FragColor.rgb = 1 - vec3( depth );
101+
gl_FragColor.a = 1.0;
102+
}
103+
)";
104+
105+
postMaterial->uniforms = {
106+
{"tDiffuse", Uniform()},
107+
{"tDepth", Uniform()},
108+
{"cameraNear", Uniform(camera.nearPlane)},
109+
{"cameraFar", Uniform(camera.farPlane)}};
110+
111+
OrthographicCamera postCamera(-1, 1, 1, -1, 0, 1);
112+
const auto postPlane = PlaneGeometry::create(2, 2);
113+
const auto postQuad = Mesh::create(postPlane, postMaterial);
114+
Scene postScene;
115+
postScene.add(postQuad);
116+
117+
118+
canvas.onWindowResize([&](WindowSize size) {
119+
renderer.setSize(size);
120+
camera.aspect = canvas.aspect();
121+
camera.updateProjectionMatrix();
122+
});
123+
124+
canvas.animate([&] {
125+
renderer.setRenderTarget(&target);
126+
renderer.render(scene, camera);
127+
128+
postMaterial->uniforms.at("tDiffuse").setValue(target.texture.get());
129+
postMaterial->uniforms.at("tDepth").setValue(target.depthTexture.get());
130+
131+
renderer.setRenderTarget(nullptr);
132+
133+
renderer.render(postScene, postCamera);
134+
135+
controls.update();
136+
});
137+
}

include/threepp/renderers/GLRenderTarget.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "threepp/textures/Texture.hpp"
99

1010
#include "threepp/math/Vector4.hpp"
11+
#include "threepp/textures/DepthTexture.hpp"
1112

1213
#include <optional>
1314

@@ -32,6 +33,8 @@ namespace threepp {
3233
bool depthBuffer{true};
3334
bool stencilBuffer{false};
3435

36+
std::shared_ptr<DepthTexture> depthTexture;
37+
3538
Options() = default;
3639
};
3740

@@ -51,6 +54,8 @@ namespace threepp {
5154
bool depthBuffer;
5255
bool stencilBuffer;
5356

57+
std::shared_ptr<DepthTexture> depthTexture;
58+
5459
GLRenderTarget(unsigned int width, unsigned int height, const Options& options);
5560

5661
GLRenderTarget(GLRenderTarget&&) = delete;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// https://github.com/mrdoob/three.js/tree/r129/src/textures
2+
3+
#ifndef THREEPP_DEPTHTEXTURE_HPP
4+
#define THREEPP_DEPTHTEXTURE_HPP
5+
6+
#include "Texture.hpp"
7+
8+
namespace threepp {
9+
10+
class DepthTexture: public Texture {
11+
12+
public:
13+
static std::shared_ptr<DepthTexture> create(std::optional<Type> type = std::nullopt, Format format = Format::Depth);
14+
15+
private:
16+
DepthTexture(std::optional<Type> type, Format format);
17+
};
18+
19+
}// namespace threepp
20+
21+
#endif//DEPTHTEXTURE_HPP

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ set(publicHeaders
181181
"threepp/textures/CubeTexture.hpp"
182182
"threepp/textures/DataTexture.hpp"
183183
"threepp/textures/DataTexture3D.hpp"
184+
"threepp/textures/DepthTexture.hpp"
184185
"threepp/textures/Image.hpp"
185186
"threepp/textures/Texture.hpp"
186187

@@ -419,6 +420,7 @@ set(sources
419420

420421
"threepp/textures/Texture.cpp"
421422
"threepp/textures/DataTexture3D.cpp"
423+
"threepp/textures/DepthTexture.cpp"
422424

423425
"threepp/utils/BufferGeometryUtils.cpp"
424426
"threepp/utils/ImageUtils.cpp"

src/threepp/renderers/GLRenderTarget.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ GLRenderTarget::GLRenderTarget(unsigned int width, unsigned int height, const Op
2828
if (options.type) texture->type = *options.type;
2929
if (options.anisotropy) texture->anisotropy = *options.anisotropy;
3030
if (options.encoding) texture->encoding = *options.encoding;
31+
32+
if (options.depthTexture) depthTexture = options.depthTexture;
33+
3134
}
3235

3336
void GLRenderTarget::setSize(unsigned int width, unsigned int height, unsigned int depth) {
@@ -62,6 +65,7 @@ GLRenderTarget& GLRenderTarget::copy(const GLRenderTarget& source) {
6265

6366
this->depthBuffer = source.depthBuffer;
6467
this->stencilBuffer = source.stencilBuffer;
68+
this->depthTexture = source.depthTexture;
6569

6670
return *this;
6771
}

src/threepp/renderers/gl/GLTextures.cpp

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,30 @@ void gl::GLTextures::uploadTexture(TextureProperties* textureProperties, Texture
146146

147147
auto& mipmaps = texture.mipmaps();
148148

149-
if (dataTexture3D) {
149+
if (dynamic_cast<DepthTexture*>(&texture)) {
150+
151+
if (texture.type == Type::Float) {
152+
153+
glInternalFormat = GL_DEPTH_COMPONENT32F;
154+
155+
} else if (texture.type == Type::UnsignedInt) {
156+
157+
glInternalFormat = GL_DEPTH_COMPONENT24;
158+
159+
} else if (texture.type == Type::UnsignedInt248) {
160+
161+
glInternalFormat = GL_DEPTH24_STENCIL8;
162+
163+
} else {
164+
165+
glInternalFormat = GL_DEPTH_COMPONENT24;
166+
}
167+
168+
//
169+
170+
state->texImage2D(GL_TEXTURE_2D, 0, glInternalFormat, image.width, image.height, glFormat, glType, nullptr);
171+
172+
} else if (dataTexture3D) {
150173

151174
state->texImage3D(GL_TEXTURE_3D, 0, glInternalFormat,
152175
static_cast<int>(image.width),
@@ -247,6 +270,11 @@ void gl::GLTextures::deallocateRenderTarget(GLRenderTarget* renderTarget) {
247270
info->memory.textures--;
248271
}
249272

273+
if (renderTarget->depthTexture) {
274+
275+
renderTarget->depthTexture->dispose();
276+
}
277+
250278
glDeleteFramebuffers(1, &renderTargetProperties->glFramebuffer.value());
251279
if (renderTargetProperties->glDepthbuffer) glDeleteRenderbuffers(1, &renderTargetProperties->glDepthbuffer.value());
252280

@@ -431,15 +459,61 @@ void gl::GLTextures::setupRenderBufferStorage(unsigned int renderbuffer, GLRende
431459
glBindRenderbuffer(GL_RENDERBUFFER, 0);
432460
}
433461

462+
void gl::GLTextures::setupDepthTexture(unsigned int framebuffer, GLRenderTarget* renderTarget) {
463+
464+
state->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
465+
466+
// upload an empty depth texture with framebuffer size
467+
if (!properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture ||
468+
renderTarget->depthTexture->image().width != renderTarget->width ||
469+
renderTarget->depthTexture->image().height != renderTarget->height) {
470+
471+
renderTarget->depthTexture->image().width = renderTarget->width;
472+
renderTarget->depthTexture->image().height = renderTarget->height;
473+
renderTarget->depthTexture->needsUpdate();
474+
}
475+
476+
setTexture2D(*renderTarget->depthTexture, 0);
477+
478+
const auto glDepthTexture = properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture;
479+
480+
if (renderTarget->depthTexture->format == Format::Depth) {
481+
482+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *glDepthTexture, 0);
483+
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
484+
if (status != GL_FRAMEBUFFER_COMPLETE) {
485+
std::cerr << "GLTextures: Depth texture framebuffer (depth) incomplete: 0x" << std::hex << status << std::dec << std::endl;
486+
}
487+
} else if (renderTarget->depthTexture->format == Format::DepthStencil) {
488+
489+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, *glDepthTexture, 0);
490+
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
491+
if (status != GL_FRAMEBUFFER_COMPLETE) {
492+
std::cerr << "GLTextures: Depth texture framebuffer (stencil) incomplete: 0x" << std::hex << status << std::dec << std::endl;
493+
}
494+
} else {
495+
496+
throw std::runtime_error("Unknown depthTexture format");
497+
}
498+
}
499+
434500
void gl::GLTextures::setupDepthRenderbuffer(GLRenderTarget* renderTarget) {
435501

436502
const auto renderTargetProperties = properties->renderTargetProperties.get(renderTarget);
437503

438-
state->bindFramebuffer(GL_FRAMEBUFFER, renderTargetProperties->glFramebuffer.value());
439-
GLuint glDepthbuffer;
440-
glGenRenderbuffers(1, &glDepthbuffer);
441-
renderTargetProperties->glDepthbuffer = glDepthbuffer;
442-
setupRenderBufferStorage(*renderTargetProperties->glDepthbuffer, renderTarget);
504+
if (renderTarget->depthTexture) {
505+
506+
setupDepthTexture(*renderTargetProperties->glFramebuffer, renderTarget);
507+
508+
} else {
509+
510+
state->bindFramebuffer(GL_FRAMEBUFFER, renderTargetProperties->glFramebuffer.value());
511+
GLuint glDepthbuffer;
512+
glGenRenderbuffers(1, &glDepthbuffer);
513+
renderTargetProperties->glDepthbuffer = glDepthbuffer;
514+
setupRenderBufferStorage(*renderTargetProperties->glDepthbuffer, renderTarget);
515+
}
516+
443517

444518
state->bindFramebuffer(GL_FRAMEBUFFER, 0);
445519
}

src/threepp/renderers/gl/GLTextures.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ namespace threepp::gl {
5252

5353
void setupRenderBufferStorage(unsigned int renderbuffer, GLRenderTarget* renderTarget);
5454

55+
void setupDepthTexture(unsigned int framebuffer, GLRenderTarget* renderTarget);
56+
5557
// Setup GL resources for a non-texture depth buffer
5658
void setupDepthRenderbuffer(GLRenderTarget* renderTarget);
5759

src/threepp/renderers/gl/GLUtils.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ namespace threepp::gl {
4343
case Format::LuminanceAlpha:
4444
return GL_LUMINANCE_ALPHA;
4545
case Format::Depth:
46-
return GL_DEPTH;
46+
return GL_DEPTH_COMPONENT;
4747
case Format::DepthStencil:
4848
return GL_DEPTH_STENCIL;
4949
case Format::Red:
@@ -63,7 +63,7 @@ namespace threepp::gl {
6363
}
6464
}
6565

66-
constexpr inline GLuint toGLType(Type p) {
66+
constexpr GLuint toGLType(Type p) {
6767

6868
switch (p) {
6969
case Type::UnsignedByte:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
#include "threepp/textures/DepthTexture.hpp"
3+
4+
using namespace threepp;
5+
6+
DepthTexture::DepthTexture(std::optional<Type> type, Format format)
7+
: Texture({Image({}, 0, 0)}) {
8+
9+
if ( !type && format == Format::Depth ) type = Type::UnsignedShort;
10+
if ( !type && format == Format::DepthStencil ) type = Type::UnsignedInt248;
11+
12+
magFilter = Filter::Nearest;
13+
minFilter = Filter::Nearest;
14+
15+
generateMipmaps = false;
16+
}
17+
18+
std::shared_ptr<DepthTexture> DepthTexture::create(std::optional<Type> type, Format format) {
19+
return std::shared_ptr<DepthTexture>(new DepthTexture(type, format));
20+
}

0 commit comments

Comments
 (0)