From 2dfabdfe64710e34dfab6609af976486a43d17ab Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 22 Aug 2014 16:43:09 -0700 Subject: [PATCH] Support for scaling splat textures in S and T, use mipmaps for them. --- .../shaders/metavoxel_heightfield_splat.frag | 7 +++--- .../shaders/metavoxel_heightfield_splat.vert | 20 +++++++++++++--- interface/src/MetavoxelSystem.cpp | 24 ++++++++++++++++++- interface/src/MetavoxelSystem.h | 6 +++++ interface/src/renderer/TextureCache.cpp | 9 ++++++- interface/src/renderer/TextureCache.h | 1 + .../metavoxels/src/AttributeRegistry.cpp | 4 +++- libraries/metavoxels/src/AttributeRegistry.h | 9 ++++++- libraries/networking/src/PacketHeaders.cpp | 2 +- 9 files changed, 71 insertions(+), 11 deletions(-) diff --git a/interface/resources/shaders/metavoxel_heightfield_splat.frag b/interface/resources/shaders/metavoxel_heightfield_splat.frag index 6a3c058b80..bb6b0d6536 100644 --- a/interface/resources/shaders/metavoxel_heightfield_splat.frag +++ b/interface/resources/shaders/metavoxel_heightfield_splat.frag @@ -11,6 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// the number of splats per pass const int SPLAT_COUNT = 4; // the splat textures @@ -22,7 +23,7 @@ varying vec4 alphaValues; void main(void) { // blend the splat textures gl_FragColor = gl_Color * (texture2D(diffuseMaps[0], gl_TexCoord[0].st) * alphaValues.x + - texture2D(diffuseMaps[1], gl_TexCoord[0].st) * alphaValues.y + - texture2D(diffuseMaps[2], gl_TexCoord[0].st) * alphaValues.z + - texture2D(diffuseMaps[3], gl_TexCoord[0].st) * alphaValues.w); + texture2D(diffuseMaps[1], gl_TexCoord[1].st) * alphaValues.y + + texture2D(diffuseMaps[2], gl_TexCoord[2].st) * alphaValues.z + + texture2D(diffuseMaps[3], gl_TexCoord[3].st) * alphaValues.w); } diff --git a/interface/resources/shaders/metavoxel_heightfield_splat.vert b/interface/resources/shaders/metavoxel_heightfield_splat.vert index 950162073e..926bcdd6c3 100644 --- a/interface/resources/shaders/metavoxel_heightfield_splat.vert +++ b/interface/resources/shaders/metavoxel_heightfield_splat.vert @@ -23,6 +23,15 @@ uniform float heightScale; // the scale between height and texture textures uniform float textureScale; +// the splat texture offset +uniform vec2 splatTextureOffset; + +// the splat textures scales on the S axis +uniform vec4 splatTextureScalesS; + +// the splat texture scales on the T axis +uniform vec4 splatTextureScalesT; + // the lower bounds of the values corresponding to the splat textures uniform vec4 textureValueMinima; @@ -35,16 +44,21 @@ varying vec4 alphaValues; void main(void) { // add the height to the position float height = texture2D(heightMap, gl_MultiTexCoord0.st).r; - gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(0.0, height, 0.0, 0.0)); + vec4 modelSpacePosition = gl_Vertex + vec4(0.0, height, 0.0, 0.0); + gl_Position = gl_ModelViewProjectionMatrix * modelSpacePosition; // the zero height should be invisible gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0 - step(height, 0.0)); // pass along the scaled/offset texture coordinates - gl_TexCoord[0] = (gl_MultiTexCoord0 - vec4(heightScale, heightScale, 0.0, 0.0)) * textureScale; + vec4 textureSpacePosition = vec4(modelSpacePosition.xz, 0.0, 1.0) + vec4(splatTextureOffset, 0.0, 0.0); + gl_TexCoord[0] = textureSpacePosition * vec4(splatTextureScalesS[0], splatTextureScalesT[0], 0.0, 1.0); + gl_TexCoord[1] = textureSpacePosition * vec4(splatTextureScalesS[1], splatTextureScalesT[1], 0.0, 1.0); + gl_TexCoord[2] = textureSpacePosition * vec4(splatTextureScalesS[2], splatTextureScalesT[2], 0.0, 1.0); + gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3], 0.0, 1.0); // compute the alpha values for each texture - float value = texture2D(textureMap, gl_TexCoord[0].st).r; + float value = texture2D(textureMap, (gl_MultiTexCoord0.st - vec2(heightScale, heightScale)) * textureScale).r; vec4 valueVector = vec4(value, value, value, value); alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima); } diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 3864b0537f..1d97dc94fc 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -822,22 +822,38 @@ void HeightfieldBuffer::render(bool cursor) { DefaultMetavoxelRendererImplementation::getSplatHeightScaleLocation(), 1.0f / _heightSize); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getSplatTextureScaleLocation(), (float)_heightSize / innerSize); + DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getSplatTextureOffsetLocation(), + _translation.x / _scale, _translation.z / _scale); glBindTexture(GL_TEXTURE_2D, _textureTextureID); const int TEXTURES_PER_SPLAT = 4; for (int i = 0; i < _textures.size(); i += TEXTURES_PER_SPLAT) { + QVector4D scalesS, scalesT; + for (int j = 0; j < SPLAT_COUNT; j++) { glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]); int index = i + j; if (index < _networkTextures.size()) { const NetworkTexturePointer& texture = _networkTextures.at(index); - glBindTexture(GL_TEXTURE_2D, texture ? texture->getID() : 0); + if (texture) { + HeightfieldTexture* heightfieldTexture = static_cast(_textures.at(index).data()); + scalesS[j] = _scale / heightfieldTexture->getScaleS(); + scalesT[j] = _scale / heightfieldTexture->getScaleT(); + glBindTexture(GL_TEXTURE_2D, texture->getID()); + } else { + glBindTexture(GL_TEXTURE_2D, 0); + } } else { glBindTexture(GL_TEXTURE_2D, 0); } } const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL; + DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getSplatTextureScalesSLocation(), scalesS); + DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( + DefaultMetavoxelRendererImplementation::getSplatTextureScalesTLocation(), scalesT); DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue( DefaultMetavoxelRendererImplementation::getSplatTextureValueMinimaLocation(), (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, @@ -1050,6 +1066,9 @@ void DefaultMetavoxelRendererImplementation::init() { _splatHeightfieldProgram.setUniformValueArray("diffuseMaps", SPLAT_TEXTURE_UNITS, SPLAT_COUNT); _splatHeightScaleLocation = _splatHeightfieldProgram.uniformLocation("heightScale"); _splatTextureScaleLocation = _splatHeightfieldProgram.uniformLocation("textureScale"); + _splatTextureOffsetLocation = _splatHeightfieldProgram.uniformLocation("splatTextureOffset"); + _splatTextureScalesSLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesS"); + _splatTextureScalesTLocation = _splatHeightfieldProgram.uniformLocation("splatTextureScalesT"); _splatTextureValueMinimaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMinima"); _splatTextureValueMaximaLocation = _splatHeightfieldProgram.uniformLocation("textureValueMaxima"); _splatHeightfieldProgram.release(); @@ -1695,6 +1714,9 @@ int DefaultMetavoxelRendererImplementation::_baseColorScaleLocation; ProgramObject DefaultMetavoxelRendererImplementation::_splatHeightfieldProgram; int DefaultMetavoxelRendererImplementation::_splatHeightScaleLocation; int DefaultMetavoxelRendererImplementation::_splatTextureScaleLocation; +int DefaultMetavoxelRendererImplementation::_splatTextureOffsetLocation; +int DefaultMetavoxelRendererImplementation::_splatTextureScalesSLocation; +int DefaultMetavoxelRendererImplementation::_splatTextureScalesTLocation; int DefaultMetavoxelRendererImplementation::_splatTextureValueMinimaLocation; int DefaultMetavoxelRendererImplementation::_splatTextureValueMaximaLocation; ProgramObject DefaultMetavoxelRendererImplementation::_lightHeightfieldProgram; diff --git a/interface/src/MetavoxelSystem.h b/interface/src/MetavoxelSystem.h index ac4dd430fb..b1ddcf0bff 100644 --- a/interface/src/MetavoxelSystem.h +++ b/interface/src/MetavoxelSystem.h @@ -252,6 +252,9 @@ public: static ProgramObject& getSplatHeightfieldProgram() { return _splatHeightfieldProgram; } static int getSplatHeightScaleLocation() { return _splatHeightScaleLocation; } static int getSplatTextureScaleLocation() { return _splatTextureScaleLocation; } + static int getSplatTextureOffsetLocation() { return _splatTextureOffsetLocation; } + static int getSplatTextureScalesSLocation() { return _splatTextureScalesSLocation; } + static int getSplatTextureScalesTLocation() { return _splatTextureScalesTLocation; } static int getSplatTextureValueMinimaLocation() { return _splatTextureValueMinimaLocation; } static int getSplatTextureValueMaximaLocation() { return _splatTextureValueMaximaLocation; } @@ -297,6 +300,9 @@ private: static ProgramObject _splatHeightfieldProgram; static int _splatHeightScaleLocation; static int _splatTextureScaleLocation; + static int _splatTextureOffsetLocation; + static int _splatTextureScalesSLocation; + static int _splatTextureScalesTLocation; static int _splatTextureValueMinimaLocation; static int _splatTextureValueMaximaLocation; diff --git a/interface/src/renderer/TextureCache.cpp b/interface/src/renderer/TextureCache.cpp index c3e58d52bb..e13f97a1d2 100644 --- a/interface/src/renderer/TextureCache.cpp +++ b/interface/src/renderer/TextureCache.cpp @@ -320,6 +320,7 @@ Texture::~Texture() { NetworkTexture::NetworkTexture(const QUrl& url, TextureType type, const QByteArray& content) : Resource(url, !content.isEmpty()), + _type(type), _translucent(false) { if (!url.isValid()) { @@ -474,7 +475,13 @@ void NetworkTexture::setImage(const QImage& image, bool translucent, const QColo glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + if (_type == SPLAT_TEXTURE) { + // generate mipmaps for splat textures + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } glBindTexture(GL_TEXTURE_2D, 0); } diff --git a/interface/src/renderer/TextureCache.h b/interface/src/renderer/TextureCache.h index 83d9b6cc74..e1d69677f6 100644 --- a/interface/src/renderer/TextureCache.h +++ b/interface/src/renderer/TextureCache.h @@ -145,6 +145,7 @@ protected: private: + TextureType _type; bool _translucent; QColor _averageColor; }; diff --git a/libraries/metavoxels/src/AttributeRegistry.cpp b/libraries/metavoxels/src/AttributeRegistry.cpp index e823e081cc..425bf8ff4a 100644 --- a/libraries/metavoxels/src/AttributeRegistry.cpp +++ b/libraries/metavoxels/src/AttributeRegistry.cpp @@ -1055,7 +1055,9 @@ void HeightfieldTextureData::read(Bitstream& in, int bytes) { in >> _textures; } -HeightfieldTexture::HeightfieldTexture() { +HeightfieldTexture::HeightfieldTexture() : + _scaleS(1.0f), + _scaleT(1.0f) { } HeightfieldAttribute::HeightfieldAttribute(const QString& name) : diff --git a/libraries/metavoxels/src/AttributeRegistry.h b/libraries/metavoxels/src/AttributeRegistry.h index fb6ff5097d..66da7a9b6f 100644 --- a/libraries/metavoxels/src/AttributeRegistry.h +++ b/libraries/metavoxels/src/AttributeRegistry.h @@ -548,16 +548,23 @@ private: class HeightfieldTexture : public SharedObject { Q_OBJECT Q_PROPERTY(QUrl url MEMBER _url) - + Q_PROPERTY(float scaleS MEMBER _scaleS) + Q_PROPERTY(float scaleT MEMBER _scaleT) + public: Q_INVOKABLE HeightfieldTexture(); const QUrl& getURL() const { return _url; } + float getScaleS() const { return _scaleS; } + float getScaleT() const { return _scaleT; } + private: QUrl _url; + float _scaleS; + float _scaleT; }; /// An attribute that stores heightfield data. diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 619f652e1e..378d995793 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -81,7 +81,7 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeAudioStreamStats: return 1; case PacketTypeMetavoxelData: - return 2; + return 3; default: return 0; }