Skip to content
Merged
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
2 changes: 2 additions & 0 deletions examples/textures/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ add_example(NAME "data_texture" WEB WEB_EMBED
"${PROJECT_SOURCE_DIR}/data/textures/crate.gif@data/textures/crate.gif"
)
add_example(NAME "imgui_framebuffer" LINK_IMGUI WEB)

add_example(NAME "depth_texture")
137 changes: 137 additions & 0 deletions examples/textures/depth_texture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@

#include "threepp/materials/ShaderMaterial.hpp"
#include "threepp/renderers/GLRenderTarget.hpp"
#include "threepp/textures/DepthTexture.hpp"
#include "threepp/threepp.hpp"

#include <threepp/geometries/TorusKnotGeometry.hpp>

#include <cmath>

using namespace threepp;

namespace {
void setupScene(Scene& scene) {

const auto geometry = TorusKnotGeometry::create(1, 0.3, 128, 64);
const auto material = MeshBasicMaterial::create({{"color", Color::blue}});

const auto count = 50;
const auto scale = 5;

for (auto i = 0; i < count; i++) {

const auto r = math::randFloat() * 2.0f * math::PI;
const auto z = (math::randFloat() * 2.0f) - 1.0f;
const auto zScale = std::sqrt(1.0f - z * z) * scale;

const auto mesh = Mesh::create(geometry, material);
mesh->position.set(
std::cos(r) * zScale,
std::sin(r) * zScale,
z * scale);
mesh->rotation.set(math::randFloat(), math::randFloat(), math::randFloat());
scene.add(mesh);
}
}
}// namespace

int main() {

Canvas canvas("Depth texture");
GLRenderer renderer(canvas.size());
renderer.checkShaderErrors = true;

PerspectiveCamera camera(70, canvas.aspect(), 0.01f, 50.f);
camera.position.set(0, 0, 4);

Scene scene;
setupScene(scene);

OrbitControls controls(camera, canvas);
controls.enableDamping = true;


GLRenderTarget::Options options;
options.format = Format::RGB;
options.minFilter = Filter::Nearest;
options.magFilter = Filter::Nearest;
options.generateMipmaps = false;
options.stencilBuffer = false;
options.depthBuffer = true;

options.depthTexture = DepthTexture::create();
options.depthTexture->format = Format::Depth;
options.depthTexture->type = Type::Float;


GLRenderTarget target(canvas.size().width(), canvas.size().height(), options);


auto postMaterial = ShaderMaterial::create();
postMaterial->vertexShader = R"(
varying vec2 vUv;

void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
)";
postMaterial->fragmentShader = R"(
#include <packing>

varying vec2 vUv;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
uniform float cameraNear;
uniform float cameraFar;


float readDepth( sampler2D depthSampler, vec2 coord ) {
float fragCoordZ = texture2D( depthSampler, coord ).x;
float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );
return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
}

void main() {
//vec3 diffuse = texture2D( tDiffuse, vUv ).rgb;
float depth = readDepth( tDepth, vUv );

gl_FragColor.rgb = 1 - vec3( depth );
gl_FragColor.a = 1.0;
}
)";

postMaterial->uniforms = {
{"tDiffuse", Uniform()},
{"tDepth", Uniform()},
{"cameraNear", Uniform(camera.nearPlane)},
{"cameraFar", Uniform(camera.farPlane)}};

OrthographicCamera postCamera(-1, 1, 1, -1, 0, 1);
const auto postPlane = PlaneGeometry::create(2, 2);
const auto postQuad = Mesh::create(postPlane, postMaterial);
Scene postScene;
postScene.add(postQuad);


canvas.onWindowResize([&](WindowSize size) {
renderer.setSize(size);
camera.aspect = canvas.aspect();
camera.updateProjectionMatrix();
});

canvas.animate([&] {
renderer.setRenderTarget(&target);
renderer.render(scene, camera);

postMaterial->uniforms.at("tDiffuse").setValue(target.texture.get());
postMaterial->uniforms.at("tDepth").setValue(target.depthTexture.get());

renderer.setRenderTarget(nullptr);

renderer.render(postScene, postCamera);

controls.update();
});
}
5 changes: 5 additions & 0 deletions include/threepp/renderers/GLRenderTarget.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "threepp/textures/Texture.hpp"

#include "threepp/math/Vector4.hpp"
#include "threepp/textures/DepthTexture.hpp"

#include <optional>

Expand All @@ -32,6 +33,8 @@ namespace threepp {
bool depthBuffer{true};
bool stencilBuffer{false};

std::shared_ptr<DepthTexture> depthTexture;

Options() = default;
};

Expand All @@ -51,6 +54,8 @@ namespace threepp {
bool depthBuffer;
bool stencilBuffer;

std::shared_ptr<DepthTexture> depthTexture;

GLRenderTarget(unsigned int width, unsigned int height, const Options& options);

GLRenderTarget(GLRenderTarget&&) = delete;
Expand Down
21 changes: 21 additions & 0 deletions include/threepp/textures/DepthTexture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// https://github.com/mrdoob/three.js/tree/r129/src/textures

#ifndef THREEPP_DEPTHTEXTURE_HPP
#define THREEPP_DEPTHTEXTURE_HPP

#include "Texture.hpp"

namespace threepp {

class DepthTexture: public Texture {

public:
static std::shared_ptr<DepthTexture> create(std::optional<Type> type = std::nullopt, Format format = Format::Depth);

private:
DepthTexture(std::optional<Type> type, Format format);
};

}// namespace threepp

#endif//DEPTHTEXTURE_HPP
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ set(publicHeaders
"threepp/textures/CubeTexture.hpp"
"threepp/textures/DataTexture.hpp"
"threepp/textures/DataTexture3D.hpp"
"threepp/textures/DepthTexture.hpp"
"threepp/textures/Image.hpp"
"threepp/textures/Texture.hpp"

Expand Down Expand Up @@ -419,6 +420,7 @@ set(sources

"threepp/textures/Texture.cpp"
"threepp/textures/DataTexture3D.cpp"
"threepp/textures/DepthTexture.cpp"

"threepp/utils/BufferGeometryUtils.cpp"
"threepp/utils/ImageUtils.cpp"
Expand Down
4 changes: 4 additions & 0 deletions src/threepp/renderers/GLRenderTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ GLRenderTarget::GLRenderTarget(unsigned int width, unsigned int height, const Op
if (options.type) texture->type = *options.type;
if (options.anisotropy) texture->anisotropy = *options.anisotropy;
if (options.encoding) texture->encoding = *options.encoding;

if (options.depthTexture) depthTexture = options.depthTexture;

}

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

this->depthBuffer = source.depthBuffer;
this->stencilBuffer = source.stencilBuffer;
this->depthTexture = source.depthTexture;

return *this;
}
Expand Down
86 changes: 80 additions & 6 deletions src/threepp/renderers/gl/GLTextures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,30 @@ void gl::GLTextures::uploadTexture(TextureProperties* textureProperties, Texture

auto& mipmaps = texture.mipmaps();

if (dataTexture3D) {
if (dynamic_cast<DepthTexture*>(&texture)) {

if (texture.type == Type::Float) {

glInternalFormat = GL_DEPTH_COMPONENT32F;

} else if (texture.type == Type::UnsignedInt) {

glInternalFormat = GL_DEPTH_COMPONENT24;

} else if (texture.type == Type::UnsignedInt248) {

glInternalFormat = GL_DEPTH24_STENCIL8;

} else {

glInternalFormat = GL_DEPTH_COMPONENT24;
}

//

state->texImage2D(GL_TEXTURE_2D, 0, glInternalFormat, image.width, image.height, glFormat, glType, nullptr);

} else if (dataTexture3D) {

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

if (renderTarget->depthTexture) {

renderTarget->depthTexture->dispose();
}

glDeleteFramebuffers(1, &renderTargetProperties->glFramebuffer.value());
if (renderTargetProperties->glDepthbuffer) glDeleteRenderbuffers(1, &renderTargetProperties->glDepthbuffer.value());

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

void gl::GLTextures::setupDepthTexture(unsigned int framebuffer, GLRenderTarget* renderTarget) {

state->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);

// upload an empty depth texture with framebuffer size
if (!properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture ||
renderTarget->depthTexture->image().width != renderTarget->width ||
renderTarget->depthTexture->image().height != renderTarget->height) {

renderTarget->depthTexture->image().width = renderTarget->width;
renderTarget->depthTexture->image().height = renderTarget->height;
renderTarget->depthTexture->needsUpdate();
}

setTexture2D(*renderTarget->depthTexture, 0);

const auto glDepthTexture = properties->textureProperties.get(renderTarget->depthTexture.get())->glTexture;

if (renderTarget->depthTexture->format == Format::Depth) {

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *glDepthTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "GLTextures: Depth texture framebuffer (depth) incomplete: 0x" << std::hex << status << std::dec << std::endl;
}
} else if (renderTarget->depthTexture->format == Format::DepthStencil) {

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, *glDepthTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
std::cerr << "GLTextures: Depth texture framebuffer (stencil) incomplete: 0x" << std::hex << status << std::dec << std::endl;
}
} else {

throw std::runtime_error("Unknown depthTexture format");
}
}

void gl::GLTextures::setupDepthRenderbuffer(GLRenderTarget* renderTarget) {

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

state->bindFramebuffer(GL_FRAMEBUFFER, renderTargetProperties->glFramebuffer.value());
GLuint glDepthbuffer;
glGenRenderbuffers(1, &glDepthbuffer);
renderTargetProperties->glDepthbuffer = glDepthbuffer;
setupRenderBufferStorage(*renderTargetProperties->glDepthbuffer, renderTarget);
if (renderTarget->depthTexture) {

setupDepthTexture(*renderTargetProperties->glFramebuffer, renderTarget);

} else {

state->bindFramebuffer(GL_FRAMEBUFFER, renderTargetProperties->glFramebuffer.value());
GLuint glDepthbuffer;
glGenRenderbuffers(1, &glDepthbuffer);
renderTargetProperties->glDepthbuffer = glDepthbuffer;
setupRenderBufferStorage(*renderTargetProperties->glDepthbuffer, renderTarget);
}


state->bindFramebuffer(GL_FRAMEBUFFER, 0);
}
Expand Down
2 changes: 2 additions & 0 deletions src/threepp/renderers/gl/GLTextures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ namespace threepp::gl {

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

void setupDepthTexture(unsigned int framebuffer, GLRenderTarget* renderTarget);

// Setup GL resources for a non-texture depth buffer
void setupDepthRenderbuffer(GLRenderTarget* renderTarget);

Expand Down
4 changes: 2 additions & 2 deletions src/threepp/renderers/gl/GLUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace threepp::gl {
case Format::LuminanceAlpha:
return GL_LUMINANCE_ALPHA;
case Format::Depth:
return GL_DEPTH;
return GL_DEPTH_COMPONENT;
case Format::DepthStencil:
return GL_DEPTH_STENCIL;
case Format::Red:
Expand All @@ -63,7 +63,7 @@ namespace threepp::gl {
}
}

constexpr inline GLuint toGLType(Type p) {
constexpr GLuint toGLType(Type p) {

switch (p) {
case Type::UnsignedByte:
Expand Down
20 changes: 20 additions & 0 deletions src/threepp/textures/DepthTexture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

#include "threepp/textures/DepthTexture.hpp"

using namespace threepp;

DepthTexture::DepthTexture(std::optional<Type> type, Format format)
: Texture({Image({}, 0, 0)}) {

if ( !type && format == Format::Depth ) type = Type::UnsignedShort;
if ( !type && format == Format::DepthStencil ) type = Type::UnsignedInt248;

magFilter = Filter::Nearest;
minFilter = Filter::Nearest;

generateMipmaps = false;
}

std::shared_ptr<DepthTexture> DepthTexture::create(std::optional<Type> type, Format format) {
return std::shared_ptr<DepthTexture>(new DepthTexture(type, format));
}
Loading